summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/Makefile51
-rw-r--r--Documentation/filesystems/sysfs.txt342
-rw-r--r--MAINTAINERS6
-rw-r--r--Makefile114
-rw-r--r--Rules.make42
-rw-r--r--arch/arm/kernel/ecard.c2
-rw-r--r--arch/i386/Makefile2
-rw-r--r--arch/i386/boot/Makefile7
-rw-r--r--arch/i386/boot/compressed/Makefile4
-rw-r--r--arch/i386/config.in1
-rw-r--r--arch/i386/kernel/bluesmoke.c1
-rw-r--r--arch/i386/kernel/cpu/amd.c15
-rw-r--r--arch/i386/kernel/io_apic.c4
-rw-r--r--arch/i386/kernel/irq.c14
-rw-r--r--arch/i386/kernel/microcode.c4
-rw-r--r--arch/i386/mm/init.c6
-rw-r--r--arch/i386/pci/i386.c2
-rw-r--r--arch/i386/vmlinux.lds.S38
-rw-r--r--arch/ia64/ia32/sys_ia32.c3
-rw-r--r--arch/ppc/Makefile6
-rw-r--r--arch/ppc/boot/Makefile66
-rw-r--r--arch/ppc/boot/common/Makefile9
-rw-r--r--arch/ppc/boot/images/Makefile13
-rw-r--r--arch/ppc/boot/include/mpc10x.h2
-rw-r--r--arch/ppc/boot/lib/Makefile2
-rw-r--r--arch/ppc/boot/lib/div64.S58
-rw-r--r--arch/ppc/boot/of1275/Makefile2
-rw-r--r--arch/ppc/boot/openfirmware/Makefile196
-rw-r--r--arch/ppc/boot/prep/Makefile86
-rw-r--r--arch/ppc/boot/prep/misc.c28
-rw-r--r--arch/ppc/boot/simple/Makefile154
-rw-r--r--arch/ppc/boot/simple/misc.c (renamed from arch/ppc/boot/common/misc-simple.c)0
-rw-r--r--arch/ppc/boot/simple/relocate.S (renamed from arch/ppc/boot/common/relocate.S)0
-rw-r--r--arch/ppc/config.in43
-rw-r--r--arch/ppc/kernel/indirect_pci.c14
-rw-r--r--arch/ppc/kernel/misc.S15
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c7
-rw-r--r--arch/ppc/lib/Makefile2
-rw-r--r--arch/ppc/lib/div64.S58
-rw-r--r--arch/ppc/platforms/Makefile1
-rw-r--r--arch/ppc/platforms/pal4.h44
-rw-r--r--arch/ppc/platforms/pal4_pci.c78
-rw-r--r--arch/ppc/platforms/pal4_serial.h41
-rw-r--r--arch/ppc/platforms/pal4_setup.c176
-rw-r--r--arch/ppc/platforms/pcore_setup.c36
-rw-r--r--arch/ppc/vmlinux.lds.S24
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c3
-rw-r--r--arch/s390x/kernel/linux32.c3
-rw-r--r--arch/sparc/Makefile16
-rw-r--r--arch/sparc/boot/Makefile2
-rw-r--r--arch/sparc/kernel/Makefile92
-rw-r--r--arch/sparc/kernel/asm-offsets.c53
-rwxr-xr-xarch/sparc/kernel/check_asm.sh19
-rw-r--r--arch/sparc/kernel/entry.S1
-rw-r--r--arch/sparc/kernel/etrap.S1
-rw-r--r--arch/sparc/kernel/rtrap.S1
-rw-r--r--arch/sparc/kernel/sclow.S12
-rw-r--r--arch/sparc/kernel/wof.S1
-rw-r--r--arch/sparc/kernel/wuf.S1
-rw-r--r--arch/sparc/vmlinux.lds.S6
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c3
-rw-r--r--arch/sparc64/vmlinux.lds.S6
-rw-r--r--arch/um/Makefile2
-rw-r--r--arch/um/drivers/ubd_kern.c115
-rw-r--r--arch/x86_64/kernel/mtrr.c719
-rw-r--r--drivers/acorn/block/fd1772.c47
-rw-r--r--drivers/acorn/block/mfmhd.c83
-rw-r--r--drivers/acorn/scsi/acornscsi.c6
-rw-r--r--drivers/acorn/scsi/arxescsi.c8
-rw-r--r--drivers/acorn/scsi/cumana_2.c8
-rw-r--r--drivers/acorn/scsi/eesox.c8
-rw-r--r--drivers/acorn/scsi/powertec.c8
-rw-r--r--drivers/atm/Makefile6
-rw-r--r--drivers/base/base.h7
-rw-r--r--drivers/base/bus.c242
-rw-r--r--drivers/base/class.c132
-rw-r--r--drivers/base/core.c215
-rw-r--r--drivers/base/driver.c107
-rw-r--r--drivers/base/interface.c2
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power.c68
-rw-r--r--drivers/base/sys.c8
-rw-r--r--drivers/block/DAC960.c54
-rw-r--r--drivers/block/DAC960.h10
-rw-r--r--drivers/block/acsi.c149
-rw-r--r--drivers/block/amiflop.c53
-rw-r--r--drivers/block/ataflop.c51
-rw-r--r--drivers/block/cciss.c48
-rw-r--r--drivers/block/cciss.h3
-rw-r--r--drivers/block/cciss_scsi.c21
-rw-r--r--drivers/block/cpqarray.c34
-rw-r--r--drivers/block/cpqarray.h3
-rw-r--r--drivers/block/floppy.c77
-rw-r--r--drivers/block/genhd.c146
-rw-r--r--drivers/block/ll_rw_blk.c24
-rw-r--r--drivers/block/loop.c50
-rw-r--r--drivers/block/paride/epat.c1
-rw-r--r--drivers/block/paride/pcd.c95
-rw-r--r--drivers/block/paride/pd.c71
-rw-r--r--drivers/block/paride/pf.c55
-rw-r--r--drivers/block/rd.c8
-rw-r--r--drivers/block/swim3.c75
-rw-r--r--drivers/block/swim_iop.c104
-rw-r--r--drivers/block/umem.c43
-rw-r--r--drivers/block/z2ram.c13
-rw-r--r--drivers/cdrom/aztcd.c33
-rw-r--r--drivers/cdrom/cdrom.c49
-rw-r--r--drivers/cdrom/cdu31a.c228
-rw-r--r--drivers/cdrom/cm206.c73
-rw-r--r--drivers/cdrom/gscd.c106
-rw-r--r--drivers/cdrom/mcd.c56
-rw-r--r--drivers/cdrom/mcdx.c97
-rw-r--r--drivers/cdrom/optcd.c34
-rw-r--r--drivers/cdrom/sbpcd.c103
-rw-r--r--drivers/cdrom/sjcd.c32
-rw-r--r--drivers/cdrom/sonycd535.c255
-rw-r--r--drivers/char/Config.help87
-rw-r--r--drivers/char/Makefile3
-rw-r--r--drivers/char/drm/sis_ds.c22
-rw-r--r--drivers/char/ftape/lowlevel/ftape-rw.h2
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.h16
-rw-r--r--drivers/char/isicom.c10
-rw-r--r--drivers/char/rio/rio_linux.c1
-rw-r--r--drivers/char/specialix.c48
-rw-r--r--drivers/ide/ide-cd.c22
-rw-r--r--drivers/ide/ide-geometry.c9
-rw-r--r--drivers/ide/ide-probe.c49
-rw-r--r--drivers/ide/ide.c163
-rw-r--r--drivers/input/serio/sa1111ps2.c2
-rw-r--r--drivers/isdn/i4l/Makefile2
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c19
-rw-r--r--drivers/isdn/i4l/isdn_ciscohdlck.c13
-rw-r--r--drivers/isdn/i4l/isdn_common.h2
-rw-r--r--drivers/isdn/i4l/isdn_net.c412
-rw-r--r--drivers/isdn/i4l/isdn_net.h153
-rw-r--r--drivers/isdn/i4l/isdn_net_lib.c524
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c2540
-rw-r--r--drivers/isdn/i4l/isdn_ppp.h20
-rw-r--r--drivers/isdn/i4l/isdn_ppp_ccp.c601
-rw-r--r--drivers/isdn/i4l/isdn_ppp_ccp.h66
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c8
-rw-r--r--drivers/md/md.c87
-rw-r--r--drivers/message/fusion/linux_compat.h4
-rw-r--r--drivers/message/i2o/i2o_block.c39
-rw-r--r--drivers/mtd/ftl.c239
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/hamradio/soundmodem/Makefile6
-rw-r--r--drivers/nubus/nubus.c6
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/pci/pci-driver.c2
-rw-r--r--drivers/pcmcia/sa1111_generic.c2
-rw-r--r--drivers/scsi/53c700.c39
-rw-r--r--drivers/scsi/53c700.h5
-rw-r--r--drivers/scsi/Makefile4
-rw-r--r--drivers/scsi/NCR53C9x.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c3
-rw-r--r--drivers/scsi/aic7xxx/Makefile14
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_linux_host.h1
-rw-r--r--drivers/scsi/aic7xxx/aicasm/Makefile2
-rw-r--r--drivers/scsi/aic7xxx_old/aic7xxx.h4
-rw-r--r--drivers/scsi/cpqfcTSinit.c4
-rw-r--r--drivers/scsi/esp.c2
-rw-r--r--drivers/scsi/fcal.c4
-rw-r--r--drivers/scsi/hosts.c884
-rw-r--r--drivers/scsi/hosts.h97
-rw-r--r--drivers/scsi/ips.h3
-rw-r--r--drivers/scsi/osst.c2
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c3
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c3
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c3
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c3
-rw-r--r--drivers/scsi/scsi.c462
-rw-r--r--drivers/scsi/scsi.h15
-rw-r--r--drivers/scsi/scsi_debug.c62
-rw-r--r--drivers/scsi/scsi_error.c12
-rw-r--r--drivers/scsi/scsi_ioctl.c16
-rw-r--r--drivers/scsi/scsi_lib.c4
-rw-r--r--drivers/scsi/scsi_merge.c19
-rw-r--r--drivers/scsi/scsi_proc.c59
-rw-r--r--drivers/scsi/scsi_scan.c31
-rw-r--r--drivers/scsi/scsi_syms.c5
-rw-r--r--drivers/scsi/sd.c287
-rw-r--r--drivers/scsi/sd.h1
-rw-r--r--drivers/scsi/sg.c12
-rw-r--r--drivers/scsi/sr.c115
-rw-r--r--drivers/scsi/sr_ioctl.c20
-rw-r--r--drivers/scsi/sr_vendor.c18
-rw-r--r--drivers/scsi/st.c4
-rw-r--r--drivers/scsi/sym53c8xx.c41
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c15
-rw-r--r--drivers/scsi/wd33c93.c5
-rw-r--r--drivers/usb/class/audio.c10
-rw-r--r--drivers/usb/core/usb.c4
-rw-r--r--drivers/usb/host/ohci-sa1111.c2
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/zorro/Makefile3
-rw-r--r--fs/Makefile2
-rw-r--r--fs/afs/cmservice.c7
-rw-r--r--fs/aio.c23
-rw-r--r--fs/block_dev.c36
-rw-r--r--fs/driverfs/inode.c4
-rw-r--r--fs/partitions/check.c10
-rw-r--r--fs/partitions/msdos.c2
-rw-r--r--fs/read_write.c10
-rw-r--r--fs/sysfs/Makefile9
-rw-r--r--fs/sysfs/inode.c642
-rw-r--r--fs/xfs/Makefile3
-rw-r--r--fs/xfs/linux/xfs_file.c28
-rw-r--r--fs/xfs/linux/xfs_globals.c3
-rw-r--r--fs/xfs/xfs_alloc.c13
-rw-r--r--fs/xfs/xfs_alloc_btree.c32
-rw-r--r--fs/xfs/xfs_bmap_btree.c4
-rw-r--r--fs/xfs/xfs_bmap_btree.h4
-rw-r--r--fs/xfs/xfs_inode.c5
-rw-r--r--fs/xfs/xfs_inode_item.h6
-rw-r--r--include/asm-i386/io_apic.h7
-rw-r--r--include/asm-ppc/div64.h23
-rw-r--r--include/asm-ppc/pci-bridge.h5
-rw-r--r--include/asm-ppc/sections.h16
-rw-r--r--include/asm-ppc/system.h6
-rw-r--r--include/asm-sparc/ptrace.h7
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/cdrom.h9
-rw-r--r--include/linux/device.h49
-rw-r--r--include/linux/driverfs_fs.h2
-rw-r--r--include/linux/fs.h19
-rw-r--r--include/linux/genhd.h10
-rw-r--r--include/linux/ide.h13
-rw-r--r--include/linux/isdn.h39
-rw-r--r--include/linux/isdn_ppp.h46
-rw-r--r--include/linux/mm.h15
-rw-r--r--include/linux/security.h5
-rw-r--r--include/linux/sysfs.h51
-rw-r--r--include/scsi/sg.h2
-rw-r--r--init/Makefile9
-rw-r--r--kernel/ksyms.c2
-rw-r--r--mm/filemap.c31
-rw-r--r--mm/madvise.c2
-rw-r--r--mm/readahead.c46
-rw-r--r--net/ipv4/ip_proc.c208
-rw-r--r--scripts/Makefile9
-rw-r--r--scripts/lxdialog/Makefile3
-rw-r--r--security/capability.c6
-rw-r--r--security/dummy.c6
-rw-r--r--security/security.c12
-rw-r--r--sound/oss/Makefile4
-rw-r--r--sound/oss/ite8172.c12
-rw-r--r--sound/oss/sound_config.h4
-rw-r--r--sound/pci/ens1370.c6
249 files changed, 8267 insertions, 6838 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index daf40bc291ca..2e3a7333354e 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -13,14 +13,6 @@ DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
kernel-api.sgml journal-api.sgml lsm.sgml
-JBDSOURCES := $(TOPDIR)/include/linux/jbd.h \
- $(TOPDIR)/fs/jbd/journal.c \
- $(TOPDIR)/fs/jbd/recovery.c \
- $(TOPDIR)/fs/jbd/transaction.c
-
-journal-api.sgml: journal-api.tmpl $(JBDSOURCES)
- $(TOPDIR)/scripts/docgen $(JBDSOURCES) \
- <journal-api.tmpl >journal-api.sgml
###
# The build process is as follows (targets):
# (sgmldocs)
@@ -32,7 +24,7 @@ journal-api.sgml: journal-api.tmpl $(JBDSOURCES)
# The targets that may be used.
.PHONY: sgmldocs psdocs pdfdocs htmldocs clean mrproper
-BOOKS := $(addprefix Documentation/DocBook/,$(DOCBOOKS))
+BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
sgmldocs: $(BOOKS)
PS := $(patsubst %.sgml, %.ps, $(BOOKS))
@@ -86,19 +78,19 @@ $(BOOKS): $(KERNELDOC)
###
# procfs guide uses a .c file as example code.
# This requires an explicit dependency
-C-procfs-example = Documentation/DocBook/procfs_example.sgml
-Documentation/DocBook/procfs-guide.sgml: $(C-procfs-example)
+C-procfs-example = procfs_example.sgml
+C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
+$(obj)/procfs-guide.sgml: $(C-procfs-example2)
###
# The parportbook includes a few images.
# Force them to be build before the books
IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig
-IMG-parportbook2 := $(addprefix Documentation/DocBook/,$(IMG-parportbook))
+IMG-parportbook2 := $(addprefix $(obj)/,$(IMG-parportbook))
EPS-parportbook := $(patsubst %.fig,%.eps, $(IMG-parportbook2))
PNG-parportbook := $(patsubst %.fig,%.png, $(IMG-parportbook2))
-Documentation/DocBook/parportbook.html: $(PNG-parportbook)
-Documentation/DocBook/parportbook.ps Documentation/DocBook/parportbook.pdf:\
- $(EPS-parportbook)
+$(obj)/parportbook.html: $(PNG-parportbook)
+$(obj)/parportbook.ps $(obj)/parportbook.pdf: $(EPS-parportbook)
###
# Rules to generate postscript, PDF and HTML
@@ -155,21 +147,20 @@ dochelp:
###
# clean and mrproper as used by the top-level makefile
# Temporary files left by various tools
-DVI := $(patsubst %.sgml, %.dvi, $(BOOKS))
-AUX := $(patsubst %.sgml, %.aux, $(BOOKS))
-TEX := $(patsubst %.sgml, %.tex, $(BOOKS))
-LOG := $(patsubst %.sgml, %.log, $(BOOKS))
-OUT := $(patsubst %.sgml, %.out, $(BOOKS))
-
-clean:
- @rm -f $(BOOKS)
- @rm -f $(DVI) $(AUX) $(TEX) $(LOG) $(OUT)
- @rm -f $(PNG-parportbook) $(EPS-parportbook)
- @rm -f $(C-procfs-example)
-
-mrproper:
- @rm -f $(PS) $(PDF)
- @rm -f -r $(HTML) $(patsubst %.html,%,$(HTML))
+clean-files := $(DOCBOOKS) \
+ $(patsubst %.sgml, %.dvi, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.aux, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.tex, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.log, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.out, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.ps, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.pdf, $(DOCBOOKS)) \
+ $(patsubst %.sgml, %.html, $(DOCBOOKS)) \
+ $(patsubst %.fig,%.eps, $(IMG-parportbook)) \
+ $(patsubst %.fig,%.png, $(IMG-parportbook)) \
+ $(C-procfs-example)
+
+clean-rule := rm -rf $(patsubst %.html,%,$(HTML))
include $(TOPDIR)/Rules.make
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
new file mode 100644
index 000000000000..d1d1c9e5a839
--- /dev/null
+++ b/Documentation/filesystems/sysfs.txt
@@ -0,0 +1,342 @@
+
+sysfs - _The_ filesystem for exporting kernel objects.
+
+Patrick Mochel <mochel@osdl.org>
+
+17 October 2002
+
+
+Note (17 Oct 2002): the name has just been changed from driverfs to
+sysfs. Updates to the documentation will come soon; after the
+conversion to use it is completely finished.
+
+
+
+What it is:
+~~~~~~~~~~~
+driverfs is a ram-based filesystem. It was created by copying
+ramfs/inode.c to driverfs/inode.c and doing a little search-and-replace.
+
+driverfs is a means to export kernel data structures, their
+attributes, and the linkages between them to userspace.
+
+driverfs provides a unified interface for exporting attributes to
+userspace. Currently, this interface is available only to device and
+bus drivers.
+
+
+Using driverfs
+~~~~~~~~~~~~~~
+driverfs is always compiled in. You can access it by doing something like:
+
+ mount -t driverfs driverfs /devices
+
+
+Top Level Directory Layout
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driverfs directory arrangement exposes the relationship of kernel
+data structures.
+
+The top level driverfs diretory looks like:
+
+bus/
+root/
+
+root/ contains a filesystem representation of the device tree. It maps
+directly to the internal kernel device tree, which is a hierarchy of
+struct device.
+
+bus/ contains flat directory layout of the various bus types in the
+kernel. Each bus's directory contains two subdirectories:
+
+ devices/
+ drivers/
+
+devices/ contains symlinks for each device discovered in the system
+that point to the device's directory under root/.
+
+drivers/ contains a directory for each device driver that is loaded
+for devices on that particular bus (this assmumes that drivers do not
+span multiple bus types).
+
+
+More information can device-model specific features can be found in
+Documentation/device-model/.
+
+
+Directory Contents
+~~~~~~~~~~~~~~~~~~
+Each object that is represented in driverfs gets a directory, rather
+than a file, to make it simple to export attributes of that object.
+Attributes are exported via ASCII text files. The programming
+interface is discussed below.
+
+Instead of having monolithic files that are difficult to parse, all
+files are intended to export one attribute. The name of the attribute
+is the name of the file. The value of the attribute are the contents
+of the file.
+
+There should be few, if any, exceptions to this rule. You should not
+violate it, for fear of public humilation.
+
+
+The Two-Tier Model
+~~~~~~~~~~~~~~~~~~
+
+driverfs is a very simple, low-level interface. In order for kernel
+objects to use it, there must be an intermediate layer in place for
+each object type.
+
+All calls in driverfs are intended to be as type-safe as possible.
+In order to extend driverfs to support multiple data types, a layer of
+abstraction was required. This intermediate layer converts between the
+generic calls and data structures of the driverfs core to the
+subsystem-specific objects and calls.
+
+
+The Subsystem Interface
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The subsystems bear the responsibility of implementing driverfs
+extensions for the objects they control. Fortunately, it's intended to
+be really easy to do so.
+
+It's divided into three sections: directories, files, and operations.
+
+
+Directories
+~~~~~~~~~~~
+
+struct driver_dir_entry {
+ char * name;
+ struct dentry * dentry;
+ mode_t mode;
+ struct driverfs_ops * ops;
+};
+
+
+int
+driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
+
+void
+driverfs_remove_dir(struct driver_dir_entry * entry);
+
+The directory structure should be statically allocated, and reside in
+a subsystem-specific data structure:
+
+struct device {
+ ...
+ struct driver_dir_entry dir;
+};
+
+The subsystem is responsible for initializing the name, mode, and ops
+fields of the directory entry. (More on struct driverfs_ops later)
+
+
+Files
+~~~~~
+
+struct attribute {
+ char * name;
+ mode_t mode;
+};
+
+
+int
+driverfs_create_file(struct attribute * attr, struct driver_dir_entry * parent);
+
+void
+driverfs_remove_file(struct driver_dir_entry *, const char * name);
+
+
+The attribute structure is a simple, common token that the driverfs
+core handles. It has little use on its own outside of the
+core. Objects cannot use a plain struct attribute to export
+attributes, since there are no callbacks for reading and writing data.
+
+Therefore, the subsystem is required to define a data structure that
+encapsulates the attribute structure, and provides type-safe callbacks
+for reading and writing data.
+
+An example looks like this:
+
+struct device_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+
+Note that there is a struct attribute embedded in the structure. In
+order to relieve pain in declaring attributes, the subsystem should
+also define a macro, like:
+
+#define DEVICE_ATTR(_name,_mode,_show,_store) \
+struct device_attribute dev_attr_##_name = { \
+ .attr = {.name = __stringify(_name) , .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+This hides the initialization of the embedded struct, and in general,
+the internals of each structure. It yields a structure by the name of
+dev_attr_<name>.
+
+In order for objects to create files, the subsystem should create
+wrapper functions, like this:
+
+int device_create_file(struct device *device, struct device_attribute * entry);
+void device_remove_file(struct device * dev, struct device_attribute * attr);
+
+..and forward the call on to the driverfs functions.
+
+Note that there is no unique information in the attribute structures,
+so the same structure can be used to describe files of several
+different object instances.
+
+
+Operations
+~~~~~~~~~~
+
+struct driverfs_ops {
+ int (*open)(struct driver_dir_entry *);
+ int (*close)(struct driver_dir_entry *);
+ ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
+ ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
+};
+
+
+Subsystems are required to implement this set of callbacks. Their
+purpose is to translate the generic data structures into the specific
+objects, and operate on them. This can be done by defining macros like
+this:
+
+#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+
+#define to_device(d) container_of(d, struct device, dir)
+
+
+Since the directories are statically allocated in the object, you can
+derive the pointer to the object that owns the file. Ditto for the
+attribute structures.
+
+Current Interfaces
+~~~~~~~~~~~~~~~~~~
+
+The following interface layers currently exist in driverfs:
+
+
+- devices (include/linux/device.h)
+----------------------------------
+Structure:
+
+struct device_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+Declaring:
+
+DEVICE_ATTR(_name,_str,_mode,_show,_store);
+
+Creation/Removal:
+
+int device_create_file(struct device *device, struct device_attribute * entry);
+void device_remove_file(struct device * dev, struct device_attribute * attr);
+
+
+- bus drivers (include/linux/device.h)
+--------------------------------------
+Structure:
+
+struct bus_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
+};
+
+Declaring:
+
+BUS_ATTR(_name,_mode,_show,_store)
+
+Creation/Removal:
+
+int bus_create_file(struct bus_type *, struct bus_attribute *);
+void bus_remove_file(struct bus_type *, struct bus_attribute *);
+
+
+- device drivers (include/linux/device.h)
+-----------------------------------------
+
+Structure:
+
+struct driver_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+};
+
+Declaring:
+
+DRIVER_ATTR(_name,_mode,_show,_store)
+
+Creation/Removal:
+
+int driver_create_file(struct device_driver *, struct driver_attribute *);
+void driver_remove_file(struct device_driver *, struct driver_attribute *);
+
+
+Reading/Writing Data
+~~~~~~~~~~~~~~~~~~~~
+The callback functionality is similar to the way procfs works. When a
+user performs a read(2) or write(2) on the file, it first calls a
+driverfs function. This calls to the subsystem, which then calls to
+the object's show() or store() function.
+
+The buffer pointer, offset, and length should be passed to each
+function. The downstream callback should fill the buffer and return
+the number of bytes read/written.
+
+
+What driverfs is not:
+~~~~~~~~~~~~~~~~~~~~~
+It is not a replacement for either devfs or procfs.
+
+It does not handle device nodes, like devfs is intended to do. I think
+this functionality is possible, but indeed think that integration of
+the device nodes and control files should be done. Whether driverfs or
+devfs, or something else, is the place to do it, I don't know.
+
+It is not intended to be a replacement for all of the procfs
+functionality. I think that many of the driver files should be moved
+out of /proc (and maybe a few other things as well ;).
+
+
+
+Limitations:
+~~~~~~~~~~~~
+The driverfs functions assume that at most a page is being either read
+or written each time.
+
+There is a race condition that is really, really hard to fix; if not
+impossible. There exists a race between a driverfs file being opened
+and the object that owns the file going away. During the driverfs
+open() callback, the reference count for the owning object needs to be
+incremented.
+
+For drivers, we can put a struct module * owner in struct driver_dir_entry
+and do try_inc_mod_count() when we open a file. However, this won't
+work for devices, that aren't tied to a module. And, it is still not
+guaranteed to solve the race.
+
+I'm looking into fixing this, but it may not be doable without making
+a separate filesystem instance for each object. It's fun stuff. Please
+mail me with creative ideas that you know will work.
+
+
+Possible bugs:
+~~~~~~~~~~~~~~
+It may not deal with offsets and/or seeks very well, especially if
+they cross a page boundary.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index a9b191413d74..b3daddefc143 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,3 +1,4 @@
+
List of maintainers and how to submit kernel changes
Please try to follow the guidelines below. This will make things
@@ -261,7 +262,6 @@ BFS FILE SYSTEM
P: Tigran A. Aivazian
M: tigran@veritas.com
L: linux-kernel@vger.kernel.org
-W: http://www.ocston.org/~tigran/patches/bfs
S: Maintained
BLOCK LAYER
@@ -654,8 +654,8 @@ W: http://www.nyx.net/~arobinso
S: Maintained
HFS FILESYSTEM
-P: Adrian Sun
-M: asun@cobaltnet.com
+P: Oliver Neukum
+M: oliver@neukum.org
L: linux-kernel@vger.kernel.org
S: Maintained
diff --git a/Makefile b/Makefile
index e94c4aca82ee..388e62bb287b 100644
--- a/Makefile
+++ b/Makefile
@@ -239,7 +239,7 @@ ifdef include-config
# If .config doesn't exist - tough luck
-.config: arch/$(ARCH)/config.in $(shell find . -name Config.in)
+.config: arch/$(ARCH)/config.in # FIXME $(shell find . -name Config.in)
@echo '***'
@if [ -f $@ ]; then \
echo '*** The tree was updated, so your .config may be'; \
@@ -456,18 +456,23 @@ include/linux/version.h: Makefile
depend dep: .hdepend
-# .hdepend is our (misnomed) marker for whether we've run
+# .hdepend is our (misnomed) marker for whether we've
# generated module versions
-.hdepend: $(if $(filter dep depend,$(MAKECMDGOALS)),FORCE)
+make-versions := $(strip $(if $(filter dep depend,$(MAKECMDGOALS)),1) \
+ $(if $(wildcard .hdepend),,1))
+
+.hdepend: prepare FORCE
+ifneq ($(make-versions),)
@$(MAKE) include/linux/modversions.h
@touch $@
+endif
ifdef CONFIG_MODVERSIONS
# Update modversions.h, but only if it would change.
-include/linux/modversions.h: scripts/fixdep prepare FORCE
+include/linux/modversions.h: FORCE
@rm -rf .tmp_export-objs
@$(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS))
@echo -n ' Generating $@'
@@ -661,90 +666,61 @@ allmodconfig:
defconfig:
yes '' | $(CONFIG_SHELL) $(src)/scripts/Configure -d arch/$(ARCH)/config.in
-# Cleaning up
-# ---------------------------------------------------------------------------
+###
+# Cleaning is done on three levels.
+# make clean Delete all automatically generated files, including
+# tools and firmware.
+# make mrproper Delete the current configuration, and related files
+# Any core files spread around is deleted as well
+# make distclean Remove editor backup files, patch leftover files and the like
-# files removed with 'make clean'
-CLEAN_FILES += \
- include/linux/compile.h \
- vmlinux System.map \
- drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
- drivers/char/conmakehash \
- drivers/char/drm/*-mod.c \
- drivers/char/defkeymap.c drivers/char/qtronixmap.c \
- drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist \
- drivers/zorro/devlist.h drivers/zorro/gen-devlist \
- sound/oss/bin2hex sound/oss/hex2hex \
- drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} \
- drivers/scsi/aic7xxx/aic7xxx_seq.h \
- drivers/scsi/aic7xxx/aic7xxx_reg.h \
- drivers/scsi/aic7xxx/aicasm/aicasm_gram.c \
- drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \
- drivers/scsi/aic7xxx/aicasm/y.tab.h \
- drivers/scsi/aic7xxx/aicasm/aicasm \
- drivers/scsi/53c700_d.h drivers/scsi/sim710_d.h \
- drivers/scsi/53c7xx_d.h drivers/scsi/53c7xx_u.h \
- drivers/scsi/53c8xx_d.h drivers/scsi/53c8xx_u.h \
- net/802/cl2llc.c net/802/transit/pdutr.h net/802/transit/timertr.h \
- net/802/pseudo/pseudocode.h \
- net/khttpd/make_times_h net/khttpd/times.h \
- submenu*
-
-# files removed with 'make mrproper'
+# Files removed with 'make clean'
+CLEAN_FILES += vmlinux System.map MC*
+
+# Files removed with 'make mrproper'
MRPROPER_FILES += \
include/linux/autoconf.h include/linux/version.h \
- drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h \
- drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h \
- drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h \
- drivers/net/hamradio/soundmodem/gentbl \
- sound/oss/*_boot.h sound/oss/.*.boot \
- sound/oss/msndinit.c \
- sound/oss/msndperm.c \
- sound/oss/pndsperm.c \
- sound/oss/pndspini.c \
- drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw \
- .version .config* config.in config.old \
- scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp \
- scripts/lxdialog/*.o scripts/lxdialog/lxdialog \
+ .version .config .config.old config.in config.old \
.menuconfig.log \
include/asm \
.hdepend include/linux/modversions.h \
tags TAGS kernel.spec \
.tmp*
-# directories removed with 'make mrproper'
+# Directories removed with 'make mrproper'
MRPROPER_DIRS += \
.tmp_export-objs \
include/config \
include/linux/modules
-clean: archclean
- @echo 'Cleaning up'
- @find . $(RCS_FIND_IGNORE) \
- \( -name \*.[oas] -o -name core -o -name .\*.cmd -o \
- -name .\*.tmp -o -name .\*.d \) -type f -print \
- | grep -v lxdialog/ | xargs rm -f
- @rm -f $(CLEAN_FILES)
- +@$(call descend,Documentation/DocBook,clean)
-
-mrproper: clean archmrproper
- @echo 'Making mrproper'
+# clean - Delete all intermediate files
+#
+clean-dirs += $(ALL_SUBDIRS) Documentation/DocBook scripts
+
+$(addprefix _clean_,$(clean-dirs)):
+ +@$(call descend,$(patsubst _clean_%,%,$@), subdirclean)
+
+quiet_cmd_rmclean = RM $$(CLEAN_FILES)
+cmd_rmclean = rm -f $(CLEAN_FILES)
+clean: archclean $(addprefix _clean_,$(clean-dirs))
+ $(call cmd,rmclean)
@find . $(RCS_FIND_IGNORE) \
- \( -name .depend -o -name .\*.cmd \) \
- -type f -print | xargs rm -f
- @rm -rf $(MRPROPER_DIRS)
- @rm -f $(MRPROPER_FILES)
- +@$(call descend,scripts,mrproper)
- +@$(call descend,Documentation/DocBook,mrproper)
+ \( -name '*.[oas]' -o -name '.*.cmd' -o -name '.*.d' \
+ -o -name '.*.tmp' \) -type f -print | xargs rm -f
-distclean: mrproper
- @echo 'Making distclean'
+# mrproper - delete configuration + modules + core files
+#
+quiet_cmd_mrproper = RM $$(MRPROPER_DIRS) + $$(MRPROPER_FILES)
+cmd_mrproper = rm -rf $(MRPROPER_DIRS) && rm -f $(MRPROPER_FILES)
+mrproper distclean: clean archmrproper
+ @echo ' Making $@ in the srctree'
@find . $(RCS_FIND_IGNORE) \
- \( -not -type d \) -and \
\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
- -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f \
- -print | xargs rm -f
+ -o -name '.*.rej' -o -size 0 \
+ -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
+ -type f -print | xargs rm -f
+ $(call cmd,mrproper)
# Generate tags for editors
# ---------------------------------------------------------------------------
diff --git a/Rules.make b/Rules.make
index affdf72286ae..56e62f97f333 100644
--- a/Rules.make
+++ b/Rules.make
@@ -87,6 +87,7 @@ obj-m := $(filter-out %/, $(obj-m))
# Subdirectories we need to descend into
subdir-ym := $(sort $(subdir-y) $(subdir-m))
+subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
# export.o is never a composite object, since $(export-objs) has a
# fixed meaning (== objects which EXPORT_SYMBOL())
@@ -113,6 +114,10 @@ real-objs-m := $(foreach m, $(obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m
# Only build module versions for files which are selected to be built
export-objs := $(filter $(export-objs),$(real-objs-y) $(real-objs-m))
+host-progs-single := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
+host-progs-multi := $(foreach m,$(host-progs),$(if $($(m)-objs),$(m)))
+host-progs-multi-objs := $(foreach m,$(host-progs-multi),$($(m)-objs))
+
# Add subdir path
EXTRA_TARGETS := $(addprefix $(obj)/,$(EXTRA_TARGETS))
@@ -127,12 +132,19 @@ multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
multi-objs-y := $(addprefix $(obj)/,$(multi-objs-y))
multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
+subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
+clean-files := $(addprefix $(obj)/,$(clean-files))
+host-progs := $(addprefix $(obj)/,$(host-progs))
+host-progs-single := $(addprefix $(obj)/,$(host-progs-single))
+host-progs-multi := $(addprefix $(obj)/,$(host-progs-multi))
+host-progs-multi-objs := $(addprefix $(obj)/,$(host-progs-multi-objs))
# The temporary file to save gcc -MD generated dependencies must not
# contain a comma
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
-# We're called for one of three purposes:
+# We're called for one of four purposes:
+# o subdirclean: Delete intermidiate files in the current directory
# o fastdep: build module version files (.ver) for $(export-objs) in
# the current directory
# o modules_install: install the modules in the current directory
@@ -142,6 +154,19 @@ depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
# When targets are given directly (like foo.o), we just build these
# targets (That happens when someone does make some/dir/foo.[ois])
+ifeq ($(MAKECMDGOALS),subdirclean)
+
+__clean-files := $(wildcard $(EXTRA_TARGETS) $(host-progs) $(clean-files))
+
+subdirclean: $(subdir-ymn)
+ifneq ($(strip $(__clean-files) $(clean-rule)),)
+ rm -f $(__clean-files)
+ $(clean-rule)
+else
+ @/bin/true
+endif
+
+else
ifeq ($(MAKECMDGOALS),fastdep)
# ===========================================================================
@@ -161,7 +186,7 @@ else
# This sets version suffixes on exported symbols
# ---------------------------------------------------------------------------
-MODVERDIR := include/linux/modules/
+MODVERDIR := include/linux/modules
#
# Added the SMP separator to stop module accidents between uniprocessor
@@ -399,14 +424,6 @@ targets += $(multi-used-y) $(multi-used-m)
# Compile programs on the host
# ===========================================================================
-host-progs-single := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
-host-progs-multi := $(foreach m,$(host-progs),$(if $($(m)-objs),$(m)))
-host-progs-multi-objs := $(foreach m,$(host-progs-multi),$($(m)-objs))
-host-progs := $(addprefix $(obj)/,$(host-progs))
-host-progs-single := $(addprefix $(obj)/,$(host-progs-single))
-host-progs-multi := $(addprefix $(obj)/,$(host-progs-multi))
-host-progs-multi-objs := $(addprefix $(obj)/,$(host-progs-multi-objs))
-
quiet_cmd_host_cc__c = HOSTCC $(echo_target)
cmd_host_cc__c = $(HOSTCC) -Wp,-MD,$(depfile) \
$(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
@@ -431,6 +448,7 @@ $(host-progs-multi): %: $(host-progs-multi-objs) FORCE
targets += $(host-progs-single) $(host-progs-multi-objs) $(host-progs-multi)
+endif # ! subdirclean
endif # ! modules_install
endif # ! fastdep
@@ -480,9 +498,9 @@ cmd_gzip = gzip -f -9 < $< > $@
# Descending
# ---------------------------------------------------------------------------
-.PHONY: $(subdir-ym)
+.PHONY: $(subdir-ymn)
-$(subdir-ym):
+$(subdir-ymn):
+@$(call descend,$@,$(MAKECMDGOALS))
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 4cb68c31b86e..2b291c31ff8b 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -1114,7 +1114,7 @@ int ecard_register_driver(struct ecard_driver *drv)
void ecard_remove_driver(struct ecard_driver *drv)
{
- remove_driver(&drv->drv);
+ driver_unregister(&drv->drv);
}
static int ecard_match(struct device *_dev, struct device_driver *_drv)
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 4df45365d6f0..dbd363bdb52f 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -88,6 +88,6 @@ install: vmlinux
+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install)
archclean:
- +@$(call makeboot,clean)
+ +@$(call makeboot,subdirclean)
archmrproper:
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index 3369bfc67700..b06bab8ccd43 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -28,6 +28,8 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \
setup setup.o zImage bzImage
+subdir- := compressed
+
host-progs := tools/build
# Default
@@ -79,11 +81,6 @@ zlilo: $(BOOTIMAGE)
install: $(BOOTIMAGE)
sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
-clean:
- @echo 'Cleaning up (boot)'
- @rm -f $(host-progs) $(EXTRA_TARGETS)
- +@$(call descend,$(obj)/compressed) clean
-
archhelp:
@echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
@echo ' install - Install kernel using'
diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
index 53af39a4408e..16383b2df2fb 100644
--- a/arch/i386/boot/compressed/Makefile
+++ b/arch/i386/boot/compressed/Makefile
@@ -24,7 +24,3 @@ LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
$(call if_changed,ld)
-
-clean:
- @echo 'Cleaning up (boot/compressed)'
- @rm -f $(EXTRA_TARGETS)
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 1026d1a0a1f4..5777724de6f0 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -453,6 +453,7 @@ fi
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+ bool ' Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW
bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
diff --git a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c
index 5e5ef23f39b9..5941b9da5985 100644
--- a/arch/i386/kernel/bluesmoke.c
+++ b/arch/i386/kernel/bluesmoke.c
@@ -300,7 +300,6 @@ static void mce_checkregs (void *info)
static void do_mce_timer(void *data)
{
- mce_checkregs(NULL);
smp_call_function (mce_checkregs, NULL, 1, 1);
}
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 3f95d0b1f189..df360f06616e 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -42,6 +42,21 @@ static void __init init_amd(struct cpuinfo_x86 *c)
switch(c->x86)
{
+ case 4:
+ /*
+ * General Systems BIOSen alias the cpu frequency registers
+ * of the Elan at 0x000df000. Unfortuantly, one of the Linux
+ * drivers subsequently pokes it, and changes the CPU speed.
+ * Workaround : Remove the unneeded alias.
+ */
+#define CBAR (0xfffc) /* Configuration Base Address (32-bit) */
+#define CBAR_ENB (0x80000000)
+#define CBAR_KEY (0X000000CB)
+ if (c->x86_model==9 || c->x86_model == 10) {
+ if (inl (CBAR) & CBAR_ENB)
+ outl (0 | CBAR_KEY, CBAR);
+ }
+
case 5:
if( c->x86_model < 6 )
{
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 5bc54a30c2f8..4bb71d80fb1f 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -856,7 +856,9 @@ void __init print_IO_APIC(void)
printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)&reg_00);
printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID);
- if (reg_00.__reserved_1 || reg_00.__reserved_2)
+ printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.delivery_type);
+ printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.LTS);
+ if (reg_00.__reserved_0 || reg_00.__reserved_1 || reg_00.__reserved_2)
UNEXPECTED_IO_APIC();
printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 2ac7753a5f66..fdddbf524c01 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -328,8 +328,22 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
+ long esp;
irq_enter();
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /* Debugging check for stack overflow: is there less than 1KB free? */
+ __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));
+ if (unlikely(esp < (sizeof(struct task_struct) + 1024))) {
+ extern void show_stack(unsigned long *);
+
+ printk("do_IRQ: stack overflow: %ld\n",
+ esp - sizeof(struct task_struct));
+ __asm__ __volatile__("movl %%esp,%0" : "=r" (esp));
+ show_stack((void *)esp);
+ }
+#endif
kstat.irqs[cpu][irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index ccdebea64733..58201846cf7c 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -260,7 +260,7 @@ static void do_update_one(void *unused)
if (microcode[i].rev < rev) {
spin_unlock_irqrestore(&microcode_update_lock, flags);
- printk(KERN_ERR
+ printk(KERN_INFO
"microcode: CPU%d not 'upgrading' to earlier revision"
" %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
return;
@@ -268,7 +268,7 @@ static void do_update_one(void *unused)
/* notify the caller of success on this cpu */
req->err = 0;
spin_unlock_irqrestore(&microcode_update_lock, flags);
- printk(KERN_ERR
+ printk(KERN_INFO
"microcode: CPU%d already at revision"
" %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
return;
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 5218fd2ea29a..ca8a9d54f116 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -482,7 +482,7 @@ void __init mem_init(void)
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
+ printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
num_physpages << (PAGE_SHIFT-10),
codesize >> 10,
@@ -584,14 +584,14 @@ void free_initmem(void)
free_page(addr);
totalram_pages++;
}
- printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+ printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
}
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
if (start < end)
- printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
set_page_count(virt_to_page(start), 1);
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index db71a8c73b5b..9cfc595855de 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -291,7 +291,7 @@ void pcibios_set_master(struct pci_dev *dev)
lat = pcibios_max_latency;
else
return;
- printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
+ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
index 41e54abb9b5a..99301e99ae50 100644
--- a/arch/i386/vmlinux.lds.S
+++ b/arch/i386/vmlinux.lds.S
@@ -8,6 +8,7 @@ jiffies = jiffies_64;
SECTIONS
{
. = 0xC0000000 + 0x100000;
+ /* read-only */
_text = .; /* Text and read-only data */
.text : {
*(.text)
@@ -29,16 +30,34 @@ SECTIONS
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
+ __start___kallsyms = .; /* All kernel symbols */
+ __kallsyms : { *(__kallsyms) }
+ __stop___kallsyms = .;
+
+ /* writeable */
.data : { /* Data */
*(.data)
CONSTRUCTORS
}
+ . = ALIGN(4096);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
+ . = ALIGN(4096);
+ .data.page_aligned : { *(.data.idt) }
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
_edata = .; /* End of data section */
. = ALIGN(8192); /* init_task */
.data.init_task : { *(.data.init_task) }
+ /* will be freed after init */
. = ALIGN(4096); /* Init code and data */
__init_begin = .;
.init.text : { *(.init.text) }
@@ -64,23 +83,8 @@ SECTIONS
__per_cpu_end = .;
. = ALIGN(4096);
__init_end = .;
-
- . = ALIGN(4096);
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(4096);
- __nosave_end = .;
-
- . = ALIGN(4096);
- .data.page_aligned : { *(.data.idt) }
-
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- __start___kallsyms = .; /* All kernel symbols */
- __kallsyms : { *(__kallsyms) }
- __stop___kallsyms = .;
-
+ /* freed after init ends here */
+
__bss_start = .; /* BSS */
.bss : { *(.bss) }
__bss_stop = .;
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index c430e823ef08..5fa3e289b581 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -3763,12 +3763,15 @@ do_smb_super_data_conv(void *raw_data)
struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+ if (s32->version != SMB_MOUNT_OLDVERSION)
+ goto out;
s->version = s32->version;
s->mounted_uid = s32->mounted_uid;
s->uid = s32->uid;
s->gid = s32->gid;
s->file_mode = s32->file_mode;
s->dir_mode = s32->dir_mode;
+out:
return raw_data;
}
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 8fc59afbc307..75467652ef37 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -64,7 +64,7 @@ drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
drivers-$(CONFIG_8260) += arch/ppc/8260_io/
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+makeboot = $(call descend,arch/ppc/boot,$(1))
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd pImage vmlinux.sm
@@ -74,14 +74,14 @@ AFLAGS_vmlinux.lds.o := -Upowerpc
bzImage: zImage
$(BOOT_TARGETS): vmlinux
- @$(MAKEBOOT) $@
+ +@$(call makeboot,$@)
%_config: arch/ppc/configs/%_defconfig
rm -f .config arch/ppc/defconfig
cp -f arch/ppc/configs/$(@:config=defconfig) .config
archclean:
- @$(MAKEBOOT) clean
+ +@$(call makeboot,clean)
archmrproper:
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index 7fc8e3dac69e..a6a312b7ba26 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -10,25 +10,16 @@
# modified by Cort (cort@cs.nmt.edu)
#
-GZIP_FLAGS = -v9f
-
CFLAGS += -fno-builtin -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/boot/include
AFLAGS += -D__BOOTER__
OBJCOPY_ARGS = -O elf32-powerpc
-MKIMAGE := ./utils/mkimage.wrapper
-
-lib/lib.a: lib/zlib.c
- $(MAKE) -C lib
+subdir-y := simple
+subdir-$(CONFIG_ALL_PPC) := openfirmware prep
-images/vmlinux.gz: $(TOPDIR)/vmlinux
- $(MAKE) -C images vmlinux.gz
+HOSTCFLAGS += -Iarch/$(ARCH)/boot/include
-# Subdirs and tools needed for each. Assume we always need to go into
-# 'simple' unless told otherwise.
-subdir-y := lib common simple
-subdir-$(CONFIG_ALL_PPC) := openfirmware prep
tools-$(CONFIG_ALL_PPC) := addnote mknote hack-coff mkprep
tools-$(CONFIG_PPLUS) := mkbugboot mkprep
tools-$(CONFIG_4xx) := mktree
@@ -40,49 +31,24 @@ tools-$(CONFIG_PRPMC750) := mkbugboot mkprep
tools-$(CONFIG_PRPMC800) := mkbugboot mkprep
tools-$(CONFIG_SPRUCE) := mktree
-# These are dirs we don't want to go into on BOOT_TARGETS. We have them for
-# the 'depend' stage.
-NONBOOT := lib common
+all-tools := addnote mknote hack-coff mkprep mkbugboot mktree
-# These are the subdirs we want to use
-BOOTDIRS = $(filter-out $(NONBOOT), $(subdir-y))
+host-progs := $(addprefix utils/,$(tools-y))
-makeof1275:
- $(MAKE) -C of1275
-
-# This will make the tools we need. We do it like this to ensure that we use
-# HOSTCC. -- Tom
-maketools:
- $(MAKE) -C utils $(tools-y)
-
-# The targets all boards support for boot images.
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
+include $(TOPDIR)/Rules.make
-$(BOOT_TARGETS): vmapus lib/lib.a images/vmlinux.gz makeof1275 maketools
-ifneq ($(BOOTDIRS),)
- for d in $(BOOTDIRS); do $(MAKE) -C $$d $@; done
-endif
+zImage zImage.initrd znetboot znetboot.initrd: $(subdir-y)
-vmapus: $(TOPDIR)/vmlinux
-ifdef CONFIG_APUS
- $(STRIP) $(TOPDIR)/vmlinux -o images/vmapus
- gzip $(GZIP_FLAGS) images/vmapus
-endif
+simple openfirmware prep: lib common images
+openfirmware prep: of1275
-# Make an image for PPCBoot
-pImage: images/vmlinux.gz
- $(MKIMAGE) -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
- -n 'Linux-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)' \
- -d $< images/vmlinux.PPCBoot
- ln -sf vmlinux.PPCBoot images/pImage
+lib common of1275 images: FORCE
+ +@$(call descend,$(obj)/$@,)
-vmlinux.sm: $(TOPDIR)/vmlinux utils/addSystemMap
- ./utils/addSystemMap $(TOPDIR)/System.map $(TOPDIR)/vmlinux images/vmlinux.sm
+openfirmware prep simple: FORCE
+ +@$(call descend,$(obj)/$@,$(MAKECMDGOALS))
-# These are subdirs with files not normally rm'ed. -- Tom
-clean:
- $(MAKE) -C images clean
- $(MAKE) -C utils clean
- $(MAKE) -C openfirmware clean
+CLEAN_FILES += $(addprefix $(obj)/utils,$(all-tools))
-include $(TOPDIR)/Rules.make
+clean: FORCE
+ +@$(call descend,$(obj)/images,clean)
diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile
index 5295d53bb8a8..0b882179eef6 100644
--- a/arch/ppc/boot/common/Makefile
+++ b/arch/ppc/boot/common/Makefile
@@ -8,7 +8,12 @@
# Tom Rini January 2001
#
-coffcrt0.o:
- $(CC) $(AFLAGS) -DXCOFF -traditional -c -o coffcrt0.o crt0.S
+L_TARGET := lib.a
+
+obj-y := string.o util.o misc-common.o
+obj-$(CONFIG_ALL_PPC) += mpc10x_memory.o
+obj-$(CONFIG_LOPEC) += mpc10x_memory.o
+obj-$(CONFIG_PAL4) += cpc700_memory.o
+obj-$(CONFIG_SERIAL_8250_CONSOLE) += ns16550.o
include $(TOPDIR)/Rules.make
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
index 8723f6c5519e..f37cc9e47a0f 100644
--- a/arch/ppc/boot/images/Makefile
+++ b/arch/ppc/boot/images/Makefile
@@ -2,11 +2,16 @@
# This dir holds all of the images for PPC machines.
# Tom Rini January 2001
+all: $(obj)/vmlinux.gz
+
include $(TOPDIR)/Rules.make
-vmlinux.gz: $(TOPDIR)/vmlinux
- $(OBJCOPY) --strip-all -S -O binary $(TOPDIR)/vmlinux vmlinux
- gzip -vf9 vmlinux
+GZIP_FLAGS = -v9f
+
+$(obj)/vmlinux.gz: vmlinux
+ $(OBJCOPY) -S -O binary vmlinux $(obj)/vmlinux
+ gzip $(GZIP_FLAGS) $(obj)/vmlinux
clean:
- rm -f sImage vmapus vmlinux* miboot* zImage* zvmlinux*
+ rm -f $(obj)/sImage $(obj)/vmapus $(obj)/vmlinux* $(obj)/miboot*
+ rm -f $(obj)/zImage* z$(obj)/vmlinux*
diff --git a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h
index e71b667a683e..bef99d1f6b18 100644
--- a/arch/ppc/boot/include/mpc10x.h
+++ b/arch/ppc/boot/include/mpc10x.h
@@ -58,7 +58,7 @@
#define MPC10X_MCTLR_EXT_MEM_START_2 0x8c /* Banks 4-7 */
#define MPC10X_MCTLR_MEM_END_1 0x90 /* Banks 0-3 */
-#define MPC10X_MCTLR_MEM_END_2i 0x94 /* Banks 4-7 */
+#define MPC10X_MCTLR_MEM_END_2 0x94 /* Banks 4-7 */
#define MPC10X_MCTLR_EXT_MEM_END_1 0x98 /* Banks 0-3 */
#define MPC10X_MCTLR_EXT_MEM_END_2 0x9c /* Banks 4-7 */
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index f1bd994045f0..4984baf0ff96 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -4,6 +4,6 @@
L_TARGET := lib.a
-obj-y := zlib.o
+obj-y := zlib.o div64.o
include $(TOPDIR)/Rules.make
diff --git a/arch/ppc/boot/lib/div64.S b/arch/ppc/boot/lib/div64.S
new file mode 100644
index 000000000000..3527569e9926
--- /dev/null
+++ b/arch/ppc/boot/lib/div64.S
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+_GLOBAL(__div64_32)
+ lwz r5,0(r3) # get the dividend into r5/r6
+ lwz r6,4(r3)
+ cmplw r5,r4
+ li r7,0
+ li r8,0
+ blt 1f
+ divwu r7,r5,r4 # if dividend.hi >= divisor,
+ mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
+ subf. r5,r0,r5 # dividend.hi %= divisor
+ beq 3f
+1: mr r11,r5 # here dividend.hi != 0
+ andis. r0,r5,0xc000
+ bne 2f
+ cntlzw r0,r5 # we are shifting the dividend right
+ li r10,-1 # to make it < 2^32, and shifting
+ srw r10,r10,r0 # the divisor right the same amount,
+ add r9,r4,r10 # rounding up (so the estimate cannot
+ andc r11,r6,r10 # ever be too large, only too small)
+ andc r9,r9,r10
+ or r11,r5,r11
+ rotlw r9,r9,r0
+ rotlw r11,r11,r0
+ divwu r11,r11,r9 # then we divide the shifted quantities
+2: mullw r10,r11,r4 # to get an estimate of the quotient,
+ mulhwu r9,r11,r4 # multiply the estimate by the divisor,
+ subfc r6,r10,r6 # take the product from the divisor,
+ add r8,r8,r11 # and add the estimate to the accumulated
+ subfe. r5,r9,r5 # quotient
+ bne 1b
+3: cmplw r6,r4
+ blt 4f
+ divwu r0,r6,r4 # perform the remaining 32-bit division
+ mullw r10,r0,r4 # and get the remainder
+ add r8,r8,r0
+ subf r6,r10,r6
+4: stw r7,0(r3) # return the quotient in *r3
+ stw r8,4(r3)
+ mr r3,r6 # return the remainder in r3
+ blr
diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile
index e855cb64b28f..1d3a1f8bef49 100644
--- a/arch/ppc/boot/of1275/Makefile
+++ b/arch/ppc/boot/of1275/Makefile
@@ -2,7 +2,7 @@
# Makefile of1275 stuff
#
-L_TARGET := of1275.a
+L_TARGET := lib.a
obj-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \
ofstdio.o read.o release.o write.o
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
index c34d71381350..210f162442e4 100644
--- a/arch/ppc/boot/openfirmware/Makefile
+++ b/arch/ppc/boot/openfirmware/Makefile
@@ -10,24 +10,37 @@
# Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
# rules.
+EXTRA_TARGETS := start.o misc.o crt0.o coffcrt0.o coffmain.o chrpmain.o \
+ newworldmain.o common.o
+
+boot: zImage
+
+include $(TOPDIR)/Rules.make
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+of1275 := $(boot)/of1275
+images := $(boot)/images
+
OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
-COFF_LD_ARGS = -T ../ld.script -e _start -Ttext 0x00500000 -Bstatic
-CHRP_LD_ARGS = -T ../ld.script -e _start -Ttext 0x00400000
-NEWWORLD_LD_ARGS = -T ../ld.script -e _start -Ttext 0x01000000
+COFF_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x00700000 -Bstatic
+CHRP_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x00800000
+NEWWORLD_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x01000000
-COMMONOBJS = start.o misc.o ../common/string.o common.o
-COFFOBJS = ../common/coffcrt0.o $(COMMONOBJS) coffmain.o
-CHRPOBJS = ../common/crt0.o $(COMMONOBJS) chrpmain.o
-NEWWORLDOBJS = ../common/crt0.o $(COMMONOBJS) newworldmain.o
+COMMONOBJS = $(obj)/start.o $(obj)/misc.o $(obj)/common.o
+COFFOBJS = $(obj)/coffcrt0.o $(COMMONOBJS) $(obj)/coffmain.o
+CHRPOBJS = $(obj)/crt0.o $(COMMONOBJS) $(obj)/chrpmain.o
+NEWWORLDOBJS = $(obj)/crt0.o $(COMMONOBJS) $(obj)/newworldmain.o
-EXTRA_TARGETS := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS)
-LIBS = $(TOPDIR)/lib/lib.a ../lib/lib.a ../of1275/of1275.a
+LIBS = lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
-ADDNOTE := ../utils/addnote
-MKNOTE := ../utils/mknote
-SIZE := ../utils/size
-OFFSET := ../utils/offset
-HACKCOFF := ../utils/hack-coff
+ADDNOTE := $(utils)/addnote
+MKNOTE := $(utils)/mknote
+SIZE := $(utils)/size
+OFFSET := $(utils)/offset
+HACKCOFF := $(utils)/hack-coff
ifdef CONFIG_SMP
END := .smp
@@ -38,12 +51,12 @@ endif
TFTPIMAGE=/tftpboot/zImage.
-../common/coffcrt0.o:
- $(MAKE) -C ../common coffcrt0.o
+$(obj)/dummy.o: $(common)/dummy.c
+ $(CC) -c -o $@ $(common)/dummy.c
-image.o: ../images/vmlinux.gz ../common/dummy.o
- $(OBJCOPY) ../common/dummy.o $@ -R .comment \
- --add-section=.image=../images/vmlinux.gz \
+$(obj)/image.o: $(images)/vmlinux.gz $(obj)/dummy.o
+ $(OBJCOPY) $(obj)/dummy.o $@ -R .comment \
+ --add-section=.image=$(images)/vmlinux.gz \
--set-section-flags=.image=contents,alloc,load,readonly,data
ifdef CONFIG_XMON
$(OBJCOPY) $@ $@ \
@@ -52,86 +65,93 @@ ifdef CONFIG_XMON
endif
# Place the ramdisk in the initrd image.
-image-initrd.o: image.o ../images/ramdisk.image.gz
- $(OBJCOPY) image.o $@ \
- --add-section=.ramdisk=../images/ramdisk.image.gz \
+$(obj)/image-initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz
+ $(OBJCOPY) $(obj)/image.o $@ \
+ --add-section=.ramdisk=$(images)/ramdisk.image.gz \
--set-section-flags=.ramdisk=contents,alloc,load,readonly,data
# Create the note section for New-World PowerMacs.
-note: $(MKNOTE)
- $(MKNOTE) > note
-
-znetboot: vmlinux.coff vmlinux.elf-pmac zImage
- cp ../images/vmlinux.coff $(TFTPIMAGE).pmac$(END)
- cp ../images/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END)elf
- cp ../images/zImage.chrp $(TFTPIMAGE).chrp$(END)
-
-znetboot.initrd: vmlinux.initrd.coff vmlinux.initrd.elf-pmac
- cp ../images/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
- cp ../images/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
- cp ../images/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
+$(obj)/note: $(MKNOTE)
+ $(MKNOTE) > $(obj)/note
+
+znetboot: $(images)/vmlinux.coff $(images)/vmlinux.elf-pmac $(images)/zImage.chrp
+ cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END)
+ cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END)elf
+ cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
+
+znetboot.initrd: $(images)/vmlinux.initrd.coff \
+ $(images)/vmlinux.initrd.elf-pmac \
+ $(images)/zImage.initrd.chrp
+ cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
+ cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+ cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
+
+$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz
+ $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=$(images)/vmlinux.gz \
+ $(obj)/dummy.o $@
+
+$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz
+ $(OBJCOPY) $(OBJCOPY_ARGS) \
+ --add-section=initrd=$(images)/ramdisk.image.gz \
+ $(images)/miboot.image $@
-miboot.image: ../common/dummy.o ../images/vmlinux.gz
- $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=../images/vmlinux.gz \
- ../common/dummy.o ../images/$@
+$(obj)/coffcrt0.o: $(common)/crt0.S
+ $(CC) $(AFLAGS) -DXCOFF -traditional -c -o $@ $(common)/crt0.S
-miboot.initrd.image: miboot.image ../images/ramdisk.image.gz
- $(OBJCOPY) $(OBJCOPY_ARGS) \
- --add-section=initrd=../images/ramdisk.image.gz \
- ../images/miboot.image ../images/$@
+$(obj)/crt0.o: $(common)/crt0.S
+ $(CC) $(AFLAGS) -traditional -c -o $@ $(common)/crt0.S
-coffboot: $(COFFOBJS) image.o $(LIBS)
+$(obj)/coffboot: $(COFFOBJS) $(obj)/image.o $(LIBS)
$(LD) -o $@ $(COFF_LD_ARGS) $^
$(OBJCOPY) $@ $@ -R .comment -R .ramdisk
-coffboot.initrd: $(COFFOBJS) image-initrd.o $(LIBS)
+$(obj)/coffboot.initrd: $(COFFOBJS) $(obj)/image-initrd.o $(LIBS)
$(LD) -o $@ $(COFF_LD_ARGS) $^
$(OBJCOPY) $@ $@ -R .comment
-vmlinux.coff: coffboot $(HACKCOFF)
- $(OBJCOPY) $(OBJCOPY_ARGS) coffboot ../images/$@
- $(HACKCOFF) ../images/$@
- rm -f coffboot
- ln -sf vmlinux.coff ../images/zImage.pmac
-
-vmlinux.initrd.coff: coffboot.initrd $(HACKCOFF)
- $(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd ../images/$@
- $(HACKCOFF) ../images/$@
- rm -f coffboot.initrd
- ln -sf vmlinux.initrd.coff ../images/zImage.initrd.pmac
-
-vmlinux.elf-pmac: $(NEWWORLDOBJS) $(LIBS) image.o
- $(LD) $(NEWWORLD_LD_ARGS) -o ../images/$@ $^
-
-vmlinux.initrd.elf-pmac: $(NEWWORLDOBJS) $(LIBS) image-initrd.o
- $(LD) $(NEWWORLD_LD_ARGS) -o ../images/$@ $^
-
-zImage.chrp: $(CHRPOBJS) image.o $(LIBS)
- $(LD) $(CHRP_LD_ARGS) -o ../images/$@ $^
-
-zImage.initrd.chrp: $(CHRPOBJS) image-initrd.o $(LIBS)
- $(LD) $(CHRP_LD_ARGS) -o ../images/$@ $^
-
-zImage: vmlinux.coff vmlinux.elf-pmac zImage.chrp miboot.image $(ADDNOTE) \
- note
- $(OBJCOPY) ../images/vmlinux.elf-pmac ../images/vmlinux.elf-pmac \
- --add-section=.note=note -R .comment -R .ramdisk
- $(OBJCOPY) ../images/zImage.chrp ../images/zImage.chrp \
- -R .comment -R .ramdisk
- cp ../images/zImage.chrp ../images/zImage.chrp-rs6k
- $(ADDNOTE) ../images/zImage.chrp-rs6k
-
-zImage.initrd: vmlinux.initrd.coff vmlinux.initrd.elf-pmac zImage.initrd.chrp \
- miboot.initrd.image $(ADDNOTE) note
- $(OBJCOPY) ../images/vmlinux.initrd.elf-pmac \
- ../images/vmlinux.initrd.elf-pmac --add-section=.note=note \
- -R .comment
- $(OBJCOPY) ../images/zImage.initrd.chrp ../images/zImage.initrd.chrp \
- -R .comment
- cp ../images/zImage.initrd.chrp ../images/zImage.initrd.chrp-rs6k
- $(ADDNOTE) ../images/zImage.initrd.chrp-rs6k
+$(images)/vmlinux.coff: $(obj)/coffboot
+ $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot $@
+ $(HACKCOFF) $@
+ ln -sf vmlinux.coff $(images)/zImage.pmac
-clean:
- rm -f note
+$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd
+ $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot.initrd $@
+ $(HACKCOFF) $@
+ ln -sf vmlinux.initrd.coff $(images)/zImage.initrd.pmac
-include $(TOPDIR)/Rules.make
+$(images)/vmlinux.elf-pmac: $(NEWWORLDOBJS) $(LIBS) $(obj)/image.o $(obj)/note
+ $(LD) $(NEWWORLD_LD_ARGS) -o $@ $(NEWWORLDOBJS) $(LIBS) $(obj)/image.o
+ $(OBJCOPY) $@ $@ \
+ --add-section=.note=$(obj)/note -R .comment -R .ramdisk
+
+$(images)/vmlinux.initrd.elf-pmac: $(NEWWORLDOBJS) $(LIBS) \
+ $(obj)/image-initrd.o $(obj)/note
+ $(LD) $(NEWWORLD_LD_ARGS) -o $@ $(NEWWORLDOBJS) $(LIBS) \
+ $(obj)/image-initrd.o
+ $(OBJCOPY) $@ $@ \
+ --add-section=.note=$(obj)/note -R .comment
+
+$(images)/zImage.chrp: $(CHRPOBJS) $(obj)/image.o $(LIBS)
+ $(LD) $(CHRP_LD_ARGS) -o $@ $^
+ $(OBJCOPY) $@ $@ -R .comment -R .ramdisk
+
+$(images)/zImage.initrd.chrp: $(CHRPOBJS) $(obj)/image-initrd.o $(LIBS)
+ $(LD) $(CHRP_LD_ARGS) -o $@ $^
+ $(OBJCOPY) $@ $@ -R .comment
+
+$(images)/zImage.chrp-rs6k: $(images)/zImage.chrp
+ cp $(images)/zImage.chrp $@
+ $(ADDNOTE) $@
+
+$(images)/zImage.initrd.chrp-rs6k: $(images)/zImage.initrd.chrp
+ cp $(images)/zImage.initrd.chrp $@
+ $(ADDNOTE) $@
+
+zImage: $(images)/vmlinux.coff $(images)/vmlinux.elf-pmac \
+ $(images)/zImage.chrp $(images)/miboot.image
+
+zImage.initrd: $(images)/vmlinux.initrd.coff $(images)/vmlinux.initrd.elf-pmac\
+ $(images)/zImage.initrd.chrp $(images)/miboot.initrd.image
+
+clean:
+ rm -f $(obj)/note $(obj)/image.o $(obj)/coffboot $(obj)/coffboot.initrd
diff --git a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile
index e3617f80113f..b472f2bce21d 100644
--- a/arch/ppc/boot/prep/Makefile
+++ b/arch/ppc/boot/prep/Makefile
@@ -13,65 +13,79 @@
# modified by Cort (cort@cs.nmt.edu)
#
+boot: zImage
+
TFTPIMAGE = /tftpboot/zImage.prep
ifeq ($(CONFIG_SMP),y)
TFTPIMAGE = $(TFTPBOOT).smp
endif
-LD_ARGS = -T ../ld.script -Ttext 0x00800000 -Bstatic
-boot-y := head.o ../simple/legacy.o misc.o \
- ../common/util.o ../common/string.o \
- ../common/misc-common.o \
- ../common/mpc10x_memory.o
+LD_ARGS = -T $(boot)/ld.script -Ttext 0x00800000 -Bstatic
OBJCOPY_ARGS = -O elf32-powerpc
-LIBS = ../lib/lib.a
+LIBS = $(common)/lib.a $(bootlib)/lib.a
-boot-$(CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o
+boot-y := head.o misc.o
boot-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
-EXTRA_TARGETS := $(boot-y)
+EXTRA_TARGETS := $(boot-y) ../simple/legacy.o
+
+include $(TOPDIR)/Rules.make
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+of1275 := $(boot)/of1275
+images := $(boot)/images
+simple := $(boot)/simple
+
+OBJS := $(addprefix $(obj)/,$(boot-y)) $(simple)/legacy.o
# Tools
-MKPREP := ../utils/mkprep
-SIZE := ../utils/size
-OFFSET := ../utils/offset
+MKPREP := $(utils)/mkprep
+SIZE := $(utils)/size
+OFFSET := $(utils)/offset
# Extra include search dirs
-CFLAGS_kbd.o += -I$(TOPDIR)/drivers/char
+CFLAGS_kbd.o += -Idrivers/char
-all: zImage
+zImage: $(images)/zImage.prep
+zImage.initrd: $(images)/zImage.initrd.prep
-zImage: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o \
- $(MKPREP)
+$(obj)/dummy.o: $(common)/dummy.c
+ $(CC) -c -o $@ $(common)/dummy.c
+
+$(images)/zImage.prep: $(OBJS) $(LIBS) $(boot)/ld.script \
+ $(images)/vmlinux.gz $(obj)/dummy.o
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=.image=../images/vmlinux.gz \
+ --add-section=.image=$(images)/vmlinux.gz \
--set-section-flags=.image=contents,alloc,load,readonly,data \
- ../common/dummy.o image.o
- $(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
- $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr
- $(MKPREP) -pbp $@ ../images/$@.prep
- rm -f $@
-
-zImage.initrd: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz $(MKPREP) \
- ../common/dummy.o
+ $(obj)/dummy.o $(obj)/image.o
+ $(LD) $(LD_ARGS) -o $(obj)/zImage $(OBJS) $(obj)/image.o $(LIBS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/zImage $(obj)/zImage \
+ -R .comment -R .stab -R .stabstr
+ $(MKPREP) -pbp $(obj)/zImage $@
+ rm -f $(obj)/zImage
+
+$(images)/zImage.initrd.prep: $(OBJS) $(LIBS) $(boot)/ld.script \
+ $(images)/vmlinux.gz $(obj)/dummy.o
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=.ramdisk=../images/ramdisk.image.gz \
+ --add-section=.ramdisk=$(images)/ramdisk.image.gz \
--set-section-flags=.ramdisk=contents,alloc,load,readonly,data \
- --add-section=.image=../images/vmlinux.gz \
+ --add-section=.image=$(images)/vmlinux.gz \
--set-section-flags=.image=contents,alloc,load,readonly,data \
- ../common/dummy.o image.o
- $(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
- $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr
- $(MKPREP) -pbp $@ ../images/$@.prep
- rm -f $@
+ $(obj)/dummy.o $(obj)/image.o
+ $(LD) $(LD_ARGS) -o $(obj)/zImage.initrd $(OBJS) $(obj)/image.o $(LIBS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/zImage.initrd $(obj)/zImage.initrd \
+ -R .comment -R .stab -R .stabstr
+ $(MKPREP) -pbp $(obj)/zImage.initrd $@
+ rm -f $(obj)/zImage.initrd
floppy: zImage
- dd if=../images/zImage.prep of=/dev/fd0H1440 bs=64b
+ dd if=$(images)/zImage.prep of=/dev/fd0H1440 bs=64b
znetboot : zImage
- cp ../images/zImage.prep $(TFTPIMAGE)
+ cp $(images)/zImage.prep $(TFTPIMAGE)
znetboot.initrd : zImage.initrd
- cp ../images/zImage.initrd.prep $(TFTPIMAGE)
-
-include $(TOPDIR)/Rules.make
+ cp $(images)/zImage.initrd.prep $(TFTPIMAGE)
diff --git a/arch/ppc/boot/prep/misc.c b/arch/ppc/boot/prep/misc.c
index c92348aa6572..7f6680036cea 100644
--- a/arch/ppc/boot/prep/misc.c
+++ b/arch/ppc/boot/prep/misc.c
@@ -132,11 +132,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
vga_init((unsigned char *)0xC0000000);
#endif /* CONFIG_VGA_CONSOLE */
- /*
- * Find out how much memory we have.
- */
- TotalMemory = get_mem_size();
-
/*
* Tell the user where we were loaded at and where we were relocated
* to for debugging this process.
@@ -215,6 +210,29 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
puts("No residual data found.\n");
}
+ /* First, figure out what kind of host bridge we are on. If it's
+ * an MPC10x, we can ask it directly how much memory it has.
+ * Otherwise, see if the residual data has anything. This isn't
+ * the best way, but it can be the only way. If there's nothing,
+ * assume 32MB. -- Tom.
+ */
+ /* See what our host bridge is. */
+ pci_read_config_32(0x00, 0x00, &pci_viddid);
+ pci_did = (pci_viddid & 0xffff0000) >> 16;
+ /* See if we are on an MPC10x. */
+ if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
+ && ((pci_did == PCI_DEVICE_ID_MOTOROLA_MPC105)
+ || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC106)
+ || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC107)))
+ TotalMemory = get_mem_size();
+ /* If it's not, see if we have anything in the residual data. */
+ else if (residual && residual->TotalMemory)
+ TotalMemory = residual->TotalMemory;
+ /* Fall back to hard-coding 32MB. */
+ else
+ TotalMemory = 32*1024*1024;
+
+
/* assume the chunk below 8M is free */
end_avail = (char *)0x00800000;
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index a659b52cfb16..947d507774d9 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -24,9 +24,11 @@
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
-# Normally, we use the 'misc-simple.c' file for decompress_kernel and
+boot: zImage
+
+# Normally, we use the 'misc.c' file for decompress_kernel and
# whatnot. Sometimes we need to override this however.
-MISC := ../common/misc-simple.o
+MISC := misc.o
ifeq ($(CONFIG_IBM_OPENBIOS),y)
ZIMAGE := zImage-TREE
ZIMAGEINITRD := zImage.initrd-TREE
@@ -38,6 +40,14 @@ ifeq ($(CONFIG_EMBEDDEDBOOT),y)
TFTPIMAGE := /tftpboot/zImage.embedded
MISC := misc-embedded.o
endif
+ifeq ($(CONFIG_EBONY),y)
+ZIMAGE := zImage-TREE
+ZIMAGEINITRD := zImage.initrd-TREE
+EXTRA := direct.o
+END := ebony
+ENTRYPOINT := 0x01000000
+TFTPIMAGE := /tftpboot/zImage.$(END)
+endif
ifeq ($(CONFIG_EV64260),y)
EXTRA := direct.o misc-ev64260.o
TFTPIMAGE := /tftpboot/zImage.ev64260
@@ -72,11 +82,8 @@ endif
ifeq ($(CONFIG_PPLUS),y)
EXTRA := legacy.o
endif
-ifeq ($(CONFIG_LOPEC),y)
-EXTRA += ../common/mpc10x_memory.o
-endif
ifeq ($(CONFIG_PAL4),y)
-EXTRA := direct.o ../common/cpc700_memory.o
+EXTRA := direct.o
endif
ifeq ($(CONFIG_PCORE)$(CONFIG_POWERPMC250),y)
ZIMAGE := zImage-STRIPELF
@@ -122,21 +129,25 @@ endif
# Default linker args. Link at 0x00800000 or 0x00400000 by default, but
# allow it to be overridden.
ifeq ($(CONFIG_BOOT_LOAD_BOOL),y)
-LD_ARGS := -T ../ld.script -Ttext $(CONFIG_BOOT_LOAD) \
- -Bstatic
+LD_ARGS := -T $(boot)/ld.script \
+ -Ttext $(CONFIG_BOOT_LOAD) -Bstatic
else
-LD_ARGS = -T ../ld.script -Ttext 0x00800000 -Bstatic
-ifeq ($(CONFIG_8260)$(CONFIG_4xx)$(CONFIG_8xx),y)
-LD_ARGS := -T ../ld.script -Ttext 0x00400000 -Bstatic
+LD_ARGS = -T $(boot)/ld.script \
+ -Ttext 0x00800000 -Bstatic
+ifeq ($(CONFIG_8260)$(CONFIG_40x)$(CONFIG_8xx),y)
+LD_ARGS := -T $(boot)/ld.script -Ttext 0x00400000 \
+ -Bstatic
+endif
+ifeq ($(CONFIG_440),y)
+LD_ARGS := -T $(boot)/ld.script -Ttext 0x01000000 \
+ -Bstatic
endif
endif
OBJCOPY_ARGS := -O elf32-powerpc
-# head.o and ../common/relocate.o must be at the start.
-boot-y := head.o ../common/relocate.o $(EXTRA) \
- $(MISC) ../common/misc-common.o \
- ../common/string.o ../common/util.o
-boot-$(CONFIG_4xx) += embed_config.o
+# head.o and relocate.o must be at the start.
+boot-y := head.o relocate.o $(EXTRA) $(MISC)
+boot-$(CONFIG_40x) += embed_config.o
boot-$(CONFIG_8xx) += embed_config.o
boot-$(CONFIG_8260) += embed_config.o
boot-$(CONFIG_BSEIP) += iic.o
@@ -149,84 +160,97 @@ boot-$(CONFIG_8xx) += m8xx_tty.o
boot-$(CONFIG_8260) += m8260_tty.o
boot-$(CONFIG_GT64260_CONSOLE) += gt64260_tty.o
endif
-boot-$(CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+images := $(boot)/images
EXTRA_TARGETS := $(boot-y)
-LIBS := ../lib/lib.a
+LIBS := $(common)/lib.a $(bootlib)/lib.a
+
+include $(TOPDIR)/Rules.make
+
+OBJS := $(addprefix $(obj)/,$(boot-y))
# Tools
-MKBUGBOOT := ../utils/mkbugboot
-MKPREP := ../utils/mkprep
-MKTREE := ../utils/mktree
+MKBUGBOOT := $(utils)/mkbugboot
+MKPREP := $(utils)/mkprep
+MKTREE := $(utils)/mktree
+
+$(obj)/dummy.o: $(common)/dummy.c
+ $(CC) -c -o $@ $(common)/dummy.c
-zvmlinux: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o
+$(obj)/zvmlinux: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \
+ $(obj)/dummy.o
$(OBJCOPY) $(OBJCOPY_ARGS) \
- --add-section=.image=../images/vmlinux.gz \
+ --add-section=.image=$(images)/vmlinux.gz \
--set-section-flags=.image=contents,alloc,load,readonly,data \
- ../common/dummy.o image.o
- $(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
- $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \
- -R .ramdisk -R .sysmap
+ $(obj)/dummy.o $(obj)/image.o
+ $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
+ -R .stabstr -R .ramdisk -R .sysmap
-zvmlinux.initrd: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz \
- ../common/dummy.o
+$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(boot)/ld.script \
+ $(images)/vmlinux.gz $(obj)/dummy.o
$(OBJCOPY) $(OBJCOPY_ARGS) \
- --add-section=.ramdisk=../images/ramdisk.image.gz \
+ --add-section=.ramdisk=$(images)/ramdisk.image.gz \
--set-section-flags=.ramdisk=contents,alloc,load,readonly,data \
- --add-section=.image=../images/vmlinux.gz \
+ --add-section=.image=$(images)/vmlinux.gz \
--set-section-flags=.image=contents,alloc,load,readonly,data \
- ../common/dummy.o image.o
- $(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
- $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \
- -R .sysmap
+ $(obj)/dummy.o $(obj)/image.o
+ $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
+ -R .stabstr -R .sysmap
# Sort-of dummy rules, that let us format the image we want.
-zImage: $(ZIMAGE) zvmlinux
- cp -f zvmlinux ../images/zImage.elf
- rm -f zvmlinux
+zImage: $(images)/$(ZIMAGE) $(obj)/zvmlinux
+ cp -f $(obj)/zvmlinux $(images)/zImage.elf
+ rm -f $(obj)/zvmlinux
-zImage.initrd: $(ZIMAGEINITRD) zvmlinux.initrd
- cp -f zvmlinux.initrd ../images/zImage.initrd.elf
- rm -f zvmlinux.initrd
+zImage.initrd: $(images)/$(ZIMAGEINITRD) $(obj)/zvmlinux.initrd
+ cp -f $(obj)/zvmlinux.initrd $(images)/zImage.initrd.elf
+ rm -f $(obj)/zvmlinux.initrd
znetboot: zImage
ifneq ($(ZNETBOOT),)
- cp ../images/$(ZNETBOOT) $(TFTPIMAGE)
+ cp $(images)/$(ZNETBOOT) $(TFTPIMAGE)
else
- cp ../images/zImage.* $(TFTPIMAGE)
+ cp $(images)/zImage.* $(TFTPIMAGE)
endif
znetboot.initrd: zImage.initrd
ifneq ($(ZNETBOOTRD),)
- cp ../images/$(ZNETBOOTRD) $(TFTPIMAGE)
+ cp $(images)/$(ZNETBOOTRD) $(TFTPIMAGE)
else
- cp ../images/zImage.* $(TFTPIMAGE)
+ cp $(images)/zImage.* $(TFTPIMAGE)
endif
-zImage-STRIPELF: zvmlinux
- dd if=zvmlinux of=../images/zImage.$(END) skip=64 bs=1k
+$(images)/zImage-STRIPELF: $(obj)/zvmlinux
+ dd if=$(obj)/zvmlinux of=$(images)/zImage.$(END) skip=64 bs=1k
-zImage.initrd-STRIPELF: zvmlinux.initrd
- dd if=zvmlinux.initrd of=../images/zImage.initrd.$(END) skip=64 bs=1k
+$(images)/zImage.initrd-STRIPELF: $(obj)/zvmlinux.initrd
+ dd if=$(obj)/zvmlinux.initrd of=$(images)/zImage.initrd.$(END) \
+ skip=64 bs=1k
-zImage-TREE: zvmlinux
- $(MKTREE) zvmlinux ../images/zImage.$(END) $(ENTRYPOINT)
+$(images)/zImage-TREE: $(obj)/zvmlinux
+ $(MKTREE) $(obj)/zvmlinux $(images)/zImage.$(END) $(ENTRYPOINT)
-zImage.initrd-TREE: zvmlinux.initrd
- $(MKTREE) zvmlinux.initrd ../images/zImage.initrd.$(END) $(ENTRYPOINT)
+$(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd
+ $(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(END) \
+ $(ENTRYPOINT)
-zImage-MENF1: zvmlinux
- $(MKPREP) -pbp zvmlinux ../images/zImage.menf1
+$(images)/zImage-MENF1: $(obj)/zvmlinux
+ $(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.menf1
-zImage.initrd-MENF1: zvmlinux.initrd
- $(MKPREP) -pbp zvmlinux.initrd ../images/zImage.initrd.menf1
+$(images)/zImage.initrd-MENF1: $(obj)/zvmlinux.initrd
+ $(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.menf1
-zImage-PPLUS: zvmlinux $(MKPREP) $(MKBUGBOOT)
- $(MKPREP) -pbp zvmlinux ../images/zImage.pplus
- $(MKBUGBOOT) zvmlinux ../images/zImage.bugboot
+$(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT)
+ $(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.pplus
+ $(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot
-zImage.initrd-PPLUS: zvmlinux.initrd $(MKPREP) $(MKBUGBOOT)
- $(MKPREP) -pbp zvmlinux.initrd ../images/zImage.initrd.pplus
- $(MKBUGBOOT) zvmlinux.initrd ../images/zImage.initrd.bugboot
-
-include $(TOPDIR)/Rules.make
+$(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(MKPREP) $(MKBUGBOOT)
+ $(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.pplus
+ $(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot
diff --git a/arch/ppc/boot/common/misc-simple.c b/arch/ppc/boot/simple/misc.c
index 74693dc19a0a..74693dc19a0a 100644
--- a/arch/ppc/boot/common/misc-simple.c
+++ b/arch/ppc/boot/simple/misc.c
diff --git a/arch/ppc/boot/common/relocate.S b/arch/ppc/boot/simple/relocate.S
index 9c49a9c09f80..9c49a9c09f80 100644
--- a/arch/ppc/boot/common/relocate.S
+++ b/arch/ppc/boot/simple/relocate.S
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 84f098ad2753..88f8dff3cd99 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -131,6 +131,7 @@ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
Motorola-Sandpoint CONFIG_SANDPOINT \
SBS-Adirondack CONFIG_ADIR \
SBS-K2 CONFIG_K2 \
+ SBS-Palomar4 CONFIG_PAL4 \
Synergy-Gemini CONFIG_GEMINI \
Zynx-ZX4500 CONFIG_ZX4500" CHRP/PowerMac/PReP
@@ -584,23 +585,31 @@ source lib/Config.in
mainmenu_option next_comment
comment 'Kernel hacking'
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-bool 'Spinlock debugging' CONFIG_DEBUG_SPINLOCK
-bool 'Include kgdb kernel debugger' CONFIG_KGDB
-if [ "$CONFIG_KGDB" = "y" ]; then
- choice 'Serial Port' \
- "ttyS0 CONFIG_KGDB_TTYS0 \
- ttyS1 CONFIG_KGDB_TTYS1 \
- ttyS2 CONFIG_KGDB_TTYS2 \
- ttyS3 CONFIG_KGDB_TTYS3" ttyS1
-fi
-bool 'Include xmon kernel debugger' CONFIG_XMON
-bool 'Include BDI-2000 user context switcher' CONFIG_BDI_SWITCH
-if [ "$CONFIG_KGDB" = "y" -o "$CONFIG_XMON" = "y" \
- -o "$CONFIG_BDI_SWITCH" = "y" ]; then
- bool 'Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
- if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
- string 'Additional compile arguments' CONFIG_COMPILE_OPTIONS "-g -ggdb"
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_DEBUG_KERNEL" = "y" ]; then
+ bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
+ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
+ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+ if [ "$CONFIG_HIGHMEM" = "y" ]; then
+ bool ' Highmem debugging' CONFIG_DEBUG_HIGHMEM
+ fi
+ bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
+ bool ' Include kgdb kernel debugger' CONFIG_KGDB
+ if [ "$CONFIG_KGDB" = "y" ]; then
+ choice ' Serial Port' \
+ "ttyS0 CONFIG_KGDB_TTYS0 \
+ ttyS1 CONFIG_KGDB_TTYS1 \
+ ttyS2 CONFIG_KGDB_TTYS2 \
+ ttyS3 CONFIG_KGDB_TTYS3" ttyS1
+ fi
+ bool ' Include xmon kernel debugger' CONFIG_XMON
+ bool ' Include BDI-2000 user context switcher' CONFIG_BDI_SWITCH
+ if [ "$CONFIG_KGDB" = "y" -o "$CONFIG_XMON" = "y" \
+ -o "$CONFIG_BDI_SWITCH" = "y" ]; then
+ bool ' Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
+ if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
+ string ' Additional compile arguments' CONFIG_COMPILE_OPTIONS "-g -ggdb"
+ fi
fi
fi
diff --git a/arch/ppc/kernel/indirect_pci.c b/arch/ppc/kernel/indirect_pci.c
index e5db04a84a68..a012f65b3a4e 100644
--- a/arch/ppc/kernel/indirect_pci.c
+++ b/arch/ppc/kernel/indirect_pci.c
@@ -27,13 +27,18 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
{
struct pci_controller *hose = bus->sysdata;
volatile unsigned char *cfg_data;
+ u8 cfg_type = 0;
if (ppc_md.pci_exclude_device)
if (ppc_md.pci_exclude_device(bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (bus->number != hose->first_busno)
+ cfg_type = 1;
out_be32(hose->cfg_addr,
- ((offset & 0xfc) << 24) | (devfn << 16)
+ (((offset & 0xfc) | cfg_type) << 24) | (devfn << 16)
| ((bus->number - hose->bus_offset) << 8) | 0x80);
/*
* Note: the caller has already checked that offset is
@@ -60,13 +65,18 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
{
struct pci_controller *hose = bus->sysdata;
volatile unsigned char *cfg_data;
+ u8 cfg_type = 0;
if (ppc_md.pci_exclude_device)
if (ppc_md.pci_exclude_device(bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
+ if (hose->set_cfg_type)
+ if (bus->number != hose->first_busno)
+ cfg_type = 1;
+
out_be32(hose->cfg_addr,
- ((offset & 0xfc) << 24) | (devfn << 16)
+ (((offset & 0xfc) | cfg_type) << 24) | (devfn << 16)
| ((bus->number - hose->bus_offset) << 8) | 0x80);
/*
* Note: the caller has already checked that offset is
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index edd62a0bcaf9..c25bc5824e58 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -752,21 +752,6 @@ _GLOBAL(copy_page)
#endif /* CONFIG_PPC_ISERIES */
/*
- * Atomic [test&set] exchange
- *
- * unsigned long xchg_u32(void *ptr, unsigned long val)
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
-_GLOBAL(xchg_u32)
- mr r5,r3 /* Save pointer */
-10: lwarx r3,0,r5 /* Fetch old value & reserve */
- PPC405_ERR77(0,r5)
- stwcx. r4,0,r5 /* Update with new value */
- bne- 10b /* Retry if "reservation" (i.e. lock) lost */
- blr
-
-/*
* void atomic_clear_mask(atomic_t mask, atomic_t *addr)
* void atomic_set_mask(atomic_t mask, atomic_t *addr);
*/
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 78cacd63f7cf..ef796b2915f6 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -30,6 +30,8 @@
#include <linux/pmu.h>
#include <asm/prom.h>
#include <asm/system.h>
+#define __KERNEL_SYSCALLS__
+#include <asm/unistd.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
#include <asm/pmac_feature.h>
@@ -180,6 +182,10 @@ EXPORT_SYMBOL(consistent_free);
EXPORT_SYMBOL(consistent_sync);
#endif
+EXPORT_SYMBOL(open);
+EXPORT_SYMBOL(read);
+EXPORT_SYMBOL(lseek);
+EXPORT_SYMBOL(close);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
@@ -191,7 +197,6 @@ EXPORT_SYMBOL(flush_dcache_range);
EXPORT_SYMBOL(flush_icache_user_range);
EXPORT_SYMBOL(flush_icache_page);
EXPORT_SYMBOL(flush_dcache_page);
-EXPORT_SYMBOL(xchg_u32);
#ifdef CONFIG_ALTIVEC
EXPORT_SYMBOL(last_task_used_altivec);
EXPORT_SYMBOL(giveup_altivec);
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index 6019aa16e6d4..1567db763078 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -4,7 +4,7 @@
export-objs := dec_and_lock.o
-obj-y := checksum.o string.o strcase.o dec_and_lock.o
+obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o
obj-$(CONFIG_SMP) += locks.o
diff --git a/arch/ppc/lib/div64.S b/arch/ppc/lib/div64.S
new file mode 100644
index 000000000000..3527569e9926
--- /dev/null
+++ b/arch/ppc/lib/div64.S
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+_GLOBAL(__div64_32)
+ lwz r5,0(r3) # get the dividend into r5/r6
+ lwz r6,4(r3)
+ cmplw r5,r4
+ li r7,0
+ li r8,0
+ blt 1f
+ divwu r7,r5,r4 # if dividend.hi >= divisor,
+ mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
+ subf. r5,r0,r5 # dividend.hi %= divisor
+ beq 3f
+1: mr r11,r5 # here dividend.hi != 0
+ andis. r0,r5,0xc000
+ bne 2f
+ cntlzw r0,r5 # we are shifting the dividend right
+ li r10,-1 # to make it < 2^32, and shifting
+ srw r10,r10,r0 # the divisor right the same amount,
+ add r9,r4,r10 # rounding up (so the estimate cannot
+ andc r11,r6,r10 # ever be too large, only too small)
+ andc r9,r9,r10
+ or r11,r5,r11
+ rotlw r9,r9,r0
+ rotlw r11,r11,r0
+ divwu r11,r11,r9 # then we divide the shifted quantities
+2: mullw r10,r11,r4 # to get an estimate of the quotient,
+ mulhwu r9,r11,r4 # multiply the estimate by the divisor,
+ subfc r6,r10,r6 # take the product from the divisor,
+ add r8,r8,r11 # and add the estimate to the accumulated
+ subfe. r5,r9,r5 # quotient
+ bne 1b
+3: cmplw r6,r4
+ blt 4f
+ divwu r0,r6,r4 # perform the remaining 32-bit division
+ mullw r10,r0,r4 # and get the remainder
+ add r8,r8,r0
+ subf r6,r10,r6
+4: stw r7,0(r3) # return the quotient in *r3
+ stw r8,4(r3)
+ mr r3,r6 # return the remainder in r3
+ blr
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 2c2f72c81774..b90f75b8b0ab 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_LOPEC) += lopec_setup.o lopec_pci.o
obj-$(CONFIG_MCPN765) += mcpn765_setup.o mcpn765_pci.o
obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o
obj-$(CONFIG_MVME5100) += mvme5100_setup.o mvme5100_pci.o
+obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o cpc700_pic.o
obj-$(CONFIG_PCORE) += pcore_setup.o pcore_pci.o
obj-$(CONFIG_POWERPMC250) += powerpmc250.o
obj-$(CONFIG_PPLUS) += pplus_pci.o pplus_setup.o
diff --git a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h
new file mode 100644
index 000000000000..ab111ff83ad6
--- /dev/null
+++ b/arch/ppc/platforms/pal4.h
@@ -0,0 +1,44 @@
+/*
+ * arch/ppc/platforms/pal4.h
+ *
+ * Definitions for SBS Palomar IV board
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_PLATFORMS_PAL4_H
+#define __PPC_PLATFORMS_PAL4_H
+
+#define PAL4_NVRAM 0xfffc0000
+#define PAL4_NVRAM_SIZE 0x8000
+
+#define PAL4_DRAM 0xfff80000
+#define PAL4_DRAM_BR_MASK 0xc0
+#define PAL4_DRAM_BR_SHIFT 6
+#define PAL4_DRAM_RESET 0x10
+#define PAL4_DRAM_EREADY 0x40
+
+#define PAL4_MISC 0xfff80004
+#define PAL4_MISC_FB_MASK 0xc0
+#define PAL4_MISC_FLASH 0x20 /* StratFlash mapping: 1->0xff80, 0->0xfff0 */
+#define PAL4_MISC_MISC 0x08
+#define PAL4_MISC_BITF 0x02
+#define PAL4_MISC_NVKS 0x01
+
+#define PAL4_L2 0xfff80008
+#define PAL4_L2_MASK 0x07
+
+#define PAL4_PLDR 0xfff8000c
+
+/* Only two Ethernet devices on the board... */
+#define PAL4_ETH 31
+#define PAL4_INTA 20
+
+#endif /* __PPC_PLATFORMS_PAL4_H */
diff --git a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c
new file mode 100644
index 000000000000..372e846f3e54
--- /dev/null
+++ b/arch/ppc/platforms/pal4_pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/ppc/platforms/pal4_pci.c
+ *
+ * PCI support for SBS Palomar IV
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/uaccess.h>
+
+#include "cpc700.h"
+#include "pal4.h"
+
+/* not much to this.... */
+static inline int __init
+pal4_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ if (idsel == 9)
+ return PAL4_ETH;
+ else
+ return PAL4_INTA + (idsel - 3);
+}
+
+void __init
+pal4_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->pci_mem_offset = 0;
+
+ /* Could snatch these from the CPC700.... */
+ pci_init_resource(&hose->io_resource,
+ 0x0,
+ 0x03ffffff,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ 0x90000000,
+ 0x9fffffff,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = 0x00800000;
+ hose->io_space.end = 0x03ffffff;
+ hose->mem_space.start = 0x90000000;
+ hose->mem_space.end = 0x9fffffff;
+ hose->io_base_virt = (void *) 0xf8000000;
+
+ setup_indirect_pci(hose, CPC700_PCI_CONFIG_ADDR,
+ CPC700_PCI_CONFIG_DATA);
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = pal4_map_irq;
+}
diff --git a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h
new file mode 100644
index 000000000000..452486c3d226
--- /dev/null
+++ b/arch/ppc/platforms/pal4_serial.h
@@ -0,0 +1,41 @@
+/*
+ * arch/ppc/platforms/pal4_serial.h
+ *
+ * Definitions for SBS PalomarIV serial support
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_PAL4_SERIAL_H
+#define __PPC_PAL4_SERIAL_H
+
+#define CPC700_SERIAL_1 0xff600300
+#define CPC700_SERIAL_2 0xff600400
+
+#define RS_TABLE_SIZE 2
+#define BASE_BAUD (33333333 / 4 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define SERIAL_PORT_DFNS \
+ {0, BASE_BAUD, CPC700_SERIAL_1, 3, STD_COM_FLAGS, \
+ iomem_base: (unsigned char *) CPC700_SERIAL_1, \
+ io_type: SERIAL_IO_MEM}, /* ttyS0 */ \
+ {0, BASE_BAUD, CPC700_SERIAL_2, 4, STD_COM_FLAGS, \
+ iomem_base: (unsigned char *) CPC700_SERIAL_2, \
+ io_type: SERIAL_IO_MEM}
+
+#endif
diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c
new file mode 100644
index 000000000000..f4ad2252da2f
--- /dev/null
+++ b/arch/ppc/platforms/pal4_setup.c
@@ -0,0 +1,176 @@
+/*
+ * arch/ppc/platforms/pal4_setup.c
+ *
+ * Board setup routines for the SBS PalomarIV.
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+#include <linux/kdev_t.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include "cpc700.h"
+#include "pal4.h"
+
+extern void pal4_find_bridges(void);
+
+unsigned int cpc700_irq_assigns[][2] = {
+ {1, 1}, /* IRQ 0: ECC correctable error */
+ {1, 1}, /* IRQ 1: PCI write to memory range */
+ {0, 1}, /* IRQ 2: PCI write to command register */
+ {0, 1}, /* IRQ 3: UART 0 */
+ {0, 1}, /* IRQ 4: UART 1 */
+ {0, 1}, /* IRQ 5: ICC 0 */
+ {0, 1}, /* IRQ 6: ICC 1 */
+ {0, 1}, /* IRQ 7: GPT compare 0 */
+ {0, 1}, /* IRQ 8: GPT compare 1 */
+ {0, 1}, /* IRQ 9: GPT compare 2 */
+ {0, 1}, /* IRQ 10: GPT compare 3 */
+ {0, 1}, /* IRQ 11: GPT compare 4 */
+ {0, 1}, /* IRQ 12: GPT capture 0 */
+ {0, 1}, /* IRQ 13: GPT capture 1 */
+ {0, 1}, /* IRQ 14: GPT capture 2 */
+ {0, 1}, /* IRQ 15: GPT capture 3 */
+ {0, 1}, /* IRQ 16: GPT capture 4 */
+ {0, 0}, /* IRQ 17: reserved */
+ {0, 0}, /* IRQ 18: reserved */
+ {0, 0}, /* IRQ 19: reserved */
+ {0, 0}, /* IRQ 20: reserved */
+ {0, 1}, /* IRQ 21: Ethernet */
+ {0, 0}, /* IRQ 22: reserved */
+ {0, 0}, /* IRQ 23: reserved */
+ {0, 0}, /* IRQ 24: resreved */
+ {0, 0}, /* IRQ 25: reserved */
+ {0, 0}, /* IRQ 26: reserved */
+ {0, 0}, /* IRQ 27: reserved */
+ {0, 0}, /* IRQ 28: reserved */
+ {0, 0}, /* IRQ 29: reserved */
+ {0, 0}, /* IRQ 30: reserved */
+ {0, 0}, /* IRQ 31: reserved */
+};
+
+static int
+pal4_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "board\t\t: SBS Palomar IV\n");
+
+ return 0;
+}
+
+static void
+pal4_restart(char *cmd)
+{
+ __cli();
+ __asm__ __volatile__("lis 3,0xfff0\n \
+ ori 3,3,0x100\n \
+ mtspr 26,3\n \
+ li 3,0\n \
+ mtspr 27,3\n \
+ rfi");
+
+ for(;;);
+}
+
+static void
+pal4_power_off(void)
+{
+ __cli();
+ for(;;);
+}
+
+static void
+pal4_halt(void)
+{
+ pal4_power_off();
+}
+
+TODC_ALLOC();
+
+static void __init
+pal4_setup_arch(void)
+{
+ unsigned long l2;
+
+ TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+ ioremap(PAL4_NVRAM, PAL4_NVRAM_SIZE), 8);
+
+ pal4_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+ ROOT_DEV = Root_NFS;
+
+ /* The L2 gets disabled in the bootloader, but all the proper
+ bits should be present from the fw, so just re-enable it */
+ l2 = _get_L2CR();
+ if (!(l2 & L2CR_L2E)) {
+ /* presume that it was initially set if the size is
+ still present. */
+ if (l2 ^ L2CR_L2SIZ_MASK)
+ _set_L2CR(l2 | L2CR_L2E);
+ else
+ printk("L2 not set by firmware; left disabled.\n");
+ }
+}
+
+static void __init
+pal4_map_io(void)
+{
+ io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ isa_io_base = 0 /*PAL4_ISA_IO_BASE*/;
+ pci_dram_offset = 0 /*PAL4_PCI_SYS_MEM_BASE*/;
+
+ ppc_md.setup_arch = pal4_setup_arch;
+ ppc_md.show_cpuinfo = pal4_show_cpuinfo;
+
+ ppc_md.setup_io_mappings = pal4_map_io;
+
+ ppc_md.init_IRQ = cpc700_init_IRQ;
+ ppc_md.get_irq = cpc700_get_irq;
+
+ ppc_md.restart = pal4_restart;
+ ppc_md.halt = pal4_halt;
+ ppc_md.power_off = pal4_power_off;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+}
+
diff --git a/arch/ppc/platforms/pcore_setup.c b/arch/ppc/platforms/pcore_setup.c
index 14a01e866b07..06dcf811447e 100644
--- a/arch/ppc/platforms/pcore_setup.c
+++ b/arch/ppc/platforms/pcore_setup.c
@@ -168,13 +168,7 @@ pcore_init_IRQ(void)
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init(NULL);
-}
-
-static int
-pcore_get_irq(struct pt_regs *regs)
-{
- return i8259_poll();
+ i8259_init(0);
}
/*
@@ -184,22 +178,16 @@ static __inline__ void
pcore_set_bat(void)
{
unsigned long bat3u, bat3l;
- static int mapping_set = 0;
-
- if (!mapping_set) {
- __asm__ __volatile__(
- " lis %0,0xf000\n \
- ori %1,%0,0x002a\n \
- ori %0,%0,0x1ffe\n \
- mtspr 0x21e,%0\n \
- mtspr 0x21f,%1\n \
- isync\n \
- sync "
- : "=r" (bat3u), "=r" (bat3l));
-
- mapping_set = 1;
- }
- return;
+
+ __asm__ __volatile__(
+ " lis %0,0xf000\n \
+ ori %1,%0,0x002a\n \
+ ori %0,%0,0x1ffe\n \
+ mtspr 0x21e,%0\n \
+ mtspr 0x21f,%1\n \
+ isync\n \
+ sync "
+ : "=r" (bat3u), "=r" (bat3l));
}
static unsigned long __init
@@ -233,7 +221,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_arch = pcore_setup_arch;
ppc_md.show_cpuinfo = pcore_show_cpuinfo;
ppc_md.init_IRQ = pcore_init_IRQ;
- ppc_md.get_irq = pcore_get_irq;
+ ppc_md.get_irq = i8259_irq;
ppc_md.find_end_of_memory = pcore_find_end_of_memory;
ppc_md.setup_io_mappings = pcore_map_io;
diff --git a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
index cc8b249ddd13..a934f99f3274 100644
--- a/arch/ppc/vmlinux.lds.S
+++ b/arch/ppc/vmlinux.lds.S
@@ -87,9 +87,9 @@ SECTIONS
. = ALIGN(4096);
__init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : {
- *(.data.init);
+ .init.text : { *(.init.text) }
+ .init.data : {
+ *(.init.data);
__vtop_table_begin = .;
*(.vtop_fixup);
__vtop_table_end = .;
@@ -99,7 +99,7 @@ SECTIONS
}
. = ALIGN(16);
__setup_start = .;
- .setup.init : { *(.setup.init) }
+ .init.setup : { *(.init.setup) }
__setup_end = .;
__initcall_start = .;
.initcall.init : {
@@ -121,29 +121,29 @@ SECTIONS
. = ALIGN(4096);
__pmac_begin = .;
- .text.pmac : { *(.text.pmac) }
- .data.pmac : { *(.data.pmac) }
+ .pmac.text : { *(.pmac.text) }
+ .pmac.data : { *(.pmac.data) }
. = ALIGN(4096);
__pmac_end = .;
. = ALIGN(4096);
__prep_begin = .;
- .text.prep : { *(.text.prep) }
- .data.prep : { *(.data.prep) }
+ .prep.text : { *(.prep.text) }
+ .prep.data : { *(.prep.data) }
. = ALIGN(4096);
__prep_end = .;
. = ALIGN(4096);
__chrp_begin = .;
- .text.chrp : { *(.text.chrp) }
- .data.chrp : { *(.data.chrp) }
+ .chrp.text : { *(.chrp.text) }
+ .chrp.data : { *(.chrp.data) }
. = ALIGN(4096);
__chrp_end = .;
. = ALIGN(4096);
__openfirmware_begin = .;
- .text.openfirmware : { *(.text.openfirmware) }
- .data.openfirmware : { *(.data.openfirmware) }
+ .openfirmware.text : { *(.openfirmware.text) }
+ .openfirmware.data : { *(.openfirmware.data) }
. = ALIGN(4096);
__openfirmware_end = .;
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 4da5a00d54d3..045ddbe964f0 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -333,12 +333,15 @@ static void *do_smb_super_data_conv(void *raw_data)
struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+ if (s32->version != SMB_MOUNT_OLDVERSION)
+ goto out;
s->version = s32->version;
s->mounted_uid = s32->mounted_uid;
s->uid = s32->uid;
s->gid = s32->gid;
s->file_mode = s32->file_mode;
s->dir_mode = s32->dir_mode;
+out:
return raw_data;
}
diff --git a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
index 4d52a49cccf8..8490920b29b3 100644
--- a/arch/s390x/kernel/linux32.c
+++ b/arch/s390x/kernel/linux32.c
@@ -1563,12 +1563,15 @@ static void *do_smb_super_data_conv(void *raw_data)
struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+ if (s32->version != SMB_MOUNT_OLDVERSION)
+ goto out;
s->version = s32->version;
s->mounted_uid = low2highuid(s32->mounted_uid);
s->uid = low2highuid(s32->uid);
s->gid = low2highgid(s32->gid);
s->file_mode = s32->file_mode;
s->dir_mode = s32->dir_mode;
+out:
return raw_data;
}
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 9aab951ad642..24dcb2ca05b8 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.49 2001/07/27 09:42:22 davem Exp $
+#
# sparc/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
@@ -47,16 +47,24 @@ image: vmlinux
$(MAKE) -C arch/sparc/boot image
archclean:
+ rm -f arch/sparc/kernel/include
rm -f $(TOPDIR)/vmlinux.aout
-$(MAKE) -C arch/sparc/boot clean
archmrproper:
rm -f $(TOPDIR)/include/asm-sparc/asm_offsets.h
-prepare: check_asm
+prepare: include/asm-$(ARCH)/asm_offsets.h
+
+arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+ include/config/MARKER
+
+include/asm-$(ARCH)/asm_offsets.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
+ @$(generate-asm-offsets.h) < $< > $@
-check_asm: include/linux/version.h include/asm include/config/MARKER
- $(MAKE) -C arch/sparc/kernel check_asm
+include/asm-$(ARCH)/asm_offsets.h: include/asm-$(ARCH)/asm_offsets.h.tmp
+ @echo -n ' Generating $@'
+ @$(update-if-changed)
tftpboot.img:
$(MAKE) -C arch/sparc/boot tftpboot.img
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index dbe551f3cd63..ebc035a23e29 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -23,7 +23,7 @@ clean:
rm -f btfixupprep piggyback tftpboot.img btfix.o btfix.s image
BTOBJS := $(HEAD) $(init-y)
-BTLIBS := $(core-y) $(LIBS) $(drivers-y) $(net-y)
+BTLIBS := $(core-y) $(libs-y) $(drivers-y) $(net-y)
# Actual linking
image: btfix.o
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 69bab606ea3f..6adecbe49035 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -28,95 +28,3 @@ obj-y += sys_sunos.o sunos_ioctl.o
endif
include $(TOPDIR)/Rules.make
-
-HPATH := $(objtree)/include
-
-check_asm: FORCE
- @if [ ! -r $(HPATH)/asm/asm_offsets.h ] ; then \
- touch $(HPATH)/asm/asm_offsets.h ; \
- fi
- @echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
- @echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
- @echo "#define __ASM_OFFSETS_H__" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#include <linux/config.h>" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#ifndef CONFIG_SMP" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#include <linux/config.h>" > tmp.c
- @echo "#undef CONFIG_SMP" >> tmp.c
- @echo "#include <linux/sched.h>" >> tmp.c
- $(CPP) $(CPPFLAGS) tmp.c -o tmp.i
- @echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
- @echo "#include <linux/config.h>" >> check_asm_data.c
- @echo "#undef CONFIG_SMP" >> check_asm_data.c
- @echo "#include <linux/sched.h>" >> check_asm_data.c
- @echo "unsigned int check_asm_data[] = {" >> check_asm_data.c
- $(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
- $(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
- $(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
- @echo '};' >> check_asm_data.c
- $(CC) $(CFLAGS) -S -o check_asm_data.s check_asm_data.c
- @echo "/* Automatically generated. Do not edit. */" > check_asm.c
- @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
- @echo "unsigned int check_asm_data[] = {" >> check_asm.c
- $(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
- @echo "};" >> check_asm.c
- @echo 'int main(void) {' >> check_asm.c
- @echo 'int i = 0;' >> check_asm.c
- $(SH) ./check_asm.sh -printf task tmp.i check_asm.c
- $(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
- $(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
- @echo 'return 0; }' >> check_asm.c
- @rm -f tmp.[ci] check_asm_data.[cs]
- $(HOSTCC) -o check_asm check_asm.c
- ./check_asm >> asm_offsets.h
- @rm -f check_asm check_asm.c
- @echo "" >> asm_offsets.h
- @echo "#else /* CONFIG_SMP */" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#include <linux/config.h>" > tmp.c
- @echo "#undef CONFIG_SMP" >> tmp.c
- @echo "#define CONFIG_SMP 1" >> tmp.c
- @echo "#include <linux/sched.h>" >> tmp.c
- $(CPP) $(CPPFLAGS) tmp.c -o tmp.i
- @echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
- @echo "#include <linux/config.h>" >> check_asm_data.c
- @echo "#undef CONFIG_SMP" >> check_asm_data.c
- @echo "#define CONFIG_SMP 1" >> check_asm_data.c
- @echo "#include <linux/sched.h>" >> check_asm_data.c
- @echo "unsigned int check_asm_data[] = {" >> check_asm_data.c
- $(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
- $(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
- $(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
- @echo '};' >> check_asm_data.c
- $(CC) $(CFLAGS) -S -o check_asm_data.s check_asm_data.c
- @echo "/* Automatically generated. Do not edit. */" > check_asm.c
- @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
- @echo "unsigned int check_asm_data[] = {" >> check_asm.c
- $(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
- @echo "};" >> check_asm.c
- @echo 'int main(void) {' >> check_asm.c
- @echo 'int i = 0;' >> check_asm.c
- $(SH) ./check_asm.sh -printf task tmp.i check_asm.c
- $(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
- $(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
- @echo 'return 0; }' >> check_asm.c
- @rm -f tmp.[ci] check_asm_data.[cs]
- $(HOSTCC) -o check_asm check_asm.c
- ./check_asm >> asm_offsets.h
- @rm -f check_asm check_asm.c
- @echo "" >> asm_offsets.h
- @echo "#endif /* CONFIG_SMP */" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h
- @if test -r $(HPATH)/asm/asm_offsets.h; then \
- if cmp -s asm_offsets.h $(HPATH)/asm/asm_offsets.h; then \
- echo $(HPATH)/asm/asm_offsets.h is unchanged; \
- rm -f asm_offsets.h; \
- else \
- mv -f asm_offsets.h $(HPATH)/asm/asm_offsets.h; \
- fi; \
- else \
- mv -f asm_offsets.h $(HPATH)/asm/asm_offsets.h; \
- fi
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
new file mode 100644
index 000000000000..fa2e8a95ca45
--- /dev/null
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -0,0 +1,53 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ *
+ * On sparc, thread_info data is static and TI_XXX offsets are computed by hand.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+// #include <linux/mm.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int foo(void)
+{
+ DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread));
+ DEFINE(AOFF_task_ptrace, offsetof(struct task_struct, ptrace));
+ DEFINE(AOFF_task_blocked, offsetof(struct task_struct, blocked));
+ BLANK();
+ /* XXX This is the stuff for sclow.S, kill it. */
+ DEFINE(AOFF_task_pid, offsetof(struct task_struct, pid));
+ DEFINE(AOFF_task_uid, offsetof(struct task_struct, uid));
+ DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid));
+ DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid));
+ DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid));
+ /* DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); */
+ DEFINE(ASIZ_task_uid, sizeof(current->uid));
+ DEFINE(ASIZ_task_gid, sizeof(current->gid));
+ DEFINE(ASIZ_task_euid, sizeof(current->euid));
+ DEFINE(ASIZ_task_egid, sizeof(current->egid));
+ BLANK();
+ DEFINE(AOFF_thread_fork_kpsr,
+ offsetof(struct thread_struct, fork_kpsr));
+ BLANK();
+ DEFINE(AOFF_thread_w_saved, offsetof(struct thread_struct, w_saved));
+ DEFINE(AOFF_thread_rwbuf_stkptrs,
+ offsetof(struct thread_struct, rwbuf_stkptrs));
+ DEFINE(AOFF_thread_reg_window,
+ offsetof(struct thread_struct, reg_window));
+ BLANK();
+ DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context));
+
+ /* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */
+ return 0;
+}
diff --git a/arch/sparc/kernel/check_asm.sh b/arch/sparc/kernel/check_asm.sh
deleted file mode 100755
index a4d5e6d95708..000000000000
--- a/arch/sparc/kernel/check_asm.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-case $1 in
- -printf)
- sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
-/g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0 0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0 0x%08x\\n", check_asm_data[i++]);/' >> $4
- echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
- ;;
- -data)
- sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
-/g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/ ((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)), sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
- echo " sizeof(struct $2_struct)," >> $4
- ;;
- -ints)
- sed -n -e '/check_asm_data:/,/\.size/p' <$2 | sed -e 's/check_asm_data://' -e 's/\.size.*//' -e 's/\.ident.*//' -e 's/\.global.*//' -e 's/\.long[ ]\([0-9]*\)/\1,/' >>$3 ;;
- *)
- exit 1
- ;;
-esac
-exit 0
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 0e3396ed5cfd..2e6d220cd8f0 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -17,6 +17,7 @@
#include <asm/kgdb.h>
#include <asm/contregs.h>
#include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/cprefix.h>
#include <asm/vaddrs.h>
diff --git a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap.S
index 4a98b3ca42b9..fc4979449d07 100644
--- a/arch/sparc/kernel/etrap.S
+++ b/arch/sparc/kernel/etrap.S
@@ -12,6 +12,7 @@
#include <asm/page.h>
#include <asm/psr.h>
#include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
#include <asm/winmacro.h>
#include <asm/asmmacro.h>
#include <asm/thread_info.h>
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index 814be2e57645..19251358f3d9 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -7,6 +7,7 @@
#include <asm/cprefix.h>
#include <asm/page.h>
#include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/asi.h>
#include <asm/smp.h>
diff --git a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S
index 1ad511f4f4dc..594783abc295 100644
--- a/arch/sparc/kernel/sclow.S
+++ b/arch/sparc/kernel/sclow.S
@@ -36,18 +36,6 @@
LABEL(sunosnop):
CC_AND_RETT
-#if 0
-/* Not SMP safe */
- .globl LABEL(sunosgetpid)
-LABEL(sunosgetpid):
- LOAD_CURRENT(l4, l5)
- ld [%l4 + TI_TASK], %l4
- ld [%l4 + AOFF_task_pid], %i0
- ld [%l4 + AOFF_task_p_opptr], %l5
- ld [%l5 + AOFF_task_pid], %i1
- CC_AND_RETT
-#endif
-
#if (ASIZ_task_uid == 2 && ASIZ_task_euid == 2)
.globl LABEL(sunosgetuid)
LABEL(sunosgetuid):
diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S
index fb107aadadd3..f7aff720df94 100644
--- a/arch/sparc/kernel/wof.S
+++ b/arch/sparc/kernel/wof.S
@@ -8,6 +8,7 @@
#include <asm/contregs.h>
#include <asm/page.h>
#include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/smp.h>
#include <asm/asi.h>
diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S
index 7b924013a396..221f61e69613 100644
--- a/arch/sparc/kernel/wuf.S
+++ b/arch/sparc/kernel/wuf.S
@@ -8,6 +8,7 @@
#include <asm/contregs.h>
#include <asm/page.h>
#include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/smp.h>
#include <asm/asi.h>
diff --git a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
index f02a3045400c..6403f5398d5d 100644
--- a/arch/sparc/vmlinux.lds.S
+++ b/arch/sparc/vmlinux.lds.S
@@ -38,12 +38,12 @@ SECTIONS
. = ALIGN(4096);
__init_begin = .;
- .text.init : { *(.text.init) }
+ .init.text : { *(.init.text) }
__init_text_end = .;
- .data.init : { *(.data.init) }
+ .init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
- .setup_init : { *(.setup.init) }
+ .init.setup : { *(.init.setup) }
__setup_end = .;
__initcall_start = .;
.initcall.init : {
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 9b62bbe3a655..388b557b015c 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1582,6 +1582,8 @@ static void *do_smb_super_data_conv(void *raw_data)
struct smb_mount_data news, *s = &news;
struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+ if (s32->version != SMB_MOUNT_OLDVERSION)
+ goto out;
s->version = s32->version;
s->mounted_uid = low2highuid(s32->mounted_uid);
s->uid = low2highuid(s32->uid);
@@ -1589,6 +1591,7 @@ static void *do_smb_super_data_conv(void *raw_data)
s->file_mode = s32->file_mode;
s->dir_mode = s32->dir_mode;
memcpy(raw_data, s, sizeof(struct smb_mount_data));
+out:
return raw_data;
}
diff --git a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
index dd256448c7b2..50baaf6f3c4c 100644
--- a/arch/sparc64/vmlinux.lds.S
+++ b/arch/sparc64/vmlinux.lds.S
@@ -40,11 +40,11 @@ SECTIONS
__stop___kallsyms = .;
. = ALIGN(8192);
__init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
+ .init.text : { *(.init.text) }
+ .init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
- .setup_init : { *(.setup.init) }
+ .init.setup : { *(.init.setup) }
__setup_end = .;
__initcall_start = .;
.initcall.init : {
diff --git a/arch/um/Makefile b/arch/um/Makefile
index f4265f94529b..dd28bfdb90b9 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -70,7 +70,7 @@ LDFLAGS_vmlinux = -r $(ARCH_DIR)/main.o
vmlinux: $(ARCH_DIR)/main.o
-$(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S
+$(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S scripts FORCE
$(call if_changed_dep,as_s_S)
AFLAGS_uml.lds.o = -U$(SUBARCH) -DSTART=$$(($(TOP_ADDR) - $(SIZE))) \
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 68c8e1ca81d1..f961e21e68fb 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -51,22 +51,19 @@ static int ubd_open(struct inode * inode, struct file * filp);
static int ubd_release(struct inode * inode, struct file * file);
static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
-static int ubd_revalidate(kdev_t rdev);
+static int ubd_revalidate(struct gendisk *disk);
#define MAX_DEV (8)
-#define MAX_MINOR (MAX_DEV << UBD_SHIFT)
-
-#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT)
static struct block_device_operations ubd_blops = {
- .open = ubd_open,
- .release = ubd_release,
- .ioctl = ubd_ioctl,
- .revalidate = ubd_revalidate,
+ .open = ubd_open,
+ .release = ubd_release,
+ .ioctl = ubd_ioctl,
+ .revalidate_disk= ubd_revalidate,
};
/* Protected by the queue_lock */
-static request_queue_t *ubd_queue;
+static request_queue_t ubd_queue;
/* Protected by ubd_lock */
static int fake_major = 0;
@@ -347,30 +344,31 @@ int thread_fd = -1;
*/
int intr_count = 0;
-static void ubd_finish(int error)
+static void ubd_finish(struct request *req, int error)
{
int nsect;
if(error){
spin_lock(&ubd_io_lock);
- end_request(CURRENT, 0);
+ end_request(req, 0);
spin_unlock(&ubd_io_lock);
return;
}
- nsect = CURRENT->current_nr_sectors;
- CURRENT->sector += nsect;
- CURRENT->buffer += nsect << 9;
- CURRENT->errors = 0;
- CURRENT->nr_sectors -= nsect;
- CURRENT->current_nr_sectors = 0;
+ nsect = req->current_nr_sectors;
+ req->sector += nsect;
+ req->buffer += nsect << 9;
+ req->errors = 0;
+ req->nr_sectors -= nsect;
+ req->current_nr_sectors = 0;
spin_lock(&ubd_io_lock);
- end_request(CURRENT, 1);
+ end_request(req, 1);
spin_unlock(&ubd_io_lock);
}
static void ubd_handler(void)
{
struct io_thread_req req;
+ struct request *rq = elv_next_request(&ubd_queue);
int n;
do_ubd = NULL;
@@ -380,18 +378,18 @@ static void ubd_handler(void)
printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
"errno = %d\n", os_getpid(), -n);
spin_lock(&ubd_io_lock);
- end_request(CURRENT, 0);
+ end_request(rq, 0);
spin_unlock(&ubd_io_lock);
return;
}
- if((req.offset != ((__u64) (CURRENT->sector)) << 9) ||
- (req.length != (CURRENT->current_nr_sectors) << 9))
+ if((req.offset != ((__u64) (rq->sector)) << 9) ||
+ (req.length != (rq->current_nr_sectors) << 9))
panic("I/O op mismatch");
- ubd_finish(req.error);
+ ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
- do_ubd_request(ubd_queue);
+ do_ubd_request(&ubd_queue);
}
static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
@@ -483,9 +481,13 @@ static int ubd_add(int n)
goto out_unregister;
ubd_dev[n].fake = fake;
+ fake_disk->private_data = &ubd_dev[n];
+ fake_disk->queue = &ubd_queue;
add_disk(fake_disk);
}
+ disk->private_data = &ubd_dev[n];
+ disk->queue = &ubd_queue;
add_disk(disk);
make_ide_entries(disk->disk_name);
return(0);
@@ -574,11 +576,6 @@ static int ubd_mc_init(void)
__initcall(ubd_mc_init);
-static request_queue_t *ubd_get_queue(kdev_t device)
-{
- return(ubd_queue);
-}
-
int ubd_init(void)
{
int i;
@@ -588,9 +585,8 @@ int ubd_init(void)
printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
return -1;
}
- ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
- blk_init_queue(ubd_queue, do_ubd_request, &ubd_io_lock);
- elevator_init(ubd_queue, &elevator_noop);
+ blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
+ elevator_init(&ubd_queue, &elevator_noop);
if(fake_major != 0){
char name[sizeof("ubd_nnn\0")];
@@ -601,7 +597,6 @@ int ubd_init(void)
fake_major);
return -1;
}
- blk_dev[fake_major].queue = ubd_get_queue;
}
for(i = 0; i < MAX_DEV; i++)
ubd_add(i);
@@ -698,8 +693,8 @@ static int ubd_open_dev(struct ubd *dev)
static int ubd_open(struct inode *inode, struct file *filp)
{
- int n = DEVICE_NR(inode->i_rdev);
- struct ubd *dev = &ubd_dev[n];
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ubd *dev = disk->private_data;
int err;
if(dev->is_dir == 1)
goto out;
@@ -709,8 +704,8 @@ static int ubd_open(struct inode *inode, struct file *filp)
err = ubd_open_dev(dev);
if(err){
- printk(KERN_ERR "ubd%d: Can't open \"%s\": "
- "errno = %d\n", n, dev->file, -err);
+ printk(KERN_ERR "%s: Can't open \"%s\": "
+ "errno = %d\n", disk->disk_name, dev->file, -err);
goto out;
}
}
@@ -725,9 +720,10 @@ static int ubd_open(struct inode *inode, struct file *filp)
static int ubd_release(struct inode * inode, struct file * file)
{
- int n = DEVICE_NR(inode->i_rdev);
- if(--ubd_dev[n].count == 0)
- ubd_close(&ubd_dev[n]);
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ubd *dev = disk->private_data;
+ if(dev->count == 0)
+ ubd_close(dev);
return(0);
}
@@ -771,15 +767,13 @@ void cowify_req(struct io_thread_req *req, struct ubd *dev)
static int prepare_request(struct request *req, struct io_thread_req *io_req)
{
- struct ubd *dev;
+ struct gendisk *disk = req->rq_disk;
+ struct ubd *dev = disk->private_data;
__u64 block;
- int nsect, min, n;
+ int nsect;
- if(req->rq_status == RQ_INACTIVE) return(1);
+ if (req->rq_status == RQ_INACTIVE) return(1);
- min = minor(req->rq_dev);
- n = min >> UBD_SHIFT;
- dev = &ubd_dev[n];
if(dev->is_dir){
strcpy(req->buffer, "HOSTFS:");
strcat(req->buffer, dev->file);
@@ -790,7 +784,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
}
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
- printk("Write attempted on readonly ubd device %d\n", n);
+ printk("Write attempted on readonly ubd device %s\n", disk->disk_name);
spin_lock(&ubd_io_lock);
end_request(req, 0);
spin_unlock(&ubd_io_lock);
@@ -829,7 +823,7 @@ static void do_ubd_request(request_queue_t *q)
err = prepare_request(req, &io_req);
if(!err){
do_io(&io_req);
- ubd_finish(io_req.error);
+ ubd_finish(req, io_req.error);
}
}
}
@@ -852,21 +846,15 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct hd_geometry *loc = (struct hd_geometry *) arg;
+ struct ubd *dev = inode->i_bdev->bd_disk->private_data;
+ int err;
struct ubd *dev;
- int n, min, err;
struct hd_driveid ubd_id = {
.cyls = 0,
.heads = 128,
.sectors = 32,
};
-
- if(!inode) return(-EINVAL);
- min = minor(inode->i_rdev);
- n = min >> UBD_SHIFT;
- if(n > MAX_DEV)
- return(-EINVAL);
- dev = &ubd_dev[n];
switch (cmd) {
struct hd_geometry g;
struct cdrom_volctrl volume;
@@ -880,7 +868,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
case HDIO_SET_UNMASKINTR:
if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
- if((arg > 1) || (min & ((1 << UBD_SHIFT) - 1)))
+ if((arg > 1) || inode->i_bdev->bd_contains != inode->i_bdev)
return(-EINVAL);
return(0);
@@ -900,7 +888,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
case HDIO_SET_MULTCOUNT:
if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
- if(min & ((1 << UBD_SHIFT) - 1))
+ if (inode->i_bdev->bd_contains != inode->i_bdev)
return(-EINVAL);
return(0);
@@ -925,14 +913,11 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
return(-EINVAL);
}
-static int ubd_revalidate(kdev_t rdev)
+static int ubd_revalidate(struct gendisk *disk)
{
__u64 size;
- int n, err;
- struct ubd *dev;
-
- n = minor(rdev) >> UBD_SHIFT;
- dev = &ubd_dev[n];
+ int err;
+ struct ubd *dev = disk->private_data;
err = 0;
spin_lock(&ubd_lock);
@@ -941,9 +926,7 @@ static int ubd_revalidate(kdev_t rdev)
err = ubd_file_size(dev, &size);
if (!err) {
- set_capacity(ubd_gendisk[n], size / 512);
- if(fake_major != 0)
- set_capacity(fake_gendisk[n], size / 512);
+ set_capacity(disk, size / 512);
dev->size = size;
}
out:
diff --git a/arch/x86_64/kernel/mtrr.c b/arch/x86_64/kernel/mtrr.c
index 47c35bd43a5d..9d478fa81f6b 100644
--- a/arch/x86_64/kernel/mtrr.c
+++ b/arch/x86_64/kernel/mtrr.c
@@ -1,7 +1,7 @@
/* x86-64 MTRR (Memory Type Range Register) driver.
Based largely upon arch/i386/kernel/mtrr.c
- Copyright (C) 1997-2000 Richard Gooch
+ Copyright (C) 1997-2000 Richard Gooch
Copyright (C) 2002 Dave Jones.
This library is free software; you can redistribute it and/or
@@ -20,7 +20,7 @@
(For earlier history, see arch/i386/kernel/mtrr.c)
v2.00 September 2001 Dave Jones <davej@suse.de>
- Initial rewrite for x86-64.
+ Initial rewrite for x86-64.
Removal of non-Intel style MTRR code.
v2.01 June 2002 Dave Jones <davej@suse.de>
Removal of redundant abstraction layer.
@@ -84,7 +84,7 @@
typedef u8 mtrr_type;
-#define LINE_SIZE 80
+#define LINE_SIZE 80
#ifdef CONFIG_SMP
#define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type)
@@ -124,42 +124,42 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
local_irq_save(ctxt->flags);
local_irq_disable();
- /* Save value of CR4 and clear Page Global Enable (bit 7) */
+ /* Save value of CR4 and clear Page Global Enable (bit 7) */
if (cpu_has_pge) {
ctxt->cr4val = read_cr4();
write_cr4(ctxt->cr4val & ~(1UL << 7));
- }
+ }
- /* Disable and flush caches. Note that wbinvd flushes the TLBs as
- a side-effect */
+ /* Disable and flush caches. Note that wbinvd flushes the TLBs as
+ a side-effect */
cr0 = read_cr0() | 0x40000000;
- wbinvd();
+ wbinvd();
write_cr0(cr0);
- wbinvd();
+ wbinvd();
- /* Disable MTRRs, and set the default type to uncached */
+ /* Disable MTRRs, and set the default type to uncached */
rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
}
-/* Restore the processor after a set_mtrr_prepare */
+/* Restore the processor after a set_mtrr_prepare */
static void set_mtrr_done (struct set_mtrr_context *ctxt)
{
- /* Flush caches and TLBs */
- wbinvd();
+ /* Flush caches and TLBs */
+ wbinvd();
- /* Restore MTRRdefType */
+ /* Restore MTRRdefType */
wrmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
- /* Enable caches */
+ /* Enable caches */
write_cr0(read_cr0() & 0xbfffffff);
- /* Restore value of CR4 */
+ /* Restore value of CR4 */
if (cpu_has_pge)
write_cr4 (ctxt->cr4val);
- /* Re-enable interrupts locally (if enabled previously) */
+ /* Re-enable interrupts locally (if enabled previously) */
local_irq_restore(ctxt->flags);
}
@@ -193,21 +193,21 @@ static void get_mtrr (unsigned int reg, u64 *base, u32 *size, mtrr_type * type)
rdmsr (MSR_MTRRphysMask(reg), mask_lo, mask_hi);
if ((mask_lo & 0x800) == 0) {
- /* Invalid (i.e. free) range */
- *base = 0;
- *size = 0;
- *type = 0;
- return;
- }
+ /* Invalid (i.e. free) range */
+ *base = 0;
+ *size = 0;
+ *type = 0;
+ return;
+ }
rdmsr (MSR_MTRRphysBase(reg), base_lo, base_hi);
- /* Work out the shifted address mask. */
+ /* Work out the shifted address mask. */
newsize = (u64) mask_hi << 32 | (mask_lo & ~0x800);
newsize = ~newsize+1;
*size = (u32) newsize >> PAGE_SHIFT;
- *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
- *type = base_lo & 0xff;
+ *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
+ *type = base_lo & 0xff;
}
@@ -224,7 +224,7 @@ static void get_mtrr (unsigned int reg, u64 *base, u32 *size, mtrr_type * type)
static void set_mtrr_up (unsigned int reg, u64 base,
u32 size, mtrr_type type, int do_safe)
{
- struct set_mtrr_context ctxt;
+ struct set_mtrr_context ctxt;
u64 base64;
u64 size64;
@@ -232,8 +232,8 @@ static void set_mtrr_up (unsigned int reg, u64 base,
set_mtrr_prepare (&ctxt);
if (size == 0) {
- /* The invalid bit is kept in the mask, so we simply clear the
- relevant mask register to disable a range. */
+ /* The invalid bit is kept in the mask, so we simply clear the
+ relevant mask register to disable a range. */
wrmsr (MSR_MTRRphysMask(reg), 0, 0);
} else {
base64 = (base << PAGE_SHIFT) & size_and_mask;
@@ -242,7 +242,7 @@ static void set_mtrr_up (unsigned int reg, u64 base,
size64 = ~((size << PAGE_SHIFT) - 1);
size64 = size64 & size_and_mask;
wrmsr (MSR_MTRRphysMask(reg), (u32) (size64 | 0x800), (u32) (size64 >> 32));
- }
+ }
if (do_safe)
set_mtrr_done (&ctxt);
}
@@ -259,7 +259,7 @@ struct mtrr_var_range {
/* Get the MSR pair relating to a var range */
static void __init get_mtrr_var_range (unsigned int index,
- struct mtrr_var_range *vr)
+ struct mtrr_var_range *vr)
{
rdmsr (MSR_MTRRphysBase(index), vr->base_lo, vr->base_hi);
rdmsr (MSR_MTRRphysMask(index), vr->mask_lo, vr->mask_hi);
@@ -272,35 +272,35 @@ static int __init set_mtrr_var_range_testing (unsigned int index,
struct mtrr_var_range *vr)
{
u32 lo, hi;
- int changed = FALSE;
+ int changed = FALSE;
rdmsr (MSR_MTRRphysBase(index), lo, hi);
if ((vr->base_lo & 0xfffff0ff) != (lo & 0xfffff0ff) ||
(vr->base_hi & 0x000fffff) != (hi & 0x000fffff)) {
wrmsr (MSR_MTRRphysBase(index), vr->base_lo, vr->base_hi);
- changed = TRUE;
- }
+ changed = TRUE;
+ }
rdmsr (MSR_MTRRphysMask(index), lo, hi);
if ((vr->mask_lo & 0xfffff800) != (lo & 0xfffff800) ||
(vr->mask_hi & 0x000fffff) != (hi & 0x000fffff)) {
wrmsr (MSR_MTRRphysMask(index), vr->mask_lo, vr->mask_hi);
- changed = TRUE;
- }
- return changed;
+ changed = TRUE;
+ }
+ return changed;
}
static void __init get_fixed_ranges (mtrr_type * frs)
{
u32 *p = (u32 *) frs;
- int i;
+ int i;
rdmsr (MSR_MTRRfix64K_00000, p[0], p[1]);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 2; i++)
rdmsr (MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++)
rdmsr (MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
}
@@ -308,8 +308,8 @@ static void __init get_fixed_ranges (mtrr_type * frs)
static int __init set_fixed_ranges_testing (mtrr_type * frs)
{
u32 *p = (u32 *) frs;
- int changed = FALSE;
- int i;
+ int changed = FALSE;
+ int i;
u32 lo, hi;
printk (KERN_INFO "mtrr: rdmsr 64K_00000\n");
@@ -317,8 +317,8 @@ static int __init set_fixed_ranges_testing (mtrr_type * frs)
if (p[0] != lo || p[1] != hi) {
printk (KERN_INFO "mtrr: Writing %x:%x to 64K MSR. lohi were %x:%x\n", p[0], p[1], lo, hi);
wrmsr (MSR_MTRRfix64K_00000, p[0], p[1]);
- changed = TRUE;
- }
+ changed = TRUE;
+ }
printk (KERN_INFO "mtrr: rdmsr 16K_80000\n");
for (i = 0; i < 2; i++) {
@@ -326,9 +326,9 @@ static int __init set_fixed_ranges_testing (mtrr_type * frs)
if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) {
printk (KERN_INFO "mtrr: Writing %x:%x to 16K MSR%d. lohi were %x:%x\n", p[2 + i * 2], p[3 + i * 2], i, lo, hi );
wrmsr (MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
- changed = TRUE;
+ changed = TRUE;
+ }
}
- }
printk (KERN_INFO "mtrr: rdmsr 4K_C0000\n");
for (i = 0; i < 8; i++) {
@@ -337,18 +337,18 @@ static int __init set_fixed_ranges_testing (mtrr_type * frs)
if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) {
printk (KERN_INFO "mtrr: Writing %x:%x to 4K MSR%d. lohi were %x:%x\n", p[6 + i * 2], p[7 + i * 2], i, lo, hi);
wrmsr (MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
- changed = TRUE;
+ changed = TRUE;
+ }
}
- }
- return changed;
+ return changed;
}
struct mtrr_state {
- unsigned int num_var_ranges;
- struct mtrr_var_range *var_ranges;
- mtrr_type fixed_ranges[NUM_FIXED_RANGES];
- mtrr_type def_type;
+ unsigned int num_var_ranges;
+ struct mtrr_var_range *var_ranges;
+ mtrr_type fixed_ranges[NUM_FIXED_RANGES];
+ mtrr_type def_type;
unsigned char enabled;
};
@@ -356,23 +356,23 @@ struct mtrr_state {
/* Grab all of the MTRR state for this CPU into *state */
static void __init get_mtrr_state (struct mtrr_state *state)
{
- unsigned int nvrs, i;
- struct mtrr_var_range *vrs;
+ unsigned int nvrs, i;
+ struct mtrr_var_range *vrs;
u32 lo, dummy;
nvrs = state->num_var_ranges = get_num_var_ranges();
- vrs = state->var_ranges
- = kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
- if (vrs == NULL)
- nvrs = state->num_var_ranges = 0;
+ vrs = state->var_ranges
+ = kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
+ if (vrs == NULL)
+ nvrs = state->num_var_ranges = 0;
- for (i = 0; i < nvrs; i++)
- get_mtrr_var_range (i, &vrs[i]);
- get_fixed_ranges (state->fixed_ranges);
+ for (i = 0; i < nvrs; i++)
+ get_mtrr_var_range (i, &vrs[i]);
+ get_fixed_ranges (state->fixed_ranges);
rdmsr (MSR_MTRRdefType, lo, dummy);
- state->def_type = (lo & 0xff);
- state->enabled = (lo & 0xc00) >> 10;
+ state->def_type = (lo & 0xff);
+ state->enabled = (lo & 0xc00) >> 10;
}
@@ -392,26 +392,26 @@ static void __init finalize_mtrr_state (struct mtrr_state *state)
* [RETURNS] 0 if no changes made, else a mask indication what was changed.
*/
static u64 __init set_mtrr_state (struct mtrr_state *state,
- struct set_mtrr_context *ctxt)
+ struct set_mtrr_context *ctxt)
{
- unsigned int i;
+ unsigned int i;
u64 change_mask = 0;
- for (i = 0; i < state->num_var_ranges; i++)
+ for (i = 0; i < state->num_var_ranges; i++)
if (set_mtrr_var_range_testing (i, &state->var_ranges[i]))
- change_mask |= MTRR_CHANGE_MASK_VARIABLE;
+ change_mask |= MTRR_CHANGE_MASK_VARIABLE;
if (set_fixed_ranges_testing (state->fixed_ranges))
- change_mask |= MTRR_CHANGE_MASK_FIXED;
- /* Set_mtrr_restore restores the old value of MTRRdefType,
- so to set it we fiddle with the saved value */
+ change_mask |= MTRR_CHANGE_MASK_FIXED;
+ /* Set_mtrr_restore restores the old value of MTRRdefType,
+ so to set it we fiddle with the saved value */
if ((ctxt->deftype_lo & 0xff) != state->def_type
|| ((ctxt->deftype_lo & 0xc00) >> 10) != state->enabled) {
- ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
- change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
- }
+ ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
+ change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
+ }
- return change_mask;
+ return change_mask;
}
@@ -422,8 +422,8 @@ static volatile int wait_barrier_cache_enable = FALSE;
struct set_mtrr_data {
u64 smp_base;
u32 smp_size;
- unsigned int smp_reg;
- mtrr_type smp_type;
+ unsigned int smp_reg;
+ mtrr_type smp_type;
};
/*
@@ -431,67 +431,67 @@ struct set_mtrr_data {
*/
static void ipi_handler (void *info)
{
- struct set_mtrr_data *data = info;
- struct set_mtrr_context ctxt;
+ struct set_mtrr_data *data = info;
+ struct set_mtrr_context ctxt;
set_mtrr_prepare (&ctxt);
- /* Notify master that I've flushed and disabled my cache */
- atomic_dec (&undone_count);
+ /* Notify master that I've flushed and disabled my cache */
+ atomic_dec (&undone_count);
while (wait_barrier_execute)
barrier ();
- /* The master has cleared me to execute */
+ /* The master has cleared me to execute */
set_mtrr_up (data->smp_reg, data->smp_base, data->smp_size,
- data->smp_type, FALSE);
+ data->smp_type, FALSE);
- /* Notify master CPU that I've executed the function */
- atomic_dec (&undone_count);
+ /* Notify master CPU that I've executed the function */
+ atomic_dec (&undone_count);
- /* Wait for master to clear me to enable cache and return */
+ /* Wait for master to clear me to enable cache and return */
while (wait_barrier_cache_enable)
barrier ();
- set_mtrr_done (&ctxt);
+ set_mtrr_done (&ctxt);
}
static void set_mtrr_smp (unsigned int reg, u64 base, u32 size, mtrr_type type)
{
- struct set_mtrr_data data;
- struct set_mtrr_context ctxt;
-
- data.smp_reg = reg;
- data.smp_base = base;
- data.smp_size = size;
- data.smp_type = type;
- wait_barrier_execute = TRUE;
- wait_barrier_cache_enable = TRUE;
+ struct set_mtrr_data data;
+ struct set_mtrr_context ctxt;
+
+ data.smp_reg = reg;
+ data.smp_base = base;
+ data.smp_size = size;
+ data.smp_type = type;
+ wait_barrier_execute = TRUE;
+ wait_barrier_cache_enable = TRUE;
atomic_set (&undone_count, num_online_cpus() - 1);
- /* Start the ball rolling on other CPUs */
- if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
- panic ("mtrr: timed out waiting for other CPUs\n");
+ /* Start the ball rolling on other CPUs */
+ if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
+ panic ("mtrr: timed out waiting for other CPUs\n");
- /* Flush and disable the local CPU's cache */
+ /* Flush and disable the local CPU's cache */
set_mtrr_prepare (&ctxt);
- /* Wait for all other CPUs to flush and disable their caches */
+ /* Wait for all other CPUs to flush and disable their caches */
while (atomic_read (&undone_count) > 0)
barrier ();
/* Set up for completion wait and then release other CPUs to change MTRRs */
atomic_set (&undone_count, num_online_cpus() - 1);
- wait_barrier_execute = FALSE;
+ wait_barrier_execute = FALSE;
set_mtrr_up (reg, base, size, type, FALSE);
- /* Now wait for other CPUs to complete the function */
+ /* Now wait for other CPUs to complete the function */
while (atomic_read (&undone_count) > 0)
barrier ();
- /* Now all CPUs should have finished the function. Release the barrier to
- allow them to re-enable their caches and return from their interrupt,
- then enable the local cache and return */
- wait_barrier_cache_enable = FALSE;
- set_mtrr_done (&ctxt);
+ /* Now all CPUs should have finished the function. Release the barrier to
+ allow them to re-enable their caches and return from their interrupt,
+ then enable the local cache and return */
+ wait_barrier_cache_enable = FALSE;
+ set_mtrr_done (&ctxt);
}
@@ -500,44 +500,44 @@ static void __init mtrr_state_warn (u32 mask)
{
if (!mask)
return;
- if (mask & MTRR_CHANGE_MASK_FIXED)
- printk ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
- if (mask & MTRR_CHANGE_MASK_VARIABLE)
- printk ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
- if (mask & MTRR_CHANGE_MASK_DEFTYPE)
- printk ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
- printk ("mtrr: probably your BIOS does not setup all CPUs\n");
+ if (mask & MTRR_CHANGE_MASK_FIXED)
+ printk ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
+ if (mask & MTRR_CHANGE_MASK_VARIABLE)
+ printk ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
+ if (mask & MTRR_CHANGE_MASK_DEFTYPE)
+ printk ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
+ printk ("mtrr: probably your BIOS does not setup all CPUs\n");
}
-#endif /* CONFIG_SMP */
+#endif /* CONFIG_SMP */
static inline char * attrib_to_str (int x)
{
- return (x <= 6) ? mtrr_strings[x] : "?";
+ return (x <= 6) ? mtrr_strings[x] : "?";
}
static void __init init_table (void)
{
- int i, max;
+ int i, max;
- max = get_num_var_ranges ();
+ max = get_num_var_ranges ();
if ((usage_table = kmalloc (max * sizeof *usage_table, GFP_KERNEL))==NULL) {
- printk ("mtrr: could not allocate\n");
- return;
- }
+ printk ("mtrr: could not allocate\n");
+ return;
+ }
for (i = 0; i < max; i++)
usage_table[i] = 1;
#ifdef USERSPACE_INTERFACE
if ((ascii_buffer = kmalloc (max * LINE_SIZE, GFP_KERNEL)) == NULL) {
- printk ("mtrr: could not allocate\n");
- return;
- }
- ascii_buf_bytes = 0;
- compute_ascii ();
+ printk ("mtrr: could not allocate\n");
+ return;
+ }
+ ascii_buf_bytes = 0;
+ compute_ascii ();
#endif
}
@@ -548,18 +548,18 @@ static void __init init_table (void)
*/
static int get_free_region(void)
{
- int i, max;
- mtrr_type ltype;
+ int i, max;
+ mtrr_type ltype;
u64 lbase;
u32 lsize;
- max = get_num_var_ranges ();
+ max = get_num_var_ranges ();
for (i = 0; i < max; ++i) {
get_mtrr (i, &lbase, &lsize, &ltype);
if (lsize == 0)
return i;
- }
- return -ENOSPC;
+ }
+ return -ENOSPC;
}
@@ -597,16 +597,16 @@ static int get_free_region(void)
int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
{
- int i, max;
- mtrr_type ltype;
+ int i, max;
+ mtrr_type ltype;
u64 lbase, last;
u32 lsize;
if (base + size < 0x100) {
printk (KERN_WARNING
"mtrr: cannot set region below 1 MiB (0x%Lx000,0x%x000)\n",
- base, size);
- return -EINVAL;
+ base, size);
+ return -EINVAL;
}
#if defined(__x86_64__) && defined(CONFIG_AGP)
@@ -621,7 +621,7 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
#endif
/* Check upper bits of base and last are equal and lower bits are 0
- for base and 1 for last */
+ for base and 1 for last */
last = base + size - 1;
for (lbase = base; !(lbase & 1) && (last & 1);
lbase = lbase >> 1, last = last >> 1) ;
@@ -630,35 +630,36 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
printk (KERN_WARNING
"mtrr: base(0x%Lx000) is not aligned on a size(0x%x000) boundary\n",
base, size);
- return -EINVAL;
- }
+ return -EINVAL;
+ }
if (type >= MTRR_NUM_TYPES) {
- printk ("mtrr: type: %u illegal\n", type);
- return -EINVAL;
- }
+ printk ("mtrr: type: %u illegal\n", type);
+ return -EINVAL;
+ }
- /* If the type is WC, check that this processor supports it */
+ /* If the type is WC, check that this processor supports it */
if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
printk (KERN_WARNING
"mtrr: your processor doesn't support write-combining\n");
- return -ENOSYS;
- }
+ return -ENOSYS;
+ }
if (base & (size_or_mask>>PAGE_SHIFT)) {
printk (KERN_WARNING "mtrr: base(%lx) exceeds the MTRR width(%lx)\n",
- base, (size_or_mask>>PAGE_SHIFT));
+ (unsigned long) base,
+ (unsigned long) (size_or_mask>>PAGE_SHIFT));
return -EINVAL;
}
if (size & (size_or_mask>>PAGE_SHIFT)) {
printk (KERN_WARNING "mtrr: size exceeds the MTRR width\n");
- return -EINVAL;
- }
+ return -EINVAL;
+ }
- increment = increment ? 1 : 0;
- max = get_num_var_ranges ();
- /* Search for existing MTRR */
+ increment = increment ? 1 : 0;
+ max = get_num_var_ranges ();
+ /* Search for existing MTRR */
down (&mtrr_lock);
for (i = 0; i < max; ++i) {
get_mtrr (i, &lbase, &lsize, &ltype);
@@ -667,15 +668,15 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
if ((base < lbase) && (base + size <= lbase))
continue;
- /* At this point we know there is some kind of overlap/enclosure */
+ /* At this point we know there is some kind of overlap/enclosure */
if ((base < lbase) || (base + size > lbase + lsize)) {
up (&mtrr_lock);
printk (KERN_WARNING
"mtrr: 0x%Lx000,0x%x000 overlaps existing"
" 0x%Lx000,0x%x000\n", base, size, lbase, lsize);
- return -EINVAL;
- }
- /* New region is enclosed by an existing region */
+ return -EINVAL;
+ }
+ /* New region is enclosed by an existing region */
if (ltype != type) {
if (type == MTRR_TYPE_UNCACHABLE)
continue;
@@ -685,26 +686,26 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
base, size,
attrib_to_str (ltype),
attrib_to_str (type));
- return -EINVAL;
- }
+ return -EINVAL;
+ }
if (increment)
++usage_table[i];
- compute_ascii ();
+ compute_ascii ();
up (&mtrr_lock);
- return i;
- }
- /* Search for an empty MTRR */
+ return i;
+ }
+ /* Search for an empty MTRR */
i = get_free_region();
if (i < 0) {
up (&mtrr_lock);
- printk ("mtrr: no more MTRRs available\n");
- return i;
- }
- set_mtrr (i, base, size, type);
- usage_table[i] = 1;
- compute_ascii ();
+ printk ("mtrr: no more MTRRs available\n");
+ return i;
+ }
+ set_mtrr (i, base, size, type);
+ usage_table[i] = 1;
+ compute_ascii ();
up (&mtrr_lock);
- return i;
+ return i;
}
@@ -744,10 +745,10 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
int mtrr_add (u64 base, u32 size, unsigned int type, char increment)
{
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
- printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
- return -EINVAL;
- }
+ return -EINVAL;
+ }
return mtrr_add_page (base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
increment);
}
@@ -767,56 +768,56 @@ int mtrr_add (u64 base, u32 size, unsigned int type, char increment)
* On success the register is returned, on failure a negative error
* code.
*/
-
+
int mtrr_del_page (int reg, u64 base, u32 size)
{
- int i, max;
- mtrr_type ltype;
+ int i, max;
+ mtrr_type ltype;
u64 lbase;
u32 lsize;
- max = get_num_var_ranges ();
+ max = get_num_var_ranges ();
down (&mtrr_lock);
if (reg < 0) {
- /* Search for existing MTRR */
+ /* Search for existing MTRR */
for (i = 0; i < max; ++i) {
get_mtrr (i, &lbase, &lsize, &ltype);
if (lbase == base && lsize == size) {
- reg = i;
- break;
- }
- }
+ reg = i;
+ break;
+ }
+ }
if (reg < 0) {
up (&mtrr_lock);
printk ("mtrr: no MTRR for %Lx000,%x000 found\n", base, size);
- return -EINVAL;
+ return -EINVAL;
+ }
}
- }
if (reg >= max) {
up (&mtrr_lock);
- printk ("mtrr: register: %d too big\n", reg);
- return -EINVAL;
- }
+ printk ("mtrr: register: %d too big\n", reg);
+ return -EINVAL;
+ }
get_mtrr (reg, &lbase, &lsize, &ltype);
if (lsize < 1) {
up (&mtrr_lock);
- printk ("mtrr: MTRR %d not used\n", reg);
- return -EINVAL;
- }
+ printk ("mtrr: MTRR %d not used\n", reg);
+ return -EINVAL;
+ }
if (usage_table[reg] < 1) {
up (&mtrr_lock);
- printk ("mtrr: reg: %d has count=0\n", reg);
- return -EINVAL;
- }
+ printk ("mtrr: reg: %d has count=0\n", reg);
+ return -EINVAL;
+ }
if (--usage_table[reg] < 1)
set_mtrr (reg, 0, 0, 0);
- compute_ascii ();
+ compute_ascii ();
up (&mtrr_lock);
- return reg;
+ return reg;
}
@@ -834,14 +835,14 @@ int mtrr_del_page (int reg, u64 base, u32 size)
* On success the register is returned, on failure a negative error
* code.
*/
-
+
int mtrr_del (int reg, u64 base, u32 size)
{
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
- printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
- return -EINVAL;
- }
+ return -EINVAL;
+ }
return mtrr_del_page (reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
}
@@ -851,64 +852,64 @@ int mtrr_del (int reg, u64 base, u32 size)
static int mtrr_file_add (u64 base, u32 size, unsigned int type,
struct file *file, int page)
{
- int reg, max;
- unsigned int *fcount = file->private_data;
+ int reg, max;
+ unsigned int *fcount = file->private_data;
- max = get_num_var_ranges ();
+ max = get_num_var_ranges ();
if (fcount == NULL) {
if ((fcount =
kmalloc (max * sizeof *fcount, GFP_KERNEL)) == NULL) {
- printk ("mtrr: could not allocate\n");
- return -ENOMEM;
+ printk ("mtrr: could not allocate\n");
+ return -ENOMEM;
+ }
+ memset (fcount, 0, max * sizeof *fcount);
+ file->private_data = fcount;
}
- memset (fcount, 0, max * sizeof *fcount);
- file->private_data = fcount;
- }
- if (!page) {
+ if (!page) {
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
printk
("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
- return -EINVAL;
+ return -EINVAL;
+ }
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
}
- base >>= PAGE_SHIFT;
- size >>= PAGE_SHIFT;
- }
- reg = mtrr_add_page (base, size, type, 1);
+ reg = mtrr_add_page (base, size, type, 1);
if (reg >= 0)
++fcount[reg];
- return reg;
+ return reg;
}
static int mtrr_file_del (u64 base, u32 size,
- struct file *file, int page)
+ struct file *file, int page)
{
- int reg;
- unsigned int *fcount = file->private_data;
+ int reg;
+ unsigned int *fcount = file->private_data;
- if (!page) {
+ if (!page) {
if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
printk
("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
- return -EINVAL;
+ return -EINVAL;
+ }
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
}
- base >>= PAGE_SHIFT;
- size >>= PAGE_SHIFT;
- }
- reg = mtrr_del_page (-1, base, size);
+ reg = mtrr_del_page (-1, base, size);
if (reg < 0)
return reg;
if (fcount == NULL)
return reg;
if (fcount[reg] < 1)
return -EINVAL;
- --fcount[reg];
- return reg;
+ --fcount[reg];
+ return reg;
}
@@ -924,8 +925,8 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len,
if (copy_to_user (buf, ascii_buffer + *ppos, len))
return -EFAULT;
- *ppos += len;
- return len;
+ *ppos += len;
+ return len;
}
@@ -939,240 +940,240 @@ static ssize_t mtrr_write (struct file *file, const char *buf,
int i, err, reg;
u64 base;
u32 size;
- char *ptr;
- char line[LINE_SIZE];
+ char *ptr;
+ char line[LINE_SIZE];
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- /* Can't seek (pwrite) on this device */
+ /* Can't seek (pwrite) on this device */
if (ppos != &file->f_pos)
return -ESPIPE;
- memset (line, 0, LINE_SIZE);
+ memset (line, 0, LINE_SIZE);
if (len > LINE_SIZE)
len = LINE_SIZE;
if (copy_from_user (line, buf, len - 1))
return -EFAULT;
- ptr = line + strlen (line) - 1;
+ ptr = line + strlen (line) - 1;
if (*ptr == '\n')
*ptr = '\0';
if (!strncmp (line, "disable=", 8)) {
- reg = simple_strtoul (line + 8, &ptr, 0);
- err = mtrr_del_page (reg, 0, 0);
+ reg = simple_strtoul (line + 8, &ptr, 0);
+ err = mtrr_del_page (reg, 0, 0);
if (err < 0)
return err;
- return len;
- }
+ return len;
+ }
if (strncmp (line, "base=", 5)) {
- printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
- return -EINVAL;
- }
+ printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
+ return -EINVAL;
+ }
- base = simple_strtoull (line + 5, &ptr, 0);
+ base = simple_strtoull (line + 5, &ptr, 0);
for (; isspace (*ptr); ++ptr) ;
if (strncmp (ptr, "size=", 5)) {
- printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
- return -EINVAL;
- }
+ printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
+ return -EINVAL;
+ }
- size = simple_strtoull (ptr + 5, &ptr, 0);
+ size = simple_strtoull (ptr + 5, &ptr, 0);
if ((base & 0xfff) || (size & 0xfff)) {
- printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
printk ("mtrr: size: 0x%x base: 0x%Lx\n", size, base);
- return -EINVAL;
- }
+ return -EINVAL;
+ }
for (; isspace (*ptr); ++ptr) ;
if (strncmp (ptr, "type=", 5)) {
- printk ("mtrr: no \"type=\" in line: \"%s\"\n", line);
- return -EINVAL;
- }
- ptr += 5;
+ printk ("mtrr: no \"type=\" in line: \"%s\"\n", line);
+ return -EINVAL;
+ }
+ ptr += 5;
for (; isspace (*ptr); ++ptr) ;
for (i = 0; i < MTRR_NUM_TYPES; ++i) {
if (strcmp (ptr, mtrr_strings[i]))
continue;
- base >>= PAGE_SHIFT;
- size >>= PAGE_SHIFT;
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
err = mtrr_add_page ((u64) base, size, i, 1);
if (err < 0)
return err;
- return len;
- }
- printk ("mtrr: illegal type: \"%s\"\n", ptr);
- return -EINVAL;
+ return len;
+ }
+ printk ("mtrr: illegal type: \"%s\"\n", ptr);
+ return -EINVAL;
}
static int mtrr_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- int err;
- mtrr_type type;
- struct mtrr_sentry sentry;
- struct mtrr_gentry gentry;
+ int err;
+ mtrr_type type;
+ struct mtrr_sentry sentry;
+ struct mtrr_gentry gentry;
switch (cmd) {
- default:
- return -ENOIOCTLCMD;
+ default:
+ return -ENOIOCTLCMD;
- case MTRRIOC_ADD_ENTRY:
+ case MTRRIOC_ADD_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
+ return -EFAULT;
err = mtrr_file_add (sentry.base, sentry.size, sentry.type,
file, 0);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_SET_ENTRY:
+ case MTRRIOC_SET_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
- err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);
+ return -EFAULT;
+ err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_DEL_ENTRY:
+ case MTRRIOC_DEL_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
- err = mtrr_file_del (sentry.base, sentry.size, file, 0);
+ return -EFAULT;
+ err = mtrr_file_del (sentry.base, sentry.size, file, 0);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_KILL_ENTRY:
+ case MTRRIOC_KILL_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
- err = mtrr_del (-1, sentry.base, sentry.size);
+ return -EFAULT;
+ err = mtrr_del (-1, sentry.base, sentry.size);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_GET_ENTRY:
+ case MTRRIOC_GET_ENTRY:
if (copy_from_user (&gentry, (void *) arg, sizeof gentry))
- return -EFAULT;
+ return -EFAULT;
if (gentry.regnum >= get_num_var_ranges ())
return -EINVAL;
get_mtrr (gentry.regnum, (u64*) &gentry.base, &gentry.size, &type);
- /* Hide entries that go above 4GB */
+ /* Hide entries that go above 4GB */
if (gentry.base + gentry.size > 0x100000
|| gentry.size == 0x100000)
- gentry.base = gentry.size = gentry.type = 0;
- else {
- gentry.base <<= PAGE_SHIFT;
- gentry.size <<= PAGE_SHIFT;
- gentry.type = type;
- }
+ gentry.base = gentry.size = gentry.type = 0;
+ else {
+ gentry.base <<= PAGE_SHIFT;
+ gentry.size <<= PAGE_SHIFT;
+ gentry.type = type;
+ }
if (copy_to_user ((void *) arg, &gentry, sizeof gentry))
- return -EFAULT;
- break;
+ return -EFAULT;
+ break;
- case MTRRIOC_ADD_PAGE_ENTRY:
+ case MTRRIOC_ADD_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
+ return -EFAULT;
err = mtrr_file_add (sentry.base, sentry.size, sentry.type, file, 1);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_SET_PAGE_ENTRY:
+ case MTRRIOC_SET_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
- err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
+ return -EFAULT;
+ err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_DEL_PAGE_ENTRY:
+ case MTRRIOC_DEL_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
- err = mtrr_file_del (sentry.base, sentry.size, file, 1);
+ return -EFAULT;
+ err = mtrr_file_del (sentry.base, sentry.size, file, 1);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_KILL_PAGE_ENTRY:
+ case MTRRIOC_KILL_PAGE_ENTRY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
- return -EFAULT;
- err = mtrr_del_page (-1, sentry.base, sentry.size);
+ return -EFAULT;
+ err = mtrr_del_page (-1, sentry.base, sentry.size);
if (err < 0)
return err;
- break;
+ break;
- case MTRRIOC_GET_PAGE_ENTRY:
+ case MTRRIOC_GET_PAGE_ENTRY:
if (copy_from_user (&gentry, (void *) arg, sizeof gentry))
- return -EFAULT;
+ return -EFAULT;
if (gentry.regnum >= get_num_var_ranges ())
return -EINVAL;
get_mtrr (gentry.regnum, (u64*) &gentry.base, &gentry.size, &type);
- gentry.type = type;
+ gentry.type = type;
if (copy_to_user ((void *) arg, &gentry, sizeof gentry))
- return -EFAULT;
- break;
- }
- return 0;
+ return -EFAULT;
+ break;
+ }
+ return 0;
}
static int mtrr_close (struct inode *ino, struct file *file)
{
- int i, max;
- unsigned int *fcount = file->private_data;
+ int i, max;
+ unsigned int *fcount = file->private_data;
if (fcount == NULL)
return 0;
lock_kernel ();
- max = get_num_var_ranges ();
+ max = get_num_var_ranges ();
for (i = 0; i < max; ++i) {
while (fcount[i] > 0) {
if (mtrr_del (i, 0, 0) < 0)
printk ("mtrr: reg %d not used\n", i);
- --fcount[i];
+ --fcount[i];
+ }
}
- }
unlock_kernel ();
- kfree (fcount);
- file->private_data = NULL;
- return 0;
+ kfree (fcount);
+ file->private_data = NULL;
+ return 0;
}
static struct file_operations mtrr_fops = {
.owner = THIS_MODULE,
- .read = mtrr_read,
- .write = mtrr_write,
+ .read = mtrr_read,
+ .write = mtrr_write,
.ioctl = mtrr_ioctl,
.release = mtrr_close,
};
@@ -1185,38 +1186,38 @@ static devfs_handle_t devfs_handle;
static void compute_ascii (void)
{
- char factor;
- int i, max;
- mtrr_type type;
+ char factor;
+ int i, max;
+ mtrr_type type;
u64 base;
u32 size;
- ascii_buf_bytes = 0;
- max = get_num_var_ranges ();
+ ascii_buf_bytes = 0;
+ max = get_num_var_ranges ();
for (i = 0; i < max; i++) {
get_mtrr (i, &base, &size, &type);
if (size == 0)
usage_table[i] = 0;
else {
if (size < (0x100000 >> PAGE_SHIFT)) {
- /* less than 1MB */
- factor = 'K';
- size <<= PAGE_SHIFT - 10;
+ /* less than 1MB */
+ factor = 'K';
+ size <<= PAGE_SHIFT - 10;
} else {
- factor = 'M';
- size >>= 20 - PAGE_SHIFT;
- }
+ factor = 'M';
+ size >>= 20 - PAGE_SHIFT;
+ }
sprintf (ascii_buffer + ascii_buf_bytes,
"reg%02i: base=0x%05Lx000 (%4iMB), size=%4i%cB: %s, count=%d\n",
i, base, (u32) base >> (20 - PAGE_SHIFT), size, factor,
- attrib_to_str (type), usage_table[i]);
+ attrib_to_str (type), usage_table[i]);
ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);
+ }
}
- }
- devfs_set_file_size (devfs_handle, ascii_buf_bytes);
+ devfs_set_file_size (devfs_handle, ascii_buf_bytes);
#ifdef CONFIG_PROC_FS
- if (proc_root_mtrr)
- proc_root_mtrr->size = ascii_buf_bytes;
+ if (proc_root_mtrr)
+ proc_root_mtrr->size = ascii_buf_bytes;
#endif
}
@@ -1225,7 +1226,7 @@ static void compute_ascii (void)
EXPORT_SYMBOL (mtrr_add);
EXPORT_SYMBOL (mtrr_del);
-
+
static void __init mtrr_setup (void)
{
printk ("mtrr: v%s)\n", MTRR_VERSION);
@@ -1234,7 +1235,7 @@ static void __init mtrr_setup (void)
/* Query the width (in bits) of the physical
addressable memory on the Hammer family. */
if ((cpuid_eax (0x80000000) >= 0x80000008)) {
- u32 phys_addr;
+ u32 phys_addr;
phys_addr = cpuid_eax (0x80000008) & 0xff;
size_or_mask = ~((1L << phys_addr) - 1);
/*
@@ -1263,30 +1264,30 @@ void __init mtrr_init_secondary_cpu (void)
{
u64 mask;
int count;
- struct set_mtrr_context ctxt;
+ struct set_mtrr_context ctxt;
- /* Note that this is not ideal, since the cache is only flushed/disabled
- for this CPU while the MTRRs are changed, but changing this requires
- more invasive changes to the way the kernel boots */
+ /* Note that this is not ideal, since the cache is only flushed/disabled
+ for this CPU while the MTRRs are changed, but changing this requires
+ more invasive changes to the way the kernel boots */
set_mtrr_prepare (&ctxt);
- mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
- set_mtrr_done (&ctxt);
+ mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
+ set_mtrr_done (&ctxt);
- /* Use the atomic bitops to update the global mask */
+ /* Use the atomic bitops to update the global mask */
for (count = 0; count < sizeof mask * 8; ++count) {
if (mask & 0x01)
set_bit (count, &smp_changes_mask);
- mask >>= 1;
- }
+ mask >>= 1;
+ }
}
-#endif /* CONFIG_SMP */
+#endif /* CONFIG_SMP */
int __init mtrr_init (void)
{
#ifdef CONFIG_SMP
- /* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */
+ /* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */
finalize_mtrr_state (&smp_mtrr_state);
mtrr_state_warn (smp_changes_mask);
@@ -1295,17 +1296,17 @@ int __init mtrr_init (void)
#endif
#ifdef CONFIG_PROC_FS
- proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
- if (proc_root_mtrr) {
- proc_root_mtrr->owner = THIS_MODULE;
- proc_root_mtrr->proc_fops = &mtrr_fops;
- }
+ proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
+ if (proc_root_mtrr) {
+ proc_root_mtrr->owner = THIS_MODULE;
+ proc_root_mtrr->proc_fops = &mtrr_fops;
+ }
#endif
#ifdef CONFIG_DEVFS_FS
- devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
- S_IFREG | S_IRUGO | S_IWUSR,
- &mtrr_fops, NULL);
+ devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ &mtrr_fops, NULL);
#endif
- init_table ();
- return 0;
+ init_table ();
+ return 0;
}
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 1d55917a10f8..3c0ae2ebb5a9 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -156,6 +156,7 @@
#define FLOPPY_DMA 0
#define DEVICE_NAME "floppy"
#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&floppy_queue)
#include <linux/blk.h>
/* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
@@ -179,6 +180,8 @@
#define DPRINT(a)
#endif
+static struct request_queue floppy_queue;
+
/* Disk types: DD */
static struct archy_disk_type {
const char *name;
@@ -1140,14 +1143,11 @@ static void floppy_off(unsigned int nr)
- but if it sees a disc change line go high (?) it flips to using
it. Well maybe I'll add that in the future (!?)
*/
-static int check_floppy_change(dev_t dev)
+static int check_floppy_change(struct gendisk *disk)
{
- unsigned int drive = (dev & 0x03);
+ struct archy_floppy_struct *p = disk->private_data;
+ unsigned int drive = p - unit;
- if (major(dev) != MAJOR_NR) {
- printk("floppy_changed: not a floppy\n");
- return 0;
- }
if (test_bit(drive, &fake_change)) {
/* simulated change (e.g. after formatting) */
return 1;
@@ -1156,7 +1156,7 @@ static int check_floppy_change(dev_t dev)
/* surely changed (the WP signal changed at least once) */
return 1;
}
- if (unit[drive].wpstat) {
+ if (p->wpstat) {
/* WP is on -> could be changed: to be sure, buffers should be
* invalidated...
*/
@@ -1165,9 +1165,10 @@ static int check_floppy_change(dev_t dev)
return 1; /* DAG - was 0 */
}
-static int floppy_revalidate(dev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
{
- int drive = dev & 3;
+ struct archy_floppy_struct *p = disk->private_data;
+ unsigned int drive = p - unit;
if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
|| unit[drive].disktype == 0) {
@@ -1176,7 +1177,7 @@ static int floppy_revalidate(dev_t dev)
#endif
clear_bit(drive, &fake_change);
clear_bit(drive, &changed_floppies);
- unit[drive].disktype = 0;
+ p->disktype = 0;
}
return 0;
}
@@ -1521,23 +1522,24 @@ static int floppy_release(struct inode *inode, struct file *filp)
static struct block_device_operations floppy_fops =
{
- .open = floppy_open,
- .release = floppy_release,
- .ioctl = fd_ioctl,
- .check_media_change = check_floppy_change,
- .revalidate = floppy_revalidate,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = fd_ioctl,
+ .media_changed = check_floppy_change,
+ .revalidate_disk= floppy_revalidate,
};
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
{
- int drive = minor & 3;
- if ((minor>> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
+ int drive = *part & 3;
+ if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
return NULL;
- return disks[drive];
+ return get_disk(disks[drive]);
}
int fd1772_init(void)
{
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int i;
if (!machine_is_archimedes())
@@ -1580,16 +1582,19 @@ int fd1772_init(void)
out of some special memory... */
DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
#endif
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request);
+ blk_init_queue(&floppy_queue, do_fd_request, &lock);
for (i = 0; i < FD_MAX_UNITS; i++) {
unit[i].track = -1;
disks[i]->major = MAJOR_NR;
disks[i]->first_minor = 0;
disks[i]->fops = &floppy_fops;
sprintf(disks[i]->disk_name, "fd%d", i);
+ disks[i]->private_data = &unit[i];
+ disks[i]->queue = &floppy_queue;
set_capacity(disks[i], MAX_DISK_SIZE * 2);
}
- blk_set_probe(MAJOR_NR, floppy_find);
+ blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+ floppy_find, NULL, NULL);
for (i = 0; i < FD_MAX_UNITS; i++)
add_disk(disks[i]);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index d4c01d605559..95471970b5d8 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -114,7 +114,7 @@
#include <linux/delay.h>
#define MAJOR_NR MFM_ACORN_MAJOR
-#define DEVICE_NR(device) (minor(device) >> 6)
+#define QUEUE (&mfm_queue)
#include <linux/blk.h>
#include <linux/blkpg.h>
@@ -128,6 +128,8 @@
#include <asm/hardware/ioc.h>
static void (*do_mfm)(void) = NULL;
+static struct request_queue mfm_queue;
+static spinlock_t mfm_lock = SPIN_LOCK_UNLOCKED;
/*
* This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
*/
@@ -225,7 +227,7 @@ static void mfm_seek(void);
static void mfm_rerequest(void);
static void mfm_request(void);
static void mfm_specify (void);
-static void issue_request(int dev, unsigned int block, unsigned int nsect,
+static void issue_request(unsigned int block, unsigned int nsect,
struct request *req);
static unsigned int mfm_addr; /* Controller address */
@@ -739,7 +741,7 @@ static void request_done(int uptodate)
/* Yep - a partial access */
/* and issue the remainder */
- issue_request(minor(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
+ issue_request(PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
return;
}
@@ -794,30 +796,31 @@ static struct cont rw_cont =
* Actually gets round to issuing the request - note everything at this
* point is in 256 byte sectors not Linux 512 byte blocks
*/
-static void issue_request(int dev, unsigned int block, unsigned int nsect,
+static void issue_request(unsigned int block, unsigned int nsect,
struct request *req)
{
+ struct gendisk *disk = req->rq_disk;
+ struct mfm_info *p = disk->private_data;
int track, start_head, start_sector;
int sectors_to_next_cyl;
+ dev = p - mfm_info;
- dev >>= 6;
-
- track = block / mfm_info[dev].sectors;
- start_sector = block % mfm_info[dev].sectors;
- start_head = track % mfm_info[dev].heads;
+ track = block / p->sectors;
+ start_sector = block % p->sectors;
+ start_head = track % p->heads;
/* First get the number of whole tracks which are free before the next
track */
- sectors_to_next_cyl = (mfm_info[dev].heads - (start_head + 1)) * mfm_info[dev].sectors;
+ sectors_to_next_cyl = (p->heads - (start_head + 1)) * p->sectors;
/* Then add in the number of sectors left on this track */
- sectors_to_next_cyl += (mfm_info[dev].sectors - start_sector);
+ sectors_to_next_cyl += (p->sectors - start_sector);
- DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", mfm_info[dev].sectors, track);
+ DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", p->sectors, track);
raw_cmd.dev = dev;
raw_cmd.sector = start_sector;
raw_cmd.head = start_head;
- raw_cmd.cylinder = track / mfm_info[dev].heads;
+ raw_cmd.cylinder = track / p->heads;
raw_cmd.cmdtype = CURRENT->cmd;
raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
raw_cmd.cmddata[0] = dev + 1; /* DAG: +1 to get US */
@@ -895,7 +898,7 @@ static void mfm_request(void)
Busy = 1;
while (1) {
- unsigned int dev, block, nsect, unit;
+ unsigned int block, nsect;
struct gendisk *disk;
DBG("mfm_request: loop start\n");
@@ -912,16 +915,9 @@ static void mfm_request(void)
DBG("mfm_request: before arg extraction\n");
- dev = minor(CURRENT->rq_dev);
- unit = dev>>6;
+ disk = CURRENT->rq_disk;
block = CURRENT->sector;
nsect = CURRENT->nr_sectors;
-#ifdef DEBUG
- /*if (unit==1) */ console_printf("mfm_request: raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);
-#endif
- if (unit >= mfm_drives)
- printk("mfm: bad disk number: %d\n", unit);
- disk = mfm_gendisk[unit];
if (block >= get_capacity(disk) ||
block+nsect > get_capacity(disk)) {
printk("%s: bad access: block=%d, count=%d, nr_sects=%ld\n",
@@ -951,7 +947,7 @@ static void mfm_request(void)
printk("mfm: continue 4\n");
continue;
}
- issue_request(dev, block, nsect, CURRENT);
+ issue_request(block, nsect, CURRENT);
break;
}
@@ -1006,6 +1002,7 @@ static void mfm_geometry(int drive)
{
struct mfm_info *p = mfm_info + drive;
struct gendisk *disk = mfm_gendisk[drive];
+ disk->private_data = p;
if (p->cylinders)
printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n",
disk->disk_name,
@@ -1166,21 +1163,18 @@ static int mfm_initdrives(void)
static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
{
+ struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
struct hd_geometry *geo = (struct hd_geometry *) arg;
- int device = DEVICE_NR(minor(inode->i_rdev));
- if (device >= mfm_drives)
- return -EINVAL;
if (cmd != HDIO_GETGEO)
return -EINVAL;
if (!arg)
return -EINVAL;
- if (put_user (mfm_info[device].heads, &geo->heads))
+ if (put_user (p->heads, &geo->heads))
return -EFAULT;
- if (put_user (mfm_info[device].sectors, &geo->sectors))
+ if (put_user (p->sectors, &geo->sectors))
return -EFAULT;
- if (put_user (mfm_info[device].cylinders, &geo->cylinders))
+ if (put_user (p->cylinders, &geo->cylinders))
return -EFAULT;
- start = get_start_sect(inode->i_bdev);
if (put_user (get_start_sect(inode->i_bdev), &geo->start))
return -EFAULT;
return 0;
@@ -1203,24 +1197,26 @@ void mfm_setup(char *str, int *ints)
void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
unsigned char heads, unsigned int secsize)
{
- int drive = MINOR(bdev->bd_dev) >> 6;
+ struct mfm_info *p = bdev->bd_disk->private_data;
+ int drive = p - mfm_info;
unsigned long disksize = bdev->bd_inode->i_size;
- if (mfm_info[drive].cylinders == 1) {
- mfm_info[drive].sectors = secsptrack;
- mfm_info[drive].heads = heads;
- mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);
+ if (p->cylinders == 1) {
+ p->sectors = secsptrack;
+ p->heads = heads;
+ p->cylinders = discsize / (secsptrack * heads * secsize);
- if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {
- printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + drive);
+ if ((heads < 1) || (p->cylinders > 1024)) {
+ printk("%s: Insane disc shape! Setting to 512/4/32\n",
+ bdev->bd_disk->disk_name);
/* These values are fairly arbitary, but are there so that if your
* lucky you can pick apart your disc to find out what is going on -
* I reckon these figures won't hurt MOST drives
*/
- mfm_info[drive].sectors = 32;
- mfm_info[drive].heads = 4;
- mfm_info[drive].cylinders = 512;
+ p->sectors = 32;
+ p->heads = 4;
+ p->cylinders = 512;
}
if (raw_cmd.dev == drive)
mfm_specify ();
@@ -1317,7 +1313,7 @@ static int __init mfm_init (void)
hdc63463_irqpolladdress = mfm_IRQPollLoc;
hdc63463_irqpollmask = irqmask;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request);
+ blk_init_queue(&mfm_queue, do_mfm_request, &mfm_lock);
Busy = 0;
lastspecifieddrive = -1;
@@ -1349,6 +1345,7 @@ static int __init mfm_init (void)
for (i = 0; i < mfm_drives; i++) {
mfm_geometry(i);
+ mfm_gendisk[i]->queue = &mfm_queue;
add_disk(mfm_gendisk[i]);
}
return 0;
@@ -1357,7 +1354,7 @@ out4:
for (i = 0; i < mfm_drives; i++)
put_disk(mfm_gendisk[i]);
out3:
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mfm_queue);
unregister_blkdev(MAJOR_NR, "mfm");
out2:
release_region(mfm_addr, 10);
@@ -1380,7 +1377,7 @@ static void __exit mfm_exit(void)
del_gendisk(mfm_gendisk[i]);
put_disk(mfm_gendisk[i]);
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mfm_queue);
unregister_blkdev(MAJOR_NR, "mfm");
if (ecs)
ecard_release(ecs);
diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
index b0b8a490a214..6ab6f0d3b126 100644
--- a/drivers/acorn/scsi/acornscsi.c
+++ b/drivers/acorn/scsi/acornscsi.c
@@ -3010,14 +3010,12 @@ int acornscsi_proc_info(char *buffer, char **start, off_t offset,
int length, int host_no, int inout)
{
int pos, begin = 0, devidx;
- struct Scsi_Host *instance = scsi_hostlist;
+ struct Scsi_Host *instance;
Scsi_Device *scd;
AS_Host *host;
char *p = buffer;
- for (instance = scsi_hostlist;
- instance && instance->host_no != host_no;
- instance = instance->next);
+ instance = scsi_host_hn_get(host_no);
if (inout == 1 || !instance)
return -EINVAL;
diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c
index 646aada2b49b..016d019fb59f 100644
--- a/drivers/acorn/scsi/arxescsi.c
+++ b/drivers/acorn/scsi/arxescsi.c
@@ -384,15 +384,11 @@ int arxescsi_proc_info(char *buffer, char **start, off_t offset,
int length, int host_no, int inout)
{
int pos, begin;
- struct Scsi_Host *host = scsi_hostlist;
+ struct Scsi_Host *host;
ARXEScsi_Info *info;
Scsi_Device *scd;
- while (host) {
- if (host->host_no == host_no)
- break;
- host = host->next;
- }
+ host = scsi_host_hn_get(host_no);
if (!host)
return 0;
diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
index 15dd45c3871f..010b31b6ee23 100644
--- a/drivers/acorn/scsi/cumana_2.c
+++ b/drivers/acorn/scsi/cumana_2.c
@@ -498,15 +498,11 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
int length, int host_no, int inout)
{
int pos, begin;
- struct Scsi_Host *host = scsi_hostlist;
+ struct Scsi_Host *host;
CumanaScsi2_Info *info;
Scsi_Device *scd;
- while (host) {
- if (host->host_no == host_no)
- break;
- host = host->next;
- }
+ host = scsi_host_hn_get(host_no);
if (!host)
return 0;
diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
index d010d4430c23..f64f67cb3082 100644
--- a/drivers/acorn/scsi/eesox.c
+++ b/drivers/acorn/scsi/eesox.c
@@ -499,15 +499,11 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
int length, int host_no, int inout)
{
int pos, begin;
- struct Scsi_Host *host = scsi_hostlist;
+ struct Scsi_Host *host;
EESOXScsi_Info *info;
Scsi_Device *scd;
- while (host) {
- if (host->host_no == host_no)
- break;
- host = host->next;
- }
+ host = scsi_host_hn_get(host_no);
if (!host)
return 0;
diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
index f5783217a5f8..7f90b93793a5 100644
--- a/drivers/acorn/scsi/powertec.c
+++ b/drivers/acorn/scsi/powertec.c
@@ -404,15 +404,11 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
int length, int host_no, int inout)
{
int pos, begin;
- struct Scsi_Host *host = scsi_hostlist;
+ struct Scsi_Host *host;
PowerTecScsi_Info *info;
Scsi_Device *scd;
- while (host) {
- if (host->host_no == host_no)
- break;
- host = host->next;
- }
+ host = scsi_host_hn_get(host_no);
if (!host)
return 0;
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index ccae789befa9..2d88513912c0 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -8,6 +8,10 @@ export-objs := uPD98402.o suni.o idt77105.o
fore_200e-objs := fore200e.o
host-progs := fore200e_mkfirm
+# Files generated that shall be removed upon make clean
+clean-files := {atmsar11,pca200e,pca200e_ecd,sba200e_ecd}.{bin,bin1,bin2}
+# Firmware generated that shall be removed upon make clean
+clean-files += fore200e_pca_fw.c fore200e_sba_fw.c
obj-$(CONFIG_ATM_ZATM) += zatm.o uPD98402.o
obj-$(CONFIG_ATM_NICSTAR) += nicstar.o
@@ -61,6 +65,6 @@ $(obj)/fore200e_sba_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_SBA_FW)) \
-i $(CONFIG_ATM_FORE200E_SBA_FW) -o $@
# deal with the various suffixes of the binary firmware images
-$(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(obj)/%.data
+$(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(src)/%.data
objcopy -Iihex $< -Obinary $@.gz
gzip -df $@.gz
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 0c05ae058971..3f294f8cafff 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -8,6 +8,7 @@
extern struct list_head global_device_list;
extern spinlock_t device_lock;
+extern struct semaphore device_sem;
extern struct device * get_device_locked(struct device *);
@@ -20,6 +21,9 @@ extern void device_remove_dir(struct device * dev);
extern int bus_make_dir(struct bus_type * bus);
extern void bus_remove_dir(struct bus_type * bus);
+extern int bus_add_driver(struct device_driver *);
+extern void bus_remove_driver(struct device_driver *);
+
extern int driver_make_dir(struct device_driver * drv);
extern void driver_remove_dir(struct device_driver * drv);
@@ -48,9 +52,6 @@ extern int interface_add(struct device_class *, struct device *);
extern void interface_remove(struct device_class *, struct device *);
-extern int driver_attach(struct device_driver * drv);
-extern void driver_detach(struct device_driver * drv);
-
#ifdef CONFIG_HOTPLUG
extern int dev_hotplug(struct device *dev, const char *action);
#else
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7daffbfd9913..207270822e3c 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -43,28 +43,23 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
int (*callback)(struct device * dev, void * data))
{
struct list_head * node;
- struct device * prev = NULL;
int error = 0;
- get_bus(bus);
- spin_lock(&device_lock);
- list_for_each(node,&bus->devices) {
- struct device * dev = get_device_locked(to_dev(node));
- if (dev) {
- spin_unlock(&device_lock);
- error = callback(dev,data);
- if (prev)
- put_device(prev);
- prev = dev;
- spin_lock(&device_lock);
- if (error)
- break;
+ bus = get_bus(bus);
+ if (bus) {
+ down_read(&bus->rwsem);
+ list_for_each(node,&bus->devices) {
+ struct device * dev = get_device(to_dev(node));
+ if (dev) {
+ error = callback(dev,data);
+ put_device(dev);
+ if (error)
+ break;
+ }
}
+ up_read(&bus->rwsem);
+ put_bus(bus);
}
- spin_unlock(&device_lock);
- if (prev)
- put_device(prev);
- put_bus(bus);
return error;
}
@@ -72,33 +67,127 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
int (*callback)(struct device_driver * drv, void * data))
{
struct list_head * node;
- struct device_driver * prev = NULL;
int error = 0;
- /* pin bus in memory */
- get_bus(bus);
+ bus = get_bus(bus);
+ if (bus) {
+ down_read(&bus->rwsem);
+ list_for_each(node,&bus->drivers) {
+ struct device_driver * drv = get_driver(to_drv(node));
+ if (drv) {
+ error = callback(drv,data);
+ put_driver(drv);
+ if (error)
+ break;
+ }
+ }
+ up_read(&bus->rwsem);
+ put_bus(bus);
+ }
+ return error;
+}
- spin_lock(&device_lock);
- list_for_each(node,&bus->drivers) {
- struct device_driver * drv = get_driver(to_drv(node));
- if (drv) {
- spin_unlock(&device_lock);
- error = callback(drv,data);
- if (prev)
- put_driver(prev);
- prev = drv;
- spin_lock(&device_lock);
- if (error)
- break;
+static void attach(struct device * dev)
+{
+ pr_debug("bound device '%s' to driver '%s'\n",
+ dev->bus_id,dev->driver->name);
+ list_add_tail(&dev->driver_list,&dev->driver->devices);
+}
+
+static int bus_match(struct device * dev, struct device_driver * drv)
+{
+ int error = -ENODEV;
+ if (dev->bus->match(dev,drv)) {
+ dev->driver = drv;
+ if (drv->probe) {
+ if (!(error = drv->probe(dev)))
+ attach(dev);
+ else
+ dev->driver = NULL;
+ } else
+ attach(dev);
+ }
+ return error;
+}
+
+static int device_attach(struct device * dev)
+{
+ struct bus_type * bus = dev->bus;
+ struct list_head * entry;
+ int error = 0;
+
+ if (dev->driver) {
+ attach(dev);
+ return 0;
+ }
+
+ if (!bus->match)
+ return 0;
+
+ list_for_each(entry,&bus->drivers) {
+ struct device_driver * drv =
+ get_driver(container_of(entry,struct device_driver,bus_list));
+ if (!drv)
+ continue;
+ error = bus_match(dev,drv);
+ put_driver(drv);
+ if (!error)
+ break;
+ }
+ return error;
+}
+
+static int driver_attach(struct device_driver * drv)
+{
+ struct bus_type * bus = drv->bus;
+ struct list_head * entry;
+ int error = 0;
+
+ if (!bus->match)
+ return 0;
+
+ list_for_each(entry,&bus->devices) {
+ struct device * dev = container_of(entry,struct device,bus_list);
+ if (get_device(dev)) {
+ if (!dev->driver) {
+ if (!bus_match(dev,drv) && dev->driver)
+ devclass_add_device(dev);
+ }
+ put_device(dev);
}
}
- spin_unlock(&device_lock);
- if (prev)
- put_driver(prev);
- put_bus(bus);
return error;
}
+static void detach(struct device * dev, struct device_driver * drv)
+{
+ if (drv) {
+ list_del_init(&dev->driver_list);
+ devclass_remove_device(dev);
+ if (drv->remove)
+ drv->remove(dev);
+ dev->driver = NULL;
+ }
+}
+
+static void device_detach(struct device * dev)
+{
+ detach(dev,dev->driver);
+}
+
+static void driver_detach(struct device_driver * drv)
+{
+ struct list_head * entry, * next;
+ list_for_each_safe(entry,next,&drv->devices) {
+ struct device * dev = container_of(entry,struct device,driver_list);
+ if (get_device(dev)) {
+ detach(dev,drv);
+ put_device(dev);
+ }
+ }
+
+}
+
/**
* bus_add_device - add device to bus
* @dev: device being added
@@ -110,12 +199,13 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
*/
int bus_add_device(struct device * dev)
{
- if (dev->bus) {
- pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
- get_bus(dev->bus);
- spin_lock(&device_lock);
+ struct bus_type * bus = get_bus(dev->bus);
+ if (bus) {
+ down_write(&dev->bus->rwsem);
+ pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id);
list_add_tail(&dev->bus_list,&dev->bus->devices);
- spin_unlock(&device_lock);
+ device_attach(dev);
+ up_write(&dev->bus->rwsem);
device_bus_link(dev);
}
return 0;
@@ -131,17 +221,70 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
+ down_write(&dev->bus->rwsem);
+ pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id);
device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
+ device_detach(dev);
+ list_del_init(&dev->bus_list);
+ up_write(&dev->bus->rwsem);
put_bus(dev->bus);
}
}
+int bus_add_driver(struct device_driver * drv)
+{
+ struct bus_type * bus = get_bus(drv->bus);
+ if (bus) {
+ down_write(&bus->rwsem);
+ pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
+ list_add_tail(&drv->bus_list,&bus->drivers);
+ driver_attach(drv);
+ up_write(&bus->rwsem);
+ driver_make_dir(drv);
+ }
+ return 0;
+}
+
+void bus_remove_driver(struct device_driver * drv)
+{
+ if (drv->bus) {
+ down_write(&drv->bus->rwsem);
+ pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name);
+ driver_detach(drv);
+ list_del_init(&drv->bus_list);
+ up_write(&drv->bus->rwsem);
+ }
+}
+
+struct bus_type * get_bus(struct bus_type * bus)
+{
+ struct bus_type * ret = bus;
+ spin_lock(&device_lock);
+ if (bus && bus->present && atomic_read(&bus->refcount))
+ atomic_inc(&bus->refcount);
+ else
+ ret = NULL;
+ spin_unlock(&device_lock);
+ return ret;
+}
+
+void put_bus(struct bus_type * bus)
+{
+ if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
+ return;
+ list_del_init(&bus->node);
+ spin_unlock(&device_lock);
+ BUG_ON(bus->present);
+ bus_remove_dir(bus);
+}
+
int bus_register(struct bus_type * bus)
{
- rwlock_init(&bus->lock);
+ init_rwsem(&bus->rwsem);
INIT_LIST_HEAD(&bus->devices);
INIT_LIST_HEAD(&bus->drivers);
atomic_set(&bus->refcount,2);
+ bus->present = 1;
spin_lock(&device_lock);
list_add_tail(&bus->node,&bus_driver_list);
@@ -156,13 +299,14 @@ int bus_register(struct bus_type * bus)
return 0;
}
-void put_bus(struct bus_type * bus)
+void bus_unregister(struct bus_type * bus)
{
- if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
- return;
- list_del_init(&bus->node);
+ spin_lock(&device_lock);
+ bus->present = 0;
spin_unlock(&device_lock);
- bus_remove_dir(bus);
+
+ pr_debug("bus %s: unregistering\n",bus->name);
+ put_bus(bus);
}
EXPORT_SYMBOL(bus_for_each_dev);
@@ -170,4 +314,6 @@ EXPORT_SYMBOL(bus_for_each_drv);
EXPORT_SYMBOL(bus_add_device);
EXPORT_SYMBOL(bus_remove_device);
EXPORT_SYMBOL(bus_register);
+EXPORT_SYMBOL(bus_unregister);
+EXPORT_SYMBOL(get_bus);
EXPORT_SYMBOL(put_bus);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index dfef9793871a..7328f3231a65 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -10,27 +10,29 @@ static LIST_HEAD(class_list);
int devclass_add_driver(struct device_driver * drv)
{
- if (drv->devclass) {
- pr_debug("Registering driver %s:%s with class %s\n",
- drv->bus->name,drv->name,drv->devclass->name);
-
- spin_lock(&device_lock);
- list_add_tail(&drv->class_list,&drv->devclass->drivers);
- spin_unlock(&device_lock);
+ struct device_class * cls = get_devclass(drv->devclass);
+ if (cls) {
+ down_write(&cls->rwsem);
+ pr_debug("device class %s: adding driver %s:%s\n",
+ cls->name,drv->bus->name,drv->name);
+ list_add_tail(&drv->class_list,&cls->drivers);
devclass_drv_link(drv);
+ up_write(&cls->rwsem);
}
return 0;
}
void devclass_remove_driver(struct device_driver * drv)
{
- if (drv->devclass) {
- pr_debug("Removing driver %s:%s:%s\n",
- drv->devclass->name,drv->bus->name,drv->name);
- spin_lock(&device_lock);
+ struct device_class * cls = drv->devclass;
+ if (cls) {
+ down_write(&cls->rwsem);
+ pr_debug("device class %s: removing driver %s:%s\n",
+ cls->name,drv->bus->name,drv->name);
list_del_init(&drv->class_list);
- spin_unlock(&device_lock);
devclass_drv_unlink(drv);
+ up_write(&cls->rwsem);
+ put_devclass(cls);
}
}
@@ -38,9 +40,7 @@ void devclass_remove_driver(struct device_driver * drv)
static void enum_device(struct device_class * cls, struct device * dev)
{
u32 val;
- spin_lock(&device_lock);
val = cls->devnum++;
- spin_unlock(&device_lock);
dev->class_num = val;
devclass_dev_link(cls,dev);
}
@@ -51,18 +51,44 @@ static void unenum_device(struct device_class * cls, struct device * dev)
dev->class_num = 0;
}
+/**
+ * devclass_add_device - register device with device class
+ * @dev: device to be registered
+ *
+ * This is called when a device is either registered with the
+ * core, or after the a driver module is loaded and bound to
+ * the device.
+ * The class is determined by looking at @dev's driver, so one
+ * way or another, it must be bound to something. Once the
+ * class is determined, it's set to prevent against concurrent
+ * calls for the same device stomping on each other.
+ *
+ * /sbin/hotplug should be called once the device is added to
+ * class and all the interfaces.
+ */
int devclass_add_device(struct device * dev)
{
- struct device_class * cls = dev->driver->devclass;
+ struct device_class * cls;
int error = 0;
- if (cls) {
- pr_debug("adding device '%s' to class '%s'\n",
- dev->name,cls->name);
- if (cls->add_device)
- error = cls->add_device(dev);
- if (!error) {
- enum_device(cls,dev);
- interface_add(cls,dev);
+
+ if (dev->driver) {
+ cls = get_devclass(dev->driver->devclass);
+ if (cls) {
+ down_write(&cls->rwsem);
+ pr_debug("device class %s: adding device %s\n",
+ cls->name,dev->name);
+ if (cls->add_device)
+ error = cls->add_device(dev);
+ if (!error) {
+ enum_device(cls,dev);
+ interface_add(cls,dev);
+ }
+
+ /* notify userspace (call /sbin/hotplug) here */
+
+ up_write(&cls->rwsem);
+ if (error)
+ put_devclass(cls);
}
}
return error;
@@ -70,40 +96,74 @@ int devclass_add_device(struct device * dev)
void devclass_remove_device(struct device * dev)
{
- struct device_class * cls = dev->driver->devclass;
- if (cls) {
- pr_debug("removing device '%s' from class '%s'\n",
- dev->name,cls->name);
- interface_remove(cls,dev);
- unenum_device(cls,dev);
- if (cls->remove_device)
- cls->remove_device(dev);
+ struct device_class * cls;
+
+ if (dev->driver) {
+ cls = dev->driver->devclass;
+ if (cls) {
+ down_write(&cls->rwsem);
+ pr_debug("device class %s: removing device %s\n",
+ cls->name,dev->name);
+ interface_remove(cls,dev);
+ unenum_device(cls,dev);
+ if (cls->remove_device)
+ cls->remove_device(dev);
+ up_write(&cls->rwsem);
+ put_devclass(cls);
+ }
}
}
+struct device_class * get_devclass(struct device_class * cls)
+{
+ struct device_class * ret = cls;
+ spin_lock(&device_lock);
+ if (cls && cls->present && atomic_read(&cls->refcount) > 0)
+ atomic_inc(&cls->refcount);
+ else
+ ret = NULL;
+ spin_unlock(&device_lock);
+ return ret;
+}
+
+void put_devclass(struct device_class * cls)
+{
+ if (atomic_dec_and_lock(&cls->refcount,&device_lock)) {
+ list_del_init(&cls->node);
+ spin_unlock(&device_lock);
+ devclass_remove_dir(cls);
+ }
+}
+
+
int devclass_register(struct device_class * cls)
{
INIT_LIST_HEAD(&cls->drivers);
INIT_LIST_HEAD(&cls->intf_list);
-
- pr_debug("registering device class '%s'\n",cls->name);
+ init_rwsem(&cls->rwsem);
+ atomic_set(&cls->refcount,2);
+ cls->present = 1;
+ pr_debug("device class '%s': registering\n",cls->name);
spin_lock(&device_lock);
list_add_tail(&cls->node,&class_list);
spin_unlock(&device_lock);
devclass_make_dir(cls);
+ put_devclass(cls);
return 0;
}
void devclass_unregister(struct device_class * cls)
{
- pr_debug("unregistering device class '%s'\n",cls->name);
- devclass_remove_dir(cls);
spin_lock(&device_lock);
- list_del_init(&class_list);
+ cls->present = 0;
spin_unlock(&device_lock);
+ pr_debug("device class '%s': unregistering\n",cls->name);
+ put_devclass(cls);
}
EXPORT_SYMBOL(devclass_register);
EXPORT_SYMBOL(devclass_unregister);
+EXPORT_SYMBOL(get_devclass);
+EXPORT_SYMBOL(put_devclass);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 83c31723d844..bd82a792d877 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -19,136 +19,12 @@ LIST_HEAD(global_device_list);
int (*platform_notify)(struct device * dev) = NULL;
int (*platform_notify_remove)(struct device * dev) = NULL;
+DECLARE_MUTEX(device_sem);
+
spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
#define to_dev(node) container_of(node,struct device,driver_list)
-static int probe(struct device * dev, struct device_driver * drv)
-{
- dev->driver = drv;
- return drv->probe ? drv->probe(dev) : 0;
-}
-
-static void attach(struct device * dev)
-{
- spin_lock(&device_lock);
- list_add_tail(&dev->driver_list,&dev->driver->devices);
- spin_unlock(&device_lock);
- devclass_add_device(dev);
-}
-
-/**
- * found_match - do actual binding of device to driver
- * @dev: device
- * @drv: driver
- *
- * We're here because the bus's match callback returned success for this
- * pair. We call the driver's probe callback to verify they're really a
- * match made in heaven.
- *
- * In the future, we may want to notify userspace of the binding. (But,
- * we might not want to do it here).
- *
- * We may also want to create a symlink in the driver's directory to the
- * device's physical directory.
- */
-static int found_match(struct device * dev, struct device_driver * drv)
-{
- int error = 0;
-
- if (!(error = probe(dev,get_driver(drv)))) {
- pr_debug("bound device '%s' to driver '%s'\n",
- dev->bus_id,drv->name);
- attach(dev);
- } else {
- put_driver(drv);
- dev->driver = NULL;
- }
- return error;
-}
-
-/**
- * device_attach - try to associated device with a driver
- * @drv: current driver to try
- * @data: device in disguise
- *
- * This function is used as a callback to bus_for_each_drv.
- * It calls the bus's match callback to check if the driver supports
- * the device. If so, it calls the found_match() function above to
- * take care of all the details.
- */
-static int do_device_attach(struct device_driver * drv, void * data)
-{
- struct device * dev = (struct device *)data;
- int error = 0;
-
- if (drv->bus->match && drv->bus->match(dev,drv))
- error = found_match(dev,drv);
- return error;
-}
-
-static int device_attach(struct device * dev)
-{
- int error = 0;
- if (!dev->driver) {
- if (dev->bus)
- error = bus_for_each_drv(dev->bus,dev,do_device_attach);
- } else
- attach(dev);
- return error;
-}
-
-static void device_detach(struct device * dev)
-{
- struct device_driver * drv = dev->driver;
-
- if (drv) {
- devclass_remove_device(dev);
- if (drv && drv->remove)
- drv->remove(dev);
- dev->driver = NULL;
- }
-}
-
-static int do_driver_attach(struct device * dev, void * data)
-{
- struct device_driver * drv = (struct device_driver *)data;
- int error = 0;
-
- if (!dev->driver) {
- if (dev->bus->match && dev->bus->match(dev,drv))
- error = found_match(dev,drv);
- }
- return error;
-}
-
-int driver_attach(struct device_driver * drv)
-{
- return bus_for_each_dev(drv->bus,drv,do_driver_attach);
-}
-
-void driver_detach(struct device_driver * drv)
-{
- struct list_head * node;
- struct device * prev = NULL;
-
- spin_lock(&device_lock);
- list_for_each(node,&drv->devices) {
- struct device * dev = get_device_locked(to_dev(node));
- if (dev) {
- if (prev)
- list_del_init(&prev->driver_list);
- spin_unlock(&device_lock);
- device_detach(dev);
- if (prev)
- put_device(prev);
- prev = dev;
- spin_lock(&device_lock);
- }
- }
- spin_unlock(&device_lock);
-}
-
int device_add(struct device *dev)
{
int error;
@@ -156,14 +32,14 @@ int device_add(struct device *dev)
if (!dev || !strlen(dev->bus_id))
return -EINVAL;
- spin_lock(&device_lock);
- dev->present = 1;
+ down(&device_sem);
+ dev->state = DEVICE_REGISTERED;
if (dev->parent) {
list_add_tail(&dev->g_list,&dev->parent->g_list);
list_add_tail(&dev->node,&dev->parent->children);
} else
list_add_tail(&dev->g_list,&global_device_list);
- spin_unlock(&device_lock);
+ up(&device_sem);
pr_debug("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
@@ -173,9 +49,6 @@ int device_add(struct device *dev)
bus_add_device(dev);
- /* bind to driver */
- device_attach(dev);
-
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
@@ -183,12 +56,13 @@ int device_add(struct device *dev)
/* notify userspace of device entry */
dev_hotplug(dev, "add");
+ devclass_add_device(dev);
register_done:
if (error) {
- spin_lock(&device_lock);
+ up(&device_sem);
list_del_init(&dev->g_list);
list_del_init(&dev->node);
- spin_unlock(&device_lock);
+ up(&device_sem);
}
return error;
}
@@ -203,6 +77,7 @@ void device_initialize(struct device *dev)
INIT_LIST_HEAD(&dev->intf_list);
spin_lock_init(&dev->lock);
atomic_set(&dev->refcount,1);
+ dev->state = DEVICE_INITIALIZED;
if (dev->parent)
get_device(dev->parent);
}
@@ -234,22 +109,15 @@ int device_register(struct device *dev)
return error;
}
-struct device * get_device_locked(struct device * dev)
+struct device * get_device(struct device * dev)
{
struct device * ret = dev;
- if (dev && dev->present && atomic_read(&dev->refcount) > 0)
+ down(&device_sem);
+ if (device_present(dev) && atomic_read(&dev->refcount) > 0)
atomic_inc(&dev->refcount);
else
ret = NULL;
- return ret;
-}
-
-struct device * get_device(struct device * dev)
-{
- struct device * ret;
- spin_lock(&device_lock);
- ret = get_device_locked(dev);
- spin_unlock(&device_lock);
+ up(&device_sem);
return ret;
}
@@ -259,34 +127,23 @@ struct device * get_device(struct device * dev)
*/
void put_device(struct device * dev)
{
- struct device * parent;
- if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
+ down(&device_sem);
+ if (!atomic_dec_and_test(&dev->refcount)) {
+ up(&device_sem);
return;
- parent = dev->parent;
- dev->parent = NULL;
- spin_unlock(&device_lock);
+ }
+ list_del_init(&dev->node);
+ list_del_init(&dev->g_list);
+ up(&device_sem);
- BUG_ON(dev->present);
+ BUG_ON((dev->state != DEVICE_GONE));
- if (dev->release)
- dev->release(dev);
-
- if (parent)
- put_device(parent);
+ device_del(dev);
}
void device_del(struct device * dev)
{
- spin_lock(&device_lock);
- dev->present = 0;
- list_del_init(&dev->node);
- list_del_init(&dev->g_list);
- list_del_init(&dev->bus_list);
- list_del_init(&dev->driver_list);
- spin_unlock(&device_lock);
-
- pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
- dev->bus_id,dev->name);
+ struct device * parent = dev->parent;
/* Notify the platform of the removal, in case they
* need to do anything...
@@ -297,11 +154,16 @@ void device_del(struct device * dev)
/* notify userspace that this device is about to disappear */
dev_hotplug (dev, "remove");
- device_detach(dev);
bus_remove_device(dev);
/* remove the driverfs directory */
device_remove_dir(dev);
+
+ if (dev->release)
+ dev->release(dev);
+
+ if (parent)
+ put_device(parent);
}
/**
@@ -315,22 +177,15 @@ void device_del(struct device * dev)
*/
void device_unregister(struct device * dev)
{
- device_del(dev);
- put_device(dev);
-}
-
-static int __init device_init(void)
-{
- int error;
+ down(&device_sem);
+ dev->state = DEVICE_GONE;
+ up(&device_sem);
- error = init_driverfs_fs();
- if (error)
- panic("DEV: could not initialize driverfs");
- return 0;
+ pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
+ dev->bus_id,dev->name);
+ put_device(dev);
}
-core_initcall(device_init);
-
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(device_unregister);
EXPORT_SYMBOL(get_device);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 221e525736bd..4bf4a005b918 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -16,29 +16,61 @@ int driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device *, void * ))
{
struct list_head * node;
- struct device * prev = NULL;
int error = 0;
- get_driver(drv);
- spin_lock(&device_lock);
- list_for_each(node,&drv->devices) {
- struct device * dev = get_device_locked(to_dev(node));
- if (dev) {
- spin_unlock(&device_lock);
- error = callback(dev,data);
- if (prev)
- put_device(prev);
- prev = dev;
- spin_lock(&device_lock);
- if (error)
- break;
+ drv = get_driver(drv);
+ if (drv) {
+ down_read(&drv->bus->rwsem);
+ list_for_each(node,&drv->devices) {
+ struct device * dev = get_device(to_dev(node));
+ if (dev) {
+ error = callback(dev,data);
+ put_device(dev);
+ if (error)
+ break;
+ }
}
+ up_read(&drv->bus->rwsem);
+ put_driver(drv);
}
- spin_unlock(&device_lock);
- put_driver(drv);
return error;
}
+struct device_driver * get_driver(struct device_driver * drv)
+{
+ struct device_driver * ret = drv;
+ spin_lock(&device_lock);
+ if (drv && drv->present && atomic_read(&drv->refcount) > 0)
+ atomic_inc(&drv->refcount);
+ else
+ ret = NULL;
+ spin_unlock(&device_lock);
+ return ret;
+}
+
+
+void remove_driver(struct device_driver * drv)
+{
+ BUG();
+}
+
+/**
+ * put_driver - decrement driver's refcount and clean up if necessary
+ * @drv: driver in question
+ */
+void put_driver(struct device_driver * drv)
+{
+ struct bus_type * bus = drv->bus;
+ if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
+ return;
+ spin_unlock(&device_lock);
+ BUG_ON(drv->present);
+ bus_remove_driver(drv);
+ if (drv->release)
+ drv->release(drv);
+ put_bus(bus);
+}
+
/**
* driver_register - register driver with bus
* @drv: driver to register
@@ -50,54 +82,29 @@ int driver_register(struct device_driver * drv)
if (!drv->bus)
return -EINVAL;
- pr_debug("Registering driver '%s' with bus '%s'\n",drv->name,drv->bus->name);
+ pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name);
get_bus(drv->bus);
atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock);
INIT_LIST_HEAD(&drv->devices);
- spin_lock(&device_lock);
- list_add(&drv->bus_list,&drv->bus->drivers);
- spin_unlock(&device_lock);
- driver_make_dir(drv);
- driver_attach(drv);
+ drv->present = 1;
+ bus_add_driver(drv);
put_driver(drv);
return 0;
}
-static void __remove_driver(struct device_driver * drv)
-{
- pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
- driver_detach(drv);
- driver_remove_dir(drv);
- if (drv->release)
- drv->release(drv);
- put_bus(drv->bus);
-}
-
-void remove_driver(struct device_driver * drv)
+void driver_unregister(struct device_driver * drv)
{
spin_lock(&device_lock);
- atomic_set(&drv->refcount,0);
- list_del_init(&drv->bus_list);
+ drv->present = 0;
spin_unlock(&device_lock);
- __remove_driver(drv);
-}
-
-/**
- * put_driver - decrement driver's refcount and clean up if necessary
- * @drv: driver in question
- */
-void put_driver(struct device_driver * drv)
-{
- if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
- return;
- list_del_init(&drv->bus_list);
- spin_unlock(&device_lock);
- __remove_driver(drv);
+ pr_debug("driver %s:%s: unregistering\n",drv->bus->name,drv->name);
+ put_driver(drv);
}
EXPORT_SYMBOL(driver_for_each_dev);
EXPORT_SYMBOL(driver_register);
+EXPORT_SYMBOL(driver_unregister);
+EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver);
-EXPORT_SYMBOL(remove_driver);
diff --git a/drivers/base/interface.c b/drivers/base/interface.c
index a585b729c5c4..8a5c6e6bc226 100644
--- a/drivers/base/interface.c
+++ b/drivers/base/interface.c
@@ -19,7 +19,7 @@ static DEVICE_ATTR(name,S_IRUGO,device_read_name,NULL);
static ssize_t
device_read_power(struct device * dev, char * page, size_t count, loff_t off)
{
- return off ? 0 : sprintf(page,"%d\n",dev->current_state);
+ return off ? 0 : sprintf(page,"%d\n",dev->power_state);
}
static ssize_t
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 29c90e34e67e..3856bc52b411 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -39,7 +39,7 @@ int platform_device_register(struct platform_device * pdev)
void platform_device_unregister(struct platform_device * pdev)
{
if (pdev)
- put_device(&pdev->dev);
+ device_unregister(&pdev->dev);
}
static int platform_match(struct device * dev, struct device_driver * drv)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index c98984dfd8ab..176be19b72d1 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -8,6 +8,8 @@
*
*/
+#define DEBUG 0
+
#include <linux/device.h>
#include <linux/module.h>
#include "base.h"
@@ -28,34 +30,21 @@
int device_suspend(u32 state, u32 level)
{
struct list_head * node;
- struct device * prev = NULL;
int error = 0;
- if(level == SUSPEND_POWER_DOWN)
- printk(KERN_EMERG "Shutting down devices\n");
- else
- printk(KERN_EMERG "Suspending devices\n");
+ printk(KERN_EMERG "Suspending devices\n");
- spin_lock(&device_lock);
+ down(&device_sem);
list_for_each(node,&global_device_list) {
- struct device * dev = get_device_locked(to_dev(node));
- if (dev) {
- spin_unlock(&device_lock);
- if(dev->driver) {
- if(level == SUSPEND_POWER_DOWN) {
- if(dev->driver->remove)
- dev->driver->remove(dev);
- } else if(dev->driver->suspend)
- error = dev->driver->suspend(dev,state,level);
- }
- if (prev)
- put_device(prev);
- prev = dev;
- spin_lock(&device_lock);
+ struct device * dev = to_dev(node);
+ if (device_present(dev) && dev->driver && dev->driver->suspend) {
+ pr_debug("suspending device %s\n",dev->name);
+ error = dev->driver->suspend(dev,state,level);
+ if (error)
+ printk(KERN_ERR "%s: suspend returned %d\n",dev->name,error);
}
}
- spin_unlock(&device_lock);
-
+ up(&device_sem);
return error;
}
@@ -70,33 +59,38 @@ int device_suspend(u32 state, u32 level)
void device_resume(u32 level)
{
struct list_head * node;
- struct device * prev = NULL;
- spin_lock(&device_lock);
+ down(&device_sem);
list_for_each_prev(node,&global_device_list) {
- struct device * dev = get_device_locked(to_dev(node));
- if (dev) {
- spin_unlock(&device_lock);
- if (dev->driver && dev->driver->resume)
- dev->driver->resume(dev,level);
- if (prev)
- put_device(prev);
- prev = dev;
- spin_lock(&device_lock);
+ struct device * dev = to_dev(node);
+ if (device_present(dev) && dev->driver && dev->driver->resume) {
+ pr_debug("resuming device %s\n",dev->name);
+ dev->driver->resume(dev,level);
}
}
- spin_unlock(&device_lock);
+ up(&device_sem);
printk(KERN_EMERG "Devices Resumed\n");
}
/**
- * device_shutdown - call device_suspend with status set to shutdown, to
- * cause all devices to remove themselves cleanly
+ * device_shutdown - call ->remove() on each device to shutdown.
*/
void device_shutdown(void)
{
- device_suspend(4, SUSPEND_POWER_DOWN);
+ struct list_head * entry;
+
+ printk(KERN_EMERG "Shutting down devices\n");
+
+ down(&device_sem);
+ list_for_each(entry,&global_device_list) {
+ struct device * dev = to_dev(entry);
+ if (device_present(dev) && dev->driver && dev->driver->shutdown) {
+ pr_debug("shutting down %s\n",dev->name);
+ dev->driver->shutdown(dev);
+ }
+ }
+ up(&device_sem);
}
EXPORT_SYMBOL(device_suspend);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index a61fea973d36..cd681d1190bd 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -10,6 +10,8 @@
* add themselves as children of the system bus.
*/
+#define DEBUG 1
+
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -76,8 +78,8 @@ int sys_register_root(struct sys_root * root)
*/
void sys_unegister_root(struct sys_root * root)
{
- put_device(&root->sysdev);
- put_device(&root->dev);
+ device_unregister(&root->sysdev);
+ device_unregister(&root->dev);
}
/**
@@ -125,7 +127,7 @@ int sys_device_register(struct sys_device * sysdev)
void sys_device_unregister(struct sys_device * sysdev)
{
if (sysdev)
- put_device(&sysdev->dev);
+ device_unregister(&sysdev->dev);
}
struct bus_type system_bus_type = {
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 1c1a72e440e6..dca532fef7a2 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -75,18 +75,18 @@ static DAC960_Controller_T
*DAC960_Controllers[DAC960_MaxControllers] = { NULL };
-static int DAC960_revalidate(kdev_t);
+static int DAC960_revalidate(struct gendisk *);
/*
DAC960_BlockDeviceOperations is the Block Device Operations structure for
DAC960 Logical Disk Devices.
*/
static struct block_device_operations DAC960_BlockDeviceOperations = {
- owner: THIS_MODULE,
- open: DAC960_Open,
- release: DAC960_Release,
- ioctl: DAC960_IOCTL,
- revalidate: DAC960_revalidate,
+ .owner = THIS_MODULE,
+ .open = DAC960_Open,
+ .release = DAC960_Release,
+ .ioctl = DAC960_IOCTL,
+ .revalidate_disk= DAC960_revalidate,
};
@@ -308,9 +308,9 @@ static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
{
- spin_unlock_irq(Controller->RequestQueue->queue_lock);
+ spin_unlock_irq(Controller->RequestQueue.queue_lock);
__wait_event(Controller->CommandWaitQueue, Controller->FreeCommands);
- spin_lock_irq(Controller->RequestQueue->queue_lock);
+ spin_lock_irq(Controller->RequestQueue.queue_lock);
}
@@ -1931,7 +1931,6 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
{
int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
RequestQueue_T *RequestQueue;
- int MinorNumber;
int n;
/*
@@ -1947,7 +1946,7 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
/*
Initialize the I/O Request Queue.
*/
- RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber);
+ RequestQueue = &Controller->RequestQueue;
Controller->queue_lock = SPIN_LOCK_UNLOCKED;
blk_init_queue(RequestQueue, DAC960_RequestFunction, &Controller->queue_lock);
RequestQueue->queuedata = Controller;
@@ -1956,7 +1955,6 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
blk_queue_max_phys_segments(RequestQueue, ~0);
blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
- Controller->RequestQueue = RequestQueue;
for (n = 0; n < DAC960_MaxLogicalDrives; n++) {
struct gendisk *disk = Controller->disks[n];
sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n);
@@ -1989,7 +1987,7 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
/*
Remove the I/O Request Queue.
*/
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MajorNumber));
+ blk_cleanup_queue(&Controller->RequestQueue);
}
static long disk_size(DAC960_Controller_T *Controller, int disk)
@@ -2019,12 +2017,16 @@ static void DAC960_ComputeGenericDiskInfo(DAC960_Controller_T *Controller)
set_capacity(Controller->disks[disk], disk_size(Controller, disk));
}
-static int DAC960_revalidate(kdev_t dev)
+static int DAC960_revalidate(struct gendisk *disk)
{
- int ctlr = DAC960_ControllerNumber(dev);
- int disk = DAC960_LogicalDriveNumber(dev);
- DAC960_Controller_T *p = DAC960_Controllers[ctlr];
- set_capacity(p->disks[disk], disk_size(p, disk));
+ DAC960_Controller_T *p = disk->private_data;
+ int unit;
+ for (unit = 0; unit < DAC960_MaxLogicalDrives; unit++) {
+ if (p->disks[unit] == disk) {
+ set_capacity(disk, disk_size(p, unit));
+ return 0;
+ }
+ }
return 0;
}
@@ -2093,6 +2095,7 @@ static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
{
void (*InterruptHandler)(int, void *, Registers_T *) = NULL;
+ DAC960_Controller_T *Controller = NULL;
DAC960_FirmwareType_T FirmwareType = 0;
unsigned short VendorID = 0, DeviceID = 0;
unsigned int MemoryWindowSize = 0;
@@ -2145,7 +2148,6 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
}
while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
{
- DAC960_Controller_T *Controller = NULL;
DAC960_IO_Address_T IO_Address = 0;
DAC960_PCI_Address_T PCI_Address = 0;
unsigned char Bus = PCI_Device->bus->number;
@@ -2155,6 +2157,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
unsigned char ErrorStatus, Parameter0, Parameter1;
unsigned int IRQ_Channel = PCI_Device->irq;
void *BaseAddress;
+ Controller = NULL;
if (pci_enable_device(PCI_Device) != 0) continue;
switch (HardwareType)
{
@@ -2202,6 +2205,8 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
if (!Controller->disks[i])
goto Enomem;
+ Controller->disks[i]->private_data = Controller;
+ Controller->disks[i]->queue = &Controller->RequestQueue;
}
Controller->ControllerNumber = DAC960_ControllerCount;
init_waitqueue_head(&Controller->CommandWaitQueue);
@@ -2831,7 +2836,7 @@ static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command)
static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
boolean WaitForCommand)
{
- RequestQueue_T *RequestQueue = Controller->RequestQueue;
+ RequestQueue_T *RequestQueue = &Controller->RequestQueue;
ListHead_T *RequestQueueHead;
IO_Request_T *Request;
DAC960_Command_T *Command;
@@ -5225,7 +5230,6 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
}
}
-
/*
DAC960_Open is the Device Open Function for the DAC960 Driver.
*/
@@ -5265,9 +5269,8 @@ static int DAC960_Open(Inode_T *Inode, File_T *File)
long size;
Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
size = disk_size(Controller, LogicalDriveNumber);
- /* BROKEN, same as modular ide-floppy/ide-disk; same fix - ->probe() */
set_capacity(Controller->disks[LogicalDriveNumber], size);
- add_disk(Controller->disks[LogicalDriveNumber]);
+ Inode->i_bdev->bd_invalidated = 1;
}
if (!get_capacity(Controller->disks[LogicalDriveNumber]))
return -ENXIO;
@@ -5314,7 +5317,6 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
DiskGeometry_T Geometry, *UserGeometry;
DAC960_Controller_T *Controller;
- int res;
if (File != NULL && (File->f_flags & O_NONBLOCK))
return DAC960_UserIOCTL(Inode, File, Request, Argument);
@@ -5379,7 +5381,7 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
unsigned int Request, unsigned long Argument)
{
- int ErrorCode;
+ int ErrorCode = 0;
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
switch (Request)
{
@@ -5492,11 +5494,11 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
while (Controller->V1.DirectCommandActive[DCDB.Channel]
[DCDB.TargetID])
{
- spin_unlock_irq(Controller->RequestQueue->queue_lock);
+ spin_unlock_irq(Controller->RequestQueue.queue_lock);
__wait_event(Controller->CommandWaitQueue,
!Controller->V1.DirectCommandActive
[DCDB.Channel][DCDB.TargetID]);
- spin_lock_irq(Controller->RequestQueue->queue_lock);
+ spin_lock_irq(Controller->RequestQueue.queue_lock);
}
Controller->V1.DirectCommandActive[DCDB.Channel]
[DCDB.TargetID] = true;
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index fcc3ac714542..e66cd95f87dd 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -2364,7 +2364,7 @@ typedef struct DAC960_Controller
DAC960_Command_T *FreeCommands;
unsigned char *CombinedStatusBuffer;
unsigned char *CurrentStatusBuffer;
- RequestQueue_T *RequestQueue;
+ RequestQueue_T RequestQueue;
spinlock_t queue_lock;
WaitQueue_T CommandWaitQueue;
WaitQueue_T HealthStatusWaitQueue;
@@ -2504,7 +2504,7 @@ static inline
void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
ProcessorFlags_T *ProcessorFlags)
{
- spin_lock_irqsave(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+ spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
}
@@ -2516,7 +2516,7 @@ static inline
void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
ProcessorFlags_T *ProcessorFlags)
{
- spin_unlock_irqrestore(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+ spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
}
@@ -2553,7 +2553,7 @@ static inline
void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
ProcessorFlags_T *ProcessorFlags)
{
- spin_lock_irqsave(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+ spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
}
@@ -2566,7 +2566,7 @@ static inline
void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
ProcessorFlags_T *ProcessorFlags)
{
- spin_unlock_irqrestore(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+ spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
}
#error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 520eeabab869..8b3daa5771c6 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -45,7 +45,6 @@
#define MAJOR_NR ACSI_MAJOR
#define DEVICE_NAME "ACSI"
-#define DEVICE_NR(device) (minor(device) >> 4)
#include <linux/config.h>
#include <linux/module.h>
@@ -59,6 +58,7 @@
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/major.h>
+#define QUEUE (&acsi_queue)
#include <linux/blk.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -80,6 +80,7 @@ typedef void Scsi_Device; /* hack to avoid including scsi.h */
#include <asm/atari_stram.h>
static void (*do_acsi)(void) = NULL;
+static struct request_queue acsi_queue;
#define DEBUG
#undef DEBUG_DETECT
@@ -119,6 +120,7 @@ struct acsi_info_struct {
unsigned old_atari_disk : 1; /* Is an old Atari disk */
unsigned changed : 1; /* Medium has been changed */
unsigned long size; /* #blocks */
+ int access_count;
} acsi_info[MAX_DEV];
/*
@@ -232,8 +234,8 @@ typedef union {
/* Default size if capacity cannot be determined (1 GByte) */
#define DEFAULT_SIZE 0x1fffff
-#define CARTRCH_STAT(dev,buf) \
- (acsi_info[(dev)].old_atari_disk ? \
+#define CARTRCH_STAT(aip,buf) \
+ (aip->old_atari_disk ? \
(((buf)[0] & 0x7f) == 0x28) : \
((((buf)[0] & 0x70) == 0x70) ? \
(((buf)[2] & 0x0f) == 0x06) : \
@@ -245,7 +247,6 @@ char *acsi_buffer;
unsigned long phys_acsi_buffer;
static int NDevices;
-static int access_count[MAX_DEV];
static int CurrentNReq;
static int CurrentNSect;
@@ -348,7 +349,7 @@ struct acsi_error {
static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
rwflag, int enable);
static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error( const unsigned char *errblk, int dev );
+static void acsi_print_error(const unsigned char *errblk, int struct acsi_info_struct *aip);
static void acsi_interrupt (int irq, void *data, struct pt_regs *fp);
static void unexpected_acsi_interrupt( void );
static void bad_rw_intr( void );
@@ -364,10 +365,10 @@ static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg );
static int acsi_open( struct inode * inode, struct file * filp );
static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal( int target, int flag );
+static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
static int acsi_change_blk_size( int target, int lun);
static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (kdev_t);
+static int acsi_revalidate (struct gendisk *disk);
/************************* End of Prototypes **************************/
@@ -691,12 +692,12 @@ int acsi_extcmd( unsigned char *buffer, int cnt )
#endif
-static void acsi_print_error( const unsigned char *errblk, int dev )
+static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
{ int atari_err, i, errcode;
struct acsi_error *arr;
- atari_err = acsi_info[dev].old_atari_disk;
+ atari_err = aip->old_atari_disk;
if (atari_err)
errcode = errblk[0] & 0x7f;
else
@@ -780,15 +781,15 @@ static void read_intr( void )
status = acsi_getstatus();
if (status != 0) {
- int dev = DEVICE_NR(CURRENT->rq_dev);
- printk( KERN_ERR "ad%c: ", dev+'a' );
- if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target,
- acsi_info[dev].lun))
+ struct gendisk *disk = CURRENT->rq_disk;
+ struct acsi_info_struct *aip = disk->private_data;
+ printk(KERN_ERR "%s: ", disk->disk_name);
+ if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
else {
- acsi_print_error( acsi_buffer, dev );
- if (CARTRCH_STAT( dev, acsi_buffer ))
- acsi_info[dev].changed = 1;
+ acsi_print_error(acsi_buffer, aip);
+ if (CARTRCH_STAT(aip, acsi_buffer))
+ aip->changed = 1;
}
ENABLE_IRQ();
bad_rw_intr();
@@ -811,15 +812,15 @@ static void write_intr(void)
status = acsi_getstatus();
if (status != 0) {
- int dev = DEVICE_NR(CURRENT->rq_dev);
- printk( KERN_ERR "ad%c: ", dev+'a' );
- if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target,
- acsi_info[dev].lun))
+ struct gendisk *disk = CURRENT->rq_disk;
+ struct acsi_info_struct *aip = disk->private_data;
+ printk( KERN_ERR "%s: ", disk->disk_name);
+ if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
else {
- acsi_print_error( acsi_buffer, dev );
- if (CARTRCH_STAT( dev, acsi_buffer ))
- acsi_info[dev].changed = 1;
+ acsi_print_error(acsi_buffer, aip);
+ if (CARTRCH_STAT(aip, acsi_buffer))
+ aip->changed = 1;
}
bad_rw_intr();
redo_acsi_request();
@@ -944,11 +945,13 @@ static void do_acsi_request( request_queue_t * q )
static void redo_acsi_request( void )
-
-{ unsigned block, dev, target, lun, nsect;
+{
+ unsigned block, target, lun, nsect;
char *buffer;
unsigned long pbuffer;
struct buffer_head *bh;
+ struct gendisk *disk;
+ struct acsi_info_struct *aip;
repeat:
CLEAR_TIMER();
@@ -963,35 +966,33 @@ static void redo_acsi_request( void )
return;
}
- if (major(CURRENT->rq_dev) != MAJOR_NR)
- panic(DEVICE_NAME ": request list destroyed");
+ disk = CURRENT->rq_disk;
+ aip = disk->private_data;
if (CURRENT->bh) {
if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
panic(DEVICE_NAME ": block not locked");
}
- dev = DEVICE_NR(CURRENT->rq_dev);
block = CURRENT->sector;
- if (dev >= NDevices ||
- block+CURRENT->nr_sectors >= get_capacity(acsi_gendisk[dev])) {
+ if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
#ifdef DEBUG
- printk( "ad%c: attempted access for blocks %d...%ld past end of device at block %ld.\n",
- dev+'a',
+ printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
+ disk->disk_name,
block, block + CURRENT->nr_sectors - 1,
- get_capacity(acsi_gendisk[dev]));
+ get_capacity(disk));
#endif
end_request(CURRENT, 0);
goto repeat;
}
- if (acsi_info[dev].changed) {
- printk( KERN_NOTICE "ad%c: request denied because cartridge has "
- "been changed.\n", dev+'a' );
+ if (aip->changed) {
+ printk( KERN_NOTICE "%s: request denied because cartridge has "
+ "been changed.\n", disk->disk_name);
end_request(CURRENT, 0);
goto repeat;
}
- target = acsi_info[dev].target;
- lun = acsi_info[dev].lun;
+ target = aip->target;
+ lun = aip->lun;
/* Find out how many sectors should be transferred from/to
* consecutive buffers and thus can be done with a single command.
@@ -1085,7 +1086,8 @@ static void redo_acsi_request( void )
static int acsi_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
{
- int dev = DEVICE_NR(inode->i_rdev);
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct acsi_info_struct *aip = disk->private_data;
switch (cmd) {
case HDIO_GETGEO:
/* HDIO_GETGEO is supported more for getting the partition's
@@ -1095,13 +1097,13 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
* easy, use Adaptec's usual 64/32 mapping */
put_user( 64, &geo->heads );
put_user( 32, &geo->sectors );
- put_user( acsi_info[dev].size >> 11, &geo->cylinders );
+ put_user( aip->size >> 11, &geo->cylinders );
put_user(get_start_sect(inode->i_bdev), &geo->start);
return 0;
}
case SCSI_IOCTL_GET_IDLUN:
/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
- put_user( acsi_info[dev].target | (acsi_info[dev].lun << 8),
+ put_user( aip->target | (aip->lun << 8),
&((Scsi_Idlun *) arg)->dev_id );
put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
return 0;
@@ -1128,19 +1130,19 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
static int acsi_open( struct inode * inode, struct file * filp )
{
- int device = DEVICE_NR(inode->i_rdev);
- struct acsi_info_struct *aip = &acsi_info[device];
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct acsi_info_struct *aip = disk->private_data;
- if (access_count[device] == 0 && aip->removable) {
+ if (aip->access_count == 0 && aip->removable) {
#if 0
aip->changed = 1; /* safety first */
#endif
check_disk_change( inode->i_bdev );
if (aip->changed) /* revalidate was not successful (no medium) */
return -ENXIO;
- acsi_prevent_removal(device, 1);
+ acsi_prevent_removal(aip, 1);
}
- access_count[device]++;
+ aip->access_count++;
if (filp && filp->f_mode) {
check_disk_change( inode->i_bdev );
@@ -1162,9 +1164,10 @@ static int acsi_open( struct inode * inode, struct file * filp )
static int acsi_release( struct inode * inode, struct file * file )
{
- int device = DEVICE_NR(inode->i_rdev);
- if (--access_count[device] == 0 && acsi_info[device].removable)
- acsi_prevent_removal(device, 0);
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct acsi_info_struct *aip = disk->private_data;
+ if (--aip->access_count == 0 && aip->removable)
+ acsi_prevent_removal(aip, 0);
return( 0 );
}
@@ -1172,12 +1175,11 @@ static int acsi_release( struct inode * inode, struct file * file )
* Prevent or allow a media change for removable devices.
*/
-static void acsi_prevent_removal(int device, int flag)
+static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
{
stdma_lock( NULL, NULL );
- CMDSET_TARG_LUN(pa_med_rem_cmd, acsi_info[device].target,
- acsi_info[device].lun);
+ CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
CMDSET_LEN( pa_med_rem_cmd, flag );
if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
@@ -1188,12 +1190,10 @@ static void acsi_prevent_removal(int device, int flag)
stdma_release();
}
-static int acsi_media_change (kdev_t dev)
+static int acsi_media_change(struct gendisk *disk)
{
- int device = DEVICE_NR(dev);
- struct acsi_info_struct *aip;
+ struct acsi_info_struct *aip = disk->private_data;
- aip = &acsi_info[device];
if (!aip->removable)
return 0;
@@ -1214,19 +1214,19 @@ static int acsi_media_change (kdev_t dev)
acsi_wait_for_IRQ(3*HZ)) {
if (acsi_getstatus()) {
if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- if (CARTRCH_STAT(device, acsi_buffer))
+ if (CARTRCH_STAT(aip, acsi_buffer))
aip->changed = 1;
}
else {
- printk( KERN_ERR "ad%c: REQUEST SENSE failed in test for "
- "medium change; assuming a change\n", device + 'a' );
+ printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
+ "medium change; assuming a change\n", disk->disk_name );
aip->changed = 1;
}
}
}
else {
- printk( KERN_ERR "ad%c: Test for medium changed timed out; "
- "assuming a change\n", device + 'a');
+ printk( KERN_ERR "%s: Test for medium changed timed out; "
+ "assuming a change\n", disk->disk_name);
aip->changed = 1;
}
ENABLE_IRQ();
@@ -1591,12 +1591,12 @@ int SLM_devices[8];
#endif
static struct block_device_operations acsi_fops = {
- owner: THIS_MODULE,
- open: acsi_open,
- release: acsi_release,
- ioctl: acsi_ioctl,
- check_media_change: acsi_media_change,
- revalidate: acsi_revalidate,
+ .owner = THIS_MODULE,
+ .open = acsi_open,
+ .release = acsi_release,
+ .ioctl = acsi_ioctl,
+ .media_changed = acsi_media_change,
+ .revalidate_disk= acsi_revalidate,
};
#ifdef CONFIG_ATARI_SLM_MODULE
@@ -1640,7 +1640,7 @@ int acsi_init( void )
phys_acsi_buffer = virt_to_phys( acsi_buffer );
STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_acsi_request, &acsi_lock);
+ blk_init_queue(&acsi_queue, do_acsi_request, &acsi_lock);
#ifdef CONFIG_ATARI_SLM
err = slm_init();
#endif
@@ -1737,7 +1737,9 @@ int acsi_init( void )
disk->minors = 1;
}
disk->fops = &acsi_fops;
+ disk->private_data = &acsi_info[i];
set_capacity(disk, acsi_info[i].size);
+ disk->queue = &acsi_queue;
add_disk(disk);
}
return 0;
@@ -1745,7 +1747,7 @@ out4:
while (i--)
put_disk(acsi_gendisk[i]);
out3:
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&acsi_queue);
atari_stram_free( acsi_buffer );
out2:
unregister_blkdev( MAJOR_NR, "ad" );
@@ -1772,7 +1774,7 @@ void cleanup_module(void)
{
int i;
del_timer( &acsi_timer );
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&acsi_queue);
atari_stram_free( acsi_buffer );
if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
@@ -1804,10 +1806,9 @@ void cleanup_module(void)
*
*/
-static int acsi_revalidate(kdev_t dev)
+static int acsi_revalidate(struct gendisk *disk)
{
- int unit = DEVICE_NR(dev);
- struct acsi_info_struct *aip = &acsi_info[unit];
+ struct acsi_info_struct *aip = disk->private_data;
stdma_lock( NULL, NULL );
if (acsi_devinit(aip) != DEV_SUPPORTED) {
printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
@@ -1820,6 +1821,6 @@ static int acsi_revalidate(kdev_t dev)
ENABLE_IRQ();
stdma_release();
- set_capacity(acsi_gendisk[unit], aip->size);
+ set_capacity(disk, aip->size);
return 0;
}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 9e6ae34ae194..c6481047ae64 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -81,7 +81,7 @@
#define MAJOR_NR FLOPPY_MAJOR
#define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&floppy_queue)
#include <linux/blk.h>
#undef DEBUG /* print _LOTS_ of infos */
@@ -123,6 +123,8 @@ static long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't ident
MODULE_PARM(fd_def_df0,"l");
MODULE_LICENSE("GPL");
+static struct request_queue floppy_queue;
+
/*
* Macros
*/
@@ -1377,14 +1379,10 @@ static void redo_fd_request(void)
return;
}
- if (major(CURRENT->rq_dev) != MAJOR_NR)
- panic(DEVICE_NAME ": request list destroyed");
-
device = minor(CURRENT->rq_dev);
if (device < 8) {
/* manual selection */
drive = device & 3;
- floppy = unit + drive;
} else {
/* Auto-detection */
#ifdef DEBUG
@@ -1392,8 +1390,8 @@ static void redo_fd_request(void)
printk("redo_fd_request: default to normal\n");
#endif
drive = device & 3;
- floppy = unit + drive;
}
+ floppy = CURRENT->rq_disk->private_data;
/* Here someone could investigate to be more efficient */
for (cnt = 0; cnt < CURRENT->current_nr_sectors; cnt++) {
@@ -1428,11 +1426,11 @@ static void redo_fd_request(void)
switch (rq_data_dir(CURRENT)) {
case READ:
- memcpy(data, unit[drive].trackbuf + sector * 512, 512);
+ memcpy(data, floppy->trackbuf + sector * 512, 512);
break;
case WRITE:
- memcpy(unit[drive].trackbuf + sector * 512, data, 512);
+ memcpy(floppy->trackbuf + sector * 512, data, 512);
/* keep the drive spinning while writes are scheduled */
if (!fd_motor_on(drive)) {
@@ -1446,7 +1444,7 @@ static void redo_fd_request(void)
save_flags (flags);
cli();
- unit[drive].dirty = 1;
+ floppy->dirty = 1;
/* reset the timer */
del_timer (flush_track_timer + drive);
@@ -1674,9 +1672,10 @@ static int floppy_release(struct inode * inode, struct file * filp)
* to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop.
*/
-static int amiga_floppy_change(kdev_t dev)
+static int amiga_floppy_change(struct gendisk *disk)
{
- int drive = minor(dev) & 3;
+ struct amiga_floppy_struct *p = disk->private_data;
+ int drive = p - unit;
int changed;
static int first_time = 1;
@@ -1692,8 +1691,8 @@ static int amiga_floppy_change(kdev_t dev)
if (changed) {
fd_probe(drive);
- unit[drive].track = -1;
- unit[drive].dirty = 0;
+ p->track = -1;
+ p->dirty = 0;
writepending = 0; /* if this was true before, too bad! */
writefromint = 0;
return 1;
@@ -1702,11 +1701,11 @@ static int amiga_floppy_change(kdev_t dev)
}
static struct block_device_operations floppy_fops = {
- .owner = THIS_MODULE,
- .open = floppy_open,
- .release = floppy_release,
- .ioctl = fd_ioctl,
- .check_media_change = amiga_floppy_change,
+ .owner = THIS_MODULE,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = fd_ioctl,
+ .media_changed = amiga_floppy_change,
};
void __init amiga_floppy_setup (char *str, int *ints)
@@ -1745,6 +1744,8 @@ static int __init fd_probe_drives(void)
disk->first_minor = drive;
disk->fops = &floppy_fops;
sprintf(disk->disk_name, "fd%d", drive);
+ disk->private_data = &unit[drive];
+ disk->queue = &floppy_queue;
set_capacity(disk, 880*2);
add_disk(disk);
}
@@ -1758,12 +1759,12 @@ static int __init fd_probe_drives(void)
return -ENOMEM;
}
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
{
- int drive = minor & 3;
+ int drive = *part & 3;
if (unit[drive].type->code == FD_NODRIVE)
return NULL;
- return unit[drive].gendisk;
+ return get_disk(unit[drive].gendisk);
}
int __init amiga_floppy_init(void)
@@ -1808,9 +1809,7 @@ int __init amiga_floppy_init(void)
unregister_blkdev(MAJOR_NR,"fd");
return -EBUSY;
}
- blk_set_probe(MAJOR_NR, floppy_find);
if (fd_probe_drives() < 1) { /* No usable drives */
- blk_set_probe(MAJOR_NR, NULL);
free_irq(IRQ_AMIGA_CIAA_TB, NULL);
free_irq(IRQ_AMIGA_DSKBLK, NULL);
amiga_chip_free(raw_buf);
@@ -1818,6 +1817,8 @@ int __init amiga_floppy_init(void)
unregister_blkdev(MAJOR_NR,"fd");
return -ENXIO;
}
+ blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+ floppy_find, NULL, NULL);
/* initialize variables */
init_timer(&motor_on_timer);
@@ -1842,7 +1843,7 @@ int __init amiga_floppy_init(void)
post_write_timer.data = 0;
post_write_timer.function = post_write;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &amiflop_lock);
+ blk_init_queue(&floppy_queue, do_fd_request, &amiflop_lock);
for (i = 0; i < 128; i++)
mfmdecode[i]=255;
for (i = 0; i < 16; i++)
@@ -1877,12 +1878,12 @@ void cleanup_module(void)
kfree(unit[i].trackbuf);
}
}
- blk_set_probe(MAJOR_NR, NULL);
+ blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
free_irq(IRQ_AMIGA_CIAA_TB, NULL);
free_irq(IRQ_AMIGA_DSKBLK, NULL);
custom.dmacon = DMAF_DISK; /* disable DMA */
amiga_chip_free(raw_buf);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&floppy_queue);
release_mem_region(CUSTOM_PHYSADDR+0x20, 8);
unregister_blkdev(MAJOR_NR, "fd");
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index c2ae35bb875b..897fa52e2f61 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -94,7 +94,7 @@
#define MAJOR_NR FLOPPY_MAJOR
#define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&floppy_queue)
#include <linux/blk.h>
#include <linux/blkpg.h>
@@ -102,6 +102,8 @@
#undef DEBUG
+static struct request_queue floppy_queue;
+
/* Disk types: DD, HD, ED */
static struct atari_disk_type {
const char *name;
@@ -1355,9 +1357,10 @@ static int fd_device[4] = { 0,0,0,0 };
* due to unrecognised disk changes.
*/
-static int check_floppy_change (kdev_t dev)
+static int check_floppy_change(struct gendisk *disk)
{
- unsigned int drive = minor(dev) & 0x03;
+ struct atari_floppy_struct *p = disk->private_data;
+ unsigned int drive = p - unit;
if (test_bit (drive, &fake_change)) {
/* simulated change (e.g. after formatting) */
return 1;
@@ -1376,9 +1379,10 @@ static int check_floppy_change (kdev_t dev)
return 0;
}
-static int floppy_revalidate (kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
{
- int drive = minor(dev) & 3;
+ struct atari_floppy_struct *p = disk->private_data;
+ unsigned int drive = p - unit;
if (test_bit(drive, &changed_floppies) ||
test_bit(drive, &fake_change) ||
@@ -1530,6 +1534,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
{
int drive, type;
kdev_t device;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
struct atari_format_descr fmt_desc;
struct atari_disk_type *dtp;
struct floppy_struct getprm;
@@ -1591,8 +1596,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
* or the next access will revalidate - and clear UDT :-(
*/
- if (check_floppy_change(device))
- floppy_revalidate(device);
+ if (check_floppy_change(disk))
+ floppy_revalidate(disk);
if (UD.flags & FTD_MSG)
printk (KERN_INFO "floppy%d: setting size %d spt %d str %d!\n",
@@ -1902,21 +1907,21 @@ static int floppy_release( struct inode * inode, struct file * filp )
}
static struct block_device_operations floppy_fops = {
- owner: THIS_MODULE,
- open: floppy_open,
- release: floppy_release,
- ioctl: fd_ioctl,
- check_media_change: check_floppy_change,
- revalidate: floppy_revalidate,
+ .owner = THIS_MODULE,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = fd_ioctl,
+ .media_changed = check_floppy_change,
+ .revalidate_disk= floppy_revalidate,
};
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
{
- int drive = minor & 3;
- int type = minor >> 2;
+ int drive = *part & 3;
+ int type = *part >> 2;
if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
return NULL;
- return unit[drive].disk;
+ return get_disk(unit[drive].disk);
}
int __init atari_floppy_init (void)
@@ -1963,6 +1968,8 @@ int __init atari_floppy_init (void)
PhysTrackBuffer = virt_to_phys(TrackBuffer);
BufferDrive = BufferSide = BufferTrack = -1;
+ blk_init_queue(&floppy_queue, do_fd_request, &ataflop_lock);
+
for (i = 0; i < FD_MAX_UNITS; i++) {
unit[i].track = -1;
unit[i].flags = 0;
@@ -1970,12 +1977,14 @@ int __init atari_floppy_init (void)
unit[i].disk->first_minor = i;
sprintf(unit[i].disk->disk_name, "fd%d", i);
unit[i].disk->fops = &floppy_fops;
+ unit[i].disk->private_data = &unit[i];
+ unit[i].disk->queue = &floppy_queue;
set_capacity(unit[i].disk, MAX_DISK_SIZE * 2);
add_disk(unit[i].disk);
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &ataflop_lock);
- blk_set_probe(MAJOR_NR, floppy_find);
+ blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+ floppy_find, NULL, NULL);
printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
DriveType == 0 ? 'D' : DriveType == 1 ? 'H' : 'E',
@@ -2033,14 +2042,14 @@ int init_module (void)
void cleanup_module (void)
{
int i;
+ blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
for (i = 0; i < FD_MAX_UNITS; i++) {
del_gendisk(unit[i].disk);
put_disk(unit[i].disk);
}
unregister_blkdev(MAJOR_NR, "fd");
- blk_set_probe(MAJOR_NR, NULL);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&floppy_queue);
del_timer_sync(&fd_timer);
atari_stram_free( DMABuffer );
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index caa30e1c6e84..ec16c3bfae72 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -105,7 +105,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg);
static int revalidate_allvol(kdev_t dev);
-static int cciss_revalidate(kdev_t dev);
+static int cciss_revalidate(struct gendisk *disk);
static int deregister_disk(int ctlr, int logvol);
static int register_new_disk(int cltr);
@@ -125,11 +125,11 @@ static void cciss_procinit(int i) {}
#endif /* CONFIG_PROC_FS */
static struct block_device_operations cciss_fops = {
- owner: THIS_MODULE,
- open: cciss_open,
- release: cciss_release,
- ioctl: cciss_ioctl,
- revalidate: cciss_revalidate,
+ .owner = THIS_MODULE,
+ .open = cciss_open,
+ .release = cciss_release,
+ .ioctl = cciss_ioctl,
+ .revalidate_disk= cciss_revalidate,
};
#include "cciss_scsi.c" /* For SCSI tape support */
@@ -699,12 +699,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
}
-static int cciss_revalidate(kdev_t dev)
+static int cciss_revalidate(struct gendisk *disk)
{
- int ctlr = major(dev) - MAJOR_NR;
- int target = minor(dev) >> NWD_SHIFT;
- struct gendisk *disk = hba[ctlr]->gendisk[target];
- set_capacity(disk, hba[ctlr]->drv[target].nr_blocks);
+ drive_info_struct *drv = disk->private_data;
+ set_capacity(disk, drv->nr_blocks);
return 0;
}
@@ -765,7 +763,7 @@ static int revalidate_allvol(kdev_t dev)
drive_info_struct *drv = &(hba[ctlr]->drv[i]);
if (!drv->nr_blocks)
continue;
- (BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size;
+ hba[ctlr]->queue.hardsect_size = drv->block_size;
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
}
@@ -1690,10 +1688,11 @@ static void do_cciss_request(request_queue_t *q)
{
ctlr_info_t *h= q->queuedata;
CommandList_struct *c;
- int log_unit, start_blk, seg;
+ int start_blk, seg;
struct request *creq;
u64bit temp64;
struct scatterlist tmp_sg[MAXSGENTRIES];
+ drive_info_struct *drv;
int i, dir;
if (blk_queue_plugged(q))
@@ -1707,16 +1706,6 @@ queue:
if (creq->nr_phys_segments > MAXSGENTRIES)
BUG();
- if (h->ctlr != major(creq->rq_dev)-MAJOR_NR )
- {
- printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
- h->ctlr, major(creq->rq_dev), creq);
- blkdev_dequeue_request(creq);
- complete_buffers(creq->bio, 0);
- end_that_request_last(creq);
- goto startio;
- }
-
if (( c = cmd_alloc(h, 1)) == NULL)
goto startio;
@@ -1728,10 +1717,10 @@ queue:
c->rq = creq;
/* fill in the request */
- log_unit = minor(creq->rq_dev) >> NWD_SHIFT;
+ drv = creq->rq_disk->private_data;
c->Header.ReplyQueue = 0; // unused in simple mode
c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag
- c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
+ c->Header.LUN.LogDev.VolId= drv->LunID;
c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
c->Request.Type.Type = TYPE_CMD; // It is a command.
@@ -1854,7 +1843,7 @@ static void do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
* See if we can queue up some more IO
*/
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
- blk_start_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
+ blk_start_queue(&h->queue);
}
/*
* We cannot read the structure directly, for portablity we must use
@@ -2425,7 +2414,7 @@ static int __init cciss_init_one(struct pci_dev *pdev,
cciss_procinit(i);
- q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+ q = &hba[i]->queue;
q->queuedata = hba[i];
spin_lock_init(&hba[i]->lock);
blk_init_queue(q, do_cciss_request, &hba[i]->lock);
@@ -2447,9 +2436,12 @@ static int __init cciss_init_one(struct pci_dev *pdev,
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
disk->major = MAJOR_NR + i;
disk->first_minor = j << NWD_SHIFT;
+ disk->fops = &cciss_fops;
+ disk->queue = &hba[i]->queue;
+ disk->private_data = drv;
if( !(drv->nr_blocks))
continue;
- (BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size;
+ hba[i]->queue.hardsect_size = drv->block_size;
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
}
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 30d569d1aacb..10d5d261fd76 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -70,6 +70,7 @@ struct ctlr_info
unsigned int maxQsinceinit;
unsigned int maxSG;
spinlock_t lock;
+ struct request_queue queue;
//* pointers to command and error info pool */
CommandList_struct *cmd_pool;
@@ -245,7 +246,7 @@ struct board_type {
struct access_method *access;
};
-#define CCISS_LOCK(i) ((BLK_DEFAULT_QUEUE(MAJOR_NR + i))->queue_lock)
+#define CCISS_LOCK(i) (hba[i]->queue.queue_lock)
#endif /* CCISS_H */
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index ceedd2d59575..6a1b2d18eec6 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1250,8 +1250,6 @@ cciss_scsi_user_command(int ctlr, int hostno, char *buffer, int length)
return length;
}
-/* It's a pity that we need this, but, we do... */
-extern struct Scsi_Host *scsi_hostlist; /* from ../scsi/hosts.c */
int
cciss_scsi_proc_info(char *buffer, /* data buffer */
@@ -1268,24 +1266,9 @@ cciss_scsi_proc_info(char *buffer, /* data buffer */
ctlr_info_t *ci;
int cntl_num;
- /* Lets see if we can find our Scsi_Host...
- this might be kind of "bad", searching scis_hostlist this way
- but how else can we find the scsi host? I think I've seen
- this coded both ways, (circular list and null terminated list)
- I coded it to work either way, since I wasn't sure. */
-
- sh = scsi_hostlist;
- found=0;
- do {
- if (sh == NULL) break;
- if (sh->host_no == hostnum) {
- found++;
- break;
- }
- sh = sh->next;
- } while (sh != scsi_hostlist && sh != NULL);
- if (sh == NULL || found == 0) /* This really shouldn't ever happen. */
+ sh = scsi_host_hn_get(hostnum);
+ if (sh == NULL) /* This really shouldn't ever happen. */
return -EINVAL;
ci = (ctlr_info_t *) sh->hostdata[0];
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 5893a6e528c2..f8ba4997ead6 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -150,7 +150,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout);
static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
static void ida_timer(unsigned long tdata);
-static int ida_revalidate(kdev_t dev);
+static int ida_revalidate(struct gendisk *disk);
static int revalidate_allvol(kdev_t dev);
#ifdef CONFIG_PROC_FS
@@ -163,11 +163,11 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset,
#endif
static struct block_device_operations ida_fops = {
- owner: THIS_MODULE,
- open: ida_open,
- release: ida_release,
- ioctl: ida_ioctl,
- revalidate: ida_revalidate,
+ .owner = THIS_MODULE,
+ .open = ida_open,
+ .release = ida_release,
+ .ioctl = ida_ioctl,
+ .revalidate_disk= ida_revalidate,
};
@@ -296,7 +296,7 @@ static void __exit cpqarray_exit(void)
iounmap(hba[i]->vaddr);
unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
del_timer(&hba[i]->timer);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
+ blk_cleanup_queue(&hba[i]->queue);
remove_proc_entry(hba[i]->devname, proc_array);
pci_free_consistent(hba[i]->pci_dev,
NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool),
@@ -378,7 +378,7 @@ static int __init cpqarray_init(void)
ida_procinit(i);
- q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+ q = &hba[i]->queue;
q->queuedata = hba[i];
spin_lock_init(&hba[i]->lock);
blk_init_queue(q, do_ida_request, &hba[i]->lock);
@@ -409,8 +409,10 @@ static int __init cpqarray_init(void)
disk->fops = &ida_fops;
if (!drv->nr_blks)
continue;
- (BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->blk_size;
+ hba[i]->queue.hardsect_size = drv->blk_size;
set_capacity(disk, drv->nr_blks);
+ disk->queue = &hba[i]->queue;
+ disk->private_data = drv;
add_disk(disk);
}
}
@@ -1004,7 +1006,7 @@ static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
/*
* See if we can queue up some more IO
*/
- do_ida_request(BLK_DEFAULT_QUEUE(MAJOR_NR+h->ctlr));
+ do_ida_request(&h->queue);
spin_unlock_irqrestore(IDA_LOCK(h->ctlr), flags);
}
@@ -1446,8 +1448,10 @@ static int revalidate_allvol(kdev_t dev)
drv_info_t *drv = &hba[ctlr]->drv[i];
if (!drv->nr_blks)
continue;
- (BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size;
+ hba[ctlr]->queue.hardsect_size = drv->blk_size;
set_capacity(disk, drv->nr_blks);
+ disk->queue = &hba[ctlr]->queue;
+ disk->private_data = drv;
add_disk(disk);
}
@@ -1455,12 +1459,10 @@ static int revalidate_allvol(kdev_t dev)
return 0;
}
-static int ida_revalidate(kdev_t dev)
+static int ida_revalidate(struct gendisk *disk)
{
- int ctlr = major(dev) - MAJOR_NR;
- int target = DEVICE_NR(dev);
- struct gendisk *gdev = ida_gendisk[ctlr][target];
- set_capacity(gdev, hba[ctlr]->drv[target].nr_blks);
+ drv_info_t *drv = disk->private_data;
+ set_capacity(disk, drv->nr_blks);
return 0;
}
diff --git a/drivers/block/cpqarray.h b/drivers/block/cpqarray.h
index 54b115635cc0..38bf3b457328 100644
--- a/drivers/block/cpqarray.h
+++ b/drivers/block/cpqarray.h
@@ -105,6 +105,7 @@ struct ctlr_info {
cmdlist_t *cmd_pool;
dma_addr_t cmd_pool_dhandle;
unsigned long *cmd_pool_bits;
+ struct request_queue queue;
spinlock_t lock;
unsigned int Qdepth;
@@ -117,7 +118,7 @@ struct ctlr_info {
unsigned int misc_tflags;
};
-#define IDA_LOCK(i) ((BLK_DEFAULT_QUEUE(MAJOR_NR + i))->queue_lock)
+#define IDA_LOCK(i) (&hba[i]->lock)
#endif
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3fde460ce7ea..7206ab3847a5 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -243,13 +243,13 @@ static int irqdma_allocated;
#define MAJOR_NR FLOPPY_MAJOR
#define DEVICE_NAME "floppy"
#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
-
#include <linux/blk.h>
#include <linux/blkpg.h>
#include <linux/cdrom.h> /* for the compatibility eject ioctl */
#include <linux/completion.h>
static struct request *current_req;
+static struct request_queue floppy_queue;
#ifndef fd_get_dma_residue
#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -2295,12 +2295,10 @@ static int do_format(kdev_t device, struct format_descr *tmp_format_req)
static inline void end_request(struct request *req, int uptodate)
{
- kdev_t dev = req->rq_dev;
-
if (end_that_request_first(req, uptodate, current_count_sectors))
return;
- add_blkdev_randomness(major(dev));
- floppy_off(DEVICE_NR(dev));
+ add_blkdev_randomness(MAJOR_NR);
+ floppy_off((int)req->rq_disk->private_data);
blkdev_dequeue_request(req);
end_that_request_last(req);
@@ -2313,7 +2311,7 @@ static inline void end_request(struct request *req, int uptodate)
* logical buffer */
static void request_done(int uptodate)
{
- struct request_queue *q = QUEUE;
+ struct request_queue *q = &floppy_queue;
struct request *req = current_req;
unsigned long flags;
int block;
@@ -2913,7 +2911,7 @@ static void redo_fd_request(void)
for (;;) {
if (!current_req) {
- struct request *req = elv_next_request(QUEUE);
+ struct request *req = elv_next_request(&floppy_queue);
if (!req) {
do_floppy = NULL;
unlock_fdc();
@@ -2921,9 +2919,6 @@ static void redo_fd_request(void)
}
current_req = req;
}
- if (major(current_req->rq_dev) != MAJOR_NR)
- panic(DEVICE_NAME ": request list destroyed");
-
device = current_req->rq_dev;
set_fdc(DRIVE(device));
reschedule_timeout(current_reqD, "redo fd request", 0);
@@ -3796,14 +3791,9 @@ static int floppy_open(struct inode * inode, struct file * filp)
/*
* Check if the disk has been changed or if a change has been faked.
*/
-static int check_floppy_change(kdev_t dev)
+static int check_floppy_change(struct gendisk *disk)
{
- int drive = DRIVE(dev);
-
- if (major(dev) != MAJOR_NR) {
- DPRINT("check_floppy_change: not a floppy\n");
- return 0;
- }
+ int drive = (int)disk->private_data;
if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
return 1;
@@ -3822,7 +3812,7 @@ static int check_floppy_change(kdev_t dev)
if (UTESTF(FD_DISK_CHANGED) ||
UTESTF(FD_VERIFY) ||
test_bit(drive, &fake_change) ||
- (!TYPE(dev) && !current_type[drive]))
+ (!ITYPE(UDRS->fd_device) && !current_type[drive]))
return 1;
return 0;
}
@@ -3884,16 +3874,17 @@ static int __floppy_read_block_0(struct block_device *bdev)
return 0;
}
-static int floppy_read_block_0(kdev_t dev)
+static int floppy_read_block_0(struct gendisk *disk)
{
struct block_device *bdev;
int ret;
- bdev = bdget(kdev_t_to_nr(dev));
+ bdev = bdget(MKDEV(disk->major, disk->first_minor));
if (!bdev) {
- printk("No block device for %s\n", __bdevname(dev));
+ printk("No block device for %s\n", disk->disk_name);
BUG();
}
+ bdev->bd_disk = disk; /* ewww */
ret = __floppy_read_block_0(bdev);
atomic_dec(&bdev->bd_count);
return ret;
@@ -3903,10 +3894,10 @@ static int floppy_read_block_0(kdev_t dev)
* the bootblock (block 0). "Autodetection" is also needed to check whether
* there is a disk in the drive at all... Thus we also do it for fixed
* geometry formats */
-static int floppy_revalidate(kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
{
-#define NO_GEOM (!current_type[drive] && !TYPE(dev))
- int drive=DRIVE(dev);
+ int drive=(int)disk->private_data;
+#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
int cf;
int res = 0;
@@ -3934,24 +3925,24 @@ static int floppy_revalidate(kdev_t dev)
UDRS->generation++;
if (NO_GEOM){
/* auto-sensing */
- res = floppy_read_block_0(dev);
+ res = floppy_read_block_0(disk);
} else {
if (cf)
poll_drive(0, FD_RAW_NEED_DISK);
process_fd_request();
}
}
- set_capacity(disks[drive], floppy_sizes[minor(dev)]);
+ set_capacity(disk, floppy_sizes[UDRS->fd_device]);
return res;
}
static struct block_device_operations floppy_fops = {
- owner: THIS_MODULE,
- open: floppy_open,
- release: floppy_release,
- ioctl: fd_ioctl,
- check_media_change: check_floppy_change,
- revalidate: floppy_revalidate,
+ .owner = THIS_MODULE,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = fd_ioctl,
+ .media_changed = check_floppy_change,
+ .revalidate_disk= floppy_revalidate,
};
static void __init register_devfs_entries (int drive)
@@ -4212,14 +4203,14 @@ static struct platform_device floppy_device = {
},
};
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
{
- int drive = (minor&3) | ((minor&0x80) >> 5);
+ int drive = (*part&3) | ((*part&0x80) >> 5);
if (drive >= N_DRIVE ||
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
- return disks[drive];
+ return get_disk(disks[drive]);
}
int __init floppy_init(void)
@@ -4249,7 +4240,8 @@ int __init floppy_init(void)
sprintf(disks[i]->disk_name, "fd%d", i);
}
- blk_set_probe(MAJOR_NR, floppy_find);
+ blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+ floppy_find, NULL, NULL);
for (i=0; i<256; i++)
if (ITYPE(i))
@@ -4257,7 +4249,7 @@ int __init floppy_init(void)
else
floppy_sizes[i] = MAX_DISK_SIZE << 1;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock);
+ blk_init_queue(&floppy_queue, do_fd_request, &floppy_lock);
reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
config_types();
@@ -4359,6 +4351,9 @@ int __init floppy_init(void)
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
+ /* to be cleaned up... */
+ disks[drive]->private_data = (void*)drive;
+ disks[drive]->queue = &floppy_queue;
add_disk(disks[drive]);
}
@@ -4368,9 +4363,9 @@ int __init floppy_init(void)
out1:
del_timer(&fd_timeout);
out2:
+ blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
unregister_blkdev(MAJOR_NR,"fd");
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- blk_set_probe(MAJOR_NR, NULL);
+ blk_cleanup_queue(&floppy_queue);
out:
for (i=0; i<N_DRIVE; i++)
put_disk(disks[i]);
@@ -4563,8 +4558,8 @@ void cleanup_module(void)
platform_device_unregister(&floppy_device);
devfs_unregister (devfs_handle);
+ blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
unregister_blkdev(MAJOR_NR, "fd");
- blk_set_probe(MAJOR_NR, NULL);
for (drive = 0; drive < N_DRIVE; drive++) {
if ((allowed_drive_mask & (1 << drive)) &&
fdc_state[FDC(drive)].version != FDC_NONE)
@@ -4572,7 +4567,7 @@ void cleanup_module(void)
put_disk(disks[drive]);
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&floppy_queue);
/* eject disk, if any */
fd_eject(0);
}
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 449e69061bbc..24200d33cf0a 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/kmod.h>
static rwlock_t gendisk_lock;
@@ -33,22 +34,74 @@ static rwlock_t gendisk_lock;
*/
static LIST_HEAD(gendisk_list);
-/*
- * TEMPORARY KLUDGE.
- */
-static struct {
- struct list_head list;
- struct gendisk *(*get)(int minor);
-} gendisks[MAX_BLKDEV];
+struct blk_probe {
+ struct blk_probe *next;
+ dev_t dev;
+ unsigned long range;
+ struct module *owner;
+ struct gendisk *(*get)(dev_t dev, int *part, void *data);
+ void (*lock)(dev_t, void *);
+ void *data;
+} *probes[MAX_BLKDEV];
+
+/* index in the above */
+static inline int dev_to_index(dev_t dev)
+{
+ return MAJOR(dev);
+}
+
+void blk_register_region(dev_t dev, unsigned long range, struct module *module,
+ struct gendisk *(*probe)(dev_t, int *, void *),
+ void (*lock)(dev_t, void *), void *data)
+{
+ int index = dev_to_index(dev);
+ struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
+ struct blk_probe **s;
+ p->owner = module;
+ p->get = probe;
+ p->lock = lock;
+ p->dev = dev;
+ p->range = range;
+ p->data = data;
+ write_lock(&gendisk_lock);
+ for (s = &probes[index]; *s && (*s)->range < range; s = &(*s)->next)
+ ;
+ p->next = *s;
+ *s = p;
+ write_unlock(&gendisk_lock);
+}
-void blk_set_probe(int major, struct gendisk *(p)(int))
+void blk_unregister_region(dev_t dev, unsigned long range)
{
+ int index = dev_to_index(dev);
+ struct blk_probe **s;
write_lock(&gendisk_lock);
- gendisks[major].get = p;
+ for (s = &probes[index]; *s; s = &(*s)->next) {
+ struct blk_probe *p = *s;
+ if (p->dev == dev || p->range == range) {
+ *s = p->next;
+ kfree(p);
+ break;
+ }
+ }
write_unlock(&gendisk_lock);
}
-EXPORT_SYMBOL(blk_set_probe); /* Will go away */
-
+
+EXPORT_SYMBOL(blk_register_region);
+EXPORT_SYMBOL(blk_unregister_region);
+
+static struct gendisk *exact_match(dev_t dev, int *part, void *data)
+{
+ struct gendisk *p = data;
+ *part = MINOR(dev) - p->first_minor;
+ return p;
+}
+
+static void exact_lock(dev_t dev, void *data)
+{
+ struct gendisk *p = data;
+ get_disk(p);
+}
/**
* add_gendisk - add partitioning information to kernel list
@@ -60,10 +113,11 @@ EXPORT_SYMBOL(blk_set_probe); /* Will go away */
void add_disk(struct gendisk *disk)
{
write_lock(&gendisk_lock);
- list_add(&disk->list, &gendisks[disk->major].list);
list_add_tail(&disk->full_list, &gendisk_list);
write_unlock(&gendisk_lock);
disk->flags |= GENHD_FL_UP;
+ blk_register_region(MKDEV(disk->major, disk->first_minor), disk->minors,
+ NULL, exact_match, exact_lock, disk);
register_disk(disk);
}
@@ -74,8 +128,9 @@ void unlink_gendisk(struct gendisk *disk)
{
write_lock(&gendisk_lock);
list_del_init(&disk->full_list);
- list_del_init(&disk->list);
write_unlock(&gendisk_lock);
+ blk_unregister_region(MKDEV(disk->major, disk->first_minor),
+ disk->minors);
}
/**
@@ -88,30 +143,40 @@ void unlink_gendisk(struct gendisk *disk)
struct gendisk *
get_gendisk(dev_t dev, int *part)
{
+ int index = dev_to_index(dev);
struct gendisk *disk;
- struct list_head *p;
- int major = MAJOR(dev);
- int minor = MINOR(dev);
+ struct blk_probe *p;
+ unsigned best = ~0U;
- *part = 0;
+retry:
read_lock(&gendisk_lock);
- if (gendisks[major].get) {
- disk = gendisks[major].get(minor);
- if (disk)
- get_disk(disk);
- read_unlock(&gendisk_lock);
- return disk;
- }
- list_for_each(p, &gendisks[major].list) {
- disk = list_entry(p, struct gendisk, list);
- if (disk->first_minor > minor)
+ for (p = probes[index]; p; p = p->next) {
+ struct gendisk *(*probe)(dev_t, int *, void *);
+ struct module *owner;
+ void *data;
+ if (p->dev > dev || p->dev + p->range <= dev)
continue;
- if (disk->first_minor + disk->minors <= minor)
+ if (p->range >= best) {
+ read_unlock(&gendisk_lock);
+ return NULL;
+ }
+ if (!try_inc_mod_count(p->owner))
continue;
- get_disk(disk);
+ owner = p->owner;
+ data = p->data;
+ probe = p->get;
+ best = p->range;
+ *part = dev - p->dev;
+ if (p->lock)
+ p->lock(dev, data);
read_unlock(&gendisk_lock);
- *part = minor - disk->first_minor;
- return disk;
+ disk = probe(dev, part, data);
+ /* Currently ->owner protects _only_ ->probe() itself. */
+ if (owner)
+ __MOD_DEC_USE_COUNT(owner);
+ if (disk)
+ return disk;
+ goto retry;
}
read_unlock(&gendisk_lock);
return NULL;
@@ -183,8 +248,6 @@ struct seq_operations partitions_op = {
extern int blk_dev_init(void);
-extern int soc_probe(void);
-extern int atmdev_init(void);
struct device_class disk_devclass = {
.name = "disk",
@@ -193,13 +256,26 @@ struct device_class disk_devclass = {
static struct bus_type disk_bus = {
name: "block",
};
+
+static struct gendisk *base_probe(dev_t dev, int *part, void *data)
+{
+ char name[20];
+ sprintf(name, "block-major-%d", MAJOR(dev));
+ request_module(name);
+ return NULL;
+}
int __init device_init(void)
{
+ struct blk_probe *base = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
int i;
rwlock_init(&gendisk_lock);
- for (i = 0; i < MAX_BLKDEV; i++)
- INIT_LIST_HEAD(&gendisks[i].list);
+ memset(base, 0, sizeof(struct blk_probe));
+ base->dev = MKDEV(1,0);
+ base->range = MKDEV(MAX_BLKDEV-1, 255) - base->dev + 1;
+ base->get = base_probe;
+ for (i = 1; i < MAX_BLKDEV; i++)
+ probes[i] = base;
blk_dev_init();
devclass_register(&disk_devclass);
bus_register(&disk_bus);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index eb877e50a8d1..c5697e05a6b8 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -670,12 +670,10 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
bit++;
} while (bit < __REQ_NR_BITS);
- if (rq->flags & REQ_CMD)
- printk("sector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
+ printk("sector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
rq->nr_sectors,
rq->current_nr_sectors);
-
- printk("\n");
+ printk("bio %p, biotail %p\n", rq->bio, rq->biotail);
}
void blk_recount_segments(request_queue_t *q, struct bio *bio)
@@ -1927,7 +1925,7 @@ inline void blk_recalc_rq_segments(struct request *rq)
inline void blk_recalc_rq_sectors(struct request *rq, int nsect)
{
- if (rq->flags & REQ_CMD) {
+ if (rq->bio) {
rq->hard_sector += nsect;
rq->nr_sectors = rq->hard_nr_sectors -= nsect;
rq->sector = rq->hard_sector;
@@ -1968,20 +1966,28 @@ int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
req->errors = 0;
if (!uptodate) {
- printk("end_request: I/O error, dev %s, sector %llu\n",
- kdevname(req->rq_dev), (unsigned long long)req->sector);
error = -EIO;
+ if (!(req->flags & REQ_QUIET))
+ printk("end_request: I/O error, dev %s, sector %llu\n",
+ kdevname(req->rq_dev),
+ (unsigned long long)req->sector);
}
while ((bio = req->bio)) {
- const int nsect = bio_iovec(bio)->bv_len >> 9;
- int new_bio = 0;
+ int new_bio = 0, nsect;
+
+ if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
+ printk("%s: bio idx %d >= vcnt %d\n", __FUNCTION__,
+ bio->bi_idx, bio->bi_vcnt);
+ break;
+ }
BIO_BUG_ON(bio_iovec(bio)->bv_len > bio->bi_size);
/*
* not a complete bvec done
*/
+ nsect = bio_iovec(bio)->bv_len >> 9;
if (unlikely(nsect > nr_sectors)) {
int partial = nr_sectors << 9;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 14fa8720f8db..ea1c987812cf 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -437,7 +437,7 @@ static struct bio *loop_get_bio(struct loop_device *lo)
static int loop_end_io_transfer(struct bio *bio, unsigned int bytes_done, int err)
{
struct bio *rbh = bio->bi_private;
- struct loop_device *lo = &loop_dev[minor(to_kdev_t(rbh->bi_bdev->bd_dev))];
+ struct loop_device *lo = rbh->bi_bdev->bd_disk->private_data;
if (bio->bi_size)
return 1;
@@ -916,20 +916,9 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
static int lo_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct loop_device *lo;
- int dev, err;
+ struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ int err;
- if (!inode)
- return -EINVAL;
- if (major(inode->i_rdev) != MAJOR_NR) {
- printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n",
- MAJOR_NR);
- return -ENODEV;
- }
- dev = minor(inode->i_rdev);
- if (dev >= max_loop)
- return -ENODEV;
- lo = &loop_dev[dev];
down(&lo->lo_ctl_mutex);
switch (cmd) {
case LOOP_SET_FD:
@@ -953,14 +942,9 @@ static int lo_ioctl(struct inode * inode, struct file * file,
static int lo_open(struct inode *inode, struct file *file)
{
- struct loop_device *lo;
- int dev, type;
-
- dev = minor(inode->i_rdev);
- if (dev >= max_loop)
- return -ENODEV;
+ struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ int type;
- lo = &loop_dev[dev];
down(&lo->lo_ctl_mutex);
type = lo->lo_encrypt_type;
@@ -973,14 +957,9 @@ static int lo_open(struct inode *inode, struct file *file)
static int lo_release(struct inode *inode, struct file *file)
{
- struct loop_device *lo;
- int dev, type;
-
- dev = minor(inode->i_rdev);
- if (dev >= max_loop)
- return 0;
+ struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ int type;
- lo = &loop_dev[dev];
down(&lo->lo_ctl_mutex);
type = lo->lo_encrypt_type;
--lo->lo_refcnt;
@@ -1034,16 +1013,6 @@ int loop_unregister_transfer(int number)
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-request_queue_t *loop_get_queue(kdev_t dev)
-{
- int minor = minor(dev);
-
- if (minor < max_loop)
- return &loop_dev[minor].lo_queue;
-
- return NULL;
-}
-
int __init loop_init(void)
{
int i;
@@ -1093,11 +1062,10 @@ int __init loop_init(void)
disk->first_minor = i;
disk->fops = &lo_fops;
sprintf(disk->disk_name, "loop%d", i);
+ disk->private_data = lo;
+ disk->queue = &lo->lo_queue;
add_disk(disk);
}
-
- blk_dev[LOOP_MAJOR].queue = loop_get_queue;
-
printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
return 0;
diff --git a/drivers/block/paride/epat.c b/drivers/block/paride/epat.c
index 0a7126756371..e325adc996f2 100644
--- a/drivers/block/paride/epat.c
+++ b/drivers/block/paride/epat.c
@@ -304,7 +304,6 @@ static void epat_log_adapter( PIA *pi, char * scratch, int verbose )
static void epat_init_proto( PIA *pi)
{ MOD_INC_USE_COUNT;
- printk("epat_init_proto");
}
static void epat_release_proto( PIA *pi)
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 95bedb2a580c..44101ada1e45 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -239,6 +239,7 @@ static int pcd_bufblk = -1; /* block in buffer, in CD units,
*/
static struct pcd_unit *pcd_current; /* current request's drive */
+static struct request *pcd_req;
static int pcd_retries; /* retries on current request */
static int pcd_busy; /* request being processed ? */
static int pcd_sector; /* address of next requested sector */
@@ -249,12 +250,37 @@ static int pcd_warned; /* Have we logged a phase warning ? */
/* kernel glue structures */
+static int pcd_block_open(struct inode *inode, struct file *file)
+{
+ struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+ return cdrom_open(&cd->info, inode, file);
+}
+
+static int pcd_block_release(struct inode *inode, struct file *file)
+{
+ struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+ return cdrom_release(&cd->info, file);
+}
+
+static int pcd_block_ioctl(struct inode *inode, struct file *file,
+ unsigned cmd, unsigned long arg)
+{
+ struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+ return cdrom_ioctl(&cd->info, inode, cmd, arg);
+}
+
+static int pcd_block_media_changed(struct gendisk *disk)
+{
+ struct pcd_unit *cd = disk->private_data;
+ return cdrom_media_changed(&cd->info);
+}
+
static struct block_device_operations pcd_bdops = {
- .owner = THIS_MODULE,
- .open = cdrom_open,
- .release = cdrom_release,
- .ioctl = cdrom_ioctl,
- .check_media_change = cdrom_media_changed,
+ .owner = THIS_MODULE,
+ .open = pcd_block_open,
+ .release = pcd_block_release,
+ .ioctl = pcd_block_ioctl,
+ .media_changed = pcd_block_media_changed,
};
static struct cdrom_device_ops pcd_dops = {
@@ -297,7 +323,6 @@ static void pcd_init_units(void)
snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
cd->info.ops = &pcd_dops;
cd->info.handle = cd;
- cd->info.dev = mk_kdev(major, unit);
cd->info.speed = 0;
cd->info.capacity = 1;
cd->info.mask = 0;
@@ -714,32 +739,43 @@ static int pcd_detect(void)
}
/* I/O request processing */
+static struct request_queue pcd_queue;
static void do_pcd_request(request_queue_t * q)
{
if (pcd_busy)
return;
while (1) {
- struct request *req;
- if (blk_queue_empty(QUEUE))
+ if (blk_queue_empty(q))
return;
- req = CURRENT;
- if (rq_data_dir(req) == READ) {
- struct pcd_unit *cd = pcd + minor(req->rq_dev);
+ pcd_req = elv_next_request(q);
+ if (rq_data_dir(pcd_req) == READ) {
+ struct pcd_unit *cd = pcd_req->rq_disk->private_data;
if (cd != pcd_current)
pcd_bufblk = -1;
pcd_current = cd;
- pcd_sector = req->sector;
- pcd_count = req->current_nr_sectors;
- pcd_buf = req->buffer;
+ pcd_sector = pcd_req->sector;
+ pcd_count = pcd_req->current_nr_sectors;
+ pcd_buf = pcd_req->buffer;
pcd_busy = 1;
ps_set_intr(do_pcd_read, 0, 0, nice);
return;
} else
- end_request(req, 0);
+ end_request(pcd_req, 0);
}
}
+static inline void next_request(int success)
+{
+ long saved_flags;
+
+ spin_lock_irqsave(&pcd_lock, saved_flags);
+ end_request(pcd_req, success);
+ pcd_busy = 0;
+ do_pcd_request(&pcd_queue);
+ spin_unlock_irqrestore(&pcd_lock, saved_flags);
+}
+
static int pcd_ready(void)
{
return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
@@ -761,7 +797,6 @@ static void pcd_start(void)
{
int b, i;
char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
- unsigned long saved_flags;
pcd_bufblk = pcd_sector / 4;
b = pcd_bufblk;
@@ -772,11 +807,7 @@ static void pcd_start(void)
if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
pcd_bufblk = -1;
- spin_lock_irqsave(&pcd_lock, saved_flags);
- pcd_busy = 0;
- end_request(CURRENT, 0);
- do_pcd_request(NULL);
- spin_unlock_irqrestore(&pcd_lock, saved_flags);
+ next_request(0);
return;
}
@@ -791,12 +822,7 @@ static void do_pcd_read(void)
pcd_retries = 0;
pcd_transfer();
if (!pcd_count) {
- unsigned long saved_flags;
- spin_lock_irqsave(&pcd_lock, saved_flags);
- end_request(CURRENT, 1);
- pcd_busy = 0;
- do_pcd_request(NULL);
- spin_unlock_irqrestore(&pcd_lock, saved_flags);
+ next_request(1);
return;
}
@@ -814,18 +840,14 @@ static void do_pcd_read_drq(void)
pi_do_claimed(pcd_current->pi, pcd_start);
return;
}
- spin_lock_irqsave(&pcd_lock, saved_flags);
- pcd_busy = 0;
pcd_bufblk = -1;
- end_request(CURRENT, 0);
- do_pcd_request(NULL);
- spin_unlock_irqrestore(&pcd_lock, saved_flags);
+ next_request(0);
return;
}
do_pcd_read();
spin_lock_irqsave(&pcd_lock, saved_flags);
- do_pcd_request(NULL);
+ do_pcd_request(&pcd_queue);
spin_unlock_irqrestore(&pcd_lock, saved_flags);
}
@@ -934,15 +956,17 @@ static int __init pcd_init(void)
return -1;
}
+ blk_init_queue(&pcd_queue, do_pcd_request, &pcd_lock);
+
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
if (cd->present) {
register_cdrom(&cd->info);
+ cd->disk->private_data = cd;
+ cd->disk->queue = &pcd_queue;
add_disk(cd->disk);
}
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_pcd_request, &pcd_lock);
-
return 0;
}
@@ -959,6 +983,7 @@ static void __exit pcd_exit(void)
}
put_disk(cd->disk);
}
+ blk_cleanup_queue(&pcd_queue);
unregister_blkdev(MAJOR_NR, name);
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 2278ee4928ab..ba58a2af3ebb 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -196,9 +196,6 @@ MODULE_PARM(drive3, "1-8i");
#include "pseudo.h"
#define PD_BITS 4
-#define DEVICE_NR(device) (minor(device)>>PD_BITS)
-#define PD_PARTNS (1<<PD_BITS)
-#define PD_DEVS PD_PARTNS*PD_UNITS
/* numbers for "SCSI" geometry */
@@ -249,7 +246,7 @@ static void do_pd_request(request_queue_t * q);
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static int pd_release(struct inode *inode, struct file *file);
-static int pd_revalidate(kdev_t dev);
+static int pd_revalidate(struct gendisk *p);
static int pd_detect(void);
static void do_pd_read(void);
static void do_pd_read_start(void);
@@ -284,7 +281,7 @@ struct pd_unit pd[PD_UNITS];
static int pd_identify(struct pd_unit *disk);
static void pd_media_check(struct pd_unit *disk);
static void pd_doorlock(struct pd_unit *disk, int func);
-static int pd_check_media(kdev_t dev);
+static int pd_check_media(struct gendisk *p);
static void pd_eject(struct pd_unit *disk);
static char pd_scratch[512]; /* scratch block buffer */
@@ -315,12 +312,12 @@ static char *pd_errs[17] = { "ERR", "INDEX", "ECC", "DRQ", "SEEK", "WRERR",
extern struct block_device_operations pd_fops;
static struct block_device_operations pd_fops = {
- .owner = THIS_MODULE,
- .open = pd_open,
- .release = pd_release,
- .ioctl = pd_ioctl,
- .check_media_change = pd_check_media,
- .revalidate = pd_revalidate
+ .owner = THIS_MODULE,
+ .open = pd_open,
+ .release = pd_release,
+ .ioctl = pd_ioctl,
+ .media_changed = pd_check_media,
+ .revalidate_disk= pd_revalidate
};
static void pd_init_units(void)
@@ -347,8 +344,7 @@ static void pd_init_units(void)
static int pd_open(struct inode *inode, struct file *file)
{
- int unit = DEVICE_NR(inode->i_rdev);
- struct pd_unit *disk = pd + unit;
+ struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
disk->access++;
@@ -362,9 +358,9 @@ static int pd_open(struct inode *inode, struct file *file)
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
struct hd_geometry *geo = (struct hd_geometry *) arg;
struct hd_geometry g;
- struct pd_unit *disk = pd + DEVICE_NR(inode->i_rdev);
switch (cmd) {
case CDROMEJECT:
@@ -392,8 +388,7 @@ static int pd_ioctl(struct inode *inode, struct file *file,
static int pd_release(struct inode *inode, struct file *file)
{
- int unit = DEVICE_NR(inode->i_rdev);
- struct pd_unit *disk = pd + unit;
+ struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
if (!--disk->access && disk->removable)
pd_doorlock(disk, IDE_DOORUNLOCK);
@@ -401,10 +396,10 @@ static int pd_release(struct inode *inode, struct file *file)
return 0;
}
-static int pd_check_media(kdev_t dev)
+static int pd_check_media(struct gendisk *p)
{
- int r, unit = DEVICE_NR(dev);
- struct pd_unit *disk = pd + unit;
+ struct pd_unit *disk = p->private_data;
+ int r;
if (!disk->removable)
return 0;
pd_media_check(disk);
@@ -413,14 +408,13 @@ static int pd_check_media(kdev_t dev)
return r;
}
-static int pd_revalidate(kdev_t dev)
+static int pd_revalidate(struct gendisk *p)
{
- int unit = DEVICE_NR(dev);
- struct pd_unit *disk = pd + unit;
+ struct pd_unit *disk = p->private_data;
if (pd_identify(disk))
- set_capacity(disk->gd, disk->capacity);
+ set_capacity(p, disk->capacity);
else
- set_capacity(disk->gd, 0);
+ set_capacity(p, 0);
return 0;
}
@@ -665,6 +659,8 @@ static int pd_probe_drive(struct pd_unit *disk)
return pd_identify(disk);
}
+static struct request_queue pd_queue;
+
static int pd_detect(void)
{
int k, unit;
@@ -712,6 +708,8 @@ static int pd_detect(void)
p->first_minor = unit << PD_BITS;
set_capacity(p, disk->capacity);
disk->gd = p;
+ p->private_data = disk;
+ p->queue = &pd_queue;
add_disk(p);
}
}
@@ -730,26 +728,18 @@ static int pd_ready(void)
static void do_pd_request(request_queue_t * q)
{
- int unit;
-
if (pd_busy)
return;
repeat:
- if (blk_queue_empty(QUEUE))
+ if (blk_queue_empty(q))
return;
- pd_req = elv_next_request(QUEUE);
- unit = DEVICE_NR(pd_req->rq_dev);
- if (unit >= PD_UNITS) {
- end_request(pd_req, 0);
- goto repeat;
- }
-
+ pd_req = elv_next_request(q);
pd_block = pd_req->sector;
pd_run = pd_req->nr_sectors;
pd_count = pd_req->current_nr_sectors;
- pd_current = pd + unit;
- if (pd_block + pd_count > get_capacity(pd_current->gd)) {
+ pd_current = pd_req->rq_disk->private_data;
+ if (pd_block + pd_count > get_capacity(pd_req->rq_disk)) {
end_request(pd_req, 0);
goto repeat;
}
@@ -797,7 +787,7 @@ static inline void next_request(int success)
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(pd_req, success);
pd_busy = 0;
- do_pd_request(NULL);
+ do_pd_request(&pd_queue);
spin_unlock_irqrestore(&pd_lock, saved_flags);
}
@@ -903,16 +893,14 @@ static void do_pd_write_done(void)
static int __init pd_init(void)
{
- request_queue_t *q;
if (disable)
return -1;
if (register_blkdev(MAJOR_NR, name, &pd_fops)) {
printk("%s: unable to get major number %d\n", name, major);
return -1;
}
- q = BLK_DEFAULT_QUEUE(MAJOR_NR);
- blk_init_queue(q, do_pd_request, &pd_lock);
- blk_queue_max_sectors(q, cluster);
+ blk_init_queue(&pd_queue, do_pd_request, &pd_lock);
+ blk_queue_max_sectors(&pd_queue, cluster);
printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
name, name, PD_VERSION, major, cluster, nice);
@@ -938,6 +926,7 @@ static void __exit pd_exit(void)
pi_release(disk->pi);
}
}
+ blk_cleanup_queue(&pd_queue);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 9598323b5694..7ab87ba87d7d 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -191,7 +191,6 @@ MODULE_PARM(drive3, "1-7i");
/* set up defines for blk.h, why don't all drivers do it this way ? */
#define MAJOR_NR major
-#define DEVICE_NR(device) minor(device)
#include <linux/blk.h>
#include <linux/blkpg.h>
@@ -272,7 +271,7 @@ struct pf_unit units[PF_UNITS];
static int pf_identify(struct pf_unit *pf);
static void pf_lock(struct pf_unit *pf, int func);
static void pf_eject(struct pf_unit *pf);
-static int pf_check_media(kdev_t dev);
+static int pf_check_media(struct gendisk *disk);
static char pf_scratch[512]; /* scratch block buffer */
@@ -294,11 +293,11 @@ static char *pf_buf; /* buffer for request in progress */
/* kernel glue structures */
static struct block_device_operations pf_fops = {
- .owner = THIS_MODULE,
- .open = pf_open,
- .release = pf_release,
- .ioctl = pf_ioctl,
- .check_media_change = pf_check_media,
+ .owner = THIS_MODULE,
+ .open = pf_open,
+ .release = pf_release,
+ .ioctl = pf_ioctl,
+ .media_changed = pf_check_media,
};
void pf_init_units(void)
@@ -328,8 +327,7 @@ void pf_init_units(void)
static int pf_open(struct inode *inode, struct file *file)
{
- int unit = DEVICE_NR(inode->i_rdev);
- struct pf_unit *pf = units + unit;
+ struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
pf_identify(pf);
@@ -348,10 +346,9 @@ static int pf_open(struct inode *inode, struct file *file)
static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- int unit = DEVICE_NR(inode->i_rdev);
+ struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
struct hd_geometry *geo = (struct hd_geometry *) arg;
struct hd_geometry g;
- struct pf_unit *pf = units + unit;
sector_t capacity;
if (cmd == CDROMEJECT) {
@@ -380,10 +377,9 @@ static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
static int pf_release(struct inode *inode, struct file *file)
{
- int unit = DEVICE_NR(inode->i_rdev);
- struct pf_unit *pf = units + unit;
+ struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
- if ((unit >= PF_UNITS) || (pf->access <= 0))
+ if (pf->access <= 0)
return -EINVAL;
pf->access--;
@@ -395,7 +391,7 @@ static int pf_release(struct inode *inode, struct file *file)
}
-static int pf_check_media(kdev_t dev)
+static int pf_check_media(struct gendisk *disk)
{
return 1;
}
@@ -784,25 +780,23 @@ static int pf_ready(void)
return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask));
}
+static struct request_queue pf_queue;
+
static void do_pf_request(request_queue_t * q)
{
- int unit;
-
if (pf_busy)
return;
- repeat:
- if (elv_queue_empty(QUEUE))
+repeat:
+ if (elv_queue_empty(q))
return;
- pf_req = elv_next_request(QUEUE);
- unit = DEVICE_NR(pf_req->rq_dev);
- pf_current = units + unit;
+ pf_req = elv_next_request(q);
+ pf_current = pf_req->rq_disk->private_data;
pf_block = pf_req->sector;
pf_run = pf_req->nr_sectors;
pf_count = pf_req->current_nr_sectors;
- if ((unit >= PF_UNITS) ||
- (pf_block + pf_count > get_capacity(pf_current->disk))) {
+ if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
end_request(pf_req, 0);
goto repeat;
}
@@ -849,7 +843,7 @@ static inline void next_request(int success)
spin_lock_irqsave(&pf_spin_lock, saved_flags);
end_request(pf_req, success);
pf_busy = 0;
- do_pf_request(NULL);
+ do_pf_request(&pf_queue);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
}
@@ -960,7 +954,6 @@ static int __init pf_init(void)
{ /* preliminary initialisation */
struct pf_unit *pf;
int unit;
- request_queue_t *q;
if (disable)
return -1;
@@ -977,15 +970,16 @@ static int __init pf_init(void)
put_disk(pf->disk);
return -1;
}
- q = BLK_DEFAULT_QUEUE(MAJOR_NR);
- blk_init_queue(q, do_pf_request, &pf_spin_lock);
- blk_queue_max_phys_segments(q, cluster);
- blk_queue_max_hw_segments(q, cluster);
+ blk_init_queue(&pf_queue, do_pf_request, &pf_spin_lock);
+ blk_queue_max_phys_segments(&pf_queue, cluster);
+ blk_queue_max_hw_segments(&pf_queue, cluster);
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
struct gendisk *disk = pf->disk;
if (!pf->present)
continue;
+ disk->private_data = pf;
+ disk->queue = &pf_queue;
add_disk(disk);
}
return 0;
@@ -1003,6 +997,7 @@ static void __exit pf_exit(void)
put_disk(pf->disk);
pi_release(pf->pi);
}
+ blk_cleanup_queue(&pf_queue);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index bbd247fa29dc..3129c2da894b 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -51,6 +51,7 @@
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
+#include <linux/backing-dev.h>
#include <asm/uaccess.h>
/*
@@ -89,7 +90,7 @@ static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
*/
int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */
/*
- * It would be very desiderable to have a soft-blocksize (that in the case
+ * It would be very desirable to have a soft-blocksize (that in the case
* of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because
* doing that we'll achieve a far better MM footprint. Using a rd_blocksize of
* BLOCK_SIZE in the worst case we'll make PAGE_SIZE/BLOCK_SIZE buffer-pages
@@ -351,6 +352,10 @@ static struct file_operations initrd_fops = {
#endif
+static struct backing_dev_info rd_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+ .memory_backed = 1, /* Does not contribute to dirty memory */
+};
static int rd_open(struct inode * inode, struct file * filp)
{
@@ -379,6 +384,7 @@ static int rd_open(struct inode * inode, struct file * filp)
rd_bdev[unit]->bd_openers++;
rd_bdev[unit]->bd_block_size = rd_blocksize;
rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
+ rd_bdev[unit]->bd_inode->i_mapping->backing_dev_info = &rd_backing_dev_info;
rd_bdev[unit]->bd_inode->i_size = rd_length[unit];
rd_bdev[unit]->bd_queue = &blk_dev[MAJOR_NR].request_queue;
rd_bdev[unit]->bd_disk = get_disk(rd_disks[unit]);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 2a5f3afefbfa..0dba63e52d4b 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -34,10 +34,11 @@
#define MAJOR_NR FLOPPY_MAJOR
#define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&swim3_queue)
#include <linux/blk.h>
#include <linux/devfs_fs_kernel.h>
+static struct request_queue swim3_queue;
static struct gendisk *disks[2];
#define MAX_FLOPPIES 2
@@ -246,8 +247,8 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param);
static int floppy_open(struct inode *inode, struct file *filp);
static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(kdev_t dev);
-static int floppy_revalidate(kdev_t dev);
+static int floppy_check_change(struct gendisk *disk);
+static int floppy_revalidate(struct gendisk *disk);
static int swim3_add_device(struct device_node *swims);
int swim3_init(void);
@@ -819,18 +820,12 @@ static struct floppy_struct floppy_type =
static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param)
{
- struct floppy_state *fs;
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
int err;
- int devnum = minor(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
return -EPERM;
- fs = &floppy_states[devnum];
-
if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
@@ -851,19 +846,10 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
static int floppy_open(struct inode *inode, struct file *filp)
{
- struct floppy_state *fs;
- volatile struct swim3 *sw;
- int n, err;
- int devnum = minor(inode->i_rdev);
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ volatile struct swim3 *sw = fs->swim3;
+ int n, err = 0;
- if (devnum >= floppy_count)
- return -ENODEV;
- if (filp == 0)
- return -EIO;
-
- fs = &floppy_states[devnum];
- sw = fs->swim3;
- err = 0;
if (fs->ref_count == 0) {
if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
@@ -926,15 +912,8 @@ static int floppy_open(struct inode *inode, struct file *filp)
static int floppy_release(struct inode *inode, struct file *filp)
{
- struct floppy_state *fs;
- volatile struct swim3 *sw;
- int devnum = minor(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
-
- fs = &floppy_states[devnum];
- sw = fs->swim3;
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ volatile struct swim3 *sw = fs->swim3;
if (fs->ref_count > 0 && --fs->ref_count == 0) {
swim3_action(fs, MOTOR_OFF);
out_8(&sw->control_bic, 0xff);
@@ -942,29 +921,17 @@ static int floppy_release(struct inode *inode, struct file *filp)
return 0;
}
-static int floppy_check_change(kdev_t dev)
+static int floppy_check_change(struct gendisk *disk)
{
- struct floppy_state *fs;
- int devnum = minor(dev);
-
- if (major(dev) != MAJOR_NR || (devnum >= floppy_count))
- return 0;
-
- fs = &floppy_states[devnum];
+ struct floppy_state *fs = disk->private_data;
return fs->ejected;
}
-static int floppy_revalidate(kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
{
- struct floppy_state *fs;
+ struct floppy_state *fs = disk->private_data;
volatile struct swim3 *sw;
int ret, n;
- int devnum = minor(dev);
-
- if (major(dev) != MAJOR_NR || (devnum >= floppy_count))
- return 0;
-
- fs = &floppy_states[devnum];
if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
@@ -1002,11 +969,11 @@ static void floppy_off(unsigned int nr)
}
static struct block_device_operations floppy_fops = {
- open: floppy_open,
- release: floppy_release,
- ioctl: floppy_ioctl,
- check_media_change: floppy_check_change,
- revalidate: floppy_revalidate,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = floppy_ioctl,
+ .media_changed = floppy_check_change,
+ .revalidate_disk= floppy_revalidate,
};
static devfs_handle_t floppy_devfs_handle;
@@ -1047,12 +1014,14 @@ int swim3_init(void)
err = -EBUSY;
goto out;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &swim3_lock);
+ blk_init_queue(&swim3_queue, do_fd_request, &swim3_lock);
for (i = 0; i < floppy_count; i++) {
struct gendisk *disk = disks[i];
disk->major = MAJOR_NR;
disk->first_minor = i;
disk->fops = &floppy_fops;
+ disk->private_data = &floppy_states[i];
+ disk->queue = &swim3_queue;
sprintf(disk->disk_name, "fd%d", i);
set_capacity(disk, 2880);
add_disk(disk);
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 3ec747c3f80f..fdc9567d60a0 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -28,7 +28,7 @@
#define MAJOR_NR FLOPPY_MAJOR
#define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&swim_queue)
#include <linux/stddef.h>
#include <linux/kernel.h>
@@ -97,7 +97,7 @@ static char *drive_names[7] = {
int swimiop_init(void);
static void swimiop_init_request(struct swim_iop_req *);
-static int swimiop_send_request(CURRENT, struct swim_iop_req *);
+static int swimiop_send_request(struct swim_iop_req *);
static void swimiop_receive(struct iop_msg *, struct pt_regs *);
static void swimiop_status_update(int, struct swim_drvstatus *);
static int swimiop_eject(struct floppy_state *fs);
@@ -106,8 +106,8 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param);
static int floppy_open(struct inode *inode, struct file *filp);
static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(kdev_t dev);
-static int floppy_revalidate(kdev_t dev);
+static int floppy_check_change(struct gendisk *disk);
+static int floppy_revalidate(struct gendisk *disk);
static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible);
static void release_drive(struct floppy_state *fs);
@@ -118,13 +118,14 @@ static void do_fd_request(request_queue_t * q);
static void start_request(struct floppy_state *fs);
static struct block_device_operations floppy_fops = {
- open: floppy_open,
- release: floppy_release,
- ioctl: floppy_ioctl,
- check_media_change: floppy_check_change,
- revalidate: floppy_revalidate,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = floppy_ioctl,
+ .media_changed = floppy_check_change,
+ .revalidate_disk= floppy_revalidate,
};
+static struct request_queue swim_queue;
/*
* SWIM IOP initialization
*/
@@ -147,8 +148,7 @@ int swimiop_init(void)
MAJOR_NR);
return -EBUSY;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request,
- &swim_iop_lock);
+ blk_init_queue(&swim_queue, do_fd_request, &swim_iop_lock);
printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
DRIVER_VERSION);
@@ -166,7 +166,7 @@ int swimiop_init(void)
swimiop_init_request(&req);
cmd->code = CMD_STATUS;
cmd->drive_num = i + 1;
- if (swimiop_send_request(CURRENT, &req) != 0) continue;
+ if (swimiop_send_request(&req) != 0) continue;
while (!req.complete);
if (cmd->error != 0) {
printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error);
@@ -195,6 +195,8 @@ int swimiop_init(void)
disk->first_minor = i;
disk->fops = &floppy_fops;
sprintf(disk->disk_name, "fd%d", i);
+ disk->private_data = &floppy_states[i];
+ disk->queue = &swim_queue;
set_capacity(disk, 2880 * 2);
add_disk(disk);
}
@@ -209,7 +211,7 @@ static void swimiop_init_request(struct swim_iop_req *req)
req->done = NULL;
}
-static int swimiop_send_request(CURRENT, struct swim_iop_req *req)
+static int swimiop_send_request(struct swim_iop_req *req)
{
unsigned long cpu_flags;
int err;
@@ -324,7 +326,7 @@ static int swimiop_eject(struct floppy_state *fs)
swimiop_init_request(&req);
cmd->code = CMD_EJECT;
cmd->drive_num = fs->drive_num;
- err = swimiop_send_request(CURRENT, &req);
+ err = swimiop_send_request(&req);
if (err) {
release_drive(fs);
return err;
@@ -348,18 +350,12 @@ static struct floppy_struct floppy_type =
static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param)
{
- struct floppy_state *fs;
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
int err;
- int devnum = MINOR(inode->i_rdev);
- if (devnum >= floppy_count)
- return -ENODEV;
-
if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
return -EPERM;
- fs = &floppy_states[devnum];
-
switch (cmd) {
case FDEJECT:
if (fs->ref_count != 1)
@@ -377,32 +373,19 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
static int floppy_open(struct inode *inode, struct file *filp)
{
- struct floppy_state *fs;
- int err;
- int devnum = MINOR(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
- if (filp == 0)
- return -EIO;
-
- fs = &floppy_states[devnum];
- err = 0;
- if (fs->ref_count == -1 || filp->f_flags & O_EXCL) return -EBUSY;
-
- if (err == 0 && (filp->f_flags & O_NDELAY) == 0
- && (filp->f_mode & 3)) {
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+
+ if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
+ return -EBUSY;
+
+ if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) {
check_disk_change(inode->i_bdev);
if (fs->ejected)
- err = -ENXIO;
+ return -ENXIO;
}
- if (err == 0 && (filp->f_mode & 2)) {
- if (fs->write_prot)
- err = -EROFS;
- }
-
- if (err) return err;
+ if ((filp->f_mode & 2) && fs->write_prot)
+ return -EROFS;
if (filp->f_flags & O_EXCL)
fs->ref_count = -1;
@@ -414,43 +397,24 @@ static int floppy_open(struct inode *inode, struct file *filp)
static int floppy_release(struct inode *inode, struct file *filp)
{
- struct floppy_state *fs;
- int devnum = MINOR(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
-
- fs = &floppy_states[devnum];
- if (fs->ref_count > 0) fs->ref_count--;
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ if (fs->ref_count > 0)
+ fs->ref_count--;
return 0;
}
-static int floppy_check_change(kdev_t dev)
+static int floppy_check_change(struct gendisk *disk)
{
- struct floppy_state *fs;
- int devnum = MINOR(dev);
-
- if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
- return 0;
-
- fs = &floppy_states[devnum];
+ struct floppy_state *fs = disk->private_data;
return fs->ejected;
}
-static int floppy_revalidate(kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
{
- struct floppy_state *fs;
- int devnum = MINOR(dev);
-
- if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
- return 0;
-
- fs = &floppy_states[devnum];
-
+ struct floppy_state *fs = disk->private_data;
grab_drive(fs, revalidating, 0);
/* yadda, yadda */
release_drive(fs);
-
return 0;
}
@@ -604,7 +568,7 @@ static void start_request(struct floppy_state *fs)
cmd->first_block = CURRENT->sector;
cmd->num_blocks = CURRENT->current_nr_sectors;
- if (swimiop_send_request(CURRENT, &req)) {
+ if (swimiop_send_request(&req)) {
end_request(CURRENT, 0);
continue;
}
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 4a2b212f1261..8abd7ea68233 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -67,7 +67,6 @@
#define MM_BLKSIZE 1024 /* 1k blocks */
#define MM_HARDSECT 512 /* 512-byte hardware sectors */
#define MM_SHIFT 6 /* max 64 partitions on 4 cards */
-#define DEVICE_NR(device) (minor(device)>>MM_SHIFT)
/*
* Version Information
@@ -812,10 +811,10 @@ static void del_battery_timer(void)
* That's crap, since doing that while some partitions are opened
* or mounted will give you really nasty results.
*/
-static int mm_revalidate(kdev_t i_rdev)
+static int mm_revalidate(struct gendisk *disk)
{
- int card_number = DEVICE_NR(i_rdev);
- set_capacity(mm_gendisk[card_number], cards[card_number].mm_size << 1);
+ struct cardinfo *card = disk->private_data;
+ set_capacity(disk, card->mm_size << 1);
return 0;
}
/*
@@ -826,17 +825,14 @@ static int mm_revalidate(kdev_t i_rdev)
static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
{
if (cmd == HDIO_GETGEO) {
- unsigned int minor = minor(i->i_rdev);
- int err, size, card_number = (minor >> MM_SHIFT);
+ struct cardinfo *card = i->i_bdev->bd_disk->private_data;
+ int size = card->mm_size * (1024 / MM_HARDSECT);
struct hd_geometry geo;
/*
* get geometry: we have to fake one... trim the size to a
* multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
* whatever cylinders.
*/
- err = ! access_ok(VERIFY_WRITE, arg, sizeof(geo));
- if (err) return -EFAULT;
- size = cards[card_number].mm_size * (1024 / MM_HARDSECT);
geo.heads = 64;
geo.sectors = 32;
geo.start = get_start_sect(i->i_bdev);
@@ -855,13 +851,9 @@ static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned
-----------------------------------------------------------------------------------
Future support for removable devices
*/
-static int mm_check_change(kdev_t i_rdev)
+static int mm_check_change(struct gendisk *disk)
{
- int card_number = DEVICE_NR(i_rdev);
-/* struct cardinfo *dev = cards + card_number; */
- if (card_number >= num_cards) /* paranoid */
- return 0;
-
+/* struct cardinfo *dev = disk->private_data; */
return 0;
}
/*
@@ -870,10 +862,10 @@ static int mm_check_change(kdev_t i_rdev)
-----------------------------------------------------------------------------------
*/
static struct block_device_operations mm_fops = {
- owner: THIS_MODULE,
- ioctl: mm_ioctl,
- revalidate: mm_revalidate,
- check_media_change: mm_check_change,
+ .owner = THIS_MODULE,
+ .ioctl = mm_ioctl,
+ .revalidate_disk= mm_revalidate,
+ .media_changed = mm_check_change,
};
/*
-----------------------------------------------------------------------------------
@@ -1149,16 +1141,6 @@ static struct pci_driver mm_pci_driver = {
-----------------------------------------------------------------------------------
*/
-static request_queue_t * mm_queue_proc(kdev_t dev)
-{
- int c = DEVICE_NR(dev);
-
- if (c < MM_MAXCARDS)
- return &cards[c].queue;
- else
- return BLK_DEFAULT_QUEUE(MAJOR_NR);
-}
-
int __init mm_init(void)
{
int retval, i;
@@ -1183,7 +1165,6 @@ int __init mm_init(void)
}
devfs_handle = devfs_mk_dir(NULL, "umem", NULL);
- blk_dev[MAJOR_NR].queue = mm_queue_proc;
for (i = 0; i < num_cards; i++) {
struct gendisk *disk = mm_gendisk[i];
sprintf(disk->disk_name, "umem%c", 'a'+i);
@@ -1191,6 +1172,8 @@ int __init mm_init(void)
disk->major = major_nr;
disk->first_minor = i << MM_SHIFT;
disk->fops = &mm_fops;
+ disk->private_data = &cards[i];
+ disk->queue = &cards[i].queue;
set_capacity(disk, cards[i].mm_size << 1);
add_disk(disk);
}
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index edb2676680e3..2311552b77e7 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -345,11 +345,10 @@ static struct block_device_operations z2_fops =
.release = z2_release,
};
-static struct gendisk *z2_find(int minor)
+static struct gendisk *z2_find(dev_t dev, int *part, void *data)
{
- if (minor > Z2MINOR_COUNT)
- return NULL;
- return z2ram_gendisk;
+ *part = 0;
+ return get_disk(z2ram_gendisk);
}
int __init
@@ -377,7 +376,8 @@ z2_init( void )
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_z2_request, &z2ram_lock);
add_disk(z2ram_gendisk);
- blk_set_probe(MAJOR_NR, z2_find);
+ blk_register_region(MKDEV(MAJOR_NR, 0), Z2MINOR_COUNT, THIS_MODULE,
+ z2_find, NULL, NULL);
return 0;
}
@@ -404,8 +404,7 @@ void
cleanup_module( void )
{
int i, j;
-
- blk_set_probe(MAJOR_NR, NULL);
+ blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 )
printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index b8e1880d8714..93745b274cee 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -168,8 +168,7 @@
#include <linux/version.h>
#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
-
+#define QUEUE (&azt_queue)
#include <linux/blk.h>
#include "aztcd.h"
@@ -227,10 +226,11 @@
#define AZT_DEBUG_MULTISESSION
#endif
+static struct request_queue azt_queue;
+
static int current_valid(void)
{
return !blk_queue_empty(QUEUE) &&
- major(CURRENT->rq_dev) == MAJOR_NR &&
CURRENT->cmd == READ &&
CURRENT->sector != -1;
}
@@ -329,18 +329,18 @@ static int aztGetMultiDiskInfo(void);
static int aztGetToc(int multi);
/* Kernel Interface Functions */
-static int check_aztcd_media_change(kdev_t full_dev);
+static int check_aztcd_media_change(struct gendisk *disk);
static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
unsigned long arg);
static int aztcd_open(struct inode *ip, struct file *fp);
static int aztcd_release(struct inode *inode, struct file *file);
static struct block_device_operations azt_fops = {
- .owner = THIS_MODULE,
- .open = aztcd_open,
- .release = aztcd_release,
- .ioctl = aztcd_ioctl,
- .check_media_change = check_aztcd_media_change,
+ .owner = THIS_MODULE,
+ .open = aztcd_open,
+ .release = aztcd_release,
+ .ioctl = aztcd_ioctl,
+ .media_changed = check_aztcd_media_change,
};
/* Aztcd State Machine: Controls Drive Operating State */
@@ -790,7 +790,7 @@ static int aztGetQChannelInfo(struct azt_Toc *qp)
/*
* Read the table of contents (TOC) and TOC header if necessary
*/
-static int aztUpdateToc()
+static int aztUpdateToc(void)
{
int st;
@@ -1141,7 +1141,7 @@ __setup("aztcd=", aztcd_setup);
/*
* Checking if the media has been changed
*/
-static int check_aztcd_media_change(kdev_t full_dev)
+static int check_aztcd_media_change(struct gendisk *disk)
{
if (aztDiskChanged) { /* disk changed */
aztDiskChanged = 0;
@@ -1677,8 +1677,8 @@ static int aztcd_release(struct inode *inode, struct file *file)
{
#ifdef AZT_DEBUG
printk("aztcd: executing aztcd_release\n");
- printk("inode: %p, inode->i_rdev: %x file: %p\n", inode,
- inode->i_rdev, file);
+ printk("inode: %p, device: %s file: %p\n", inode,
+ inode->i_bdev->bd_disk->disk_name, file);
#endif
if (!--azt_open_count) {
azt_invalidate_buffers();
@@ -1917,12 +1917,13 @@ static int __init aztcd_init(void)
ret = -EIO;
goto err_out3;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin);
- blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
+ blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin);
+ blk_queue_hardsect_size(&azt_queue, 2048);
azt_disk->major = MAJOR_NR;
azt_disk->first_minor = 0;
azt_disk->fops = &azt_fops;
sprintf(azt_disk->disk_name, "aztcd");
+ azt_disk->queue = &azt_queue;
add_disk(azt_disk);
azt_invalidate_buffers();
@@ -1952,7 +1953,7 @@ static void __exit aztcd_exit(void)
printk("What's that: can't unregister aztcd\n");
return;
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&azt_queue);
if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
SWITCH_IDE_MASTER;
release_region(azt_port, 8); /*IDE-interface */
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 0fce58ecee6f..a4f52acc1e9e 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -267,6 +267,7 @@
#include <linux/blkpg.h>
#include <linux/init.h>
#include <linux/fcntl.h>
+#include <linux/blkdev.h>
#include <asm/uaccess.h>
@@ -338,14 +339,11 @@ static struct cdrom_device_info *topCdromPtr;
int register_cdrom(struct cdrom_device_info *cdi)
{
static char banner_printed;
- int major = major(cdi->dev);
struct cdrom_device_ops *cdo = cdi->ops;
int *change_capability = (int *)&cdo->capability; /* hack */
cdinfo(CD_OPEN, "entering register_cdrom\n");
- if (major < 0 || major >= MAX_BLKDEV)
- return -1;
if (cdo->open == NULL || cdo->release == NULL)
return -2;
if ( !banner_printed ) {
@@ -389,16 +387,11 @@ int register_cdrom(struct cdrom_device_info *cdi)
int unregister_cdrom(struct cdrom_device_info *unreg)
{
struct cdrom_device_info *cdi, *prev;
- int major = major(unreg->dev);
-
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
- if (major < 0 || major >= MAX_BLKDEV)
- return -1;
-
prev = NULL;
cdi = topCdromPtr;
- while (cdi != NULL && !kdev_same(cdi->dev, unreg->dev)) {
+ while (cdi && cdi != unreg) {
prev = cdi;
cdi = cdi->next;
}
@@ -414,17 +407,6 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
return 0;
}
-static struct cdrom_device_info *cdrom_find_device(kdev_t dev)
-{
- struct cdrom_device_info *cdi;
-
- cdi = topCdromPtr;
- while (cdi != NULL && !kdev_same(cdi->dev, dev))
- cdi = cdi->next;
-
- return cdi;
-}
-
/* We use the open-option O_NONBLOCK to indicate that the
* purpose of opening is only for subsequent ioctl() calls; no device
* integrity checks are performed.
@@ -433,16 +415,11 @@ static struct cdrom_device_info *cdrom_find_device(kdev_t dev)
* is in their own interest: device control becomes a lot easier
* this way.
*/
-int cdrom_open(struct inode *ip, struct file *fp)
+int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
{
- struct cdrom_device_info *cdi;
- kdev_t dev = ip->i_rdev;
int ret;
cdinfo(CD_OPEN, "entering cdrom_open\n");
- if ((cdi = cdrom_find_device(dev)) == NULL)
- return -ENODEV;
-
/* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */
if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS))
@@ -627,10 +604,8 @@ int check_for_audio_disc(struct cdrom_device_info * cdi,
/* Admittedly, the logic below could be performed in a nicer way. */
-int cdrom_release(struct inode *ip, struct file *fp)
+int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
{
- kdev_t dev = ip->i_rdev;
- struct cdrom_device_info *cdi = cdrom_find_device(dev);
struct cdrom_device_ops *cdo = cdi->ops;
int opened_for_data;
@@ -843,9 +818,8 @@ int media_changed(struct cdrom_device_info *cdi, int queue)
return ret;
}
-int cdrom_media_changed(kdev_t dev)
+int cdrom_media_changed(struct cdrom_device_info *cdi)
{
- struct cdrom_device_info *cdi = cdrom_find_device(dev);
/* This talks to the VFS, which doesn't like errors - just 1 or 0.
* Returning "0" is always safe (media hasn't been changed). Do that
* if the low-level cdrom driver dosn't support media changed. */
@@ -1457,14 +1431,17 @@ static int cdrom_read_block(struct cdrom_device_info *cdi,
* these days. ATAPI / SCSI specific code now mainly resides in
* mmc_ioct().
*/
-int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
+int cdrom_ioctl(struct cdrom_device_info *cdi, struct inode *ip,
+ unsigned int cmd, unsigned long arg)
{
- kdev_t dev = ip->i_rdev;
- struct cdrom_device_info *cdi = cdrom_find_device(dev);
struct cdrom_device_ops *cdo = cdi->ops;
int ret;
+ /* Try the generic SCSI command ioctl's first.. */
+ ret = scsi_cmd_ioctl(ip->i_bdev, cmd, arg);
+ if (ret != -ENOTTY)
+ return ret;
+
/* the first few commands do not deal with audio drive_info, but
only with routines in cdrom device operations. */
switch (cmd) {
@@ -1614,7 +1591,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
if (!CDROM_CAN(CDC_RESET))
return -ENOSYS;
- invalidate_buffers(dev);
+ invalidate_bdev(ip->i_bdev, 0);
return cdo->reset(cdi);
}
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index f4077094707a..686fe183eb1b 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -177,7 +177,6 @@
#include "cdu31a.h"
#define MAJOR_NR CDU31A_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
#include <linux/blk.h>
#define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */
@@ -238,6 +237,7 @@ static volatile unsigned short sony_cd_result_reg;
static volatile unsigned short sony_cd_read_reg;
static volatile unsigned short sony_cd_fifost_reg;
+static struct request_queue cdu31a_queue;
static spinlock_t cdu31a_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
static int sony_spun_up = 0; /* Has the drive been spun up? */
@@ -1531,6 +1531,7 @@ read_data_block(char *buffer,
*/
static void do_cdu31a_request(request_queue_t * q)
{
+ struct request *req;
int block;
int nblock;
unsigned char res_reg[12];
@@ -1578,125 +1579,111 @@ static void do_cdu31a_request(request_queue_t * q)
del_timer(&cdu31a_abort_timer);
while (1) {
- cdu31a_request_startover:
/*
* The beginning here is stolen from the hard disk driver. I hope
* it's right.
*/
- if (blk_queue_empty(QUEUE))
+ if (blk_queue_empty(q))
goto end_do_cdu31a_request;
- if (!sony_spun_up) {
+ if (!sony_spun_up)
scd_spinup();
- }
- block = CURRENT->sector;
- nblock = CURRENT->nr_sectors;
+ req = elv_next_request(q);
+ block = req->sector;
+ nblock = req->nr_sectors;
if (!sony_toc_read) {
printk("CDU31A: TOC not read\n");
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
+ end_request(req, 0);
+ continue;
}
- if(CURRENT->flags & REQ_CMD) {
- switch (rq_data_dir(CURRENT)) {
- case READ:
- /*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
- */
- if ((block / 4) >= sony_toc.lead_out_start_lba) {
- printk
- ("CDU31A: Request past end of media\n");
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
- if (((block + nblock) / 4) >=
- sony_toc.lead_out_start_lba) {
- printk
- ("CDU31A: Request past end of media\n");
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
+ /* WTF??? */
+ if (!(req->flags & REQ_CMD))
+ continue;
+ if (rq_data_dir(req) == WRITE) {
+ end_request(req, 0);
+ continue;
+ }
+ if (rq_data_dir(req) != READ)
+ panic("CDU31A: Unknown cmd");
+ /*
+ * If the block address is invalid or the request goes beyond the end of
+ * the media, return an error.
+ */
+ if ((block / 4) >= sony_toc.lead_out_start_lba) {
+ printk("CDU31A: Request past end of media\n");
+ end_request(req, 0);
+ continue;
+ }
+ if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
+ printk("CDU31A: Request past end of media\n");
+ end_request(req, 0);
+ continue;
+ }
- num_retries = 0;
+ num_retries = 0;
- try_read_again:
- while (handle_sony_cd_attention());
+ try_read_again:
+ while (handle_sony_cd_attention());
- if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
+ if (!sony_toc_read) {
+ printk("CDU31A: TOC not read\n");
+ end_request(req, 0);
+ continue;
+ }
- /* If no data is left to be read from the drive, start the
- next request. */
- if (sony_blocks_left == 0) {
- if (start_request
- (block / 4, CDU31A_READAHEAD / 4, 0)) {
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
- }
- /* If the requested block is not the next one waiting in
- the driver, abort the current operation and start a
- new one. */
- else if (block != sony_next_block) {
+ /* If no data is left to be read from the drive, start the
+ next request. */
+ if (sony_blocks_left == 0) {
+ if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) {
+ end_request(req, 0);
+ continue;
+ }
+ }
+ /* If the requested block is not the next one waiting in
+ the driver, abort the current operation and start a
+ new one. */
+ else if (block != sony_next_block) {
#if DEBUG
- printk
- ("CDU31A Warning: Read for block %d, expected %d\n",
- block, sony_next_block);
+ printk("CDU31A Warning: Read for block %d, expected %d\n",
+ block, sony_next_block);
#endif
- abort_read();
- if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
- if (start_request
- (block / 4, CDU31A_READAHEAD / 4, 0)) {
- printk
- ("CDU31a: start request failed\n");
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
- }
+ abort_read();
+ if (!sony_toc_read) {
+ printk("CDU31A: TOC not read\n");
+ end_request(req, 0);
+ continue;
+ }
+ if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) {
+ printk("CDU31a: start request failed\n");
+ end_request(req, 0);
+ continue;
+ }
+ }
- read_data_block(CURRENT->buffer, block, nblock,
- res_reg, &res_size);
- if (res_reg[0] == 0x20) {
- if (num_retries > MAX_CDU31A_RETRIES) {
- end_request(CURRENT, 0);
- goto cdu31a_request_startover;
- }
+ read_data_block(req->buffer, block, nblock, res_reg, &res_size);
- num_retries++;
- if (res_reg[1] == SONY_NOT_SPIN_ERR) {
- do_sony_cd_cmd(SONY_SPIN_UP_CMD,
- NULL, 0, res_reg,
- &res_size);
- } else {
- printk
- ("CDU31A: %s error for block %d, nblock %d\n",
- translate_error(res_reg[1]),
- block, nblock);
- }
- goto try_read_again;
- } else {
- end_request(CURRENT, 1);
- }
- break;
+ if (res_reg[0] != 0x20) {
+ end_request(req, 1);
+ continue;
+ }
- case WRITE:
- end_request(CURRENT, 0);
- break;
+ if (num_retries > MAX_CDU31A_RETRIES) {
+ end_request(req, 0);
+ continue;
+ }
- default:
- panic("CDU31A: Unknown cmd");
- }
+ num_retries++;
+ if (res_reg[1] == SONY_NOT_SPIN_ERR) {
+ do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
+ &res_size);
+ } else {
+ printk("CDU31A: %s error for block %d, nblock %d\n",
+ translate_error(res_reg[1]), block, nblock);
}
+ goto try_read_again;
}
end_do_cdu31a_request:
spin_lock_irq(q->queue_lock);
@@ -3151,15 +3138,6 @@ static void scd_release(struct cdrom_device_info *cdi)
sony_usage--;
}
-struct block_device_operations scd_bdops =
-{
- .owner = THIS_MODULE,
- .open = cdrom_open,
- .release = cdrom_release,
- .ioctl = cdrom_ioctl,
- .check_media_change = cdrom_media_changed,
-};
-
static struct cdrom_device_ops scd_dops = {
.open = scd_open,
.release = scd_release,
@@ -3188,6 +3166,36 @@ static struct cdrom_device_info scd_info = {
.name = "cdu31a"
};
+static int scd_block_open(struct inode *inode, struct file *file)
+{
+ return cdrom_open(&scd_info, inode, file);
+}
+
+static int scd_block_release(struct inode *inode, struct file *file)
+{
+ return cdrom_release(&scd_info, file);
+}
+
+static int scd_block_ioctl(struct inode *inode, struct file *file,
+ unsigned cmd, unsigned long arg)
+{
+ return cdrom_ioctl(&scd_info, inode, cmd, arg);
+}
+
+static int scd_block_media_changed(struct gendisk *disk)
+{
+ return cdrom_media_changed(&scd_info);
+}
+
+struct block_device_operations scd_bdops =
+{
+ .owner = THIS_MODULE,
+ .open = scd_block_open,
+ .release = scd_block_release,
+ .ioctl = scd_block_ioctl,
+ .media_changed = scd_block_media_changed,
+};
+
static struct gendisk *scd_gendisk;
/* The different types of disc loading mechanisms supported */
@@ -3430,18 +3438,16 @@ int __init cdu31a_init(void)
is_a_cdu31a =
strcmp("CD-ROM CDU31A", drive_config.product_id) == 0;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR),
- do_cdu31a_request,
- &cdu31a_lock);
+ blk_init_queue(&cdu31a_queue, do_cdu31a_request, &cdu31a_lock);
init_timer(&cdu31a_abort_timer);
cdu31a_abort_timer.function = handle_abort_timeout;
- scd_info.dev = mk_kdev(MAJOR_NR, 0);
scd_info.mask = deficiency;
scd_gendisk = disk;
if (register_cdrom(&scd_info))
goto errout0;
+ disk->queue = &cdu31a_queue;
add_disk(disk);
disk_changed = 1;
@@ -3449,7 +3455,7 @@ int __init cdu31a_init(void)
errout0:
printk("Unable to register CDU-31a with Uniform cdrom driver\n");
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&cdu31a_queue);
put_disk(disk);
errout1:
if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
@@ -3476,7 +3482,7 @@ void __exit cdu31a_exit(void)
return;
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&cdu31a_queue);
if (cdu31a_irq > 0)
free_irq(cdu31a_irq, NULL);
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index 8a83a381bcc1..aa3b09000a88 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -198,7 +198,6 @@ History:
#include <asm/io.h>
#define MAJOR_NR CM206_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
#include <linux/blk.h>
@@ -302,6 +301,7 @@ struct cm206_struct {
#define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */
static struct cm206_struct *cd; /* the main memory structure */
+static struct request_queue cm206_queue;
static spinlock_t cm206_lock = SPIN_LOCK_UNLOCKED;
/* First, we define some polling functions. These are actually
@@ -770,15 +770,6 @@ void get_disc_status(void)
}
}
-struct block_device_operations cm206_bdops =
-{
- .owner = THIS_MODULE,
- .open = cdrom_open,
- .release = cdrom_release,
- .ioctl = cdrom_ioctl,
- .check_media_change = cdrom_media_changed,
-};
-
/* The new open. The real opening strategy is defined in cdrom.c. */
static int cm206_open(struct cdrom_device_info *cdi, int purpose)
@@ -860,24 +851,25 @@ static void do_cm206_request(request_queue_t * q)
long int i, cd_sec_no;
int quarter, error;
uch *source, *dest;
+ struct request *req;
- while (1) { /* repeat until all requests have been satisfied */
- if (blk_queue_empty(QUEUE))
+ while (1) { /* repeat until all requests have been satisfied */
+ if (blk_queue_empty(q))
return;
- if (CURRENT->cmd != READ) {
- debug(("Non-read command %d on cdrom\n",
- CURRENT->cmd));
- end_request(CURRENT, 0);
+ req = elv_next_request(q);
+ if (req->cmd != READ) {
+ debug(("Non-read command %d on cdrom\n", req->cmd));
+ end_request(req, 0);
continue;
}
spin_unlock_irq(q->queue_lock);
error = 0;
- for (i = 0; i < CURRENT->nr_sectors; i++) {
+ for (i = 0; i < req->nr_sectors; i++) {
int e1, e2;
- cd_sec_no = (CURRENT->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */
- quarter = (CURRENT->sector + i) % BLOCKS_ISO;
- dest = CURRENT->buffer + i * LINUX_BLOCK_SIZE;
+ cd_sec_no = (req->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */
+ quarter = (req->sector + i) % BLOCKS_ISO;
+ dest = req->buffer + i * LINUX_BLOCK_SIZE;
/* is already in buffer memory? */
if (cd->sector_first <= cd_sec_no
&& cd_sec_no < cd->sector_last) {
@@ -899,7 +891,7 @@ static void do_cm206_request(request_queue_t * q)
}
}
spin_lock_irq(q->queue_lock);
- end_request(CURRENT, !error);
+ end_request(req, !error);
}
}
@@ -1357,6 +1349,36 @@ static struct cdrom_device_info cm206_info = {
.name = "cm206",
};
+static int cm206_block_open(struct inode *inode, struct file *file)
+{
+ return cdrom_open(&cm206_info, inode, file);
+}
+
+static int cm206_block_release(struct inode *inode, struct file *file)
+{
+ return cdrom_release(&cm206_info, file);
+}
+
+static int cm206_block_ioctl(struct inode *inode, struct file *file,
+ unsigned cmd, unsigned long arg)
+{
+ return cdrom_ioctl(&cm206_info, inode, cmd, arg);
+}
+
+static int cm206_block_media_changed(struct gendisk *disk)
+{
+ return cdrom_media_changed(&cm206_info);
+}
+
+static struct block_device_operations cm206_bdops =
+{
+ .owner = THIS_MODULE,
+ .open = cm206_block_open,
+ .release = cm206_block_release,
+ .ioctl = cm206_block_ioctl,
+ .media_changed = cm206_block_media_changed,
+};
+
static struct gendisk *cm206_gendisk;
/* This function probes for the adapter card. It returns the base
@@ -1479,15 +1501,14 @@ int __init cm206_init(void)
disk->fops = &cm206_bdops;
disk->flags = GENHD_FL_CD;
cm206_gendisk = disk;
- cm206_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&cm206_info) != 0) {
printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
goto out_cdrom;
}
+ blk_init_queue(&cm206_queue, do_cm206_request, &cm206_lock);
+ blk_queue_hardsect_size(&cm206_queue, 2048);
+ disk->queue = &cm206_queue;
add_disk(disk);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cm206_request,
- &cm206_lock);
- blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */
cd->sector_last = -1; /* flag no data buffered */
@@ -1550,7 +1571,7 @@ void __exit cm206_exit(void)
printk("Can't unregister major cm206\n");
return;
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&cm206_queue);
free_irq(cm206_irq, NULL);
kfree(cd);
release_region(cm206_base, 16);
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index d82b99f5a4b5..44ed8327f795 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -70,7 +70,6 @@
#include <asm/uaccess.h>
#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
#include <linux/blk.h>
#define gscd_port gscd /* for compatible parameter passing with "insmod" */
#include "gscd.h"
@@ -86,7 +85,7 @@ MODULE_PARM(gscd, "h");
* static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
*/
-static void gscd_read_cmd(void);
+static void gscd_read_cmd(struct request *req);
static void gscd_hsg2msf(long hsg, struct msf *msf);
static void gscd_bin2bcd(unsigned char *p);
@@ -97,7 +96,7 @@ static int gscd_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
static int gscd_open(struct inode *, struct file *);
static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(kdev_t);
+static int check_gscd_med_chg(struct gendisk *disk);
/* GoldStar Funktionen */
@@ -151,35 +150,25 @@ static int AudioEnd_f;
static struct timer_list gscd_timer;
static spinlock_t gscd_lock = SPIN_LOCK_UNLOCKED;
+struct request_queue gscd_queue;
static struct block_device_operations gscd_fops = {
- .owner = THIS_MODULE,
- .open = gscd_open,
- .release = gscd_release,
- .ioctl = gscd_ioctl,
- .check_media_change = check_gscd_med_chg,
+ .owner = THIS_MODULE,
+ .open = gscd_open,
+ .release = gscd_release,
+ .ioctl = gscd_ioctl,
+ .media_changed = check_gscd_med_chg,
};
/*
* Checking if the media has been changed
* (not yet implemented)
*/
-static int check_gscd_med_chg(kdev_t full_dev)
+static int check_gscd_med_chg(struct gendisk *disk)
{
- int target;
-
-
- target = minor(full_dev);
-
- if (target > 0) {
- printk
- ("GSCD: GoldStar CD-ROM request error: invalid device.\n");
- return 0;
- }
#ifdef GSCD_DEBUG
printk("gscd: check_med_change\n");
#endif
-
return 0;
}
@@ -240,16 +229,14 @@ static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
* When Linux gets variable block sizes this will probably go away.
*/
-static void gscd_transfer(void)
+static void gscd_transfer(struct request *req)
{
- long offs;
-
- while (CURRENT->nr_sectors > 0 && gscd_bn == CURRENT->sector / 4) {
- offs = (CURRENT->sector & 3) * 512;
- memcpy(CURRENT->buffer, gscd_buf + offs, 512);
- CURRENT->nr_sectors--;
- CURRENT->sector++;
- CURRENT->buffer += 512;
+ while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
+ long offs = (req->sector & 3) * 512;
+ memcpy(req->buffer, gscd_buf + offs, 512);
+ req->nr_sectors--;
+ req->sector++;
+ req->buffer += 512;
}
}
@@ -265,46 +252,40 @@ static void do_gscd_request(request_queue_t * q)
static void __do_gscd_request(unsigned long dummy)
{
- unsigned int block, dev;
+ struct request *req;
+ unsigned int block;
unsigned int nsect;
- repeat:
- if (blk_queue_empty(QUEUE))
+repeat:
+ if (blk_queue_empty(&gscd_queue))
return;
- dev = minor(CURRENT->rq_dev);
- block = CURRENT->sector;
- nsect = CURRENT->nr_sectors;
+ req = elv_next_request(&gscd_queue);
+ block = req->sector;
+ nsect = req->nr_sectors;
- if (CURRENT->sector == -1)
+ if (req->sector == -1)
goto out;
- if (CURRENT->cmd != READ) {
- printk("GSCD: bad cmd %p\n", CURRENT->cmd);
- end_request(CURRENT, 0);
+ if (req->cmd != READ) {
+ printk("GSCD: bad cmd %d\n", req->cmd);
+ end_request(req, 0);
goto repeat;
}
- if (dev != 0) {
- printk("GSCD: this version supports only one device\n");
- end_request(CURRENT, 0);
- goto repeat;
- }
-
- gscd_transfer();
+ gscd_transfer(req);
/* if we satisfied the request from the buffer, we're done. */
- if (CURRENT->nr_sectors == 0) {
- end_request(CURRENT, 1);
+ if (req->nr_sectors == 0) {
+ end_request(req, 1);
goto repeat;
}
#ifdef GSCD_DEBUG
- printk("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect);
+ printk("GSCD: block %d, nsect %d\n", block, nsect);
#endif
-
- gscd_read_cmd();
- out:
+ gscd_read_cmd(req);
+out:
return;
}
@@ -315,25 +296,23 @@ static void __do_gscd_request(unsigned long dummy)
* read-data command.
*/
-static void gscd_read_cmd(void)
+static void gscd_read_cmd(struct request *req)
{
long block;
struct gscd_Play_msf gscdcmd;
char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */
-
-
cmd_status();
if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
printk("GSCD: no disk or door open\n");
- end_request(CURRENT, 0);
+ end_request(req, 0);
} else {
if (disk_state & ST_INVALID) {
printk("GSCD: disk invalid\n");
- end_request(CURRENT, 0);
+ end_request(req, 0);
} else {
gscd_bn = -1; /* purge our buffer */
- block = CURRENT->sector / 4;
+ block = req->sector / 4;
gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */
cmd[2] = gscdcmd.start.min;
@@ -347,9 +326,9 @@ static void gscd_read_cmd(void)
cmd_out(TYPE_DATA, (char *) &cmd,
(char *) &gscd_buf[0], 1);
- gscd_bn = CURRENT->sector / 4;
- gscd_transfer();
- end_request(CURRENT, 1);
+ gscd_bn = req->sector / 4;
+ gscd_transfer(req);
+ end_request(req, 1);
}
}
SET_TIMER(__do_gscd_request, 1);
@@ -911,7 +890,7 @@ static void __exit gscd_exit(void)
printk("What's that: can't unregister GoldStar-module\n");
return;
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&gscd_queue);
release_region(gscd_port, GSCD_IO_EXTENT);
printk(KERN_INFO "GoldStar-module released.\n");
}
@@ -989,11 +968,12 @@ static int __init gscd_init(void)
devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_gscd_request, &gscd_lock);
+ blk_init_queue(&gscd_queue, do_gscd_request, &gscd_lock);
disk_state = 0;
gscdPresent = 1;
+ gscd_disk->queue = &gscd_queue;
add_disk(gscd_disk);
printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index e6c72eabda52..a12e6c63d2a4 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -102,7 +102,7 @@
#include <asm/uaccess.h>
#define MAJOR_NR MITSUMI_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
+#define QUEUE (&mcd_queue)
#include <linux/blk.h>
#define mcd_port mcd /* for compatible parameter passing with "insmod" */
@@ -116,6 +116,7 @@ static int mcd1xhold;
/* Is the drive connected properly and responding?? */
static int mcdPresent;
+static struct request_queue mcd_queue;
#define QUICK_LOOP_DELAY udelay(45) /* use udelay */
#define QUICK_LOOP_COUNT 20
@@ -123,7 +124,6 @@ static int mcdPresent;
static int current_valid(void)
{
return !blk_queue_empty(QUEUE) &&
- major(CURRENT->rq_dev) == MAJOR_NR &&
CURRENT->cmd == READ &&
CURRENT->sector != -1;
}
@@ -188,18 +188,9 @@ static void mcd_release(struct cdrom_device_info *cdi);
static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr);
static int mcd_tray_move(struct cdrom_device_info *cdi, int position);
static spinlock_t mcd_spinlock = SPIN_LOCK_UNLOCKED;
-int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+static int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
void *arg);
-int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-
-struct block_device_operations mcd_bdops =
-{
- .owner = THIS_MODULE,
- .open = cdrom_open,
- .release = cdrom_release,
- .ioctl = cdrom_ioctl,
- .check_media_change = cdrom_media_changed,
-};
+static int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
static struct timer_list mcd_timer;
@@ -221,6 +212,36 @@ static struct cdrom_device_info mcd_info = {
.name = "mcd",
};
+static int mcd_block_open(struct inode *inode, struct file *file)
+{
+ return cdrom_open(&mcd_info, inode, file);
+}
+
+static int mcd_block_release(struct inode *inode, struct file *file)
+{
+ return cdrom_release(&mcd_info, file);
+}
+
+static int mcd_block_ioctl(struct inode *inode, struct file *file,
+ unsigned cmd, unsigned long arg)
+{
+ return cdrom_ioctl(&mcd_info, inode, cmd, arg);
+}
+
+static int mcd_block_media_changed(struct gendisk *disk)
+{
+ return cdrom_media_changed(&mcd_info);
+}
+
+static struct block_device_operations mcd_bdops =
+{
+ .owner = THIS_MODULE,
+ .open = mcd_block_open,
+ .release = mcd_block_release,
+ .ioctl = mcd_block_ioctl,
+ .media_changed = mcd_block_media_changed,
+};
+
static struct gendisk *mcd_gendisk;
#ifndef MODULE
@@ -1055,8 +1076,7 @@ int __init mcd_init(void)
goto out_region;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mcd_request,
- &mcd_spinlock);
+ blk_init_queue(&mcd_queue, do_mcd_request, &mcd_spinlock);
/* check for card */
@@ -1128,12 +1148,12 @@ int __init mcd_init(void)
disk->fops = &mcd_bdops;
disk->flags = GENHD_FL_CD;
mcd_gendisk = disk;
- mcd_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&mcd_info) != 0) {
printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
goto out_cdrom;
}
+ disk->queue = &mcd_queue;
add_disk(disk);
printk(msg);
return 0;
@@ -1144,7 +1164,7 @@ out_probe:
release_region(mcd_port, 4);
out_region:
unregister_blkdev(MAJOR_NR, "mcd");
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mcd_queue);
put_disk(disk);
return -EIO;
}
@@ -1523,7 +1543,7 @@ void __exit mcd_exit(void)
printk(KERN_WARNING "Can't unregister major mcd\n");
return;
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mcd_queue);
del_timer_sync(&mcd_timer);
}
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index 9747c15b926b..1227392aeac0 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -220,13 +220,38 @@ struct s_drive_stuff {
int mcdx_init(void);
void do_mcdx_request(request_queue_t * q);
-struct block_device_operations mcdx_bdops =
+static int mcdx_block_open(struct inode *inode, struct file *file)
{
- owner: THIS_MODULE,
- open: cdrom_open,
- release: cdrom_release,
- ioctl: cdrom_ioctl,
- check_media_change: cdrom_media_changed,
+ struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+ return cdrom_open(&p->info, inode, file);
+}
+
+static int mcdx_block_release(struct inode *inode, struct file *file)
+{
+ struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+ return cdrom_release(&p->info, file);
+}
+
+static int mcdx_block_ioctl(struct inode *inode, struct file *file,
+ unsigned cmd, unsigned long arg)
+{
+ struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+ return cdrom_ioctl(&p->info, inode, cmd, arg);
+}
+
+static int mcdx_block_media_changed(struct gendisk *disk)
+{
+ struct s_drive_stuff *p = disk->private_data;
+ return cdrom_media_changed(&p->info);
+}
+
+static struct block_device_operations mcdx_bdops =
+{
+ .owner = THIS_MODULE,
+ .open = mcdx_block_open,
+ .release = mcdx_block_release,
+ .ioctl = mcdx_block_ioctl,
+ .media_changed = mcdx_block_media_changed,
};
@@ -292,6 +317,7 @@ static struct s_drive_stuff *mcdx_irq_map[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static spinlock_t mcdx_lock = SPIN_LOCK_UNLOCKED;
+static struct request_queue mcdx_queue;
MODULE_PARM(mcdx, "1-4i");
static struct cdrom_device_ops mcdx_dops = {
@@ -550,66 +576,63 @@ static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
void do_mcdx_request(request_queue_t * q)
{
- int dev;
struct s_drive_stuff *stuffp;
+ struct request *req;
again:
- if (blk_queue_empty(QUEUE))
+ if (blk_queue_empty(q))
return;
- dev = minor(CURRENT->rq_dev);
- stuffp = mcdx_stuffp[dev];
+ req = elv_next_request(q);
+ stuffp = req->rq_disk->private_data;
- if ((dev < 0)
- || (dev >= MCDX_NDRIVES)
- || !stuffp || (!stuffp->present)) {
- xwarn("do_request(): bad device: %s\n",
- kdevname(CURRENT->rq_dev));
+ if (!stuffp->present) {
+ xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
xtrace(REQUEST, "end_request(0): bad device\n");
- end_request(CURRENT, 0);
+ end_request(req, 0);
return;
}
if (stuffp->audio) {
xwarn("do_request() attempt to read from audio cd\n");
xtrace(REQUEST, "end_request(0): read from audio\n");
- end_request(CURRENT, 0);
+ end_request(req, 0);
return;
}
xtrace(REQUEST, "do_request() (%lu + %lu)\n",
- CURRENT->sector, CURRENT->nr_sectors);
+ req->sector, req->nr_sectors);
- if (CURRENT->cmd != READ) {
+ if (req->cmd != READ) {
xwarn("do_request(): non-read command to cd!!\n");
xtrace(REQUEST, "end_request(0): write\n");
- end_request(CURRENT, 0);
+ end_request(req, 0);
return;
}
else {
stuffp->status = 0;
- while (CURRENT->nr_sectors) {
+ while (req->nr_sectors) {
int i;
i = mcdx_transfer(stuffp,
- CURRENT->buffer,
- CURRENT->sector,
- CURRENT->nr_sectors);
+ req->buffer,
+ req->sector,
+ req->nr_sectors);
if (i == -1) {
- end_request(CURRENT, 0);
+ end_request(req, 0);
goto again;
}
- CURRENT->sector += i;
- CURRENT->nr_sectors -= i;
- CURRENT->buffer += (i * 512);
+ req->sector += i;
+ req->nr_sectors -= i;
+ req->buffer += (i * 512);
}
- end_request(CURRENT, 1);
+ end_request(req, 1);
goto again;
xtrace(REQUEST, "end_request(1)\n");
- end_request(CURRENT, 1);
+ end_request(req, 1);
}
goto again;
@@ -1041,10 +1064,10 @@ void __exit mcdx_exit(void)
kfree(stuffp);
}
- if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
+ if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
xwarn("cleanup() unregister_blkdev() failed\n");
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mcdx_queue);
#if !MCDX_QUIET
else
xinfo("cleanup() succeeded\n");
@@ -1179,8 +1202,7 @@ int __init mcdx_init_drive(int drive)
return 1;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mcdx_request,
- &mcdx_lock);
+ blk_init_queue(&mcdx_queue, do_mcdx_request, &mcdx_lock);
xtrace(INIT, "init() subscribe irq and i/o\n");
mcdx_irq_map[stuffp->irq] = stuffp;
@@ -1190,7 +1212,7 @@ int __init mcdx_init_drive(int drive)
xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
stuffp->irq = 0;
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mcdx_queue);
kfree(stuffp);
put_disk(disk);
return 0;
@@ -1218,7 +1240,6 @@ int __init mcdx_init_drive(int drive)
stuffp->info.capacity = 1;
stuffp->info.handle = stuffp;
sprintf(stuffp->info.name, "mcdx%d", drive);
- stuffp->info.dev = mk_kdev(MAJOR_NR, drive);
disk->major = MAJOR_NR;
disk->first_minor = drive;
strcpy(disk->disk_name, stuffp->info.name);
@@ -1240,9 +1261,11 @@ int __init mcdx_init_drive(int drive)
put_disk(disk);
if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
xwarn("cleanup() unregister_blkdev() failed\n");
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&mcdx_queue);
return 2;
}
+ disk->private_data = stuffp;
+ disk->queue = &mcdx_queue;
add_disk(disk);
printk(msg);
return 0;
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index 6abce539684e..01e2cff57400 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -76,7 +76,7 @@
#include <asm/io.h>
#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
+#define QUEUE (&opt_queue)
#include <linux/blk.h>
#include <linux/cdrom.h>
@@ -265,8 +265,8 @@ static int sleep_timeout; /* max # of ticks to sleep */
static DECLARE_WAIT_QUEUE_HEAD(waitq);
static void sleep_timer(unsigned long data);
static struct timer_list delay_timer = {function: sleep_timer};
-spinlock_t optcd_lock = SPIN_LOCK_UNLOCKED;
-
+static spinlock_t optcd_lock = SPIN_LOCK_UNLOCKED;
+static struct request_queue opt_queue;
/* Timer routine: wake up when desired flag goes low,
or when timeout expires. */
@@ -977,7 +977,6 @@ static int update_toc(void)
static int current_valid(void)
{
return !blk_queue_empty(QUEUE) &&
- major(CURRENT->rq_dev) == MAJOR_NR &&
CURRENT->cmd == READ &&
CURRENT->sector != -1;
}
@@ -1896,8 +1895,8 @@ static int opt_release(struct inode *ip, struct file *fp)
int status;
DEBUG((DEBUG_VFS, "executing opt_release"));
- DEBUG((DEBUG_VFS, "inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
- ip, ip -> i_rdev, fp));
+ DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
+ ip, ip->i_bdev->bd_disk->disk_name, fp));
if (!--open_count) {
toc_uptodate = 0;
@@ -1918,10 +1917,11 @@ static int opt_release(struct inode *ip, struct file *fp)
/* Check if disk has been changed */
-static int opt_media_change(kdev_t dev)
+static int opt_media_change(struct gendisk *disk)
{
DEBUG((DEBUG_VFS, "executing opt_media_change"));
- DEBUG((DEBUG_VFS, "dev: 0x%x; disk_changed = %d\n", dev, disk_changed));
+ DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
+ disk->disk_name, disk_changed));
if (disk_changed) {
disk_changed = 0;
@@ -1973,11 +1973,11 @@ static int __init version_ok(void)
static struct block_device_operations opt_fops = {
- .owner = THIS_MODULE,
- .open = opt_open,
- .release = opt_release,
- .ioctl = opt_ioctl,
- .check_media_change = opt_media_change,
+ .owner = THIS_MODULE,
+ .open = opt_open,
+ .release = opt_release,
+ .ioctl = opt_ioctl,
+ .media_changed = opt_media_change,
};
#ifndef MODULE
@@ -2054,9 +2054,9 @@ static int __init optcd_init(void)
}
devfs_register (NULL, "optcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &opt_fops, NULL);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request,
- &optcd_lock);
- blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
+ blk_init_queue(&opt_queue, do_optcd_request, &optcd_lock);
+ blk_queue_hardsect_size(&opt_queue, 2048);
+ optcd_disk->queue = &opt_queue;
add_disk(optcd_disk);
printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
@@ -2073,7 +2073,7 @@ static void __exit optcd_exit(void)
printk(KERN_ERR "optcd: what's that: can't unregister\n");
return;
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&opt_queue);
release_region(optcd_port, 4);
printk(KERN_INFO "optcd: module released.\n");
}
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 22a4ca708c6f..58eaf08e4d57 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -354,6 +354,13 @@
* Marcin Dalecki
*/
+/*
+ * Add bio/kdev_t changes for 2.5.x required to make it work again.
+ * Still room for improvement in the request handling here if anyone
+ * actually cares. Bring your own chainsaw. Paul G. 02/2002
+ */
+
+
#include <linux/module.h>
#include <linux/version.h>
@@ -456,12 +463,15 @@ static int sbpcd[] =
* Protects access to global structures etc.
*/
static spinlock_t sbpcd_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+static struct request_queue sbpcd_queue;
MODULE_PARM(sbpcd, "2i");
MODULE_PARM(max_drives, "i");
#define NUM_PROBE (sizeof(sbpcd) / sizeof(int))
+static spinlock_t sbpcd_lock = SPIN_LOCK_UNLOCKED;
+
/*==========================================================================*/
#define INLINE inline
@@ -4841,7 +4851,7 @@ static void do_sbpcd_request(request_queue_t * q)
#ifdef DEBUG_GTL
xnr=++xx_nr;
- if(blk_queue_empty(QUEUE))
+ if(blk_queue_empty(q))
{
printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
xnr, current->pid, jiffies);
@@ -4850,32 +4860,27 @@ static void do_sbpcd_request(request_queue_t * q)
return;
}
+ req = elv_next_request(q);
+
printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
- xnr, CURRENT, CURRENT->sector, CURRENT->nr_sectors, current->pid, jiffies);
+ xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
#endif
-
- if (blk_queue_empty(QUEUE))
+ if (blk_queue_empty(q))
return;
- req = CURRENT; /* take out our request so no other */
- blkdev_dequeue_request(req); /* task can fuck it up GTL */
+ req = elv_next_request(q); /* take out our request so no other */
if (req -> sector == -1)
- end_request(CURRENT, 0);
+ end_request(req, 0);
spin_unlock_irq(q->queue_lock);
down(&ioctl_read_sem);
- if (req->cmd != READ)
+ if (rq_data_dir(CURRENT) != READ)
{
- msg(DBG_INF, "bad cmd %d\n", req->cmd);
- goto err_done;
- }
- p = D_S + minor(req->rq_dev);
- if (p->drv_id==-1) {
- msg(DBG_INF, "do_request: bad device: %s\n",
- kdevname(req->rq_dev));
+ msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
goto err_done;
}
+ p = req->rq_disk->private_data;
#if OLD_BUSY
while (busy_audio) sbp_sleep(HZ); /* wait a bit */
busy_data=1;
@@ -4903,7 +4908,7 @@ static void do_sbpcd_request(request_queue_t * q)
#endif
up(&ioctl_read_sem);
spin_lock_irq(q->queue_lock);
- end_request(CURRENT, 1);
+ end_request(req, 1);
goto request_loop;
}
@@ -4944,7 +4949,7 @@ static void do_sbpcd_request(request_queue_t * q)
#endif
up(&ioctl_read_sem);
spin_lock_irq(q->queue_lock);
- end_request(CURRENT, 1);
+ end_request(req, 1);
goto request_loop;
}
}
@@ -4960,7 +4965,7 @@ static void do_sbpcd_request(request_queue_t * q)
up(&ioctl_read_sem);
sbp_sleep(0); /* wait a bit, try again */
spin_lock_irq(q->queue_lock);
- end_request(CURRENT, 0);
+ end_request(req, 0);
goto request_loop;
}
/*==========================================================================*/
@@ -5351,13 +5356,38 @@ static int sbp_data(struct request *req)
}
/*==========================================================================*/
+static int sbpcd_block_open(struct inode *inode, struct file *file)
+{
+ struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+ return cdrom_open(p->sbpcd_infop, inode, file);
+}
+
+static int sbpcd_block_release(struct inode *inode, struct file *file)
+{
+ struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+ return cdrom_release(p->sbpcd_infop, file);
+}
+
+static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
+ unsigned cmd, unsigned long arg)
+{
+ struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+ return cdrom_ioctl(p->sbpcd_infop, inode, cmd, arg);
+}
+
+static int sbpcd_block_media_changed(struct gendisk *disk)
+{
+ struct sbpcd_drive *p = disk->private_data;
+ return cdrom_media_changed(p->sbpcd_infop);
+}
+
static struct block_device_operations sbpcd_bdops =
{
- owner: THIS_MODULE,
- open: cdrom_open,
- release: cdrom_release,
- ioctl: cdrom_ioctl,
- check_media_change: cdrom_media_changed,
+ .owner = THIS_MODULE,
+ .open = sbpcd_block_open,
+ .release = sbpcd_block_release,
+ .ioctl = sbpcd_block_ioctl,
+ .media_changed = sbpcd_block_media_changed,
};
/*==========================================================================*/
/*
@@ -5752,6 +5782,12 @@ int __init sbpcd_init(void)
if (i>=0) p->CD_changed=1;
}
+ if (!request_region(CDo_command,4,major_name))
+ {
+ printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
+ return -EIO;
+ }
+
/*
* Turn on the CD audio channels.
* The addresses are obtained from SOUND_BASE (see sbpcd.h).
@@ -5770,11 +5806,10 @@ int __init sbpcd_init(void)
goto init_done;
#endif /* MODULE */
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sbpcd_request, &sbpcd_lock);
-
- request_region(CDo_command,4,major_name);
+ blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock);
devfs_handle = devfs_mk_dir (NULL, "sbp", NULL);
+
for (j=0;j<NR_SBPCD;j++)
{
struct cdrom_device_info * sbpcd_infop;
@@ -5804,7 +5839,7 @@ int __init sbpcd_init(void)
printk("Can't unregister %s\n", major_name);
}
release_region(CDo_command,4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&sbpcd_queue);
return -EIO;
}
#ifdef MODULE
@@ -5820,7 +5855,7 @@ int __init sbpcd_init(void)
if (sbpcd_infop == NULL)
{
release_region(CDo_command,4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&sbpcd_queue);
return -ENOMEM;
}
memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
@@ -5828,7 +5863,6 @@ int __init sbpcd_init(void)
sbpcd_infop->speed = 2;
sbpcd_infop->capacity = 1;
sprintf(sbpcd_infop->name, "sbpcd%d", j);
- sbpcd_infop->dev = mk_kdev(MAJOR_NR, j);
sbpcd_infop->handle = p;
p->sbpcd_infop = sbpcd_infop;
disk = alloc_disk(1);
@@ -5844,9 +5878,11 @@ int __init sbpcd_init(void)
{
printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
}
+ disk->private_data = p;
+ disk->queue = &sbpcd_queue;
add_disk(disk);
}
- blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CD_FRAMESIZE);
+ blk_queue_hardsect_size(&sbpcd_queue, CD_FRAMESIZE);
#ifndef MODULE
init_done:
@@ -5865,7 +5901,7 @@ void sbpcd_exit(void)
return;
}
release_region(CDo_command,4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&sbpcd_queue);
devfs_unregister (devfs_handle);
for (j=0;j<NR_SBPCD;j++)
{
@@ -5874,7 +5910,6 @@ void sbpcd_exit(void)
put_disk(D_S[j].disk);
vfree(D_S[j].sbp_buf);
if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
- devfs_unregister(D_S[j].disk.de);
if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
{
msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
@@ -5885,6 +5920,7 @@ void sbpcd_exit(void)
msg(DBG_INF, "%s module released.\n", major_name);
}
+
module_init(__sbpcd_init) /*HACK!*/;
module_exit(sbpcd_exit);
@@ -5899,8 +5935,7 @@ static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
{
p->CD_changed=0;
msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
- /* BUG! Should invalidate buffers! --AJK */
- /* Why should it do the above at all?! --mdcki */
+ invalidate_buffers(full_dev);
current_drive->diskstate_flags &= ~toc_bit;
current_drive->diskstate_flags &= ~cd_size_bit;
#if SAFE_MIXED
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 9dcdda8741b0..58f111663d85 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -77,11 +77,12 @@
#include <asm/uaccess.h>
#define MAJOR_NR SANYO_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
+#define QUEUE (&sjcd_queue)
#include <linux/blk.h>
#include "sjcd.h"
static int sjcd_present = 0;
+static struct request_queue sjcd_queue;
#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
@@ -453,15 +454,11 @@ static void sjcd_get_status(void)
/*
* Check the drive if the disk is changed. Should be revised.
*/
-static int sjcd_disk_change(kdev_t full_dev)
+static int sjcd_disk_change(struct gendisk *disk)
{
#if 0
- printk("SJCD: sjcd_disk_change( 0x%x )\n", full_dev);
+ printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
#endif
- if (minor(full_dev) > 0) {
- printk("SJCD: request error: invalid device minor.\n");
- return 0;
- }
if (!sjcd_command_is_in_progress)
sjcd_get_status();
return (sjcd_status_valid ? sjcd_media_is_changed : 0);
@@ -1067,7 +1064,6 @@ static void sjcd_invalidate_buffers(void)
static int current_valid(void)
{
return !blk_queue_empty(QUEUE) &&
- major(CURRENT->rq_dev) == MAJOR_NR &&
CURRENT->cmd == READ &&
CURRENT->sector != -1;
}
@@ -1645,11 +1641,11 @@ static int sjcd_release(struct inode *inode, struct file *file)
* A list of file operations allowed for this cdrom.
*/
static struct block_device_operations sjcd_fops = {
- .owner = THIS_MODULE,
- .open = sjcd_open,
- .release = sjcd_release,
- .ioctl = sjcd_ioctl,
- .check_media_change = sjcd_disk_change,
+ .owner = THIS_MODULE,
+ .open = sjcd_open,
+ .release = sjcd_release,
+ .ioctl = sjcd_ioctl,
+ .media_changed = sjcd_disk_change,
};
/*
@@ -1686,8 +1682,8 @@ static int __init sjcd_init(void)
return (-EIO);
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock);
- blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
+ blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock);
+ blk_queue_hardsect_size(&sjcd_queue, 2048);
sjcd_disk = alloc_disk(1);
if (!sjcd_disk) {
@@ -1786,13 +1782,14 @@ static int __init sjcd_init(void)
printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);
+ sjcd_disk->queue = &sjcd_queue;
add_disk(sjcd_disk);
sjcd_present++;
return (0);
out3:
release_region(sjcd_base, 4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&sjcd_queue);
out2:
put_disk(sjcd_disk);
out1:
@@ -1807,11 +1804,10 @@ static void __exit sjcd_exit(void)
del_gendisk(sjcd_disk);
put_disk(sjcd_disk);
release_region(sjcd_base, 4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&sjcd_queue);
if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
printk("SJCD: cannot unregister device.\n");
printk(KERN_INFO "SJCD: module: removed.\n");
- return (0);
}
module_init(sjcd_init);
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index 68e8103a7223..20d010e83bd9 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -135,7 +135,6 @@
#include <linux/cdrom.h>
#define MAJOR_NR CDU535_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
#include <linux/blk.h>
#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
@@ -221,6 +220,7 @@ static unsigned short read_status_reg;
static unsigned short data_reg;
static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
+static struct request_queue sonycd535_queue;
static int initialized; /* Has the drive been initialized? */
static int sony_disc_changed = 1; /* Has the disk been changed
@@ -280,17 +280,10 @@ static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
* check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
*/
static int
-cdu535_check_media_change(kdev_t full_dev)
+cdu535_check_media_change(struct gendisk *disk)
{
- int retval;
-
- if (minor(full_dev) != 0) {
- printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
- return 0;
- }
-
/* if driver is not initialized, always return 0 */
- retval = initialized ? sony_disc_changed : 0;
+ int retval = initialized ? sony_disc_changed : 0;
sony_disc_changed = 0;
return retval;
}
@@ -793,7 +786,7 @@ size_to_buf(unsigned int size, Byte *buf)
static void
do_cdu535_request(request_queue_t * q)
{
- unsigned int dev;
+ struct request *req;
unsigned int read_size;
int block;
int nsect;
@@ -804,130 +797,121 @@ do_cdu535_request(request_queue_t * q)
Byte cmd[2];
while (1) {
- if (blk_queue_empty(QUEUE))
+ if (blk_queue_empty(q))
return;
- dev = minor(CURRENT->rq_dev);
- block = CURRENT->sector;
- nsect = CURRENT->nr_sectors;
- if (dev != 0) {
- end_request(CURRENT, 0);
+ req = elv_next_request(q);
+ block = req->sector;
+ nsect = req->nr_sectors;
+ if (!(req->flags & REQ_CMD))
+ continue; /* FIXME */
+ if (rq_data_dir(req) == WRITE) {
+ end_request(req, 0);
continue;
}
- if(CURRENT->flags & REQ_CMD) {
- switch (rq_data_dir(CURRENT)) {
- case READ:
+ if (rq_data_dir(req) != READ)
+ panic("Unknown SONY CD cmd");
+ /*
+ * If the block address is invalid or the request goes beyond
+ * the end of the media, return an error.
+ */
+ if (sony_toc->lead_out_start_lba <= (block/4)) {
+ end_request(req, 0);
+ return;
+ }
+ if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
+ end_request(req, 0);
+ return;
+ }
+ while (0 < nsect) {
+ /*
+ * If the requested sector is not currently in
+ * the read-ahead buffer, it must be read in.
+ */
+ if ((block < sony_first_block) || (sony_last_block < block)) {
+ sony_first_block = (block / 4) * 4;
+ log_to_msf(block / 4, params);
+
/*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
+ * If the full read-ahead would go beyond the end of the media, trim
+ * it back to read just till the end of the media.
*/
- if (sony_toc->lead_out_start_lba <= (block / 4)) {
- end_request(CURRENT, 0);
- return;
- }
- if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
- end_request(CURRENT, 0);
- return;
+ if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
+ sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
+ read_size = sony_toc->lead_out_start_lba - (block / 4);
+ } else {
+ sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
+ read_size = sony_buffer_sectors;
}
- while (0 < nsect) {
+ size_to_buf(read_size, &params[3]);
+
+ /*
+ * Read the data. If the drive was not spinning,
+ * spin it up and try some more.
+ */
+ for (spin_up_retry=0 ;; ++spin_up_retry) {
+ /* This loop has been modified to support the Sony
+ * CDU-510/515 series, thanks to Claudio Porfiri
+ * <C.Porfiri@nisms.tei.ericsson.se>.
+ */
/*
- * If the requested sector is not currently in the read-ahead buffer,
- * it must be read in.
+ * This part is to deal with very slow hardware. We
+ * try at most MAX_SPINUP_RETRY times to read the same
+ * block. A check for seek_and_read_N_blocks' result is
+ * performed; if the result is wrong, the CDROM's engine
+ * is restarted and the operation is tried again.
*/
- if ((block < sony_first_block) || (sony_last_block < block)) {
- sony_first_block = (block / 4) * 4;
- log_to_msf(block / 4, params);
-
- /*
- * If the full read-ahead would go beyond the end of the media, trim
- * it back to read just till the end of the media.
- */
- if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
- sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
- read_size = sony_toc->lead_out_start_lba - (block / 4);
- } else {
- sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
- read_size = sony_buffer_sectors;
- }
- size_to_buf(read_size, &params[3]);
-
- /*
- * Read the data. If the drive was not spinning,
- * spin it up and try some more.
- */
- for (spin_up_retry=0 ;; ++spin_up_retry) {
- /* This loop has been modified to support the Sony
- * CDU-510/515 series, thanks to Claudio Porfiri
- * <C.Porfiri@nisms.tei.ericsson.se>.
- */
- /*
- * This part is to deal with very slow hardware. We
- * try at most MAX_SPINUP_RETRY times to read the same
- * block. A check for seek_and_read_N_blocks' result is
- * performed; if the result is wrong, the CDROM's engine
- * is restarted and the operation is tried again.
- */
- /*
- * 1995-06-01: The system got problems when downloading
- * from Slackware CDROM, the problem seems to be:
- * seek_and_read_N_blocks returns BAD_STATUS and we
- * should wait for a while before retrying, so a new
- * part was added to discriminate the return value from
- * seek_and_read_N_blocks for the various cases.
- */
- int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
- if (0 <= readStatus) /* Good data; common case, placed first */
- break;
- if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
- /* give up */
- if (readStatus == NO_ROOM)
- printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
- else
- printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
- status[0]);
- sony_first_block = -1;
- sony_last_block = -1;
- end_request(CURRENT, 0);
- return;
- }
- if (readStatus == BAD_STATUS) {
- /* Sleep for a while, then retry */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
- }
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME
- " debug: calling spin up when reading data!\n");
-#endif
- cmd[0] = SONY535_SPIN_UP;
- do_sony_cmd(cmd, 1, status, NULL, 0, 0);
- }
- }
/*
- * The data is in memory now, copy it to the buffer and advance to the
- * next block to read.
+ * 1995-06-01: The system got problems when downloading
+ * from Slackware CDROM, the problem seems to be:
+ * seek_and_read_N_blocks returns BAD_STATUS and we
+ * should wait for a while before retrying, so a new
+ * part was added to discriminate the return value from
+ * seek_and_read_N_blocks for the various cases.
*/
- copyoff = block - sony_first_block;
- memcpy(CURRENT->buffer,
- sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-
- block += 1;
- nsect -= 1;
- CURRENT->buffer += 512;
+ int readStatus = seek_and_read_N_blocks(params, read_size,
+ status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
+ if (0 <= readStatus) /* Good data; common case, placed first */
+ break;
+ if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
+ /* give up */
+ if (readStatus == NO_ROOM)
+ printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
+ else
+ printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
+ status[0]);
+ sony_first_block = -1;
+ sony_last_block = -1;
+ end_request(req, 0);
+ return;
+ }
+ if (readStatus == BAD_STATUS) {
+ /* Sleep for a while, then retry */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
+ }
+#if DEBUG > 0
+ printk(CDU535_MESSAGE_NAME
+ " debug: calling spin up when reading data!\n");
+#endif
+ cmd[0] = SONY535_SPIN_UP;
+ do_sony_cmd(cmd, 1, status, NULL, 0, 0);
}
-
- end_request(CURRENT, 1);
- break;
-
- case WRITE:
- end_request(CURRENT, 0);
- break;
-
- default:
- panic("Unknown SONY CD cmd");
}
+ /*
+ * The data is in memory now, copy it to the buffer and advance to the
+ * next block to read.
+ */
+ copyoff = block - sony_first_block;
+ memcpy(req->buffer,
+ sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
+
+ block += 1;
+ nsect -= 1;
+ req->buffer += 512;
}
+
+ end_request(req, 1);
}
}
@@ -1071,20 +1055,12 @@ cdu_ioctl(struct inode *inode,
unsigned int cmd,
unsigned long arg)
{
- unsigned int dev;
Byte status[2];
Byte cmd_buff[10], params[10];
int i;
int dsc_status;
int err;
- if (!inode) {
- return -EINVAL;
- }
- dev = minor(inode->i_rdev) >> 6;
- if (dev != 0) {
- return -EINVAL;
- }
if (check_drive_status() != 0)
return -EIO;
@@ -1447,11 +1423,11 @@ cdu_release(struct inode *inode,
static struct block_device_operations cdu_fops =
{
- .owner = THIS_MODULE,
- .open = cdu_open,
- .release = cdu_release,
- .ioctl = cdu_ioctl,
- .check_media_change = cdu535_check_media_change,
+ .owner = THIS_MODULE,
+ .open = cdu_open,
+ .release = cdu_release,
+ .ioctl = cdu_ioctl,
+ .media_changed = cdu535_check_media_change,
};
static struct gendisk *cdu_disk;
@@ -1582,10 +1558,9 @@ static int __init sony535_init(void)
err = -EIO;
goto out1;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cdu535_request,
- &sonycd535_lock);
- blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE);
- sony_toc = kamlloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
+ blk_init_queue(&sonycd535_queue, do_cdu535_request, &sonycd535_lock);
+ blk_queue_hardsect_size(&sonycd535_queue, CDU535_BLOCK_SIZE);
+ sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
err = -ENOMEM;
if (!sony_toc)
goto out2;
@@ -1618,6 +1593,7 @@ static int __init sony535_init(void)
sony535_cd_base_io);
goto out7;
}
+ cdu_disk->queue = &sonycd535_queue;
add_disk(cdu_disk);
return 0;
@@ -1634,7 +1610,7 @@ out4:
out3:
kfree(sony_toc);
out2:
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(&sonycd535_queue);
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
out1:
devfs_unregister(sony_devfs_handle);
@@ -1699,6 +1675,7 @@ static sony535_exit(void)
DEVFS_SPECIAL_BLK, 0);
del_gendisk(cdu_disk);
put_disk(cdu_disk);
+ blk_cleanup_queue(&sonycd535_queue);
if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
else
diff --git a/drivers/char/Config.help b/drivers/char/Config.help
index b03cd9da93b0..34e204aca958 100644
--- a/drivers/char/Config.help
+++ b/drivers/char/Config.help
@@ -40,93 +40,6 @@ CONFIG_MWAVE
The module will be called mwave.o. If you want to compile it as
a module, say M here and read Documentation/modules.txt.
-CONFIG_AGP
- AGP (Accelerated Graphics Port) is a bus system mainly used to
- connect graphics cards to the rest of the system.
-
- If you have an AGP system and you say Y here, it will be possible to
- use the AGP features of your 3D rendering video card. This code acts
- as a sort of "AGP driver" for the motherboard's chipset.
-
- If you need more texture memory than you can get with the AGP GART
- (theoretically up to 256 MB, but in practice usually 64 or 128 MB
- due to kernel allocation issues), you could use PCI accesses
- and have up to a couple gigs of texture space.
-
- Note that this is the only means to have XFree4/GLX use
- write-combining with MTRR support on the AGP bus. Without it, OpenGL
- direct rendering will be a lot slower but still faster than PIO.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
- This driver is available as a module. If you want to compile it as
- a module, say M here and read <file:Documentation/modules.txt>. The
- module will be called agpgart.o.
-
-CONFIG_AGP_INTEL
- This option gives you AGP support for the GLX component of the
- XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850 and 860 chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
-CONFIG_AGP_I810
- This option gives you AGP support for the Xserver on the Intel 810
- 815 and 830m chipset boards for their on-board integrated graphics. This
- is required to do any useful video modes with these boards.
-
-CONFIG_AGP_I460
- This option gives you AGP GART support for the Intel 460GX chipset
- for IA64 processors.
-
-CONFIG_AGP_VIA
- This option gives you AGP support for the GLX component of the
- XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
-CONFIG_AGP_AMD
- This option gives you AGP support for the GLX component of the
- XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
-CONFIG_AGP_SIS
- This option gives you AGP support for the GLX component of the "soon
- to be released" XFree86 4.x on Silicon Integrated Systems [SiS]
- chipsets.
-
- Note that 5591/5592 AGP chipsets are NOT supported.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
-CONFIG_AGP_SWORKS
- Say Y here to support the Serverworks AGP card. See
- <http://www.serverworks.com/> for product descriptions and images.
-
-CONFIG_AGP_ALI
- This option gives you AGP support for the GLX component of the
- XFree86 4.x on the following ALi chipsets. The supported chipsets
- include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
- For the ALi-chipset question, ALi suggests you refer to
- <http://www.ali.com.tw/eng/support/index.shtml>.
-
- The M1541 chipset can do AGP 1x and 2x, but note that there is an
- acknowledged incompatibility with Matrox G200 cards. Due to
- timing issues, this chipset cannot do AGP 2x with the G200.
- This is a hardware limitation. AGP 1x seems to be fine, though.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
-CONFIG_AGP_HP_ZX1
- This option gives you AGP GART support for the HP ZX1 chipset
- for IA64 processors.
-
CONFIG_I810_TCO
Hardware driver for the TCO timer built into the Intel i810 and i815
chipset family. The TCO (Total Cost of Ownership) timer is a
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d0be4dd0e8cb..e65360cf6538 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -104,6 +104,9 @@ obj-$(CONFIG_AGP) += agp/
obj-$(CONFIG_DRM) += drm/
obj-$(CONFIG_PCMCIA) += pcmcia/
+# Files generated that shall be removed upon make clean
+clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
+
include $(TOPDIR)/Rules.make
$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE)
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
index 95880a482d79..f55cf6ab41bc 100644
--- a/drivers/char/drm/sis_ds.c
+++ b/drivers/char/drm/sis_ds.c
@@ -50,15 +50,16 @@ set_t *setInit(void)
set_t *set;
set = (set_t *)MALLOC(sizeof(set_t));
- for(i = 0; i < SET_SIZE; i++){
- set->list[i].free_next = i+1;
- set->list[i].alloc_next = -1;
- }
- set->list[SET_SIZE-1].free_next = -1;
- set->free = 0;
- set->alloc = -1;
- set->trace = -1;
-
+ if (set) {
+ for(i = 0; i < SET_SIZE; i++){
+ set->list[i].free_next = i+1;
+ set->list[i].alloc_next = -1;
+ }
+ set->list[SET_SIZE-1].free_next = -1;
+ set->free = 0;
+ set->alloc = -1;
+ set->trace = -1;
+ }
return set;
}
@@ -172,7 +173,8 @@ static void *calloc(size_t nmemb, size_t size)
{
void *addr;
addr = kmalloc(nmemb*size, GFP_KERNEL);
- memset(addr, 0, nmemb*size);
+ if (addr)
+ memset(addr, 0, nmemb*size);
return addr;
}
#define free(n) kfree(n)
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.h b/drivers/char/ftape/lowlevel/ftape-rw.h
index df2b8b0cd93c..f93d224413e0 100644
--- a/drivers/char/ftape/lowlevel/ftape-rw.h
+++ b/drivers/char/ftape/lowlevel/ftape-rw.h
@@ -71,7 +71,7 @@ typedef struct {
/* Count nr of 1's in pattern.
*/
-extern inline int count_ones(unsigned long mask)
+static inline int count_ones(unsigned long mask)
{
int bits;
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.h b/drivers/char/ftape/zftape/zftape-vtbl.h
index 7248db11c9f5..63de244153ce 100644
--- a/drivers/char/ftape/zftape/zftape-vtbl.h
+++ b/drivers/char/ftape/zftape/zftape-vtbl.h
@@ -168,11 +168,11 @@ extern int zft_fake_volume_headers (eof_mark_union *eof_map,
extern int zft_weof (unsigned int count, zft_position *pos);
extern void zft_move_past_eof (zft_position *pos);
-extern inline int zft_tape_at_eod (const zft_position *pos);
-extern inline int zft_tape_at_lbot (const zft_position *pos);
-extern inline void zft_position_before_eof (zft_position *pos,
+static inline int zft_tape_at_eod (const zft_position *pos);
+static inline int zft_tape_at_lbot (const zft_position *pos);
+static inline void zft_position_before_eof (zft_position *pos,
const zft_volinfo *volume);
-extern inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
+static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
const zft_position *pos);
/* this function decrements the zft_seg_pos counter if we are right
@@ -180,7 +180,7 @@ extern inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
* need to position before the eof mark. NOTE: zft_tape_pos is not
* changed
*/
-extern inline void zft_position_before_eof(zft_position *pos,
+static inline void zft_position_before_eof(zft_position *pos,
const zft_volinfo *volume)
{
TRACE_FUN(ft_t_flow);
@@ -195,7 +195,7 @@ extern inline void zft_position_before_eof(zft_position *pos,
/* Mmmh. Is the position at the end of the last volume, that is right
* before the last EOF mark also logical an EOD condition?
*/
-extern inline int zft_tape_at_eod(const zft_position *pos)
+static inline int zft_tape_at_eod(const zft_position *pos)
{
TRACE_FUN(ft_t_any);
@@ -207,7 +207,7 @@ extern inline int zft_tape_at_eod(const zft_position *pos)
}
}
-extern inline int zft_tape_at_lbot(const zft_position *pos)
+static inline int zft_tape_at_lbot(const zft_position *pos)
{
if (zft_qic_mode) {
return (pos->seg_pos <= zft_first_vtbl->start_seg &&
@@ -220,7 +220,7 @@ extern inline int zft_tape_at_lbot(const zft_position *pos)
/* This one checks for EOF. return remaing space (may be negative)
*/
-extern inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
+static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
const zft_position *pos)
{
return (__s64)(vtbl->size - pos->volume_pos);
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 713ed380c7b7..eb6f325bc19c 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -122,7 +122,7 @@ struct miscdevice isiloader_device = {
};
-extern inline int WaitTillCardIsFree(unsigned short base)
+static inline int WaitTillCardIsFree(unsigned short base)
{
unsigned long count=0;
while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
@@ -358,7 +358,7 @@ static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev
return 0;
}
-extern inline void schedule_bh(struct isi_port * port)
+static inline void schedule_bh(struct isi_port * port)
{
queue_task(&port->bh_tqueue, &tq_isicom);
mark_bh(ISICOM_BH);
@@ -823,7 +823,7 @@ static void isicom_config_port(struct isi_port * port)
/* open et all */
-extern inline void isicom_setup_board(struct isi_board * bp)
+static inline void isicom_setup_board(struct isi_board * bp)
{
int channel;
struct isi_port * port;
@@ -1091,7 +1091,7 @@ static int isicom_open(struct tty_struct * tty, struct file * filp)
/* close et all */
-extern inline void isicom_shutdown_board(struct isi_board * bp)
+static inline void isicom_shutdown_board(struct isi_board * bp)
{
int channel;
struct isi_port * port;
@@ -1353,7 +1353,7 @@ static int isicom_chars_in_buffer(struct tty_struct * tty)
}
/* ioctl et all */
-extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
+static inline void isicom_send_break(struct isi_port * port, unsigned long length)
{
struct isi_board * card = port->card;
short wait = 10;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index b8fdb02ba674..baa80dfb6626 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -53,7 +53,6 @@
#include <linux/fcntl.h>
#include <linux/major.h>
#include <linux/delay.h>
-#include <linux/tqueue.h>
#include <linux/version.h>
#include <linux/pci.h>
#include <linux/slab.h>
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index b4d46077daa8..c04abce4a6c3 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -239,28 +239,28 @@ static inline int sx_paranoia_check(struct specialix_port const * port,
*/
/* Get board number from pointer */
-extern inline int board_No (struct specialix_board * bp)
+static inline int board_No (struct specialix_board * bp)
{
return bp - sx_board;
}
/* Get port number from pointer */
-extern inline int port_No (struct specialix_port const * port)
+static inline int port_No (struct specialix_port const * port)
{
return SX_PORT(port - sx_port);
}
/* Get pointer to board from pointer to port */
-extern inline struct specialix_board * port_Board(struct specialix_port const * port)
+static inline struct specialix_board * port_Board(struct specialix_port const * port)
{
return &sx_board[SX_BOARD(port - sx_port)];
}
/* Input Byte from CL CD186x register */
-extern inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
+static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
{
bp->reg = reg | 0x80;
outb (reg | 0x80, bp->base + SX_ADDR_REG);
@@ -269,7 +269,7 @@ extern inline unsigned char sx_in(struct specialix_board * bp, unsigned short r
/* Output Byte to CL CD186x register */
-extern inline void sx_out(struct specialix_board * bp, unsigned short reg,
+static inline void sx_out(struct specialix_board * bp, unsigned short reg,
unsigned char val)
{
bp->reg = reg | 0x80;
@@ -279,7 +279,7 @@ extern inline void sx_out(struct specialix_board * bp, unsigned short reg,
/* Input Byte from CL CD186x register */
-extern inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
+static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
{
bp->reg = reg;
outb (reg, bp->base + SX_ADDR_REG);
@@ -288,7 +288,7 @@ extern inline unsigned char sx_in_off(struct specialix_board * bp, unsigned sho
/* Output Byte to CL CD186x register */
-extern inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
+static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
unsigned char val)
{
bp->reg = reg;
@@ -298,7 +298,7 @@ extern inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
/* Wait for Channel Command Register ready */
-extern inline void sx_wait_CCR(struct specialix_board * bp)
+static inline void sx_wait_CCR(struct specialix_board * bp)
{
unsigned long delay;
@@ -311,7 +311,7 @@ extern inline void sx_wait_CCR(struct specialix_board * bp)
/* Wait for Channel Command Register ready */
-extern inline void sx_wait_CCR_off(struct specialix_board * bp)
+static inline void sx_wait_CCR_off(struct specialix_board * bp)
{
unsigned long delay;
@@ -327,13 +327,13 @@ extern inline void sx_wait_CCR_off(struct specialix_board * bp)
* specialix IO8+ IO range functions.
*/
-extern inline int sx_check_io_range(struct specialix_board * bp)
+static inline int sx_check_io_range(struct specialix_board * bp)
{
return check_region (bp->base, SX_IO_SPACE);
}
-extern inline void sx_request_io_range(struct specialix_board * bp)
+static inline void sx_request_io_range(struct specialix_board * bp)
{
request_region(bp->base,
bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE,
@@ -341,7 +341,7 @@ extern inline void sx_request_io_range(struct specialix_board * bp)
}
-extern inline void sx_release_io_range(struct specialix_board * bp)
+static inline void sx_release_io_range(struct specialix_board * bp)
{
release_region(bp->base,
bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
@@ -351,7 +351,7 @@ extern inline void sx_release_io_range(struct specialix_board * bp)
/* Must be called with enabled interrupts */
/* Ugly. Very ugly. Don't use this for anything else than initialization
code */
-extern inline void sx_long_delay(unsigned long delay)
+static inline void sx_long_delay(unsigned long delay)
{
unsigned long i;
@@ -599,7 +599,7 @@ static int sx_probe(struct specialix_board *bp)
* Interrupt processing routines.
* */
-extern inline void sx_mark_event(struct specialix_port * port, int event)
+static inline void sx_mark_event(struct specialix_port * port, int event)
{
/*
* I'm not quite happy with current scheme all serial
@@ -616,7 +616,7 @@ extern inline void sx_mark_event(struct specialix_port * port, int event)
}
-extern inline struct specialix_port * sx_get_port(struct specialix_board * bp,
+static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
unsigned char const * what)
{
unsigned char channel;
@@ -635,7 +635,7 @@ extern inline struct specialix_port * sx_get_port(struct specialix_board * bp,
}
-extern inline void sx_receive_exc(struct specialix_board * bp)
+static inline void sx_receive_exc(struct specialix_board * bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -701,7 +701,7 @@ extern inline void sx_receive_exc(struct specialix_board * bp)
}
-extern inline void sx_receive(struct specialix_board * bp)
+static inline void sx_receive(struct specialix_board * bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -732,7 +732,7 @@ extern inline void sx_receive(struct specialix_board * bp)
}
-extern inline void sx_transmit(struct specialix_board * bp)
+static inline void sx_transmit(struct specialix_board * bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -802,7 +802,7 @@ extern inline void sx_transmit(struct specialix_board * bp)
}
-extern inline void sx_check_modem(struct specialix_board * bp)
+static inline void sx_check_modem(struct specialix_board * bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -962,7 +962,7 @@ void turn_ints_on (struct specialix_board *bp)
/* Called with disabled interrupts */
-extern inline int sx_setup_board(struct specialix_board * bp)
+static inline int sx_setup_board(struct specialix_board * bp)
{
int error;
@@ -986,7 +986,7 @@ extern inline int sx_setup_board(struct specialix_board * bp)
/* Called with disabled interrupts */
-extern inline void sx_shutdown_board(struct specialix_board *bp)
+static inline void sx_shutdown_board(struct specialix_board *bp)
{
if (!(bp->flags & SX_BOARD_ACTIVE))
return;
@@ -1867,7 +1867,7 @@ static int sx_set_modem_info(struct specialix_port * port, unsigned int cmd,
}
-extern inline void sx_send_break(struct specialix_port * port, unsigned long length)
+static inline void sx_send_break(struct specialix_port * port, unsigned long length)
{
struct specialix_board *bp = port_Board(port);
unsigned long flags;
@@ -1886,7 +1886,7 @@ extern inline void sx_send_break(struct specialix_port * port, unsigned long len
}
-extern inline int sx_set_serial_info(struct specialix_port * port,
+static inline int sx_set_serial_info(struct specialix_port * port,
struct serial_struct * newinfo)
{
struct serial_struct tmp;
@@ -1942,7 +1942,7 @@ extern inline int sx_set_serial_info(struct specialix_port * port,
}
-extern inline int sx_get_serial_info(struct specialix_port * port,
+static inline int sx_get_serial_info(struct specialix_port * port,
struct serial_struct * retinfo)
{
struct serial_struct tmp;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 8fffe423ab14..864053a676dd 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2647,7 +2647,6 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *devinfo = &info->devinfo;
- devinfo->dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
devinfo->ops = &ide_cdrom_dops;
devinfo->mask = 0;
devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
@@ -3026,15 +3025,9 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int error;
-
- /* Try the generic SCSI command ioctl's first.. */
- error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
- if (error != -ENOTTY)
- return error;
+ struct cdrom_info *info = drive->driver_data;
- /* Then the generic cdrom ioctl's.. */
- return cdrom_ioctl(inode, file, cmd, arg);
+ return cdrom_ioctl(&info->devinfo, inode, cmd, arg);
}
static
@@ -3044,9 +3037,9 @@ int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
int rc = -ENOMEM;
MOD_INC_USE_COUNT;
- if (info->buffer == NULL)
+ if (!info->buffer)
info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
- if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) {
+ if (!info->buffer || (rc = cdrom_open(&info->devinfo, ip, fp))) {
drive->usage--;
MOD_DEC_USE_COUNT;
}
@@ -3057,15 +3050,16 @@ static
void ide_cdrom_release (struct inode *inode, struct file *file,
ide_drive_t *drive)
{
- cdrom_release (inode, file);
+ struct cdrom_info *info = drive->driver_data;
+ cdrom_release (&info->devinfo, file);
MOD_DEC_USE_COUNT;
}
static
int ide_cdrom_check_media_change (ide_drive_t *drive)
{
- return cdrom_media_changed(mk_kdev(drive->disk->major,
- drive->disk->first_minor));
+ struct cdrom_info *info = drive->driver_data;
+ return cdrom_media_changed(&info->devinfo);
}
static
diff --git a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c
index dba3cda964aa..52d5e84726e4 100644
--- a/drivers/ide/ide-geometry.c
+++ b/drivers/ide/ide-geometry.c
@@ -83,7 +83,6 @@ void probe_cmos_for_drives (ide_hwif_t *hwif)
}
-extern ide_drive_t * get_info_ptr(kdev_t);
extern unsigned long current_capacity (ide_drive_t *);
/*
@@ -147,19 +146,15 @@ static void ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int
* Returns 1 if the geometry translation was successful.
*/
-int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg)
+int ide_xlate_1024 (struct block_device *bdev, int xparm, int ptheads, const char *msg)
{
- ide_drive_t *drive;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
const char *msg1 = "";
int heads = 0;
int c, h, s;
int transl = 1; /* try translation */
int ret = 0;
- drive = get_info_ptr(i_rdev);
- if (!drive)
- return 0;
-
/* remap? */
if (drive->remap_0_to_1 != 2) {
if (xparm == 1) { /* DM */
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 478bffc6aed8..3cb2ffff7c91 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -47,6 +47,7 @@
#include <linux/ide.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
+#include <linux/kmod.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -971,6 +972,41 @@ int init_irq (ide_hwif_t *hwif)
EXPORT_SYMBOL(init_irq);
+static void ata_lock(dev_t dev, void *data)
+{
+ ide_hwif_t *hwif = data;
+ int unit = MINOR(dev) >> PARTN_BITS;
+ get_disk(hwif->drives[unit].disk);
+}
+
+struct gendisk *ata_probe(dev_t dev, int *part, void *data)
+{
+ ide_hwif_t *hwif = data;
+ int unit = MINOR(dev) >> PARTN_BITS;
+ ide_drive_t *drive = &hwif->drives[unit];
+ if (!drive->present) {
+ put_disk(drive->disk);
+ return NULL;
+ }
+ if (!drive->driver) {
+ if (drive->media == ide_disk)
+ (void) request_module("ide-disk");
+ if (drive->scsi)
+ (void) request_module("ide-scsi");
+ if (drive->media == ide_cdrom)
+ (void) request_module("ide-cd");
+ if (drive->media == ide_tape)
+ (void) request_module("ide-tape");
+ if (drive->media == ide_floppy)
+ (void) request_module("ide-floppy");
+ }
+ if (!drive->driver) {
+ put_disk(drive->disk);
+ return NULL;
+ }
+ return drive->disk;
+}
+
/*
* init_gendisk() (as opposed to ide_geninit) is called for each major device,
* after probing for drives, to allocate partition tables and other data
@@ -992,12 +1028,15 @@ static void init_gendisk (ide_hwif_t *hwif)
}
for (unit = 0; unit < units; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
struct gendisk *disk = disks[unit];
disk->major = hwif->major;
disk->first_minor = unit << PARTN_BITS;
sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit);
disk->fops = ide_fops;
- hwif->drives[unit].disk = disk;
+ disk->private_data = drive;
+ disk->queue = &drive->queue;
+ drive->disk = disk;
}
for (unit = 0; unit < units; ++unit) {
@@ -1024,6 +1063,9 @@ static void init_gendisk (ide_hwif_t *hwif)
device_register(&drive->gendev);
}
+ blk_register_region(MKDEV(hwif->major, 0), units << PARTN_BITS,
+ THIS_MODULE, ata_probe, ata_lock, hwif);
+
return;
err_kmalloc_gd:
@@ -1083,10 +1125,7 @@ int hwif_init (ide_hwif_t *hwif)
printk("%s: probed IRQ %d failed, using default.\n",
hwif->name, hwif->irq);
}
-
init_gendisk(hwif);
- blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].queue = ide_get_queue;
hwif->present = 1; /* success */
return 1;
}
@@ -1150,7 +1189,7 @@ int ideprobe_init (void)
}
#ifdef MODULE
-extern int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
+extern int (*ide_xlate_1024_hook)(struct block_device *, int, int, const char *);
int init_module (void)
{
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 00830680bb42..23d39bcf3e0b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -878,7 +878,6 @@ ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
unsigned long block;
- unsigned int minor = minor(rq->rq_dev), unit = minor >> PARTN_BITS;
ide_hwif_t *hwif = HWIF(drive);
BUG_ON(!(rq->flags & REQ_STARTED));
@@ -897,15 +896,8 @@ ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
* bail early if we've sent a device to sleep, however how to wake
* this needs to be a masked flag. FIXME for proper operations.
*/
- if (drive->suspend_reset) {
+ if (drive->suspend_reset)
goto kill_rq;
- }
-
- if (unit >= MAX_DRIVES) {
- printk("%s: bad device number: %s\n",
- hwif->name, kdevname(rq->rq_dev));
- goto kill_rq;
- }
block = rq->sector;
if (blk_fs_request(rq) &&
@@ -1172,18 +1164,6 @@ queue_next:
EXPORT_SYMBOL(ide_do_request);
/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-request_queue_t *ide_get_queue (kdev_t dev)
-{
- ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[major(dev)].data;
-
- return &hwif->drives[DEVICE_NR(dev) & 1].queue;
-}
-
-EXPORT_SYMBOL(ide_get_queue);
-
-/*
* Passes the stuff to ide_do_request
*/
void do_ide_request(request_queue_t *q)
@@ -1496,32 +1476,6 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
EXPORT_SYMBOL(ide_intr);
/*
- * get_info_ptr() returns the (ide_drive_t *) for a given device number.
- * It returns NULL if the given device number does not match any present drives.
- */
-ide_drive_t *get_info_ptr (kdev_t i_rdev)
-{
- int major = major(i_rdev);
- unsigned int h;
-
- for (h = 0; h < MAX_HWIFS; ++h) {
- ide_hwif_t *hwif = &ide_hwifs[h];
- if (hwif->present && major == hwif->major) {
- unsigned unit = DEVICE_NR(i_rdev);
- if (unit < MAX_DRIVES) {
- ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present)
- return drive;
- }
- break;
- }
- }
- return NULL;
-}
-
-EXPORT_SYMBOL(get_info_ptr);
-
-/*
* This function is intended to be used prior to invoking ide_do_drive_cmd().
*/
void ide_init_drive_cmd (struct request *rq)
@@ -1572,7 +1526,20 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
#endif
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
- rq->rq_dev = mk_kdev(major,(drive->select.b.unit)<<PARTN_BITS);
+
+ /*
+ * Aiee. This is ugly, but it gets called before "drive->disk"
+ * has been initialized. Al will fix it, I'm sure.
+ */
+ if (drive->disk)
+ rq->rq_dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
+ else {
+ printk("IDE init is ugly:");
+ dump_stack();
+ rq->rq_dev = mk_kdev(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS);
+ }
+
+ rq->rq_disk = drive->disk;
if (action == ide_wait)
rq->waiting = &wait;
spin_lock_irqsave(&ide_lock, flags);
@@ -1615,18 +1582,14 @@ EXPORT_SYMBOL(ide_revalidate_drive);
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
-int ide_revalidate_disk (kdev_t i_rdev)
+static int ide_revalidate_disk(struct gendisk *disk)
{
- ide_drive_t *drive;
- if ((drive = get_info_ptr(i_rdev)) == NULL)
- return -ENODEV;
+ ide_drive_t *drive = disk->private_data;
if (DRIVER(drive)->revalidate)
DRIVER(drive)->revalidate(drive);
return 0;
}
-EXPORT_SYMBOL(ide_revalidate_disk);
-
void ide_probe_module (void)
{
if (!ide_probe) {
@@ -1642,28 +1605,9 @@ EXPORT_SYMBOL(ide_probe_module);
static int ide_open (struct inode * inode, struct file * filp)
{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
- return -ENXIO;
- if (drive->driver == NULL) {
- if (drive->media == ide_disk)
- (void) request_module("ide-disk");
- if (drive->scsi)
- (void) request_module("ide-scsi");
- if (drive->media == ide_cdrom)
- (void) request_module("ide-cd");
- if (drive->media == ide_tape)
- (void) request_module("ide-tape");
- if (drive->media == ide_floppy)
- (void) request_module("ide-floppy");
- }
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
drive->usage++;
- if (drive->driver != NULL)
- return DRIVER(drive)->open(inode, filp, drive);
- printk (KERN_WARNING "%s: driver not present\n", drive->name);
- drive->usage--;
- return -ENXIO;
+ return DRIVER(drive)->open(inode, filp, drive);
}
/*
@@ -1672,13 +1616,9 @@ static int ide_open (struct inode * inode, struct file * filp)
*/
static int ide_release (struct inode * inode, struct file * file)
{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {
- drive->usage--;
- if (drive->driver != NULL)
- DRIVER(drive)->release(inode, file, drive);
- }
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ DRIVER(drive)->release(inode, file, drive);
+ drive->usage--;
return 0;
}
@@ -1772,7 +1712,6 @@ void ide_unregister (unsigned int index)
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit, i;
unsigned long flags;
- unsigned int p, minor;
ide_hwif_t old_hwif;
if (index >= MAX_HWIFS)
@@ -1792,25 +1731,10 @@ void ide_unregister (unsigned int index)
}
hwif->present = 0;
- /*
- * All clear? Then blow away the buffer cache
- */
spin_unlock_irqrestore(&ide_lock, flags);
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- drive = &hwif->drives[unit];
- if (!drive->present)
- continue;
- minor = drive->select.b.unit << PARTN_BITS;
- for (p = 0; p < (1<<PARTN_BITS); ++p) {
- if (get_capacity(drive->disk)) {
- kdev_t devp = mk_kdev(hwif->major, minor+p);
- invalidate_device(devp, 0);
- }
- }
#ifdef CONFIG_PROC_FS
- destroy_proc_ide_drives(hwif);
+ destroy_proc_ide_drives(hwif);
#endif
- }
spin_lock_irqsave(&ide_lock, flags);
hwgroup = hwif->hwgroup;
@@ -1885,9 +1809,8 @@ void ide_unregister (unsigned int index)
/*
* Remove us from the kernel's knowledge
*/
+ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
unregister_blkdev(hwif->major, hwif->name);
- blk_dev[hwif->major].data = NULL;
- blk_dev[hwif->major].queue = NULL;
for (i = 0; i < MAX_DRIVES; i++) {
struct gendisk *disk = hwif->drives[i].disk;
hwif->drives[i].disk = NULL;
@@ -2482,28 +2405,21 @@ EXPORT_SYMBOL(ata_attach);
static int ide_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int err = 0, major, minor;
- ide_drive_t *drive;
- struct request rq;
- kdev_t dev;
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
ide_settings_t *setting;
-
- major = major(dev); minor = minor(dev);
- if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
- return -ENODEV;
+ int err = 0;
if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
if (cmd == setting->read_ioctl) {
err = ide_read_setting(drive, setting);
return err >= 0 ? put_user(err, (long *) arg) : err;
} else {
- if ((minor(inode->i_rdev) & PARTN_MASK))
+ if (inode->i_bdev != inode->i_bdev->bd_contains)
return -EINVAL;
return ide_write_setting(drive, setting, arg);
}
}
- ide_init_drive_cmd (&rq);
switch (cmd) {
case HDIO_GETGEO:
{
@@ -2532,7 +2448,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY:
- if (minor(inode->i_rdev) & PARTN_MASK)
+ if (inode->i_bdev != inode->i_bdev->bd_contains)
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
@@ -2662,12 +2578,9 @@ static int ide_ioctl (struct inode *inode, struct file *file,
}
}
-static int ide_check_media_change (kdev_t i_rdev)
+static int ide_check_media_change(struct gendisk *disk)
{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(i_rdev)) == NULL)
- return -ENODEV;
+ ide_drive_t *drive = disk->private_data;
if (drive->driver != NULL)
return DRIVER(drive)->media_change(drive);
return 0;
@@ -3491,12 +3404,12 @@ void ide_unregister_driver(ide_driver_t *driver)
EXPORT_SYMBOL(ide_unregister_driver);
struct block_device_operations ide_fops[] = {{
- .owner = THIS_MODULE,
- .open = ide_open,
- .release = ide_release,
- .ioctl = ide_ioctl,
- .check_media_change = ide_check_media_change,
- .revalidate = ide_revalidate_disk
+ .owner = THIS_MODULE,
+ .open = ide_open,
+ .release = ide_release,
+ .ioctl = ide_ioctl,
+ .media_changed = ide_check_media_change,
+ .revalidate_disk= ide_revalidate_disk
}};
EXPORT_SYMBOL(ide_fops);
@@ -3538,8 +3451,6 @@ int __init ide_init (void)
return 0;
}
-module_init(ide_init);
-
#ifdef MODULE
char *options = NULL;
MODULE_PARM(options,"s");
@@ -3589,4 +3500,6 @@ void cleanup_module (void)
__setup("", ide_setup);
+module_init(ide_init);
+
#endif /* MODULE */
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 502d3c90b864..01dc3c0681f2 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -354,7 +354,7 @@ static int __init ps2_init(void)
static void __exit ps2_exit(void)
{
- remove_driver(&ps2_driver.drv);
+ driver_unregister(&ps2_driver.drv);
}
module_init(ps2_init);
diff --git a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile
index 407501c0d6b1..58c4e6d3ed35 100644
--- a/drivers/isdn/i4l/Makefile
+++ b/drivers/isdn/i4l/Makefile
@@ -19,7 +19,7 @@ isdn-objs := isdn_net.o isdn_net_lib.o \
# Optional parts of multipart objects.
-isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o
+isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o
isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o
isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o
isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index 6049970e1f2a..c48275b76141 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -907,16 +907,15 @@ static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *
*************************************************************/
static struct isdn_ppp_compressor ippp_bsd_compress = {
- NULL,NULL, /* prev,next: overwritten by isdn_ppp */
- CI_BSD_COMPRESS, /* compress_proto */
- bsd_alloc, /* alloc */
- bsd_free, /* free */
- bsd_init, /* init */
- bsd_reset, /* reset */
- bsd_compress, /* compress */
- bsd_decompress, /* decompress */
- bsd_incomp, /* incomp */
- bsd_stats /* comp_stat */
+ .num = CI_BSD_COMPRESS,
+ .alloc = bsd_alloc,
+ .free = bsd_free,
+ .init = bsd_init,
+ .reset = bsd_reset,
+ .compress = bsd_compress,
+ .decompress = bsd_decompress,
+ .incomp = bsd_incomp,
+ .stat = bsd_stats,
};
/*************************************************************
diff --git a/drivers/isdn/i4l/isdn_ciscohdlck.c b/drivers/isdn/i4l/isdn_ciscohdlck.c
index 0f08f3daea88..cab5b1a2100f 100644
--- a/drivers/isdn/i4l/isdn_ciscohdlck.c
+++ b/drivers/isdn/i4l/isdn_ciscohdlck.c
@@ -20,6 +20,19 @@
#include <linux/if_arp.h>
#include <linux/inetdevice.h>
+/*
+ * Definitions for Cisco-HDLC header.
+ */
+
+#define CISCO_ADDR_UNICAST 0x0f
+#define CISCO_ADDR_BROADCAST 0x8f
+#define CISCO_CTRL 0x00
+#define CISCO_TYPE_CDP 0x2000
+#define CISCO_TYPE_SLARP 0x8035
+#define CISCO_SLARP_REQUEST 0
+#define CISCO_SLARP_REPLY 1
+#define CISCO_SLARP_KEEPALIVE 2
+
/*
* CISCO HDLC keepalive specific stuff
*/
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index 3c81ffcb5d80..64e1c1e9c819 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -47,7 +47,7 @@
#endif
#define isdn_BUG() \
-do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
+do { printk(KERN_WARNING "ISDN BUG at %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 4b504da722de..f41603c1287d 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -33,412 +33,8 @@
#include "isdn_concap.h"
#include "isdn_ciscohdlck.h"
-/*
- * Outline of new tbusy handling:
- *
- * Old method, roughly spoken, consisted of setting tbusy when entering
- * isdn_net_start_xmit() and at several other locations and clearing
- * it from isdn_net_start_xmit() thread when sending was successful.
- *
- * With 2.3.x multithreaded network core, to prevent problems, tbusy should
- * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
- * condition is detected. Other threads (in particular isdn_net_stat_callb())
- * are only allowed to clear tbusy.
- *
- * -HE
- */
-
-/*
- * About SOFTNET:
- * Most of the changes were pretty obvious and basically done by HE already.
- *
- * One problem of the isdn net device code is that is uses struct net_device
- * for masters and slaves. However, only master interface are registered to
- * the network layer, and therefore, it only makes sense to call netif_*
- * functions on them.
- *
- * --KG
- */
-
-/*
- * Find out if the netdevice has been ifup-ed yet.
- */
-static inline int
-isdn_net_device_started(isdn_net_dev *idev)
-{
- return netif_running(&idev->mlp->dev);
-}
-
-/*
- * stop the network -> net_device queue.
- */
-static inline void
-isdn_net_dev_stop_queue(isdn_net_dev *idev)
-{
- netif_stop_queue(&idev->mlp->dev);
-}
-
-/*
- * find out if the net_device which this lp belongs to (lp can be
- * master or slave) is busy. It's busy iff all (master and slave)
- * queues are busy
- */
-static inline int
-isdn_net_device_busy(isdn_net_dev *idev)
-{
- isdn_net_local *mlp = idev->mlp;
- unsigned long flags;
- int retval = 1;
-
- if (!isdn_net_dev_busy(idev))
- return 0;
-
- spin_lock_irqsave(&mlp->online_lock, flags);
- list_for_each_entry(idev, &mlp->online, online) {
- if (!isdn_net_dev_busy(idev)) {
- retval = 0;
- break;
- }
- }
- spin_unlock_irqrestore(&mlp->online_lock, flags);
- return retval;
-}
-
-static inline
-void isdn_net_inc_frame_cnt(isdn_net_dev *idev)
-{
- atomic_inc(&idev->frame_cnt);
- if (isdn_net_device_busy(idev))
- isdn_net_dev_stop_queue(idev);
-}
-
-static inline void
-isdn_net_dec_frame_cnt(isdn_net_dev *idev)
-{
- atomic_dec(&idev->frame_cnt);
-
- if (!isdn_net_device_busy(idev)) {
- if (!skb_queue_empty(&idev->super_tx_queue))
- tasklet_schedule(&idev->tlet);
- else
- isdn_net_dev_wake_queue(idev);
- }
-}
-
-static inline
-void isdn_net_zero_frame_cnt(isdn_net_dev *idev)
-{
- atomic_set(&idev->frame_cnt, 0);
-}
-
-/* Prototypes */
-
-int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg);
-
char *isdn_net_revision = "$Revision: 1.140.6.11 $";
-/* A packet has successfully been sent out. */
-
-int
-isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c)
-{
- isdn_net_local *mlp = idev->mlp;
-
- isdn_net_dec_frame_cnt(idev);
- mlp->stats.tx_packets++;
- mlp->stats.tx_bytes += c->parm.length;
- return 1;
-}
-
-static void
-isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
-{
- u_short proto = ntohs(skb->protocol);
-
- printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
- dev->name,
- (reason != NULL) ? reason : "unknown",
- (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
-
- dst_link_failure(skb);
-}
-
-static void
-isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev)
-{
- unsigned char *p = skb->nh.raw; /* hopefully, this was set correctly */
- unsigned short proto = ntohs(skb->protocol);
- int data_ofs;
- struct ip_ports {
- unsigned short source;
- unsigned short dest;
- } *ipp;
- char addinfo[100];
-
- data_ofs = ((p[0] & 15) * 4);
- switch (proto) {
- case ETH_P_IP:
- switch (p[9]) {
- case IPPROTO_ICMP:
- strcpy(addinfo, "ICMP");
- break;
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- ipp = (struct ip_ports *) (&p[data_ofs]);
- sprintf(addinfo, "%s, port: %d -> %d",
- p[9] == IPPROTO_TCP ? "TCP" : "UDP",
- ntohs(ipp->source), ntohs(ipp->dest));
- break;
- default:
- sprintf(addinfo, "type %d", p[9]);
- }
- printk(KERN_INFO
- "OPEN: %u.%u.%u.%u -> %u.%u.%u.%u %s\n",
-
- NIPQUAD(*(u32 *)(p + 12)), NIPQUAD(*(u32 *)(p + 16)),
- addinfo);
- break;
- case ETH_P_ARP:
- printk(KERN_INFO
- "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
- NIPQUAD(*(u32 *)(p + 14)), NIPQUAD(*(u32 *)(p + 24)));
- break;
- default:
- printk(KERN_INFO "OPEN: unknown proto %#x\n", proto);
- }
-}
-
-/*
- * this function is used to send supervisory data, i.e. data which was
- * not received from the network layer, but e.g. frames from ipppd, CCP
- * reset frames etc.
- */
-void
-isdn_net_write_super(isdn_net_dev *idev, struct sk_buff *skb)
-{
- if (in_irq()) {
- // we can't grab the lock from irq context,
- // so we just queue the packet
- skb_queue_tail(&idev->super_tx_queue, skb);
-
- tasklet_schedule(&idev->tlet);
- return;
- }
-
- spin_lock_bh(&idev->xmit_lock);
- if (!isdn_net_dev_busy(idev)) {
- isdn_net_writebuf_skb(idev, skb);
- } else {
- skb_queue_tail(&idev->super_tx_queue, skb);
- }
- spin_unlock_bh(&idev->xmit_lock);
-}
-
-/*
- * all frames sent from the (net) LL to a HL driver should go via this function
- * it's serialized by the caller holding the idev->xmit_lock spinlock
- */
-void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
-{
- isdn_net_local *mlp = idev->mlp;
- int ret;
- int len = skb->len; /* save len */
-
- /* before obtaining the lock the caller should have checked that
- the lp isn't busy */
- if (isdn_net_dev_busy(idev)) {
- isdn_BUG();
- goto error;
- }
-
- if (!isdn_net_online(idev)) {
- isdn_BUG();
- goto error;
- }
- ret = isdn_slot_write(idev->isdn_slot, skb);
- if (ret != len) {
- /* we should never get here */
- printk(KERN_WARNING "%s: HL driver queue full\n", idev->name);
- goto error;
- }
-
- idev->transcount += len;
- isdn_net_inc_frame_cnt(idev);
- return;
-
- error:
- dev_kfree_skb(skb);
- mlp->stats.tx_errors++;
-}
-
-static void
-isdn_net_dial_slave(isdn_net_local *mlp)
-{
- isdn_net_dev *idev;
-
- list_for_each_entry(idev, &mlp->slaves, slaves) {
- if (!isdn_net_bound(idev)) {
- isdn_net_dial(idev);
- break;
- }
- }
-}
-
-/*
- * Based on cps-calculation, check if device is overloaded.
- * If so, and if a slave exists, trigger dialing for it.
- * If any slave is online, deliver packets using a simple round robin
- * scheme.
- *
- * Return: 0 on success, !0 on failure.
- */
-
-int
-isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
- isdn_net_dev *idev;
- isdn_net_local *mlp = ndev->priv;
-
- ndev->trans_start = jiffies;
-
- if (list_empty(&mlp->online))
- return isdn_net_autodial(skb, ndev);
-
- idev = isdn_net_get_locked_dev(mlp);
- if (!idev) {
- printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
- netif_stop_queue(ndev);
- return 1;
- }
- /* we have our idev locked from now on */
-
- isdn_net_writebuf_skb(idev, skb);
- spin_unlock_bh(&idev->xmit_lock);
-
- /* the following stuff is here for backwards compatibility.
- * in future, start-up and hangup of slaves (based on current load)
- * should move to userspace and get based on an overall cps
- * calculation
- */
- if (jiffies != idev->last_jiffies) {
- idev->cps = idev->transcount * HZ / (jiffies - idev->last_jiffies);
- idev->last_jiffies = jiffies;
- idev->transcount = 0;
- }
- if (dev->net_verbose > 3)
- printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
-
- if (idev->cps > mlp->triggercps) {
- if (!idev->sqfull) {
- /* First time overload: set timestamp only */
- idev->sqfull = 1;
- idev->sqfull_stamp = jiffies;
- } else {
- /* subsequent overload: if slavedelay exceeded, start dialing */
- if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) {
- isdn_net_dial_slave(mlp);
- }
- }
- } else {
- if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) {
- idev->sqfull = 0;
- }
- /* this is a hack to allow auto-hangup for slaves on moderate loads */
- list_del(&mlp->online);
- list_add_tail(&mlp->online, &idev->online);
- }
-
- return 0;
-}
-
-int
-isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
-{
- isdn_net_local *mlp = ndev->priv;
- isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
-
- /* are we dialing already? */
- if (isdn_net_bound(idev))
- goto stop_queue;
-
- if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
- goto discard;
-
- if (isdn_net_dial(idev) < 0)
- goto discard;
-
- /* Log packet, which triggered dialing */
- if (dev->net_verbose)
- isdn_net_log_skb(skb, idev);
-
- stop_queue:
- netif_stop_queue(ndev);
- return 1;
-
- discard:
- isdn_net_unreachable(ndev, skb, "dial rejected");
- dev_kfree_skb(skb);
- return 0;
-}
-
-
-/*
- * Got a packet from ISDN-Channel.
- */
-static void
-isdn_net_receive(isdn_net_dev *idev, struct sk_buff *skb)
-{
- isdn_net_local *mlp = idev->mlp;
-
- idev->transcount += skb->len;
-
- mlp->stats.rx_packets++;
- mlp->stats.rx_bytes += skb->len;
- skb->dev = &mlp->dev;
- skb->pkt_type = PACKET_HOST;
- skb->mac.raw = skb->data;
- isdn_dumppkt("R:", skb->data, skb->len, 40);
-
- mlp->ops->receive(mlp, idev, skb);
-}
-
-/*
- * A packet arrived via ISDN. Search interface-chain for a corresponding
- * interface. If found, deliver packet to receiver-function and return 1,
- * else return 0.
- */
-int
-isdn_net_rcv_skb(int idx, struct sk_buff *skb)
-{
- isdn_net_dev *idev = isdn_slot_idev(idx);
-
- if (!idev) {
- HERE;
- return 0;
- }
- if (!isdn_net_online(idev))
- return 0;
-
- isdn_net_receive(idev, skb);
- return 0;
-}
-
-/*
- * This is called from certain upper protocol layers (multilink ppp
- * and x25iface encapsulation module) that want to initiate dialing
- * themselves.
- */
-int
-isdn_net_dial_req(isdn_net_dev *idev)
-{
- isdn_net_local *mlp = idev->mlp;
- /* is there a better error code? */
- if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
- return -EBUSY;
-
- return isdn_net_dial(idev);
-}
-
// ISDN_NET_ENCAP_IPTYP
// ethernet type field
// ======================================================================
@@ -581,6 +177,8 @@ static struct isdn_netif_ops ether_ops = {
void
isdn_net_init(void)
{
+ isdn_net_lib_init();
+
register_isdn_netif(ISDN_NET_ENCAP_ETHER, &ether_ops);
register_isdn_netif(ISDN_NET_ENCAP_RAWIP, &rawip_ops);
register_isdn_netif(ISDN_NET_ENCAP_IPTYP, &iptyp_ops);
@@ -593,7 +191,11 @@ isdn_net_init(void)
#ifdef CONFIG_ISDN_PPP
register_isdn_netif(ISDN_NET_ENCAP_SYNCPPP, &isdn_ppp_ops);
#endif
+}
- isdn_net_lib_init();
+void
+isdn_net_exit(void)
+{
+ isdn_net_lib_exit();
}
diff --git a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h
index 16a443f584dd..14f94befc91f 100644
--- a/drivers/isdn/i4l/isdn_net.h
+++ b/drivers/isdn/i4l/isdn_net.h
@@ -14,138 +14,29 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/isdn.h>
- /* Definitions for hupflags: */
-#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */
-#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */
-#define ISDN_MANCHARGE 16 /* Charge Interval manually set */
-/*
- * Definitions for Cisco-HDLC header.
- */
-
-#define CISCO_ADDR_UNICAST 0x0f
-#define CISCO_ADDR_BROADCAST 0x8f
-#define CISCO_CTRL 0x00
-#define CISCO_TYPE_CDP 0x2000
-#define CISCO_TYPE_SLARP 0x8035
-#define CISCO_SLARP_REQUEST 0
-#define CISCO_SLARP_REPLY 1
-#define CISCO_SLARP_KEEPALIVE 2
-
-extern void isdn_net_init(void);
-extern void isdn_net_exit(void);
-extern void isdn_net_lib_init(void);
-extern void isdn_net_lib_exit(void);
-extern void isdn_net_hangup_all(void);
-extern int isdn_net_ioctl(struct inode *, struct file *, uint, ulong);
-
-extern int register_isdn_netif(int encap, struct isdn_netif_ops *ops);
-extern int isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev);
-extern int isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev);
-
-extern int isdn_net_dial(isdn_net_dev *idev);
-
-extern int isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c);
-
-extern int isdn_net_stat_callback(int, isdn_ctrl *);
-extern int isdn_net_find_icall(int, int, int, setup_parm *);
-extern int isdn_net_hangup(isdn_net_dev *);
-extern int isdn_net_rcv_skb(int, struct sk_buff *);
-extern int isdn_net_dial_req(isdn_net_dev *);
-extern void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb);
-extern void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
-extern int isdn_net_online(isdn_net_dev *);
-
-enum {
- ST_CHARGE_NULL,
- ST_CHARGE_GOT_CINF, /* got a first charge info */
- ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */
-};
-
-#define ISDN_NET_MAX_QUEUE_LENGTH 2
-
-/*
- * is this particular channel busy?
- */
-static inline int
-isdn_net_dev_busy(isdn_net_dev *idev)
-{
- if (atomic_read(&idev->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH)
- return 0;
- else
- return 1;
-}
-
-/*
- * For the given net device, this will get a non-busy channel out of the
- * corresponding bundle. The returned channel is locked.
- */
-static inline isdn_net_dev *
-isdn_net_get_locked_dev(isdn_net_local *mlp)
-{
- unsigned long flags;
- isdn_net_dev *idev;
-
- spin_lock_irqsave(&mlp->online_lock, flags);
-
- list_for_each_entry(idev, &mlp->online, online) {
- spin_lock_bh(&idev->xmit_lock);
- if (!isdn_net_dev_busy(idev)) {
- /* point the head to next online channel */
- list_del(&mlp->online);
- list_add(&mlp->online, &idev->online);
- goto found;
- }
- spin_unlock_bh(&idev->xmit_lock);
- }
- idev = NULL;
-
- found:
- spin_unlock_irqrestore(&mlp->online_lock, flags);
- return idev;
-}
-
-/*
- * add a channel to a bundle
- */
-static inline void
-isdn_net_add_to_bundle(isdn_net_local *mlp, isdn_net_dev *idev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mlp->online_lock, flags);
- list_add(&idev->online, &mlp->online);
- spin_unlock_irqrestore(&mlp->online_lock, flags);
-}
-/*
- * remove a channel from the bundle it belongs to
- */
-static inline void
-isdn_net_rm_from_bundle(isdn_net_dev *idev)
-{
- isdn_net_local *mlp = idev->mlp;
- unsigned long flags;
-
- spin_lock_irqsave(&mlp->online_lock, flags);
- // list_del(&idev->online); FIXME
- spin_unlock_irqrestore(&mlp->online_lock, flags);
-}
-
-/*
- * wake up the network -> net_device queue.
- * For slaves, wake the corresponding master interface.
- */
-static inline void
-isdn_net_dev_wake_queue(isdn_net_dev *idev)
-{
- netif_wake_queue(&idev->mlp->dev);
-}
-
-static inline int
-isdn_net_bound(isdn_net_dev *idev)
-{
- return idev->isdn_slot >= 0;
-}
+void isdn_net_init(void);
+void isdn_net_exit(void);
+void isdn_net_lib_init(void);
+void isdn_net_lib_exit(void);
+void isdn_net_hangup_all(void);
+int isdn_net_ioctl(struct inode *, struct file *, uint, ulong);
+
+int register_isdn_netif(int encap, struct isdn_netif_ops *ops);
+int isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+void isdn_net_online(isdn_net_dev *idev);
+void isdn_net_offline(isdn_net_dev *idev);
+
+int isdn_net_stat_callback(int, isdn_ctrl *);
+int isdn_net_find_icall(int, int, int, setup_parm *);
+int isdn_net_rcv_skb(int, struct sk_buff *);
+
+int isdn_net_hangup(isdn_net_dev *);
+int isdn_net_dial_req(isdn_net_dev *);
+void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb);
+void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
+int isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev);
+isdn_net_dev *isdn_net_get_xmit_dev(isdn_net_local *mlp);
static inline int
put_u8(unsigned char *p, u8 x)
diff --git a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c
index 4cb417240aae..ba0144200c1f 100644
--- a/drivers/isdn/i4l/isdn_net_lib.c
+++ b/drivers/isdn/i4l/isdn_net_lib.c
@@ -80,12 +80,13 @@ lp_put(isdn_net_local *lp)
isdn_BUG();
}
-int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg); /* FIXME */
-
+static int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg);
static void isdn_net_tasklet(unsigned long data);
static void isdn_net_dial_timer(unsigned long data);
static int isdn_init_netif(struct net_device *ndev);
static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...);
+static int isdn_net_dial(isdn_net_dev *idev);
+static int isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c);
static struct fsm isdn_net_fsm;
@@ -151,6 +152,18 @@ static char *isdn_net_ev_str[] = {
"EV_DO_ACCEPT",
};
+/* Definitions for hupflags: */
+
+#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */
+#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */
+#define ISDN_MANCHARGE 16 /* Charge Interval manually set */
+
+enum {
+ ST_CHARGE_NULL,
+ ST_CHARGE_GOT_CINF, /* got a first charge info */
+ ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */
+};
+
/* ====================================================================== */
/* Registration of ISDN network interface types */
/* ====================================================================== */
@@ -208,7 +221,8 @@ isdn_net_set_encap(isdn_net_local *lp, int encap)
if (lp->ops && lp->ops->cleanup)
lp->ops->cleanup(lp);
- if (encap < 0 || encap >= ISDN_NET_ENCAP_NR) {
+ if (encap < 0 || encap >= ISDN_NET_ENCAP_NR ||
+ !isdn_netif_ops[encap]) {
lp->p_encap = -1;
lp->ops = NULL;
retval = -EINVAL;
@@ -348,7 +362,6 @@ isdn_net_addif(char *name, isdn_net_local *mlp)
strcpy(idev->name, name);
tasklet_init(&idev->tlet, isdn_net_tasklet, (unsigned long) idev);
- spin_lock_init(&idev->xmit_lock);
skb_queue_head_init(&idev->super_tx_queue);
idev->isdn_slot = -1;
@@ -356,7 +369,7 @@ isdn_net_addif(char *name, isdn_net_local *mlp)
idev->pre_channel = -1;
idev->exclusive = -1;
- idev->ppp_slot = -1;
+ idev->ipppd = NULL;
idev->pppbind = -1;
init_timer(&idev->dial_timer);
@@ -380,6 +393,7 @@ isdn_net_addif(char *name, isdn_net_local *mlp)
mlp->magic = ISDN_NET_MAGIC;
INIT_LIST_HEAD(&mlp->slaves);
INIT_LIST_HEAD(&mlp->online);
+ spin_lock_init(&mlp->xmit_lock);
mlp->p_encap = -1;
isdn_net_set_encap(mlp, ISDN_NET_ENCAP_RAWIP);
@@ -1007,7 +1021,7 @@ isdn_net_hangup_all(void)
* Remove all network-interfaces
*/
void
-isdn_net_exit(void)
+isdn_net_cleanup(void)
{
isdn_net_dev *idev;
int retval;
@@ -1025,9 +1039,6 @@ isdn_net_exit(void)
isdn_BUG();
}
up(&sem);
-
- // FIXME
- isdn_net_lib_exit();
}
/* ====================================================================== */
@@ -1053,7 +1064,7 @@ isdn_net_open(struct net_device *dev)
if (lp->ops->open)
retval = lp->ops->open(lp);
- if (!retval)
+ if (retval)
return retval;
netif_start_queue(dev);
@@ -1069,7 +1080,6 @@ isdn_net_open(struct net_device *dev)
/*
* Shutdown a net-interface.
*/
-// FIXME share?
static int
isdn_net_close(struct net_device *dev)
{
@@ -1083,14 +1093,14 @@ isdn_net_close(struct net_device *dev)
netif_stop_queue(dev);
- list_for_each_safe(l, n, &lp->online) {
- sdev = list_entry(l, isdn_net_dev, online);
+ list_for_each_safe(l, n, &lp->slaves) {
+ sdev = list_entry(l, isdn_net_dev, slaves);
isdn_net_hangup(sdev);
}
/* The hangup will make the refcnt drop back to
* 1 (referenced by list only) soon. */
spin_lock_irqsave(&running_devs_lock, flags);
- while (atomic_read(&dev->refcnt) != 1) {
+ while (atomic_read(&lp->refcnt) != 1) {
spin_unlock_irqrestore(&running_devs_lock, flags);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/10);
@@ -1147,29 +1157,12 @@ isdn_init_netif(struct net_device *ndev)
}
/* ====================================================================== */
-
-static void
-isdn_net_tasklet(unsigned long data)
-{
- isdn_net_dev *idev = (isdn_net_dev *) data;
- struct sk_buff *skb;
-
- spin_lock_bh(&idev->xmit_lock);
- while (!isdn_net_dev_busy(idev)) {
- skb = skb_dequeue(&idev->super_tx_queue);
- if (!skb)
- break;
- isdn_net_writebuf_skb(idev, skb);
- }
- spin_unlock_bh(&idev->xmit_lock);
-}
-
-/* ====================================================================== */
/* call control state machine */
/* ====================================================================== */
// FIXME
-int isdn_net_online(isdn_net_dev *idev)
+static int
+isdn_net_is_connected(isdn_net_dev *idev)
{
return idev->fi.state == ST_ACTIVE;
}
@@ -1234,7 +1227,7 @@ isdn_net_bind_channel(isdn_net_dev *idev, int slot)
return retval;
}
-int
+static int
isdn_net_dial(isdn_net_dev *idev)
{
int retval;
@@ -1250,6 +1243,127 @@ isdn_net_dial(isdn_net_dev *idev)
return retval;
}
+static void
+isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
+{
+ u_short proto = ntohs(skb->protocol);
+
+ printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
+ dev->name,
+ (reason != NULL) ? reason : "unknown",
+ (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
+
+ dst_link_failure(skb);
+}
+
+/*
+ * This is called from certain upper protocol layers (multilink ppp
+ * and x25iface encapsulation module) that want to initiate dialing
+ * themselves.
+ */
+int
+isdn_net_dial_req(isdn_net_dev *idev)
+{
+ isdn_net_local *mlp = idev->mlp;
+ /* is there a better error code? */
+ if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
+ return -EBUSY;
+
+ return isdn_net_dial(idev);
+}
+
+static void
+isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev)
+{
+ unsigned char *p = skb->nh.raw; /* hopefully, this was set correctly */
+ unsigned short proto = ntohs(skb->protocol);
+ int data_ofs;
+ struct ip_ports {
+ unsigned short source;
+ unsigned short dest;
+ } *ipp;
+ char addinfo[100];
+
+ data_ofs = ((p[0] & 15) * 4);
+ switch (proto) {
+ case ETH_P_IP:
+ switch (p[9]) {
+ case IPPROTO_ICMP:
+ strcpy(addinfo, "ICMP");
+ break;
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ ipp = (struct ip_ports *) (&p[data_ofs]);
+ sprintf(addinfo, "%s, port: %d -> %d",
+ p[9] == IPPROTO_TCP ? "TCP" : "UDP",
+ ntohs(ipp->source), ntohs(ipp->dest));
+ break;
+ default:
+ sprintf(addinfo, "type %d", p[9]);
+ }
+ printk(KERN_INFO
+ "OPEN: %u.%u.%u.%u -> %u.%u.%u.%u %s\n",
+
+ NIPQUAD(*(u32 *)(p + 12)), NIPQUAD(*(u32 *)(p + 16)),
+ addinfo);
+ break;
+ case ETH_P_ARP:
+ printk(KERN_INFO
+ "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
+ NIPQUAD(*(u32 *)(p + 14)), NIPQUAD(*(u32 *)(p + 24)));
+ break;
+ default:
+ printk(KERN_INFO "OPEN: unknown proto %#x\n", proto);
+ }
+}
+
+int
+isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
+{
+ isdn_net_local *mlp = ndev->priv;
+ isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
+ int retval;
+
+ if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
+ goto discard;
+
+ retval = isdn_net_dial(idev);
+ if (retval == -ESRCH)
+ goto stop_queue;
+
+ if (retval < 0)
+ goto discard;
+
+ /* Log packet, which triggered dialing */
+ if (dev->net_verbose)
+ isdn_net_log_skb(skb, idev);
+
+ stop_queue:
+ netif_stop_queue(ndev);
+ return 1;
+
+ discard:
+ isdn_net_unreachable(ndev, skb, "dial rejected");
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+
+static void
+isdn_net_dial_slave(isdn_net_local *mlp)
+{
+ isdn_net_dev *idev;
+
+ if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
+ return;
+
+ list_for_each_entry(idev, &mlp->slaves, slaves) {
+ if (fsm_event(&idev->fi, EV_DO_DIAL, NULL) != -ESRCH) {
+ break;
+ }
+ }
+}
+
static int
accept_icall(struct fsm_inst *fi, int pr, void *arg)
{
@@ -1640,14 +1754,12 @@ bconn(struct fsm_inst *fi, int pr, void *arg)
del_timer(&idev->dial_timer);
}
- isdn_net_add_to_bundle(mlp, idev);
-
printk(KERN_INFO "%s connected\n", idev->name);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
idev->chargetime = jiffies;
-
+ idev->frame_cnt = 0;
idev->transcount = 0;
idev->cps = 0;
idev->last_jiffies = jiffies;
@@ -1655,8 +1767,8 @@ bconn(struct fsm_inst *fi, int pr, void *arg)
if (mlp->ops->connected)
mlp->ops->connected(idev);
else
- isdn_net_dev_wake_queue(idev);
-
+ isdn_net_online(idev);
+
return 0;
}
@@ -1669,11 +1781,11 @@ bhup(struct fsm_inst *fi, int pr, void *arg)
del_timer(&idev->dial_timer);
if (mlp->ops->disconnected)
mlp->ops->disconnected(idev);
+ else
+ isdn_net_offline(idev);
printk(KERN_INFO "%s: disconnected\n", idev->name);
fsm_change_state(fi, ST_WAIT_DHUP);
- isdn_net_rm_from_bundle(idev);
- return 0;
}
static int
@@ -1748,10 +1860,7 @@ isdn_net_hangup(isdn_net_dev *idev)
isdn_ctrl cmd;
del_timer(&idev->dial_timer);
- if (!isdn_net_bound(idev)) {
- isdn_BUG();
- return 1;
- }
+
printk(KERN_INFO "%s: local hangup\n", idev->name);
isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
return 1;
@@ -1769,7 +1878,6 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
isdn_net_dev *idev = isdn_slot_idev(idx);
if (!idev) {
- HERE;
return 0;
}
switch (c->command) {
@@ -1791,7 +1899,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
}
}
-int
+static int
isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
{
fsm_event(&idev->fi, pr, arg);
@@ -1873,6 +1981,326 @@ static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...)
printk(KERN_DEBUG "%s\n", buf);
}
+/* ====================================================================== */
+/* xmit path */
+/* ====================================================================== */
+
+#define ISDN_NET_MAX_QUEUE_LENGTH 2
+
+/*
+ * is this particular channel busy?
+ */
+static inline int
+isdn_net_dev_busy(isdn_net_dev *idev)
+{
+ return idev->frame_cnt >= ISDN_NET_MAX_QUEUE_LENGTH;
+}
+
+/*
+ * find out if the net_device which this mlp is belongs to is busy.
+ * It's busy iff all channels are busy.
+ * must hold mlp->xmit_lock
+ * FIXME: Use a mlp->frame_cnt instead of loop?
+ */
+static inline int
+isdn_net_local_busy(isdn_net_local *mlp)
+{
+ isdn_net_dev *idev;
+
+ list_for_each_entry(idev, &mlp->online, online) {
+ if (!isdn_net_dev_busy(idev))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * For the given net device, this will get a non-busy channel out of the
+ * corresponding bundle.
+ * must hold mlp->xmit_lock
+ */
+isdn_net_dev *
+isdn_net_get_xmit_dev(isdn_net_local *mlp)
+{
+ isdn_net_dev *idev;
+
+ list_for_each_entry(idev, &mlp->online, online) {
+ if (!isdn_net_dev_busy(idev)) {
+ /* point the head to next online channel */
+ list_del(&mlp->online);
+ list_add(&mlp->online, &idev->online);
+ return idev;
+ }
+ }
+ return NULL;
+}
+
+/* mlp->xmit_lock must be held */
+static inline void
+isdn_net_inc_frame_cnt(isdn_net_dev *idev)
+{
+ isdn_net_local *mlp = idev->mlp;
+
+ if (isdn_net_dev_busy(idev))
+ isdn_BUG();
+
+ idev->frame_cnt++;
+ if (isdn_net_local_busy(mlp))
+ netif_stop_queue(&mlp->dev);
+}
+
+/* mlp->xmit_lock must be held */
+static inline void
+isdn_net_dec_frame_cnt(isdn_net_dev *idev)
+{
+ isdn_net_local *mlp = idev->mlp;
+
+ idev->frame_cnt--;
+
+ if (isdn_net_dev_busy(idev))
+ isdn_BUG();
+
+ if (!skb_queue_empty(&idev->super_tx_queue))
+ tasklet_schedule(&idev->tlet);
+ else
+ netif_wake_queue(&mlp->dev);
+}
+
+static void
+isdn_net_tasklet(unsigned long data)
+{
+ isdn_net_dev *idev = (isdn_net_dev *) data;
+ isdn_net_local *mlp = idev->mlp;
+ struct sk_buff *skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mlp->xmit_lock, flags);
+ while (!isdn_net_dev_busy(idev) &&
+ (skb = skb_dequeue(&idev->super_tx_queue))) {
+ isdn_net_writebuf_skb(idev, skb);
+ }
+ spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+}
+
+/* We're good to accept (IP/whatever) traffic now */
+
+void
+isdn_net_online(isdn_net_dev *idev)
+{
+ // FIXME check we're connected
+ isdn_net_local *mlp = idev->mlp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mlp->xmit_lock, flags);
+ list_add(&idev->online, &mlp->online);
+ spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+
+ netif_wake_queue(&mlp->dev);
+}
+
+/* No more (IP/whatever) traffic over the net interface */
+
+void
+isdn_net_offline(isdn_net_dev *idev)
+{
+ isdn_net_local *mlp = idev->mlp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mlp->xmit_lock, flags);
+ list_del(&idev->online);
+ spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+
+ skb_queue_purge(&idev->super_tx_queue);
+}
+
+/*
+ * all frames sent from the (net) LL to a HL driver should go via this function
+ * must hold mlp->xmit_lock
+ */
+void
+isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
+{
+ isdn_net_local *mlp = idev->mlp;
+ int ret;
+ int len = skb->len; /* save len */
+
+ /* before obtaining the lock the caller should have checked that
+ the lp isn't busy */
+ if (isdn_net_dev_busy(idev)) {
+ isdn_BUG();
+ goto error;
+ }
+
+ if (!isdn_net_is_connected(idev)) {
+ isdn_BUG();
+ goto error;
+ }
+ ret = isdn_slot_write(idev->isdn_slot, skb);
+ if (ret != len) {
+ /* we should never get here */
+ printk(KERN_WARNING "%s: HL driver queue full\n", idev->name);
+ goto error;
+ }
+
+ idev->transcount += len;
+ isdn_net_inc_frame_cnt(idev);
+ return;
+
+ error:
+ dev_kfree_skb(skb);
+ mlp->stats.tx_errors++;
+}
+
+/* A packet has successfully been sent out. */
+
+static int
+isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c)
+{
+ isdn_net_local *mlp = idev->mlp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mlp->xmit_lock, flags);
+ isdn_net_dec_frame_cnt(idev);
+ spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+ mlp->stats.tx_packets++;
+ mlp->stats.tx_bytes += c->parm.length;
+ return 1;
+}
+
+/*
+ * Based on cps-calculation, check if device is overloaded.
+ * If so, and if a slave exists, trigger dialing for it.
+ * If any slave is online, deliver packets using a simple round robin
+ * scheme.
+ *
+ * Return: 0 on success, !0 on failure.
+ */
+
+int
+isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ isdn_net_dev *idev;
+ isdn_net_local *mlp = ndev->priv;
+ unsigned long flags;
+ int retval;
+
+ ndev->trans_start = jiffies;
+
+ spin_lock_irqsave(&mlp->xmit_lock, flags);
+
+ if (list_empty(&mlp->online)) {
+ retval = isdn_net_autodial(skb, ndev);
+ goto out;
+ }
+
+ idev = isdn_net_get_xmit_dev(mlp);
+ if (!idev) {
+ printk(KERN_INFO "%s: all channels busy - requeuing!\n", ndev->name);
+ netif_stop_queue(ndev);
+ retval = 1;
+ goto out;
+ }
+
+ isdn_net_writebuf_skb(idev, skb);
+
+ /* the following stuff is here for backwards compatibility.
+ * in future, start-up and hangup of slaves (based on current load)
+ * should move to userspace and get based on an overall cps
+ * calculation
+ */
+ if (jiffies != idev->last_jiffies) {
+ idev->cps = idev->transcount * HZ / (jiffies - idev->last_jiffies);
+ idev->last_jiffies = jiffies;
+ idev->transcount = 0;
+ }
+ if (dev->net_verbose > 3)
+ printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
+
+ if (idev->cps > mlp->triggercps) {
+ if (!idev->sqfull) {
+ /* First time overload: set timestamp only */
+ idev->sqfull = 1;
+ idev->sqfull_stamp = jiffies;
+ } else {
+ /* subsequent overload: if slavedelay exceeded, start dialing */
+ if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) {
+ isdn_net_dial_slave(mlp);
+ }
+ }
+ } else {
+ if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) {
+ idev->sqfull = 0;
+ }
+ /* this is a hack to allow auto-hangup for slaves on moderate loads */
+ list_del(&mlp->online);
+ list_add_tail(&mlp->online, &idev->online);
+ }
+
+ retval = 0;
+ out:
+ spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+ return retval;
+}
+
+/*
+ * this function is used to send supervisory data, i.e. data which was
+ * not received from the network layer, but e.g. frames from ipppd, CCP
+ * reset frames etc.
+ * must hold mlp->xmit_lock
+ */
+void
+isdn_net_write_super(isdn_net_dev *idev, struct sk_buff *skb)
+{
+ if (!isdn_net_dev_busy(idev)) {
+ isdn_net_writebuf_skb(idev, skb);
+ } else {
+ skb_queue_tail(&idev->super_tx_queue, skb);
+ }
+}
+
+/* ====================================================================== */
+/* receive path */
+/* ====================================================================== */
+
+/*
+ * A packet arrived via ISDN. Search interface-chain for a corresponding
+ * interface. If found, deliver packet to receiver-function and return 1,
+ * else return 0.
+ */
+int
+isdn_net_rcv_skb(int idx, struct sk_buff *skb)
+{
+ isdn_net_dev *idev = isdn_slot_idev(idx);
+ isdn_net_local *mlp;
+
+ if (!idev) {
+ isdn_BUG();
+ return 0;
+ }
+ if (!isdn_net_is_connected(idev)) {
+ isdn_BUG();
+ return 0;
+ }
+
+ mlp = idev->mlp;
+
+ idev->transcount += skb->len;
+
+ mlp->stats.rx_packets++;
+ mlp->stats.rx_bytes += skb->len;
+ skb->dev = &mlp->dev;
+ skb->pkt_type = PACKET_HOST;
+ isdn_dumppkt("R:", skb->data, skb->len, 40);
+
+ mlp->ops->receive(mlp, idev, skb);
+
+ return 1;
+}
+
+/* ====================================================================== */
+/* init / exit */
+/* ====================================================================== */
+
void
isdn_net_lib_init(void)
{
@@ -1882,5 +2310,7 @@ isdn_net_lib_init(void)
void
isdn_net_lib_exit(void)
{
+ isdn_net_cleanup();
+
fsm_free(&isdn_net_fsm);
}
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 3c59a373459b..13395d86720a 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -18,635 +18,535 @@
#include "isdn_common.h"
#include "isdn_ppp.h"
+#include "isdn_ppp_ccp.h"
#include "isdn_net.h"
-/* Prototypes */
-static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
-static int isdn_ppp_closewait(int slot);
-static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
- struct sk_buff *skb, int proto);
-static int isdn_ppp_if_get_unit(char *namebuf);
-static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
- struct ippp_struct *,struct ippp_struct *,int *proto);
-static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
- struct sk_buff *skb,int proto);
-static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
- struct ippp_struct *is,struct ippp_struct *master,int type);
-static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
- struct sk_buff *skb);
+static struct sk_buff *
+isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask);
-/* New CCP stuff */
-static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
-static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
- unsigned char code, unsigned char id,
- unsigned char *data, int len);
-static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
-static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
-static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
- unsigned char id);
-static void isdn_ppp_ccp_timer_callback(unsigned long closure);
-static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
- unsigned char id);
-static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
- struct isdn_ppp_resetparams *rp);
-static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
- unsigned char id);
+static int
+isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *);
+/* ====================================================================== */
+/* IPPPD handling */
+/* ====================================================================== */
+/* We use reference counting for struct ipppd. It is alloced on
+ * open() on /dev/ipppX and saved into file->private, making for one
+ * reference. release() will release this reference, after all other
+ * references are gone, the destructor frees it.
+ *
+ * Another reference is taken by isdn_ppp_bind() and freed by
+ * isdn_ppp_unbind(). The callbacks from isdn_net_lib.c happen only
+ * between isdn_ppp_bind() and isdn_ppp_unbind(), i.e. access to
+ * idev->ipppd is safe without further locking.
+ */
-#ifdef CONFIG_ISDN_MPP
-static ippp_bundle * isdn_ppp_bundle_arr = NULL;
-
-static int isdn_ppp_mp_bundle_array_init(void);
-static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to);
-static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *idev,
- struct sk_buff *skb);
-static void isdn_ppp_mp_cleanup(isdn_net_local *lp );
+#define IPPPD_DEBUG
-static int isdn_ppp_bundle(struct ippp_struct *, int unit);
-#endif /* CONFIG_ISDN_MPP */
-
-char *isdn_ppp_revision = "$Revision: 1.85.6.9 $";
+#ifdef IPPPD_DEBUG
+#define ipppd_debug(i, fmt, arg...) \
+ printk(KERN_DEBUG "ipppd %p minor %d state %#x %s: " fmt "\n", (i), \
+ (i)->minor, (i)->state, __FUNCTION__ , ## arg)
+#else
+#define ipppd_debug(...) do { } while (0)
+#endif
-static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
+/* ipppd::flags */
+enum {
+ IPPPD_FL_HUP = 0x01,
+ IPPPD_FL_WAKEUP = 0x02,
+};
-static struct isdn_ppp_compressor *ipc_head = NULL;
+/* ipppd::state */
+enum {
+ IPPPD_ST_OPEN,
+ IPPPD_ST_ASSIGNED,
+ IPPPD_ST_CONNECTED,
+};
+
+struct ipppd {
+ struct list_head ipppds;
+ int state;
+ int flags;
+ struct sk_buff_head rq;
+ wait_queue_head_t wq;
+ struct isdn_net_dev_s *idev;
+ int unit;
+ int minor;
+ unsigned long debug;
+ atomic_t refcnt;
+};
+
+/* ====================================================================== */
+
+static spinlock_t ipppds_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(ipppds);
-/*
- * frame log (debug)
- */
static void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
+ipppd_destroy(struct ipppd *ipppd)
{
- int cnt,
- j,
- i;
- char buf[80];
+ HERE;
- if (len < maxlen)
- maxlen = len;
+ skb_queue_purge(&ipppd->rq);
+ kfree(ipppd);
+}
- for (i = 0, cnt = 0; cnt < maxlen; i++) {
- for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
- sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
- printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
- }
+static inline struct ipppd *
+ipppd_get(struct ipppd *ipppd)
+{
+ atomic_inc(&ipppd->refcnt);
+ printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt));
+ return ipppd;
}
-/*
- * unbind isdn_net_local <=> ippp-device
- * note: it can happen, that we hangup/free the master before the slaves
- * in this case we bind another lp to the master device
- */
-static void
-isdn_ppp_free(isdn_net_dev *idev)
+static inline void
+ipppd_put(struct ipppd *ipppd)
+{
+ printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt));
+
+ if (atomic_dec_and_test(&ipppd->refcnt))
+ ipppd_destroy(ipppd);
+}
+
+/* ====================================================================== */
+/* char dev ops */
+
+/* --- open ------------------------------------------------------------- */
+
+static int
+ipppd_open(struct inode *ino, struct file *file)
{
unsigned long flags;
- struct ippp_struct *is;
+ unsigned int minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
+ struct ipppd *ipppd;
- if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
- __FUNCTION__ , idev->ppp_slot);
- return;
- }
+ ipppd = kmalloc(sizeof(*ipppd), GFP_KERNEL);
+ if (!ipppd)
+ return -ENOMEM;
- save_flags(flags);
- cli();
+ memset(ipppd, 0, sizeof(*ipppd));
+ atomic_set(&ipppd->refcnt, 0);
+
+ /* file->private_data holds a reference */
+ file->private_data = ipppd_get(ipppd);
+
+ ipppd->unit = -1; /* set by isdn_ppp_bind */
+ ipppd->minor = minor;
+ ipppd->state = IPPPD_ST_OPEN;
+ init_waitqueue_head(&ipppd->wq);
+ skb_queue_head_init(&ipppd->rq);
+
+ spin_lock_irqsave(&ipppds, flags);
+ list_add(&ipppd->ipppds, &ipppds);
+ spin_unlock_irqrestore(&ipppds, flags);
+
+ ipppd_debug(ipppd, "minor %d", minor);
-#ifdef CONFIG_ISDN_MPP
- spin_lock(&idev->pb->lock);
-#endif
- isdn_net_rm_from_bundle(idev);
-#ifdef CONFIG_ISDN_MPP
- if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */
- isdn_ppp_mp_cleanup(lp);
+ return 0;
+}
- lp->netdev->pb->ref_ct--;
- spin_unlock(&lp->netdev->pb->lock);
-#endif /* CONFIG_ISDN_MPP */
- if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
- __FUNCTION__ , idev->ppp_slot);
- restore_flags(flags);
- return;
- }
- is = ippp_table[idev->ppp_slot];
- if ((is->state & IPPP_CONNECT))
- isdn_ppp_closewait(idev->ppp_slot); /* force wakeup on ippp device */
- else if (is->state & IPPP_ASSIGNED)
- is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */
+/* --- release --------------------------------------------------------- */
- if (is->debug & 0x1)
- printk(KERN_DEBUG "isdn_ppp_free %d %p\n", idev->ppp_slot, is->idev);
+static int
+ipppd_release(struct inode *ino, struct file *file)
+{
+ unsigned long flags;
+ struct ipppd *ipppd = file->private_data;
- is->idev = NULL; /* link is down .. set lp to NULL */
- idev->ppp_slot = -1; /* is this OK ?? */
+ ipppd_debug(ipppd, "");
- restore_flags(flags);
- return;
+ if (ipppd->state == IPPPD_ST_CONNECTED)
+ isdn_net_hangup(ipppd->idev);
+
+ spin_lock_irqsave(&ipppds, flags);
+ list_del(&ipppd->ipppds);
+ spin_unlock_irqrestore(&ipppds, flags);
+
+ ipppd_put(ipppd);
+
+ return 0;
}
-/*
- * bind isdn_net_local <=> ippp-device
- */
-int
-isdn_ppp_bind(isdn_net_dev *idev)
+/* --- read ------------------------------------------------------------- */
+
+/* read() is always non blocking */
+static ssize_t
+ipppd_read(struct file *file, char *buf, size_t count, loff_t *off)
{
- int i;
- int unit = 0;
- long flags;
- struct ippp_struct *is;
+ struct ipppd *is;
+ struct sk_buff *skb;
int retval;
- save_flags(flags);
- cli();
- if (idev->pppbind < 0) { /* device bound to ippp device ? */
- struct list_head *l;
- char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
- memset(exclusive, 0, ISDN_MAX_CHANNELS);
- /* step through net devices to find exclusive minors */
- list_for_each(l, &isdn_net_devs) {
- isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
- if (p->pppbind >= 0)
- exclusive[p->pppbind] = 1;
- }
- /*
- * search a free device / slot
- */
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) { /* OPEN, but not connected! */
- break;
- }
- }
- } else {
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (ippp_table[i]->minor == idev->pppbind &&
- (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
- break;
- }
- }
+ if (off != &file->f_pos)
+ return -ESPIPE;
+
+ is = file->private_data;
- if (i >= ISDN_MAX_CHANNELS) {
- restore_flags(flags);
- printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
- retval = -1;
+ skb = skb_dequeue(&is->rq);
+ if (!skb) {
+ retval = -EAGAIN;
goto out;
}
- unit = isdn_ppp_if_get_unit(idev->name); /* get unit number from interface name .. ugly! */
- if (unit < 0) {
- printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", idev->name);
- retval = -1;
- goto out;
+ if (skb->len > count) {
+ retval = -EMSGSIZE;
+ goto out_free;
}
-
- idev->ppp_slot = i;
- is = ippp_table[i];
- is->idev = idev;
- is->unit = unit;
- is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */
-#ifdef CONFIG_ISDN_MPP
- retval = isdn_ppp_mp_init(lp, NULL);
- if (retval < 0)
- goto out;
-#endif /* CONFIG_ISDN_MPP */
-
- retval = idev->ppp_slot;
+ if (copy_to_user(buf, skb->data, skb->len)) {
+ retval = -EFAULT;
+ goto out_free;
+ }
+ retval = skb->len;
+ out_free:
+ dev_kfree_skb(skb);
out:
- restore_flags(flags);
return retval;
}
-/*
- * kick the ipppd on the device
- * (wakes up daemon after B-channel connect)
- */
+/* --- write ------------------------------------------------------------ */
-static void
-isdn_ppp_wakeup_daemon(isdn_net_dev *idev)
+/* write() is always non blocking */
+static ssize_t
+ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
{
- if (idev->ppp_slot < 0 || idev->ppp_slot >= ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
- __FUNCTION__, idev->ppp_slot);
- return;
- }
- ippp_table[idev->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
- wake_up_interruptible(&ippp_table[idev->ppp_slot]->wq);
-}
+ isdn_net_dev *idev;
+ struct ipppd *ipppd;
+ struct sk_buff *skb;
+ char *p;
+ int retval;
+ u16 proto;
-/*
- * there was a hangup on the netdevice
- * force wakeup of the ippp device
- * go into 'device waits for release' state
- */
-static int
-isdn_ppp_closewait(int slot)
-{
- struct ippp_struct *is;
+ if (off != &file->f_pos)
+ return -ESPIPE;
- if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "%s: slot(%d) out of range\n",
- __FUNCTION__ , slot);
- return 0;
- }
- is = ippp_table[slot];
- if (is->state)
- wake_up_interruptible(&is->wq);
- is->state = IPPP_CLOSEWAIT;
- return 1;
-}
+ ipppd = file->private_data;
+ ipppd_debug(ipppd, "count = %d", count);
-/*
- * isdn_ppp_find_slot / isdn_ppp_free_slot
- */
+ if (ipppd->state != IPPPD_ST_CONNECTED) {
+ retval = -ENOTCONN;
+ goto out;
+ }
-static int
-isdn_ppp_get_slot(void)
-{
- int i;
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (!ippp_table[i]->state)
- return i;
+ idev = ipppd->idev;
+ if (!idev) {
+ isdn_BUG();
+ retval = -ENODEV;
+ goto out;
}
- return -1;
+ /* Daemon needs to send at least full header, AC + proto */
+ if (count < 4) {
+ retval = -EMSGSIZE;
+ goto out;
+ }
+ skb = isdn_ppp_dev_alloc_skb(idev, count, GFP_KERNEL);
+ if (!skb) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ p = skb_put(skb, count);
+ if (copy_from_user(p, buf, count)) {
+ kfree_skb(skb);
+ retval = -EFAULT;
+ goto out;
+ }
+ /* Don't reset huptimer for LCP packets. (Echo requests). */
+ proto = PPP_PROTOCOL(p);
+ if (proto != PPP_LCP)
+ idev->huptimer = 0;
+
+ /* Keeps CCP/compression states in sync */
+ switch (proto) {
+ case PPP_CCP:
+ ippp_ccp_send_ccp(idev->mlp->ccp, skb);
+ break;
+ case PPP_CCPFRAG:
+ ippp_ccp_send_ccp(idev->ccp, skb);
+ break;
+ }
+ /* FIXME: Somewhere we need protection against the
+ * queue growing too large */
+ isdn_net_write_super(idev, skb);
+
+ retval = count;
+
+ out:
+ return retval;
}
-/*
- * isdn_ppp_open
- */
+/* --- poll ------------------------------------------------------------- */
-static int
-isdn_ppp_open(struct inode *ino, struct file *file)
+static unsigned int
+ipppd_poll(struct file *file, poll_table * wait)
{
- uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
- int slot;
- struct ippp_struct *is;
+ unsigned int mask;
+ struct ipppd *is;
- slot = isdn_ppp_get_slot();
- if (slot < 0) {
- return -EBUSY;
- }
- is = file->private_data = ippp_table[slot];
+ is = file->private_data;
- printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, minor, is->state);
+ ipppd_debug(is, "");
- /* compression stuff */
- is->link_compressor = is->compressor = NULL;
- is->link_decompressor = is->decompressor = NULL;
- is->link_comp_stat = is->comp_stat = NULL;
- is->link_decomp_stat = is->decomp_stat = NULL;
- is->compflags = 0;
+ /* just registers wait_queue hook. This doesn't really wait. */
+ poll_wait(file, &is->wq, wait);
- is->reset = isdn_ppp_ccp_reset_alloc(is);
+ if (is->flags & IPPPD_FL_HUP) {
+ mask = POLLHUP;
+ goto out;
+ }
+ /* we're always ready to send .. */
+ mask = POLLOUT | POLLWRNORM;
- is->idev = NULL;
- is->mp_seqno = 0; /* MP sequence number */
- is->pppcfg = 0; /* ppp configuration */
- is->mpppcfg = 0; /* mppp configuration */
- is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
- is->unit = -1; /* set, when we have our interface */
- is->mru = 1524; /* MRU, default 1524 */
- is->maxcid = 16; /* VJ: maxcid */
- is->tk = current;
- init_waitqueue_head(&is->wq);
- is->minor = minor;
-#ifdef CONFIG_ISDN_PPP_VJ
/*
- * VJ header compression init
+ * if IPPP_FL_WAKEUP is set we return even if we have nothing to read
*/
- is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
-#endif
-
- is->state = IPPP_OPEN;
- isdn_lock_drivers();
-
- return 0;
-}
-
-/*
- * release ippp device
- */
-static int
-isdn_ppp_release(struct inode *ino, struct file *file)
-{
- uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
- struct ippp_struct *is;
-
- lock_kernel();
-
- is = file->private_data;
-
- if (is->debug & 0x1)
- printk(KERN_DEBUG "ippp: release, minor: %d %p\n", minor, is->idev);
-
- if (is->idev) { /* a lp address says: this link is still up */
- /*
- * isdn_net_hangup() calls isdn_ppp_free()
- * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
- * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
- */
- is->state &= ~IPPP_CONNECT;
- isdn_net_hangup(is->idev);
+ if (!skb_queue_empty(&is->rq) || is->flags & IPPPD_FL_WAKEUP) {
+ is->flags &= ~IPPPD_FL_WAKEUP;
+ mask |= POLLIN | POLLRDNORM;
+ set_current_state(TASK_INTERRUPTIBLE); // FIXME
+ schedule_timeout(HZ);
}
- skb_queue_purge(&is->rq);
-
-#ifdef CONFIG_ISDN_PPP_VJ
-/* TODO: if this was the previous master: link the slcomp to the new master */
- slhc_free(is->slcomp);
- is->slcomp = NULL;
-#endif
-/* TODO: if this was the previous master: link the the stuff to the new master */
- if(is->comp_stat)
- is->compressor->free(is->comp_stat);
- if(is->link_comp_stat)
- is->link_compressor->free(is->link_comp_stat);
- if(is->link_decomp_stat)
- is->link_decompressor->free(is->link_decomp_stat);
- if(is->decomp_stat)
- is->decompressor->free(is->decomp_stat);
- is->compressor = is->link_compressor = NULL;
- is->decompressor = is->link_decompressor = NULL;
- is->comp_stat = is->link_comp_stat = NULL;
- is->decomp_stat = is->link_decomp_stat = NULL;
-
- /* Clean up if necessary */
- if(is->reset)
- isdn_ppp_ccp_reset_free(is);
-
- /* this slot is ready for new connections */
- is->state = 0;
-
- isdn_unlock_drivers();
-
- unlock_kernel();
- return 0;
+ out:
+ return mask;
}
-/*
- * get_arg .. ioctl helper
- */
+/* --- ioctl ------------------------------------------------------------ */
+
+/* get_arg .. ioctl helper */
static int
-get_arg(void *b, void *val, int len)
+get_arg(unsigned long arg, void *val, int len)
{
- if (len <= 0)
- len = sizeof(void *);
- if (copy_from_user((void *) val, b, len))
+ if (copy_from_user((void *) val, (void *) arg, len))
return -EFAULT;
return 0;
}
-/*
- * set arg .. ioctl helper
- */
+/* set arg .. ioctl helper */
static int
-set_arg(void *b, void *val,int len)
+set_arg(unsigned long arg, void *val,int len)
{
- if (copy_to_user(b, (void *) val, len))
+ if (copy_to_user((void *) arg, (void *) val, len))
return -EFAULT;
return 0;
}
-/*
- * ippp device ioctl
- */
static int
-isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned long arg)
+ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
+ unsigned long arg)
{
isdn_net_dev *idev;
unsigned long val;
- int r,i,j;
- struct ippp_struct *is;
+ int r;
+ struct ipppd *is;
struct isdn_ppp_comp_data data;
+ unsigned int cfg;
- is = (struct ippp_struct *) file->private_data;
+ is = file->private_data;
idev = is->idev;
- if (is->debug & 0x1)
- printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", is->minor, cmd, is->state);
-
- if (!(is->state & IPPP_OPEN))
- return -EINVAL;
+ ipppd_debug(is, "cmd %#x", cmd);
switch (cmd) {
- case PPPIOCBUNDLE:
+ case PPPIOCBUNDLE:
#ifdef CONFIG_ISDN_MPP
- if (!(is->state & IPPP_CONNECT))
- return -EINVAL;
- if ((r = get_arg((void *) arg, &val, sizeof(val) )))
- return r;
- printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
- (int) is->minor, (int) is->unit, (int) val);
- return isdn_ppp_bundle(is, val);
-#else
- return -1;
-#endif
- break;
- case PPPIOCGUNIT: /* get ppp/isdn unit number */
- if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
- return r;
- break;
- case PPPIOCGIFNAME:
- if(!idev)
- return -EINVAL;
- if ((r = set_arg((void *) arg, idev->name, strlen(idev->name))))
- return r;
- break;
- case PPPIOCGMPFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
- return r;
+ if (is->state != IPPPD_ST_CONNECTED) {
+ r = -EINVAL;
break;
- case PPPIOCSMPFLAGS: /* set configuration flags */
- if ((r = get_arg((void *) arg, &val, sizeof(val) )))
- return r;
- is->mpppcfg = val;
- break;
- case PPPIOCGFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
- return r;
+ }
+ r = get_arg(arg, &val, sizeof(val));
+ if (r)
break;
- case PPPIOCSFLAGS: /* set configuration flags */
- if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
- return r;
- }
- if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
- if (idev) {
- /* OK .. we are ready to send buffers */
- isdn_net_dev_wake_queue(idev);
- }
- }
- is->pppcfg = val;
+
+ printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
+ is->minor, is->unit, val);
+ r = isdn_ppp_bundle(is, val);
+#else
+ r = -EINVAL;
+#endif
+ break;
+ case PPPIOCGUNIT: /* get ppp/isdn unit number */
+ r = set_arg(arg, &is->unit, sizeof(is->unit));
+ break;
+ case PPPIOCGDEBUG:
+ r = set_arg(arg, &is->debug, sizeof(is->debug));
+ break;
+ case PPPIOCSDEBUG:
+ r = get_arg(arg, &val, sizeof(val));
+ if (r)
break;
- case PPPIOCGIDLE: /* get idle time information */
- if (idev) {
- struct ppp_idle pidle;
- pidle.xmit_idle = pidle.recv_idle = idev->huptimer;
- if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
- return r;
- }
+ is->debug = val;
+ if (idev) {
+ idev->debug = val;
+ idev->mlp->debug = val;
+ }
+ break;
+ case PPPIOCGCOMPRESSORS:
+ {
+ unsigned long protos[8];
+ ippp_ccp_get_compressors(protos);
+ r = set_arg(arg, protos, sizeof(protos));
+ break;
+ }
+ default:
+ r = -ENOTTY;
+ break;
+ }
+
+ if (r != -ENOTTY)
+ goto out;
+
+ if (!idev) {
+ r = -ENODEV;
+ goto out;
+ }
+
+ switch (cmd) {
+ case PPPIOCGIFNAME:
+ r = set_arg(arg, idev->name, strlen(idev->name)+1);
+ break;
+ case PPPIOCGMPFLAGS: /* get configuration flags */
+ r = set_arg(arg, &idev->mlp->mpppcfg, sizeof(idev->mlp->mpppcfg));
+ break;
+ case PPPIOCSMPFLAGS: /* set configuration flags */
+ r = get_arg(arg, &val, sizeof(val));
+ if (r)
break;
- case PPPIOCSMRU: /* set receive unit size for PPP */
- if ((r = get_arg((void *) arg, &val, sizeof(val) )))
- return r;
- is->mru = val;
+ idev->mlp->mpppcfg = val;
+ break;
+ case PPPIOCGFLAGS: /* get configuration flags */
+ cfg = idev->pppcfg | ippp_ccp_get_flags(idev->ccp);
+ r = set_arg(arg, &cfg, sizeof(cfg));
+ break;
+ case PPPIOCSFLAGS: /* set configuration flags */
+ r = get_arg(arg, &val, sizeof(val));
+ if (r)
break;
- case PPPIOCSMPMRU:
+ if ((val & SC_ENABLE_IP) && !(idev->pppcfg & SC_ENABLE_IP)) {
+ idev->pppcfg = val;
+ /* OK .. we are ready to send buffers */
+ isdn_net_online(idev);
break;
- case PPPIOCSMPMTU:
+ }
+ idev->pppcfg = val;
+ break;
+ case PPPIOCGIDLE: /* get idle time information */
+ {
+ struct ppp_idle pidle;
+ pidle.xmit_idle = pidle.recv_idle = idev->huptimer;
+ r = set_arg(arg, &pidle,sizeof(pidle));
+ break;
+ }
+ case PPPIOCSMRU: /* set receive unit size for PPP */
+ r = get_arg(arg, &val, sizeof(val));
+ if (r)
break;
- case PPPIOCSMAXCID: /* set the maximum compression slot id */
- if ((r = get_arg((void *) arg, &val, sizeof(val) )))
- return r;
- val++;
- if (is->maxcid != val) {
-#ifdef CONFIG_ISDN_PPP_VJ
- struct slcompress *sltmp;
-#endif
- if (is->debug & 0x1)
- printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
- is->maxcid = val;
+ r = ippp_ccp_set_mru(idev->ccp, val);
+ break;
+ case PPPIOCSMPMRU:
+ break;
+ case PPPIOCSMPMTU:
+ break;
#ifdef CONFIG_ISDN_PPP_VJ
- sltmp = slhc_init(16, val);
- if (!sltmp) {
- printk(KERN_ERR "ippp, can't realloc slhc struct\n");
- return -ENOMEM;
- }
- if (is->slcomp)
- slhc_free(is->slcomp);
- is->slcomp = sltmp;
-#endif
- }
- break;
- case PPPIOCGDEBUG:
- if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
- return r;
+ case PPPIOCSMAXCID: /* set the maximum compression slot id */
+ {
+ struct slcompress *sltmp;
+ r = get_arg(arg, &val, sizeof(val));
+ if (r)
break;
- case PPPIOCSDEBUG:
- if ((r = get_arg((void *) arg, &val, sizeof(val) )))
- return r;
- is->debug = val;
+ val++;
+ sltmp = slhc_init(16, val);
+ if (!sltmp) {
+ r = -ENOMEM;
break;
- case PPPIOCGCOMPRESSORS:
- {
- unsigned long protos[8] = {0,};
- struct isdn_ppp_compressor *ipc = ipc_head;
- while(ipc) {
- j = ipc->num / (sizeof(long)*8);
- i = ipc->num % (sizeof(long)*8);
- if(j < 8)
- protos[j] |= (0x1<<i);
- ipc = ipc->next;
- }
- if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
- return r;
- }
+ }
+ if (idev->mlp->slcomp)
+ slhc_free(idev->mlp->slcomp);
+ idev->mlp->slcomp = sltmp;
+ r = 0;
+ break;
+ }
+#endif
+ case PPPIOCSCOMPRESSOR:
+ r = get_arg(arg, &data, sizeof(data));
+ if (r)
break;
- case PPPIOCSCOMPRESSOR:
- if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
- return r;
- return isdn_ppp_set_compressor(is, &data);
- case PPPIOCGCALLINFO:
- {
- isdn_net_local *mlp;
- struct isdn_net_phone *phone;
- struct pppcallinfo pci;
- int i;
- memset((char *) &pci,0,sizeof(struct pppcallinfo));
- if(idev) {
- mlp = idev->mlp;
- strncpy(pci.local_num, mlp->msn, 63);
- i = 0;
- list_for_each_entry(phone, &mlp->phone[1], list) {
- if (i++ == idev->dial) {
- strncpy(pci.remote_num,phone->num,63);
- break;
- }
- }
- pci.charge_units = idev->charge;
- if(idev->outgoing)
- pci.calltype = CALLTYPE_OUTGOING;
- else
- pci.calltype = CALLTYPE_INCOMING;
- if(mlp->flags & ISDN_NET_CALLBACK)
- pci.calltype |= CALLTYPE_CALLBACK;
- }
- return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+ r = isdn_ppp_set_compressor(idev, &data);
+ break;
+ case PPPIOCGCALLINFO:
+ {
+ isdn_net_local *mlp;
+ struct isdn_net_phone *phone;
+ struct pppcallinfo pci;
+ int i;
+ memset(&pci, 0, sizeof(pci));
+
+ mlp = idev->mlp;
+ strncpy(pci.local_num, mlp->msn, 63);
+ i = 0;
+ list_for_each_entry(phone, &mlp->phone[1], list) {
+ if (i++ == idev->dial) {
+ strncpy(pci.remote_num,phone->num,63);
+ break;
}
- default:
- break;
- }
- return 0;
-}
-
-static unsigned int
-isdn_ppp_poll(struct file *file, poll_table * wait)
-{
- unsigned int mask;
- struct ippp_struct *is;
-
- is = file->private_data;
-
- if (is->debug & 0x2)
- printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
- minor(file->f_dentry->d_inode->i_rdev));
-
- /* just registers wait_queue hook. This doesn't really wait. */
- poll_wait(file, &is->wq, wait);
-
- if (!(is->state & IPPP_OPEN)) {
- if(is->state == IPPP_CLOSEWAIT) {
- mask = POLLHUP;
- goto out;
}
- printk(KERN_DEBUG "isdn_ppp: device not open\n");
- mask = POLLERR;
- goto out;
+ pci.charge_units = idev->charge;
+ if (idev->outgoing)
+ pci.calltype = CALLTYPE_OUTGOING;
+ else
+ pci.calltype = CALLTYPE_INCOMING;
+ if (mlp->flags & ISDN_NET_CALLBACK)
+ pci.calltype |= CALLTYPE_CALLBACK;
+ r = set_arg(arg, &pci, sizeof(pci));
+ break;
}
- /* we're always ready to send .. */
- mask = POLLOUT | POLLWRNORM;
-
- /*
- * if IPPP_NOBLOCK is set we return even if we have nothing to read
- */
- if (!skb_queue_empty(&is->rq) || is->state & IPPP_NOBLOCK) {
- is->state &= ~IPPP_NOBLOCK;
- mask |= POLLIN | POLLRDNORM;
+ default:
+ r = -ENOTTY;
+ break;
}
-
out:
- return mask;
+ return r;
}
-/*
- * fill up isdn_ppp_read() queue ..
- */
+/* --- fops ------------------------------------------------------------- */
+
+struct file_operations isdn_ppp_fops =
+{
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = ipppd_read,
+ .write = ipppd_write,
+ .poll = ipppd_poll,
+ .ioctl = ipppd_ioctl,
+ .open = ipppd_open,
+ .release = ipppd_release,
+};
+
+/* --- ipppd_queue_read ------------------------------------------------- */
+
+/* Queue packets for ipppd to read(). */
static int
-isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
+ipppd_queue_read(struct ipppd *is, u16 proto, unsigned char *buf, int len)
{
struct sk_buff *skb;
unsigned char *p;
- struct ippp_struct *is;
-
- if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
- printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
- return 0;
- }
- is = ippp_table[slot];
+ int retval;
- if (!(is->state & IPPP_CONNECT)) {
- printk(KERN_DEBUG "ippp: device not activated.\n");
- return 0;
+ if (is->state != IPPPD_ST_CONNECTED) {
+ printk(KERN_DEBUG "ippp: device not connected.\n");
+ retval = -ENOTCONN;
+ goto out;
}
if (skb_queue_len(&is->rq) > IPPP_MAX_RQ_LEN) {
printk(KERN_WARNING "ippp: Queue is full\n");
- return 0;
+ retval = -EBUSY;
+ goto out;
}
skb = dev_alloc_skb(len + 4);
if (!skb) {
printk(KERN_WARNING "ippp: Can't alloc buf\n");
- return 0;
+ retval = -ENOMEM;
+ goto out;
}
p = skb_put(skb, 4);
p += put_u8(p, PPP_ALLSTATIONS);
@@ -655,151 +555,274 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
memcpy(skb_put(skb, len), buf, len);
skb_queue_tail(&is->rq, skb);
- wake_up_interruptible(&is->wq);
+ wake_up(&is->wq);
- return len;
+ retval = len;
+ out:
+ return retval;
}
+/* ====================================================================== */
+
+/* Prototypes */
+static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
+ struct sk_buff *skb, int proto);
+static int isdn_ppp_if_get_unit(char *namebuf);
+
+static void
+isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto);
+
+static void
+isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb);
+
+static struct sk_buff *
+isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask);
+
+static void
+isdn_ppp_lp_push_header(void *priv, struct sk_buff *skb, u16 proto);
+
+/* New CCP stuff */
+static void
+isdn_ppp_dev_kick_up(void *priv);
+
+#ifdef CONFIG_ISDN_MPP
+static ippp_bundle * isdn_ppp_bundle_arr = NULL;
+
+static int isdn_ppp_mp_bundle_array_init(void);
+static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to);
+static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *idev,
+ struct sk_buff *skb);
+static void isdn_ppp_mp_cleanup(isdn_net_local *lp );
+
+static int isdn_ppp_bundle(struct ipppd *, int unit);
+#endif /* CONFIG_ISDN_MPP */
+
+char *isdn_ppp_revision = "$Revision: 1.85.6.9 $";
+
/*
- * read() .. non-blocking: ipppd calls it only after select()
- * reports, that there is data
+ * frame log (debug)
*/
-
-static ssize_t
-isdn_ppp_read(struct file *file, char *buf, size_t count, loff_t *off)
+void
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
{
- struct ippp_struct *is;
- struct sk_buff *skb;
- int retval;
+ int cnt,
+ j,
+ i;
+ char buf[80];
- if (off != &file->f_pos)
- return -ESPIPE;
-
- is = file->private_data;
+ if (len < maxlen)
+ maxlen = len;
- if (!(is->state & IPPP_OPEN)) {
- retval = 0;
- goto out;
- }
- skb = skb_dequeue(&is->rq);
- if (!skb) {
- retval = -EAGAIN;
- goto out;
- }
- if (skb->len > count) {
- retval = -EMSGSIZE;
- goto out_free;
+ for (i = 0, cnt = 0; cnt < maxlen; i++) {
+ for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
+ sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
+ printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
}
- if (copy_to_user(buf, skb->data, skb->len)) {
- retval = -EFAULT;
- goto out_free;
+}
+
+
+static void
+isdn_ppp_push_header(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+{
+ unsigned char *p;
+
+ if (skb_headroom(skb) < 4) {
+ isdn_BUG();
+ return;
}
- retval = skb->len;
- out_free:
- dev_kfree_skb(skb);
- out:
- return retval;
+ if ((idev->pppcfg & SC_COMP_PROT) && proto <= 0xff)
+ put_u8(skb_push(skb, 1), proto);
+ else
+ put_u16(skb_push(skb, 2), proto);
+
+ if (idev->pppcfg & SC_COMP_AC)
+ return;
+
+ p = skb_push(skb, 2);
+ p += put_u8(p, PPP_ALLSTATIONS);
+ p += put_u8(p, PPP_UI);
}
/*
- * ipppd wanna write a packet to the card .. non-blocking
+ * unbind isdn_net_local <=> ippp-device
+ * note: it can happen, that we hangup/free the master before the slaves
+ * in this case we bind another lp to the master device
*/
-
-static ssize_t
-isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
+static void
+isdn_ppp_unbind(isdn_net_dev *idev)
{
- isdn_net_dev *idev;
- struct ippp_struct *is;
- int proto;
- unsigned char protobuf[4];
- int retval;
+ struct ipppd *is = idev->ipppd;
+
+ if (!is) {
+ isdn_BUG();
+ return;
+ }
- if (off != &file->f_pos)
- return -ESPIPE;
+ ipppd_debug(is, "");
- lock_kernel();
+ if (is->state != IPPPD_ST_ASSIGNED)
+ isdn_BUG();
- is = file->private_data;
+ is->state = IPPPD_ST_OPEN;
- if (!(is->state & IPPP_CONNECT)) {
- retval = 0;
- goto out;
- }
+ /* is->idev will be invalid shortly */
+ ippp_ccp_free(idev->ccp);
- /* -> push it directly to the lowlevel interface */
+ is->idev = NULL;
+ /* lose the reference we took on isdn_ppp_bind */
+ ipppd_put(is);
+ idev->ipppd = NULL;
- idev = is->idev;
- if (!idev)
- printk(KERN_DEBUG "isdn_ppp_write: idev == NULL\n");
- else {
+ return;
+}
+
+/*
+ * bind isdn_net_local <=> ippp-device
+ */
+int
+isdn_ppp_bind(isdn_net_dev *idev)
+{
+ int unit = 0;
+ unsigned long flags;
+ int retval = 0;
+ struct ipppd *ipppd;
+
+ if (idev->ipppd) {
+ isdn_BUG();
+ return 0;
+ }
+
+ spin_lock_irqsave(&ipppds_lock, flags);
+ if (idev->pppbind < 0) { /* device bound to ippp device ? */
+ struct list_head *l;
+ char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
+ memset(exclusive, 0, ISDN_MAX_CHANNELS);
+ /* step through net devices to find exclusive minors */
+ list_for_each(l, &isdn_net_devs) {
+ isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
+ if (p->pppbind >= 0 && p->pppbind < ISDN_MAX_CHANNELS)
+ exclusive[p->pppbind] = 1;
+ }
/*
- * Don't reset huptimer for
- * LCP packets. (Echo requests).
+ * search a free device / slot
*/
- if (copy_from_user(protobuf, buf, 4)) {
- retval = -EFAULT;
- goto out;
+ list_for_each_entry(ipppd, &ipppds, ipppds) {
+ if (!ipppd)
+ continue;
+ if (ipppd->state != IPPPD_ST_OPEN)
+ continue;
+ if (!exclusive[ipppd->minor])
+ break;
+ goto found;
}
- proto = PPP_PROTOCOL(protobuf);
- if (proto != PPP_LCP)
- idev->huptimer = 0;
-
- if (idev->isdn_slot < 0) {
- retval = 0;
- goto out;
+ } else {
+ list_for_each_entry(ipppd, &ipppds, ipppds) {
+ if (!ipppd)
+ continue;
+ if (ipppd->state != IPPPD_ST_OPEN)
+ continue;
+ if (ipppd->minor == idev->pppbind)
+ goto found;
}
- if ((dev->drv[isdn_slot_driver(idev->isdn_slot)]->flags & DRV_FLAG_RUNNING) &&
- isdn_net_online(idev)) {
- unsigned short hl;
- struct sk_buff *skb;
- /*
- * we need to reserve enought space in front of
- * sk_buff. old call to dev_alloc_skb only reserved
- * 16 bytes, now we are looking what the driver want
- */
- hl = isdn_slot_hdrlen(idev->isdn_slot);
- skb = alloc_skb(hl+count, GFP_ATOMIC);
- if (!skb) {
- printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
- retval = count;
- goto out;
- }
- skb_reserve(skb, hl);
- if (copy_from_user(skb_put(skb, count), buf, count))
- {
- kfree_skb(skb);
- retval = -EFAULT;
- goto out;
- }
- if (is->debug & 0x40) {
- printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
- isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,idev->ppp_slot);
- }
+ }
- isdn_ppp_send_ccp(idev,idev->mlp,skb); /* keeps CCP/compression states in sync */
+ printk(KERN_INFO "isdn_ppp_bind: no ipppd\n");
+ retval = -ESRCH;
+ goto err;
- isdn_net_write_super(idev, skb);
- }
+ found:
+ unit = isdn_ppp_if_get_unit(idev->name); /* get unit number from interface name .. ugly! */
+ if (unit < 0) {
+ printk(KERN_INFO "isdn_ppp_bind: illegal interface name %s.\n", idev->name);
+ retval = -ENODEV;
+ goto err;
}
- retval = count;
+ ipppd->unit = unit;
+ ipppd->state = IPPPD_ST_ASSIGNED;
+ ipppd->idev = idev;
+ /* we hold a reference until isdn_ppp_unbind() */
+ idev->ipppd = ipppd_get(ipppd);
+ spin_unlock_irqrestore(&ipppds_lock, flags);
+
+ idev->pppcfg = 0; /* config flags */
+ /* seq no last seen, maybe set to bundle min, when joining? */
+ idev->pppseq = -1;
+
+ idev->ccp = ippp_ccp_alloc();
+ if (!idev->ccp) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ idev->ccp->proto = PPP_COMPFRAG;
+ idev->ccp->priv = idev;
+ idev->ccp->alloc_skb = isdn_ppp_dev_alloc_skb;
+ idev->ccp->push_header = isdn_ppp_dev_push_header;
+ idev->ccp->xmit = isdn_ppp_dev_xmit;
+ idev->ccp->kick_up = isdn_ppp_dev_kick_up;
+
+#ifdef CONFIG_ISDN_MPP
+ retval = isdn_ppp_mp_init(lp, NULL);
+#endif /* CONFIG_ISDN_MPP */
out:
- unlock_kernel();
+ if (retval) {
+ idev->ipppd->state = IPPPD_ST_OPEN;
+ ipppd_put(idev->ipppd);
+ idev->ipppd = NULL;
+ }
+
+ return retval;
+
+ err:
+ spin_unlock_irqrestore(&ipppds_lock, flags);
return retval;
}
-struct file_operations isdn_ppp_fops =
+/*
+ * kick the ipppd on the device
+ * (wakes up daemon after B-channel connect)
+ */
+
+static void
+isdn_ppp_connected(isdn_net_dev *idev)
{
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = isdn_ppp_read,
- .write = isdn_ppp_write,
- .poll = isdn_ppp_poll,
- .ioctl = isdn_ppp_ioctl,
- .open = isdn_ppp_open,
- .release = isdn_ppp_release,
-};
+ struct ipppd *ipppd = idev->ipppd;
+
+ ipppd_debug(ipppd, "");
+
+ ipppd->state = IPPPD_ST_CONNECTED;
+ ipppd->flags |= IPPPD_FL_WAKEUP;
+ wake_up(&ipppd->wq);
+}
+
+static void
+isdn_ppp_disconnected(isdn_net_dev *idev)
+{
+ struct ipppd *ipppd = idev->ipppd;
+
+ ipppd_debug(ipppd, "");
+
+ if (idev->pppcfg & SC_ENABLE_IP)
+ isdn_net_offline(idev);
+
+ if (ipppd->state != IPPPD_ST_CONNECTED)
+ isdn_BUG();
+
+ ipppd->state = IPPPD_ST_ASSIGNED;
+ ipppd->flags |= IPPPD_FL_HUP;
+ wake_up(&ipppd->wq);
+
+#ifdef CONFIG_ISDN_MPP
+ spin_lock(&idev->pb->lock);
+ if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */
+ isdn_ppp_mp_cleanup(lp);
+
+ lp->netdev->pb->ref_ct--;
+ spin_unlock(&lp->netdev->pb->lock);
+#endif /* CONFIG_ISDN_MPP */
+
+}
/*
* init memory, structures etc.
@@ -808,37 +831,17 @@ struct file_operations isdn_ppp_fops =
int
isdn_ppp_init(void)
{
- int i,
- j;
-
#ifdef CONFIG_ISDN_MPP
if( isdn_ppp_mp_bundle_array_init() < 0 )
return -ENOMEM;
#endif /* CONFIG_ISDN_MPP */
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (!(ippp_table[i] = (struct ippp_struct *)
- kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
- printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
- for (j = 0; j < i; j++)
- kfree(ippp_table[j]);
- return -1;
- }
- memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
- ippp_table[i]->state = 0;
- skb_queue_head_init(&ippp_table[i]->rq);
- }
return 0;
}
void
isdn_ppp_cleanup(void)
{
- int i;
-
- for (i = 0; i < ISDN_MAX_CHANNELS; i++)
- kfree(ippp_table[i]);
-
#ifdef CONFIG_ISDN_MPP
if (isdn_ppp_bundle_arr)
kfree(isdn_ppp_bundle_arr);
@@ -850,25 +853,31 @@ isdn_ppp_cleanup(void)
* check for address/control field and skip if allowed
* retval != 0 -> discard packet silently
*/
-static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb)
+static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
{
+ u8 val;
+
if (skb->len < 1)
return -1;
- if (skb->data[0] == 0xff) {
- if (skb->len < 2)
- return -1;
-
- if (skb->data[1] != 0x03)
+ get_u8(skb->data, &val);
+ if (val != PPP_ALLSTATIONS) {
+ /* if AC compression was not negotiated, but no AC present,
+ discard packet */
+ if (idev->pppcfg & SC_REJ_COMP_AC)
return -1;
- // skip address/control (AC) field
- skb_pull(skb, 2);
- } else {
- if (is->pppcfg & SC_REJ_COMP_AC)
- // if AC compression was not negotiated, but used, discard packet
- return -1;
+ return 0;
}
+ if (skb->len < 2)
+ return -1;
+
+ get_u8(skb->data + 1, &val);
+ if (val != PPP_UI)
+ return -1;
+
+ /* skip address/control (AC) field */
+ skb_pull(skb, 2);
return 0;
}
@@ -876,84 +885,80 @@ static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb)
* get the PPP protocol header and pull skb
* retval < 0 -> discard packet silently
*/
-static int isdn_ppp_strip_proto(struct sk_buff *skb)
+int isdn_ppp_strip_proto(struct sk_buff *skb)
{
- int proto;
-
+ u16 proto;
+ u8 val;
+
if (skb->len < 1)
return -1;
- if (skb->data[0] & 0x1) {
- // protocol field is compressed
- proto = skb->data[0];
+ get_u8(skb->data, &val);
+ if (val & 0x1) {
+ /* protocol field is compressed */
+ proto = val;
skb_pull(skb, 1);
} else {
if (skb->len < 2)
return -1;
- proto = ((int) skb->data[0] << 8) + skb->data[1];
+ get_u16(skb->data, &proto);
skb_pull(skb, 2);
}
return proto;
}
-
/*
* handler for incoming packets on a syncPPP interface
*/
static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
- struct ippp_struct *is;
- int slot;
+ struct ipppd *is;
int proto;
- /*
- * If encapsulation is syncppp, don't reset
- * huptimer on LCP packets.
- */
- if (PPP_PROTOCOL(skb->data) != PPP_LCP)
- idev->huptimer = 0;
-
- slot = idev->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
- slot);
- kfree_skb(skb);
- return;
- }
- is = ippp_table[slot];
+ is = idev->ipppd;
+ if (!is)
+ goto err;
if (is->debug & 0x4) {
- printk(KERN_DEBUG "ippp_receive: is:%p lp:%p slot:%d unit:%d len:%d\n",
- is,lp,idev->ppp_slot,is->unit,(int) skb->len);
- isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,idev->ppp_slot);
+ printk(KERN_DEBUG "ippp_receive: is:%p lp:%p unit:%d len:%d\n",
+ is, lp, is->unit, skb->len);
+ isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,-1);
}
- if (isdn_ppp_skip_ac(is, skb) < 0) {
- kfree_skb(skb);
- return;
- }
+ if (isdn_ppp_skip_ac(idev, skb) < 0)
+ goto err;
+
proto = isdn_ppp_strip_proto(skb);
- if (proto < 0) {
- kfree_skb(skb);
- return;
- }
+ if (proto < 0)
+ goto err;
+
+ /* Don't reset huptimer on LCP packets. */
+ if (proto != PPP_LCP)
+ idev->huptimer = 0;
#ifdef CONFIG_ISDN_MPP
if (is->compflags & SC_LINK_DECOMP_ON) {
skb = isdn_ppp_decompress(skb, is, NULL, &proto);
if (!skb) // decompression error
- return;
+ goto put;
}
if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
if (proto == PPP_MP) {
isdn_ppp_mp_receive(lp, idev, skb);
- return;
+ goto put;
}
}
-#endif
isdn_ppp_push_higher(lp, idev, skb, proto);
+ put:
+#else
+ isdn_ppp_push_higher(lp, idev, skb, proto);
+#endif
+ return;
+
+ err:
+ kfree_skb(skb);
}
/*
@@ -966,28 +971,16 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb, int proto)
{
struct net_device *dev = &lp->dev;
- struct ippp_struct *is, *mis;
- int slot;
-
- slot = idev->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
- slot);
- goto drop_packet;
- }
- is = ippp_table[slot];
-
- mis = ippp_table[slot];
+ struct ipppd *is = idev->ipppd;
if (is->debug & 0x10) {
printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
- isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,slot);
+ isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit, -1);
}
- if (mis->compflags & SC_DECOMP_ON) {
- skb = isdn_ppp_decompress(skb, is, mis, &proto);
- if (!skb) // decompression error
- return;
- }
+ skb = ippp_ccp_decompress(lp->ccp, skb, &proto);
+ if (!skb) // decompression error
+ goto out;
+
switch (proto) {
case PPP_IPX: /* untested */
if (is->debug & 0x20)
@@ -1002,19 +995,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
case PPP_COMP:
case PPP_COMPFRAG:
printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
- goto drop_packet;
+ goto drop;
#ifdef CONFIG_ISDN_PPP_VJ
case PPP_VJC_UNCOMP:
if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
- if (idev->ppp_slot < 0) {
- printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
- __FUNCTION__ , idev->ppp_slot);
- goto drop_packet;
- }
- if (slhc_remember(ippp_table[idev->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+ if (slhc_remember(lp->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
- goto drop_packet;
+ goto drop;
}
skb->protocol = htons(ETH_P_IP);
break;
@@ -1029,82 +1017,55 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
if (!skb) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
skb = skb_old;
- goto drop_packet;
+ goto drop;
}
skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len);
- if (idev->ppp_slot < 0) {
- printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
- __FUNCTION__ , idev->ppp_slot);
- goto drop_packet;
- }
- pkt_len = slhc_uncompress(ippp_table[idev->ppp_slot]->slcomp,
+ pkt_len = slhc_uncompress(lp->slcomp,
skb->data, skb_old->len);
kfree_skb(skb_old);
if (pkt_len < 0)
- goto drop_packet;
+ goto drop;
skb_trim(skb, pkt_len);
skb->protocol = htons(ETH_P_IP);
}
break;
#endif
- case PPP_CCP:
case PPP_CCPFRAG:
- isdn_ppp_receive_ccp(idev,lp,skb,proto);
+ ippp_ccp_receive_ccp(idev->ccp, skb);
+ goto ccp;
+ case PPP_CCP:
+ ippp_ccp_receive_ccp(lp->ccp, skb);
+ ccp:
/* Dont pop up ResetReq/Ack stuff to the daemon any
longer - the job is done already */
if(skb->data[0] == CCP_RESETREQ ||
skb->data[0] == CCP_RESETACK)
- break;
+ goto free;
/* fall through */
default:
- isdn_ppp_fill_rq(skb->data, skb->len, proto, idev->ppp_slot); /* push data to pppd device */
- kfree_skb(skb);
- return;
+ // FIXME use skb directly
+ ipppd_queue_read(is, proto, skb->data, skb->len);
+ goto free;
}
/* Reset hangup-timer */
idev->huptimer = 0;
skb->dev = dev;
- skb->mac.raw = skb->data;
netif_rx(skb);
/* net_dev->local->stats.rx_packets++; done in isdn_net.c */
+ out:
return;
- drop_packet:
+ drop:
lp->stats.rx_dropped++;
+ free:
kfree_skb(skb);
}
/*
- * isdn_ppp_skb_push ..
- * checks whether we have enough space at the beginning of the skb
- * and allocs a new SKB if necessary
- */
-static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
-{
- struct sk_buff *skb = *skb_p;
-
- if(skb_headroom(skb) < len) {
- struct sk_buff *nskb = skb_realloc_headroom(skb, len);
-
- if (!nskb) {
- printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
- dev_kfree_skb(skb);
- return NULL;
- }
- printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
- dev_kfree_skb(skb);
- *skb_p = nskb;
- return skb_push(nskb, len);
- }
- return skb_push(skb,len);
-}
-
-
-/*
* send ppp frame .. we expect a PIDCOMPressable proto --
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
*
@@ -1118,30 +1079,13 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_net_local *mlp = ndev->priv;
isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
unsigned int proto = PPP_IP; /* 0x21 */
- struct ippp_struct *ipt,*ipts;
- int slot;
+ struct ipppd *ipppd;
ndev->trans_start = jiffies;
if (list_empty(&mlp->online))
return isdn_net_autodial(skb, ndev);
- slot = idev->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
- slot);
- kfree_skb(skb);
- return 0;
- }
- ipts = ippp_table[slot];
-
- if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
- if (ipts->debug & 0x1)
- printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
- netif_stop_queue(ndev);
- return 1;
- }
-
switch (ntohs(skb->protocol)) {
case ETH_P_IP:
proto = PPP_IP;
@@ -1153,42 +1097,32 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
skb->protocol);
dev_kfree_skb(skb);
- return 0;
+ goto out;
}
- idev = isdn_net_get_locked_dev(mlp);
+ idev = isdn_net_get_xmit_dev(mlp);
if (!idev) {
- printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
- netif_stop_queue(ndev);
- return 1;
+ printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
+ goto stop;
}
- /* we have our lp locked from now on */
- slot = idev->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
- slot);
- kfree_skb(skb);
- return 0;
+ if (!(idev->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
+ isdn_BUG();
+ goto stop;
}
- ipt = ippp_table[slot];
+ ipppd = idev->ipppd;
idev->huptimer = 0;
/*
* after this line .. requeueing in the device queue is no longer allowed!!!
*/
- /* Pull off the fake header we stuck on earlier to keep
- * the fragmentation code happy.
- */
- skb_pull(skb,IPPP_MAX_HEADER);
-
- if (ipt->debug & 0x4)
+ if (ipppd->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
- if (ipts->debug & 0x40)
- isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,idev->ppp_slot);
+ if (ipppd->debug & 0x40)
+ isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipppd->unit, -1);
#ifdef CONFIG_ISDN_PPP_VJ
- if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
+ if (proto == PPP_IP && idev->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
struct sk_buff *new_skb;
unsigned short hl;
/*
@@ -1213,8 +1147,8 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
skb_put(new_skb, skb->len);
buf = skb->data;
- pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
- &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
+ pktlen = slhc_compress(mlp->slcomp, skb->data, skb->len, new_skb->data,
+ &buf, !(idev->pppcfg & SC_NO_TCP_CCID));
if (buf != skb->data) {
if (new_skb->data != buf)
@@ -1241,17 +1175,9 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/*
* normal (single link) or bundle compression
*/
- if(ipts->compflags & SC_COMP_ON) {
- /* We send compressed only if both down- und upstream
- compression is negotiated, that means, CCP is up */
- if(ipts->compflags & SC_DECOMP_ON) {
- skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
- } else {
- printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
- }
- }
+ skb = ippp_ccp_compress(mlp->ccp, skb, &proto);
- if (ipt->debug & 0x24)
+ if (ipppd->debug & 0x24)
printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
#ifdef CONFIG_ISDN_MPP
@@ -1281,45 +1207,29 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
#endif
+#if 0
/*
* 'link in bundle' compression ...
*/
- if(ipt->compflags & SC_LINK_COMP_ON)
+ if (ipt->compflags & SC_LINK_COMP_ON)
skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+#endif
- if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
- unsigned char *data = isdn_ppp_skb_push(&skb,1);
- if(!data)
- goto unlock;
- data[0] = proto & 0xff;
- }
- else {
- unsigned char *data = isdn_ppp_skb_push(&skb,2);
- if(!data)
- goto unlock;
- data[0] = (proto >> 8) & 0xff;
- data[1] = proto & 0xff;
- }
- if(!(ipt->pppcfg & SC_COMP_AC)) {
- unsigned char *data = isdn_ppp_skb_push(&skb,2);
- if(!data)
- goto unlock;
- data[0] = 0xff; /* All Stations */
- data[1] = 0x03; /* Unnumbered information */
- }
-
- /* tx-stats are now updated via BSENT-callback */
+ isdn_ppp_push_header(idev, skb, proto);
- if (ipts->debug & 0x40) {
+ if (ipppd->debug & 0x40) {
printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
- isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,idev->ppp_slot);
+ isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, ipppd->unit, -1);
}
isdn_net_writebuf_skb(idev, skb);
- unlock:
- spin_unlock_bh(&idev->xmit_lock);
+ out:
return 0;
+
+ stop:
+ netif_stop_queue(ndev);
+ return 1;
}
#ifdef CONFIG_ISDN_MPP
@@ -1372,7 +1282,7 @@ static ippp_bundle * isdn_ppp_mp_bundle_alloc(void)
static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
{
isdn_net_dev *idev = lp->netdev;
- struct ippp_struct * is;
+ struct ipppd * is;
if (idev->ppp_slot < 0) {
printk(KERN_ERR "%s: >ppp_slot(%d) out of range\n",
@@ -1396,7 +1306,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
}
lp->netdev->pb->ref_ct++;
- is->last_link_seqno = 0;
+ is->pppseq = 0;
return 0;
}
@@ -1413,7 +1323,7 @@ static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *dev,
struct sk_buff *skb)
{
isdn_net_dev *idev = lp->netdev;
- struct ippp_struct *is;
+ struct ipppd *is;
isdn_net_dev *qdev;
ippp_bundle * mp;
isdn_mppp_stats * stats;
@@ -1442,7 +1352,7 @@ static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *dev,
isdn_ppp_mp_print_recv_pkt(slot, skb);
newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
- skb, is->last_link_seqno);
+ skb, is->pppseq);
/* if this packet seq # is less than last already processed one,
@@ -1460,14 +1370,14 @@ static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *dev,
}
/* find the minimum received sequence number over all links */
- is->last_link_seqno = minseq = newseq;
+ is->pppseq = minseq = newseq;
list_for_each_entry(qdev, &lp->online, online) {
slot = qdev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
__FUNCTION__ ,slot);
} else {
- u32 lls = ippp_table[slot]->last_link_seqno;
+ u32 lls = ippp_table[slot]->pppseq;
if (MP_LT(lls, minseq))
minseq = lls;
}
@@ -1754,7 +1664,7 @@ static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb )
}
static int
-isdn_ppp_bundle(struct ippp_struct *is, int unit)
+isdn_ppp_bundle(struct ipppd *is, int unit)
{
char ifn[IFNAMSIZ + 1];
isdn_net_dev *p;
@@ -1804,11 +1714,11 @@ out:
*/
static int
-isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
+isdn_ppp_dev_ioctl_stats(struct ifreq *ifr, struct net_device *dev)
{
- struct ppp_stats *res,
- t;
+ struct ppp_stats *res, t;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
+ struct slcompress *slcomp;
int err;
res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
@@ -1828,8 +1738,8 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
t.p.ppp_obytes = lp->stats.tx_bytes;
t.p.ppp_oerrors = lp->stats.tx_errors;
#ifdef CONFIG_ISDN_PPP_VJ
- if (slot >= 0 && ippp_table[slot]->slcomp) {
- struct slcompress *slcomp = ippp_table[slot]->slcomp;
+ slcomp = lp->slcomp;
+ if (slcomp) {
t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
t.vj.vjs_compressed = slcomp->sls_o_compressed;
t.vj.vjs_searches = slcomp->sls_o_searches;
@@ -1858,17 +1768,18 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EINVAL;
switch (cmd) {
- case SIOCGPPPVER:
- r = (char *) ifr->ifr_ifru.ifru_data;
- len = strlen(PPP_VERSION) + 1;
- if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
- break;
- case SIOCGPPPSTATS:
- error = isdn_ppp_dev_ioctl_stats(0, ifr, dev);
- break;
- default:
- error = -EINVAL;
- break;
+ case SIOCGPPPVER:
+ r = (char *) ifr->ifr_ifru.ifru_data;
+ len = strlen(PPP_VERSION) + 1;
+ if (copy_to_user(r, PPP_VERSION, len))
+ error = -EFAULT;
+ break;
+ case SIOCGPPPSTATS:
+ error = isdn_ppp_dev_ioctl_stats(ifr, dev);
+ break;
+ default:
+ error = -EINVAL;
+ break;
}
return error;
}
@@ -1962,868 +1873,167 @@ isdn_ppp_hangup_slave(char *name)
/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
generate a CCP Reset-Request or tear down CCP altogether */
-static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
+static void isdn_ppp_dev_kick_up(void *priv)
{
- isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->idev->ppp_slot);
+ isdn_net_dev *idev = priv;
+
+ ipppd_queue_read(idev->ipppd, PPP_COMPFRAG, NULL, 0);
}
-/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
- but absolutely nontrivial. The most abstruse problem we are facing is
- that the generation, reception and all the handling of timeouts and
- resends including proper request id management should be entirely left
- to the (de)compressor, but indeed is not covered by the current API to
- the (de)compressor. The API is a prototype version from PPP where only
- some (de)compressors have yet been implemented and all of them are
- rather simple in their reset handling. Especially, their is only one
- outstanding ResetAck at a time with all of them and ResetReq/-Acks do
- not have parameters. For this very special case it was sufficient to
- just return an error code from the decompressor and have a single
- reset() entry to communicate all the necessary information between
- the framework and the (de)compressor. Bad enough, LZS is different
- (and any other compressor may be different, too). It has multiple
- histories (eventually) and needs to Reset each of them independently
- and thus uses multiple outstanding Acks and history numbers as an
- additional parameter to Reqs/Acks.
- All that makes it harder to port the reset state engine into the
- kernel because it is not just the same simple one as in (i)pppd but
- it must be able to pass additional parameters and have multiple out-
- standing Acks. We are trying to achieve the impossible by handling
- reset transactions independent by their id. The id MUST change when
- the data portion changes, thus any (de)compressor who uses more than
- one resettable state must provide and recognize individual ids for
- each individual reset transaction. The framework itself does _only_
- differentiate them by id, because it has no other semantics like the
- (de)compressor might.
- This looks like a major redesign of the interface would be nice,
- but I don't have an idea how to do it better. */
-
-/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
- getting that lengthy because there is no simple "send-this-frame-out"
- function above but every wrapper does a bit different. Hope I guess
- correct in this hack... */
-
-static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
- unsigned char code, unsigned char id,
- unsigned char *data, int len)
+static void isdn_ppp_lp_kick_up(void *priv)
{
- struct sk_buff *skb;
- unsigned char *p;
- int hl;
- int cnt = 0;
- isdn_net_dev *idev = is->idev;
-
- /* Alloc large enough skb */
- hl = isdn_slot_hdrlen(idev->isdn_slot);
- skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
- if(!skb) {
- printk(KERN_WARNING
- "ippp: CCP cannot send reset - out of memory\n");
- return;
- }
- skb_reserve(skb, hl);
-
- /* We may need to stuff an address and control field first */
- if(!(is->pppcfg & SC_COMP_AC)) {
- p = skb_put(skb, 2);
- *p++ = 0xff;
- *p++ = 0x03;
- }
+ isdn_net_local *lp = priv;
+ isdn_net_dev *idev;
- /* Stuff proto, code, id and length */
- p = skb_put(skb, 6);
- *p++ = (proto >> 8);
- *p++ = (proto & 0xff);
- *p++ = code;
- *p++ = id;
- cnt = 4 + len;
- *p++ = (cnt >> 8);
- *p++ = (cnt & 0xff);
-
- /* Now stuff remaining bytes */
- if(len) {
- p = skb_put(skb, len);
- memcpy(p, data, len);
+ if (list_empty(&lp->online)) {
+ isdn_BUG();
+ return;
}
-
- /* skb is now ready for xmit */
- printk(KERN_DEBUG "Sending CCP Frame:\n");
- isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
-
- isdn_net_write_super(idev, skb);
+ idev = list_entry(lp->online.next, isdn_net_dev, online);
+ ipppd_queue_read(idev->ipppd, PPP_COMP, NULL, 0);
}
-/* Allocate the reset state vector */
-static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
-{
- struct ippp_ccp_reset *r;
- r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
- if(!r) {
- printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
- " structure - no mem\n");
- return NULL;
- }
- memset(r, 0, sizeof(struct ippp_ccp_reset));
- printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
- is->reset = r;
- return r;
-}
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */
-/* Destroy the reset state vector. Kill all pending timers first. */
-static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
+static struct sk_buff *
+__isdn_ppp_alloc_skb(isdn_net_dev *idev, int len, unsigned int gfp_mask)
{
- unsigned int id;
+ int hl = IPPP_MAX_HEADER + isdn_slot_hdrlen(idev->isdn_slot);
+ struct sk_buff *skb;
- printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
- is->reset);
- for(id = 0; id < 256; id++) {
- if(is->reset->rs[id]) {
- isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
- }
- }
- kfree(is->reset);
- is->reset = NULL;
-}
+ skb = alloc_skb(hl + len, gfp_mask);
+ if (!skb)
+ return NULL;
-/* Free a given state and clear everything up for later reallocation */
-static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
- unsigned char id)
-{
- struct ippp_ccp_reset_state *rs;
-
- if(is->reset->rs[id]) {
- printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
- rs = is->reset->rs[id];
- /* Make sure the kernel will not call back later */
- if(rs->ta)
- del_timer(&rs->timer);
- is->reset->rs[id] = NULL;
- kfree(rs);
- } else {
- printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
- }
+ skb_reserve(skb, hl);
+ return skb;
}
-/* The timer callback function which is called when a ResetReq has timed out,
- aka has never been answered by a ResetAck */
-static void isdn_ppp_ccp_timer_callback(unsigned long closure)
+static struct sk_buff *
+isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask)
{
- struct ippp_ccp_reset_state *rs =
- (struct ippp_ccp_reset_state *)closure;
+ isdn_net_dev *idev = priv;
- if(!rs) {
- printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
- return;
- }
- if(rs->ta && rs->state == CCPResetSentReq) {
- /* We are correct here */
- if(!rs->expra) {
- /* Hmm, there is no Ack really expected. We can clean
- up the state now, it will be reallocated if the
- decompressor insists on another reset */
- rs->ta = 0;
- isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
- return;
- }
- printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
- rs->id);
- /* Push it again */
- isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
- rs->data, rs->dlen);
- /* Restart timer */
- rs->timer.expires = jiffies + HZ*5;
- add_timer(&rs->timer);
- } else {
- printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
- rs->state);
- }
+ return __isdn_ppp_alloc_skb(idev, len, gfp_mask);
}
-/* Allocate a new reset transaction state */
-static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
- unsigned char id)
+static struct sk_buff *
+isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask)
{
- struct ippp_ccp_reset_state *rs;
- if(is->reset->rs[id]) {
- printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
- id);
+ isdn_net_local *lp = priv;
+ isdn_net_dev *idev;
+
+ if (list_empty(&lp->online)) {
+ isdn_BUG();
return NULL;
- } else {
- rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
- if(!rs)
- return NULL;
- memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
- rs->state = CCPResetIdle;
- rs->is = is;
- rs->id = id;
- rs->timer.data = (unsigned long)rs;
- rs->timer.function = isdn_ppp_ccp_timer_callback;
- is->reset->rs[id] = rs;
}
- return rs;
+ idev = list_entry(lp->online.next, isdn_net_dev, online);
+ return __isdn_ppp_alloc_skb(idev, len, gfp_mask);
}
-
-/* A decompressor wants a reset with a set of parameters - do what is
- necessary to fulfill it */
-static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
- struct isdn_ppp_resetparams *rp)
+static void
+isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto)
{
- struct ippp_ccp_reset_state *rs;
-
- if(rp->valid) {
- /* The decompressor defines parameters by itself */
- if(rp->rsend) {
- /* And he wants us to send a request */
- if(!(rp->idval)) {
- printk(KERN_ERR "ippp_ccp: decompressor must"
- " specify reset id\n");
- return;
- }
- if(is->reset->rs[rp->id]) {
- /* There is already a transaction in existence
- for this id. May be still waiting for a
- Ack or may be wrong. */
- rs = is->reset->rs[rp->id];
- if(rs->state == CCPResetSentReq && rs->ta) {
- printk(KERN_DEBUG "ippp_ccp: reset"
- " trans still in progress"
- " for id %d\n", rp->id);
- } else {
- printk(KERN_WARNING "ippp_ccp: reset"
- " trans in wrong state %d for"
- " id %d\n", rs->state, rp->id);
- }
- } else {
- /* Ok, this is a new transaction */
- printk(KERN_DEBUG "ippp_ccp: new trans for id"
- " %d to be started\n", rp->id);
- rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
- if(!rs) {
- printk(KERN_ERR "ippp_ccp: out of mem"
- " allocing ccp trans\n");
- return;
- }
- rs->state = CCPResetSentReq;
- rs->expra = rp->expra;
- if(rp->dtval) {
- rs->dlen = rp->dlen;
- memcpy(rs->data, rp->data, rp->dlen);
- }
- /* HACK TODO - add link comp here */
- isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
- CCP_RESETREQ, rs->id,
- rs->data, rs->dlen);
- /* Start the timer */
- rs->timer.expires = jiffies + 5*HZ;
- add_timer(&rs->timer);
- rs->ta = 1;
- }
- } else {
- printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
- }
- } else {
- /* The reset params are invalid. The decompressor does not
- care about them, so we just send the minimal requests
- and increase ids only when an Ack is received for a
- given id */
- if(is->reset->rs[is->reset->lastid]) {
- /* There is already a transaction in existence
- for this id. May be still waiting for a
- Ack or may be wrong. */
- rs = is->reset->rs[is->reset->lastid];
- if(rs->state == CCPResetSentReq && rs->ta) {
- printk(KERN_DEBUG "ippp_ccp: reset"
- " trans still in progress"
- " for id %d\n", rp->id);
- } else {
- printk(KERN_WARNING "ippp_ccp: reset"
- " trans in wrong state %d for"
- " id %d\n", rs->state, rp->id);
- }
- } else {
- printk(KERN_DEBUG "ippp_ccp: new trans for id"
- " %d to be started\n", is->reset->lastid);
- rs = isdn_ppp_ccp_reset_alloc_state(is,
- is->reset->lastid);
- if(!rs) {
- printk(KERN_ERR "ippp_ccp: out of mem"
- " allocing ccp trans\n");
- return;
- }
- rs->state = CCPResetSentReq;
- /* We always expect an Ack if the decompressor doesnt
- know better */
- rs->expra = 1;
- rs->dlen = 0;
- /* HACK TODO - add link comp here */
- isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
- rs->id, NULL, 0);
- /* Start the timer */
- rs->timer.expires = jiffies + 5*HZ;
- add_timer(&rs->timer);
- rs->ta = 1;
- }
- }
-}
+ isdn_net_dev *idev = priv;
-/* An Ack was received for this id. This means we stop the timer and clean
- up the state prior to calling the decompressors reset routine. */
-static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
- unsigned char id)
-{
- struct ippp_ccp_reset_state *rs = is->reset->rs[id];
-
- if(rs) {
- if(rs->ta && rs->state == CCPResetSentReq) {
- /* Great, we are correct */
- if(!rs->expra)
- printk(KERN_DEBUG "ippp_ccp: ResetAck received"
- " for id %d but not expected\n", id);
- } else {
- printk(KERN_INFO "ippp_ccp: ResetAck received out of"
- "sync for id %d\n", id);
- }
- if(rs->ta) {
- rs->ta = 0;
- del_timer(&rs->timer);
- }
- isdn_ppp_ccp_reset_free_state(is, id);
- } else {
- printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
- " %d\n", id);
- }
- /* Make sure the simple reset stuff uses a new id next time */
- is->reset->lastid++;
+ isdn_ppp_push_header(idev, skb, proto);
}
-/*
- * decompress packet
- *
- * if master = 0, we're trying to uncompress an per-link compressed packet,
- * as opposed to an compressed reconstructed-from-MPPP packet.
- * proto is updated to protocol field of uncompressed packet.
- *
- * retval: decompressed packet,
- * same packet if uncompressed,
- * NULL if decompression error
- */
-
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
- int *proto)
+static void
+isdn_ppp_lp_push_header(void *priv, struct sk_buff *skb, u16 proto)
{
- void *stat = NULL;
- struct isdn_ppp_compressor *ipc = NULL;
- struct sk_buff *skb_out;
- int len;
- struct ippp_struct *ri;
- struct isdn_ppp_resetparams rsparm;
- unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
-
- if(!master) {
- // per-link decompression
- stat = is->link_decomp_stat;
- ipc = is->link_decompressor;
- ri = is;
- } else {
- stat = master->decomp_stat;
- ipc = master->decompressor;
- ri = master;
- }
-
- if (!ipc) {
- // no decompressor -> we can't decompress.
- printk(KERN_DEBUG "ippp: no decompressor defined!\n");
- return skb;
- }
- if (!stat) // if we have a compressor, stat has been set as well
- BUG();
-
- if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
- // compressed packets are compressed by their protocol type
+ isdn_net_local *lp = priv;
+ isdn_net_dev *idev;
- // Set up reset params for the decompressor
- memset(&rsparm, 0, sizeof(rsparm));
- rsparm.data = rsdata;
- rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
-
- skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
- len = ipc->decompress(stat, skb, skb_out, &rsparm);
- kfree_skb(skb);
- if (len <= 0) {
- switch(len) {
- case DECOMP_ERROR:
- printk(KERN_INFO "ippp: decomp wants reset %s params\n",
- rsparm.valid ? "with" : "without");
-
- isdn_ppp_ccp_reset_trans(ri, &rsparm);
- break;
- case DECOMP_FATALERROR:
- ri->pppcfg |= SC_DC_FERROR;
- /* Kick ipppd to recognize the error */
- isdn_ppp_ccp_kickup(ri);
- break;
- }
- kfree_skb(skb_out);
- return NULL;
- }
- *proto = isdn_ppp_strip_proto(skb_out);
- if (*proto < 0) {
- kfree_skb(skb_out);
- return NULL;
- }
- return skb_out;
- } else {
- // uncompressed packets are fed through the decompressor to
- // update the decompressor state
- ipc->incomp(stat, skb, *proto);
- return skb;
+ if (list_empty(&lp->online)) {
+ isdn_BUG();
+ return;
}
+ idev = list_entry(lp->online.next, isdn_net_dev, online);
+ isdn_ppp_push_header(idev, skb, proto);
}
-/*
- * compress a frame
- * type=0: normal/bundle compression
- * =1: link compression
- * returns original skb if we haven't compressed the frame
- * and a new skb pointer if we've done it
- */
-static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
- struct ippp_struct *is,struct ippp_struct *master,int type)
+static void
+isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb)
{
- int ret;
- int new_proto;
- struct isdn_ppp_compressor *compressor;
- void *stat;
- struct sk_buff *skb_out;
-
- /* we do not compress control protocols */
- if(*proto < 0 || *proto > 0x3fff) {
- return skb_in;
- }
-
- if(type) { /* type=1 => Link compression */
- return skb_in;
- }
- else {
- if(!master) {
- compressor = is->compressor;
- stat = is->comp_stat;
- }
- else {
- compressor = master->compressor;
- stat = master->comp_stat;
- }
- new_proto = PPP_COMP;
- }
-
- if(!compressor) {
- printk(KERN_ERR "isdn_ppp: No compressor set!\n");
- return skb_in;
- }
- if(!stat) {
- printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
- return skb_in;
- }
+ isdn_net_dev *idev = priv;
- /* Allow for at least 150 % expansion (for now) */
- skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 +
- skb_headroom(skb_in), GFP_ATOMIC);
- if(!skb_out)
- return skb_in;
- skb_reserve(skb_out, skb_headroom(skb_in));
-
- ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
- if(!ret) {
- dev_kfree_skb(skb_out);
- return skb_in;
- }
-
- dev_kfree_skb(skb_in);
- *proto = new_proto;
- return skb_out;
+ isdn_net_write_super(idev, skb);
}
-/*
- * we received a CCP frame ..
- * not a clean solution, but we MUST handle a few cases in the kernel
- */
-static void isdn_ppp_receive_ccp(isdn_net_dev *idev, isdn_net_local *lp,
- struct sk_buff *skb,int proto)
+static void
+isdn_ppp_lp_xmit(void *priv, struct sk_buff *skb)
{
- struct ippp_struct *is;
- struct ippp_struct *mis;
- int len;
- struct isdn_ppp_resetparams rsparm;
- unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+ isdn_net_local *lp = priv;
+ isdn_net_dev *idev;
- printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
- idev->ppp_slot);
- if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
- __FUNCTION__ , idev->ppp_slot);
+ if (list_empty(&lp->online)) {
+ isdn_BUG();
return;
}
- is = ippp_table[idev->ppp_slot];
- isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
-
- mis = is;
-
- switch(skb->data[0]) {
- case CCP_CONFREQ:
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Disable compression here!\n");
- if(proto == PPP_CCP)
- mis->compflags &= ~SC_COMP_ON;
- else
- is->compflags &= ~SC_LINK_COMP_ON;
- break;
- case CCP_TERMREQ:
- case CCP_TERMACK:
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Disable (de)compression here!\n");
- if(proto == PPP_CCP)
- mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
- else
- is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
- break;
- case CCP_CONFACK:
- /* if we RECEIVE an ackowledge we enable the decompressor */
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Enable decompression here!\n");
- if(proto == PPP_CCP) {
- if (!mis->decompressor)
- break;
- mis->compflags |= SC_DECOMP_ON;
- } else {
- if (!is->decompressor)
- break;
- is->compflags |= SC_LINK_DECOMP_ON;
- }
- break;
-
- case CCP_RESETACK:
- printk(KERN_DEBUG "Received ResetAck from peer\n");
- len = (skb->data[2] << 8) | skb->data[3];
- len -= 4;
-
- if(proto == PPP_CCP) {
- /* If a reset Ack was outstanding for this id, then
- clean up the state engine */
- isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
- if(mis->decompressor && mis->decomp_stat)
- mis->decompressor->
- reset(mis->decomp_stat,
- skb->data[0],
- skb->data[1],
- len ? &skb->data[4] : NULL,
- len, NULL);
- /* TODO: This is not easy to decide here */
- mis->compflags &= ~SC_DECOMP_DISCARD;
- }
- else {
- isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
- if(is->link_decompressor && is->link_decomp_stat)
- is->link_decompressor->
- reset(is->link_decomp_stat,
- skb->data[0],
- skb->data[1],
- len ? &skb->data[4] : NULL,
- len, NULL);
- /* TODO: neither here */
- is->compflags &= ~SC_LINK_DECOMP_DISCARD;
- }
- break;
-
- case CCP_RESETREQ:
- printk(KERN_DEBUG "Received ResetReq from peer\n");
- /* Receiving a ResetReq means we must reset our compressor */
- /* Set up reset params for the reset entry */
- memset(&rsparm, 0, sizeof(rsparm));
- rsparm.data = rsdata;
- rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
- /* Isolate data length */
- len = (skb->data[2] << 8) | skb->data[3];
- len -= 4;
- if(proto == PPP_CCP) {
- if(mis->compressor && mis->comp_stat)
- mis->compressor->
- reset(mis->comp_stat,
- skb->data[0],
- skb->data[1],
- len ? &skb->data[4] : NULL,
- len, &rsparm);
- }
- else {
- if(is->link_compressor && is->link_comp_stat)
- is->link_compressor->
- reset(is->link_comp_stat,
- skb->data[0],
- skb->data[1],
- len ? &skb->data[4] : NULL,
- len, &rsparm);
- }
- /* Ack the Req as specified by rsparm */
- if(rsparm.valid) {
- /* Compressor reset handler decided how to answer */
- if(rsparm.rsend) {
- /* We should send a Frame */
- isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
- rsparm.idval ? rsparm.id
- : skb->data[1],
- rsparm.dtval ?
- rsparm.data : NULL,
- rsparm.dtval ?
- rsparm.dlen : 0);
- } else {
- printk(KERN_DEBUG "ResetAck suppressed\n");
- }
- } else {
- /* We answer with a straight reflected Ack */
- isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
- skb->data[1],
- len ? &skb->data[4] : NULL,
- len);
- }
- break;
- }
+ idev = list_entry(lp->online.next, isdn_net_dev, online);
+ isdn_net_write_super(idev, skb);
}
-
-/*
- * Daemon sends a CCP frame ...
- */
-
-/* TODO: Clean this up with new Reset semantics */
-
-/* I believe the CCP handling as-is is done wrong. Compressed frames
- * should only be sent/received after CCP reaches UP state, which means
- * both sides have sent CONF_ACK. Currently, we handle both directions
- * independently, which means we may accept compressed frames too early
- * (supposedly not a problem), but may also mean we send compressed frames
- * too early, which may turn out to be a problem.
- * This part of state machine should actually be handled by (i)pppd, but
- * that's too big of a change now. --kai
- */
-
-/* Actually, we might turn this into an advantage: deal with the RFC in
- * the old tradition of beeing generous on what we accept, but beeing
- * strict on what we send. Thus we should just
- * - accept compressed frames as soon as decompression is negotiated
- * - send compressed frames only when decomp *and* comp are negotiated
- * - drop rx compressed frames if we cannot decomp (instead of pushing them
- * up to ipppd)
- * and I tried to modify this file according to that. --abp
- */
-
-static void isdn_ppp_send_ccp(isdn_net_dev *idev, isdn_net_local *lp, struct sk_buff *skb)
+static int
+isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data)
{
- struct ippp_struct *mis,*is;
- int proto, slot = idev->ppp_slot;
- unsigned char *data;
-
- if(!skb || skb->len < 3)
- return;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
- __FUNCTION__ , slot);
- return;
- }
- is = ippp_table[slot];
- /* Daemon may send with or without address and control field comp */
- data = skb->data;
- if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
- data += 2;
- if(skb->len < 5)
- return;
- }
-
- proto = ((int)data[0]<<8)+data[1];
- if(proto != PPP_CCP && proto != PPP_CCPFRAG)
- return;
+ struct ippp_ccp *ccp;
- printk(KERN_DEBUG "Received CCP frame from daemon:\n");
- isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
+ if (data->flags & IPPP_COMP_FLAG_LINK)
+ ccp = idev->ccp;
+ else
+ ccp = idev->mlp->ccp;
- mis = is;
- if (mis != is)
- printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
-
- switch(data[2]) {
- case CCP_CONFREQ:
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Disable decompression here!\n");
- if(proto == PPP_CCP)
- is->compflags &= ~SC_DECOMP_ON;
- else
- is->compflags &= ~SC_LINK_DECOMP_ON;
- break;
- case CCP_TERMREQ:
- case CCP_TERMACK:
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Disable (de)compression here!\n");
- if(proto == PPP_CCP)
- is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
- else
- is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
- break;
- case CCP_CONFACK:
- /* if we SEND an ackowledge we can/must enable the compressor */
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Enable compression here!\n");
- if(proto == PPP_CCP) {
- if (!is->compressor)
- break;
- is->compflags |= SC_COMP_ON;
- } else {
- if (!is->compressor)
- break;
- is->compflags |= SC_LINK_COMP_ON;
- }
- break;
- case CCP_RESETACK:
- /* If we send a ACK we should reset our compressor */
- if(is->debug & 0x10)
- printk(KERN_DEBUG "Reset decompression state here!\n");
- printk(KERN_DEBUG "ResetAck from daemon passed by\n");
- if(proto == PPP_CCP) {
- /* link to master? */
- if(is->compressor && is->comp_stat)
- is->compressor->reset(is->comp_stat, 0, 0,
- NULL, 0, NULL);
- is->compflags &= ~SC_COMP_DISCARD;
- }
- else {
- if(is->link_compressor && is->link_comp_stat)
- is->link_compressor->reset(is->link_comp_stat,
- 0, 0, NULL, 0, NULL);
- is->compflags &= ~SC_LINK_COMP_DISCARD;
- }
- break;
- case CCP_RESETREQ:
- /* Just let it pass by */
- printk(KERN_DEBUG "ResetReq from daemon passed by\n");
- break;
- }
+ return ippp_ccp_set_compressor(ccp, idev->ipppd->unit, data);
}
-int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
-{
- ipc->next = ipc_head;
- ipc->prev = NULL;
- if(ipc_head) {
- ipc_head->prev = ipc;
- }
- ipc_head = ipc;
- return 0;
-}
+// ISDN_NET_ENCAP_SYNCPPP
+// ======================================================================
-int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
+static int
+isdn_ppp_open(isdn_net_local *lp)
{
- if(ipc->prev)
- ipc->prev->next = ipc->next;
- else
- ipc_head = ipc->next;
- if(ipc->next)
- ipc->next->prev = ipc->prev;
- ipc->prev = ipc->next = NULL;
- return 0;
-}
+ lp->mpppcfg = 0; /* mppp configuration */
+ lp->mp_seqno = 0; /* MP sequence number */
-static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
-{
- struct isdn_ppp_compressor *ipc = ipc_head;
- int ret;
- void *stat;
- int num = data->num;
-
- if(is->debug & 0x10)
- printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
- (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
-
- /* If is has no valid reset state vector, we cannot allocate a
- decompressor. The decompressor would cause reset transactions
- sooner or later, and they need that vector. */
-
- if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
- printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
- " allow decompression.\n");
+#ifdef CONFIG_ISDN_PPP_VJ
+ lp->slcomp = slhc_init(16, 16);
+#endif
+ lp->ccp = ippp_ccp_alloc();
+ if (!lp->ccp)
return -ENOMEM;
- }
+ lp->ccp->proto = PPP_COMP;
+ lp->ccp->priv = lp;
+ lp->ccp->alloc_skb = isdn_ppp_lp_alloc_skb;
+ lp->ccp->push_header = isdn_ppp_lp_push_header;
+ lp->ccp->xmit = isdn_ppp_lp_xmit;
+ lp->ccp->kick_up = isdn_ppp_lp_kick_up;
- while(ipc) {
- if(ipc->num == num) {
- stat = ipc->alloc(data);
- if(stat) {
- ret = ipc->init(stat,data,is->unit,0);
- if(!ret) {
- printk(KERN_ERR "Can't init (de)compression!\n");
- ipc->free(stat);
- stat = NULL;
- break;
- }
- }
- else {
- printk(KERN_ERR "Can't alloc (de)compression!\n");
- break;
- }
-
- if(data->flags & IPPP_COMP_FLAG_XMIT) {
- if(data->flags & IPPP_COMP_FLAG_LINK) {
- if(is->link_comp_stat)
- is->link_compressor->free(is->link_comp_stat);
- is->link_comp_stat = stat;
- is->link_compressor = ipc;
- }
- else {
- if(is->comp_stat)
- is->compressor->free(is->comp_stat);
- is->comp_stat = stat;
- is->compressor = ipc;
- }
- }
- else {
- if(data->flags & IPPP_COMP_FLAG_LINK) {
- if(is->link_decomp_stat)
- is->link_decompressor->free(is->link_decomp_stat);
- is->link_decomp_stat = stat;
- is->link_decompressor = ipc;
- }
- else {
- if(is->decomp_stat)
- is->decompressor->free(is->decomp_stat);
- is->decomp_stat = stat;
- is->decompressor = ipc;
- }
- }
- return 0;
- }
- ipc = ipc->next;
- }
- return -EINVAL;
+ return 0;
}
-// ISDN_NET_ENCAP_SYNCPPP
-// ======================================================================
-
-static int
-isdn_ppp_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr,
- unsigned plen)
+static void
+isdn_ppp_close(isdn_net_local *lp)
{
- skb_push(skb, IPPP_MAX_HEADER);
-
- return IPPP_MAX_HEADER;
+#ifdef CONFIG_ISDN_PPP_VJ
+ slhc_free(lp->slcomp);
+ lp->slcomp = NULL;
+#endif
+ ippp_ccp_free(lp->ccp);
+ lp->ccp = NULL;
}
struct isdn_netif_ops isdn_ppp_ops = {
.hard_start_xmit = isdn_ppp_start_xmit,
- .hard_header = isdn_ppp_header,
.do_ioctl = isdn_ppp_dev_ioctl,
.flags = IFF_NOARP | IFF_POINTOPOINT,
.type = ARPHRD_PPP,
.receive = isdn_ppp_receive,
- .connected = isdn_ppp_wakeup_daemon,
+ .connected = isdn_ppp_connected,
+ .disconnected = isdn_ppp_disconnected,
.bind = isdn_ppp_bind,
- .unbind = isdn_ppp_free,
-
+ .unbind = isdn_ppp_unbind,
+ .open = isdn_ppp_open,
+ .close = isdn_ppp_close,
};
diff --git a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h
index af6f50fd11db..20745b31ef1d 100644
--- a/drivers/isdn/i4l/isdn_ppp.h
+++ b/drivers/isdn/i4l/isdn_ppp.h
@@ -15,17 +15,15 @@
extern struct file_operations isdn_ppp_fops;
extern struct isdn_netif_ops isdn_ppp_ops;
-extern int isdn_ppp_init(void);
-extern void isdn_ppp_cleanup(void);
-extern int isdn_ppp_dial_slave(char *);
-extern int isdn_ppp_hangup_slave(char *);
+int isdn_ppp_init(void);
+void isdn_ppp_cleanup(void);
+int isdn_ppp_dial_slave(char *);
+int isdn_ppp_hangup_slave(char *);
-#define IPPP_OPEN 0x01
-#define IPPP_CONNECT 0x02
-#define IPPP_CLOSEWAIT 0x04
-#define IPPP_NOBLOCK 0x08
-#define IPPP_ASSIGNED 0x10
+void
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,
+ int unit, int slot);
+int
+isdn_ppp_strip_proto(struct sk_buff *skb);
#define IPPP_MAX_HEADER 10
-
-
diff --git a/drivers/isdn/i4l/isdn_ppp_ccp.c b/drivers/isdn/i4l/isdn_ppp_ccp.c
new file mode 100644
index 000000000000..ab573e7a6376
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_ppp_ccp.c
@@ -0,0 +1,601 @@
+
+#include "isdn_ppp_ccp.h"
+#include "isdn_common.h"
+#include "isdn_net.h"
+#include "isdn_ppp.h"
+#include <linux/ppp-comp.h>
+
+/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
+ but absolutely nontrivial. The most abstruse problem we are facing is
+ that the generation, reception and all the handling of timeouts and
+ resends including proper request id management should be entirely left
+ to the (de)compressor, but indeed is not covered by the current API to
+ the (de)compressor. The API is a prototype version from PPP where only
+ some (de)compressors have yet been implemented and all of them are
+ rather simple in their reset handling. Especially, their is only one
+ outstanding ResetAck at a time with all of them and ResetReq/-Acks do
+ not have parameters. For this very special case it was sufficient to
+ just return an error code from the decompressor and have a single
+ reset() entry to communicate all the necessary information between
+ the framework and the (de)compressor. Bad enough, LZS is different
+ (and any other compressor may be different, too). It has multiple
+ histories (eventually) and needs to Reset each of them independently
+ and thus uses multiple outstanding Acks and history numbers as an
+ additional parameter to Reqs/Acks.
+ All that makes it harder to port the reset state engine into the
+ kernel because it is not just the same simple one as in (i)pppd but
+ it must be able to pass additional parameters and have multiple out-
+ standing Acks. We are trying to achieve the impossible by handling
+ reset transactions independent by their id. The id MUST change when
+ the data portion changes, thus any (de)compressor who uses more than
+ one resettable state must provide and recognize individual ids for
+ each individual reset transaction. The framework itself does _only_
+ differentiate them by id, because it has no other semantics like the
+ (de)compressor might.
+ This looks like a major redesign of the interface would be nice,
+ but I don't have an idea how to do it better. */
+
+/* ====================================================================== */
+
+/* Free a given state and clear everything up for later reallocation */
+static void
+ippp_ccp_reset_free_state(struct ippp_ccp *ccp, unsigned char id)
+{
+ struct ippp_ccp_reset_state *rs = ccp->reset->rs[id];
+
+ if (!rs)
+ return;
+
+ if (rs->ta) // FIXME?
+ del_timer_sync(&rs->timer);
+
+ kfree(rs);
+ ccp->reset->rs[id] = NULL;
+}
+
+static void
+do_xmit_reset(struct ippp_ccp *ccp, unsigned char code, unsigned char id,
+ unsigned char *data, int len)
+{
+ struct sk_buff *skb;
+ unsigned char *p;
+ u16 proto = ccp->proto == PPP_COMP ? PPP_CCP : PPP_CCPFRAG;
+
+ skb = ccp->alloc_skb(ccp->priv, 4 + len, GFP_ATOMIC);
+ ccp->push_header(ccp->priv, skb, proto);
+
+ p = skb_put(skb, 4);
+ p += put_u8 (p, code);
+ p += put_u8 (p, id);
+ p += put_u16(p, len + 4);
+
+ if (len)
+ memcpy(skb_put(skb, len), data, len);
+
+ isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1);
+
+ ccp->xmit(ccp->priv, skb);
+}
+
+/* The timer callback function which is called when a ResetReq has timed out,
+ aka has never been answered by a ResetAck */
+static void
+isdn_ppp_ccp_timer_callback(unsigned long data)
+{
+ struct ippp_ccp_reset_state *rs = (struct ippp_ccp_reset_state *) data;
+
+ if (!rs->ta) {
+ isdn_BUG();
+ return;
+ }
+ if (rs->state != CCPResetSentReq) {
+ printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
+ rs->state);
+ rs->ta = 0;
+ return;
+ }
+ /* We are correct here */
+ if (!rs->expra) {
+ /* Hmm, there is no Ack really expected. We can clean
+ up the state now, it will be reallocated if the
+ decompressor insists on another reset */
+ rs->ta = 0;
+ ippp_ccp_reset_free_state(rs->ccp, rs->id);
+ return;
+ }
+ printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+ rs->id);
+ /* Push it again */
+ do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen);
+
+ mod_timer(&rs->timer, jiffies + 5 * HZ);
+}
+
+/* Allocate a new reset transaction state */
+static struct ippp_ccp_reset_state *
+ippp_ccp_reset_alloc_state(struct ippp_ccp *ccp, unsigned char id)
+{
+ struct ippp_ccp_reset_state *rs;
+
+ rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+ if(!rs)
+ return NULL;
+ memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
+ rs->state = CCPResetIdle;
+ rs->ccp = ccp;
+ rs->id = id;
+ init_timer(&rs->timer);
+ rs->timer.data = (unsigned long)rs;
+ rs->timer.function = isdn_ppp_ccp_timer_callback;
+
+ ccp->reset->rs[id] = rs;
+ return rs;
+}
+
+/* A decompressor wants a reset with a set of parameters - do what is
+ necessary to fulfill it */
+static void
+ippp_ccp_reset_xmit(struct ippp_ccp *ccp,
+ struct isdn_ppp_resetparams *rp)
+{
+ struct ippp_ccp_reset_state *rs;
+ int id;
+
+ if (rp->valid) {
+ /* The decompressor defines parameters by itself */
+ if (!rp->rsend)
+ return;
+
+ /* And it wants us to send a request */
+ if (!rp->idval) {
+ isdn_BUG();
+ return;
+ }
+ id = rp->id;
+ } else {
+ /* The reset params are invalid. The decompressor does not
+ care about them, so we just send the minimal requests
+ and increase ids only when an Ack is received for a
+ given id */
+ id = ccp->reset->lastid++;
+ /* We always expect an Ack if the decompressor doesnt
+ know better */
+ rp->expra = 1;
+ rp->dtval = 0;
+ }
+ rs = ccp->reset->rs[id];
+ if (rs) {
+ printk(KERN_INFO "ippp_ccp: reset xmit in wrong state %d "
+ "for id %d (%d)\n", rs->state, id, rs->ta);
+ return;
+ }
+ /* Ok, this is a new transaction */
+ printk(KERN_DEBUG "ippp_ccp: new xmit for id %d\n", id);
+ rs = ippp_ccp_reset_alloc_state(ccp, id);
+ if(!rs) {
+ printk(KERN_INFO "ippp_ccp: out of mem allocing ccp trans\n");
+ return;
+ }
+ rs->expra = rp->expra;
+ rs->id = id;
+ if (rp->dtval) {
+ rs->dlen = rp->dlen;
+ memcpy(rs->data, rp->data, rp->dlen);
+ } else {
+ rs->dlen = 0;
+ }
+
+ rs->state = CCPResetSentReq;
+ do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen);
+
+ /* Start the timer */
+ rs->timer.expires = jiffies + 5*HZ;
+ add_timer(&rs->timer);
+ rs->ta = 1;
+}
+
+/* ====================================================================== */
+
+struct ippp_ccp *
+ippp_ccp_alloc(void)
+{
+ struct ippp_ccp *ccp;
+
+ ccp = kmalloc(sizeof(*ccp), GFP_ATOMIC); // FIXME
+ memset(ccp, 0, sizeof(*ccp));
+ ccp->mru = 1524; /* MRU, default 1524 */
+ ccp->reset = kmalloc(sizeof(*ccp->reset), GFP_ATOMIC); // FIXME alloc together?
+ if (!ccp->reset) {
+ kfree(ccp);
+ return NULL;
+ }
+ memset(ccp->reset, 0, sizeof(*ccp->reset));
+ return ccp;
+}
+
+void
+ippp_ccp_free(struct ippp_ccp *ccp)
+{
+ int id;
+
+ if (ccp->comp_stat)
+ ccp->compressor->free(ccp->comp_stat);
+ if (ccp->decomp_stat)
+ ccp->decompressor->free(ccp->decomp_stat);
+
+ for (id = 0; id < 256; id++) {
+ if (ccp->reset->rs[id])
+ ippp_ccp_reset_free_state(ccp, id);
+ }
+ kfree(ccp->reset);
+ kfree(ccp);
+}
+
+int
+ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru)
+{
+ ccp->mru = mru;
+ return 0;
+}
+
+unsigned int
+ippp_ccp_get_flags(struct ippp_ccp *ccp)
+{
+ return ccp->compflags & (SC_DC_ERROR|SC_DC_FERROR);
+}
+
+/*
+ * compress a frame
+ * returns original skb if we did not compress the frame
+ * and a new skb otherwise
+ */
+struct sk_buff *
+ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
+{
+ struct sk_buff *skb;
+
+ if (!(ccp->compflags & (SC_COMP_ON|SC_DECOMP_ON))) {
+ /* We send compressed only if both down- und upstream
+ compression is negotiated, that means, CCP is up */
+ return skb_in;
+ }
+ /* we do not compress control protocols */
+ if (*proto < 0 || *proto > 0x3fff) {
+ return skb_in;
+ }
+ if (!ccp->compressor || !ccp->comp_stat) {
+ isdn_BUG();
+ return skb_in;
+ }
+ /* Allow for at least 150 % expansion (for now) */
+ skb = alloc_skb(skb_in->len*2 + skb_headroom(skb_in), GFP_ATOMIC);
+ if (!skb)
+ return skb_in;
+
+ skb_reserve(skb, skb_headroom(skb_in));
+ if (!ccp->compressor->compress(ccp->comp_stat, skb_in, skb, *proto)) {
+ dev_kfree_skb(skb);
+ return skb_in;
+ }
+ isdn_ppp_frame_log("comp in:", skb_in->data, skb_in->len, 20, -1, -1);
+ isdn_ppp_frame_log("comp out:", skb->data, skb->len, 20, -1, -1);
+ dev_kfree_skb(skb_in);
+ *proto = ccp->proto;
+ return skb;
+}
+
+/*
+ * decompress packet
+ *
+ * proto is updated to protocol field of uncompressed packet.
+ * retval: decompressed packet,
+ * same packet if uncompressed,
+ * NULL if decompression error
+ */
+
+struct sk_buff *
+ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
+{
+ struct sk_buff *skb;
+ struct isdn_ppp_resetparams rsparm;
+ unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+ int len;
+
+ if (!(ccp->compflags & SC_DECOMP_ON)) {
+ return skb_in;
+ }
+ if (!ccp->decompressor || !ccp->decomp_stat) {
+ isdn_BUG();
+ return skb_in;
+ }
+ if (*proto != ccp->proto) {
+ /* uncompressed packets are fed through the decompressor to
+ * update the decompressor state */
+ ccp->decompressor->incomp(ccp->decomp_stat, skb_in, *proto);
+ return skb_in;
+ }
+ skb = dev_alloc_skb(ccp->mru + PPP_HDRLEN); // FIXME oom?
+
+ // Set up reset params for the decompressor
+ memset(&rsparm, 0, sizeof(rsparm));
+ rsparm.data = rsdata;
+ rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+
+ len = ccp->decompressor->decompress(ccp->decomp_stat, skb_in, skb,
+ &rsparm);
+ isdn_ppp_frame_log("deco in:", skb_in->data, skb_in->len, 20, -1, -1);
+ isdn_ppp_frame_log("deco out:", skb->data, skb->len, 20, -1, -1);
+ kfree_skb(skb_in);
+
+ if (len <= 0) {
+ switch(len) {
+ case DECOMP_ERROR:
+ printk(KERN_INFO "ippp: decomp wants reset with%s params\n",
+ rsparm.valid ? "" : "out");
+
+ ippp_ccp_reset_xmit(ccp, &rsparm);
+ break;
+ case DECOMP_FATALERROR:
+ ccp->compflags |= SC_DC_FERROR;
+ /* Kick ipppd to recognize the error */
+ ccp->kick_up(ccp->priv);
+ break;
+ }
+ kfree_skb(skb);
+ return NULL;
+ }
+ *proto = isdn_ppp_strip_proto(skb);
+ if (*proto < 0) {
+ kfree_skb(skb);
+ return NULL;
+ }
+ return skb;
+}
+
+/* An Ack was received for this id. This means we stop the timer and clean
+ up the state prior to calling the decompressors reset routine. */
+static void
+isdn_ppp_ccp_reset_ack_rcvd(struct ippp_ccp *ccp, unsigned char id)
+{
+ struct ippp_ccp_reset_state *rs = ccp->reset->rs[id];
+
+ if (!rs) {
+ printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
+ " %d\n", id);
+ return;
+ }
+
+ if (rs->ta && rs->state == CCPResetSentReq) {
+ /* Great, we are correct */
+ if(!rs->expra)
+ printk(KERN_DEBUG "ippp_ccp: ResetAck received"
+ " for id %d but not expected\n", id);
+ } else {
+ printk(KERN_INFO "ippp_ccp: ResetAck received out of"
+ "sync for id %d\n", id);
+ }
+ if(rs->ta) {
+ rs->ta = 0;
+ del_timer(&rs->timer);
+ }
+ ippp_ccp_reset_free_state(ccp, id);
+}
+
+void
+ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
+{
+ int len;
+ struct isdn_ppp_resetparams rsparm;
+ unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
+ isdn_ppp_frame_log("ccp-recv", skb->data, skb->len, 32, -1, -1);
+
+ switch(skb->data[0]) {
+ case CCP_CONFREQ:
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Disable compression here!\n");
+
+ ccp->compflags &= ~SC_COMP_ON;
+ break;
+ case CCP_TERMREQ:
+ case CCP_TERMACK:
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Disable (de)compression here!\n");
+
+ ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+ break;
+ case CCP_CONFACK:
+ /* if we RECEIVE an ackowledge we enable the decompressor */
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Enable decompression here!\n");
+
+ if (!ccp->decomp_stat)
+ break;
+ ccp->compflags |= SC_DECOMP_ON;
+ break;
+ case CCP_RESETACK:
+ printk(KERN_DEBUG "Received ResetAck from peer\n");
+ len = (skb->data[2] << 8) | skb->data[3];
+ len -= 4;
+
+ /* If a reset Ack was outstanding for this id, then
+ clean up the state engine */
+ isdn_ppp_ccp_reset_ack_rcvd(ccp, skb->data[1]);
+ if (ccp->decomp_stat)
+ ccp->decompressor->reset(ccp->decomp_stat,
+ skb->data[0], skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len, NULL);
+ /* TODO: This is not easy to decide here */
+ ccp->compflags &= ~SC_DECOMP_DISCARD;
+ break;
+ case CCP_RESETREQ:
+ printk(KERN_DEBUG "Received ResetReq from peer\n");
+ /* Receiving a ResetReq means we must reset our compressor */
+ /* Set up reset params for the reset entry */
+ memset(&rsparm, 0, sizeof(rsparm));
+ rsparm.data = rsdata;
+ rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+ /* Isolate data length */
+ len = (skb->data[2] << 8) | skb->data[3];
+ len -= 4;
+ if (ccp->comp_stat)
+ ccp->compressor->reset(ccp->comp_stat,
+ skb->data[0], skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len, &rsparm);
+ /* Ack the Req as specified by rsparm */
+ if (rsparm.valid) {
+ /* Compressor reset handler decided how to answer */
+ if (!rsparm.rsend) {
+ printk(KERN_DEBUG "ResetAck suppressed\n");
+ return;
+ }
+ /* We should send a Frame */
+ do_xmit_reset(ccp, CCP_RESETACK,
+ rsparm.idval ? rsparm.id : skb->data[1],
+ rsparm.data,
+ rsparm.dtval ? rsparm.dlen : 0);
+ return;
+ }
+ /* We answer with a straight reflected Ack */
+ do_xmit_reset(ccp, CCP_RESETACK, skb->data[1],
+ skb->data + 4, len);
+ }
+}
+
+void
+ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
+{
+ isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1);
+
+ switch (skb->data[2]) {
+ case CCP_CONFREQ:
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Disable decompression here!\n");
+
+ ccp->compflags &= ~SC_DECOMP_ON;
+ break;
+ case CCP_TERMREQ:
+ case CCP_TERMACK:
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Disable (de)compression here!\n");
+
+ ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+ break;
+ case CCP_CONFACK:
+ /* if we SEND an ackowledge we can/must enable the compressor */
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Enable compression here!\n");
+
+ if (!ccp->compressor)
+ break;
+
+ ccp->compflags |= SC_COMP_ON;
+ break;
+ case CCP_RESETACK:
+ /* If we send a ACK we should reset our compressor */
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "Reset decompression state here!\n");
+
+ printk(KERN_DEBUG "ResetAck from daemon passed by\n");
+
+ if (!ccp->comp_stat)
+ break;
+
+ ccp->compressor->reset(ccp->comp_stat, 0, 0, NULL, 0, NULL);
+ ccp->compflags &= ~SC_COMP_DISCARD;
+ break;
+ case CCP_RESETREQ:
+ /* Just let it pass by */
+ printk(KERN_DEBUG "ResetReq from daemon passed by\n");
+ break;
+ }
+}
+
+static struct isdn_ppp_compressor *ipc_head = NULL;
+
+int
+ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
+ struct isdn_ppp_comp_data *data)
+{
+ struct isdn_ppp_compressor *ipc = ipc_head;
+ int ret;
+ void *stat;
+ int num = data->num;
+
+ if (ccp->debug & 0x10)
+ printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit,
+ data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num);
+
+ for (ipc = ipc_head; ipc; ipc = ipc->next) {
+ if (ipc->num != num)
+ continue;
+
+ stat = ipc->alloc(data);
+ if (!stat) {
+ printk(KERN_ERR "Can't alloc (de)compression!\n");
+ break;
+ }
+ ret = ipc->init(stat, data, unit, 0);
+ if(!ret) {
+ printk(KERN_ERR "Can't init (de)compression!\n");
+ ipc->free(stat);
+ break;
+ }
+ if (data->flags & IPPP_COMP_FLAG_XMIT) {
+ if (ccp->comp_stat)
+ ccp->compressor->free(ccp->comp_stat);
+ ccp->comp_stat = stat;
+ ccp->compressor = ipc;
+ } else {
+ if (ccp->decomp_stat)
+ ccp->decompressor->free(ccp->decomp_stat);
+ ccp->decomp_stat = stat;
+ ccp->decompressor = ipc;
+ }
+ return 0;
+ }
+ return -EINVAL;
+}
+
+void
+ippp_ccp_get_compressors(unsigned long protos[8])
+{
+ struct isdn_ppp_compressor *ipc;
+ int i, j;
+
+ memset(protos, 0, sizeof(unsigned long) * 8);
+ for (ipc = ipc_head; ipc; ipc = ipc->next) {
+ j = ipc->num / (sizeof(long)*8);
+ i = ipc->num % (sizeof(long)*8);
+ if (j < 8)
+ protos[j] |= 1 << i;
+ }
+}
+
+int
+isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
+{
+ ipc->next = ipc_head;
+ ipc->prev = NULL;
+ if (ipc_head) {
+ ipc_head->prev = ipc;
+ }
+ ipc_head = ipc;
+ return 0;
+}
+
+int
+isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
+{
+ if (ipc->prev)
+ ipc->prev->next = ipc->next;
+ else
+ ipc_head = ipc->next;
+ if (ipc->next)
+ ipc->next->prev = ipc->prev;
+ ipc->prev = ipc->next = NULL;
+ return 0;
+}
+
diff --git a/drivers/isdn/i4l/isdn_ppp_ccp.h b/drivers/isdn/i4l/isdn_ppp_ccp.h
new file mode 100644
index 000000000000..d9ece852d24f
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_ppp_ccp.h
@@ -0,0 +1,66 @@
+
+#include <linux/kernel.h>
+#include <linux/isdn_ppp.h>
+
+/* for ippp_ccp::flags */
+
+#define SC_DECOMP_ON 0x01
+#define SC_COMP_ON 0x02
+#define SC_DECOMP_DISCARD 0x04
+#define SC_COMP_DISCARD 0x08
+
+/* SC_DC_ERROR/FERROR go in here as well, but are defined elsewhere
+
+ #define SC_DC_FERROR 0x00800000
+ #define SC_DC_ERROR 0x00400000
+*/
+
+struct ippp_ccp {
+ int proto;
+ struct isdn_ppp_compressor *compressor;
+ struct isdn_ppp_compressor *decompressor;
+ void *comp_stat;
+ void *decomp_stat;
+ unsigned long compflags;
+ struct ippp_ccp_reset *reset;
+ int mru;
+ int debug;
+ void *priv;
+ void (*xmit)(void *priv, struct sk_buff *skb);
+ void (*kick_up)(void *priv);
+ void (*push_header)(void *priv, struct sk_buff *skb, u16);
+ struct sk_buff *(*alloc_skb)(void *priv, int len, int gfp_mask);
+};
+
+struct ippp_ccp *
+ippp_ccp_alloc(void);
+
+void
+ippp_ccp_free(struct ippp_ccp *ccp);
+
+int
+ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru);
+
+unsigned int
+ippp_ccp_get_flags(struct ippp_ccp *ccp);
+
+struct sk_buff *
+ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb, int *proto);
+
+struct sk_buff *
+ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb, int *proto);
+
+void
+ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
+
+void
+ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
+
+void
+ippp_ccp_get_compressors(unsigned long protos[8]);
+
+int
+ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
+ struct isdn_ppp_comp_data *data);
+
+
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index e757d5063398..612c7b19c85a 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -11,11 +11,12 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/interrupt.h>
#include <linux/init.h>
#include "isdnloop.h"
static char *revision = "$Revision: 1.11.6.7 $";
-static char *isdnloop_id;
+static char *isdnloop_id = "loop0";
MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
MODULE_AUTHOR("Fritz Elfert");
@@ -76,7 +77,7 @@ isdnloop_bchan_send(isdnloop_card * card, int ch)
};
cmd.command = ISDN_STAT_BSENT;
cmd.parm.length = len;
- if ( ack ) card->interface.statcallb(&cmd);
+ card->interface.statcallb(&cmd);
} else
card->sndcount[ch] = 0;
}
@@ -421,8 +422,9 @@ isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card * card)
return 0;
save_flags(flags);
cli();
- nskb = skb_clone(skb, GFP_ATOMIC);
+ nskb = dev_alloc_skb(skb->len);
if (nskb) {
+ memcpy(skb_put(nskb, len), skb->data, len);
skb_queue_tail(&card->bqueue[channel], nskb);
dev_kfree_skb(skb);
} else
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 784e3b69213e..a60461dee898 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -200,6 +200,7 @@ static mddev_t * mddev_find(int unit)
INIT_LIST_HEAD(&new->disks);
INIT_LIST_HEAD(&new->all_mddevs);
atomic_set(&new->active, 1);
+ blk_queue_make_request(&new->queue, md_fail_request);
goto retry;
}
@@ -1275,6 +1276,39 @@ abort:
return 1;
}
+static struct gendisk *md_probe(dev_t dev, int *part, void *data)
+{
+ static DECLARE_MUTEX(disks_sem);
+ int unit = MINOR(dev);
+ mddev_t *mddev = mddev_find(unit);
+ struct gendisk *disk;
+
+ if (!mddev)
+ return NULL;
+
+ down(&disks_sem);
+ if (disks[unit]) {
+ up(&disks_sem);
+ mddev_put(mddev);
+ return NULL;
+ }
+ disk = alloc_disk(1);
+ if (!disk) {
+ up(&disks_sem);
+ mddev_put(mddev);
+ return NULL;
+ }
+ disk->major = MD_MAJOR;
+ disk->first_minor = mdidx(mddev);
+ sprintf(disk->disk_name, "md%d", mdidx(mddev));
+ disk->fops = &md_fops;
+ disk->private_data = mddev;
+ disk->queue = &mddev->queue;
+ add_disk(disk);
+ disks[mdidx(mddev)] = disk;
+ up(&disks_sem);
+ return NULL;
+}
#define TOO_BIG_CHUNKSIZE KERN_ERR \
"too big chunk_size: %d > %d\n"
@@ -1394,14 +1428,10 @@ static int do_md_run(mddev_t * mddev)
#endif
}
- disk = alloc_disk(1);
+ md_probe(mdidx(mddev), NULL, NULL);
+ disk = disks[mdidx(mddev)];
if (!disk)
return -ENOMEM;
- disk->major = MD_MAJOR;
- disk->first_minor = mdidx(mddev);
- sprintf(disk->disk_name, "md%d", mdidx(mddev));
- disk->fops = &md_fops;
-
mddev->pers = pers[pnum];
blk_queue_make_request(&mddev->queue, mddev->pers->make_request);
@@ -1417,7 +1447,6 @@ static int do_md_run(mddev_t * mddev)
if (err) {
printk(KERN_ERR "md: pers->run() failed ...\n");
mddev->pers = NULL;
- put_disk(disk);
return -EINVAL;
}
@@ -1430,9 +1459,6 @@ static int do_md_run(mddev_t * mddev)
md_update_sb(mddev);
md_recover_arrays();
set_capacity(disk, md_size[mdidx(mddev)]<<1);
- add_disk(disk);
- disks[mdidx(mddev)] = disk;
-
return (0);
}
@@ -1543,13 +1569,8 @@ static int do_md_stop(mddev_t * mddev, int ro)
md_size[mdidx(mddev)] = 0;
disk = disks[mdidx(mddev)];
- disks[mdidx(mddev)] = NULL;
-
- if (disk) {
- del_gendisk(disk);
- put_disk(disk);
- }
-
+ if (disk)
+ set_capacity(disk, 0);
} else
printk(KERN_INFO "md: md%d switched to read-only mode.\n", mdidx(mddev));
err = 0;
@@ -3083,18 +3104,6 @@ static void md_geninit(void)
#endif
}
-request_queue_t * md_queue_proc(kdev_t dev)
-{
- mddev_t *mddev = mddev_find(minor(dev));
- request_queue_t *q = BLK_DEFAULT_QUEUE(MAJOR_NR);
- if (mddev) {
- if (mddev->pers)
- q = &mddev->queue;
- mddev_put(mddev);
- }
- return q;
-}
-
int __init md_init(void)
{
static char * name = "mdrecoveryd";
@@ -3109,6 +3118,8 @@ int __init md_init(void)
return (-1);
}
devfs_handle = devfs_mk_dir (NULL, "md", NULL);
+ blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
+ md_probe, NULL, NULL);
for (minor=0; minor < MAX_MD_DEVS; ++minor) {
char devname[128];
sprintf (devname, "%u", minor);
@@ -3117,10 +3128,6 @@ int __init md_init(void)
S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL);
}
- /* all requests on an uninitialised device get failed... */
- blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), md_fail_request);
- blk_dev[MAJOR_NR].queue = md_queue_proc;
-
md_recovery_thread = md_register_thread(md_do_recovery, NULL, name);
if (!md_recovery_thread)
printk(KERN_ALERT
@@ -3447,6 +3454,8 @@ int init_module(void)
void cleanup_module(void)
{
+ int i;
+ blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS);
md_unregister_thread(md_recovery_thread);
devfs_unregister(devfs_handle);
@@ -3456,8 +3465,16 @@ void cleanup_module(void)
#ifdef CONFIG_PROC_FS
remove_proc_entry("mdstat", NULL);
#endif
-
- blk_dev[MAJOR_NR].queue = NULL;
+ for (i = 0; i < MAX_MD_DEVS; i++) {
+ struct gendisk *disk = disks[i];
+ mddev_t *mddev;
+ if (!disks[i])
+ continue;
+ mddev = disk->private_data;
+ del_gendisk(disk);
+ put_disk(disk);
+ mddev_put(mddev);
+ }
}
#endif
diff --git a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h
index a6e7ecdcb4e1..99575438c027 100644
--- a/drivers/message/fusion/linux_compat.h
+++ b/drivers/message/fusion/linux_compat.h
@@ -75,11 +75,11 @@ typedef int (*__init_module_func_t)(void);
typedef void (*__cleanup_module_func_t)(void);
#define module_init(x) \
int init_module(void) __attribute__((alias(#x))); \
- extern inline __init_module_func_t __init_module_inline(void) \
+ static inline __init_module_func_t __init_module_inline(void) \
{ return x; }
#define module_exit(x) \
void cleanup_module(void) __attribute__((alias(#x))); \
- extern inline __cleanup_module_func_t __cleanup_module_inline(void) \
+ static inline __cleanup_module_func_t __cleanup_module_inline(void) \
{ return x; }
#else
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index b6f8af6193f1..08731b7c5977 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -225,7 +225,6 @@ static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int
static void i2ob_end_request(struct request *);
static void i2ob_request(request_queue_t *);
static int i2ob_init_iop(unsigned int);
-static request_queue_t* i2ob_get_queue(kdev_t);
static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
static int i2ob_evt(void *);
@@ -1284,14 +1283,6 @@ static int i2ob_init_iop(unsigned int unit)
}
/*
- * Get the request queue for the given device.
- */
-static request_queue_t* i2ob_get_queue(kdev_t dev)
-{
- return I2O_UNIT(dev).req_queue;
-}
-
-/*
* Probe the I2O subsytem for block class devices
*/
static void i2ob_scan(int bios)
@@ -1551,10 +1542,9 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
/*
* Have we seen a media change ?
*/
-static int i2ob_media_change(kdev_t dev)
+static int i2ob_media_change(struct gendisk *disk)
{
- int i=minor(dev);
- i>>=4;
+ int i = (int)disk->private_data;
if(i2ob_media_change_flag[i])
{
i2ob_media_change_flag[i]=0;
@@ -1563,11 +1553,11 @@ static int i2ob_media_change(kdev_t dev)
return 0;
}
-static int i2ob_revalidate(kdev_t dev)
+static int i2ob_revalidate(struct gendisk *disk)
{
- int minor = minor(dev) & ~15;
- return i2ob_install_device(i2ob_dev[minor].controller, i2ob_dev[minor].i2odev,
- minor);
+ int i = (int)disk->private_data;
+ return i2ob_install_device(i2ob_dev[i<<4].controller,
+ i2ob_dev[i<<4].i2odev, i<<4);
}
/*
@@ -1616,12 +1606,12 @@ static void i2ob_reboot_event(void)
static struct block_device_operations i2ob_fops =
{
- owner: THIS_MODULE,
- open: i2ob_open,
- release: i2ob_release,
- ioctl: i2ob_ioctl,
- check_media_change: i2ob_media_change,
- revalidate: i2ob_revalidate,
+ .owner = THIS_MODULE,
+ .open = i2ob_open,
+ .release = i2ob_release,
+ .ioctl = i2ob_ioctl,
+ .media_changed = i2ob_media_change,
+ .revalidate_disk= i2ob_revalidate,
};
/*
@@ -1650,6 +1640,9 @@ static int i2o_block_init(void)
struct gendisk *disk = alloc_disk(16);
if (!disk)
goto oom;
+ /* to be cleaned up */
+ disk->private_data = (void*)i;
+ disk->queue = i2ob_dev[i<<4].req_queue;
i2o_disk[i] = disk;
}
#ifdef MODULE
@@ -1660,8 +1653,6 @@ static int i2o_block_init(void)
* Now fill in the boiler plate
*/
- blk_dev[MAJOR_NR].queue = i2ob_get_queue;
-
for (i = 0; i < MAX_I2OB << 4; i++) {
i2ob_dev[i].refcnt = 0;
i2ob_dev[i].flags = 0;
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index e40e34d3c7d6..d3e54f36e118 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -175,16 +175,16 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg);
static int ftl_open(struct inode *inode, struct file *file);
static release_t ftl_close(struct inode *inode, struct file *file);
-static int ftl_revalidate(kdev_t dev);
+static int ftl_revalidate(struct gendisk *disk);
static void ftl_erase_callback(struct erase_info *done);
static struct block_device_operations ftl_blk_fops = {
- owner: THIS_MODULE,
- open: ftl_open,
- release: ftl_close,
- ioctl: ftl_ioctl,
- revalidate: ftl_revalidate,
+ .owner = THIS_MODULE,
+ .open = ftl_open,
+ .release = ftl_close,
+ .ioctl = ftl_ioctl,
+ .revalidate_disk= ftl_revalidate,
};
/*======================================================================
@@ -823,61 +823,53 @@ static u_int32_t find_free(partition_t *part)
static int ftl_open(struct inode *inode, struct file *file)
{
- int minor = minor(inode->i_rdev);
- partition_t *partition;
+ partition_t *partition = inode->i_bdev->bd_disk->private_data;
+ if (!partition)
+ return -ENODEV;
- if (minor>>4 >= MAX_MTD_DEVICES)
- return -ENODEV;
-
- partition = myparts[minor>>4];
-
- if (!partition)
- return -ENODEV;
-
- if (partition->state != FTL_FORMATTED)
- return -ENXIO;
+ if (partition->state != FTL_FORMATTED)
+ return -ENXIO;
- if (get_capacity(partition->disk) == 0)
- return -ENXIO;
+ if (get_capacity(partition->disk) == 0)
+ return -ENXIO;
- if (!get_mtd_device(partition->mtd, -1))
- return /* -E'SBUGGEREDOFF */ -ENXIO;
+ if (!get_mtd_device(partition->mtd, -1))
+ return /* -E'SBUGGEREDOFF */ -ENXIO;
- if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) {
- put_mtd_device(partition->mtd);
- return -EROFS;
- }
+ if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) {
+ put_mtd_device(partition->mtd);
+ return -EROFS;
+ }
- DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor);
+ DEBUG(0, "ftl_cs: ftl_open(%s)\n", inode->i_bdev->b_disk->disk_name);
- atomic_inc(&partition->open);
+ atomic_inc(&partition->open);
- return 0;
+ return 0;
}
/*====================================================================*/
static release_t ftl_close(struct inode *inode, struct file *file)
{
- int minor = minor(inode->i_rdev);
- partition_t *part = myparts[minor >> 4];
- int i;
+ partition_t *part = inode->i_bdev->bd_disk->private_data;
+ int i;
- DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor);
+ DEBUG(0, "ftl_cs: ftl_close(%s)\n", inode->i_bdev->b_disk->disk_name);
- /* Wait for any pending erase operations to complete */
- if (part->mtd->sync)
- part->mtd->sync(part->mtd);
+ /* Wait for any pending erase operations to complete */
+ if (part->mtd->sync)
+ part->mtd->sync(part->mtd);
- for (i = 0; i < part->header.NumTransferUnits; i++) {
- if (part->XferInfo[i].state == XFER_ERASED)
- prepare_xfer(part, i);
- }
+ for (i = 0; i < part->header.NumTransferUnits; i++) {
+ if (part->XferInfo[i].state == XFER_ERASED)
+ prepare_xfer(part, i);
+ }
- atomic_dec(&part->open);
+ atomic_dec(&part->open);
- put_mtd_device(part->mtd);
- release_return(0);
+ put_mtd_device(part->mtd);
+ release_return(0);
} /* ftl_close */
@@ -1091,25 +1083,26 @@ static int ftl_write(partition_t *part, caddr_t buffer,
static int ftl_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg)
{
- struct hd_geometry *geo = (struct hd_geometry *)arg;
- int ret = 0, minor = minor(inode->i_rdev);
- partition_t *part= myparts[minor >> 4];
- u_long sect;
-
- if (!part)
- return -ENODEV; /* How? */
-
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo));
- if (ret) return ret;
- /* Sort of arbitrary: round size down to 4K boundary */
- sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
- put_user(1, (char *)&geo->heads);
- put_user(8, (char *)&geo->sectors);
- put_user((sect>>3), (short *)&geo->cylinders);
- put_user(get_start_sect(inode->i_bdev), (u_long *)&geo->start);
- return 0;
+ partition_t *part = inode->i_bdev->bd_disk->private_data;
+ struct hd_geometry *geo = (struct hd_geometry *)arg;
+ int ret = 0;
+ u_long sect;
+
+ if (!part)
+ return -ENODEV; /* How? */
+
+ if (cmd != HDIO_GETGEO)
+ return -EINVAL;
+ ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo));
+ if (ret)
+ return ret;
+ /* Sort of arbitrary: round size down to 4K boundary */
+ sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
+ put_user(1, (char *)&geo->heads);
+ put_user(8, (char *)&geo->sectors);
+ put_user((sect>>3), (short *)&geo->cylinders);
+ put_user(get_start_sect(inode->i_bdev), (u_long *)&geo->start);
+ return 0;
} /* ftl_ioctl */
/*======================================================================
@@ -1118,13 +1111,11 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
======================================================================*/
-static int ftl_revalidate(kdev_t dev)
+static int ftl_revalidate(struct gendisk *disk)
{
- int unit = minor(dev) >> 4;
- partition_t *part = myparts[unit];
+ partition_t *part = disk->private_data;
scan_header(part);
- set_capacity(part->disk,
- le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
+ set_capacity(disk, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
return 0;
}
@@ -1134,50 +1125,48 @@ static int ftl_revalidate(kdev_t dev)
======================================================================*/
-static void do_ftl_request(request_arg_t)
-{
- int ret, minor;
- partition_t *part;
+static struct request_queue ftl_queue;
- do {
- // sti();
- if (blk_queue_empty(QUEUE))
- return;
+static void do_ftl_request(struct request_queue *q)
+{
+ struct request *req;
+ partition_t *part;
+ int ret;
+
+ do {
+ // sti();
+ if (blk_queue_empty(q))
+ return;
+ req = elv_next_request(q);
+ part = req->rq_disk->private_data;
+ if (part) {
+ ret = 0;
+ switch (rq_data_dir(CURRENT)) {
+ case READ:
+ ret = ftl_read(part, req->buffer, req->sector,
+ req->current_nr_sectors);
+ if (ret)
+ printk("ftl_read returned %d\n", ret);
+ break;
+ case WRITE:
+ ret = ftl_write(part, req->buffer, req->sector,
+ req->current_nr_sectors);
+ if (ret)
+ printk("ftl_write returned %d\n", ret);
+ break;
+ default:
+ panic("ftl_cs: unknown block command!\n");
+ }
+ } else {
+ ret = 1;
+ printk("NULL part in ftl_request\n");
+ }
+
+ if (!ret)
+ req->sector += req->current_nr_sectors;
- minor = minor(CURRENT->rq_dev);
-
- part = myparts[minor >> 4];
- if (part) {
- ret = 0;
-
- switch (rq_data_dir(CURRENT)) {
- case READ:
- ret = ftl_read(part, CURRENT->buffer, CURRENT->sector,
- CURRENT->current_nr_sectors);
- if (ret) printk("ftl_read returned %d\n", ret);
- break;
-
- case WRITE:
- ret = ftl_write(part, CURRENT->buffer, CURRENT->sector,
- CURRENT->current_nr_sectors);
- if (ret) printk("ftl_write returned %d\n", ret);
- break;
-
- default:
- panic("ftl_cs: unknown block command!\n");
-
- }
- } else {
- ret = 1;
- printk("NULL part in ftl_request\n");
- }
-
- if (!ret) {
- CURRENT->sector += CURRENT->current_nr_sectors;
- }
-
- end_request(CURRENT, (ret == 0) ? 1 : 0);
- } while (1);
+ end_request(req, (ret == 0) ? 1 : 0);
+ } while (1);
} /* do_ftl_request */
/*====================================================================*/
@@ -1246,6 +1235,8 @@ static void ftl_notify_add(struct mtd_info *mtd)
atomic_set(&partition->open, 0);
myparts[device] = partition;
set_capacity(disk, le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE);
+ disk->private_data = partition;
+ disk->queue = &ftl_queue;
add_disk(disk);
#ifdef PCMCIA_DEBUG
printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n",
@@ -1287,31 +1278,29 @@ static void ftl_notify_remove(struct mtd_info *mtd)
int init_ftl(void)
{
- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
- DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n");
-
- if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
- printk(KERN_NOTICE "ftl_cs: unable to grab major "
- "device number!\n");
- return -EAGAIN;
- }
- blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request, &lock);
- register_mtd_user(&ftl_notifier);
-
- return 0;
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n");
+
+ if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
+ printk(KERN_NOTICE "ftl_cs: unable to grab major "
+ "device number!\n");
+ return -EAGAIN;
+ }
+ blk_init_queue(&ftl_queue, &do_ftl_request, &lock);
+ register_mtd_user(&ftl_notifier);
+ return 0;
}
static void __exit cleanup_ftl(void)
{
- unregister_mtd_user(&ftl_notifier);
- unregister_blkdev(FTL_MAJOR, "ftl");
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR));
+ unregister_mtd_user(&ftl_notifier);
+ unregister_blkdev(FTL_MAJOR, "ftl");
+ blk_cleanup_queue(&ftl_queue);
}
module_init(init_ftl);
module_exit(cleanup_ftl);
-
MODULE_LICENSE("Dual MPL/GPL");
MODULE_AUTHOR("David Hinds <dhinds@sonic.net>");
MODULE_DESCRIPTION("Support code for Flash Translation Layer, used on PCMCIA devices and M-Systems DiskOnChip 1000");
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 47bf73b1fa1d..e0d807c8b065 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -2052,7 +2052,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->ip_summed != CHECKSUM_HW)
vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
else
- vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum);
+ vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum);
if (!skb_shinfo(skb)->nr_frags) {
vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data,
diff --git a/drivers/net/hamradio/soundmodem/Makefile b/drivers/net/hamradio/soundmodem/Makefile
index a3fe3f4e61cd..77de2ca25c87 100644
--- a/drivers/net/hamradio/soundmodem/Makefile
+++ b/drivers/net/hamradio/soundmodem/Makefile
@@ -19,6 +19,12 @@ soundmodem-objs := $(soundmodem-y)
host-progs := gentbl
HOST_LOADLIBES := -lm
+# Files generated that shall be removed upon make clean
+clean-files := sm_tbl_afsk1200.h sm_tbl_afsk2400_7.h \
+ sm_tbl_afsk2400_8.h sm_tbl_afsk2666.h \
+ sm_tbl_psk4800.h sm_tbl_hapn4800.h \
+ sm_tbl_fsk9600.h
+
include $(TOPDIR)/Rules.make
# Dependencies on generates files need to be listed explicitly
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 85b4c3e09348..2071ce5ffa10 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -72,7 +72,7 @@ struct nubus_board* nubus_boards;
Etcetera, etcetera. Hopefully this clears up some confusion over
what the following code actually does. */
-extern inline int not_useful(void *p, int map)
+static inline int not_useful(void *p, int map)
{
unsigned long pv=(unsigned long)p;
pv &= 3;
@@ -148,14 +148,14 @@ static void nubus_move(unsigned char **ptr, int len, int map)
have to expand it from a 24-bit signed number to a 32-bit signed
number. */
-extern inline long nubus_expand32(long foo)
+static inline long nubus_expand32(long foo)
{
if(foo & 0x00800000) /* 24bit negative */
foo |= 0xFF000000;
return foo;
}
-extern inline void *nubus_rom_addr(int slot)
+static inline void *nubus_rom_addr(int slot)
{
/*
* Returns the first byte after the card. We then walk
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 307ea814439a..d26c2e02ef62 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -31,6 +31,9 @@ endif
host-progs := gen-devlist
+# Files generated that shall be removed upon make clean
+clean-files := devlist.h classlist.h
+
include $(TOPDIR)/Rules.make
# Dependencies on generated files need to be listed explicitly
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 040cc588981b..3ef7d9eb6e84 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -141,7 +141,7 @@ pci_register_driver(struct pci_driver *drv)
void
pci_unregister_driver(struct pci_driver *drv)
{
- remove_driver(&drv->driver);
+ driver_unregister(&drv->driver);
}
static struct pci_driver pci_compat_driver = {
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index 9bf1a6c392d4..7afea0c7b3aa 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -297,7 +297,7 @@ static int __init sa1111_drv_pcmcia_init(void)
static void __exit sa1111_drv_pcmcia_exit(void)
{
- remove_driver(&pcmcia_driver.drv);
+ driver_unregister(&pcmcia_driver.drv);
}
module_init(sa1111_drv_pcmcia_init);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 35158ea70aa1..9724e5f269e6 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -170,6 +170,8 @@ STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt);
STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int);
STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
+STATIC int NCR_700_slave_attach(Scsi_Device *SDpnt);
+STATIC void NCR_700_slave_detach(Scsi_Device *SDpnt);
static char *NCR_700_phase[] = {
"",
@@ -280,9 +282,11 @@ NCR_700_detect(Scsi_Host_Template *tpnt,
tpnt->eh_host_reset_handler = NCR_700_host_reset;
tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST;
tpnt->sg_tablesize = NCR_700_SG_SEGMENTS;
- tpnt->cmd_per_lun = NCR_700_MAX_TAGS;
+ tpnt->cmd_per_lun = NCR_700_CMD_PER_LUN;
tpnt->use_clustering = DISABLE_CLUSTERING;
tpnt->proc_info = NCR_700_proc_directory_info;
+ tpnt->slave_attach = NCR_700_slave_attach;
+ tpnt->slave_detach = NCR_700_slave_detach;
tpnt->use_blk_tcq = 1;
tpnt->highmem_io = 1;
@@ -891,8 +895,8 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
printk(KERN_WARNING "scsi%d (%d:%d) Rejected first tag queue attempt, turning off tag queueing\n", host->host_no, pun, lun);
NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);
hostdata->tag_negotiated &= ~(1<<SCp->target);
- SCp->device->tagged_queue = 0;
SCp->device->tagged_supported = 0;
+ scsi_deactivate_tcq(SCp->device);
} else {
printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n",
host->host_no, pun, lun,
@@ -1719,13 +1723,11 @@ NCR_700_proc_directory_info(char *proc_buf, char **startp,
{
static char buf[4096]; /* 1 page should be sufficient */
int len = 0;
- struct Scsi_Host *host = scsi_hostlist;
+ struct Scsi_Host *host;
struct NCR_700_Host_Parameters *hostdata;
Scsi_Device *SDp;
- while(host != NULL && host->host_no != host_no)
- host = host->next;
-
+ host = scsi_host_hn_get(host_no);
if(host == NULL)
return 0;
@@ -1739,7 +1741,7 @@ NCR_700_proc_directory_info(char *proc_buf, char **startp,
Target Depth Active Next Tag\n\
====== ===== ====== ========\n");
for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) {
- len += sprintf(&buf[len]," %2d:%2d %4d %4d %4d\n", SDp->id, SDp->lun, SDp->queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
+ len += sprintf(&buf[len]," %2d:%2d %4d %4d %4d\n", SDp->id, SDp->lun, SDp->current_queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
}
if((len -= offset) <= 0)
return 0;
@@ -1776,13 +1778,13 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n",
SCp->host->host_no, SCp->target, SCp->lun,
NCR_700_get_depth(SCp->device)));
- return 1;
+ return SCSI_MLQUEUE_DEVICE_BUSY;
}
if(NCR_700_get_depth(SCp->device) >= NCR_700_MAX_TAGS) {
DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n",
SCp->host->host_no, SCp->target, SCp->lun,
NCR_700_get_depth(SCp->device)));
- return 1;
+ return SCSI_MLQUEUE_DEVICE_BUSY;
}
NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);
@@ -1998,6 +2000,25 @@ NCR_700_host_reset(Scsi_Cmnd * SCp)
return SUCCESS;
}
+STATIC int
+NCR_700_slave_attach(Scsi_Device *SDp)
+{
+ /* to do here: allocate memory; build a queue_full list */
+ if(SDp->tagged_supported) {
+ /* do TCQ stuff here */
+ } else {
+ /* initialise to default depth */
+ scsi_adjust_queue_depth(SDp, 0, SDp->host->cmd_per_lun);
+ }
+ return 0;
+}
+
+STATIC void
+NCR_700_slave_detach(Scsi_Device *SDp)
+{
+ /* to do here: deallocate memory */
+}
+
EXPORT_SYMBOL(NCR_700_detect);
EXPORT_SYMBOL(NCR_700_release);
EXPORT_SYMBOL(NCR_700_intr);
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index ccb675372935..f01bdb2e1321 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -30,6 +30,11 @@
/* Alter this with care: too many tags won't give the elevator a chance to
* work; too few will cause the device to operate less efficiently */
#define NCR_700_MAX_TAGS 16
+/* This is the default number of commands per LUN in the untagged case.
+ * two is a good value because it means we can have one command active and
+ * one command fully prepared and waiting
+ */
+#define NCR_700_CMD_PER_LUN 2
/* magic byte identifying an internally generated REQUEST_SENSE command */
#define NCR_700_INTERNAL_SENSE_MAGIC 0x42
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index b9f1779ff00f..1edb859c1b50 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -132,6 +132,10 @@ a100u2w-objs := inia100.o i60uscsi.o
cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \
cpqfcTSworker.o cpqfcTStrigger.o
+# Files generated that shall be removed upon make clean
+clean-files := 53c8xx_d.h 53c7xx_d.h sim710_d.h 53c700_d.h \
+ 53c8xx_u.h 53c7xx_u.h sim710_u.h 53c700_u.h
+
include $(TOPDIR)/Rules.make
$(obj)/53c7,8xx.o: $(obj)/53c8xx_d.h $(obj)/53c8xx_u.h
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index a83d865e925d..f880e78f0454 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -289,7 +289,7 @@ static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
#endif
#ifdef DEBUG_ESP_CMDS
-extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
+inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
unchar cmd)
{
esp->espcmdlog[esp->espcmdent] = cmd;
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 5afa780d5593..bfcab7bbabf7 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -1060,7 +1060,8 @@ int aac_scsi_cmd(Scsi_Cmnd * scsicmd)
*/
spin_unlock_irq(scsicmd->host->host_lock);
- fsa_dev_ptr->devno[cid] = DEVICE_NR(scsicmd->sc_request->sr_request->rq_dev);
+ fsa_dev_ptr->devno[cid] =
+ DEVICE_NR(scsicmd->request->rq_dev);
ret = aac_read(scsicmd, cid);
spin_lock_irq(scsicmd->host->host_lock);
return ret;
diff --git a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile
index d92ba2bdc047..ea95d8a13309 100644
--- a/drivers/scsi/aic7xxx/Makefile
+++ b/drivers/scsi/aic7xxx/Makefile
@@ -20,6 +20,13 @@ endif
#EXTRA_CFLAGS += -g
+# Files generated that shall be removed upon make clean
+clean-files := aic7xxx_seq.h aic7xxx_reg.h
+
+# Command to be executed upon make clean
+# Note: Assignment without ':' to force late evaluation of $(src)
+clean-rule = @$(MAKE) -C $(src)/aicasm clean
+
include $(TOPDIR)/Rules.make
# Dependencies for generated files need to be listed explicitly
@@ -30,12 +37,13 @@ $(addprefix $(obj)/,$(aic7xxx-objs)): $(obj)/aic7xxx_reg.h
ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
-$(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h: $(src)/aic7xxx.seq \
- $(src)/aic7xxx.reg \
- $(obj)/aicasm/aicasm
+$(obj)/aic7xxx_seq.h: $(src)/aic7xxx.seq $(src)/aic7xxx.reg \
+ $(obj)/aicasm/aicasm
$(obj)/aicasm/aicasm -I. -r $(obj)/aic7xxx_reg.h \
-o $(obj)/aic7xxx_seq.h $(src)/aic7xxx.seq
+$(obj)/aic7xxx_reg.h: $(obj)/aix7xxx_seq.h
+
$(obj)/aicasm/aicasm: $(src)/aicasm/*.[chyl]
$(MAKE) -C $(src)/aicasm
diff --git a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
index de53201f4df1..27ba7345c53a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
@@ -63,7 +63,6 @@ int ahc_linux_abort(Scsi_Cmnd *);
* to do with card config are filled in after the card is detected.
*/
#define AIC7XXX { \
- next: NULL, \
module: NULL, \
proc_dir: NULL, \
proc_info: ahc_linux_proc_info, \
diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
index 790402e0dd68..39acae36dcac 100644
--- a/drivers/scsi/aic7xxx/aicasm/Makefile
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile
@@ -43,7 +43,7 @@ aicdb.h:
fi
clean:
- rm -f $(CLEANFILES) $(PROG)
+ @rm -f $(CLEANFILES) $(PROG)
y.tab.h aicasm_gram.c: aicasm_gram.y
$(YACC) $(YFLAGS) aicasm_gram.y
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h
index 4d9ba148d0d5..016a1b2e2ee6 100644
--- a/drivers/scsi/aic7xxx_old/aic7xxx.h
+++ b/drivers/scsi/aic7xxx_old/aic7xxx.h
@@ -30,14 +30,10 @@
* to do with card config are filled in after the card is detected.
*/
#define AIC7XXX { \
- next: NULL, \
- module: NULL, \
proc_info: aic7xxx_proc_info, \
- name: NULL, \
detect: aic7xxx_detect, \
release: aic7xxx_release, \
info: aic7xxx_info, \
- command: NULL, \
queuecommand: aic7xxx_queue, \
eh_strategy_handler: NULL, \
eh_abort_handler: NULL, \
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index 03954b23e494..8c002c0ee76b 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -938,9 +938,7 @@ int cpqfcTS_proc_info (char *buffer, char **start, off_t offset, int length,
char buf[81];
// Search the Scsi host list for our controller
- for (host=scsi_hostlist; host; host=host->next)
- if (host->host_no == hostno)
- break;
+ host = scsi_host_hn_get(hostno);
if (!host) return -ESRCH;
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 6634124b45b4..921f4369a3e9 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -378,7 +378,7 @@ static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
#endif
#ifdef DEBUG_ESP_CMDS
-extern inline void esp_cmd(struct esp *esp, u8 cmd)
+static inline void esp_cmd(struct esp *esp, u8 cmd)
{
esp->espcmdlog[esp->espcmdent] = cmd;
esp->espcmdent = (esp->espcmdent + 1) & 31;
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
index 77192c05310f..12c127b0b4cd 100644
--- a/drivers/scsi/fcal.c
+++ b/drivers/scsi/fcal.c
@@ -213,9 +213,7 @@ int fcal_proc_info (char *buffer, char **start, off_t offset, int length, int ho
char *pos = buffer;
int i, j;
- for (host=scsi_hostlist; host; host=host->next)
- if (host->host_no == hostno)
- break;
+ host = scsi_host_hn_get(hostno);
if (!host) return -ESRCH;
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 520f31dfbf82..b3d725b16add 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -15,12 +15,15 @@
* Updated to reflect the new initialization scheme for the higher
* level of scsi drivers (sd/sr/st)
* September 17, 2000 Torben Mathiasen <tmm@image.dk>
+ *
+ * Restructured scsi_host lists and associated functions.
+ * September 04, 2002 Mike Anderson (andmike@us.ibm.com)
*/
/*
* This file contains the medium level SCSI
- * host interface initialization, as well as the scsi_hosts array of SCSI
+ * host interface initialization, as well as the scsi_hosts list of SCSI
* hosts currently present in the system.
*/
@@ -31,232 +34,711 @@
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
+#include <asm/dma.h>
#include "scsi.h"
#include "hosts.h"
-/*
-static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v 1.20 1996/12/12 19:18:32 davem Exp $";
-*/
+LIST_HEAD(scsi_host_tmpl_list);
+LIST_HEAD(scsi_host_hn_list);
-/*
- * The scsi host entries should be in the order you wish the
- * cards to be detected. A driver may appear more than once IFF
- * it can deal with being detected (and therefore initialized)
- * with more than one simultaneous host number, can handle being
- * reentrant, etc.
+LIST_HEAD(scsi_host_list);
+spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
+
+struct Scsi_Device_Template * scsi_devicelist;
+
+static int scsi_host_next_hn; /* host_no for next new host */
+static int scsi_hosts_registered; /* cnt of registered scsi hosts */
+
+/**
+ * scsi_tp_for_each_host - call function for each scsi host off a template
+ * @shost_tp: a pointer to a scsi host template
+ * @callback: a pointer to callback function
*
- * They may appear in any order, as each SCSI host is told which host
- * number it is during detection.
- */
+ * Return value:
+ * 0 on Success / 1 on Failure
+ **/
+int scsi_tp_for_each_host(Scsi_Host_Template *shost_tp, int
+ (*callback)(struct Scsi_Host *shost))
+{
+ struct list_head *lh, *lh_sf;
+ struct Scsi_Host *shost;
-/*
- * When figure is run, we don't want to link to any object code. Since
- * the macro for each host will contain function pointers, we cannot
- * use it and instead must use a "blank" that does no such
- * idiocy.
- */
+ spin_lock(&scsi_host_list_lock);
-Scsi_Host_Template * scsi_hosts;
+ list_for_each_safe(lh, lh_sf, &scsi_host_list) {
+ shost = list_entry(lh, struct Scsi_Host, sh_list);
+ if (shost->hostt == shost_tp) {
+ spin_unlock(&scsi_host_list_lock);
+ callback(shost);
+ spin_lock(&scsi_host_list_lock);
+ }
+ }
+ spin_unlock(&scsi_host_list_lock);
-/*
- * Our semaphores and timeout counters, where size depends on
- * MAX_SCSI_HOSTS here.
- */
+ return 0;
+}
-Scsi_Host_Name * scsi_host_no_list;
-struct Scsi_Host * scsi_hostlist;
-struct Scsi_Device_Template * scsi_devicelist;
+/**
+ * scsi_host_generic_release - default release function for hosts
+ * @shost:
+ *
+ * Description:
+ * This is the default case for the release function. It should do
+ * the right thing for most correctly written host adapters.
+ **/
+static void scsi_host_generic_release(struct Scsi_Host *shost)
+{
+ if (shost->irq)
+ free_irq(shost->irq, NULL);
+ if (shost->dma_channel != 0xff)
+ free_dma(shost->dma_channel);
+ if (shost->io_port && shost->n_io_port)
+ release_region(shost->io_port, shost->n_io_port);
+}
+
+/**
+ * scsi_host_chk_and_release - check a scsi host for release and release
+ * @shost: a pointer to a scsi host to release
+ *
+ * Return value:
+ * 0 on Success / 1 on Failure
+ **/
+int scsi_host_chk_and_release(struct Scsi_Host *shost)
+{
+ int pcount;
+ Scsi_Device *sdev;
+ struct Scsi_Device_Template *sdev_tp;
+ Scsi_Cmnd *scmd;
+
+ /*
+ * Current policy is all shosts go away on unregister.
+ */
+ if (shost->hostt->module && GET_USE_COUNT(shost->hostt->module))
+ return 1;
+
+ /*
+ * FIXME Do ref counting. We force all of the devices offline to
+ * help prevent race conditions where other hosts/processors could
+ * try and get in and queue a command.
+ */
+ for (sdev = shost->host_queue; sdev; sdev = sdev->next)
+ sdev->online = FALSE;
+
+ for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+ /*
+ * Loop over all of the commands associated with the
+ * device. If any of them are busy, then set the state
+ * back to inactive and bail.
+ */
+ for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+ if (scmd->request && scmd->request->rq_status !=
+ RQ_INACTIVE) {
+ printk(KERN_ERR "SCSI device not inactive"
+ "- rq_status=%d, target=%d, pid=%ld,"
+ "state=%d, owner=%d.\n",
+ scmd->request->rq_status,
+ scmd->target, scmd->pid,
+ scmd->state, scmd->owner);
+ for (sdev = shost->host_queue; sdev;
+ sdev = sdev->next) {
+ for (scmd = sdev->device_queue; scmd;
+ scmd = scmd->next)
+ if (scmd->request->rq_status ==
+ RQ_SCSI_DISCONNECTING)
+ scmd->request->rq_status = RQ_INACTIVE;
+ }
+ printk(KERN_ERR "Device busy???\n");
+ return 1;
+ }
+ /*
+ * No, this device is really free. Mark it as such, and
+ * continue on.
+ */
+ scmd->state = SCSI_STATE_DISCONNECTING;
+ if (scmd->request)
+ scmd->request->rq_status =
+ RQ_SCSI_DISCONNECTING; /* Mark as
+ busy */
+ }
+ }
-int max_scsi_hosts;
-int next_scsi_host;
-
-void
-scsi_unregister(struct Scsi_Host * sh){
- struct Scsi_Host * shpnt;
- Scsi_Host_Name *shn;
-
- if(scsi_hostlist == sh)
- scsi_hostlist = sh->next;
- else {
- shpnt = scsi_hostlist;
- while(shpnt->next != sh) shpnt = shpnt->next;
- shpnt->next = shpnt->next->next;
- }
-
- /*
- * We have to unregister the host from the scsi_host_no_list as well.
- * Decide by the host_no not by the name because most host drivers are
- * able to handle more than one adapters from the same kind (or family).
- */
- for ( shn=scsi_host_no_list; shn && (sh->host_no != shn->host_no);
- shn=shn->next);
- if (shn) shn->host_registered = 0;
- /* else {} : This should not happen, we should panic here... */
-
- /* If we are removing the last host registered, it is safe to reuse
- * its host number (this avoids "holes" at boot time) (DB)
- * It is also safe to reuse those of numbers directly below which have
- * been released earlier (to avoid some holes in numbering).
- */
- if(sh->host_no == max_scsi_hosts - 1) {
- while(--max_scsi_hosts >= next_scsi_host) {
- shpnt = scsi_hostlist;
- while(shpnt && shpnt->host_no != max_scsi_hosts - 1)
- shpnt = shpnt->next;
- if(shpnt)
- break;
+ /*
+ * Next we detach the high level drivers from the Scsi_Device
+ * structures
+ */
+ for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+ for (sdev_tp = scsi_devicelist; sdev_tp;
+ sdev_tp = sdev_tp->next)
+ if (sdev_tp->detach)
+ (*sdev_tp->detach) (sdev);
+
+ /* If something still attached, punt */
+ if (sdev->attached) {
+ printk(KERN_ERR "Attached usage count = %d\n",
+ sdev->attached);
+ return 1;
+ }
+
+ if (shost->hostt->slave_detach)
+ (*shost->hostt->slave_detach) (sdev);
+
+ devfs_unregister(sdev->de);
+ device_unregister(&sdev->sdev_driverfs_dev);
+ }
+
+ /* Next we free up the Scsi_Cmnd structures for this host */
+
+ for (sdev = shost->host_queue; sdev;
+ sdev = shost->host_queue) {
+ scsi_release_commandblocks(sdev);
+ blk_cleanup_queue(&sdev->request_queue);
+ /* Next free up the Scsi_Device structures for this host */
+ shost->host_queue = sdev->next;
+ if (sdev->inquiry)
+ kfree(sdev->inquiry);
+ kfree(sdev);
+ }
+
+ /* Remove the instance of the individual hosts */
+ pcount = scsi_hosts_registered;
+ if (shost->hostt->release)
+ (*shost->hostt->release) (shost);
+ else {
+ scsi_host_generic_release(shost);
}
- }
- next_scsi_host--;
- kfree((char *) sh);
+
+ if (pcount == scsi_hosts_registered)
+ scsi_unregister(shost);
+
+ return 0;
}
-/* We call this when we come across a new host adapter. We only do this
- * once we are 100% sure that we want to use this host adapter - it is a
- * pain to reverse this, so we try to avoid it
- */
+/**
+ * scsi_unregister - unregister a scsi host
+ * @shost: scsi host to be unregistered
+ **/
+void scsi_unregister(struct Scsi_Host *shost)
+{
+ struct list_head *lh;
+ Scsi_Host_Name *shost_name;
+
+ /* Remove shost from scsi_host_list */
+ spin_lock(&scsi_host_list_lock);
+ list_del(&shost->sh_list);
+ spin_unlock(&scsi_host_list_lock);
+
+ /* Unregister from scsi_host_hn_list */
+ list_for_each(lh, &scsi_host_hn_list) {
+ shost_name = list_entry(lh, Scsi_Host_Name, shn_list);
+ if (shost->host_no == shost_name->host_no)
+ shost_name->host_registered = 0;
+ }
+
+ /*
+ * Next, kill the kernel error recovery thread for this host.
+ */
+ if (shost->ehandler) {
+ DECLARE_MUTEX_LOCKED(sem);
+ shost->eh_notify = &sem;
+ send_sig(SIGHUP, shost->ehandler, 1);
+ down(&sem);
+ shost->eh_notify = NULL;
+ }
+
+ scsi_hosts_registered--;
+ shost->hostt->present--;
+
+ /* Cleanup proc and driverfs */
+#ifdef CONFIG_PROC_FS
+ scsi_proc_host_rm(shost);
+ if (!shost->hostt->present)
+ remove_proc_entry(shost->hostt->proc_name, proc_scsi);
+#endif
+ device_unregister(&shost->host_driverfs_dev);
+
+ kfree(shost);
+}
+
+/**
+ * scsi_host_hn_add - allocate and add new Scsi_Host_Name
+ * @name: String to store in name field
+ *
+ * Return value:
+ * Pointer to a new Scsi_Host_Name
+ **/
+Scsi_Host_Name *scsi_host_hn_add(char *name)
+{
+ Scsi_Host_Name *shost_name;
+ int len;
+
+ len = strlen(name);
+ shost_name = kmalloc(sizeof(*shost_name), GFP_KERNEL);
+ if (!shost_name) {
+ printk(KERN_ERR "%s: out of memory at line %d.\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ shost_name->name = kmalloc(len + 1, GFP_KERNEL);
+ if (!shost_name->name) {
+ kfree(shost_name);
+ printk(KERN_ERR "%s: out of memory at line %d.\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ if (len)
+ strncpy(shost_name->name, name, len);
+ shost_name->name[len] = 0;
+ shost_name->host_no = scsi_host_next_hn++;
+ shost_name->host_registered = 0;
+ list_add_tail(&shost_name->shn_list, &scsi_host_hn_list);
+
+ return shost_name;
+}
+
+/**
+ * scsi_register - register a scsi host adapter instance.
+ * @shost_tp: pointer to scsi host template
+ * @xtr_bytes: extra bytes to allocate for driver
+ *
+ * Note:
+ * We call this when we come across a new host adapter. We only do
+ * this once we are 100% sure that we want to use this host adapter -
+ * it is a pain to reverse this, so we try to avoid it
+ *
+ * Return value:
+ * Pointer to a new Scsi_Host
+ **/
extern int blk_nohighio;
-struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
+struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
{
- struct Scsi_Host * retval, *shpnt, *o_shp;
- Scsi_Host_Name *shn, *shn2;
- int flag_new = 1;
- const char * hname;
- size_t hname_len;
- retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j,
- (tpnt->unchecked_isa_dma && j ?
- GFP_DMA : 0) | GFP_ATOMIC);
- if(retval == NULL)
- {
- printk("scsi: out of memory in scsi_register.\n");
- return NULL;
- }
-
- memset(retval, 0, sizeof(struct Scsi_Host) + j);
-
- /* trying to find a reserved entry (host_no) */
- hname = (tpnt->proc_name) ? tpnt->proc_name : "";
- hname_len = strlen(hname);
- for (shn = scsi_host_no_list;shn;shn = shn->next) {
- if (!(shn->host_registered) &&
- (hname_len > 0) && (0 == strncmp(hname, shn->name, hname_len))) {
- flag_new = 0;
- retval->host_no = shn->host_no;
- shn->host_registered = 1;
- break;
+ struct Scsi_Host *shost, *shost_scr;
+ Scsi_Host_Name *shost_name = NULL;
+ Scsi_Host_Name *shn = NULL;
+ char *hname;
+ size_t hname_len;
+ struct list_head *lh;
+ int gfp_mask;
+ DECLARE_MUTEX_LOCKED(sem);
+
+ gfp_mask = GFP_KERNEL;
+ if (shost_tp->unchecked_isa_dma && xtr_bytes)
+ gfp_mask |= __GFP_DMA;
+
+ shost = kmalloc(sizeof(struct Scsi_Host) + xtr_bytes, gfp_mask);
+ if (!shost) {
+ printk(KERN_ERR "%s: out of memory.\n", __FUNCTION__);
+ return NULL;
}
- }
- spin_lock_init(&retval->default_lock);
- scsi_assign_lock(retval, &retval->default_lock);
- atomic_set(&retval->host_active,0);
- retval->host_busy = 0;
- retval->host_failed = 0;
- if (flag_new) {
- shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC);
- if (!shn) {
- kfree(retval);
- printk(KERN_ERR "scsi: out of memory(2) in scsi_register.\n");
- return NULL;
- }
- shn->name = kmalloc(hname_len + 1, GFP_ATOMIC);
- if (hname_len > 0)
- strncpy(shn->name, hname, hname_len);
- shn->name[hname_len] = 0;
- shn->host_no = max_scsi_hosts++;
- shn->host_registered = 1;
- shn->next = NULL;
- if (scsi_host_no_list) {
- for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next)
- ;
- shn2->next = shn;
+
+ memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes);
+
+ /*
+ * Determine host number. Check reserved first before allocating
+ * new one
+ */
+ hname = (shost_tp->proc_name) ? shost_tp->proc_name : "";
+ hname_len = strlen(hname);
+
+ if (hname_len)
+ list_for_each(lh, &scsi_host_hn_list) {
+ shn = list_entry(lh, Scsi_Host_Name, shn_list);
+ if (!(shn->host_registered) &&
+ !strncmp(hname, shn->name, hname_len)) {
+ shost_name = shn;
+ break;
+ }
+ }
+
+ if (!shost_name) {
+ shost_name = scsi_host_hn_add(hname);
+ if (!shost_name) {
+ kfree(shost);
+ return NULL;
+ }
}
- else
- scsi_host_no_list = shn;
- retval->host_no = shn->host_no;
- }
- next_scsi_host++;
- retval->host_queue = NULL;
- init_waitqueue_head(&retval->host_wait);
- retval->resetting = 0;
- retval->last_reset = 0;
- retval->irq = 0;
- retval->dma_channel = 0xff;
-
- /* These three are default values which can be overridden */
- retval->max_channel = 0;
- retval->max_id = 8;
- retval->max_lun = 8;
-
- /*
- * All drivers right now should be able to handle 12 byte commands.
- * Every so often there are requests for 16 byte commands, but individual
- * low-level drivers need to certify that they actually do something
- * sensible with such commands.
- */
- retval->max_cmd_len = 12;
-
- retval->unique_id = 0;
- retval->io_port = 0;
- retval->hostt = tpnt;
- retval->next = NULL;
- retval->in_recovery = 0;
- retval->ehandler = NULL; /* Initial value until the thing starts up. */
- retval->eh_notify = NULL; /* Who we notify when we exit. */
-
- retval->max_host_blocked = tpnt->max_host_blocked ? tpnt->max_host_blocked : SCSI_DEFAULT_HOST_BLOCKED;
-
- retval->host_blocked = 0;
- retval->host_self_blocked = FALSE;
+
+ shost->host_no = shost_name->host_no;
+ shost_name->host_registered = 1;
+ scsi_hosts_registered++;
+
+ spin_lock_init(&shost->default_lock);
+ scsi_assign_lock(shost, &shost->default_lock);
+ atomic_set(&shost->host_active,0);
+
+ init_waitqueue_head(&shost->host_wait);
+ shost->dma_channel = 0xff;
+
+ /* These three are default values which can be overridden */
+ shost->max_channel = 0;
+ shost->max_id = 8;
+ shost->max_lun = 8;
+
+ /*
+ * All drivers right now should be able to handle 12 byte
+ * commands. Every so often there are requests for 16 byte
+ * commands, but individual low-level drivers need to certify that
+ * they actually do something sensible with such commands.
+ */
+ shost->max_cmd_len = 12;
+ shost->hostt = shost_tp;
+ shost->host_blocked = FALSE;
+ shost->host_self_blocked = FALSE;
#ifdef DEBUG
- printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j);
+ printk("%s: %x %x: %d\n", __FUNCTION_ (int)shost,
+ (int)shost->hostt, xtr_bytes);
#endif
- /* The next six are the default values which can be overridden
- * if need be */
- retval->this_id = tpnt->this_id;
- retval->can_queue = tpnt->can_queue;
- retval->sg_tablesize = tpnt->sg_tablesize;
- retval->cmd_per_lun = tpnt->cmd_per_lun;
- retval->unchecked_isa_dma = tpnt->unchecked_isa_dma;
- retval->use_clustering = tpnt->use_clustering;
- if (!blk_nohighio)
- retval->highmem_io = tpnt->highmem_io;
-
- retval->max_sectors = tpnt->max_sectors;
- retval->use_blk_tcq = tpnt->use_blk_tcq;
-
- if(!scsi_hostlist)
- scsi_hostlist = retval;
- else {
- shpnt = scsi_hostlist;
- if (retval->host_no < shpnt->host_no) {
- retval->next = shpnt;
- wmb(); /* want all to see these writes in this order */
- scsi_hostlist = retval;
+ /*
+ * The next six are the default values which can be overridden if
+ * need be
+ */
+ shost->this_id = shost_tp->this_id;
+ shost->can_queue = shost_tp->can_queue;
+ shost->sg_tablesize = shost_tp->sg_tablesize;
+ shost->cmd_per_lun = shost_tp->cmd_per_lun;
+ shost->unchecked_isa_dma = shost_tp->unchecked_isa_dma;
+ shost->use_clustering = shost_tp->use_clustering;
+ if (!blk_nohighio)
+ shost->highmem_io = shost_tp->highmem_io;
+
+ shost->max_sectors = shost_tp->max_sectors;
+ shost->use_blk_tcq = shost_tp->use_blk_tcq;
+
+ spin_lock(&scsi_host_list_lock);
+ /*
+ * FIXME When device naming is complete remove this step that
+ * orders the scsi_host_list by host number and just do a
+ * list_add_tail.
+ */
+ list_for_each(lh, &scsi_host_list) {
+ shost_scr = list_entry(lh, struct Scsi_Host, sh_list);
+ if (shost->host_no < shost_scr->host_no) {
+ __list_add(&shost->sh_list, shost_scr->sh_list.prev,
+ &shost_scr->sh_list);
+ goto found;
+ }
}
- else {
- for (o_shp = shpnt, shpnt = shpnt->next; shpnt;
- o_shp = shpnt, shpnt = shpnt->next) {
- if (retval->host_no < shpnt->host_no) {
- retval->next = shpnt;
- wmb();
- o_shp->next = retval;
- break;
+ list_add_tail(&shost->sh_list, &scsi_host_list);
+found:
+ spin_unlock(&scsi_host_list_lock);
+
+#ifdef CONFIG_PROC_FS
+ /* Add the new driver to /proc/scsi if not already there */
+ if (!shost_tp->proc_dir)
+ scsi_proc_host_mkdir(shost_tp);
+ scsi_proc_host_add(shost);
+#endif
+
+ strncpy(shost->host_driverfs_dev.name, shost_tp->proc_name,
+ DEVICE_NAME_SIZE-1);
+ sprintf(shost->host_driverfs_dev.bus_id, "scsi%d",
+ shost->host_no);
+
+ shost->eh_notify = &sem;
+ kernel_thread((int (*)(void *)) scsi_error_handler, (void *) shost, 0);
+ /*
+ * Now wait for the kernel error thread to initialize itself
+ * as it might be needed when we scan the bus.
+ */
+ down(&sem);
+ shost->eh_notify = NULL;
+
+ shost->hostt->present++;
+
+ return shost;
+}
+
+
+/**
+ * scsi_register_host - register a low level host driver
+ * @shost_tp: pointer to a scsi host driver template
+ *
+ * Return value:
+ * 0 on Success / 1 on Failure.
+ **/
+int scsi_register_host(Scsi_Host_Template *shost_tp)
+{
+ int cur_cnt;
+ Scsi_Device *sdev;
+ struct Scsi_Device_Template *sdev_tp;
+ struct list_head *lh;
+ struct Scsi_Host *shost;
+
+ /*
+ * Check no detect routine.
+ */
+ if (!shost_tp->detect)
+ return 1;
+
+ /* If max_sectors isn't set, default to max */
+ if (!shost_tp->max_sectors)
+ shost_tp->max_sectors = 1024;
+
+ cur_cnt = scsi_hosts_registered;
+
+ MOD_INC_USE_COUNT;
+
+ /*
+ * The detect routine must carefully spinunlock/spinlock if it
+ * enables interrupts, since all interrupt handlers do spinlock as
+ * well.
+ */
+
+ /*
+ * detect should do its own locking
+ * FIXME present is now set is scsi_register which breaks manual
+ * registration code below.
+ */
+ shost_tp->detect(shost_tp);
+
+ if (shost_tp->present) {
+ /*
+ * FIXME Who needs manual registration and why???
+ */
+ if (cur_cnt == scsi_hosts_registered) {
+ if (shost_tp->present > 1) {
+ printk(KERN_ERR "scsi: Failure to register"
+ "low-level scsi driver");
+ scsi_unregister_host(shost_tp);
+ return 1;
+ }
+ /*
+ * The low-level driver failed to register a driver.
+ * We can do this now.
+ */
+ if(scsi_register(shost_tp, 0)==NULL) {
+ printk(KERN_ERR "scsi: register failed.\n");
+ scsi_unregister_host(shost_tp);
+ return 1;
+ }
+ }
+
+ list_add_tail(&shost_tp->shtp_list, &scsi_host_tmpl_list);
+
+ /* The next step is to call scan_scsis here. This generates the
+ * Scsi_Devices entries
+ */
+ list_for_each(lh, &scsi_host_list) {
+ shost = list_entry(lh, struct Scsi_Host, sh_list);
+ if (shost->hostt == shost_tp) {
+ const char *dm_name;
+ if (shost_tp->info) {
+ dm_name = shost_tp->info(shost);
+ } else {
+ dm_name = shost_tp->name;
+ }
+ printk(KERN_INFO "scsi%d : %s\n",
+ shost->host_no, dm_name);
+
+ /* first register parent with driverfs */
+ device_register(&shost->host_driverfs_dev);
+ scan_scsis(shost, 0, 0, 0, 0);
+ }
+ }
+
+ for (sdev_tp = scsi_devicelist; sdev_tp;
+ sdev_tp = sdev_tp->next) {
+ if (sdev_tp->init && sdev_tp->dev_noticed)
+ (*sdev_tp->init) ();
+ }
+
+ /*
+ * Next we create the Scsi_Cmnd structures for this host
+ */
+ list_for_each(lh, &scsi_host_list) {
+ shost = list_entry(lh, struct Scsi_Host, sh_list);
+ for (sdev = shost->host_queue; sdev; sdev = sdev->next)
+ if (sdev->host->hostt == shost_tp) {
+ for (sdev_tp = scsi_devicelist;
+ sdev_tp;
+ sdev_tp = sdev_tp->next)
+ if (sdev_tp->attach)
+ (*sdev_tp->attach) (sdev);
+ if (sdev->attached) {
+ scsi_build_commandblocks(sdev);
+ if (sdev->current_queue_depth == 0)
+ goto out_of_space;
+ }
+ }
+ }
+
+ /* This does any final handling that is required. */
+ for (sdev_tp = scsi_devicelist; sdev_tp;
+ sdev_tp = sdev_tp->next) {
+ if (sdev_tp->finish && sdev_tp->nr_dev) {
+ (*sdev_tp->finish) ();
+ }
}
- }
- if (! shpnt)
- o_shp->next = retval;
- }
- }
-
- return retval;
+ }
+
+ return 0;
+
+out_of_space:
+ scsi_unregister_host(shost_tp); /* easiest way to clean up?? */
+ return 1;
+}
+
+/**
+ * scsi_unregister_host - unregister a low level host adapter driver
+ * @shost_tp: scsi host template to unregister.
+ *
+ * Description:
+ * Similarly, this entry point should be called by a loadable module
+ * if it is trying to remove a low level scsi driver from the system.
+ *
+ * Return value:
+ * 0 on Success / 1 on Failure
+ *
+ * Notes:
+ * rmmod does not care what we return here the module will be
+ * removed.
+ **/
+int scsi_unregister_host(Scsi_Host_Template *shost_tp)
+{
+ int pcount;
+
+ /* get the big kernel lock, so we don't race with open() */
+ lock_kernel();
+
+ pcount = scsi_hosts_registered;
+
+ scsi_tp_for_each_host(shost_tp, scsi_host_chk_and_release);
+
+ if (pcount != scsi_hosts_registered)
+ printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
+ (scsi_hosts_registered == 1) ? "" : "s");
+
+ /*
+ * Remove it from the list if all
+ * hosts were successfully removed (ie preset == 0)
+ */
+ if (!shost_tp->present) {
+ list_del(&shost_tp->shtp_list);
+ }
+
+ MOD_DEC_USE_COUNT;
+
+ unlock_kernel();
+ return 0;
+
+}
+
+/**
+ * *scsi_host_get_next - get scsi host and inc ref count
+ * @shost: pointer to a Scsi_Host or NULL to start.
+ *
+ * Return value:
+ * A pointer to next Scsi_Host in list or NULL.
+ **/
+struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *shost)
+{
+ struct list_head *lh = NULL;
+
+ spin_lock(&scsi_host_list_lock);
+ if (shost) {
+ /* XXX Dec ref on cur shost */
+ lh = shost->sh_list.next;
+ } else {
+ lh = scsi_host_list.next;
+ }
+
+ if (lh == &scsi_host_list) {
+ shost = (struct Scsi_Host *)NULL;
+ goto done;
+ }
+
+ shost = list_entry(lh, struct Scsi_Host, sh_list);
+ /* XXX Inc ref count */
+
+done:
+ spin_unlock(&scsi_host_list_lock);
+ return shost;
+}
+
+/**
+ * scsi_host_hn_get - get a Scsi_Host by host no and inc ref count
+ * @host_no: host number to locate
+ *
+ * Return value:
+ * A pointer to located Scsi_Host or NULL.
+ **/
+struct Scsi_Host *scsi_host_hn_get(unsigned short host_no)
+{
+ struct list_head *lh;
+ struct Scsi_Host *shost;
+
+ spin_lock(&scsi_host_list_lock);
+ list_for_each(lh, &scsi_host_list) {
+ shost = list_entry(lh, struct Scsi_Host, sh_list);
+ if (shost->host_no == host_no) {
+ /* XXX Inc ref count */
+ goto done;
+ }
+ }
+
+ shost = (struct Scsi_Host *)NULL;
+done:
+ spin_unlock(&scsi_host_list_lock);
+ return shost;
+}
+
+/**
+ * *scsi_host_put - dec a Scsi_Host ref count
+ * @shost: Pointer to Scsi_Host to dec.
+ **/
+void scsi_host_put(struct Scsi_Host *shost)
+{
+
+ /* XXX Get list lock */
+ /* XXX dec ref count */
+ /* XXX Release list lock */
+ return;
+}
+
+/**
+ * scsi_host_hn_init - init scsi host number list from string
+ * @shost_hn: string of scsi host driver names.
+ **/
+void __init scsi_host_hn_init(char *shost_hn)
+{
+ char *temp = shost_hn;
+
+ while (temp) {
+ while (*temp && (*temp != ':') && (*temp != ','))
+ temp++;
+ if (!*temp)
+ temp = NULL;
+ else
+ *temp++ = 0;
+ (void)scsi_host_hn_add(shost_hn);
+ shost_hn = temp;
+ }
+}
+
+/**
+ * scsi_host_no_release - free all entries in scsi host number list
+ **/
+void __exit scsi_host_hn_release()
+{
+ struct list_head *lh, *next;
+ Scsi_Host_Name *shn;
+
+ list_for_each_safe(lh, next, &scsi_host_hn_list) {
+ shn = list_entry(lh, Scsi_Host_Name, shn_list);
+ if (shn->name)
+ kfree(shn->name);
+ kfree(shn);
+ }
}
void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev)
@@ -279,8 +761,7 @@ void scsi_host_busy_dec_and_test(struct Scsi_Host *shost, Scsi_Device *sdev)
if (shost->in_recovery && (shost->host_busy == shost->host_failed)) {
up(shost->eh_wait);
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
- "thread (%d)\n",
- atomic_read(&shost->eh_wait->count)));
+ " thread\n"));
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -295,8 +776,7 @@ void scsi_host_failed_inc_and_test(struct Scsi_Host *shost)
if (shost->host_busy == shost->host_failed) {
up(shost->eh_wait);
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
- "thread (%d)\n",
- atomic_read(&shost->eh_wait->count)));
+ " thread\n"));
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
index a899c89ded0b..bf835126f727 100644
--- a/drivers/scsi/hosts.h
+++ b/drivers/scsi/hosts.h
@@ -16,15 +16,14 @@
* of the same type.
*
* Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
+ *
+ * Restructured scsi_host lists and associated functions.
+ * September 04, 2002 Mike Anderson (andmike@us.ibm.com)
*/
#ifndef _HOSTS_H
#define _HOSTS_H
-/*
- $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
-*/
-
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
@@ -58,8 +57,7 @@ typedef struct scsi_disk Disk;
typedef struct SHT
{
- /* Used with loadable modules so we can construct a linked list. */
- struct SHT * next;
+ struct list_head shtp_list;
/* Used with loadable modules so that we know when it is safe to unload */
struct module * module;
@@ -374,7 +372,7 @@ struct Scsi_Host
* This information is private to the scsi mid-layer. Wrapping it in a
* struct private is a way of marking it in a sort of C++ type of way.
*/
- struct Scsi_Host * next;
+ struct list_head sh_list;
Scsi_Device * host_queue;
struct list_head all_scsi_hosts;
struct list_head my_devices;
@@ -510,28 +508,26 @@ struct Scsi_Host
* thing. This physical pseudo-device isn't real and won't be available
* from any high-level drivers.
*/
-extern void scsi_free_host_dev(Scsi_Device * SDpnt);
-extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt);
+extern void scsi_free_host_dev(Scsi_Device *);
+extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host *);
-extern void scsi_unblock_requests(struct Scsi_Host * SHpnt);
-extern void scsi_block_requests(struct Scsi_Host * SHpnt);
-extern void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel);
+extern void scsi_unblock_requests(struct Scsi_Host *);
+extern void scsi_block_requests(struct Scsi_Host *);
+extern void scsi_report_bus_reset(struct Scsi_Host *, int);
typedef struct SHN
- {
- struct SHN * next;
- char * name;
- unsigned short host_no;
- unsigned short host_registered;
- } Scsi_Host_Name;
+{
+ struct list_head shn_list;
+ char *name;
+ unsigned short host_no;
+ unsigned short host_registered;
+} Scsi_Host_Name;
-extern Scsi_Host_Name * scsi_host_no_list;
-extern struct Scsi_Host * scsi_hostlist;
extern struct Scsi_Device_Template * scsi_devicelist;
-extern Scsi_Host_Template * scsi_hosts;
-
-extern void build_proc_dir_entries(Scsi_Host_Template *);
+extern void scsi_proc_host_mkdir(Scsi_Host_Template *);
+extern void scsi_proc_host_add(struct Scsi_Host *);
+extern void scsi_proc_host_rm(struct Scsi_Host *);
/*
* scsi_init initializes the scsi hosts.
@@ -540,34 +536,33 @@ extern void build_proc_dir_entries(Scsi_Host_Template *);
extern int next_scsi_host;
unsigned int scsi_init(void);
-extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j);
-extern void scsi_unregister(struct Scsi_Host * i);
-extern void scsi_register_blocked_host(struct Scsi_Host * SHpnt);
-extern void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt);
+extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int);
+extern void scsi_unregister(struct Scsi_Host *);
+extern void scsi_register_blocked_host(struct Scsi_Host *);
+extern void scsi_deregister_blocked_host(struct Scsi_Host *);
-static inline void scsi_assign_lock(struct Scsi_Host *host, spinlock_t *lock)
+static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
{
- host->host_lock = lock;
+ shost->host_lock = lock;
}
-static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt,
+static inline void scsi_set_pci_device(struct Scsi_Host *shost,
struct pci_dev *pdev)
{
- SHpnt->pci_dev = pdev;
- SHpnt->host_driverfs_dev.parent=&pdev->dev;
+ shost->pci_dev = pdev;
+ shost->host_driverfs_dev.parent=&pdev->dev;
+
+ /* register parent with driverfs */
+ device_register(&shost->host_driverfs_dev);
}
/*
* Prototypes for functions/data in scsi_scan.c
*/
-extern void scan_scsis(struct Scsi_Host *shpnt,
- uint hardcoded,
- uint hchannel,
- uint hid,
- uint hlun);
+extern void scan_scsis(struct Scsi_Host *, uint, uint, uint, uint);
-extern void scsi_mark_host_reset(struct Scsi_Host *Host);
+extern void scsi_mark_host_reset(struct Scsi_Host *);
#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -596,7 +591,7 @@ struct Scsi_Device_Template
struct device_driver scsi_driverfs_driver;
};
-void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
+void scsi_initialize_queue(Scsi_Device *, struct Scsi_Host *);
/*
@@ -607,6 +602,12 @@ extern int scsi_unregister_device(struct Scsi_Device_Template *);
extern int scsi_register_host(Scsi_Host_Template *);
extern int scsi_unregister_host(Scsi_Host_Template *);
+extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *);
+extern struct Scsi_Host *scsi_host_hn_get(unsigned short);
+extern void scsi_host_put(struct Scsi_Host *);
+extern void scsi_host_hn_init(char *);
+extern void scsi_host_hn_release(void);
+
/*
* host_busy inc/dec/test functions
*/
@@ -614,7 +615,6 @@ extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
-
/*
* This is an ugly hack. If we expect to be able to load devices at run time,
* we need to leave extra room in some of the data structures. Doing a
@@ -643,21 +643,22 @@ extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
/**
* scsi_find_device - find a device given the host
+ * @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
* @pun: SCSI target number (physical unit number)
* @lun: SCSI Logical Unit Number
**/
-static inline Scsi_Device *scsi_find_device(struct Scsi_Host *host,
+static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost,
int channel, int pun, int lun) {
- Scsi_Device *SDpnt;
+ Scsi_Device *sdev;
- for(SDpnt = host->host_queue;
- SDpnt != NULL;
- SDpnt = SDpnt->next)
- if(SDpnt->channel == channel && SDpnt->id == pun
- && SDpnt->lun ==lun)
+ for (sdev = shost->host_queue;
+ sdev != NULL;
+ sdev = sdev->next)
+ if (sdev->channel == channel && sdev->id == pun
+ && sdev->lun ==lun)
break;
- return SDpnt;
+ return sdev;
}
#endif
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index 13d2ecb5a6ba..9e0c43d5ae97 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -407,7 +407,6 @@
*/
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
#define IPS { \
- next : NULL, \
module : NULL, \
proc_info : NULL, \
proc_dir : NULL, \
@@ -437,7 +436,6 @@
}
#elif LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
#define IPS { \
- next : NULL, \
module : NULL, \
proc_info : NULL, \
name : NULL, \
@@ -466,7 +464,6 @@
}
#else
#define IPS { \
- next : NULL, \
module : NULL, \
proc_info : NULL, \
name : NULL, \
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index fc5f5aa2f1bb..99c8a8f2f26c 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -322,8 +322,6 @@ static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
}
}
- if (SRpnt->sr_device->scsi_level <= SCSI_2)
- cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
init_completion(&STp->wait);
SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
(STp->buffer)->use_sg : 0;
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 5882c11b1ac9..f466b76ca6e2 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -294,7 +294,8 @@ static void aha152x_config_cs(dev_link_t *link)
tail = &link->dev;
info->ndev = 0;
- for (host = scsi_hostlist; host; host = host->next)
+ for (host = scsi_host_get_next(NULL); host;
+ host = scsi_host_get_next(host))
if (host->hostt == &driver_template)
for (dev = host->host_queue; dev; dev = dev->next) {
u_long arg[2], id;
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 3149c5bb8596..d8e6294cc667 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -258,7 +258,8 @@ static void fdomain_config(dev_link_t *link)
tail = &link->dev;
info->ndev = 0;
- for (host = scsi_hostlist; host; host = host->next)
+ for (host = scsi_host_get_next(NULL); host;
+ host = scsi_host_get_next(host))
if (host->hostt == &driver_template)
for (dev = host->host_queue; dev; dev = dev->next) {
u_long arg[2], id;
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index fc521c26e672..82916db1c391 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1520,7 +1520,8 @@ static void nsp_cs_config(dev_link_t *link)
DEBUG(0, "GET_SCSI_INFO\n");
tail = &link->dev;
info->ndev = 0;
- for (host = scsi_hostlist; host != NULL; host = host->next) {
+ for (host = scsi_host_get_next(NULL); host;
+ host = scsi_host_get_next(host))
if (host->hostt == &driver_template) {
for (dev = host->host_queue; dev != NULL; dev = dev->next) {
u_long arg[2], id;
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 0bfa59d14e5f..6e01a0c82fae 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -281,7 +281,8 @@ static void qlogic_config(dev_link_t *link)
tail = &link->dev;
info->ndev = 0;
- for (host = scsi_hostlist; host; host = host->next)
+ for (host = scsi_host_get_next(NULL); host;
+ host = scsi_host_get_next(host))
if (host->hostt == &driver_template)
for (dev = host->host_queue; dev; dev = dev->next) {
u_long arg[2], id;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d05400f6d047..6df3f92793e8 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -798,6 +798,12 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
serial_number = 1;
SCpnt->serial_number = serial_number;
SCpnt->pid = scsi_pid++;
+ /*
+ * If SCSI-2 or lower, store the LUN value in cmnd.
+ */
+ if (SCpnt->device->scsi_level <= SCSI_2)
+ SCpnt->cmnd[1] = (SCpnt->cmnd[1] & 0x1f) |
+ (SCpnt->lun << 5 & 0xe0);
/*
* We will wait MIN_RESET_DELAY clock ticks after the last reset so
@@ -1659,33 +1665,6 @@ void scsi_adjust_queue_depth(Scsi_Device *SDpnt, int tagged, int tags)
}
}
-void __init scsi_host_no_insert(char *str, int n)
-{
- Scsi_Host_Name *shn, *shn2;
- int len;
-
- len = strlen(str);
- if (len && (shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC))) {
- if ((shn->name = kmalloc(len+1, GFP_ATOMIC))) {
- strncpy(shn->name, str, len);
- shn->name[len] = 0;
- shn->host_no = n;
- shn->host_registered = 0;
- shn->next = NULL;
- if (scsi_host_no_list) {
- for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next)
- ;
- shn2->next = shn;
- }
- else
- scsi_host_no_list = shn;
- max_scsi_hosts = n+1;
- }
- else
- kfree((char *) shn);
- }
-}
-
#ifdef CONFIG_PROC_FS
static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
{
@@ -1698,7 +1677,8 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
/*
* First, see if there are any attached devices or not.
*/
- for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+ for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+ HBA_ptr = scsi_host_get_next(HBA_ptr)) {
if (HBA_ptr->host_queue != NULL) {
break;
}
@@ -1706,7 +1686,8 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
size = sprintf(buffer + len, "Attached devices: %s\n", (HBA_ptr) ? "" : "none");
len += size;
pos = begin + len;
- for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+ for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+ HBA_ptr = scsi_host_get_next(HBA_ptr)) {
#if 0
size += sprintf(buffer + len, "scsi%2d: %s\n", (int) HBA_ptr->host_no,
HBA_ptr->hostt->procname);
@@ -1873,7 +1854,8 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel,
id, lun);
- for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+ for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+ HBA_ptr = scsi_host_get_next(HBA_ptr)) {
if (HBA_ptr->host_no == host) {
break;
}
@@ -1918,7 +1900,8 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
lun = simple_strtoul(p + 1, &p, 0);
- for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+ for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+ HBA_ptr = scsi_host_get_next(HBA_ptr)) {
if (HBA_ptr->host_no == host) {
break;
}
@@ -1988,369 +1971,6 @@ out:
#endif
/*
- * This entry point should be called by a driver if it is trying
- * to add a low level scsi driver to the system.
- */
-int scsi_register_host(Scsi_Host_Template * tpnt)
-{
- int pcount;
- struct Scsi_Host *shpnt;
- Scsi_Device *SDpnt;
- struct Scsi_Device_Template *sdtpnt;
- const char *name;
- int out_of_space = 0;
-
- if (tpnt->next || !tpnt->detect)
- return 1; /* Must be already loaded, or
- * no detect routine available
- */
-
- /* If max_sectors isn't set, default to max */
- if (!tpnt->max_sectors)
- tpnt->max_sectors = 1024;
-
- pcount = next_scsi_host;
-
- MOD_INC_USE_COUNT;
-
- /* The detect routine must carefully spinunlock/spinlock if
- it enables interrupts, since all interrupt handlers do
- spinlock as well. */
-
- /*
- * detect should do its own locking
- */
- tpnt->present = tpnt->detect(tpnt);
-
- if (tpnt->present) {
- if (pcount == next_scsi_host) {
- if (tpnt->present > 1) {
- printk(KERN_ERR "scsi: Failure to register low-level scsi driver");
- scsi_unregister_host(tpnt);
- return 1;
- }
- /*
- * The low-level driver failed to register a driver.
- * We can do this now.
- */
- if(scsi_register(tpnt, 0)==NULL)
- {
- printk(KERN_ERR "scsi: register failed.\n");
- scsi_unregister_host(tpnt);
- return 1;
- }
- }
- tpnt->next = scsi_hosts; /* Add to the linked list */
- scsi_hosts = tpnt;
-
- /* Add the new driver to /proc/scsi */
-#ifdef CONFIG_PROC_FS
- build_proc_dir_entries(tpnt);
-#endif
-
-
- /*
- * Add the kernel threads for each host adapter that will
- * handle error correction.
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt) {
- DECLARE_MUTEX_LOCKED(sem);
-
- shpnt->eh_notify = &sem;
- kernel_thread((int (*)(void *)) scsi_error_handler,
- (void *) shpnt, 0);
-
- /*
- * Now wait for the kernel error thread to initialize itself
- * as it might be needed when we scan the bus.
- */
- down(&sem);
- shpnt->eh_notify = NULL;
- }
- }
-
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt) {
- if (tpnt->info) {
- name = tpnt->info(shpnt);
- } else {
- name = tpnt->name;
- }
- printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */
- shpnt->host_no, name);
- strncpy(shpnt->host_driverfs_dev.name,name,
- DEVICE_NAME_SIZE-1);
- sprintf(shpnt->host_driverfs_dev.bus_id,
- "scsi%d",
- shpnt->host_no);
- }
- }
-
- /* The next step is to call scan_scsis here. This generates the
- * Scsi_Devices entries
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt) {
- /* first register parent with driverfs */
- device_register(&shpnt->host_driverfs_dev);
- scan_scsis(shpnt, 0, 0, 0, 0);
- }
- }
-
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
- if (sdtpnt->init && sdtpnt->dev_noticed)
- (*sdtpnt->init) ();
- }
-
- /*
- * Next we create the Scsi_Cmnd structures for this host
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next)
- if (SDpnt->host->hostt == tpnt) {
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
- if (sdtpnt->attach)
- (*sdtpnt->attach) (SDpnt);
- if (SDpnt->attached) {
- scsi_build_commandblocks(SDpnt);
- if (SDpnt->current_queue_depth == 0)
- out_of_space = 1;
- }
- }
- }
-
- /* This does any final handling that is required. */
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
- if (sdtpnt->finish && sdtpnt->nr_dev) {
- (*sdtpnt->finish) ();
- }
- }
- }
-
- if (out_of_space) {
- scsi_unregister_host(tpnt); /* easiest way to clean up?? */
- return 1;
- } else
- return 0;
-}
-
-/*
- * Similarly, this entry point should be called by a loadable module if it
- * is trying to remove a low level scsi driver from the system.
- */
-int scsi_unregister_host(Scsi_Host_Template * tpnt)
-{
- int online_status;
- int pcount0, pcount;
- Scsi_Cmnd *SCpnt;
- Scsi_Device *SDpnt;
- Scsi_Device *SDpnt1;
- struct Scsi_Device_Template *sdtpnt;
- struct Scsi_Host *sh1;
- struct Scsi_Host *shpnt;
- char name[10]; /* host_no>=10^9? I don't think so. */
-
- /* get the big kernel lock, so we don't race with open() */
- lock_kernel();
-
- /*
- * First verify that this host adapter is completely free with no pending
- * commands
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- for (SDpnt = shpnt->host_queue; SDpnt;
- SDpnt = SDpnt->next) {
- if (SDpnt->host->hostt == tpnt
- && SDpnt->host->hostt->module
- && GET_USE_COUNT(SDpnt->host->hostt->module))
- goto err_out;
- /*
- * FIXME(eric) - We need to find a way to notify the
- * low level driver that we are shutting down - via the
- * special device entry that still needs to get added.
- *
- * Is detach interface below good enough for this?
- */
- }
- }
-
- /*
- * FIXME(eric) put a spinlock on this. We force all of the devices offline
- * to help prevent race conditions where other hosts/processors could try and
- * get in and queue a command.
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- for (SDpnt = shpnt->host_queue; SDpnt;
- SDpnt = SDpnt->next) {
- if (SDpnt->host->hostt == tpnt)
- SDpnt->online = FALSE;
-
- }
- }
-
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt != tpnt) {
- continue;
- }
- for (SDpnt = shpnt->host_queue; SDpnt;
- SDpnt = SDpnt->next) {
- /*
- * Loop over all of the commands associated with the device. If any of
- * them are busy, then set the state back to inactive and bail.
- */
- for (SCpnt = SDpnt->device_queue; SCpnt;
- SCpnt = SCpnt->next) {
- online_status = SDpnt->online;
- SDpnt->online = FALSE;
- if (SCpnt->request && SCpnt->request->rq_status != RQ_INACTIVE) {
- printk(KERN_ERR "SCSI device not inactive - rq_status=%d, target=%d, pid=%ld, state=%d, owner=%d.\n",
- SCpnt->request->rq_status, SCpnt->target, SCpnt->pid,
- SCpnt->state, SCpnt->owner);
- for (SDpnt1 = shpnt->host_queue; SDpnt1;
- SDpnt1 = SDpnt1->next) {
- for (SCpnt = SDpnt1->device_queue; SCpnt;
- SCpnt = SCpnt->next)
- if (SCpnt->request->rq_status == RQ_SCSI_DISCONNECTING)
- SCpnt->request->rq_status = RQ_INACTIVE;
- }
- SDpnt->online = online_status;
- printk(KERN_ERR "Device busy???\n");
- goto err_out;
- }
- /*
- * No, this device is really free. Mark it as such, and
- * continue on.
- */
- SCpnt->state = SCSI_STATE_DISCONNECTING;
- if(SCpnt->request)
- SCpnt->request->rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */
- }
- }
- }
- /* Next we detach the high level drivers from the Scsi_Device structures */
-
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt != tpnt) {
- continue;
- }
- for (SDpnt = shpnt->host_queue; SDpnt;
- SDpnt = SDpnt->next) {
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
- if (sdtpnt->detach)
- (*sdtpnt->detach) (SDpnt);
-
- /* If something still attached, punt */
- if (SDpnt->attached) {
- printk(KERN_ERR "Attached usage count = %d\n", SDpnt->attached);
- goto err_out;
- }
- if (shpnt->hostt->slave_detach)
- (*shpnt->hostt->slave_detach) (SDpnt);
- devfs_unregister (SDpnt->de);
- put_device(&SDpnt->sdev_driverfs_dev);
- }
- }
-
- /*
- * Next, kill the kernel error recovery thread for this host.
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt
- && shpnt->ehandler != NULL) {
- DECLARE_MUTEX_LOCKED(sem);
-
- shpnt->eh_notify = &sem;
- send_sig(SIGHUP, shpnt->ehandler, 1);
- down(&sem);
- shpnt->eh_notify = NULL;
- }
- }
-
- /* Next we free up the Scsi_Cmnd structures for this host */
-
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt != tpnt) {
- continue;
- }
- for (SDpnt = shpnt->host_queue; SDpnt;
- SDpnt = shpnt->host_queue) {
- scsi_release_commandblocks(SDpnt);
-
- blk_cleanup_queue(&SDpnt->request_queue);
- /* Next free up the Scsi_Device structures for this host */
- shpnt->host_queue = SDpnt->next;
- if (SDpnt->inquiry)
- kfree(SDpnt->inquiry);
- kfree((char *) SDpnt);
-
- }
- }
-
- /* Next we go through and remove the instances of the individual hosts
- * that were detected */
-
- pcount0 = next_scsi_host;
- for (shpnt = scsi_hostlist; shpnt; shpnt = sh1) {
- sh1 = shpnt->next;
- if (shpnt->hostt != tpnt)
- continue;
- pcount = next_scsi_host;
- /* Remove the /proc/scsi directory entry */
- sprintf(name,"%d",shpnt->host_no);
- remove_proc_entry(name, tpnt->proc_dir);
- put_device(&shpnt->host_driverfs_dev);
- if (tpnt->release)
- (*tpnt->release) (shpnt);
- else {
- /* This is the default case for the release function.
- * It should do the right thing for most correctly
- * written host adapters.
- */
- if (shpnt->irq)
- free_irq(shpnt->irq, NULL);
- if (shpnt->dma_channel != 0xff)
- free_dma(shpnt->dma_channel);
- if (shpnt->io_port && shpnt->n_io_port)
- release_region(shpnt->io_port, shpnt->n_io_port);
- }
- if (pcount == next_scsi_host)
- scsi_unregister(shpnt);
- tpnt->present--;
- }
-
- if (pcount0 != next_scsi_host)
- printk(KERN_INFO "scsi : %d host%s left.\n", next_scsi_host,
- (next_scsi_host == 1) ? "" : "s");
-
- /*
- * Remove it from the linked list and /proc if all
- * hosts were successfully removed (ie preset == 0)
- */
- if (!tpnt->present) {
- Scsi_Host_Template **SHTp = &scsi_hosts;
- Scsi_Host_Template *SHT;
-
- while ((SHT = *SHTp) != NULL) {
- if (SHT == tpnt) {
- *SHTp = SHT->next;
- remove_proc_entry(tpnt->proc_name, proc_scsi);
- break;
- }
- SHTp = &SHT->next;
- }
- }
- MOD_DEC_USE_COUNT;
-
- unlock_kernel();
- return 0;
-
-err_out:
- unlock_kernel();
- return -1;
-}
-
-/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
*/
@@ -2361,7 +1981,7 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
int out_of_space = 0;
#ifdef CONFIG_KMOD
- if (scsi_hosts == NULL)
+ if (scsi_host_get_next(NULL) == NULL)
request_module("scsi_hostadapter");
#endif
@@ -2375,7 +1995,8 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
* First scan the devices that we know about, and see if we notice them.
*/
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+ for (shpnt = scsi_host_get_next(NULL); shpnt;
+ shpnt = scsi_host_get_next(shpnt)) {
for (SDpnt = shpnt->host_queue; SDpnt;
SDpnt = SDpnt->next) {
if (tpnt->detect)
@@ -2394,7 +2015,8 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
/*
* Now actually connect the devices to the new driver.
*/
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+ for (shpnt = scsi_host_get_next(NULL); shpnt;
+ shpnt = scsi_host_get_next(shpnt)) {
for (SDpnt = shpnt->host_queue; SDpnt;
SDpnt = SDpnt->next) {
if (tpnt->attach)
@@ -2444,7 +2066,8 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
* Next, detach the devices from the driver.
*/
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+ for (shpnt = scsi_host_get_next(NULL); shpnt;
+ shpnt = scsi_host_get_next(shpnt)) {
for (SDpnt = shpnt->host_queue; SDpnt;
SDpnt = SDpnt->next) {
if (tpnt->detach)
@@ -2516,7 +2139,8 @@ static void scsi_dump_status(int level)
Scsi_Device *SDpnt;
printk(KERN_INFO "Dump of scsi host parameters:\n");
i = 0;
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+ for (shpnt = scsi_host_get_next(NULL); shpnt;
+ shpnt = scsi_host_get_next(shpnt)) {
printk(KERN_INFO " %d %d %d : %d %d\n",
shpnt->host_failed,
shpnt->host_busy,
@@ -2527,7 +2151,8 @@ static void scsi_dump_status(int level)
printk(KERN_INFO "\n\n");
printk(KERN_INFO "Dump of scsi command parameters:\n");
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+ for (shpnt = scsi_host_get_next(NULL); shpnt;
+ shpnt = scsi_host_get_next(shpnt)) {
printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result\n");
for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
@@ -2565,26 +2190,6 @@ static void scsi_dump_status(int level)
}
#endif /* CONFIG_PROC_FS */
-static int __init scsi_host_no_init (char *str)
-{
- static int next_no = 0;
- char *temp;
-
- while (str) {
- temp = str;
- while (*temp && (*temp != ':') && (*temp != ','))
- temp++;
- if (!*temp)
- temp = NULL;
- else
- *temp++ = 0;
- scsi_host_no_insert(str, next_no);
- str = temp;
- next_no++;
- }
- return 1;
-}
-
static char *scsihosts;
MODULE_PARM(scsihosts, "s");
@@ -2724,9 +2329,8 @@ static int __init init_scsi(void)
#endif
scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
- if (scsihosts)
- printk(KERN_INFO "scsi: host order: %s\n", scsihosts);
- scsi_host_no_init (scsihosts);
+
+ scsi_host_hn_init(scsihosts);
bus_register(&scsi_driverfs_bus_type);
@@ -2738,19 +2342,11 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void)
{
- Scsi_Host_Name *shn, *shn2 = NULL;
int i;
devfs_unregister (scsi_devfs_handle);
- for (shn = scsi_host_no_list;shn;shn = shn->next) {
- if (shn->name)
- kfree(shn->name);
- if (shn2)
- kfree (shn2);
- shn2 = shn;
- }
- if (shn2)
- kfree (shn2);
+
+ scsi_host_hn_release();
#ifdef CONFIG_PROC_FS
/* No, we're not here anymore. Don't show the /proc/scsi files. */
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index f616c4b8cdf7..710e34267961 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -877,6 +877,12 @@ struct scsi_cmnd {
extern int scsi_reset_provider(Scsi_Device *, int);
+#define MSG_SIMPLE_TAG 0x20
+#define MSG_HEAD_TAG 0x21
+#define MSG_ORDERED_TAG 0x22
+
+#define SCSI_NO_TAG (-1) /* identify no tag in use */
+
/**
* scsi_activate_tcq - turn on tag command queueing
* @SDpnt: device to turn on TCQ for
@@ -892,7 +898,7 @@ static inline void scsi_activate_tcq(Scsi_Device *SDpnt, int depth) {
if(SDpnt->tagged_supported && !blk_queue_tagged(q)) {
blk_queue_init_tags(q, depth);
- SDpnt->tagged_queue = 1;
+ scsi_adjust_queue_depth(SDpnt, MSG_ORDERED_TAG, depth);
}
}
@@ -902,13 +908,8 @@ static inline void scsi_activate_tcq(Scsi_Device *SDpnt, int depth) {
**/
static inline void scsi_deactivate_tcq(Scsi_Device *SDpnt) {
blk_queue_free_tags(&SDpnt->request_queue);
- SDpnt->tagged_queue = 0;
+ scsi_adjust_queue_depth(SDpnt, 0, 2);
}
-#define MSG_SIMPLE_TAG 0x20
-#define MSG_HEAD_TAG 0x21
-#define MSG_ORDERED_TAG 0x22
-
-#define SCSI_NO_TAG (-1) /* identify no tag in use */
/**
* scsi_populate_tag_msg - place a tag message in a buffer
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 44628796d12e..d32b1a65d6ee 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -108,9 +108,13 @@ static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
#define SDEBUG_SENSE_LEN 32
struct sdebug_dev_info {
- Scsi_Device * sdp;
unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */
+ unsigned int channel;
+ unsigned int target;
+ unsigned int lun;
+ struct Scsi_Host *host;
char reset;
+ char used;
};
static struct sdebug_dev_info * devInfop;
@@ -154,7 +158,7 @@ static int resp_write(Scsi_Cmnd * SCpnt, int upper_blk, int block, int num,
static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
int bufflen, struct sdebug_dev_info * devip);
static void timer_intr_handler(unsigned long);
-static struct sdebug_dev_info * devInfoReg(Scsi_Device * sdp);
+static struct sdebug_dev_info * devInfoReg(Scsi_Cmnd *scmd);
static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
int asc, int asq, int inbandLen);
static int check_reset(Scsi_Cmnd * SCpnt, struct sdebug_dev_info * devip);
@@ -222,7 +226,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
return schedule_resp(SCpnt, NULL, done, 0, 0);
}
- if ((target > driver_template.this_id) || (SCpnt->lun != 0))
+ if (SCpnt->lun != 0)
return schedule_resp(SCpnt, NULL, done,
DID_NO_CONNECT << 16, 0);
#if 0
@@ -230,14 +234,10 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
(int)SCpnt->device->host->host_no, (int)SCpnt->device->id,
SCpnt->device, (int)*cmd);
#endif
- if (NULL == SCpnt->device->hostdata) {
- devip = devInfoReg(SCpnt->device);
- if (NULL == devip)
- return schedule_resp(SCpnt, NULL, done,
- DID_NO_CONNECT << 16, 0);
- SCpnt->device->hostdata = devip;
- }
- devip = SCpnt->device->hostdata;
+ devip = devInfoReg(SCpnt);
+ if (NULL == devip)
+ return schedule_resp(SCpnt, NULL, done,
+ DID_NO_CONNECT << 16, 0);
if ((SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts) &&
(scsi_debug_every_nth > 0) &&
@@ -474,8 +474,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
int dev_id_num, len;
char dev_id_str[6];
- dev_id_num = ((devip->sdp->host->host_no + 1) * 1000) +
- devip->sdp->id;
+ dev_id_num = ((devip->host->host_no + 1) * 1000) +
+ devip->target;
len = snprintf(dev_id_str, 6, "%d", dev_id_num);
len = (len > 6) ? 6 : len;
if (0 == cmd[2]) { /* supported vital product data pages */
@@ -861,8 +861,7 @@ static int scsi_debug_release(struct Scsi_Host * hpnt)
if (++num_releases == num_present) {
#ifdef DRIVERFS_SUPPORT
do_remove_driverfs_files();
- remove_driver(&sdebug_driverfs_driver);
- // driver_unregister(&sdebug_driverfs_driver);
+ driver_unregister(&sdebug_driverfs_driver);
#endif
vfree(fake_storep);
vfree(devInfop);
@@ -870,21 +869,28 @@ static int scsi_debug_release(struct Scsi_Host * hpnt)
return 0;
}
-static struct sdebug_dev_info * devInfoReg(Scsi_Device * sdp)
+static struct sdebug_dev_info * devInfoReg(Scsi_Cmnd *scmd)
{
int k;
struct sdebug_dev_info * devip;
for (k = 0; k < scsi_debug_num_devs; ++k) {
devip = &devInfop[k];
- if (devip->sdp == sdp)
+ if ((devip->channel == scmd->channel) &&
+ (devip->target == scmd->target) &&
+ (devip->lun == scmd->lun) &&
+ (devip->host == scmd->host))
return devip;
}
for (k = 0; k < scsi_debug_num_devs; ++k) {
devip = &devInfop[k];
- if (NULL == devip->sdp) {
- devip->sdp = sdp;
+ if (!devip->used) {
+ devip->channel = scmd->channel;
+ devip->target = scmd->target;
+ devip->lun = scmd->lun;
+ devip->host = scmd->host;
devip->reset = 1;
+ devip->used = 1;
memset(devip->sense_buff, 0, SDEBUG_SENSE_LEN);
devip->sense_buff[0] = 0x70;
return devip;
@@ -934,19 +940,15 @@ static int scsi_debug_biosparam(Disk * disk, struct block_device * bdev,
static int scsi_debug_device_reset(Scsi_Cmnd * SCpnt)
{
- Scsi_Device * sdp;
- int k;
+ struct sdebug_dev_info * devip;
if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
printk(KERN_INFO "scsi_debug: device_reset\n");
++num_dev_resets;
- if (SCpnt && ((sdp = SCpnt->device))) {
- for (k = 0; k < scsi_debug_num_devs; ++k) {
- if (sdp->hostdata == (devInfop + k))
- break;
- }
- if (k < scsi_debug_num_devs)
- devInfop[k].reset = 1;
+ if (SCpnt) {
+ devip = devInfoReg(SCpnt);
+ if (devip)
+ devip->reset = 1;
}
return SUCCESS;
}
@@ -960,9 +962,9 @@ static int scsi_debug_bus_reset(Scsi_Cmnd * SCpnt)
if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
printk(KERN_INFO "scsi_debug: bus_reset\n");
++num_bus_resets;
- if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+ if (SCpnt && ((sdp = SCpnt->device)) && ((hp = SCpnt->host))) {
for (k = 0; k < scsi_debug_num_devs; ++k) {
- if (hp == devInfop[k].sdp->host)
+ if (hp == devInfop[k].host)
devInfop[k].reset = 1;
}
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 386857db783d..3d9ed3f4442e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -502,6 +502,10 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
*/
scmd->owner = SCSI_OWNER_LOWLEVEL;
+ if (scmd->device->scsi_level <= SCSI_2)
+ scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
+ (scmd->lun << 5 & 0xe0);
+
if (host->can_queue) {
DECLARE_MUTEX_LOCKED(sem);
@@ -610,9 +614,6 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
memcpy((void *) scmd->cmnd, (void *) generic_sense,
sizeof(generic_sense));
- if (scmd->device->scsi_level <= SCSI_2)
- scmd->cmnd[1] = scmd->lun << 5;
-
scsi_result = (!scmd->host->hostt->unchecked_isa_dma)
? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
@@ -839,9 +840,6 @@ retry_tur:
memcpy((void *) scmd->cmnd, (void *) tur_command,
sizeof(tur_command));
- if (scmd->device->scsi_level <= SCSI_2)
- scmd->cmnd[1] = scmd->lun << 5;
-
/*
* zero the sense buffer. the scsi spec mandates that any
* untransferred sense data should be interpreted as being zero.
@@ -1419,7 +1417,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
}
sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
- sreq->sr_cmnd[1] = (sdev->scsi_level <= SCSI_2) ? (sdev->lun << 5) : 0;
+ sreq->sr_cmnd[1] = 0;
sreq->sr_cmnd[2] = 0;
sreq->sr_cmnd[3] = 0;
sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index d1c431cc4017..f2676bf18282 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -160,7 +160,7 @@ int scsi_set_medium_removal(Scsi_Device *dev, char state)
return 0;
scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
- scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
+ scsi_cmd[1] = 0;
scsi_cmd[2] = 0;
scsi_cmd[3] = 0;
scsi_cmd[4] = state;
@@ -297,12 +297,6 @@ int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic)
if(copy_from_user(buf, cmd_in + cmdlen, inlen))
goto error;
- /*
- * Set the lun field to the correct value.
- */
- if (dev->scsi_level <= SCSI_2)
- cmd[1] = (cmd[1] & 0x1f) | (dev->lun << 5);
-
switch (opcode) {
case FORMAT_UNIT:
timeout = FORMAT_UNIT_TIMEOUT;
@@ -416,7 +410,6 @@ scsi_ioctl_get_pci(Scsi_Device * dev, void *arg)
int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
{
char scsi_cmd[MAX_COMMAND_SIZE];
- char cmd_byte1;
/* No idea how this happens.... */
if (!dev)
@@ -431,7 +424,6 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
if (!scsi_block_when_processing_errors(dev)) {
return -ENODEV;
}
- cmd_byte1 = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
switch (cmd) {
case SCSI_IOCTL_GET_IDLUN:
@@ -484,7 +476,7 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
case SCSI_IOCTL_TEST_UNIT_READY:
scsi_cmd[0] = TEST_UNIT_READY;
- scsi_cmd[1] = cmd_byte1;
+ scsi_cmd[1] = 0;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 0;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -492,7 +484,7 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
break;
case SCSI_IOCTL_START_UNIT:
scsi_cmd[0] = START_STOP;
- scsi_cmd[1] = cmd_byte1;
+ scsi_cmd[1] = 0;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 1;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -500,7 +492,7 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
break;
case SCSI_IOCTL_STOP_UNIT:
scsi_cmd[0] = START_STOP;
- scsi_cmd[1] = cmd_byte1;
+ scsi_cmd[1] = 0;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 0;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index a73a677e6818..dfa18e0c0eb9 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -857,7 +857,7 @@ void scsi_request_fn(request_queue_t * q)
scsi_init_cmd_from_req(SCpnt, SRpnt);
}
- } else if (req->flags & REQ_CMD) {
+ } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
SRpnt = NULL;
STpnt = scsi_get_request_dev(req);
if (!STpnt) {
@@ -919,7 +919,7 @@ void scsi_request_fn(request_queue_t * q)
req = NULL;
spin_unlock_irq(q->queue_lock);
- if (SCpnt->request->flags & REQ_CMD) {
+ if (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC)) {
/*
* This will do a couple of things:
* 1) Fill in the actual SCSI command.
diff --git a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
index 980d7047e6e9..ac79b081270c 100644
--- a/drivers/scsi/scsi_merge.c
+++ b/drivers/scsi/scsi_merge.c
@@ -62,16 +62,28 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
int count, gfp_mask;
/*
- * First we need to know how many scatter gather segments are needed.
+ * non-sg block request. FIXME: check bouncing for isa hosts!
*/
- count = req->nr_phys_segments;
+ if ((req->flags & REQ_BLOCK_PC) && !req->bio) {
+ /*
+ * FIXME: isa bouncing
+ */
+ if (SCpnt->host->unchecked_isa_dma)
+ goto fail;
+
+ SCpnt->request_bufflen = req->data_len;
+ SCpnt->request_buffer = req->data;
+ req->buffer = req->data;
+ SCpnt->use_sg = 0;
+ return 1;
+ }
/*
* we used to not use scatter-gather for single segment request,
* but now we do (it makes highmem I/O easier to support without
* kmapping pages)
*/
- SCpnt->use_sg = count;
+ SCpnt->use_sg = req->nr_phys_segments;
gfp_mask = GFP_NOIO;
if (in_interrupt()) {
@@ -111,6 +123,7 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
/*
* kill it. there should be no leftover blocks in this request
*/
+fail:
SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
BUG_ON(SCpnt);
return 0;
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 2f7e4adcc360..7f49373be381 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -119,35 +119,44 @@ static int proc_scsi_write(struct file * file, const char * buf,
return(ret);
}
-void build_proc_dir_entries(Scsi_Host_Template * tpnt)
+void scsi_proc_host_mkdir(Scsi_Host_Template *shost_tp)
{
- struct Scsi_Host *hpnt;
- char name[10]; /* see scsi_unregister_host() */
-
- tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi);
- if (!tpnt->proc_dir) {
- printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries");
+ shost_tp->proc_dir = proc_mkdir(shost_tp->proc_name, proc_scsi);
+ if (!shost_tp->proc_dir) {
+ printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
+ __FUNCTION__, shost_tp->proc_name);
return;
}
- tpnt->proc_dir->owner = tpnt->module;
-
- hpnt = scsi_hostlist;
- while (hpnt) {
- if (tpnt == hpnt->hostt) {
- struct proc_dir_entry *p;
- sprintf(name,"%d",hpnt->host_no);
- p = create_proc_read_entry(name,
- S_IFREG | S_IRUGO | S_IWUSR,
- tpnt->proc_dir,
- proc_scsi_read,
- (void *)hpnt);
- if (!p)
- panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
- p->write_proc=proc_scsi_write;
- p->owner = tpnt->module;
- }
- hpnt = hpnt->next;
+ shost_tp->proc_dir->owner = shost_tp->module;
+}
+
+void scsi_proc_host_add(struct Scsi_Host *shost)
+{
+ char name[10];
+ struct proc_dir_entry *p;
+
+ sprintf(name,"%d",shost->host_no);
+ p = create_proc_read_entry(name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ shost->hostt->proc_dir,
+ proc_scsi_read,
+ (void *)shost);
+ if (!p) {
+ printk(KERN_ERR "%s: Failed to register host %d in"
+ "%s\n", __FUNCTION__, shost->host_no,
+ shost->hostt->proc_name);
+ } else {
+ p->write_proc=proc_scsi_write;
+ p->owner = shost->hostt->module;
}
+
+}
+
+void scsi_proc_host_rm(struct Scsi_Host *shost)
+{
+ char name[10];
+ sprintf(name,"%d",shost->host_no);
+ remove_proc_entry(name, shost->hostt->proc_dir);
}
/*
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 6d174708da82..bbd593135c11 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -291,15 +291,11 @@ __setup("max_scsi_report_luns=", scsi_report_luns_setup);
**/
static void scsi_unlock_floptical(Scsi_Request *sreq, unsigned char *result)
{
- Scsi_Device *sdscan = sreq->sr_device;
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
printk(KERN_NOTICE "scsi: unlocking floptical drive\n");
scsi_cmd[0] = MODE_SENSE;
- if (sdscan->scsi_level <= SCSI_2)
- scsi_cmd[1] = (sdscan->lun << 5) & 0xe0;
- else
- scsi_cmd[1] = 0;
+ scsi_cmd[1] = 0;
scsi_cmd[2] = 0x2e;
scsi_cmd[3] = 0;
scsi_cmd[4] = 0x2a; /* size */
@@ -611,8 +607,6 @@ unsigned char *scsi_get_evpd_page(Scsi_Device *sdev, Scsi_Request *sreq)
{
unsigned char *evpd_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
- int lun = sdev->lun;
- int scsi_level = sdev->scsi_level;
int max_lgth = 255;
retry:
@@ -629,10 +623,7 @@ retry:
memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
scsi_cmd[0] = INQUIRY;
- if ((lun > 0) && (scsi_level <= SCSI_2))
- scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
- else
- scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[1] = 0x01;
scsi_cmd[4] = max_lgth;
sreq->sr_cmd_len = 0;
sreq->sr_sense_buffer[0] = 0;
@@ -870,8 +861,6 @@ int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq)
unsigned char *id_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
int id_idx, scnt, ret;
- int lun = sdev->lun;
- int scsi_level = sdev->scsi_level;
int max_lgth = 255;
retry:
@@ -888,10 +877,7 @@ retry:
memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
scsi_cmd[0] = INQUIRY;
- if ((lun > 0) && (scsi_level <= SCSI_2))
- scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
- else
- scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[1] = 0x01;
scsi_cmd[2] = 0x83;
scsi_cmd[4] = max_lgth;
sreq->sr_cmd_len = 0;
@@ -977,8 +963,6 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq)
{
unsigned char *serialnumber_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
- int lun = sdev->lun;
- int scsi_level = sdev->scsi_level;
int max_lgth = 255;
retry:
@@ -995,10 +979,7 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq)
memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
scsi_cmd[0] = INQUIRY;
- if ((lun > 0) && (scsi_level <= SCSI_2))
- scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
- else
- scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[1] = 0x01;
scsi_cmd[2] = 0x80;
scsi_cmd[4] = max_lgth;
sreq->sr_cmd_len = 0;
@@ -1181,8 +1162,6 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
memset(scsi_cmd, 0, 6);
scsi_cmd[0] = INQUIRY;
- if ((sdev->lun > 0) && (sdev->scsi_level <= SCSI_2))
- scsi_cmd[1] = (sdev->lun << 5) & 0xe0;
scsi_cmd[4] = 36; /* issue conservative alloc_length */
sreq->sr_cmd_len = 0;
sreq->sr_data_direction = SCSI_DATA_READ;
@@ -1230,8 +1209,6 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
if (possible_inq_resp_len > 36) { /* do additional INQUIRY */
memset(scsi_cmd, 0, 6);
scsi_cmd[0] = INQUIRY;
- if ((sdev->lun > 0) && (sdev->scsi_level <= SCSI_2))
- scsi_cmd[1] = (sdev->lun << 5) & 0xe0;
scsi_cmd[4] = (unsigned char) possible_inq_resp_len;
sreq->sr_cmd_len = 0;
sreq->sr_data_direction = SCSI_DATA_READ;
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index e85aeca9d8e6..bd4e8d0dc859 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -91,8 +91,9 @@ EXPORT_SYMBOL(scsi_reset_provider);
/*
* These are here only while I debug the rest of the scsi stuff.
*/
-EXPORT_SYMBOL(scsi_hostlist);
-EXPORT_SYMBOL(scsi_hosts);
+EXPORT_SYMBOL(scsi_host_get_next);
+EXPORT_SYMBOL(scsi_host_hn_get);
+EXPORT_SYMBOL(scsi_host_put);
EXPORT_SYMBOL(scsi_devicelist);
EXPORT_SYMBOL(scsi_device_types);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 1b7abd00b167..e5f80585a33b 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -51,7 +51,6 @@
#define MAJOR_NR SCSI_DISK0_MAJOR
#define LOCAL_END_REQUEST
-#define DEVICE_NR(device) (((major(device) & SD_MAJOR_MASK) << (8 - 4)) + (minor(device) >> 4))
#include <linux/blk.h>
#include <linux/blkpg.h>
#include "scsi.h"
@@ -87,10 +86,10 @@
static Scsi_Disk ** sd_dsk_arr;
static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
-static int check_scsidisk_media_change(kdev_t);
-static int sd_revalidate(kdev_t);
+static int check_scsidisk_media_change(struct gendisk *);
+static int sd_revalidate(struct gendisk *);
-static void sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr);
+static void sd_init_onedisk(Scsi_Disk * sdkp, struct gendisk *disk);
static int sd_init(void);
static void sd_finish(void);
@@ -187,17 +186,16 @@ sd_find_target(void *hp, int scsi_id)
static int sd_ioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg)
{
- kdev_t dev = inode->i_rdev;
- Scsi_Disk * sdkp;
- struct Scsi_Host * host;
- Scsi_Device * sdp;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ Scsi_Disk *sdkp = disk->private_data;
+ Scsi_Device *sdp = sdkp->device;
+ struct Scsi_Host *host;
int diskinfo[4];
- int dsk_nr = DEVICE_NR(dev);
+ int error;
- SCSI_LOG_IOCTL(1, printk("sd_ioctl: dsk_nr=%d, cmd=0x%x\n",
- dsk_nr, cmd));
- sdkp = sd_get_sdisk(dsk_nr);
- if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
+ SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n",
+ disk->disk_name, cmd));
+ if (!sdp)
return -ENODEV;
/*
* If we are in the middle of error recovery, don't let anyone
@@ -209,6 +207,10 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
if( !scsi_block_when_processing_errors(sdp) )
return -ENODEV;
+ error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
+ if (error != -ENOTTY)
+ return error;
+
switch (cmd)
{
case HDIO_GETGEO: /* Return BIOS disk parameters */
@@ -264,29 +266,6 @@ static void sd_dskname(unsigned int dsk_nr, char *buffer)
}
}
-/**
- * sd_find_queue - yields queue associated with device
- * @dev: kernel device descriptor (kdev_t)
- *
- * Returns NULL if no match, otherwise returns pointer to associated
- * request queue.
- *
- * Note: this function is invoked (often) from the block subsystem
- * and should not wait on anything (sd_get_sdisk() does have a read
- * spinlock).
- **/
-static request_queue_t *sd_find_queue(kdev_t dev)
-{
- Scsi_Disk *sdkp;
- int dsk_nr = DEVICE_NR(dev);
-
- sdkp = sd_get_sdisk(dsk_nr);
- if (sdkp && sdkp->device)
- return &sdkp->device->request_queue;
- else
- return NULL; /* No such device */
-}
-
static struct gendisk **sd_disks;
/**
@@ -299,33 +278,54 @@ static struct gendisk **sd_disks;
**/
static int sd_init_command(Scsi_Cmnd * SCpnt)
{
- int dsk_nr, part_nr, this_count;
+ int this_count, timeout;
+ struct gendisk *disk;
sector_t block;
- Scsi_Device *sdp;
-#if CONFIG_SCSI_LOGGING
- char nbuff[6];
-#endif
+ Scsi_Device *sdp = SCpnt->device;
+
+ timeout = SD_TIMEOUT;
+ if (SCpnt->device->type != TYPE_DISK)
+ timeout = SD_MOD_TIMEOUT;
+
/*
- * don't support specials for nwo
+ * these are already setup, just copy cdb basically
+ */
+ if (SCpnt->request->flags & REQ_BLOCK_PC) {
+ struct request *rq = SCpnt->request;
+
+ if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
+ return 0;
+
+ memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+ if (rq_data_dir(rq) == WRITE)
+ SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+ else if (rq->data_len)
+ SCpnt->sc_data_direction = SCSI_DATA_READ;
+ else
+ SCpnt->sc_data_direction = SCSI_DATA_NONE;
+
+ this_count = rq->data_len;
+ if (rq->timeout)
+ timeout = rq->timeout;
+
+ goto queue;
+ }
+
+ /*
+ * we only do REQ_CMD and REQ_BLOCK_PC
*/
if (!(SCpnt->request->flags & REQ_CMD))
return 0;
- part_nr = SD_PARTITION(SCpnt->request->rq_dev);
- dsk_nr = DEVICE_NR(SCpnt->request->rq_dev);
-
+ disk = SCpnt->request->rq_disk;
block = SCpnt->request->sector;
this_count = SCpnt->request_bufflen >> 9;
- SCSI_LOG_HLQUEUE(1, printk("sd_command_init: dsk_nr=%d, block=%llu, "
- "count=%d\n", dsk_nr, (unsigned long long)block, this_count));
+ SCSI_LOG_HLQUEUE(1, printk("sd_command_init: disk=%s, block=%llu, "
+ "count=%d\n", disk->disk_name, (unsigned long long)block, this_count));
- sdp = SCpnt->device;
- /* >>>>> the "(part_nr & 0xf)" excludes 15th partition, why?? */
- /* >>>>> this change is not in the lk 2.5 series */
- if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) ||
- !sdp || !sdp->online ||
- block + SCpnt->request->nr_sectors > get_capacity(sd_disks[dsk_nr])) {
+ if (!sdp || !sdp->online ||
+ block + SCpnt->request->nr_sectors > get_capacity(disk)) {
SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n",
SCpnt->request->nr_sectors));
SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
@@ -340,9 +340,8 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
return 0;
}
- SCSI_LOG_HLQUEUE(2, sd_dskname(dsk_nr, nbuff));
- SCSI_LOG_HLQUEUE(2, printk("%s : [part_nr=%d], block=%llu\n",
- nbuff, part_nr, (unsigned long long)block));
+ SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
+ disk->disk_name, (unsigned long long)block));
/*
* If we have a 1K hardware sectorsize, prevent access to single
@@ -399,11 +398,10 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
}
SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
- nbuff, (rq_data_dir(SCpnt->request) == WRITE) ?
+ disk->disk_name, (rq_data_dir(SCpnt->request) == WRITE) ?
"writing" : "reading", this_count, SCpnt->request->nr_sectors));
- SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
- ((SCpnt->lun << 5) & 0xe0) : 0;
+ SCpnt->cmnd[1] = 0;
if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (this_count > 0xffff)
@@ -433,12 +431,12 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
* host adapter, it's safe to assume that we can at least transfer
* this many bytes between each connect / disconnect.
*/
+queue:
SCpnt->transfersize = sdp->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = MAX_RETRIES;
- SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ?
- SD_TIMEOUT : SD_MOD_TIMEOUT);
+ SCpnt->timeout_per_command = timeout;
/*
* This is the completion routine we use. This is matched in terms
@@ -468,16 +466,14 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
**/
static int sd_open(struct inode *inode, struct file *filp)
{
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ Scsi_Disk *sdkp = disk->private_data;
+ Scsi_Device * sdp = sdkp->device;
int retval = -ENXIO;
- Scsi_Device * sdp;
- Scsi_Disk * sdkp;
- int dsk_nr = DEVICE_NR(inode->i_rdev);
- SCSI_LOG_HLQUEUE(3, printk("sd_open: dsk_nr=%d, part_nr=%d\n",
- dsk_nr, SD_PARTITION(inode->i_rdev)));
+ SCSI_LOG_HLQUEUE(3, printk("sd_open: disk=%s\n", disk->disk_name));
- sdkp = sd_get_sdisk(dsk_nr);
- if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
+ if (!sdkp)
return -ENXIO; /* No such device */
/*
@@ -555,14 +551,12 @@ error_out:
**/
static int sd_release(struct inode *inode, struct file *filp)
{
- Scsi_Disk * sdkp;
- int dsk_nr = DEVICE_NR(inode->i_rdev);
- Scsi_Device * sdp;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ Scsi_Disk *sdkp = disk->private_data;
+ Scsi_Device *sdp = sdkp->device;
- SCSI_LOG_HLQUEUE(3, printk("sd_release: dsk_nr=%d, part_nr=%d\n",
- dsk_nr, SD_PARTITION(inode->i_rdev)));
- sdkp = sd_get_sdisk(dsk_nr);
- if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
+ SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name));
+ if (!sdp)
return -ENODEV; /* open uses ENXIO ?? */
/* ... and what if there are packets in flight and this close()
@@ -585,12 +579,12 @@ static int sd_release(struct inode *inode, struct file *filp)
static struct block_device_operations sd_fops =
{
- owner: THIS_MODULE,
- open: sd_open,
- release: sd_release,
- ioctl: sd_ioctl,
- check_media_change: check_scsidisk_media_change,
- revalidate: sd_revalidate
+ .owner = THIS_MODULE,
+ .open = sd_open,
+ .release = sd_release,
+ .ioctl = sd_ioctl,
+ .media_changed = check_scsidisk_media_change,
+ .revalidate_disk= sd_revalidate
};
/**
@@ -608,12 +602,8 @@ static void sd_rw_intr(Scsi_Cmnd * SCpnt)
sector_t block_sectors = 1;
sector_t error_sector;
#if CONFIG_SCSI_LOGGING
- char nbuff[6];
-
- SCSI_LOG_HLCOMPLETE(1, sd_dskname(DEVICE_NR(SCpnt->request->rq_dev),
- nbuff));
SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n",
- nbuff, result));
+ SCpnt->request->rq_disk->disk_name, result));
if (0 != result) {
SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[0,2,asc,ascq]"
"=%x,%x,%x,%x\n", SCpnt->sense_buffer[0],
@@ -714,21 +704,18 @@ sd_set_media_not_present(Scsi_Disk *sdkp) {
*
* Note: this function is invoked from the block subsystem.
**/
-static int check_scsidisk_media_change(kdev_t full_dev)
+static int check_scsidisk_media_change(struct gendisk *disk)
{
+ Scsi_Disk *sdkp = disk->private_data;
+ Scsi_Device *sdp = sdkp->device;
int retval;
int flag = 0; /* <<<< what is this for?? */
- Scsi_Disk * sdkp;
- Scsi_Device * sdp;
- int dsk_nr = DEVICE_NR(full_dev);
-
- sdkp = sd_get_sdisk(dsk_nr);
SCSI_LOG_HLQUEUE(3, printk("check_scsidisk_media_change: "
- "dsk_nr=%d\n", dsk_nr));
- if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) {
- printk(KERN_ERR "check_scsidisk_media_change: dsk_nr=%d, "
- "invalid device\n", dsk_nr);
+ "disk=%s\n", disk->disk_name));
+ if (!sdp) {
+ printk(KERN_ERR "check_scsidisk_media_change: disk=%s, "
+ "invalid device\n", disk->disk_name);
return 0;
}
if (!sdp->removable)
@@ -815,9 +802,7 @@ sd_spinup_disk(Scsi_Disk *sdkp, char *diskname,
while (retries < 3) {
cmd[0] = TEST_UNIT_READY;
- cmd[1] = (sdp->scsi_level <= SCSI_2) ?
- ((sdp->lun << 5) & 0xe0) : 0;
- memset((void *) &cmd[2], 0, 8);
+ memset((void *) &cmd[1], 0, 9);
SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0;
@@ -851,9 +836,7 @@ sd_spinup_disk(Scsi_Disk *sdkp, char *diskname,
printk(KERN_NOTICE "%s: Spinning up disk...",
diskname);
cmd[0] = START_STOP;
- cmd[1] = (sdp->scsi_level <= SCSI_2) ?
- ((sdp->lun << 5) & 0xe0) : 0;
- cmd[1] |= 1; /* Return immediately */
+ cmd[1] = 1; /* Return immediately */
memset((void *) &cmd[2], 0, 8);
cmd[4] = 1; /* Start spin cycle */
SRpnt->sr_cmd_len = 0;
@@ -894,7 +877,6 @@ sd_read_cache_type(Scsi_Disk *sdkp, char *diskname,
Scsi_Request *SRpnt, unsigned char *buffer) {
unsigned char cmd[10];
- Scsi_Device *sdp = sdkp->device;
int the_result, retries;
retries = 3;
@@ -902,9 +884,7 @@ sd_read_cache_type(Scsi_Disk *sdkp, char *diskname,
memset((void *) &cmd[0], 0, 10);
cmd[0] = MODE_SENSE;
- cmd[1] = (sdp->scsi_level <= SCSI_2) ?
- ((sdp->lun << 5) & 0xe0) : 0;
- cmd[1] |= 0x08; /* DBD */
+ cmd[1] = 0x08; /* DBD */
cmd[2] = 0x08; /* current values, cache page */
cmd[4] = 128; /* allocation length */
@@ -924,20 +904,29 @@ sd_read_cache_type(Scsi_Disk *sdkp, char *diskname,
} while (the_result && retries);
if (the_result) {
- printk(KERN_ERR "%s : MODE SENSE failed.\n"
- "%s : status = %x, message = %02x, host = %d, driver = %02x \n",
- diskname, diskname,
- status_byte(the_result),
- msg_byte(the_result),
- host_byte(the_result),
- driver_byte(the_result)
- );
- if (driver_byte(the_result) & DRIVER_SENSE)
- print_req_sense("sd", SRpnt);
- else
- printk(KERN_ERR "%s : sense not available. \n", diskname);
-
- printk(KERN_ERR "%s : assuming drive cache: write through\n", diskname);
+ if(status_byte(the_result) == CHECK_CONDITION
+ && (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70
+ && (SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST
+ /* The next are ASC 0x24 ASCQ 0x00: Invalid field in CDB */
+ && SRpnt->sr_sense_buffer[12] == 0x24
+ && SRpnt->sr_sense_buffer[13] == 0x00) {
+ printk(KERN_NOTICE "SCSI device %s: cache data unavailable\n", diskname);
+ } else {
+ printk(KERN_ERR "%s : MODE SENSE failed.\n"
+ "%s : status = %x, message = %02x, host = %d, driver = %02x \n",
+ diskname, diskname,
+ status_byte(the_result),
+ msg_byte(the_result),
+ host_byte(the_result),
+ driver_byte(the_result)
+ );
+ if (driver_byte(the_result) & DRIVER_SENSE)
+ print_req_sense("sd", SRpnt);
+ else
+ printk(KERN_ERR "%s : sense not available. \n", diskname);
+
+ printk(KERN_ERR "%s : assuming drive cache: write through\n", diskname);
+ }
sdkp->WCE = 0;
sdkp->RCD = 0;
} else {
@@ -968,9 +957,7 @@ sd_read_capacity(Scsi_Disk *sdkp, char *diskname,
retries = 3;
do {
cmd[0] = READ_CAPACITY;
- cmd[1] = (sdp->scsi_level <= SCSI_2) ?
- ((sdp->lun << 5) & 0xe0) : 0;
- memset((void *) &cmd[2], 0, 8);
+ memset((void *) &cmd[1], 0, 9);
memset((void *) buffer, 0, 8);
SRpnt->sr_cmd_len = 0;
@@ -1090,7 +1077,6 @@ sd_do_mode_sense6(Scsi_Device *sdp, Scsi_Request *SRpnt,
memset((void *) &cmd[0], 0, 8);
cmd[0] = MODE_SENSE;
- cmd[1] = (sdp->scsi_level <= SCSI_2) ? ((sdp->lun << 5) & 0xe0) : 0;
cmd[2] = modepage;
cmd[4] = len;
@@ -1157,18 +1143,13 @@ sd_read_write_protect_flag(Scsi_Disk *sdkp, char *diskname,
* Note: this function is local to this driver.
**/
static void
-sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) {
- char diskname[40];
+sd_init_onedisk(Scsi_Disk * sdkp, struct gendisk *disk)
+{
unsigned char *buffer;
Scsi_Device *sdp;
Scsi_Request *SRpnt;
- SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: dsk_nr=%d\n", dsk_nr));
-
- /*
- * Get the name of the disk, in case we need to log it somewhere.
- */
- sd_dskname(dsk_nr, diskname);
+ SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: disk=%s\n", disk->disk_name));
/*
* If the device is offline, don't try and read capacity or any
@@ -1198,14 +1179,14 @@ sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) {
sdkp->media_present = 1;
sdkp->write_prot = 0;
- sd_spinup_disk(sdkp, diskname, SRpnt, buffer);
- sd_read_cache_type(sdkp, diskname, SRpnt, buffer);
+ sd_spinup_disk(sdkp, disk->disk_name, SRpnt, buffer);
+ sd_read_cache_type(sdkp, disk->disk_name, SRpnt, buffer);
if (sdkp->media_present)
- sd_read_capacity(sdkp, diskname, SRpnt, buffer);
+ sd_read_capacity(sdkp, disk->disk_name, SRpnt, buffer);
if (sdp->removable && sdkp->media_present)
- sd_read_write_protect_flag(sdkp, diskname, SRpnt, buffer);
+ sd_read_write_protect_flag(sdkp, disk->disk_name, SRpnt, buffer);
SRpnt->sr_device->ten = 1;
SRpnt->sr_device->remap = 1;
@@ -1324,18 +1305,18 @@ static void sd_finish()
Scsi_Disk * sdkp;
SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n"));
- for (k = 0; k < N_USED_SD_MAJORS; k++)
- blk_dev[SD_MAJOR(k)].queue = sd_find_queue;
for (k = 0; k < sd_template.dev_max; ++k) {
sdkp = sd_get_sdisk(k);
if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
- sd_init_onedisk(sdkp, k);
- if (!sdkp->has_been_registered) {
- set_capacity(sd_disks[k], sdkp->capacity);
- add_disk(sd_disks[k]);
- sdkp->has_been_registered = 1;
- }
+ sd_init_onedisk(sdkp, sd_disks[k]);
+ if (sdkp->has_been_registered)
+ continue;
+ set_capacity(sd_disks[k], sdkp->capacity);
+ sd_disks[k]->private_data = sdkp;
+ sd_disks[k]->queue = &sdkp->device->request_queue;
+ add_disk(sd_disks[k]);
+ sdkp->has_been_registered = 1;
}
}
return;
@@ -1438,16 +1419,15 @@ static int sd_attach(Scsi_Device * sdp)
return 0;
}
-static int sd_revalidate(kdev_t dev)
+static int sd_revalidate(struct gendisk *disk)
{
- int dsk_nr = DEVICE_NR(dev);
- Scsi_Disk * sdkp = sd_get_sdisk(dsk_nr);
+ Scsi_Disk *sdkp = disk->private_data;
- if (!sdkp || !sdkp->device)
+ if (!sdkp->device)
return -ENODEV;
- sd_init_onedisk(sdkp, dsk_nr);
- set_capacity(sd_disks[dsk_nr], sdkp->capacity);
+ sd_init_onedisk(sdkp, disk);
+ set_capacity(disk, sdkp->capacity);
return 0;
}
@@ -1465,7 +1445,6 @@ static int sd_revalidate(kdev_t dev)
static void sd_detach(Scsi_Device * sdp)
{
Scsi_Disk *sdkp = NULL;
- kdev_t dev;
int dsk_nr;
unsigned long iflags;
@@ -1495,7 +1474,6 @@ static void sd_detach(Scsi_Device * sdp)
if (sdkp->has_been_registered) {
sdkp->has_been_registered = 0;
- dev = MKDEV_SD(dsk_nr);
del_gendisk(sd_disks[dsk_nr]);
}
sdp->attached--;
@@ -1546,10 +1524,8 @@ static void __exit exit_sd(void)
vfree(sd_dsk_arr[k]);
vfree(sd_dsk_arr);
}
- for (k = 0; k < N_USED_SD_MAJORS; k++)
- blk_dev[SD_MAJOR(k)].queue = NULL;
sd_template.dev_max = 0;
- remove_driver(&sd_template.scsi_driverfs_driver);
+ driver_unregister(&sd_template.scsi_driverfs_driver);
unregister_reboot_notifier(&sd_notifier_block);
}
@@ -1611,7 +1587,6 @@ static int sd_synchronize_cache(int index, int verbose)
unsigned char cmd[10] = { 0 };
cmd[0] = SYNCHRONIZE_CACHE;
- cmd[1] = SDpnt->scsi_level <= SCSI_2 ? (SDpnt->lun << 5) & 0xe0 : 0;
/* leave the rest of the command zero to indicate
* flush everything */
scsi_wait_req(SRpnt, (void *)cmd, NULL, 0,
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index ad75b842e13d..847e7c403e6c 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -40,6 +40,5 @@ extern kdev_t sd_find_target(void *host, int tgt);
#define N_SD_MAJORS 8
#define SD_MAJOR_MASK (N_SD_MAJORS - 1)
-#define SD_PARTITION(i) (((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255))
#endif
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a18bf6db8fcf..4e7682ec0565 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -705,10 +705,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
SRpnt->sr_request->rq_dev = sdp->i_rdev;
SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_cmd_len = hp->cmd_len;
- if (!(hp->flags & SG_FLAG_LUN_INHIBIT)) {
- if (sdp->device->scsi_level <= SCSI_2)
- cmnd[1] = (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
- }
SRpnt->sr_use_sg = srp->data.k_use_sg;
SRpnt->sr_sglist_len = srp->data.sglist_len;
SRpnt->sr_bufflen = srp->data.bufflen;
@@ -1659,7 +1655,7 @@ exit_sg(void)
sg_dev_arr = NULL;
}
sg_template.dev_max = 0;
- remove_driver(&sg_template.scsi_driverfs_driver);
+ driver_unregister(&sg_template.scsi_driverfs_driver);
}
static int
@@ -3103,7 +3099,8 @@ sg_proc_host_info(char *buffer, int *len, off_t * begin, off_t offset, int size)
struct Scsi_Host *shp;
int k;
- for (k = 0, shp = scsi_hostlist; shp; shp = shp->next, ++k) {
+ for (k = 0, shp = scsi_host_get_next(NULL); shp;
+ shp = scsi_host_get_next(shp), ++k) {
for (; k < shp->host_no; ++k)
PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\n");
PRINT_PROC("%u\t%hu\t%hd\t%hu\t%d\t%d\n",
@@ -3147,7 +3144,8 @@ sg_proc_hoststrs_info(char *buffer, int *len, off_t * begin,
char buff[SG_MAX_HOST_STR_LEN];
char *cp;
- for (k = 0, shp = scsi_hostlist; shp; shp = shp->next, ++k) {
+ for (k = 0, shp = scsi_host_get_next(NULL); shp;
+ shp = scsi_host_get_next(shp), ++k) {
for (; k < shp->host_no; ++k)
PRINT_PROC("<no active host>\n");
strncpy(buff, shp->hostt->info ? shp->hostt->info(shp) :
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 39af5cce16f0..56ca67c79400 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -51,7 +51,6 @@
#define MAJOR_NR SCSI_CDROM_MAJOR
#define LOCAL_END_REQUEST
-#define DEVICE_NR(device) (minor(device))
#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
@@ -196,8 +195,7 @@ static void rw_intr(Scsi_Cmnd * SCpnt)
int this_count = SCpnt->bufflen >> 9;
int good_sectors = (result == 0 ? this_count : 0);
int block_sectors = 0;
- int device_nr = DEVICE_NR(SCpnt->request->rq_dev);
- Scsi_CD *cd = &scsi_CDs[device_nr];
+ Scsi_CD *cd = SCpnt->request->rq_disk->private_data;
#ifdef DEBUG
printk("sr.c done: %x %p\n", result, SCpnt->request->bh->b_data);
@@ -247,31 +245,14 @@ static void rw_intr(Scsi_Cmnd * SCpnt)
scsi_io_completion(SCpnt, good_sectors, block_sectors);
}
-
-static request_queue_t *sr_find_queue(kdev_t dev)
-{
- Scsi_CD *cd;
-
- if (minor(dev) >= sr_template.dev_max)
- return NULL;
- cd = &scsi_CDs[minor(dev)];
- if (!cd->device)
- return NULL;
- return &cd->device->request_queue;
-}
-
static int sr_init_command(Scsi_Cmnd * SCpnt)
{
- int dev, devm, block=0, this_count, s_size;
- Scsi_CD *cd;
-
- devm = minor(SCpnt->request->rq_dev);
- dev = DEVICE_NR(SCpnt->request->rq_dev);
- cd = &scsi_CDs[dev];
+ int block=0, this_count, s_size, timeout = SR_TIMEOUT;
+ Scsi_CD *cd = SCpnt->request->rq_disk->private_data;
- SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
+ SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", disk->disk_name, block));
- if (dev >= sr_template.nr_dev || !cd->device || !cd->device->online) {
+ if (!cd->device || !cd->device->online) {
SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request->nr_sectors));
SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
return 0;
@@ -285,6 +266,30 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
return 0;
}
+ /*
+ * these are already setup, just copy cdb basically
+ */
+ if (SCpnt->request->flags & REQ_BLOCK_PC) {
+ struct request *rq = SCpnt->request;
+
+ if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
+ return 0;
+
+ memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+ if (rq_data_dir(rq) == WRITE)
+ SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+ else if (rq->data_len)
+ SCpnt->sc_data_direction = SCSI_DATA_READ;
+ else
+ SCpnt->sc_data_direction = SCSI_DATA_NONE;
+
+ this_count = rq->data_len;
+ if (rq->timeout)
+ timeout = rq->timeout;
+
+ goto queue;
+ }
+
if (!(SCpnt->request->flags & REQ_CMD)) {
blk_dump_rq_flags(SCpnt->request, "sr unsup command");
return 0;
@@ -336,9 +341,7 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
(rq_data_dir(SCpnt->request) == WRITE) ? "writing" : "reading",
this_count, SCpnt->request->nr_sectors));
- SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
- ((SCpnt->lun << 5) & 0xe0) : 0;
-
+ SCpnt->cmnd[1] = 0;
block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
if (this_count > 0xffff)
@@ -357,11 +360,12 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
* host adapter, it's safe to assume that we can at least transfer
* this many bytes between each connect / disconnect.
*/
+queue:
SCpnt->transfersize = cd->device->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = MAX_RETRIES;
- SCpnt->timeout_per_command = SR_TIMEOUT;
+ SCpnt->timeout_per_command = timeout;
/*
* This is the completion routine we use. This is matched in terms
@@ -388,13 +392,38 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
return 1;
}
+static int sr_block_open(struct inode *inode, struct file *file)
+{
+ Scsi_CD *cd = inode->i_bdev->bd_disk->private_data;
+ return cdrom_open(&cd->cdi, inode, file);
+}
+
+static int sr_block_release(struct inode *inode, struct file *file)
+{
+ Scsi_CD *cd = inode->i_bdev->bd_disk->private_data;
+ return cdrom_release(&cd->cdi, file);
+}
+
+static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ Scsi_CD *cd = inode->i_bdev->bd_disk->private_data;
+ return cdrom_ioctl(&cd->cdi, inode, cmd, arg);
+}
+
+static int sr_block_media_changed(struct gendisk *disk)
+{
+ Scsi_CD *cd = disk->private_data;
+ return cdrom_media_changed(&cd->cdi);
+}
+
struct block_device_operations sr_bdops =
{
- owner: THIS_MODULE,
- open: cdrom_open,
- release: cdrom_release,
- ioctl: cdrom_ioctl,
- check_media_change: cdrom_media_changed,
+ .owner = THIS_MODULE,
+ .open = sr_block_open,
+ .release = sr_block_release,
+ .ioctl = sr_block_ioctl,
+ .media_changed = sr_block_media_changed,
};
static int sr_open(struct cdrom_device_info *cdi, int purpose)
@@ -486,9 +515,7 @@ static void get_sectorsize(Scsi_CD *cd)
do {
cmd[0] = READ_CAPACITY;
- cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun << 5) & 0xe0) : 0;
- memset((void *) &cmd[2], 0, 8);
+ memset((void *) &cmd[1], 0, 9);
SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; /* Mark as really busy */
SRpnt->sr_cmd_len = 0;
@@ -599,8 +626,6 @@ void get_capabilities(Scsi_CD *cd)
}
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = MODE_SENSE;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun << 5) & 0xe0) : 0;
cgc.cmd[2] = 0x2a;
cgc.cmd[4] = 128;
cgc.buffer = buffer;
@@ -678,13 +703,6 @@ void get_capabilities(Scsi_CD *cd)
*/
static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
{
- Scsi_CD *cd = cdi->handle;
- Scsi_Device *device = cd->device;
-
- /* set the LUN */
- if (device->scsi_level <= SCSI_2)
- cgc->cmd[1] |= device->lun << 5;
-
if (cgc->timeout <= 0)
cgc->timeout = IOCTL_TIMEOUT;
@@ -730,8 +748,6 @@ void sr_finish()
{
int i;
- blk_dev[MAJOR_NR].queue = sr_find_queue;
-
for (i = 0; i < sr_template.nr_dev; ++i) {
struct gendisk *disk;
Scsi_CD *cd = &scsi_CDs[i];
@@ -770,7 +786,6 @@ void sr_finish()
cd->cdi.ops = &sr_dops;
cd->cdi.handle = cd;
- cd->cdi.dev = mk_kdev(MAJOR_NR, i);
cd->cdi.mask = 0;
cd->cdi.capacity = 1;
/*
@@ -783,6 +798,8 @@ void sr_finish()
disk->driverfs_dev = &cd->device->sdev_driverfs_dev;
register_cdrom(&cd->cdi);
set_capacity(disk, cd->capacity);
+ disk->private_data = cd;
+ disk->queue = &cd->device->request_queue;
add_disk(disk);
}
}
@@ -839,7 +856,7 @@ static void __exit exit_sr(void)
kfree(scsi_CDs);
sr_template.dev_max = 0;
- remove_driver(&sr_template.scsi_driverfs_driver);
+ driver_unregister(&sr_template.scsi_driverfs_driver);
}
module_init(init_sr);
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 82c0f0c52a86..c9d7c1f4c11e 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -200,8 +200,6 @@ static int test_unit_ready(Scsi_CD *cd)
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun) << 5) : 0;
cgc.quiet = 1;
cgc.data_direction = SCSI_DATA_NONE;
cgc.timeout = IOCTL_TIMEOUT;
@@ -215,8 +213,6 @@ int sr_tray_move(struct cdrom_device_info *cdi, int pos)
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = GPCMD_START_STOP_UNIT;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun) << 5) : 0;
cgc.cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
cgc.data_direction = SCSI_DATA_NONE;
cgc.timeout = IOCTL_TIMEOUT;
@@ -293,8 +289,6 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun) << 5) : 0;
cgc.cmd[2] = 0x40; /* I do want the subchannel info */
cgc.cmd[3] = 0x02; /* Give me medium catalog number info */
cgc.cmd[8] = 24;
@@ -327,8 +321,6 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun) << 5) : 0;
cgc.cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */
cgc.cmd[3] = speed & 0xff; /* LSB */
cgc.data_direction = SCSI_DATA_NONE;
@@ -361,8 +353,6 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun) << 5) : 0;
cgc.cmd[8] = 12; /* LSB of length */
cgc.buffer = buffer;
cgc.buflen = 12;
@@ -382,8 +372,6 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- ((cd->device->lun) << 5) : 0;
cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
cgc.cmd[6] = tocentry->cdte_track;
cgc.cmd[8] = 12; /* LSB of length */
@@ -411,8 +399,6 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
struct cdrom_ti* ti = (struct cdrom_ti*)arg;
cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
cgc.cmd[4] = ti->cdti_trk0;
cgc.cmd[5] = ti->cdti_ind0;
cgc.cmd[7] = ti->cdti_trk1;
@@ -463,9 +449,7 @@ static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = GPCMD_READ_CD; /* READ_CD */
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
- cgc.cmd[1] |= ((format & 7) << 2);
+ cgc.cmd[1] = ((format & 7) << 2);
cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff;
cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff;
cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff;
@@ -521,8 +505,6 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = GPCMD_READ_10;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff;
cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff;
cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff;
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 6803d45c7b26..76a701bb4502 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -124,9 +124,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
#endif
memset(&cgc, 0, sizeof(struct cdrom_generic_command));
cgc.cmd[0] = MODE_SELECT;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
- cgc.cmd[1] |= (1 << 4);
+ cgc.cmd[1] = (1 << 4);
cgc.cmd[4] = 12;
modesel = (struct ccs_modesel_head *) buffer;
memset(modesel, 0, sizeof(*modesel));
@@ -180,8 +178,6 @@ int sr_cd_check(struct cdrom_device_info *cdi)
case VENDOR_SCSI3:
cgc.cmd[0] = READ_TOC;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
cgc.cmd[8] = 12;
cgc.cmd[9] = 0x40;
cgc.buffer = buffer;
@@ -210,9 +206,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
case VENDOR_NEC:{
unsigned long min, sec, frame;
cgc.cmd[0] = 0xde;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
- cgc.cmd[1] |= 0x03;
+ cgc.cmd[1] = 0x03;
cgc.cmd[2] = 0xb0;
cgc.buffer = buffer;
cgc.buflen = 0x16;
@@ -242,9 +236,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
/* we request some disc information (is it a XA-CD ?,
* where starts the last session ?) */
cgc.cmd[0] = 0xc7;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
- cgc.cmd[1] |= 0x03;
+ cgc.cmd[1] = 0x03;
cgc.buffer = buffer;
cgc.buflen = 4;
cgc.quiet = 1;
@@ -272,8 +264,6 @@ int sr_cd_check(struct cdrom_device_info *cdi)
case VENDOR_WRITER:
cgc.cmd[0] = READ_TOC;
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
cgc.cmd[8] = 0x04;
cgc.cmd[9] = 0x40;
cgc.buffer = buffer;
@@ -291,8 +281,6 @@ int sr_cd_check(struct cdrom_device_info *cdi)
break;
}
cgc.cmd[0] = READ_TOC; /* Read TOC */
- cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
- (cd->device->lun << 5) : 0;
cgc.cmd[6] = rc & 0x7f; /* number of last session */
cgc.cmd[8] = 0x0c;
cgc.cmd[9] = 0x40;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 194077d101ba..43c05cb65e7b 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -381,8 +381,6 @@ static Scsi_Request *
}
}
- if (SRpnt->sr_device->scsi_level <= SCSI_2)
- cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
init_completion(&STp->wait);
SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
if (SRpnt->sr_use_sg) {
@@ -3994,7 +3992,7 @@ static void __exit exit_st(void)
kfree(scsi_tapes);
}
st_template.dev_max = 0;
- remove_driver(&st_template.scsi_driverfs_driver);
+ driver_unregister(&st_template.scsi_driverfs_driver);
printk(KERN_INFO "st: Unloaded.\n");
}
diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
index 4e02050bd885..2085c6fc3ed1 100644
--- a/drivers/scsi/sym53c8xx.c
+++ b/drivers/scsi/sym53c8xx.c
@@ -1279,16 +1279,6 @@ static __inline__ int scsi_data_direction(Scsi_Cmnd *cmd)
#endif /* SCSI_DATA_UNKNOWN */
-/*
-** Head of list of NCR boards
-**
-** For kernel version < 1.3.70, host is retrieved by its irq level.
-** For later kernels, the internal host control block address
-** (struct ncb) is used as device id parameter of the irq stuff.
-*/
-
-static struct Scsi_Host *first_host = NULL;
-
/*
** /proc directory entry and proc_info function
@@ -5880,11 +5870,6 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
/*
** Done.
- */
- if (!first_host)
- first_host = instance;
-
- /*
** Fill Linux host instance structure
** and return success.
*/
@@ -14228,36 +14213,30 @@ static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
printk("sym53c8xx_proc_info: hostno=%d, func=%d\n", hostno, func);
#endif
- for (host = first_host; host; host = host->next) {
- if (host->hostt != first_host->hostt)
- continue;
- if (host->host_no == hostno) {
- host_data = (struct host_data *) host->hostdata;
- ncb = host_data->ncb;
- break;
- }
- }
+ host = scsi_host_hn_get(hostno);
+ if (!host)
+ return -EINVAL;
+ host_data = (struct host_data *) host->hostdata;
+ ncb = host_data->ncb;
+ retv = -EINVAL;
if (!ncb)
- return -EINVAL;
+ goto out;
if (func) {
#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
retv = ncr_user_command(ncb, buffer, length);
-#else
- retv = -EINVAL;
#endif
- }
- else {
+ } else {
if (start)
*start = buffer;
#ifdef SCSI_NCR_USER_INFO_SUPPORT
retv = ncr_host_info(ncb, buffer, offset, length);
-#else
- retv = -EINVAL;
#endif
}
+out:
+ scsi_host_put(host);
return retv;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 685a29399965..3b096fc6eaec 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1793,16 +1793,12 @@ static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
hcb_p np = 0;
int retv;
- for (host = first_host; host; host = host->next) {
- if (host->hostt != first_host->hostt)
- continue;
- if (host->host_no == hostno) {
- host_data = (struct host_data *) host->hostdata;
- np = host_data->ncb;
- break;
- }
- }
+ host = scsi_host_hn_get(hostno);
+ if (!host)
+ return -EINVAL;
+ host_data = (struct host_data *) host->hostdata;
+ np = host_data->ncb;
if (!np)
return -EINVAL;
@@ -1823,6 +1819,7 @@ static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
#endif
}
+ scsi_host_put(host);
return retv;
}
#endif /* SYM_LINUX_PROC_INFO_SUPPORT */
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 1673571beab0..5ee05c8d2f6a 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -1871,10 +1871,7 @@ Scsi_Cmnd *cmd;
int x,i;
static int stop = 0;
- for (instance=scsi_hostlist; instance; instance=instance->next) {
- if (instance->host_no == hn)
- break;
- }
+ instance = scsi_host_hn_get(hn);
if (!instance) {
printk("*** Hmm... Can't find host #%d!\n",hn);
return (-ESRCH);
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 3d78f9ab1c7e..5c90b0057c64 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -395,7 +395,7 @@ struct usb_audio_state {
/* prevent picking up a bogus abs macro */
#undef abs
-extern inline int abs(int x)
+static inline int abs(int x)
{
if (x < 0)
return -x;
@@ -404,7 +404,7 @@ extern inline int abs(int x)
/* --------------------------------------------------------------------- */
-extern inline unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
{
unsigned r = 0;
@@ -1939,13 +1939,13 @@ static void release(struct usb_audio_state *s)
kfree(s);
}
-extern inline int prog_dmabuf_in(struct usb_audiodev *as)
+static inline int prog_dmabuf_in(struct usb_audiodev *as)
{
usbin_stop(as);
return dmabuf_init(&as->usbin.dma);
}
-extern inline int prog_dmabuf_out(struct usb_audiodev *as)
+static inline int prog_dmabuf_out(struct usb_audiodev *as)
{
usbout_stop(as);
return dmabuf_init(&as->usbout.dma);
@@ -3253,7 +3253,7 @@ static void prepmixch(struct consmixstate *state)
static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid);
-extern inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
+static inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
{
unsigned int idx;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 556dbacb7c23..e31a270ce931 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -208,7 +208,7 @@ void usb_deregister(struct usb_driver *driver)
{
info("deregistering driver %s", driver->name);
- remove_driver (&driver->driver);
+ driver_unregister (&driver->driver);
usbfs_update_special();
}
@@ -1394,7 +1394,7 @@ static void __exit usb_exit(void)
if (nousb)
return;
- remove_driver(&usb_generic_driver);
+ driver_unregister(&usb_generic_driver);
usb_major_cleanup();
usbfs_cleanup();
usb_hub_cleanup();
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 98996cd62d6e..e5b729e5ad39 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -413,7 +413,7 @@ static int __init ohci_hcd_sa1111_init (void)
static void __exit ohci_hcd_sa1111_cleanup (void)
{
- remove_driver(&ohci_hcd_sa1111_driver.drv);
+ driver_unregister(&ohci_hcd_sa1111_driver.drv);
}
module_init (ohci_hcd_sa1111_init);
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 53d5a335d832..9eb41edb4a49 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -119,6 +119,9 @@ obj-$(CONFIG_FBCON_HGA) += fbcon-hga.o
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o
+# Files generated that shall be removed upon make clean
+clean-files := promcon_tbl.c
+
include $(TOPDIR)/Rules.make
$(obj)/promcon_tbl.c: $(src)/prom.uni
diff --git a/drivers/zorro/Makefile b/drivers/zorro/Makefile
index 9bde458b4322..2131c57fccfa 100644
--- a/drivers/zorro/Makefile
+++ b/drivers/zorro/Makefile
@@ -9,6 +9,9 @@ obj-$(CONFIG_PROC_FS) += proc.o
host-progs := gen-devlist
+# Files generated that shall be removed upon make clean
+clean-files := devlist.h
+
include $(TOPDIR)/Rules.make
# Dependencies on generated files need to be listed explicitly
diff --git a/fs/Makefile b/fs/Makefile
index c28d57ab55a9..68d7074b5ae2 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_QUOTACTL) += quota.o
obj-$(CONFIG_PROC_FS) += proc/
obj-y += partitions/
-obj-y += driverfs/
+obj-y += driverfs/ sysfs/
obj-y += devpts/
obj-$(CONFIG_PROFILING) += dcookies.o
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index b95c3625257a..b3eca7db8051 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -129,11 +129,7 @@ static int kafscmd(void *arg)
/* only certain signals are of interest */
spin_lock_irq(&current->sig->siglock);
siginitsetinv(&current->blocked,0);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,3)
recalc_sigpending();
-#else
- recalc_sigpending(current);
-#endif
spin_unlock_irq(&current->sig->siglock);
/* loop around looking for things to attend to */
@@ -360,6 +356,9 @@ void afscm_stop(void)
rxrpc_call_abort(call,-ESRCH); /* abort, dequeue and put */
+ _debug("nuking active call %08x.%d",
+ ntohl(call->conn->conn_id),ntohl(call->call_id));
+ rxrpc_put_call(call);
rxrpc_put_call(call);
spin_lock(&afscm_calls_lock);
diff --git a/fs/aio.c b/fs/aio.c
index 6b51c1316ab2..da7c0a779a03 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -248,7 +248,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
write_unlock(&mm->ioctx_list_lock);
dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
- ctx, ctx->user_id, current->mm, ctx->ring_info.ring->nr);
+ ctx, ctx->user_id, current->mm, ctx->ring_info.nr);
return ctx;
out_cleanup:
@@ -281,12 +281,12 @@ static void aio_cancel_all(struct kioctx *ctx)
struct kiocb *iocb = list_kiocb(pos);
list_del_init(&iocb->ki_list);
cancel = iocb->ki_cancel;
- if (cancel)
+ if (cancel) {
iocb->ki_users++;
- spin_unlock_irq(&ctx->ctx_lock);
- if (cancel)
+ spin_unlock_irq(&ctx->ctx_lock);
cancel(iocb, &res);
- spin_lock_irq(&ctx->ctx_lock);
+ spin_lock_irq(&ctx->ctx_lock);
+ }
}
spin_unlock_irq(&ctx->ctx_lock);
}
@@ -376,7 +376,7 @@ void __put_ioctx(struct kioctx *ctx)
/* aio_get_req
* Allocate a slot for an aio request. Increments the users count
* of the kioctx so that the kioctx stays around until all requests are
- * complete. Returns -EAGAIN if no requests are free.
+ * complete. Returns NULL if no requests are free.
*/
static struct kiocb *FASTCALL(__aio_get_req(struct kioctx *ctx));
static struct kiocb *__aio_get_req(struct kioctx *ctx)
@@ -409,8 +409,6 @@ static struct kiocb *__aio_get_req(struct kioctx *ctx)
req->ki_user_obj = NULL;
req->ki_ctx = ctx;
req->ki_users = 1;
- } else {
- kmem_cache_free(kiocb_cachep, req);
okay = 1;
}
kunmap_atomic(ring, KM_USER0);
@@ -478,7 +476,7 @@ static void aio_fput_routine(void *data)
/* __aio_put_req
* Returns true if this put was the last user of the request.
*/
-static inline int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
+static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
{
dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n",
req, atomic_read(&req->ki_filp->f_count));
@@ -525,7 +523,7 @@ int aio_put_req(struct kiocb *req)
/* Lookup an ioctx id. ioctx_list is lockless for reads.
* FIXME: this is O(n) and is only suitable for development.
*/
-static inline struct kioctx *lookup_ioctx(unsigned long ctx_id)
+static struct kioctx *lookup_ioctx(unsigned long ctx_id)
{
struct kioctx *ioctx;
struct mm_struct *mm;
@@ -845,13 +843,13 @@ static int read_events(struct kioctx *ctx,
/* End fast path */
+ init_timeout(&to);
if (timeout) {
struct timespec ts;
ret = -EFAULT;
if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
goto out;
- init_timeout(&to);
set_timeout(start_jiffies, &to, &ts);
}
@@ -1197,6 +1195,9 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb *iocb,
if (NULL != cancel) {
struct io_event tmp;
printk("calling cancel\n");
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.obj = (u64)(unsigned long)kiocb->ki_user_obj;
+ tmp.data = kiocb->ki_user_data;
ret = cancel(kiocb, &tmp);
if (!ret) {
/* Cancellation succeeded -- copy the result
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1ad7f467993b..ae93c51febd5 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -527,16 +527,16 @@ int check_disk_change(struct block_device *bdev)
struct block_device_operations * bdops = bdev->bd_op;
kdev_t dev = to_kdev_t(bdev->bd_dev);
- if (bdops->check_media_change == NULL)
+ if (!bdops->media_changed)
return 0;
- if (!bdops->check_media_change(dev))
+ if (!bdops->media_changed(bdev->bd_disk))
return 0;
if (invalidate_device(dev, 0))
printk("VFS: busy inodes on changed media.\n");
- if (bdops->revalidate)
- bdops->revalidate(dev);
+ if (bdops->revalidate_disk)
+ bdops->revalidate_disk(bdev->bd_disk);
if (bdev->bd_disk->minors > 1)
bdev->bd_invalidated = 1;
return 1;
@@ -601,6 +601,13 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
if (owner)
__MOD_INC_USE_COUNT(owner);
}
+ disk = get_gendisk(bdev->bd_dev, &part);
+ if (!disk) {
+ if (owner)
+ __MOD_DEC_USE_COUNT(owner);
+ bdput(bdev);
+ return ret;
+ }
down(&bdev->bd_sem);
old = bdev->bd_op;
@@ -612,9 +619,6 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
if (owner)
__MOD_DEC_USE_COUNT(owner);
}
- disk = get_gendisk(bdev->bd_dev, &part);
- if (!disk)
- goto out1;
if (!bdev->bd_contains) {
bdev->bd_contains = bdev;
if (part) {
@@ -633,10 +637,14 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
if (!bdev->bd_openers)
bdev->bd_disk = disk;
if (!bdev->bd_queue) {
- struct blk_dev_struct *p = blk_dev + major(dev);
- bdev->bd_queue = &p->request_queue;
- if (p->queue)
- bdev->bd_queue = p->queue(dev);
+ if (disk->queue)
+ bdev->bd_queue = disk->queue;
+ else {
+ struct blk_dev_struct *p = blk_dev + major(dev);
+ bdev->bd_queue = &p->request_queue;
+ if (p->queue)
+ bdev->bd_queue = p->queue(dev);
+ }
}
if (bdev->bd_op->open) {
ret = bdev->bd_op->open(inode, file);
@@ -650,7 +658,6 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
bdi = &default_backing_dev_info;
- inode->i_data.backing_dev_info = bdi;
bdev->bd_inode->i_data.backing_dev_info = bdi;
}
if (bdev->bd_invalidated)
@@ -661,8 +668,7 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
if (!bdev->bd_openers) {
struct hd_struct *p;
p = disk->part + part - 1;
- inode->i_data.backing_dev_info =
- bdev->bd_inode->i_data.backing_dev_info =
+ bdev->bd_inode->i_data.backing_dev_info =
bdev->bd_contains->bd_inode->i_data.backing_dev_info;
if (!(disk->flags & GENHD_FL_UP) || !p->nr_sects) {
bdev->bd_contains->bd_part_count--;
@@ -685,6 +691,8 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
out2:
if (!bdev->bd_openers) {
+ bdev->bd_queue = NULL;
+ bdev->bd_disk = NULL;
bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
if (bdev != bdev->bd_contains) {
blkdev_put(bdev->bd_contains, BDEV_RAW);
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
index 0f35e27e669c..b4b5aa9f6a55 100644
--- a/fs/driverfs/inode.c
+++ b/fs/driverfs/inode.c
@@ -509,11 +509,13 @@ static void put_mount(void)
DBG("driverfs: mount_count = %d\n",mount_count);
}
-int __init init_driverfs_fs(void)
+static int __init driverfs_init(void)
{
return register_filesystem(&driverfs_fs_type);
}
+core_initcall(driverfs_init);
+
static struct dentry * get_dentry(struct dentry * parent, const char * name)
{
struct qstr qstr;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 27d57513db65..98165f99b0eb 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -289,13 +289,13 @@ static ssize_t part_start_read(struct device *dev,
char *page, size_t count, loff_t off)
{
struct hd_struct *p = dev->driver_data;
- return off ? 0 : sprintf(page, "%llu\n",(u64)p->start_sect);
+ return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
}
static ssize_t part_size_read(struct device *dev,
char *page, size_t count, loff_t off)
{
struct hd_struct *p = dev->driver_data;
- return off ? 0 : sprintf(page, "%llu\n",(u64)p->nr_sects);
+ return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
}
static struct device_attribute part_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
@@ -375,7 +375,7 @@ static ssize_t disk_size_read(struct device *dev,
char *page, size_t count, loff_t off)
{
struct gendisk *disk = dev->driver_data;
- return off ? 0 : sprintf(page, "%llu\n",(u64)get_capacity(disk));
+ return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
}
static struct device_attribute disk_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
@@ -511,8 +511,8 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
bdev->bd_invalidated = 0;
for (p = 1; p < disk->minors; p++)
delete_partition(disk, p);
- if (bdev->bd_op->revalidate)
- bdev->bd_op->revalidate(dev);
+ if (bdev->bd_op->revalidate_disk)
+ bdev->bd_op->revalidate_disk(disk);
if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
return res;
for (p = 1; p < state->limit; p++) {
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 61b0bc9bc02b..fd1e70543f46 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -28,7 +28,7 @@
#elif defined(CONFIG_BLK_DEV_IDE_MODULE)
#include <linux/module.h>
-int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
+int (*ide_xlate_1024_hook)(struct block_device *, int, int, const char *);
EXPORT_SYMBOL(ide_xlate_1024_hook);
#define ide_xlate_1024 ide_xlate_1024_hook
#endif
diff --git a/fs/read_write.c b/fs/read_write.c
index a5c0ff37d9a1..a8b23e6367ee 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -121,12 +121,6 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
if (!file)
goto bad;
- retval = security_ops->file_llseek(file);
- if (retval) {
- fput(file);
- goto bad;
- }
-
retval = -EINVAL;
if (origin <= 2) {
loff_t res = llseek(file, offset, origin);
@@ -153,10 +147,6 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
if (!file)
goto bad;
- retval = security_ops->file_llseek(file);
- if (retval)
- goto out_putf;
-
retval = -EINVAL;
if (origin > 2)
goto out_putf;
diff --git a/fs/sysfs/Makefile b/fs/sysfs/Makefile
new file mode 100644
index 000000000000..0aab3de8d9b9
--- /dev/null
+++ b/fs/sysfs/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the sysfs virtual filesystem
+#
+
+export-objs := inode.o
+
+obj-y := inode.o
+
+include $(TOPDIR)/Rules.make
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
new file mode 100644
index 000000000000..a91f47aaa378
--- /dev/null
+++ b/fs/sysfs/inode.c
@@ -0,0 +1,642 @@
+/*
+ * sysfs.c - The filesystem to export kernel objects.
+ *
+ * Copyright (c) 2001, 2002 Patrick Mochel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This is a simple, ramfs-based filesystem, designed to export kernel
+ * objects, their attributes, and the linkgaes between each other.
+ *
+ * Please see Documentation/filesystems/sysfs.txt for more information.
+ */
+
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/fs.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/backing-dev.h>
+#include <linux/sysfs.h>
+
+#include <asm/uaccess.h>
+
+/* Random magic number */
+#define SYSFS_MAGIC 0x62656572
+
+static struct super_operations sysfs_ops;
+static struct file_operations sysfs_file_operations;
+static struct inode_operations sysfs_dir_inode_operations;
+static struct address_space_operations sysfs_aops;
+
+static struct vfsmount *sysfs_mount;
+
+static struct backing_dev_info sysfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+ .memory_backed = 1, /* Does not contribute to dirty memory */
+};
+
+static int sysfs_readpage(struct file *file, struct page * page)
+{
+ if (!PageUptodate(page)) {
+ void *kaddr = kmap_atomic(page, KM_USER0);
+
+ memset(kaddr, 0, PAGE_CACHE_SIZE);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+ SetPageUptodate(page);
+ }
+ unlock_page(page);
+ return 0;
+}
+
+static int sysfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+ if (!PageUptodate(page)) {
+ void *kaddr = kmap_atomic(page, KM_USER0);
+
+ memset(kaddr, 0, PAGE_CACHE_SIZE);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+ SetPageUptodate(page);
+ }
+ return 0;
+}
+
+static int sysfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+ struct inode *inode = page->mapping->host;
+ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+
+ set_page_dirty(page);
+ if (pos > inode->i_size)
+ inode->i_size = pos;
+ return 0;
+}
+
+
+static struct inode *sysfs_get_inode(struct super_block *sb, int mode, int dev)
+{
+ struct inode *inode = new_inode(sb);
+
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_rdev = NODEV;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mapping->a_ops = &sysfs_aops;
+ inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+ switch (mode & S_IFMT) {
+ default:
+ init_special_inode(inode, mode, dev);
+ break;
+ case S_IFREG:
+ inode->i_fop = &sysfs_file_operations;
+ break;
+ case S_IFDIR:
+ inode->i_op = &sysfs_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ break;
+ case S_IFLNK:
+ inode->i_op = &page_symlink_inode_operations;
+ break;
+ }
+ }
+ return inode;
+}
+
+static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+ struct inode *inode;
+ int error = 0;
+
+ if (!dentry->d_inode) {
+ inode = sysfs_get_inode(dir->i_sb, mode, dev);
+ if (inode)
+ d_instantiate(dentry, inode);
+ else
+ error = -ENOSPC;
+ } else
+ error = -EEXIST;
+ return error;
+}
+
+static int sysfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int res;
+ mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
+ res = sysfs_mknod(dir, dentry, mode, 0);
+ if (!res)
+ dir->i_nlink++;
+ return res;
+}
+
+static int sysfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int res;
+ mode = (mode & S_IALLUGO) | S_IFREG;
+ res = sysfs_mknod(dir, dentry, mode, 0);
+ return res;
+}
+
+static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
+{
+ struct inode *inode;
+ int error = -ENOSPC;
+
+ if (dentry->d_inode)
+ return -EEXIST;
+
+ inode = sysfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+ if (inode) {
+ int l = strlen(symname)+1;
+ error = page_symlink(inode, symname, l);
+ if (!error) {
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ } else
+ iput(inode);
+ }
+ return error;
+}
+
+static inline int sysfs_positive(struct dentry *dentry)
+{
+ return (dentry->d_inode && !d_unhashed(dentry));
+}
+
+static int sysfs_empty(struct dentry *dentry)
+{
+ struct list_head *list;
+
+ spin_lock(&dcache_lock);
+
+ list_for_each(list, &dentry->d_subdirs) {
+ struct dentry *de = list_entry(list, struct dentry, d_child);
+ if (sysfs_positive(de)) {
+ spin_unlock(&dcache_lock);
+ return 0;
+ }
+ }
+
+ spin_unlock(&dcache_lock);
+ return 1;
+}
+
+static int sysfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+ down(&inode->i_sem);
+ dentry->d_inode->i_nlink--;
+ up(&inode->i_sem);
+ d_invalidate(dentry);
+ dput(dentry);
+ return 0;
+}
+
+/**
+ * sysfs_read_file - "read" data from a file.
+ * @file: file pointer
+ * @buf: buffer to fill
+ * @count: number of bytes to read
+ * @ppos: starting offset in file
+ *
+ * Userspace wants data from a file. It is up to the creator of the file to
+ * provide that data.
+ * There is a struct device_attribute embedded in file->private_data. We
+ * obtain that and check if the read callback is implemented. If so, we call
+ * it, passing the data field of the file entry.
+ * Said callback is responsible for filling the buffer and returning the number
+ * of bytes it put in it. We update @ppos correctly.
+ */
+static ssize_t
+sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ struct attribute * attr = file->f_dentry->d_fsdata;
+ struct driver_dir_entry * dir;
+ unsigned char *page;
+ ssize_t retval = 0;
+
+ dir = file->f_dentry->d_parent->d_fsdata;
+ if (!dir->ops->show)
+ return 0;
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ page = (unsigned char*)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ while (count > 0) {
+ ssize_t len;
+
+ len = dir->ops->show(dir,attr,page,count,*ppos);
+
+ if (len <= 0) {
+ if (len < 0)
+ retval = len;
+ break;
+ } else if (len > count)
+ len = count;
+
+ if (copy_to_user(buf,page,len)) {
+ retval = -EFAULT;
+ break;
+ }
+
+ *ppos += len;
+ count -= len;
+ buf += len;
+ retval += len;
+ }
+ free_page((unsigned long)page);
+ return retval;
+}
+
+/**
+ * sysfs_write_file - "write" to a file
+ * @file: file pointer
+ * @buf: data to write
+ * @count: number of bytes
+ * @ppos: starting offset
+ *
+ * Similarly to sysfs_read_file, we act essentially as a bit pipe.
+ * We check for a "write" callback in file->private_data, and pass
+ * @buffer, @count, @ppos, and the file entry's data to the callback.
+ * The number of bytes written is returned, and we handle updating
+ * @ppos properly.
+ */
+static ssize_t
+sysfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ struct attribute * attr = file->f_dentry->d_fsdata;
+ struct driver_dir_entry * dir;
+ ssize_t retval = 0;
+ char * page;
+
+ dir = file->f_dentry->d_parent->d_fsdata;
+
+ page = (char *)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ if (count >= PAGE_SIZE)
+ count = PAGE_SIZE - 1;
+ if (copy_from_user(page,buf,count))
+ goto done;
+ *(page + count) = '\0';
+
+ while (count > 0) {
+ ssize_t len;
+
+ len = dir->ops->store(dir,attr,page + retval,count,*ppos);
+
+ if (len <= 0) {
+ if (len < 0)
+ retval = len;
+ break;
+ }
+ retval += len;
+ count -= len;
+ *ppos += len;
+ buf += len;
+ }
+ done:
+ free_page((unsigned long)page);
+ return retval;
+}
+
+static loff_t
+sysfs_file_lseek(struct file *file, loff_t offset, int orig)
+{
+ loff_t retval = -EINVAL;
+
+ down(&file->f_dentry->d_inode->i_sem);
+ switch(orig) {
+ case 0:
+ if (offset > 0) {
+ file->f_pos = offset;
+ retval = file->f_pos;
+ }
+ break;
+ case 1:
+ if ((offset + file->f_pos) > 0) {
+ file->f_pos += offset;
+ retval = file->f_pos;
+ }
+ break;
+ default:
+ break;
+ }
+ up(&file->f_dentry->d_inode->i_sem);
+ return retval;
+}
+
+static int sysfs_open_file(struct inode * inode, struct file * filp)
+{
+ struct driver_dir_entry * dir;
+ int error = 0;
+
+ dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
+ if (dir) {
+ struct attribute * attr = filp->f_dentry->d_fsdata;
+ if (attr && dir->ops) {
+ if (dir->ops->open)
+ error = dir->ops->open(dir);
+ goto Done;
+ }
+ }
+ error = -EINVAL;
+ Done:
+ return error;
+}
+
+static int sysfs_release(struct inode * inode, struct file * filp)
+{
+ struct driver_dir_entry * dir;
+ dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
+ if (dir->ops->close)
+ dir->ops->close(dir);
+ return 0;
+}
+
+static struct file_operations sysfs_file_operations = {
+ .read = sysfs_read_file,
+ .write = sysfs_write_file,
+ .llseek = sysfs_file_lseek,
+ .open = sysfs_open_file,
+ .release = sysfs_release,
+};
+
+static struct inode_operations sysfs_dir_inode_operations = {
+ .lookup = simple_lookup,
+};
+
+static struct address_space_operations sysfs_aops = {
+ .readpage = sysfs_readpage,
+ .writepage = fail_writepage,
+ .prepare_write = sysfs_prepare_write,
+ .commit_write = sysfs_commit_write
+};
+
+static struct super_operations sysfs_ops = {
+ .statfs = simple_statfs,
+ .drop_inode = generic_delete_inode,
+};
+
+static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+ struct inode *inode;
+ struct dentry *root;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = SYSFS_MAGIC;
+ sb->s_op = &sysfs_ops;
+ inode = sysfs_get_inode(sb, S_IFDIR | 0755, 0);
+
+ if (!inode) {
+ pr_debug("%s: could not get inode!\n",__FUNCTION__);
+ return -ENOMEM;
+ }
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
+ iput(inode);
+ return -ENOMEM;
+ }
+ sb->s_root = root;
+ return 0;
+}
+
+static struct super_block *sysfs_get_sb(struct file_system_type *fs_type,
+ int flags, char *dev_name, void *data)
+{
+ return get_sb_single(fs_type, flags, data, sysfs_fill_super);
+}
+
+static struct file_system_type sysfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "sysfs",
+ .get_sb = sysfs_get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+static int __init sysfs_init(void)
+{
+ int err;
+
+ err = register_filesystem(&sysfs_fs_type);
+ if (!err) {
+ sysfs_mount = kern_mount(&sysfs_fs_type);
+ if (IS_ERR(sysfs_mount)) {
+ printk(KERN_ERR "sysfs: could not mount!\n");
+ err = PTR_ERR(sysfs_mount);
+ sysfs_mount = NULL;
+ }
+ }
+ return err;
+}
+
+core_initcall(sysfs_init);
+
+static struct dentry * get_dentry(struct dentry * parent, const char * name)
+{
+ struct qstr qstr;
+
+ qstr.name = name;
+ qstr.len = strlen(name);
+ qstr.hash = full_name_hash(name,qstr.len);
+ return lookup_hash(&qstr,parent);
+}
+
+/**
+ * sysfs_create_dir - create a directory in the filesystem
+ * @entry: directory entry
+ * @parent: parent directory entry
+ */
+int
+sysfs_create_dir(struct driver_dir_entry * entry,
+ struct driver_dir_entry * parent)
+{
+ struct dentry * dentry = NULL;
+ struct dentry * parent_dentry;
+ int error = 0;
+
+ if (!entry)
+ return -EINVAL;
+
+ parent_dentry = parent ? parent->dentry : NULL;
+
+ if (!parent_dentry)
+ if (sysfs_mount && sysfs_mount->mnt_sb)
+ parent_dentry = sysfs_mount->mnt_sb->s_root;
+
+ if (!parent_dentry)
+ return -EFAULT;
+
+ down(&parent_dentry->d_inode->i_sem);
+ dentry = get_dentry(parent_dentry,entry->name);
+ if (!IS_ERR(dentry)) {
+ dentry->d_fsdata = (void *) entry;
+ entry->dentry = dentry;
+ error = sysfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
+ } else
+ error = PTR_ERR(dentry);
+ up(&parent_dentry->d_inode->i_sem);
+
+ return error;
+}
+
+/**
+ * sysfs_create_file - create a file
+ * @entry: structure describing the file
+ * @parent: directory to create it in
+ */
+int
+sysfs_create_file(struct attribute * entry,
+ struct driver_dir_entry * parent)
+{
+ struct dentry * dentry;
+ int error = 0;
+
+ if (!entry || !parent)
+ return -EINVAL;
+
+ if (!parent->dentry)
+ return -EINVAL;
+
+ down(&parent->dentry->d_inode->i_sem);
+ dentry = get_dentry(parent->dentry,entry->name);
+ if (!IS_ERR(dentry)) {
+ dentry->d_fsdata = (void *)entry;
+ error = sysfs_create(parent->dentry->d_inode,dentry,entry->mode);
+ } else
+ error = PTR_ERR(dentry);
+ up(&parent->dentry->d_inode->i_sem);
+ return error;
+}
+
+/**
+ * sysfs_create_symlink - make a symlink
+ * @parent: directory we're creating in
+ * @entry: entry describing link
+ * @target: place we're symlinking to
+ *
+ */
+int sysfs_create_symlink(struct driver_dir_entry * parent,
+ char * name, char * target)
+{
+ struct dentry * dentry;
+ int error = 0;
+
+ if (!parent || !parent->dentry)
+ return -EINVAL;
+
+ down(&parent->dentry->d_inode->i_sem);
+ dentry = get_dentry(parent->dentry,name);
+ if (!IS_ERR(dentry))
+ error = sysfs_symlink(parent->dentry->d_inode,dentry,target);
+ else
+ error = PTR_ERR(dentry);
+ up(&parent->dentry->d_inode->i_sem);
+ return error;
+}
+
+/**
+ * sysfs_remove_file - exported file removal
+ * @dir: directory the file supposedly resides in
+ * @name: name of the file
+ *
+ * Try and find the file in the dir's list.
+ * If it's there, call __remove_file() (above) for the dentry.
+ */
+void sysfs_remove_file(struct driver_dir_entry * dir, const char * name)
+{
+ struct dentry * dentry;
+
+ if (!dir->dentry)
+ return;
+
+ down(&dir->dentry->d_inode->i_sem);
+ dentry = get_dentry(dir->dentry,name);
+ if (!IS_ERR(dentry)) {
+ /* make sure dentry is really there */
+ if (dentry->d_inode &&
+ (dentry->d_parent->d_inode == dir->dentry->d_inode)) {
+ sysfs_unlink(dir->dentry->d_inode,dentry);
+ }
+ }
+ up(&dir->dentry->d_inode->i_sem);
+}
+
+/**
+ * sysfs_remove_dir - exportable directory removal
+ * @dir: directory to remove
+ *
+ * To make sure we don't orphan anyone, first remove
+ * all the children in the list, then do clean up the directory.
+ */
+void sysfs_remove_dir(struct driver_dir_entry * dir)
+{
+ struct list_head * node, * next;
+ struct dentry * dentry = dir->dentry;
+ struct dentry * parent;
+
+ if (!dentry)
+ return;
+
+ parent = dget(dentry->d_parent);
+ down(&parent->d_inode->i_sem);
+ down(&dentry->d_inode->i_sem);
+
+ list_for_each_safe(node,next,&dentry->d_subdirs) {
+ struct dentry * d = list_entry(node,struct dentry,d_child);
+ /* make sure dentry is still there */
+ if (d->d_inode)
+ sysfs_unlink(dentry->d_inode,d);
+ }
+
+ d_invalidate(dentry);
+ if (sysfs_empty(dentry)) {
+ dentry->d_inode->i_nlink -= 2;
+ dentry->d_inode->i_flags |= S_DEAD;
+ parent->d_inode->i_nlink--;
+ }
+ up(&dentry->d_inode->i_sem);
+ dput(dentry);
+
+ up(&parent->d_inode->i_sem);
+ dput(parent);
+}
+
+EXPORT_SYMBOL(sysfs_create_file);
+EXPORT_SYMBOL(sysfs_create_symlink);
+EXPORT_SYMBOL(sysfs_create_dir);
+EXPORT_SYMBOL(sysfs_remove_file);
+EXPORT_SYMBOL(sysfs_remove_dir);
+MODULE_LICENSE("GPL");
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index d337420fdeaf..7c15037a9dac 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -32,7 +32,8 @@
# Makefile for XFS on Linux.
#
-# This needs -I because everything does #include <xfs.h> instead of "xfs.h".
+
+# This needs -I. because everything does #include <xfs.h> instead of "xfs.h".
# The code is wrong, local files should be included using "xfs.h", not <xfs.h>
# but I am not going to change every file at the moment.
EXTRA_CFLAGS += -Ifs/xfs -funsigned-char
diff --git a/fs/xfs/linux/xfs_file.c b/fs/xfs/linux/xfs_file.c
index c292bfc9f119..2776290d7020 100644
--- a/fs/xfs/linux/xfs_file.c
+++ b/fs/xfs/linux/xfs_file.c
@@ -113,6 +113,32 @@ linvfs_write(
}
+STATIC ssize_t
+linvfs_aio_read(
+ struct kiocb *iocb,
+ char *buf,
+ size_t count,
+ loff_t pos)
+{
+ struct iovec iov = {buf, count};
+
+ return linvfs_readv(iocb->ki_filp, &iov, 1, &iocb->ki_pos);
+}
+
+
+STATIC ssize_t
+linvfs_aio_write(
+ struct kiocb *iocb,
+ const char *buf,
+ size_t count,
+ loff_t pos)
+{
+ struct iovec iov = {(void *)buf, count};
+
+ return linvfs_writev(iocb->ki_filp, &iov, 1, &iocb->ki_pos);
+}
+
+
STATIC int
linvfs_open(
struct inode *inode,
@@ -320,6 +346,8 @@ struct file_operations linvfs_file_operations = {
.write = linvfs_write,
.readv = linvfs_readv,
.writev = linvfs_writev,
+ .aio_read = linvfs_aio_read,
+ .aio_write = linvfs_aio_write,
.ioctl = linvfs_ioctl,
.mmap = linvfs_file_mmap,
.open = linvfs_open,
diff --git a/fs/xfs/linux/xfs_globals.c b/fs/xfs/linux/xfs_globals.c
index 7f0ac30a83ba..94105d5fb14f 100644
--- a/fs/xfs/linux/xfs_globals.c
+++ b/fs/xfs/linux/xfs_globals.c
@@ -64,5 +64,6 @@ EXPORT_SYMBOL(xfs_Gqm);
EXPORT_SYMBOL(xfs_next_bit);
EXPORT_SYMBOL(xfs_contig_bits);
EXPORT_SYMBOL(xfs_bmbt_get_all);
+#if ARCH_CONVERT != ARCH_NOCONVERT
EXPORT_SYMBOL(xfs_bmbt_disk_get_all);
-
+#endif
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 5c89a956c866..5dc29c28dbaf 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2135,19 +2135,6 @@ xfs_alloc_put_freelist(
(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
sizeof(xfs_agblock_t) - 1));
- /*
- * Since blocks move to the free list without the coordination
- * used in xfs_bmap_finish, we can't allow block to be available
- * for reallocation and non-transaction writing (user data)
- * until we know that the transaction that moved it to the free
- * list is permanently on disk. We track the blocks by declaring
- * these blocks as "busy"; the busy list is maintained on a per-ag
- * basis and each transaction records which entries should be removed
- * when the iclog commits to disk. If a busy block is allocated,
- * the iclog is pushed up to the LSN that freed the block.
- */
- xfs_alloc_mark_busy(tp, INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
-
return 0;
}
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 9bb3fe79243d..6ea6af923d2b 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -223,6 +223,23 @@ xfs_alloc_delrec(
if ((error = xfs_alloc_put_freelist(cur->bc_tp,
cur->bc_private.a.agbp, NULL, bno)))
return error;
+ /*
+ * Since blocks move to the free list without the
+ * coordination used in xfs_bmap_finish, we can't allow
+ * block to be available for reallocation and
+ * non-transaction writing (user data) until we know
+ * that the transaction that moved it to the free list
+ * is permanently on disk. We track the blocks by
+ * declaring these blocks as "busy"; the busy list is
+ * maintained on a per-ag basis and each transaction
+ * records which entries should be removed when the
+ * iclog commits to disk. If a busy block is
+ * allocated, the iclog is pushed up to the LSN
+ * that freed the block.
+ */
+ xfs_alloc_mark_busy(cur->bc_tp,
+ INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
+
xfs_trans_agbtree_delta(cur->bc_tp, -1);
xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
XFS_AGF_ROOTS | XFS_AGF_LEVELS);
@@ -528,6 +545,21 @@ xfs_alloc_delrec(
if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
NULL, rbno)))
return error;
+ /*
+ * Since blocks move to the free list without the coordination
+ * used in xfs_bmap_finish, we can't allow block to be available
+ * for reallocation and non-transaction writing (user data)
+ * until we know that the transaction that moved it to the free
+ * list is permanently on disk. We track the blocks by declaring
+ * these blocks as "busy"; the busy list is maintained on a
+ * per-ag basis and each transaction records which entries
+ * should be removed when the iclog commits to disk. If a
+ * busy block is allocated, the iclog is pushed up to the
+ * LSN that freed the block.
+ */
+ xfs_alloc_mark_busy(cur->bc_tp,
+ INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
+
xfs_trans_agbtree_delta(cur->bc_tp, -1);
/*
* Adjust the current level's cursor so that we're left referring
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 07d513d24f74..47e5dec6e688 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -253,11 +253,7 @@ xfs_bmbt_trace_cursor(
xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
cur->bc_private.b.allocated,
-#if BMBT_USE_64
INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
-#else
- INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT), INT_GET(r.l2, ARCH_CONVERT), INT_GET(r.l3, ARCH_CONVERT),
-#endif
(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 8aeefd43c967..1b8aa70f480f 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -658,8 +658,8 @@ xfs_bmbt_disk_set_allf(
#else
#define xfs_bmbt_disk_set_all(r, s) \
xfs_bmbt_set_all(r, s)
-#define xfs_bmbt_disk_set_allf(r, 0, b, c, v) \
- xfs_bmbt_set_allf(r, 0, b, c, v)
+#define xfs_bmbt_disk_set_allf(r, o, b, c, v) \
+ xfs_bmbt_set_allf(r, o, b, c, v)
#endif
void
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index bd343063b60d..45acdc3999c9 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -602,9 +602,12 @@ xfs_iformat_extents(
int whichfork)
{
xfs_ifork_t *ifp;
- int nex, i;
+ int nex;
int real_size;
int size;
+#if ARCH_CONVERT != ARCH_NOCONVERT
+ int i;
+#endif
xfs_bmbt_rec_t *ep, *dp;
ifp = XFS_IFORK_PTR(ip, whichfork);
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index 4970205a5e69..c893dbfc9d37 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -126,7 +126,7 @@ typedef struct xfs_inode_log_format_v1 {
#ifdef __KERNEL__
struct xfs_buf;
-struct xfs_bmbt_rec_32;
+struct xfs_bmbt_rec_64;
struct xfs_inode;
struct xfs_mount;
@@ -141,9 +141,9 @@ typedef struct xfs_inode_log_item {
unsigned short ili_flags; /* misc flags */
unsigned short ili_logged; /* flushed logged data */
unsigned int ili_last_fields; /* fields when flushed */
- struct xfs_bmbt_rec_32 *ili_extents_buf; /* array of logged
+ struct xfs_bmbt_rec_64 *ili_extents_buf; /* array of logged
data exts */
- struct xfs_bmbt_rec_32 *ili_aextents_buf; /* array of logged
+ struct xfs_bmbt_rec_64 *ili_aextents_buf; /* array of logged
attr exts */
unsigned int ili_pushbuf_flag; /* one bit used in push_ail */
diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
index 865d995c4312..e26ea03e7347 100644
--- a/include/asm-i386/io_apic.h
+++ b/include/asm-i386/io_apic.h
@@ -22,9 +22,12 @@
* The structure of the IO-APIC:
*/
struct IO_APIC_reg_00 {
- __u32 __reserved_2 : 24,
+ __u32 __reserved_2 : 14,
+ LTS : 1,
+ delivery_type : 1,
+ __reserved_1 : 8,
ID : 4,
- __reserved_1 : 4;
+ __reserved_0 : 4;
} __attribute__ ((packed));
struct IO_APIC_reg_01 {
diff --git a/include/asm-ppc/div64.h b/include/asm-ppc/div64.h
index 114e6ab34147..ec3ae5bcb3de 100644
--- a/include/asm-ppc/div64.h
+++ b/include/asm-ppc/div64.h
@@ -1,10 +1,23 @@
#ifndef __PPC_DIV64
#define __PPC_DIV64
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
+#include <linux/types.h>
+
+extern u32 __div64_32(u64 *dividend, u32 div);
+
+#define do_div(n, div) ({ \
+ u64 __n = (n); \
+ u32 __d = (div); \
+ u32 __q, __r; \
+ if ((__n >> 32) == 0) { \
+ __q = (u32)__n / __d; \
+ __r = (u32)__n - __q * __d; \
+ (n) = __q; \
+ } else { \
+ __r = __div64_32(&__n, __d); \
+ (n) = __n; \
+ } \
+ __r; \
+})
#endif
diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
index 1d7bec303e02..f17cca329ed9 100644
--- a/include/asm-ppc/pci-bridge.h
+++ b/include/asm-ppc/pci-bridge.h
@@ -68,6 +68,11 @@ struct pci_controller {
struct pci_ops *ops;
volatile unsigned int *cfg_addr;
volatile unsigned char *cfg_data;
+ /*
+ * If set, indirect method will set the cfg_type bit as
+ * needed to generate type 1 configuration transactions.
+ */
+ int set_cfg_type;
/* Currently, we limit ourselves to 1 IO range and 3 mem
* ranges since the common pci_bus structure can't handle more
diff --git a/include/asm-ppc/sections.h b/include/asm-ppc/sections.h
index 1f2f5fd05966..564e1e58f141 100644
--- a/include/asm-ppc/sections.h
+++ b/include/asm-ppc/sections.h
@@ -2,27 +2,27 @@
#ifndef _PPC_SECTIONS_H
#define _PPC_SECTIONS_H
-#define __pmac __attribute__ ((__section__ (".text.pmac")))
-#define __pmacdata __attribute__ ((__section__ (".data.pmac")))
+#define __pmac __attribute__ ((__section__ (".pmac.text")))
+#define __pmacdata __attribute__ ((__section__ (".pmac.data")))
#define __pmacfunc(__argpmac) \
__argpmac __pmac; \
__argpmac
-#define __prep __attribute__ ((__section__ (".text.prep")))
-#define __prepdata __attribute__ ((__section__ (".data.prep")))
+#define __prep __attribute__ ((__section__ (".prep.text")))
+#define __prepdata __attribute__ ((__section__ (".prep.data")))
#define __prepfunc(__argprep) \
__argprep __prep; \
__argprep
-#define __chrp __attribute__ ((__section__ (".text.chrp")))
-#define __chrpdata __attribute__ ((__section__ (".data.chrp")))
+#define __chrp __attribute__ ((__section__ (".chrp.text")))
+#define __chrpdata __attribute__ ((__section__ (".chrp.data")))
#define __chrpfunc(__argchrp) \
__argchrp __chrp; \
__argchrp
/* this is actually just common chrp/pmac code, not OF code -- Cort */
-#define __openfirmware __attribute__ ((__section__ (".text.openfirmware")))
-#define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware")))
+#define __openfirmware __attribute__ ((__section__ (".openfirmware.text")))
+#define __openfirmwaredata __attribute__ ((__section__ (".openfirmware.data")))
#define __openfirmwarefunc(__argopenfirmware) \
__argopenfirmware __openfirmware; \
__argopenfirmware
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
index 58a305b6b0c7..8cbe28a3dc91 100644
--- a/include/asm-ppc/system.h
+++ b/include/asm-ppc/system.h
@@ -119,14 +119,14 @@ extern void __xchg_called_with_bad_pointer(void);
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr) (xchg((ptr),1))
-static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
{
switch (size) {
case 4:
- return (unsigned long )xchg_u32(ptr, x);
+ return (unsigned long) xchg_u32(ptr, x);
#if 0 /* xchg_u64 doesn't exist on 32-bit PPC */
case 8:
- return (unsigned long )xchg_u64(ptr, x);
+ return (unsigned long) xchg_u64(ptr, x);
#endif /* 0 */
}
__xchg_called_with_bad_pointer();
diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
index ff3bd04a3253..53d4136efb91 100644
--- a/include/asm-sparc/ptrace.h
+++ b/include/asm-sparc/ptrace.h
@@ -73,7 +73,12 @@ extern void show_regs(struct pt_regs *);
#define REGWIN_SZ 0x40
#endif
-#include <asm/asm_offsets.h>
+/*
+ * The asm_offsets.h is a generated file, so we cannot include it.
+ * It may be OK for glibc headers, but it's utterly pointless for C code.
+ * The assembly code using those offsets has to include it explicitly.
+ */
+/* #include <asm/asm_offsets.h> */
/* These are for pt_regs. */
#define PT_PSR 0x0
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ccb56d58de6a..42e81a4a0cab 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -235,6 +235,7 @@ struct request_queue
#define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
#define blk_queue_empty(q) elv_queue_empty(q)
#define blk_fs_request(rq) ((rq)->flags & REQ_CMD)
+#define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC)
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
#define rq_data_dir(rq) ((rq)->flags & 1)
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 4387203c95b7..7ac3926382f8 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -731,7 +731,6 @@ struct cdrom_device_info {
struct cdrom_device_info *next; /* next device_info for this major */
void *handle; /* driver-dependent data */
/* specifications */
- kdev_t dev; /* device number */
int mask; /* mask of capability: disables them */
int speed; /* maximum speed for reading data */
int capacity; /* number of discs in jukebox */
@@ -776,10 +775,10 @@ struct cdrom_device_ops {
};
/* the general block_device operations structure: */
-extern int cdrom_open(struct inode *, struct file *);
-extern int cdrom_release(struct inode *, struct file *);
-extern int cdrom_ioctl(struct inode *, struct file *, unsigned, unsigned long);
-extern int cdrom_media_changed(kdev_t);
+extern int cdrom_open(struct cdrom_device_info *, struct inode *, struct file *);
+extern int cdrom_release(struct cdrom_device_info *, struct file *);
+extern int cdrom_ioctl(struct cdrom_device_info *, struct inode *, unsigned, unsigned long);
+extern int cdrom_media_changed(struct cdrom_device_info *);
extern int register_cdrom(struct cdrom_device_info *cdi);
extern int unregister_cdrom(struct cdrom_device_info *cdi);
diff --git a/include/linux/device.h b/include/linux/device.h
index 80a63939f924..3dd9a4081298 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -48,14 +48,22 @@ enum {
RESUME_ENABLE,
};
+enum device_state {
+ DEVICE_UNINITIALIZED = 0,
+ DEVICE_INITIALIZED = 1,
+ DEVICE_REGISTERED = 2,
+ DEVICE_GONE = 3,
+};
+
struct device;
struct device_driver;
struct device_class;
struct bus_type {
char * name;
- rwlock_t lock;
+ struct rw_semaphore rwsem;
atomic_t refcount;
+ u32 present;
struct list_head node;
struct list_head devices;
@@ -73,14 +81,9 @@ struct bus_type {
extern int bus_register(struct bus_type * bus);
+extern void bus_unregister(struct bus_type * bus);
-static inline struct bus_type * get_bus(struct bus_type * bus)
-{
- BUG_ON(!atomic_read(&bus->refcount));
- atomic_inc(&bus->refcount);
- return bus;
-}
-
+extern struct bus_type * get_bus(struct bus_type * bus);
extern void put_bus(struct bus_type * bus);
extern int bus_for_each_dev(struct bus_type * bus, void * data,
@@ -114,6 +117,7 @@ struct device_driver {
rwlock_t lock;
atomic_t refcount;
+ u32 present;
struct list_head bus_list;
struct list_head class_list;
@@ -123,7 +127,7 @@ struct device_driver {
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
-
+ void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev, u32 state, u32 level);
int (*resume) (struct device * dev, u32 level);
@@ -131,16 +135,10 @@ struct device_driver {
};
-
extern int driver_register(struct device_driver * drv);
+extern void driver_unregister(struct device_driver * drv);
-static inline struct device_driver * get_driver(struct device_driver * drv)
-{
- BUG_ON(!atomic_read(&drv->refcount));
- atomic_inc(&drv->refcount);
- return drv;
-}
-
+extern struct device_driver * get_driver(struct device_driver * drv);
extern void put_driver(struct device_driver * drv);
extern void remove_driver(struct device_driver * drv);
@@ -172,6 +170,11 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
*/
struct device_class {
char * name;
+ struct rw_semaphore rwsem;
+
+ atomic_t refcount;
+ u32 present;
+
u32 devnum;
struct list_head node;
@@ -189,6 +192,9 @@ struct device_class {
extern int devclass_register(struct device_class *);
extern void devclass_unregister(struct device_class *);
+extern struct device_class * get_devclass(struct device_class *);
+extern void put_devclass(struct device_class *);
+
struct devclass_attribute {
struct attribute attr;
@@ -289,8 +295,8 @@ struct device {
void *platform_data; /* Platform specific data (e.g. ACPI,
BIOS data relevant to device) */
- u32 present;
- u32 current_state; /* Current operating state. In
+ enum device_state state;
+ u32 power_state; /* Current operating state. In
ACPI-speak, this is D0-D3, D0
being fully functional, and D3
being off. */
@@ -362,6 +368,11 @@ extern int (*platform_notify)(struct device * dev);
extern int (*platform_notify_remove)(struct device * dev);
+static inline int device_present(struct device * dev)
+{
+ return (dev && (dev->state == DEVICE_INITIALIZED || dev->state == DEVICE_REGISTERED));
+}
+
/* device and bus locking helpers.
*
* FIXME: Is there anything else we need to do?
diff --git a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h
index d859f8c2e041..b4270e947a1e 100644
--- a/include/linux/driverfs_fs.h
+++ b/include/linux/driverfs_fs.h
@@ -65,6 +65,4 @@ driverfs_create_symlink(struct driver_dir_entry * parent,
extern void
driverfs_remove_file(struct driver_dir_entry *, const char * name);
-extern int init_driverfs_fs(void);
-
#endif /* _DDFS_H_ */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index bca164f4265a..c2e39a247227 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -730,8 +730,8 @@ struct block_device_operations {
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
- int (*check_media_change) (kdev_t);
- int (*revalidate) (kdev_t);
+ int (*media_changed) (struct gendisk *);
+ int (*revalidate_disk) (struct gendisk *);
struct module *owner;
};
@@ -1251,7 +1251,8 @@ extern ssize_t do_sync_write(struct file *filp, const char *buf, size_t len, lof
ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos);
extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t);
-extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
+extern void do_generic_mapping_read(struct address_space *, struct file_ra_state *, struct file *,
+ loff_t *, read_descriptor_t *, read_actor_t);
extern ssize_t generic_file_direct_IO(int rw, struct file *file,
const struct iovec *iov, loff_t offset, unsigned long nr_segs);
extern int generic_direct_IO(int rw, struct inode *inode, const struct iovec
@@ -1268,6 +1269,18 @@ extern int generic_file_open(struct inode * inode, struct file * filp);
extern int generic_vm_writeback(struct page *page,
struct writeback_control *wbc);
+static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
+ read_descriptor_t * desc,
+ read_actor_t actor)
+{
+ do_generic_mapping_read(filp->f_dentry->d_inode->i_mapping,
+ &filp->f_ra,
+ filp,
+ ppos,
+ desc,
+ actor);
+}
+
extern struct file_operations generic_ro_fops;
extern int vfs_readlink(struct dentry *, char *, int, const char *);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 9de2f51ae935..8cd8a826bf6f 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -80,6 +80,8 @@ struct gendisk {
char disk_name[16]; /* name of major driver */
struct hd_struct *part; /* [indexed by minor] */
struct block_device_operations *fops;
+ struct request_queue *queue;
+ void *private_data;
sector_t capacity;
struct list_head list;
struct list_head full_list;
@@ -273,8 +275,12 @@ extern struct gendisk *alloc_disk(int minors);
extern struct gendisk *get_disk(struct gendisk *disk);
extern void put_disk(struct gendisk *disk);
-/* will go away */
-extern void blk_set_probe(int major, struct gendisk *(p)(int));
+extern void blk_register_region(dev_t dev, unsigned long range,
+ struct module *module,
+ struct gendisk *(*probe)(dev_t, int *, void *),
+ void (*lock)(dev_t, void *),
+ void *data);
+extern void blk_unregister_region(dev_t dev, unsigned long range);
#endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 44cb38c00b96..607464f740f5 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1256,7 +1256,6 @@ extern int noautodma;
*/
#define IDE_DRIVER /* Toggle some magic bits in blk.h */
#define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */
-#define DEVICE_NR(device) (minor(device) >> PARTN_BITS)
#include <linux/blk.h>
extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
@@ -1316,12 +1315,7 @@ extern int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long
* This routine is called from the partition-table code in genhd.c
* to "convert" a drive to a logical geometry with fewer than 1024 cyls.
*/
-extern int ide_xlate_1024 (kdev_t, int, int, const char *);
-
-/*
- * Convert kdev_t structure into ide_drive_t * one.
- */
-extern ide_drive_t *get_info_ptr (kdev_t i_rdev);
+extern int ide_xlate_1024(struct block_device *, int, int, const char *);
/*
* Return the current idea about the total capacity of this drive.
@@ -1577,11 +1571,6 @@ extern int ide_system_bus_speed(void);
extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-extern request_queue_t *ide_get_queue (kdev_t dev);
-
-/*
* CompactFlash cards and their brethern pretend to be removable hard disks,
* but they never have a slave unit, and they don't have doorlock mechanisms.
* This test catches them, and is invoked elsewhere when setting appropriate
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 8203314e2cb7..0d0ce25b333e 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -338,16 +338,35 @@ typedef struct isdn_net_local_s {
/* phone[0] = Incoming Numbers */
/* phone[1] = Outgoing Numbers */
- struct list_head slaves; /* list of all bundled channels */
- struct list_head online; /* list of all bundled channels,
- which are currently online */
- spinlock_t online_lock; /* lock to protect online list */
+ struct list_head slaves; /* list of all bundled channels
+ protected by serializing config
+ ioctls / no change allowed when
+ interface is running */
+ struct list_head online; /* list of all bundled channels
+ which can be used for actual
+ data (IP) transfer
+ protected by xmit_lock */
+
+ spinlock_t xmit_lock; /* used to protect the xmit path of
+ a net_device, including all
+ associated channels's frame_cnt */
struct list_head running_devs; /* member of global running_devs */
atomic_t refcnt; /* references held by ISDN code */
#ifdef CONFIG_ISDN_X25
struct concap_device_ops *dops; /* callbacks used by encapsulator */
#endif
+#ifdef CONFIG_ISDN_PPP
+ unsigned int mpppcfg;
+ long mp_seqno;
+ struct ippp_ccp *ccp;
+ unsigned long debug;
+#ifdef CONFIG_ISDN_PPP_VJ
+ unsigned char *cbuf;
+ struct slcompress *slcomp;
+#endif
+#endif
+
/* use an own struct for that in later versions */
ulong cisco_myseq; /* Local keepalive seq. for Cisco */
ulong cisco_mineseen; /* returned keepalive seq. from remote */
@@ -391,14 +410,11 @@ typedef struct isdn_net_dev_s {
int chargeint; /* Interval between charge-infos */
int pppbind; /* ippp device for bindings */
- int ppp_slot; /* PPPD device slot number */
+ struct ipppd *ipppd; /* /dev/ipppX which controls us */
- spinlock_t xmit_lock; /* used to protect the xmit path of */
- /* a particular channel (including */
- /* the frame_cnt */
struct sk_buff_head super_tx_queue; /* List of supervisory frames to */
/* be transmitted asap */
- atomic_t frame_cnt; /* number of frames currently */
+ int frame_cnt; /* number of frames currently */
/* queued in HL driver */
struct tasklet_struct tlet;
@@ -410,6 +426,11 @@ typedef struct isdn_net_dev_s {
char name[10]; /* Name of device */
struct list_head global_list; /* global list of all isdn_net_devs */
#ifdef CONFIG_ISDN_PPP
+ unsigned int pppcfg;
+ unsigned int pppseq; /* last seq no seen */
+ struct ippp_ccp *ccp;
+ unsigned long debug;
+
ippp_bundle * pb; /* pointer to the common bundle structure
* with the per-bundle data */
#endif
diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
index 68353a39b98c..ec6016c37421 100644
--- a/include/linux/isdn_ppp.h
+++ b/include/linux/isdn_ppp.h
@@ -8,7 +8,6 @@
#ifndef _LINUX_ISDN_PPP_H
#define _LINUX_ISDN_PPP_H
-
#define CALLTYPE_INCOMING 0x1
#define CALLTYPE_OUTGOING 0x2
#define CALLTYPE_CALLBACK 0x4
@@ -39,15 +38,6 @@ struct pppcallinfo
#define SC_OUT_SHORT_SEQ 0x00000800
#define SC_IN_SHORT_SEQ 0x00004000
-#define SC_DECOMP_ON 0x01
-#define SC_COMP_ON 0x02
-#define SC_DECOMP_DISCARD 0x04
-#define SC_COMP_DISCARD 0x08
-#define SC_LINK_DECOMP_ON 0x10
-#define SC_LINK_COMP_ON 0x20
-#define SC_LINK_DECOMP_DISCARD 0x40
-#define SC_LINK_COMP_DISCARD 0x80
-
#define ISDN_PPP_COMP_MAX_OPTIONS 16
#define IPPP_COMP_FLAG_XMIT 0x1
@@ -64,7 +54,8 @@ struct isdn_ppp_comp_data {
#include <linux/config.h>
-
+#include <linux/skbuff.h>
+#include <linux/ppp_defs.h>
#define DECOMP_ERR_NOMEM (-10)
@@ -172,8 +163,8 @@ enum ippp_ccp_reset_states {
struct ippp_ccp_reset_state {
enum ippp_ccp_reset_states state; /* State of this transaction */
- struct ippp_struct *is; /* Backlink to device stuff */
- unsigned char id; /* Backlink id index */
+ struct ippp_ccp *ccp; /* Backlink */
+ unsigned char id; /* id index */
unsigned char ta:1; /* The timer is active (flag) */
unsigned char expra:1; /* We expect a ResetAck at all */
int dlen; /* Databytes stored in data */
@@ -191,34 +182,5 @@ struct ippp_ccp_reset {
unsigned char lastid; /* Last id allocated by the engine */
};
-struct ippp_struct {
- struct ippp_struct *next_link;
- int state;
- struct sk_buff_head rq;
- wait_queue_head_t wq;
- struct task_struct *tk;
- unsigned int mpppcfg;
- unsigned int pppcfg;
- unsigned int mru;
- unsigned int mpmru;
- unsigned int mpmtu;
- unsigned int maxcid;
- struct isdn_net_dev_s *idev;
- int unit;
- int minor;
- unsigned int last_link_seqno;
- long mp_seqno;
-#ifdef CONFIG_ISDN_PPP_VJ
- unsigned char *cbuf;
- struct slcompress *slcomp;
-#endif
- unsigned long debug;
- struct isdn_ppp_compressor *compressor,*decompressor;
- struct isdn_ppp_compressor *link_compressor,*link_decompressor;
- void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
- struct ippp_ccp_reset *reset; /* Allocated on demand, may never be needed */
- unsigned long compflags;
-};
-
#endif /* __KERNEL__ */
#endif /* _LINUX_ISDN_PPP_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d0b9bdb97523..cab2c4342047 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -512,11 +512,18 @@ int write_one_page(struct page *page, int wait);
/* readahead.c */
#define VM_MAX_READAHEAD 128 /* kbytes */
#define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */
-int do_page_cache_readahead(struct file *file,
+int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
unsigned long offset, unsigned long nr_to_read);
-void page_cache_readahead(struct file *file, unsigned long offset);
-void page_cache_readaround(struct file *file, unsigned long offset);
-void handle_ra_miss(struct file *file);
+void page_cache_readahead(struct address_space *mapping,
+ struct file_ra_state *ra,
+ struct file *filp,
+ unsigned long offset);
+void page_cache_readaround(struct address_space *mapping,
+ struct file_ra_state *ra,
+ struct file *filp,
+ unsigned long offset);
+void handle_ra_miss(struct address_space *mapping,
+ struct file_ra_state *ra);
/* Do stack extension */
extern int expand_stack(struct vm_area_struct * vma, unsigned long address);
diff --git a/include/linux/security.h b/include/linux/security.h
index 072fbe94dd8b..e2f80f6a9dba 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -376,10 +376,6 @@ struct swap_info_struct;
* @file_free_security:
* Deallocate and free any security structures stored in file->f_security.
* @file contains the file structure being modified.
- * @file_llseek:
- * Check permission before re-positioning the file offset in @file.
- * @file contains the file structure being modified.
- * Return 0 if permission is granted.
* @file_ioctl:
* @file contains the file structure.
* @cmd contains the operation to perform.
@@ -790,7 +786,6 @@ struct security_operations {
int (*file_permission) (struct file * file, int mask);
int (*file_alloc_security) (struct file * file);
void (*file_free_security) (struct file * file);
- int (*file_llseek) (struct file * file);
int (*file_ioctl) (struct file * file, unsigned int cmd,
unsigned long arg);
int (*file_mmap) (struct file * file,
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
new file mode 100644
index 000000000000..6479902e1d20
--- /dev/null
+++ b/include/linux/sysfs.h
@@ -0,0 +1,51 @@
+/*
+ * sysfs.h - definitions for the device driver filesystem
+ *
+ * Copyright (c) 2001,2002 Patrick Mochel
+ *
+ * Please see Documentation/filesystems/sysfs.txt for more information.
+ */
+
+#ifndef _SYSFS_H_
+#define _SYSFS_H_
+
+struct driver_dir_entry;
+struct attribute;
+
+struct sysfs_ops {
+ int (*open)(struct driver_dir_entry *);
+ int (*close)(struct driver_dir_entry *);
+ ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
+ ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
+};
+
+struct driver_dir_entry {
+ char * name;
+ struct dentry * dentry;
+ mode_t mode;
+ struct sysfs_ops * ops;
+};
+
+struct attribute {
+ char * name;
+ mode_t mode;
+};
+
+extern int
+sysfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
+
+extern void
+sysfs_remove_dir(struct driver_dir_entry * entry);
+
+extern int
+sysfs_create_file(struct attribute * attr,
+ struct driver_dir_entry * parent);
+
+extern int
+sysfs_create_symlink(struct driver_dir_entry * parent,
+ char * name, char * target);
+
+extern void
+sysfs_remove_file(struct driver_dir_entry *, const char * name);
+
+#endif /* _SYSFS_H_ */
diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index ddf83957b343..b5f80d97f07b 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -130,7 +130,7 @@ typedef struct sg_io_hdr
/* following flag values can be "or"-ed together */
#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
-#define SG_FLAG_LUN_INHIBIT 2 /* default is overwrite lun in SCSI */
+#define SG_FLAG_UNUSED_LUN_INHIBIT 2 /* default is overwrite lun in SCSI */
/* command block (when <= SCSI_2) */
#define SG_FLAG_MMAP_IO 4 /* request memory mapped IO */
#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */
diff --git a/init/Makefile b/init/Makefile
index 6dbffbfb4b70..60f06f6ccb81 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -4,17 +4,20 @@
obj-y := main.o version.o do_mounts.o
+# files to be removed upon make clean
+clean-files := ../include/linux/compile.h
+
include $(TOPDIR)/Rules.make
# dependencies on generated files need to be listed explicitly
-$(obj)/version.o: $(objtree)/include/linux/compile.h
+$(obj)/version.o: $(obj)/../include/linux/compile.h
# compile.h changes depending on hostname, generation number, etc,
# so we regenerate it always.
# mkcompile_h will make sure to only update the
# actual file if its content has changed.
-$(objtree)/include/linux/compile.h: FORCE
- @echo -n ' Generating $@'
+$(obj)/../include/linux/compile.h: FORCE
+ @echo -n ' Generating $(echo_target)'
@sh $(srctree)/scripts/mkcompile_h $@ "$(ARCH)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index d3eddedb7468..941d5f9eec9d 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -229,7 +229,7 @@ EXPORT_SYMBOL(block_truncate_page);
EXPORT_SYMBOL(generic_block_bmap);
EXPORT_SYMBOL(generic_file_read);
EXPORT_SYMBOL(generic_file_sendfile);
-EXPORT_SYMBOL(do_generic_file_read);
+EXPORT_SYMBOL(do_generic_mapping_read);
EXPORT_SYMBOL(generic_file_write);
EXPORT_SYMBOL(generic_file_write_nolock);
EXPORT_SYMBOL(generic_file_mmap);
diff --git a/mm/filemap.c b/mm/filemap.c
index b2fbb1cbf90b..67d03d5d7732 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -570,10 +570,15 @@ void mark_page_accessed(struct page *page)
*
* This is really ugly. But the goto's actually try to clarify some
* of the logic when it comes to error handling etc.
+ * - note the struct file * is only passed for the use of readpage
*/
-void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor)
+void do_generic_mapping_read(struct address_space *mapping,
+ struct file_ra_state *ra,
+ struct file * filp,
+ loff_t *ppos,
+ read_descriptor_t * desc,
+ read_actor_t actor)
{
- struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
struct inode *inode = mapping->host;
unsigned long index, offset;
struct page *cached_page;
@@ -598,7 +603,7 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t *
break;
}
- page_cache_readahead(filp, index);
+ page_cache_readahead(mapping, ra, filp, index);
nr = nr - offset;
@@ -610,7 +615,7 @@ find_page:
page = radix_tree_lookup(&mapping->page_tree, index);
if (!page) {
read_unlock(&mapping->page_lock);
- handle_ra_miss(filp);
+ handle_ra_miss(mapping,ra);
goto no_cached_page;
}
page_cache_get(page);
@@ -891,6 +896,7 @@ generic_file_aio_read(struct kiocb *iocb, char *buf, size_t count, loff_t pos)
BUG_ON(iocb->ki_pos != pos);
return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
}
+EXPORT_SYMBOL(generic_file_aio_read);
ssize_t
generic_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
@@ -946,9 +952,9 @@ ssize_t generic_file_sendfile(struct file *out_file, struct file *in_file,
}
static ssize_t
-do_readahead(struct file *file, unsigned long index, unsigned long nr)
+do_readahead(struct address_space *mapping, struct file *filp,
+ unsigned long index, unsigned long nr)
{
- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
unsigned long max;
unsigned long active;
unsigned long inactive;
@@ -962,7 +968,7 @@ do_readahead(struct file *file, unsigned long index, unsigned long nr)
if (nr > max)
nr = max;
- do_page_cache_readahead(file, index, nr);
+ do_page_cache_readahead(mapping, filp, index, nr);
return 0;
}
@@ -975,10 +981,11 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
file = fget(fd);
if (file) {
if (file->f_mode & FMODE_READ) {
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
unsigned long start = offset >> PAGE_CACHE_SHIFT;
unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
unsigned long len = end - start + 1;
- ret = do_readahead(file, start, len);
+ ret = do_readahead(mapping, file, start, len);
}
fput(file);
}
@@ -999,6 +1006,7 @@ struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address
int error;
struct file *file = area->vm_file;
struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ struct file_ra_state *ra = &file->f_ra;
struct inode *inode = mapping->host;
struct page *page;
unsigned long size, pgoff, endoff;
@@ -1031,7 +1039,7 @@ retry_all:
*/
if (VM_SequentialReadHint(area)) {
did_readahead = 1;
- page_cache_readahead(area->vm_file, pgoff);
+ page_cache_readahead(mapping, ra, file, pgoff);
}
/*
@@ -1040,7 +1048,7 @@ retry_all:
*/
if ((pgoff < size) && !VM_RandomReadHint(area)) {
did_readahead = 1;
- page_cache_readaround(file, pgoff);
+ page_cache_readaround(mapping, ra, file, pgoff);
}
/*
@@ -1050,7 +1058,7 @@ retry_find:
page = find_get_page(mapping, pgoff);
if (!page) {
if (did_readahead) {
- handle_ra_miss(file);
+ handle_ra_miss(mapping,ra);
did_readahead = 0;
}
goto no_cached_page;
@@ -1650,6 +1658,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char *buf,
{
return generic_file_write(iocb->ki_filp, buf, count, &iocb->ki_pos);
}
+EXPORT_SYMBOL(generic_file_aio_write);
ssize_t generic_file_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
diff --git a/mm/madvise.c b/mm/madvise.c
index 4a232cead910..ac845fe3553a 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -80,7 +80,7 @@ static long madvise_willneed(struct vm_area_struct * vma,
if ((vma->vm_mm->rss + (end - start)) > rlim_rss)
return error;
- do_page_cache_readahead(file, start, end - start);
+ do_page_cache_readahead(file->f_dentry->d_inode->i_mapping, file, start, end - start);
return 0;
}
diff --git a/mm/readahead.c b/mm/readahead.c
index e1e68fc006dc..63528f6eed98 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -22,18 +22,18 @@ struct backing_dev_info default_backing_dev_info = {
/*
* Return max readahead size for this inode in number-of-pages.
*/
-static inline unsigned long get_max_readahead(struct file *file)
+static inline unsigned long get_max_readahead(struct file_ra_state *ra)
{
- return file->f_ra.ra_pages;
+ return ra->ra_pages;
}
-static inline unsigned long get_min_readahead(struct file *file)
+static inline unsigned long get_min_readahead(struct file_ra_state *ra)
{
return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE;
}
static int
-read_pages(struct file *file, struct address_space *mapping,
+read_pages(struct address_space *mapping, struct file *filp,
struct list_head *pages, unsigned nr_pages)
{
unsigned page_idx;
@@ -48,7 +48,7 @@ read_pages(struct file *file, struct address_space *mapping,
struct page *page = list_entry(pages->prev, struct page, list);
list_del(&page->list);
if (!add_to_page_cache(page, mapping, page->index)) {
- mapping->a_ops->readpage(file, page);
+ mapping->a_ops->readpage(filp, page);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
} else {
@@ -134,10 +134,11 @@ read_pages(struct file *file, struct address_space *mapping,
*
* Returns the number of pages which actually had IO started against them.
*/
-int do_page_cache_readahead(struct file *file,
- unsigned long offset, unsigned long nr_to_read)
+int do_page_cache_readahead(struct address_space *mapping,
+ struct file *filp,
+ unsigned long offset,
+ unsigned long nr_to_read)
{
- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
struct inode *inode = mapping->host;
struct page *page;
unsigned long end_index; /* The last page we want to read */
@@ -181,7 +182,7 @@ int do_page_cache_readahead(struct file *file,
* will then handle the error.
*/
if (ret) {
- read_pages(file, mapping, &page_pool, ret);
+ read_pages(mapping, filp, &page_pool, ret);
blk_run_queues();
}
BUG_ON(!list_empty(&page_pool));
@@ -216,9 +217,9 @@ check_ra_success(struct file_ra_state *ra, pgoff_t attempt,
* page_cache_readahead is the main function. If performs the adaptive
* readahead window size management and submits the readahead I/O.
*/
-void page_cache_readahead(struct file *file, unsigned long offset)
+void page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
+ struct file *filp, unsigned long offset)
{
- struct file_ra_state *ra = &file->f_ra;
unsigned max;
unsigned min;
unsigned orig_next_size;
@@ -239,11 +240,11 @@ void page_cache_readahead(struct file *file, unsigned long offset)
if (ra->next_size == -1UL)
goto out; /* Maximally shrunk */
- max = get_max_readahead(file);
+ max = get_max_readahead(ra);
if (max == 0)
goto out; /* No readahead */
- min = get_min_readahead(file);
+ min = get_min_readahead(ra);
orig_next_size = ra->next_size;
if (ra->next_size == 0 && offset == 0) {
@@ -316,7 +317,8 @@ do_io:
ra->ahead_start = 0; /* Invalidate these */
ra->ahead_size = 0;
- actual = do_page_cache_readahead(file, offset, ra->size);
+ actual = do_page_cache_readahead(mapping, filp, offset,
+ ra->size);
check_ra_success(ra, ra->size, actual, orig_next_size);
} else {
/*
@@ -327,7 +329,7 @@ do_io:
if (ra->ahead_start == 0) {
ra->ahead_start = ra->start + ra->size;
ra->ahead_size = ra->next_size;
- actual = do_page_cache_readahead(file,
+ actual = do_page_cache_readahead(mapping, filp,
ra->ahead_start, ra->ahead_size);
check_ra_success(ra, ra->ahead_size,
actual, orig_next_size);
@@ -342,12 +344,11 @@ out:
* but somewhat ascending. So readaround favours pages beyond the target one.
* We also boost the window size, as it can easily shrink due to misses.
*/
-void page_cache_readaround(struct file *file, unsigned long offset)
+void page_cache_readaround(struct address_space *mapping, struct file_ra_state *ra,
+ struct file *filp, unsigned long offset)
{
- struct file_ra_state *ra = &file->f_ra;
-
if (ra->next_size != -1UL) {
- const unsigned long min = get_min_readahead(file) * 2;
+ const unsigned long min = get_min_readahead(ra) * 2;
unsigned long target;
unsigned long backward;
@@ -365,7 +366,7 @@ void page_cache_readaround(struct file *file, unsigned long offset)
target = 0;
else
target -= backward;
- page_cache_readahead(file, target);
+ page_cache_readahead(mapping, ra, filp, target);
}
}
@@ -383,10 +384,9 @@ void page_cache_readaround(struct file *file, unsigned long offset)
* that the readahead window size will stabilise around the maximum level at
* which there is no thrashing.
*/
-void handle_ra_miss(struct file *file)
+void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra)
{
- struct file_ra_state *ra = &file->f_ra;
- const unsigned long min = get_min_readahead(file);
+ const unsigned long min = get_min_readahead(ra);
if (ra->next_size == -1UL) {
ra->next_size = min;
diff --git a/net/ipv4/ip_proc.c b/net/ipv4/ip_proc.c
index 74b67e8dcd67..7d41c499ba9e 100644
--- a/net/ipv4/ip_proc.c
+++ b/net/ipv4/ip_proc.c
@@ -67,99 +67,185 @@ static char *ax2asc2(ax25_address *a, char *buf)
}
#endif /* CONFIG_AX25 */
+struct arp_iter_state {
+ loff_t is_pneigh: 1,
+ bucket: 6,
+ pos: sizeof(loff_t) * 8 - 7;
+};
+
+static __inline__ struct neighbour *neigh_get_bucket(loff_t *pos)
+{
+ struct neighbour *n = NULL;
+ struct arp_iter_state* state = (struct arp_iter_state *)pos;
+ loff_t l = state->pos;
+ int i, bucket = state->bucket;
+
+ for (; bucket <= NEIGH_HASHMASK; ++bucket)
+ for (i = 0, n = arp_tbl.hash_buckets[bucket]; n;
+ ++i, n = n->next)
+ /* Do not confuse users "arp -a" with magic entries */
+ if ((n->nud_state & ~NUD_NOARP) && !l--) {
+ state->pos = i;
+ state->bucket = bucket;
+ goto out;
+ }
+out:
+ return n;
+}
+
+static __inline__ struct pneigh_entry *pneigh_get_bucket(loff_t *pos)
+{
+ struct pneigh_entry *n = NULL;
+ struct arp_iter_state* state = (struct arp_iter_state *)pos;
+ loff_t l = state->pos;
+ int i, bucket = state->bucket;
+
+ for (; bucket <= PNEIGH_HASHMASK; ++bucket)
+ for (i = 0, n = arp_tbl.phash_buckets[bucket]; n;
+ ++i, n = n->next)
+ if (!l--) {
+ state->pos = i;
+ state->bucket = bucket;
+ goto out;
+ }
+out:
+ return n;
+}
+
+static __inline__ void *arp_get_bucket(struct seq_file *seq, loff_t *pos)
+{
+ void *rc = neigh_get_bucket(pos);
+
+ if (!rc) {
+ struct arp_iter_state* state = (struct arp_iter_state *)pos;
+
+ read_unlock_bh(&arp_tbl.lock);
+ state->is_pneigh = 1;
+ state->bucket = 0;
+ state->pos = 0;
+ /* HACK: till there is state we can pass to seq_show... */
+ seq->private = (void *)1;
+ rc = pneigh_get_bucket(pos);
+ }
+ return rc;
+}
+
static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
{
- return (void *)(unsigned long)++*pos;
+ read_lock_bh(&arp_tbl.lock);
+ return *pos ? arp_get_bucket(seq, pos) : (void *)1;
}
static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- return (void *)(unsigned long)((++*pos) >=
- (NEIGH_HASHMASK +
- PNEIGH_HASHMASK - 1) ? 0 : *pos);
+ void *rc;
+ struct arp_iter_state* state;
+
+ if (v == (void *)1) {
+ rc = arp_get_bucket(seq, pos);
+ goto out;
+ }
+
+ state = (struct arp_iter_state *)pos;
+ if (!state->is_pneigh) {
+ struct neighbour *n = v;
+
+ rc = n = n->next;
+ if (n)
+ goto out;
+ state->pos = 0;
+ ++state->bucket;
+ rc = neigh_get_bucket(pos);
+ if (rc)
+ goto out;
+ read_unlock_bh(&arp_tbl.lock);
+ /* HACK: till there is state we can pass to seq_show... */
+ seq->private = (void *)1;
+ state->is_pneigh = 1;
+ state->bucket = 0;
+ state->pos = 0;
+ rc = pneigh_get_bucket(pos);
+ } else {
+ struct pneigh_entry *pn = v;
+
+ pn = pn->next;
+ if (!pn) {
+ ++state->bucket;
+ state->pos = 0;
+ pn = pneigh_get_bucket(pos);
+ }
+ rc = pn;
+ }
+out:
+ ++*pos;
+ return rc;
}
static void arp_seq_stop(struct seq_file *seq, void *v)
{
+ if (!seq->private)
+ read_unlock_bh(&arp_tbl.lock);
}
#define HBUFFERLEN 30
-static __inline__ void arp_format_neigh_table(struct seq_file *seq, int entry)
+static __inline__ void arp_format_neigh_entry(struct seq_file *seq,
+ struct neighbour *n)
{
char hbuffer[HBUFFERLEN];
const char hexbuf[] = "0123456789ABCDEF";
- struct neighbour *n;
int k, j;
+ char tbuf[16];
+ struct net_device *dev = n->dev;
+ int hatype = dev->type;
- read_lock_bh(&arp_tbl.lock);
- for (n = arp_tbl.hash_buckets[entry]; n; n = n->next) {
- char tbuf[16];
- struct net_device *dev = n->dev;
- int hatype = dev->type;
-
- /* Do not confuse users "arp -a" with magic entries */
- if (!(n->nud_state & ~NUD_NOARP))
- continue;
-
- read_lock(&n->lock);
- /* Convert hardware address to XX:XX:XX:XX ... form. */
+ read_lock(&n->lock);
+ /* Convert hardware address to XX:XX:XX:XX ... form. */
#ifdef CONFIG_AX25
- if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
- ax2asc2((ax25_address *)n->ha, hbuffer);
- else {
+ if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
+ ax2asc2((ax25_address *)n->ha, hbuffer);
+ else {
#endif
- for (k = 0, j = 0; k < HBUFFERLEN - 3 &&
- j < dev->addr_len; j++) {
- hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
- hbuffer[k++] = hexbuf[n->ha[j] & 15];
- hbuffer[k++] = ':';
- }
- hbuffer[--k] = 0;
+ for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) {
+ hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
+ hbuffer[k++] = hexbuf[n->ha[j] & 15];
+ hbuffer[k++] = ':';
+ }
+ hbuffer[--k] = 0;
#ifdef CONFIG_AX25
- }
-#endif
- sprintf(tbuf, "%u.%u.%u.%u",
- NIPQUAD(*(u32*)n->primary_key));
- seq_printf(seq, "%-16s 0x%-10x0x%-10x%s"
- " * %s\n",
- tbuf, hatype, arp_state_to_flags(n),
- hbuffer, dev->name);
- read_unlock(&n->lock);
}
- read_unlock_bh(&arp_tbl.lock);
+#endif
+ sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
+ seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n",
+ tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
+ read_unlock(&n->lock);
}
-static __inline__ void arp_format_pneigh_table(struct seq_file *seq, int entry)
+static __inline__ void arp_format_pneigh_entry(struct seq_file *seq,
+ struct pneigh_entry *n)
{
- struct pneigh_entry *n;
-
- for (n = arp_tbl.phash_buckets[entry]; n; n = n->next) {
- struct net_device *dev = n->dev;
- int hatype = dev ? dev->type : 0;
- char tbuf[16];
-
- sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
- seq_printf(seq, "%-16s 0x%-10x0x%-10x%s"
- " * %s\n",
- tbuf, hatype, ATF_PUBL | ATF_PERM,
- "00:00:00:00:00:00",
- dev ? dev->name : "*");
- }
+
+ struct net_device *dev = n->dev;
+ int hatype = dev ? dev->type : 0;
+ char tbuf[16];
+
+ sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
+ seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n",
+ tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
+ dev ? dev->name : "*");
}
static int arp_seq_show(struct seq_file *seq, void *v)
{
- unsigned long l = (unsigned long)v - 1;
-
- if (!l)
+ if (v == (void *)1)
seq_puts(seq, "IP address HW type Flags "
"HW address Mask Device\n");
-
- if (l <= NEIGH_HASHMASK)
- arp_format_neigh_table(seq, l);
- else
- arp_format_pneigh_table(seq, l - NEIGH_HASHMASK);
+ else {
+ if (seq->private)
+ arp_format_pneigh_entry(seq, v);
+ else
+ arp_format_neigh_entry(seq, v);
+ }
return 0;
}
diff --git a/scripts/Makefile b/scripts/Makefile
index 0921e79c6c79..6032efe0f0aa 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -11,6 +11,8 @@
EXTRA_TARGETS := fixdep split-include docproc conmakehash
+subdir- := lxdialog
+
# Yikes. We need to build this stuff here even if the user only wants
# modules.
@@ -24,6 +26,8 @@ KBUILD_BUILTIN := 1
host-progs := fixdep split-include conmakehash docproc tkparse
tkparse-objs := tkparse.o tkcond.o tkgen.o
+clean-files := kconfig.tk
+
include $(TOPDIR)/Rules.make
# In reality kconfig.tk should depend on all Config.in files,
@@ -56,8 +60,3 @@ lxdialog:
# fixdep is needed to compile other host programs
$(obj)/split-include $(obj)/docproc $(addprefix $(obj)/,$(tkparse-objs)) \
$(obj)/conmakehash lxdialog: $(obj)/fixdep
-
-mrproper:
- @rm -f $(host-progs) $(addprefix $(obj)/,$(tkparse-objs) kconfig.tk core)
- @$(call descend,scripts/lxdialog,mrproper)
-
diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
index da5e5a1ab32d..252c5bf86cd1 100644
--- a/scripts/lxdialog/Makefile
+++ b/scripts/lxdialog/Makefile
@@ -42,6 +42,3 @@ ncurses:
echo ;\
exit 1 ;\
fi
-
-mrproper:
- @rm -f $(host-progs) $(addprefix $(obj)/,$(lxdialog-objs))
diff --git a/security/capability.c b/security/capability.c
index 6f9b25ba65bd..809fac9a470b 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -442,11 +442,6 @@ static void cap_file_free_security (struct file *file)
return;
}
-static int cap_file_llseek (struct file *file)
-{
- return 0;
-}
-
static int cap_file_ioctl (struct file *file, unsigned int command,
unsigned long arg)
{
@@ -787,7 +782,6 @@ static struct security_operations capability_ops = {
.file_permission = cap_file_permission,
.file_alloc_security = cap_file_alloc_security,
.file_free_security = cap_file_free_security,
- .file_llseek = cap_file_llseek,
.file_ioctl = cap_file_ioctl,
.file_mmap = cap_file_mmap,
.file_mprotect = cap_file_mprotect,
diff --git a/security/dummy.c b/security/dummy.c
index 0b3ca57db95b..aa65562474eb 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -344,11 +344,6 @@ static void dummy_file_free_security (struct file *file)
return;
}
-static int dummy_file_llseek (struct file *file)
-{
- return 0;
-}
-
static int dummy_file_ioctl (struct file *file, unsigned int command,
unsigned long arg)
{
@@ -602,7 +597,6 @@ struct security_operations dummy_security_ops = {
.file_permission = dummy_file_permission,
.file_alloc_security = dummy_file_alloc_security,
.file_free_security = dummy_file_free_security,
- .file_llseek = dummy_file_llseek,
.file_ioctl = dummy_file_ioctl,
.file_mmap = dummy_file_mmap,
.file_mprotect = dummy_file_mprotect,
diff --git a/security/security.c b/security/security.c
index 892208b20bc4..57746fb90878 100644
--- a/security/security.c
+++ b/security/security.c
@@ -241,9 +241,9 @@ asmlinkage long sys_security (unsigned int id, unsigned int call,
return security_ops->sys_security (id, call, args);
}
-EXPORT_SYMBOL (register_security);
-EXPORT_SYMBOL (unregister_security);
-EXPORT_SYMBOL (mod_reg_security);
-EXPORT_SYMBOL (mod_unreg_security);
-EXPORT_SYMBOL (capable);
-EXPORT_SYMBOL (security_ops);
+EXPORT_SYMBOL_GPL(register_security);
+EXPORT_SYMBOL_GPL(unregister_security);
+EXPORT_SYMBOL_GPL(mod_reg_security);
+EXPORT_SYMBOL_GPL(mod_unreg_security);
+EXPORT_SYMBOL(capable);
+EXPORT_SYMBOL(security_ops);
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index c24a584bc43d..de9f457b82cc 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -96,6 +96,10 @@ wavefront-objs := wavfront.o wf_midi.o yss225.o
host-progs := bin2hex hex2hex
+# Files generated that shall be removed upon make clean
+clean-files := maui_boot.h msndperm.c msndinit.c pndsperm.c pndspini.c \
+ pss_boot.h trix_boot.h
+
include $(TOPDIR)/Rules.make
# Firmware files that need translation
diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c
index 85a18bfbdd10..3d9b3ceb17df 100644
--- a/sound/oss/ite8172.c
+++ b/sound/oss/ite8172.c
@@ -305,7 +305,7 @@ static LIST_HEAD(devs);
/* --------------------------------------------------------------------- */
-extern inline unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
{
unsigned r = 0;
@@ -510,7 +510,7 @@ static void waitcodec(struct ac97_codec *codec)
/* --------------------------------------------------------------------- */
-extern inline void stop_adc(struct it8172_state *s)
+static inline void stop_adc(struct it8172_state *s)
{
struct dmabuf* db = &s->dma_adc;
unsigned long flags;
@@ -534,7 +534,7 @@ extern inline void stop_adc(struct it8172_state *s)
spin_unlock_irqrestore(&s->lock, flags);
}
-extern inline void stop_dac(struct it8172_state *s)
+static inline void stop_dac(struct it8172_state *s)
{
struct dmabuf* db = &s->dma_dac;
unsigned long flags;
@@ -633,7 +633,7 @@ static void start_adc(struct it8172_state *s)
#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
#define DMABUF_MINORDER 1
-extern inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db)
+static inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db)
{
struct page *page, *pend;
@@ -709,7 +709,7 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
return 0;
}
-extern inline int prog_dmabuf_adc(struct it8172_state *s)
+static inline int prog_dmabuf_adc(struct it8172_state *s)
{
stop_adc(s);
return prog_dmabuf(s, &s->dma_adc, s->adcrate,
@@ -717,7 +717,7 @@ extern inline int prog_dmabuf_adc(struct it8172_state *s)
IT_AC_CAPCC);
}
-extern inline int prog_dmabuf_dac(struct it8172_state *s)
+static inline int prog_dmabuf_dac(struct it8172_state *s)
{
stop_dac(s);
return prog_dmabuf(s, &s->dma_dac, s->dacrate,
diff --git a/sound/oss/sound_config.h b/sound/oss/sound_config.h
index 050c38df5f21..4838b589cf6e 100644
--- a/sound/oss/sound_config.h
+++ b/sound/oss/sound_config.h
@@ -113,14 +113,14 @@ struct channel_info {
#if OPEN_READ == FMODE_READ && OPEN_WRITE == FMODE_WRITE
-extern __inline__ int translate_mode(struct file *file)
+static inline int translate_mode(struct file *file)
{
return file->f_mode;
}
#else
-extern __inline__ int translate_mode(struct file *file)
+static inline int translate_mode(struct file *file)
{
return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) |
((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 36f30fb25450..27b9fce23b8a 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -593,7 +593,7 @@ static void snd_es1371_codec_write(ac97_t *ac97,
}
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
- snd_printk("codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
+ snd_printk("codec write timeout at 0x%lx [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
}
static unsigned short snd_es1371_codec_read(ac97_t *ac97,
@@ -641,14 +641,14 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97,
}
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
if (++fail > 10) {
- snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
+ snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
}
goto __again;
}
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
- snd_printk("es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
+ snd_printk("es1371: codec read timeout at 0x%lx [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
}