diff options
| author | Andy Grover <agrover@groveronline.com> | 2003-03-19 00:09:51 -0800 |
|---|---|---|
| committer | Andy Grover <agrover@groveronline.com> | 2003-03-19 00:09:51 -0800 |
| commit | b39e199b453be169dfd1adec9686978057c1dc0f (patch) | |
| tree | dd7162a8e62d003159d6250069194b48a72b76d0 | |
| parent | 99d5dfb972d15c955e274d3f67e3862ce8004311 (diff) | |
| parent | d99c48c60bc52561b3125dd1f85db7a77b7031ca (diff) | |
Merge groveronline.com:/root/bk/linux-2.5
into groveronline.com:/root/bk/linux-acpi
499 files changed, 13704 insertions, 8082 deletions
diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl index ece95d2eb843..d0472f85da73 100644 --- a/Documentation/DocBook/journal-api.tmpl +++ b/Documentation/DocBook/journal-api.tmpl @@ -216,7 +216,7 @@ calls. <para> A new feature of jbd since 2.5.25 is commit callbacks with the new journal_callback_set() function you can now ask the journalling layer -to call you back when the transaction is finally commited to disk, so that +to call you back when the transaction is finally committed to disk, so that you can do some of your own management. The key to this is the journal_callback struct, this maintains the internal callback information but you can extend it like this:- @@ -232,7 +232,7 @@ extend it like this:- </programlisting> <para> -this would be useful if you needed to know when data was commited to a +this would be useful if you needed to know when data was committed to a particular inode. </para> diff --git a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl index f3912413b52c..f8d24d47cb10 100644 --- a/Documentation/DocBook/sis900.tmpl +++ b/Documentation/DocBook/sis900.tmpl @@ -536,7 +536,7 @@ by ifconfig causes the media link down. <ListItem> <Para> November 13, 2000, Revision 1.07, seventh release, 630E problem fixed -and furthur clean up. +and further clean up. </Para> </ListItem> diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting index ac3f08e2709a..c9feb2d5c797 100644 --- a/Documentation/arm/Booting +++ b/Documentation/arm/Booting @@ -47,7 +47,7 @@ which serial port it should use for the kernel console (generally used for debugging purposes, or communication with the target.) As an alternative, the boot loader can pass the relevant 'console=' -option to the kernel via the tagged lists specifing the port, and +option to the kernel via the tagged lists specifying the port, and serial format options as described in linux/Documentation/kernel-parameters.txt. diff --git a/Documentation/arm/SA1100/serial_UART b/Documentation/arm/SA1100/serial_UART index 161ec115c6f0..aea2e91ca0ef 100644 --- a/Documentation/arm/SA1100/serial_UART +++ b/Documentation/arm/SA1100/serial_UART @@ -39,7 +39,7 @@ must ensure your user space applications make use of the correct device name. The classic example is the content of the /etc/inittab file where you might have a getty process started on ttyS0. In this case: -- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. +- replace occurrences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. - don't forget to add 'ttySA0', 'console', or the appropriate tty name in /etc/securetty for root to be allowed to login as well. diff --git a/Documentation/arm/Setup b/Documentation/arm/Setup index 68ff38daacb6..0abd0720d7ed 100644 --- a/Documentation/arm/Setup +++ b/Documentation/arm/Setup @@ -97,7 +97,7 @@ below: initrd_size This describes the kernel virtual start address and size of the - inital ramdisk. + initial ramdisk. rd_start diff --git a/Documentation/arm/XScale/IOP3XX/dma.txt b/Documentation/arm/XScale/IOP3XX/dma.txt index f6ef554e491e..50c7f99e4ba8 100644 --- a/Documentation/arm/XScale/IOP3XX/dma.txt +++ b/Documentation/arm/XScale/IOP3XX/dma.txt @@ -142,7 +142,7 @@ void dma_test(void) /* User's responsibility to keep buffers cached coherent */ cpu_dcache_clean(sgl->data, sgl->data + 1024); - /* queing the buffer, this function will sleep since no callback */ + /* queuing the buffer, this function will sleep since no callback */ err = dma_queue_buffer(channel, sgl_head); /* now we are woken from DMA complete */ @@ -186,7 +186,7 @@ dma_suspend(). int dma_flush_all(dmach_t channel); This completely flushes all queued buffers and on-going DMA transfers on a -given channel. This is called when DMA channel errors have occured. +given channel. This is called when DMA channel errors have occurred. void dma_free(dmach_t channel); diff --git a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment index a944af7c0244..d145ccca169a 100644 --- a/Documentation/arm/mem_alignment +++ b/Documentation/arm/mem_alignment @@ -51,7 +51,7 @@ fixing up or sending SIGBUS signals: echo 1 > /proc/sys/debug/alignment You can also read the content of the same file to get statistical -information on unaligned access occurences plus the current mode of +information on unaligned access occurrences plus the current mode of operation for user space code. diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index f433f259b72a..6af2d42cab79 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -635,9 +635,9 @@ to the numbers of sectors in the current segment being processed which could be one of the many segments in the current bio (i.e i/o completion unit). The nr_sectors value refers to the total number of sectors in the whole request that remain to be transferred (no change). The purpose of the -hard_xxx values is for block to remember these counts everytime it hands +hard_xxx values is for block to remember these counts every time it hands over the request to the driver. These values are updated by block on -end_that_request_first, i.e. everytime the driver completes a part of the +end_that_request_first, i.e. every time the driver completes a part of the transfer and invokes block end*request helpers to mark this. The driver should not modify these values. The block layer sets up the nr_sectors and current_nr_sectors fields (based on the corresponding diff --git a/Documentation/computone.txt b/Documentation/computone.txt index 97ee950bda80..1bc1dd454a65 100644 --- a/Documentation/computone.txt +++ b/Documentation/computone.txt @@ -539,7 +539,7 @@ X X for PORTNO in $MINORS X do X if test ! -c /dev/ttyF$PORTNO ; then -X # We got the harware but no device - make it +X # We got the hardware but no device - make it X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO X fi X done @@ -552,7 +552,7 @@ X X for PORTNO in $MINORS X do X if test ! -c /dev/cuf$PORTNO ; then -X # We got the harware but no device - make it +X # We got the hardware but no device - make it X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO X fi X done diff --git a/Documentation/cpqarray.txt b/Documentation/cpqarray.txt index 620e12b6ef7c..d0e185f7c930 100644 --- a/Documentation/cpqarray.txt +++ b/Documentation/cpqarray.txt @@ -49,9 +49,9 @@ EISA Controllers: ----------------- If you want to use an EISA controller you'll have to supply some -insmod/lilo paramaters. If the driver is compiled into the kernel, must +insmod/lilo parameters. If the driver is compiled into the kernel, must give it the controller's IO port address at boot time (it is no longer -necessary to specifiy the IRQ). For example, if you had two SMART-2/E +necessary to specify the IRQ). For example, if you had two SMART-2/E controllers, in EISA slots 1 and 2 you'd give it a boot argument like this: diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 030f7b9c2b43..b9bab37848a8 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -54,7 +54,7 @@ cpufreq_driver.name - The name of this driver. cpufreq_driver.init - A pointer to the per-CPU initialization function. -cpufreq_driver.verify - A pointer to a "verification" funciton. +cpufreq_driver.verify - A pointer to a "verification" function. cpufreq_driver.setpolicy _or_ cpufreq_driver.target - See below on the differences. diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 8f1e57f10e4e..9c9036590e1b 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -898,7 +898,7 @@ Your cooperation is appreciated. ... Network Block Device is somehow similar to loopback - devices: If you read from it, it sends packet accross + devices: If you read from it, it sends packet across network asking server for data. If you write to it, it sends packet telling server to write. It could be used to mounting filesystems over the net, swapping over diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt index 7d3f2a63c401..c7c0890b56ef 100644 --- a/Documentation/driver-model/driver.txt +++ b/Documentation/driver-model/driver.txt @@ -36,7 +36,7 @@ Initialization ~~~~~~~~~~~~~~ The driver must initialize at least the name and bus fields. It should -also initalize the devclass field (when it arrives), so it may obtain +also initialize the devclass field (when it arrives), so it may obtain the proper linkage internally. It should also initialize as many of the callbacks as possible, though each is optional. @@ -93,7 +93,7 @@ static struct pci_driver eepro100_driver = { }, }; -Some may find the syntax of embedded struct intialization awkward or +Some may find the syntax of embedded struct initialization awkward or even a bit ugly. So far, it's the best way we've found to do what we want... Registration @@ -198,7 +198,7 @@ it into a supported low-power state. int (*suspend) (struct device * dev, u32 state, u32 level); suspend is called to put the device in a low power state. There are -several stages to sucessfully suspending a device, which is denoted in +several stages to successfully suspending a device, which is denoted in the @level parameter. Breaking the suspend transition into several stages affords the platform flexibility in performing device power management based on the requirements of the system and the @@ -206,7 +206,7 @@ user-defined policy. SUSPEND_NOTIFY notifies the device that a suspend transition is about to happen. This happens on system power state transition to verify -that all devices can sucessfully suspend. +that all devices can successfully suspend. A driver may choose to fail on this call, which should cause the entire suspend transition to fail. A driver should fail only if it diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt index 5ead0296f2a8..f03d39670406 100644 --- a/Documentation/driver-model/platform.txt +++ b/Documentation/driver-model/platform.txt @@ -34,7 +34,7 @@ foremost, it groups all the legacy devices under a common bus, and gives them a common parent if they don't already have one. But, besides the organizational benefits, the platform bus can also -accomodate firmware-based enumeration. +accommodate firmware-based enumeration. Device Discovery diff --git a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting index e16492d7c720..548dcf48e249 100644 --- a/Documentation/filesystems/Exporting +++ b/Documentation/filesystems/Exporting @@ -45,7 +45,7 @@ the dcache that are not needed for normal filesystem access. to already have a (non-connected) dentry, and must be able to move that dentry into place (based on the parent and name in the ->lookup). This is particuarly needed for directories as - it is a dcache invarient that directories only have one dentry. + it is a dcache invariant that directories only have one dentry. To implement these features, the dcache has: diff --git a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README index 98688f4afc79..c4516620de42 100644 --- a/Documentation/filesystems/devfs/README +++ b/Documentation/filesystems/devfs/README @@ -56,7 +56,7 @@ How it works Operational issues (essential reading) Instructions for the impatient -Permissions persistence accross reboots +Permissions persistence across reboots Dealing with drivers without devfs support All the way with Devfs Other Issues diff --git a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking index a320ac2909e7..34380d4fbce3 100644 --- a/Documentation/filesystems/directory-locking +++ b/Documentation/filesystems/directory-locking @@ -110,4 +110,4 @@ not introduce a cycle will leave it a tree and link() fails for directories). Notice that "directory" in the above == "anything that might have children", so if we are going to introduce hybrid objects we will need either to make sure that link(2) doesn't work for them or to make changes -in is_subdir() that would make it work even in presense of such beasts. +in is_subdir() that would make it work even in presence of such beasts. diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt index 12c01af809ac..ff220afb1225 100644 --- a/Documentation/filesystems/ext3.txt +++ b/Documentation/filesystems/ext3.txt @@ -48,11 +48,11 @@ resuid=n The user ID which may use the reserved blocks. sb=n Use alternate superblock at this location. -data=journal All data are commited into the journal prior +data=journal All data are committed into the journal prior to being written into the main file system. data=ordered (*) All data are forced directly out to the main file - system prior to its metadata being commited to + system prior to its metadata being committed to the journal. data=writeback Data ordering is not preserved, data may be diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index fe4e48f6f594..f75f9de90f2b 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -344,7 +344,7 @@ allocation failed. Each column represents the number of pages of a certain order which are available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE -availble in ZONE_NORMAL, etc... +available in ZONE_NORMAL, etc... 1.3 IDE devices in /proc/ide diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 9b9c223c2705..cf8bc735ca41 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -55,7 +55,7 @@ per file. It is noted that it may not be efficient to contain only value per file, so it is socially acceptable to express an array of values of the same type. -Mixing types, expressing mulitple lines of data, and doing fancy +Mixing types, expressing multiple lines of data, and doing fancy formatting of data is heavily frowned upon. Doing these things may get you publically humiliated and your code rewritten without notice. diff --git a/Documentation/i810_rng.txt b/Documentation/hw_random.txt index 21992f820dd4..21992f820dd4 100644 --- a/Documentation/i810_rng.txt +++ b/Documentation/hw_random.txt diff --git a/Documentation/ia64/IRQ-redir.txt b/Documentation/ia64/IRQ-redir.txt index b2096c3b2cb2..f7bd72261283 100644 --- a/Documentation/ia64/IRQ-redir.txt +++ b/Documentation/ia64/IRQ-redir.txt @@ -29,7 +29,7 @@ delivery mode (redirectable): The output of the command cat /proc/irq/IRQ#/smp_affinity gives the target CPU mask for the specified interrupt vector. If the CPU -mask is preceeded by the character "r", the interrupt is redirectable +mask is preceded by the character "r", the interrupt is redirectable (i.e. lowest priority mode routing is used), otherwise its route is fixed. diff --git a/Documentation/ide.txt b/Documentation/ide.txt index f7250c2b18d4..407a58f068a1 100644 --- a/Documentation/ide.txt +++ b/Documentation/ide.txt @@ -4,7 +4,7 @@ ============================================================================== - The hdparm utility can be used to controll various IDE features on a + The hdparm utility can be used to control various IDE features on a running system. It is packaged separately. Please Look for it on popular linux FTP sites. @@ -37,7 +37,7 @@ ================================================================================ Common pitfalls: -- 40-conductor IDE cables are capable of transfering data in DMA modes up to +- 40-conductor IDE cables are capable of transferring data in DMA modes up to udma2, but no faster. - If possible devices should be attached to separate channels if they are diff --git a/Documentation/input/ff.txt b/Documentation/input/ff.txt index 731249139b4a..ddfcd420ed08 100644 --- a/Documentation/input/ff.txt +++ b/Documentation/input/ff.txt @@ -163,7 +163,7 @@ Control of playing is done with write(). Below is an example: ~~~~~~~~~~~~~~~~~~~~ Not all devices have the same strength. Therefore, users should set a gain factor depending on how strong they want effects to be. This setting is -persistent accross access to the driver, so you should not care about it if +persistent across access to the driver, so you should not care about it if you are writing games, as another utility probably already set this for you. /* Set the gain of the device @@ -200,7 +200,7 @@ A value of 0 means "no auto-center". Proceed as if you wanted to upload a new effect, except that instead of setting the id field to -1, you set it to the wanted effect id. Normally, the effect is not stopped and restarted. However, depending on the -type of device, not all paramaters can be dynamically updated. For example, +type of device, not all parameters can be dynamically updated. For example, the direction of an effect cannot be updated with iforce devices. In this case, the driver stops the effect, up-load it, and restart it. diff --git a/Documentation/isdn/INTERFACE b/Documentation/isdn/INTERFACE index e8d70fae9a2a..3b56e226f4e9 100644 --- a/Documentation/isdn/INTERFACE +++ b/Documentation/isdn/INTERFACE @@ -735,7 +735,7 @@ Description of the Interface between Linklevel and Hardwarelevel driver = driver-Id command = ISDN_STAT_PROT arg = The lower 8 Bits define the addressed protocol as defined - in ISDN_PTYPE..., the upper bits are used to differenciate + in ISDN_PTYPE..., the upper bits are used to differentiate the protocol specific STAT. para = protocol and function specific. See isdnif.h for detail. diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt index a3037ffcf987..42fa117e97e8 100644 --- a/Documentation/kbuild/kconfig-language.txt +++ b/Documentation/kbuild/kconfig-language.txt @@ -69,7 +69,7 @@ applicable everywhere (see syntax). default values are visible, only the first defined one is active. Default values are not limited to the menu entry, where they are defined, this means the default can be defined somewhere else or be - overriden by an earlier definition. + overridden by an earlier definition. The default value is only assigned to the config symbol if no other value was set by the user (via the input prompt above). If an input prompt is visible the default value is presented to the user and can @@ -142,7 +142,7 @@ Menu structure -------------- The position of a menu entry in the tree is determined in two ways. First -it can be specified explicitely: +it can be specified explicitly: menu "Network device support" depends NET diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 2d0a4de89302..7d05904bb32f 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -10,7 +10,7 @@ This document describes the Linux kernel Makefiles. --- 3.1 Goal definitions --- 3.2 Built-in object goals - obj-y --- 3.3 Loadable module goals - obj-m - --- 3.4 Objects which export symbols - export-objs + --- 3.4 Objects which export symbols --- 3.5 Library file goals - L_TARGET --- 3.6 Descending down in directories --- 3.7 Compilation flags @@ -208,32 +208,11 @@ more details, with real examples. kbuild will build an ext2.o file for you out of the individual parts and then link this into built-in.o, as you would expect. ---- 3.4 Objects which export symbols - export-objs +--- 3.4 Objects which export symbols - When using loadable modules, not every global symbol in the - kernel / other modules is automatically available, only those - explicitly exported are available for your module. - - To make a symbol available for use in modules, to "export" it, - use the EXPORT_SYMBOL(<symbol>) directive in your source. In - addition, you need to list all object files which export symbols - (i.e. their source contains an EXPORT_SYMBOL() directive) in the - Makefile variable $(export-objs). - - Example: - #drivers/isdn/i4l/Makefile - # Objects that export symbols. - export-objs := isdn_common.o - - since isdn_common.c contains - - EXPORT_SYMBOL(register_isdn); - - which makes the function register_isdn available to - low-level ISDN drivers. - There exist a EXPORT_SYMBOL_GPL() variant with similar functionality, - but more restrictive with what may use that symbol. The requirement - to list the .o file in export-objs is the same. + No special notation is required in the makefiles for + modules exporting symbols. + See also Documentation/modules.txt. --- 3.5 Library file goals - L_TARGET @@ -400,7 +379,7 @@ done utilising the variable host-prog. The second step is to add an explicit dependency to the executable. This can be done in two ways. Either add the dependency in a rule, -or utilise the variable build-targets. +or utilise the variable $(always). Both possibilities are described in the following. --- 4.1 Simple Host Program @@ -526,15 +505,15 @@ Both possibilities are described in the following. $(obj)/gen-devlist is updated. Note that references to the host programs in special rules must be prefixed with $(obj). - (2) Use $(build-targets) + (2) Use $(always) When there is no suitable special rule, and the host program - shall be built when a makefile is entered, the $(build-targets) + shall be built when a makefile is entered, the $(always) variable shall be used. Example: #scripts/lxdialog/Makefile host-progs := lxdialog - build-targets := $(host-progs) + always := $(host-progs) This will tell kbuild to build lxdialog even if not referenced in any rule. @@ -543,13 +522,13 @@ Both possibilities are described in the following. "make clean" deletes most generated files in the src tree where the kernel is compiled. This includes generated files such as host programs. -Kbuild knows targets listed in $(host-progs) and $(EXTRA_TARGETS) and -they are all deleted during "make clean". +Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and +$(targets). They are all deleted during "make clean". Files matching the patterns "*.[oas]", "*.ko", plus some additional files generated by kbuild are deleted all over the kernel src tree when "make clean" is executed. -Additional files can be specified by means of $(clean-files). +Additional files can be specified in kbuild makefiles by use of $(clean-files). Example: #drivers/pci/Makefile @@ -561,7 +540,7 @@ located in the same directory as the makefile. Usually kbuild descends down in subdirectories due to "obj-* := dir/", but in the architecture makefiles where the kbuild infrastructure -is not sufficent this sometimes needs to be explicit. +is not sufficient this sometimes needs to be explicit. Example: #arch/i386/boot/Makefile @@ -818,31 +797,23 @@ When kbuild executes the following steps are followed (roughly): --- 6.5 Building non-kbuild targets - EXTRA_TARGETS + extra-y - EXTRA_TARGETS specify additional targets created in current + extra-y specify additional targets created in current directory, in addition to any targets specified by obj-*. - Listing all targets in EXTRA_TARGETS is required for three purposes: - 1) Avoid that the target is linked in as part of built-in.o - 2) Enable kbuild to check changes in command lines + Listing all targets in extra-y is required for two purposes: + 1) Enable kbuild to check changes in command lines - When $(call if_changed,xxx) is used - 3) kbuild knows what file to delete during "make clean" + 2) kbuild knows what files to delete during "make clean" Example: #arch/i386/kernel/Makefile - EXTRA_TARGETS := head.o init_task.o + extra-y := head.o init_task.o - In this example EXTRA_TARGETS is used to list object files that + In this example extra-y is used to list object files that shall be built, but shall not be linked as part of built-in.o. - Example: - #arch/i386/boot/Makefile - EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o - - In this example EXTRA_TARGETS is used to list all intermediate - targets, and all final targets. - The targets are added to EXTRA_TARGETS to enable 2) and 3) above. --- 6.6 Commands useful for building a boot image @@ -861,9 +832,10 @@ When kbuild executes the following steps are followed (roughly): needs an update, or the commandline has changed since last invocation. The latter will force a rebuild if any options to the executable have changed. - Any target that utilises if_changed must be listed in EXTRA_TARGETS, + Any target that utilises if_changed must be listed in $(targets), otherwise the command line check will fail, and the target will always be built. + Assignments to $(targets) are without $(obj)/ prefix. if_changed may be used in conjunction with custom commands as defined in 6.7 "Custom kbuild commands". Note: It is a typical mistake to forget the FORCE prerequisite. @@ -874,10 +846,34 @@ When kbuild executes the following steps are followed (roughly): objcopy Copy binary. Uses OBJCOPYFLAGS usually specified in arch/$(ARCH)/Makefile. + OBJCOPYFLAGS_$@ may be used to set additional options. gzip Compress target. Use maximum compression to compress target. + Example: + #arch/i386/boot/Makefile + LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary + LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext + + targets += setup setup.o bootsect bootsect.o + $(obj)/setup $(obj)/bootsect: %: %.o FORCE + $(call if_changed,ld) + + In this example there is two possible targets, requiring different + options to the linker. the linker options are specified using the + LDFLAGS_$@ syntax - one for each potential target. + $(targets) are assinged all potential targets, herby kbuild knows + the targets and will: + 1) check for commandline changes + 2) delete target during make clean + + The ": %: %.o" part of the prerequisite is a shorthand that + free us from listing the setup.o and bootsect.o files. + Note: It is a common mistake to forget the "target :=" assignment, + resulting in the target file being recompiled for no + obvious reason. + --- 6.7 Custom kbuild commands @@ -894,6 +890,7 @@ When kbuild executes the following steps are followed (roughly): cmd_image = $(obj)/tools/build $(BUILDFLAGS) \ $(obj)/vmlinux.bin > $@ + targets += bzImage $(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE $(call if_changed,image) @echo 'Kernel: $@ is ready' diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index bea73ad9347c..fb42e8662b58 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt @@ -21,7 +21,7 @@ are: This is a program for converting SGML template files into SGML files. When a file is referenced it is searched for symbols - exported (EXPORT_SYMBOL), to be able to distingush between internal + exported (EXPORT_SYMBOL), to be able to distinguish between internal and external functions. It invokes kernel-doc, giving it the list of functions that are to be documented. diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index 95f692f08263..e46d24a7cf34 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -488,7 +488,7 @@ memory allocation. Description: Article written for people wishing to make their data acquisition boards work on their GNU/Linux machines. Gives a basic - overview on writting drivers, from the naming of functions to + overview on writing drivers, from the naming of functions to interrupt handling. Notes: Two-parts article. Part II is at http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index eb5c056ad26c..a7057428743d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -71,6 +71,8 @@ In addition, the following text indicates that the option: Parameters denoted with BOOT are actually interpreted by the boot loader, and have no meaning to the kernel directly. +Do not modify the syntax of boot loader parameters without extreme +need or coordination with <Documentation/i386/boot.txt>. Note that ALL kernel parameters listed below are CASE SENSITIVE, and that a trailing = on the name of any parameter states that that parameter will @@ -502,30 +504,30 @@ running once the system is up. Format: <first>,<last> Specifies range of consoles to be captured by the MDA. - mem=exactmap [KNL,BOOT,IA-32] Enable setting of an exact - E820 memory map, as specified by the user. - Such mem=exactmap lines can be constructed based on - BIOS output or other requirements. See the mem=nn@ss - option description. - mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory Amount of memory to be used when the kernel is not able to see the whole system memory or for test. - mem=nn[KMG]@ss[KMG] - [KNL,BOOT] Force usage of a specific region of memory - Region of memory to be used, from ss to ss+nn. + mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel + memory. - mem=nn[KMG]#ss[KMG] - [KNL,BOOT,ACPI] Mark specific memory as ACPI data. + memmap=exactmap [KNL,IA-32] Enable setting of an exact + E820 memory map, as specified by the user. + Such memmap=exactmap lines can be constructed based on + BIOS output or other requirements. See the memmap=nn@ss + option description. + + memmap=nn[KMG]@ss[KMG] + [KNL] Force usage of a specific region of memory Region of memory to be used, from ss to ss+nn. - mem=nn[KMG]$ss[KMG] - [KNL,BOOT,ACPI] Mark specific memory as reserved. + memmap=nn[KMG]#ss[KMG] + [KNL,ACPI] Mark specific memory as ACPI data. Region of memory to be used, from ss to ss+nn. - mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel - memory. + memmap=nn[KMG]$ss[KMG] + [KNL,ACPI] Mark specific memory as reserved. + Region of memory to be used, from ss to ss+nn. memfrac= [KNL] diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt index bd5e3446365c..12acadc52e5d 100644 --- a/Documentation/kobject.txt +++ b/Documentation/kobject.txt @@ -7,7 +7,7 @@ Patrick Mochel <mochel@osdl.org> 0. Introduction -The kobject infrastructure performs basic object managment that larger +The kobject infrastructure performs basic object management that larger data structures and subsystems can leverage, rather than reimplement similar functionality. This functionality consists primarily concerns: diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index 9755756036f4..e88149116b64 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -146,7 +146,7 @@ HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h Note that there are also defined special per-driver magic numbers in sound -memory managment. See include/sound/sndmagic.h for complete list of them. Many +memory management. See include/sound/sndmagic.h for complete list of them. Many OSS sound drivers have their magic numbers constructed from the soundcard PCI ID - these are not listed here as well. diff --git a/Documentation/md.txt b/Documentation/md.txt index cecc9beba2fb..203231307a26 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -1,10 +1,10 @@ Tools that manage md devices can be found at - http://www.<country>.kernel.org/pub/linux/daemons/raid/.... + http://www.<country>.kernel.org/pub/linux/utils/raid/.... -You can boot (if you selected boot support in the configuration) with your md -device with the following kernel command lines: +You can boot with your md device with the following kernel command +lines: for old raid arrays without persistent superblocks: md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn @@ -33,4 +33,64 @@ dev0-devn: e.g. /dev/hda1,/dev/hdc1,/dev/sda1,/dev/sdb1 A possible loadlin line (Harald Hoyer <HarryH@Royal.Net>) looks like this: e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro - + +------------------------------- +The md driver can support a variety of different superblock formats. +(It doesn't yet, but it can) + +The kernel does *NOT* autodetect which format superblock is being +used. It must be told. + +Superblock format '0' is treated differently to others for legacy +reasons. + + +General Rules - apply for all superblock formats +------------------------------------------------ + +An array is 'created' by writing appropriate superblocks to all +devices. +It is 'assembled' by associating each of these devices with an +particular md virtual device. Once it is completely assembled, it can +be accessed. + +An array should be created by a user-space tool. This will write +superblocks to all devices. It will usually mark the array as +'unclean', or with some devices missing so that the kernel md driver +can create approrpriate redundancy (copying in raid1, parity +calculation in raid4/5). + +When an array is assembled, it is first initialised with the +SET_ARRAY_INFO ioctl. This contains, in particular, a major and minor +version number. The major version number selects which superblock +format is to be used. The minor number might be used to tune handling +of the format, such as suggesting where on each device to look for the +superblock. + +Then each device is added using the ADD_NEW_DISK ioctl. This +provides, in particular, a major and minor number identifying the +device to add. + +The array is started with the RUN_ARRAY ioctl. + +Once started, new devices can be added. They should have an +appropriate superblock written to them, and then passed be in with +ADD_NEW_DISK. + +Devices that have failed or are not yet active can be detached from an +array using HOT_REMOVE_DISK. + + +Specific Rules that apply to format-0 super block arrays, and + arrays with no superblock (non-presistant). +------------------------------------------------------------- + +An array can be 'created' by describing the array (level, chunksize +etc) in a SET_ARRAY_INFO ioctl. This must has major_version==0 and +raid_disks != 0. +Then uninitialised devices can be added with ADD_NEW_DISK. The +structure passed to ADD_NEW_DISK must specify the state of the device +and it's role in the array. + +One started with RUN_ARRAY, uninitialised spares can be added with +HOT_ADD_DISK. diff --git a/Documentation/networking/3c359.txt b/Documentation/networking/3c359.txt index 2babc3628acc..4af8071a6d18 100644 --- a/Documentation/networking/3c359.txt +++ b/Documentation/networking/3c359.txt @@ -41,7 +41,7 @@ the driver now re-sizes buffers based on MTU settings as well. message_level: Controls level of messages created by the driver. Defaults to 0: which only displays start-up and critical messages. Presently any non-zero value will display all soft messages as well. NB This does not turn -debuging messages on, that must be done by modified the source code. +debugging messages on, that must be done by modified the source code. Variable MTU size: diff --git a/Documentation/networking/3c509.txt b/Documentation/networking/3c509.txt index 85fe18219403..92b60517c8d3 100644 --- a/Documentation/networking/3c509.txt +++ b/Documentation/networking/3c509.txt @@ -106,7 +106,7 @@ For versions of the driver v1.18c and above, the available transceiver types are 8 transceiver type and duplex mode taken from card's EEPROM config settings 12 10baseT (RJ-45 connector); force full-duplex mode -Prior to driver version 1.18c, only tranceiver codes 0-4 were supported. Note +Prior to driver version 1.18c, only transceiver codes 0-4 were supported. Note that the new transceiver codes 8 and 12 are the *only* ones that will enable full-duplex mode, no matter what the card's detected EEPROM settings might be. This insured that merely upgrading the driver from an earlier version would @@ -146,7 +146,7 @@ you have a routing problem. Tx Carrier Errors Reported in /proc/net/dev If an EtherLink III appears to transmit packets, but the "Tx carrier errors" field in /proc/net/dev increments as quickly as the Tx packet count, you -likely have an unterminated network or the incorrect media tranceiver selected. +likely have an unterminated network or the incorrect media transceiver selected. 3c509B card is not detected on machines with an ISA PnP BIOS. While the updated driver works with most PnP BIOS programs, it does not work diff --git a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt index 149f57628a0d..0ce50b0711bc 100644 --- a/Documentation/networking/NAPI_HOWTO.txt +++ b/Documentation/networking/NAPI_HOWTO.txt @@ -85,7 +85,7 @@ There are two types of event register ACK mechanisms. In this case your only choice is to move all to dev->poll() II) Clear-on-write (COW) - i) you clear the status by writting a 1 in the bit-location you want. + i) you clear the status by writing a 1 in the bit-location you want. These are the majority of the NICs and work the best with NAPI. Put only receive events in dev->poll(); leave the rest in the old interrupt handler. @@ -200,7 +200,7 @@ dev->open = my_open; /* two new additions */ /* first register my poll method */ dev->poll = my_poll; -/* next register my weight/quanta; can be overriden in /proc */ +/* next register my weight/quanta; can be overridden in /proc */ dev->weight = 16; . . @@ -346,10 +346,10 @@ discussed further below. netif_rx_schedule_prep() returns 1 if device is in running state and gets successfully added to the core poll list. If we get a zero value we can _almost_ assume are already added to the list (instead of not running. -Logic based on the fact that you shouldnt get interrupt if not running) +Logic based on the fact that you shouldn't get interrupt if not running) We rectify this by disabling rx and rxnobuf interrupts. -II) that receive_packets(dev) and make_rx_buffs_avail() may have dissapeared. +II) that receive_packets(dev) and make_rx_buffs_avail() may have disappeared. These functionalities are still around actually...... infact, receive_packets(dev) is very close to my_poll() and @@ -442,7 +442,7 @@ static void my_poll (struct net_device *dev, int *budget) int rx_work_limit = dev->quota; /************************ end note note *********************************/ - do { // outer beggining loop starts here + do { // outer beginning loop starts here clear_rx_status_register_bit(); diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 17e1ff8d3c6c..558fe2334bc9 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -304,7 +304,7 @@ options bond1 -o bonding1 miimon=100 Configuring Multiple ARP Targets ================================ -While ARP monitoring can be done with just one target, it can be usefull +While ARP monitoring can be done with just one target, it can be useful in a High Availability setup to have several targets to monitor. In the case of just one target, the target itself may go down or have a problem making it unresponsive to ARP requests. Having an additional target (or diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c index 8ab614ec0f44..2e64bcbc295c 100644 --- a/Documentation/networking/ifenslave.c +++ b/Documentation/networking/ifenslave.c @@ -540,7 +540,7 @@ main(int argc, char **argv) static short mif_flags; -/* Get the inteface configuration from the kernel. */ +/* Get the interface configuration from the kernel. */ static int if_getconfig(char *ifname) { struct ifreq ifr; diff --git a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt index 6e864fe53e29..cab486f5ba8a 100644 --- a/Documentation/networking/sis900.txt +++ b/Documentation/networking/sis900.txt @@ -243,7 +243,7 @@ Chapter 6. Known Problems and Bugs Chapter 7. Revision History * November 13, 2000, Revision 1.07, seventh release, 630E problem - fixed and furthur clean up. + fixed and further clean up. * November 4, 1999, Revision 1.06, Second release, lots of clean up and optimization. * August 8, 1999, Revision 1.05, Initial Public Release diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt index b0220f4dc19d..e099631ddf3b 100644 --- a/Documentation/networking/sk98lin.txt +++ b/Documentation/networking/sk98lin.txt @@ -138,7 +138,7 @@ Insert a line of the form: options sk98lin ... For "...", use the same syntax as described below for the command -line paramaters of modprobe. +line parameters of modprobe. You either have to reboot your computer or unload and reload the driver to activate the new parameters. The syntax of the driver parameters is: @@ -276,7 +276,7 @@ which you set the parameter (A or B). Large frames (also called jumbo frames) are now supported by the driver. This can result in a greatly improved throughput if -transfering large amounts of data. +transferring large amounts of data. To enable large frames, set the MTU (maximum transfer unit) of the interface to the value you wish (up to 9000). The command for this is: @@ -489,7 +489,7 @@ Problems fixed: established (#10402) - Installation problems with RedHat 6.0 (#10409) New Features: -- Connection state ouput at "network connection up" +- Connection state output at "network connection up" Known limitations: - None diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt index 87038ae671b5..bcbd1e745295 100644 --- a/Documentation/networking/tuntap.txt +++ b/Documentation/networking/tuntap.txt @@ -40,7 +40,7 @@ Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com> Set permissions: e.g. chmod 0700 /dev/net/tun - if you want the device only accesible by root. Giving regular users the + if you want the device only accessible by root. Giving regular users the right to assign network devices is NOT a good idea. Users could assign bogus network interfaces to trick firewalls or administrators. diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt index 3db226945bee..aea20cd2a56e 100644 --- a/Documentation/networking/wan-router.txt +++ b/Documentation/networking/wan-router.txt @@ -577,7 +577,7 @@ bata1-2.2.1 Feb 09 2001 bata2-2.2.1 Feb 20 2001 o Bug fixes to the CHDLC device drivers. - The driver had compilation problmes under kernels + The driver had compilation problems under kernels 2.2.14 or lower. o Bug fixes to the Setup installation script. diff --git a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt index 3db226945bee..aea20cd2a56e 100644 --- a/Documentation/networking/wanpipe.txt +++ b/Documentation/networking/wanpipe.txt @@ -577,7 +577,7 @@ bata1-2.2.1 Feb 09 2001 bata2-2.2.1 Feb 20 2001 o Bug fixes to the CHDLC device drivers. - The driver had compilation problmes under kernels + The driver had compilation problems under kernels 2.2.14 or lower. o Bug fixes to the Setup installation script. diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index 22014567a14f..d9f25e1d8ca0 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt @@ -219,7 +219,7 @@ characters, each representing a particular tainted value. 2: 'F' if any module was force loaded by insmod -f, ' ' if all modules were loaded normally. - 3: 'S' if the oops occured on an SMP kernel running on hardware that + 3: 'S' if the oops occurred on an SMP kernel running on hardware that hasn't been certified as safe to run multiprocessor. Currently this occurs only on various Athlons that are not SMP capable. diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt index 1248516331f5..c9eb5dd64ff4 100644 --- a/Documentation/pnp.txt +++ b/Documentation/pnp.txt @@ -96,7 +96,7 @@ The Unified Plug and Play Layer All Plug and Play drivers, protocols, and services meet at a central location called the Plug and Play Layer. This layer is responsible for the exchange of information between PnP drivers and PnP protocols. Thus it automatically -forwards commands to the proper protocol. This makes writting PnP drivers +forwards commands to the proper protocol. This makes writing PnP drivers significantly easier. The following functions are available from the Plug and Play Layer: diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt index b14a3f3149e6..adbfe620c061 100644 --- a/Documentation/s390/Debugging390.txt +++ b/Documentation/s390/Debugging390.txt @@ -52,7 +52,7 @@ The current architectures have the following registers. 16 General propose registers, 32 bit on s/390 64 bit on z/Architecture, r0-r15 or gpr0-gpr15 used for arithmetic & addressing. -16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory managment, +16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory management, interrupt control,debugging control etc. 16 Access registers ( ar0-ar15 ) 32 bit on s/390 & z/Architecture @@ -243,7 +243,7 @@ of our 32 bit addresses,however, we use entirely separate address spaces for the user & kernel. This means we can support 2GB of non Extended RAM on s/390, & more -with the Extended memory managment swap device & +with the Extended memory management swap device & currently 4TB of physical memory currently on z/Architecture. @@ -385,7 +385,7 @@ This is a built in compiler function for runtime allocation of extra space on the callers stack which is obviously freed up on function exit ( e.g. the caller may choose to allocate nothing of a buffer of 4k if required for temporary purposes ), it generates -very efficent code ( a few cycles ) when compared to alternatives +very efficient code ( a few cycles ) when compared to alternatives like malloc. automatics: These are local variables on the stack, @@ -1091,7 +1091,7 @@ e.g. The address range 0x2000 to 0x3000 can be described described as The VM Debugger is case insensitive. VM's strengths are usually other debuggers weaknesses you can get at any resource -no matter how sensitive e.g. memory managment resources,change address translation +no matter how sensitive e.g. memory management resources,change address translation in the PSW. For kernel hacking you will reap dividends if you get good at it. The VM Debugger displays operators but not operands, probably because some @@ -1194,7 +1194,7 @@ displays the gprs on each step. Displaying & modifying Registers -------------------------------- D G will display all the gprs -Adding a extra G to all the commands is neccessary to access the full 64 bit +Adding a extra G to all the commands is necessary to access the full 64 bit content in VM on z/Architecture obviously this isn't required for access registers as these are still 32 bit. e.g. DGG instead of DG @@ -1280,7 +1280,7 @@ so it would be foolish to use this as the default on a production machine. Tracing particular processes ---------------------------- -The kernels text segment is intentionally at an address in memory that it will +The kernel's text segment is intentionally at an address in memory that it will very seldom collide with text segments of user programs ( thanks Martin ), this simplifies debugging the kernel. However it is quite common for user processes to have addresses which collide @@ -1425,7 +1425,7 @@ from the bash prompt issue shutdown -h now or halt. do a Q CPUS to find out how many cpus you have detach each one of them from cp except cpu 0 -by issueing a +by issuing a DETACH CPU 01-(number of cpus in configuration) & boot linux again. TR SIGP will trace inter processor signal processor instructions. @@ -1671,7 +1671,7 @@ compatibility & Format 1 ( 31 bit ). These are typically used to issue read & wr ( & many other instructions ) they consist of a length field & an absolute address field. For each IO typically get 1 or 2 interrupts one for channel end ( primary status ) when the channel is idle & the second for device end ( secondary status ) sometimes you get both -concurrently, you check how the IO went on by issueing a TEST SUBCHANNEL at each interrupt, +concurrently, you check how the IO went on by issuing a TEST SUBCHANNEL at each interrupt, from which you receive an Interruption response block (IRB). If you get channel & device end status in the IRB without channel checks etc. your IO probably went okay. If you didn't you probably need a doctorto examine the IRB & extended status word etc. @@ -2153,14 +2153,14 @@ program as if it just crashed on your system, it is usually called core & create current working directory. This is very useful in that a customer can mail a core dump to a technical support department & the technical support department can reconstruct what happened. -Provided the have an indentical copy of this program with debugging symbols compiled in & +Provided the have an identical copy of this program with debugging symbols compiled in & the source base of this build is available. In short it is far more useful than something like a crash log could ever hope to be. In theory all that is missing to restart a core dumped program is a kernel patch which will do the following. 1) Make a new kernel task structure -2) Reload all the dumped pages back into the kernels memory managment structures. +2) Reload all the dumped pages back into the kernel's memory management structures. 3) Do the required clock fixups 4) Get all files & network connections for the process back into an identical state ( really difficult ). 5) A few more difficult things I haven't thought of. @@ -2374,7 +2374,7 @@ for more info. e.g. to switch on the lcs "debug feature" echo 5 > /proc/s390dbf/lcs/level -& then after the error occured. +& then after the error occurred. cat /proc/s390dbf/lcs/sprintf >/logfile the logfile now contains some information which may help tech support resolve a problem in the field. @@ -2462,9 +2462,9 @@ Michael Holzheu & others here at IBM have a fairly mature port of SGI's lcrash tool which allows one to look at kernel structures in a running kernel. -It also complements a tool called dumptool which dumps all the kernels +It also complements a tool called dumptool which dumps all the kernel's memory pages & registers to either a tape or a disk. -This can be used by tech support or an ambitous end user do +This can be used by tech support or an ambitious end user do post mortem debugging of a machine like gdb core dumps. Going into how to use this tool in detail will be explained diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt index 2fdb68782b48..d9397170fb36 100644 --- a/Documentation/s390/cds.txt +++ b/Documentation/s390/cds.txt @@ -214,7 +214,7 @@ int read_conf_data(struct ccw_device, void **buffer, int *length, __u8 lpm); cdev - the ccw_device the data is requested for. buffer - Pointer to a buffer pointer. The read_conf_data() routine will allocate a buffer and initialize the buffer pointer - accordingly. It's the device driver's responsability to + accordingly. It's the device driver's responsibility to release the kernel memory if no longer needed. length - Length of the buffer allocated and retrieved. lpm - Logical path mask to be used for retrieving the data. If @@ -224,7 +224,7 @@ The read_conf_data() function returns : 0 - Successful completion -ENODEV - cdev invalid. -EINVAL - An invalid parameter was detected, or the function was called early. --EIO - An irrecoverable I/O error occured or the device is +-EIO - An irrecoverable I/O error occurred or the device is not operational. -ENOMEM - The read_conf_data() routine couldn't obtain storage. -EOPNOTSUPP - The device doesn't support the read configuration @@ -428,7 +428,7 @@ Above flag allows to exploit this feature, e.g. for communication devices that can handle lost data on the network to allow for enhanced I/O processing. Unless the channel subsystem at any time presents a secondary status interrupt, -exploiting this feature will cause only primary status interrups to be +exploiting this feature will cause only primary status interrupts to be presented to the device driver while overlapping I/O is performed. When a secondary status without error (alert status) is presented, this indicates successful completion for all overlapping ccw_device_start() requests that have diff --git a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt index db9544fbea33..e1cf3eae68de 100644 --- a/Documentation/s390/driver-model.txt +++ b/Documentation/s390/driver-model.txt @@ -53,7 +53,7 @@ This is done in several steps. a. Each driver can provide one or more parameter interfaces where parameters can be specified. These interfaces are also in the driver's responsibility. -b. After a. has been performed, if neccessary, the device is finally brought up +b. After a. has been performed, if necessary, the device is finally brought up via the 'online' interface. @@ -145,7 +145,7 @@ Parameters: cdev - the device to be deactivated. The common layer has The handler field of the struct ccw_device is meant to be set to the interrupt -handler for the device. In order to accomodate drivers which use several +handler for the device. In order to accommodate drivers which use several distinct handlers (e.g. multi subchannel devices), this is a member of ccw_device instead of ccw_driver. The handler is registered with the common layer during set_online() processing diff --git a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx index c91e792cab27..7d03e9d5b5f7 100644 --- a/Documentation/scsi/ChangeLog.ncr53c8xx +++ b/Documentation/scsi/ChangeLog.ncr53c8xx @@ -247,7 +247,7 @@ Wed Oct 21 21:00 1998 Gerard Roudier (groudier@club-internet.fr) - Add the 53c876 description to the chip table. This is only useful for printing the right name of the controller. - DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15). - - Add additionnal checking of INQUIRY data: + - Add additional checking of INQUIRY data: Check INQUIRY data received length is at least 7. Byte 7 of inquiry data contains device features bits and the driver might be confused by garbage. Also check peripheral qualifier. @@ -420,7 +420,7 @@ Sat Apr 4 20:00 1998 Gerard Roudier (groudier@club-internet.fr) - Split DATA_IN and DATA_OUT scripts into 2 sub-scripts. 64 segments are moved from on-chip RAM scripts. If more segments, a script in main memory is used for the - additionnal segments. + additional segments. - Since the SCRIPTS processor continues SCRIPTS execution after having won arbitration, do some stuff prior to testing any SCSI phase on reselection. This should have the vertue to process @@ -475,7 +475,7 @@ Sun Jan 11 22:00 1998 Gerard Roudier (groudier@club-internet.fr) ------------------------------ - Use FAST-5 instead of SLOW for slow scsi devices according to new SPI-2 draft. - - Make some changes in order to accomodate with 875 rev <= 3 + - Make some changes in order to accommodate with 875 rev <= 3 device errata listing 397. Minor consequences are: . Leave use of PCI Write and Invalidate under user control. Now, by default the driver does not enable PCI MWI and option diff --git a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx index 8dc00328bf94..ef985ec348e6 100644 --- a/Documentation/scsi/ChangeLog.sym53c8xx +++ b/Documentation/scsi/ChangeLog.sym53c8xx @@ -15,7 +15,7 @@ Sat Apr 7 19:30 2001 Gerard Roudier (groudier@club-internet.fr) - In ncr_soft_reset(), only try to ABORT the current operation for chips that support SRUN bit in ISTAT1 and if SCRIPTS are currently running, as 896 and 1010 manuals suggest. - - In the CCB abort path, donnot assume that the CCB is currently + - In the CCB abort path, do not assume that the CCB is currently queued to SCRIPTS. This is not always true, notably after a QUEUE FULL status or when using untagged commands. @@ -562,7 +562,7 @@ Tue Oct 20 22H00 1998 Gerard Roudier (groudier@club-internet.fr) * version pre-sym53c8xx-0.10 - Add the 53c876 description to the chip table. This is only useful for printing the right name of the controller. - - Add additionnal checking of INQUIRY data: + - Add additional checking of INQUIRY data: Check INQUIRY data received length is at least 7. Byte 7 of inquiry data contains device features bits and the driver might be confused by garbage. Also check peripheral qualifier. diff --git a/Documentation/scsi/ChangeLog.sym53c8xx_2 b/Documentation/scsi/ChangeLog.sym53c8xx_2 index 66934a9ddc9e..18a5d712a56a 100644 --- a/Documentation/scsi/ChangeLog.sym53c8xx_2 +++ b/Documentation/scsi/ChangeLog.sym53c8xx_2 @@ -32,7 +32,7 @@ Wed Jan 24 21:00 2001 Gerard Roudier missing free of this memory on instance detach. - Check against GPIO3 pulled low for HVD controllers (driver did just the opposite). - Misdetection of BUS mode was triggerred on module reload only, + Misdetection of BUS mode was triggered on module reload only, since BIOS settings were trusted instead on first load. Wed Feb 7 21:00 2001 Gerard Roudier @@ -71,7 +71,7 @@ Tues Apr 10 21:00 2001 Gerard Roudier #LUN <= 7. - Set busy_itl in LCB to 1 if the LCB is allocated and a SCSI command is active. This is a simplification. - - In sym_hcb_free(), donnot scan the free_ccbq if no CCBs + - In sym_hcb_free(), do not scan the free_ccbq if no CCBs has been allocated. This fixes a panic if attach failed. - Add DT/ST (double/simple transition) in the transfer negotiation announce. diff --git a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt index daaab2c057f9..6e45e70243e5 100644 --- a/Documentation/scsi/dpti.txt +++ b/Documentation/scsi/dpti.txt @@ -75,7 +75,7 @@ * to the board. * * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the - * interface files for Adaptecs managment routines. These define the structures used + * interface files for Adaptec's management routines. These define the structures used * in the ioctls. They are written to be portable. They are hard to read, but I need * to use them 'as is' or I can miss changes in the interface. * diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt index 9322203ed655..2814491600ff 100644 --- a/Documentation/scsi/ibmmca.txt +++ b/Documentation/scsi/ibmmca.txt @@ -810,9 +810,9 @@ commandline parameter is added, called 'activity'. 2) Added the READ_CONTROL bit for test_unit_ready SCSI-command. 3) Added some suppress_exception bits to read_device_capacity and - all device_inquiry occurences in the driver code. + all device_inquiry occurrences in the driver code. 4) Complaints about the various KERNEL_VERSION implementations are - taken into account. Every local_LinuxKernelVersion occurence is + taken into account. Every local_LinuxKernelVersion occurrence is now replaced by KERNEL_VERSION, defined in linux/version.h. Corresponding changes were applied to ibmmca.h, too. This was a contribution to all kernel-parts by Philipp Hahn. @@ -866,7 +866,7 @@ 2) Adapter-information and autoadaption to address-space is done. 3) Auto-probing for maximum synchronous SCSI transfer rate is working. 4) Optimization to some embedded function calls is applied. - 5) Added some comment for the user to wait for SCSI-devices beeing probed. + 5) Added some comment for the user to wait for SCSI-devices being probed. 6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but... - Michael Lang @@ -966,7 +966,7 @@ ------DA where '-' stays dark, 'D' shows the SCSI-device id - and 'A' shows the SCSI hostindex, beeing currently + and 'A' shows the SCSI hostindex, being currently accessed. During boottime, this will give the message SCSIini* @@ -1091,7 +1091,7 @@ now. Normally you really won't need to activate this flag in the kernel configuration, as all post 1989 SCSI-devices should accept the reset-signal, when the computer is switched on. The SCSI- - subsystem generates this reset while beeing initialized. This flag + subsystem generates this reset while being initialized. This flag is really reserved for users with very old, very strange or self-made SCSI-devices. Q: Why is the SCSI-order of my drives mirrored to the device-order diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt index 514c2be6ba12..fef2af3ee9e7 100644 --- a/Documentation/scsi/ncr53c8xx.txt +++ b/Documentation/scsi/ncr53c8xx.txt @@ -238,7 +238,7 @@ Queuing more than 1 command at a time to a device allows it to perform optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. In order to really gain advantage of this feature, devices must have -a reasonnable cache size (No miracle is to be expected for a low-end +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). Some kown SCSI devices do not properly support tagged command queuing. Generally, firmware revisions that fix this kind of problems are available @@ -592,7 +592,7 @@ CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO (default answer: n) Some SCSI-2 devices do not report this feature in byte 7 of inquiry response but do support it properly (TAMARACK scanners for example). -CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonnable answer: n) +CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonable answer: n) If you suspect a device of yours does not properly support disconnections, you can answer "y". Then, all SCSI devices will never disconnect the bus even while performing long SCSI operations. @@ -827,7 +827,7 @@ port address 0x1400. Available option bits: 0x0: No check. - 0x1: Check and donnot attach the controller on error. + 0x1: Check and do not attach the controller on error. 0x2: Check and just warn on error. 0x4: Disable SCSI bus integrity checking. @@ -850,7 +850,7 @@ port address 0x1400. 10.2.22 Enable use of IMMEDIATE ARBITRATION (only supported by the sym53c8xx driver. See 10.7 for more details) - iarb:0 donnot use this feature. + iarb:0 do not use this feature. iarb:#x use this feature according to bit fields as follow: bit 0 (1) : enable IARB each time the initiator has been reselected @@ -880,7 +880,7 @@ Boot fail safe settle time 10 seconds settle:10 differential support from BIOS settings diff:1 irq mode from BIOS settings irqm:1 - SCSI BUS check donnot attach on error buschk:1 + SCSI BUS check do not attach on error buschk:1 immediate arbitration disabled iarb:0 10.3 Advised boot setup commands @@ -1272,7 +1272,7 @@ following things: - terminations at both end of the SCSI chain - linux syslog messages (some of them may help you) -If you donnot find the source of problems, you can configure the +If you do not find the source of problems, you can configure the driver with no features enabled. - only asynchronous data transfers @@ -1345,14 +1345,14 @@ Field B : DSTAT io register (DMA STATUS) Field C : SIST io register (SCSI Interrupt Status) Bit 0x08 : SGE SCSI GROSS ERROR Indicates that the chip detected a severe error condition - on the SCSI BUS that prevents the SCSI protocol from functionning + on the SCSI BUS that prevents the SCSI protocol from functioning properly. - Bit 0x04 : UDC Undexpected Disconnection + Bit 0x04 : UDC Unexpected Disconnection Indicates that the device released the SCSI BUS when the chip was not expecting this to happen. A device may behave so to indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred. Bit 0x02 : RST SCSI BUS Reset - Generally SCSI targets donnot reset the SCSI BUS, although any + Generally SCSI targets do not reset the SCSI BUS, although any device on the BUS can reset it at any time. Bit 0x01 : PAR Parity SCSI parity error detected. diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt index 713afc8f919b..137a51466caf 100644 --- a/Documentation/scsi/sym53c8xx_2.txt +++ b/Documentation/scsi/sym53c8xx_2.txt @@ -205,7 +205,7 @@ Queuing more than 1 command at a time to a device allows it to perform optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. In order to really gain advantage of this feature, devices must have -a reasonnable cache size (No miracle is to be expected for a low-end +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). Some kown old SCSI devices do not properly support tagged command queuing. Generally, firmware revisions that fix this kind of problems are available @@ -579,7 +579,7 @@ characters and digits are allowed. Available option bits: 0x0: No check. - 0x1: Check and donnot attach the controller on error. + 0x1: Check and do not attach the controller on error. 0x2: Check and just warn on error. 10.2.16 Exclude a host from being attached @@ -698,7 +698,7 @@ following things: - terminations at both end of the SCSI chain - linux syslog messages (some of them may help you) -If you donnot find the source of problems, you can configure the +If you do not find the source of problems, you can configure the driver or devices in the NVRAM with minimal features. - only asynchronous data transfers @@ -756,14 +756,14 @@ Field B : DSTAT io register (DMA STATUS) Field C : SIST io register (SCSI Interrupt Status) Bit 0x08 : SGE SCSI GROSS ERROR Indicates that the chip detected a severe error condition - on the SCSI BUS that prevents the SCSI protocol from functionning + on the SCSI BUS that prevents the SCSI protocol from functioning properly. - Bit 0x04 : UDC Undexpected Disconnection + Bit 0x04 : UDC Unexpected Disconnection Indicates that the device released the SCSI BUS when the chip was not expecting this to happen. A device may behave so to - indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occured. + indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred. Bit 0x02 : RST SCSI BUS Reset - Generally SCSI targets donnot reset the SCSI BUS, although any + Generally SCSI targets do not reset the SCSI BUS, although any device on the BUS can reset it at any time. Bit 0x01 : PAR Parity SCSI parity error detected. diff --git a/Documentation/sonypi.txt b/Documentation/sonypi.txt index 31858ae77691..e66812867f27 100644 --- a/Documentation/sonypi.txt +++ b/Documentation/sonypi.txt @@ -130,7 +130,7 @@ Bugs: tested) when using the driver with the fnkeyinit parameter. I cannot reproduce it on my laptop and not all users have this problem. This happens because the fnkeyinit parameter enables the ACPI - mode (but without additionnal ACPI control, like processor + mode (but without additional ACPI control, like processor speed handling etc). Use ACPI instead of APM if it works on your laptop. diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index dddadd2cdc2d..94a562fab973 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -659,7 +659,7 @@ Module parameters Module supports autoprobe and multiple chips (max 8). Note: on some notebooks the buffer address cannot be detected automatically, or causes hang-up during initialization. - In such a case, specify the buffer top address explicity via + In such a case, specify the buffer top address explicitly via buffer_top option. For example, Sony F250: buffer_top=0x25a800 diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 75a6d70a66d3..df92be751d1a 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -2807,7 +2807,7 @@ </para> <para> - If you aquire a spinlock in the interrupt handler, and the + If you acquire a spinlock in the interrupt handler, and the lock is used in other pcm callbacks, too, then you have to release the lock before calling <function>snd_pcm_period_elapsed()</function>, because diff --git a/Documentation/sound/oss/NEWS b/Documentation/sound/oss/NEWS index de09b8c0a151..a81e0ef72ae9 100644 --- a/Documentation/sound/oss/NEWS +++ b/Documentation/sound/oss/NEWS @@ -19,7 +19,7 @@ and its driver(s) so I can try to get isapnp working for it. Before Linux 2.4 you had to specify the resources for sounddrivers statically linked into the kernel at compile time -(in make config/menuconfig/xconfig). In Linux 2.4 the ressources are +(in make config/menuconfig/xconfig). In Linux 2.4 the resources are now specified at the boot-time kernel commandline (e.g. the lilo 'append=' line or everything that's after the kernel name in grub). Read the Configure.help entry for your card for the parameters. diff --git a/Documentation/sound/oss/PSS-updates b/Documentation/sound/oss/PSS-updates index 5cb80656c6bf..c84dd7597e64 100644 --- a/Documentation/sound/oss/PSS-updates +++ b/Documentation/sound/oss/PSS-updates @@ -22,12 +22,12 @@ pss_cdrom_port This parameter takes a port address as its parameter. Any available port address can be specified to enable the CDROM port, except for 0x0 and -1 as these values would leave the port disabled. Like the joystick port, the cdrom -port will require that an appropiate CDROM driver be loaded before you can make +port will require that an appropriate CDROM driver be loaded before you can make use of the newly enabled CDROM port. Like the joystick port option above, remember to load the CDROM driver AFTER the pss sound driver. While it may differ on some PSS sound cards, all the PSS sound cards that I have seen have a builtin Wearnes CDROM port. If this is the case with your PSS sound card you -should load aztcd with the appropiate port option that matches the port you +should load aztcd with the appropriate port option that matches the port you assigned to the CDROM port when you loaded your pss sound driver. (ex. modprobe pss pss_cdrom_port=0x340 && modprobe aztcd aztcd=0x340) The default setting of this parameter leaves the CDROM port disabled to maintain full @@ -44,7 +44,7 @@ just configure non-sound components. 0 configures all components, a non-0 value will only attept to configure the CDROM and joystick ports. This parameter can be used by a user who only wished to use the builtin joystick and/or CDROM port(s) of his PSS sound card. If this driver is loaded with this -parameter and with the paramter below set to true then a user can safely unload +parameter and with the parameter below set to true then a user can safely unload this driver with the following command "rmmod pss && rmmod ad1848 && rmmod mpu401 && rmmod sound && rmmod soundcore" and retain the full functionality of his CDROM and/or joystick port(s) while gaining back the memory previously used diff --git a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx index 1f93c03ceaa4..88d6cf8b39f3 100644 --- a/Documentation/sound/oss/cs46xx +++ b/Documentation/sound/oss/cs46xx @@ -78,7 +78,7 @@ additional printfs to be active. Comment out the following line in the driver to disable compilation of the CS_DBGOUT print statements: #define CSDEBUG 1 -Please see the defintions for cs_debuglevel and cs_debugmask for additional +Please see the definitions for cs_debuglevel and cs_debugmask for additional information on the debug levels and sections. There is also a csdbg executable to allow runtime manipulation of these diff --git a/Documentation/specialix.txt b/Documentation/specialix.txt index 75e80cde8c2c..4a4b428ce8f6 100644 --- a/Documentation/specialix.txt +++ b/Documentation/specialix.txt @@ -326,7 +326,7 @@ it doesn't fit in your computer, bring back the card. Fixed bugs and restrictions: - - During intialization, interrupts are blindly turned on. + - During initialization, interrupts are blindly turned on. Having a shadow variable would cause an extra memory access on every IO instruction. - The interrupt (on the card) should be disabled when we diff --git a/Documentation/swsusp.txt b/Documentation/swsusp.txt index 9a8fd611d139..2f07ee495997 100644 --- a/Documentation/swsusp.txt +++ b/Documentation/swsusp.txt @@ -90,7 +90,7 @@ checks whether we have anything in our run queue tq_bdflush. Since we queued up function do_software_suspend, it is called. Here we shrink everything including dcache, inodes, buffers and memory (here mainly processes are swapped out). We count how many pages we need to duplicate (we have to be atomical!) then we -create an appropiate sized page directory. It will point to the original and +create an appropriate sized page directory. It will point to the original and the new (copied) address of the page. We get the free pages by __get_free_pages() but since it changes state we have to be able to track it later so it also flips in a bit in page's flags (a new Nosave flag). We diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 23eddf174e41..230c05996bd9 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -36,6 +36,10 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>, On other - If you know of the key combos for other architectures, please let me know so I can add them to this section. +On all - write a character to /proc/sysrq-trigger. eg: + + echo t > /proc/sysrq-trigger + * What are the 'command' keys? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'r' - Turns off keyboard raw mode and sets it to XLATE. diff --git a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt index 2950ab0012bf..0c7b654fec99 100644 --- a/Documentation/uml/UserModeLinux-HOWTO.txt +++ b/Documentation/uml/UserModeLinux-HOWTO.txt @@ -2509,7 +2509,7 @@ 1100..88.. ssttoopp This puts the UML in a loop reading mconsole requests until a 'go' - mconsole command is recieved. This is very useful for making backups + mconsole command is received. This is very useful for making backups of UML filesystems, as the UML can be stopped, then synced via 'sysrq s', so that everything is written to the filesystem. You can then copy the filesystem and then send the UML 'go' via mconsole. diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt index d25d24614e36..6c508f192f99 100644 --- a/Documentation/usb/URB.txt +++ b/Documentation/usb/URB.txt @@ -86,7 +86,7 @@ URBs are allocated with the following call Return value is a pointer to the allocated URB, 0 if allocation failed. The parameter isoframes specifies the number of isochronous transfer frames -you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags paramter +you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags parameter holds standard memory allocation flags, letting you control (among other things) whether the underlying code may block or not. diff --git a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt index 26c5dde778d1..cd6fb4b58e1f 100644 --- a/Documentation/usb/hiddev.txt +++ b/Documentation/usb/hiddev.txt @@ -173,7 +173,7 @@ Returns the value of a usage in a hiddev_usage_ref structure. The usage to be retrieved can be specified as above, or the user can choose to fill in the report_type field and specify the report_id as HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be -filled in with the report and field infomation associated with this +filled in with the report and field information associated with this usage if it is found. HIDIOCSUSAGE - struct hiddev_usage_ref (write) diff --git a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt index 926e17dfb975..5cb2089e81d0 100644 --- a/Documentation/usb/philips.txt +++ b/Documentation/usb/philips.txt @@ -27,9 +27,9 @@ fps Specifies the desired framerate. Is an integer in the range of 4-30. fbufs - This paramter specifies the number of internal buffers to use for storing + This parameter specifies the number of internal buffers to use for storing frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarely busy. However, on slow machines it + the cam is a bit slow or momentarily busy. However, on slow machines it only introduces lag, so choose carefully. The default is 3, which is reasonable. You can set it between 2 and 5. diff --git a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt index 9119bde035d0..1a09de3199e1 100644 --- a/Documentation/usb/scanner.txt +++ b/Documentation/usb/scanner.txt @@ -282,7 +282,7 @@ main(void) { } if((fpout=fopen("out.dat", "w+")) == NULL) { - perror("Unable to open ouput file"); + perror("Unable to open output file"); exit(1); } diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ index b00218162d58..a1d7f229e1ec 100644 --- a/Documentation/video4linux/bttv/Sound-FAQ +++ b/Documentation/video4linux/bttv/Sound-FAQ @@ -15,18 +15,18 @@ log, telling which card type is used. Like this one: bttv0: model: BT848(Hauppauge old) [autodetected] -You should verify this is correct. If it is'nt, you have to pass the +You should verify this is correct. If it isn't, you have to pass the correct board type as insmod argument, "insmod bttv card=2" for example. The file CARDLIST has a list of valid arguments for card. -If your card is'nt listed there, you might check the source code for -new entries which are not listed yet. If there is'nt one for your +If your card isn't listed there, you might check the source code for +new entries which are not listed yet. If there isn't one for your card, you can check if one of the existing entries does work for you (just trial and error...). Some boards have an extra processor for sound to do stereo decoding and other nice features. The msp34xx chips are used by Hauppauge for example. If your board has one, you might have to load a helper -module like msp3400.o to make sound work. If there is'nt one for the +module like msp3400.o to make sound work. If there isn't one for the chip used on your board: Bad luck. Start writing a new one. Well, you might want to check the video4linux mailing list archive first... diff --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt index 96ecaa8978ba..4af6c52595eb 100644 --- a/Documentation/video4linux/zr36120.txt +++ b/Documentation/video4linux/zr36120.txt @@ -146,10 +146,10 @@ found in the kernel, but it doesn't need it. The consequence is that, when loading the driver as a module, the module may tell you it's out of memory, but 'free' says otherwise. The reason is simple; the modules wants its memory -contingious, not fragmented, and after a long uptime there +contiguous, not fragmented, and after a long uptime there probably isn't a fragment of memory large enough... -The driver uses a double buffering scheme, which should realy +The driver uses a double buffering scheme, which should really be an n-way buffer, depending on the size of allocated framebuffer and the requested grab-size/format. This current version also fixes a dead-lock situation during irq diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index d0d883cdce90..dfd6b007a8d4 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt @@ -69,7 +69,7 @@ type hugetlbfs: mount none /mnt/huge -t hugetlbfs -This commands mounts a (psuedo) filesystem of type hugetlbfs on the directory +This command mounts a (pseudo) filesystem of type hugetlbfs on the directory /mnt/huge. Any files created on /mnt/huge uses hugepages. An example is given at the end of this document. @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 64 +SUBLEVEL = 65 EXTRAVERSION = # *DOCUMENTATION* @@ -198,7 +198,7 @@ export MODVERDIR := .tmp_versions comma := , depfile = $(subst $(comma),_,$(@D)/.$(@F).d) -noconfig_targets := xconfig menuconfig config oldconfig randconfig \ +noconfig_targets := xconfig gconfig menuconfig config oldconfig randconfig \ defconfig allyesconfig allnoconfig allmodconfig \ clean mrproper distclean rpm \ help tags TAGS cscope sgmldocs psdocs pdfdocs htmldocs \ @@ -327,15 +327,16 @@ endef # set -e makes the rule exit immediately on error define rule_vmlinux__ - set -e \ + set -e; \ $(if $(filter .tmp_kallsyms%,$^),, \ echo ' GEN .version'; \ . $(srctree)/scripts/mkversion > .tmp_version; \ mv -f .tmp_version .version; \ $(MAKE) $(build)=init; \ - ) - set -e \ - $(call cmd,vmlinux__); \ + ) \ + $(if $($(quiet)cmd_vmlinux__), \ + echo ' $($(quiet)cmd_vmlinux__)' &&) \ + $(cmd_vmlinux__); \ echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd endef @@ -478,17 +479,19 @@ include/linux/autoconf.h: .config scripts/fixdep uts_len := 64 -include/linux/version.h: Makefile - @if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \ +define filechk_version.h + if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \ echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \ exit 1; \ fi; - @echo -n ' GEN $@' - @(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \ + (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \ echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \ echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \ - ) > $@.tmp - @$(update-if-changed) + ) +endef + +include/linux/version.h: Makefile + $(call filechk,version.h) # --------------------------------------------------------------------------- @@ -557,7 +560,7 @@ endif # CONFIG_MODULES # Generate asm-offsets.h # --------------------------------------------------------------------------- -define generate-asm-offsets.h +define filechk_gen-asm-offsets (set -e; \ echo "#ifndef __ASM_OFFSETS_H__"; \ echo "#define __ASM_OFFSETS_H__"; \ @@ -573,7 +576,6 @@ define generate-asm-offsets.h echo "#endif" ) endef - else # ifdef include_config ifeq ($(filter-out $(noconfig_targets),$(MAKECMDGOALS)),) @@ -604,15 +606,18 @@ ifeq ($(filter-out $(noconfig_targets),$(MAKECMDGOALS)),) # Kernel configuration # --------------------------------------------------------------------------- -.PHONY: oldconfig xconfig menuconfig config \ +.PHONY: oldconfig xconfig gconfig menuconfig config \ make_with_config rpm -scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf: scripts/fixdep FORCE +scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf scripts/kconfig/gconf: scripts/fixdep FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ xconfig: scripts/kconfig/qconf ./scripts/kconfig/qconf arch/$(ARCH)/Kconfig +gconfig: scripts/kconfig/gconf + ./scripts/kconfig/gconf arch/$(ARCH)/Kconfig + menuconfig: scripts/kconfig/mconf $(Q)$(MAKE) $(build)=scripts/lxdialog ./scripts/kconfig/mconf arch/$(ARCH)/Kconfig @@ -881,13 +886,28 @@ if_changed_rule = $(if $(strip $? \ cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) -define update-if-changed - if [ -r $@ ] && cmp -s $@ $@.tmp; then \ - echo ' (unchanged)'; \ - rm -f $@.tmp; \ - else \ - echo ' (updated)'; \ - mv -f $@.tmp $@; \ +# filechk is used to check if the content of a generated file is updated. +# Sample usage: +# define filechk_sample +# echo $KERNELRELEASE +# endef +# version.h : Makefile +# $(call filechk,sample) +# The rule defined shall write to stdout the content of the new file. +# The existing file will be compared with the new one. +# - If no file exist it is created +# - If the content differ the new file is used +# - If they are equal no change, and no timestamp update + +define filechk + @set -e; \ + echo ' CHK $@'; \ + $(filechk_$(1)) < $< > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPD $@'; \ + mv -f $@.tmp $@; \ fi endef diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 9ec668ee45d3..9ee21e0f1ec1 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -119,15 +119,12 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) archclean: $(Q)$(MAKE) -f scripts/Makefile.clean obj=$(boot) -CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h.tmp \ - include/asm-$(ARCH)/asm_offsets.h +CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h define archhelp echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)' diff --git a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile index 0529f4269cc8..26fd071663ce 100644 --- a/arch/alpha/boot/Makefile +++ b/arch/alpha/boot/Makefile @@ -9,7 +9,7 @@ # host-progs := tools/mkbb tools/objstrip -EXTRA_TARGETS := vmlinux.gz vmlinux \ +targets := vmlinux.gz vmlinux \ vmlinux.nh tools/lxboot tools/bootlx tools/bootph \ bootloader bootpheader OBJSTRIP := $(obj)/tools/objstrip diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index dd960e15b357..06d9b4069e4f 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o +extra-y := head.o EXTRA_AFLAGS := $(CFLAGS) EXTRA_CFLAGS := -Werror -Wno-sign-compare diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 3b99a1d12878..b52bc3719803 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -12,7 +12,7 @@ * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru> * PCI-PCI bridges cleanup */ - +#include <linux/config.h> #include <linux/string.h> #include <linux/pci.h> #include <linux/init.h> @@ -264,45 +264,6 @@ pcibios_fixup_bus(struct pci_bus *bus) } } -void -pcibios_update_resource(struct pci_dev *dev, struct resource *parent, - struct resource *res, int resource) -{ - struct pci_controller *hose = dev->sysdata; - struct resource *root; - int where; - u32 reg; - - if (resource < PCI_ROM_RESOURCE) - where = PCI_BASE_ADDRESS_0 + (resource * 4); - else if (resource == PCI_ROM_RESOURCE) - where = dev->rom_base_reg; - else { - return; /* Don't update non-standard resources here. */ - } - - /* Point root at the hose root. */ - if (res->flags & IORESOURCE_IO) - root = hose->io_space; - else if (res->flags & IORESOURCE_MEM) - root = hose->mem_space; - else { - return; /* Don't update non-standard resources here. */ - } - - reg = (res->start - root->start) | (res->flags & 0xf); - pci_write_config_dword(dev, where, reg); - if ((res->flags & (PCI_BASE_ADDRESS_SPACE - | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) - == (PCI_BASE_ADDRESS_SPACE_MEMORY - | PCI_BASE_ADDRESS_MEM_TYPE_64)) { - pci_write_config_dword(dev, where+4, 0); - printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->dev.name); - } - - /* ??? FIXME -- record old value for shutdown. */ -} - void __init pcibios_update_irq(struct pci_dev *dev, int irq) { @@ -334,21 +295,25 @@ common_swizzle(struct pci_dev *dev, u8 *pinp) } void __devinit -pcibios_fixup_pbus_ranges(struct pci_bus * bus, - struct pbus_set_ranges_data * ranges) +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) { - struct pci_controller *hose = (struct pci_controller *)bus->sysdata; + struct pci_controller *hose = (struct pci_controller *)dev->sysdata; + unsigned long offset = 0; - ranges->io_start -= hose->io_space->start; - ranges->io_end -= hose->io_space->start; - ranges->mem_start -= hose->mem_space->start; - ranges->mem_end -= hose->mem_space->start; -/* FIXME: On older alphas we could use dense memory space - to access prefetchable resources. */ - ranges->prefetch_start -= hose->mem_space->start; - ranges->prefetch_end -= hose->mem_space->start; + if (res->flags & IORESOURCE_IO) + offset = hose->io_space->start; + else if (res->flags & IORESOURCE_MEM) + offset = hose->mem_space->start; + + region->start = res->start - offset; + region->end = res->end - offset; } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_resource_to_bus); +#endif + int pcibios_enable_device(struct pci_dev *dev, int mask) { diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 62d268e87c2f..58ac5a56fbda 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -211,9 +211,7 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) define archhelp echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index ec798c2de3ff..c0a0c7e78f46 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -69,7 +69,7 @@ endif export ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS -EXTRA_TARGETS := Image zImage bootpImage +targets := Image zImage bootpImage $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) @@ -106,5 +106,4 @@ zinstall: $(obj)/zImage $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \ $(obj)/zImage System.map "$(INSTALL_PATH)" -clean-files := $(addprefix $(obj)/,Image zImage bootpImage) subdir- := bootp compressed diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile index f24cbc2be4ac..401443670149 100644 --- a/arch/arm/boot/bootp/Makefile +++ b/arch/arm/boot/bootp/Makefile @@ -7,7 +7,7 @@ ZLDFLAGS =-p -X -T $(obj)/bootp.lds \ --defsym initrd_addr=$(INITRD_PHYS) \ --defsym params=$(PARAMS_PHYS) -EXTRA_TARGETS := bootp +extra-y := bootp # Note that bootp.lds picks up kernel.o and initrd.o $(obj)/bootp: $(addprefix $(obj)/,init.o kernel.o initrd.o bootp.lds) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index d021ee4431aa..f8ed95c4e904 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -65,8 +65,8 @@ endif SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/ -EXTRA_TARGETS := vmlinux vmlinux.lds piggy piggy.gz\ - piggy.o font.o head.o $(OBJS) +targets := vmlinux vmlinux.lds piggy piggy.gz piggy.o \ + font.o head.o $(OBJS) EXTRA_CFLAGS := $(CFLAGS_BOOT) -fpic EXTRA_AFLAGS := -traditional @@ -95,7 +95,5 @@ $(obj)/font.o: $(FONTC) $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config @sed "$(SEDFLAGS)" < $< > $@ -clean-files := $(addprefix $(obj)/,vmlinux piggy* vmlinux.lds) - $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index ef996963a864..017cb5781fb8 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -11,9 +11,6 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) obj-y := arch.o compat.o dma.o $(ENTRY_OBJ) entry-common.o irq.o \ process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \ time.o traps.o -obj-m := -obj-n := -obj- := obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_PM) += pm.o @@ -35,7 +32,7 @@ head-y := head.o obj-$(CONFIG_DEBUG_LL) += debug.o endif -EXTRA_TARGETS := $(head-y) init_task.o +extra-y := $(head-y) init_task.o # Spell out some dependencies that `make dep' doesn't spot $(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 0498981652f5..265b3c183d5a 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -259,47 +259,6 @@ struct pci_fixup pcibios_fixups[] = { }, { 0 } }; -void __devinit -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - struct pci_sys_data *sys = dev->sysdata; - u32 val, check; - int reg; - - if (debug_pci) - printk("PCI: Assigning %3s %08lx to %s\n", - res->flags & IORESOURCE_IO ? "IO" : "MEM", - res->start, dev->dev.name); - - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a - * non-standard resource. - */ - return; - } - - val = res->start; - if (res->flags & IORESOURCE_MEM) - val -= sys->mem_offset; - else - val -= sys->io_offset; - val |= res->flags & PCI_REGION_FLAG_MASK; - - pci_write_config_dword(dev, reg, val); - pci_read_config_dword(dev, reg, &check); - if ((val ^ check) & ((val & PCI_BASE_ADDRESS_SPACE_IO) ? - PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, - resource, val, check); - } -} - void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) { if (debug_pci) @@ -439,18 +398,26 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) * Convert from Linux-centric to bus-centric addresses for bridge devices. */ void __devinit -pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) { - struct pci_sys_data *root = bus->sysdata; + struct pci_sys_data *root = dev->sysdata; + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) + offset = root->io_offset; + if (res->flags & IORESOURCE_MEM) + offset = root->mem_offset; - ranges->io_start -= root->io_offset; - ranges->io_end -= root->io_offset; - ranges->mem_start -= root->mem_offset; - ranges->mem_end -= root->mem_offset; - ranges->prefetch_start -= root->mem_offset; - ranges->prefetch_end -= root->mem_offset; + region->start = res->start - offset; + region->end = res->end - offset; } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_fixup_bus); +EXPORT_SYMBOL(pcibios_resource_to_bus); +#endif + /* * This is the standard PCI-PCI bridge swizzling algorithm: * diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index ad0516f80f61..c38a6c0ead47 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -208,12 +208,13 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) { struct task_struct *tsk = current; + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); - printk("Internal error: %s: %x\n", str, err); + printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); print_modules(); printk("CPU: %d\n", smp_processor_id()); show_regs(regs); diff --git a/arch/arm/mach-arc/Makefile b/arch/arm/mach-arc/Makefile index ba89043c32c8..d783ab059552 100644 --- a/arch/arm/mach-arc/Makefile +++ b/arch/arm/mach-arc/Makefile @@ -6,12 +6,9 @@ obj-y := arch.o dma.o fault.o irq.o mm.o oldlatches.o \ small_page.o -obj-m := -obj-n := -obj- := obj-$(CONFIG_DEBUG_LL) += debug.o -EXTRA_TARGETS := head.o +extra-y := head.o AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile index 59d939779ae6..a340c8fb59fa 100644 --- a/arch/cris/kernel/Makefile +++ b/arch/cris/kernel/Makefile @@ -3,7 +3,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o +extra-y := head.o obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o setup.o time.o sys_cris.o shadows.o \ diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index d2ed950698d1..7741070702a8 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -476,21 +476,6 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. -# Common NUMA Features -config NUMA - bool "Numa Memory Allocation Support" - depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC - -config DISCONTIGMEM - bool - depends on NUMA - default y - -config HAVE_ARCH_BOOTMEM_NODE - bool - depends on NUMA - default y - config X86_TSC bool depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ @@ -680,6 +665,30 @@ config X86_PAE depends on HIGHMEM64G default y +# Common NUMA Features +config NUMA + bool "Numa Memory Allocation Support" + depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) + default n if X86_PC + default y if (X86_NUMAQ || X86_SUMMIT) + +# Need comments to help the hapless user trying to turn on NUMA support +comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support" + depends on X86_NUMAQ && (!HIGHMEM64G || !SMP) + +comment "NUMA (Summit) requires SMP, 64GB highmem support, full ACPI" + depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI || ACPI_HT_ONLY) + +config DISCONTIGMEM + bool + depends on NUMA + default y + +config HAVE_ARCH_BOOTMEM_NODE + bool + depends on NUMA + default y + config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" depends on HIGHMEM4G || HIGHMEM64G diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index 6e959662fb5d..e52670075477 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile @@ -25,9 +25,8 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA #RAMDISK := -DRAMDISK=512 -EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \ - setup setup.o zImage bzImage - +targets := vmlinux.bin bootsect bootsect.o setup setup.o \ + zImage bzImage subdir- := compressed host-progs := tools/build diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile index eee828a9be6f..258ea95224f6 100644 --- a/arch/i386/boot/compressed/Makefile +++ b/arch/i386/boot/compressed/Makefile @@ -4,7 +4,7 @@ # create a compressed vmlinux image from the original vmlinux # -EXTRA_TARGETS := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o EXTRA_AFLAGS := -traditional LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index c423f788cf7f..f1ea1c5d2d99 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c index 20d4cda0e427..3a00de873a4c 100644 --- a/arch/i386/kernel/cpu/centaur.c +++ b/arch/i386/kernel/cpu/centaur.c @@ -248,6 +248,37 @@ static void __init winchip2_protect_mcr(void) } #endif +static void __init init_c3(struct cpuinfo_x86 *c) +{ + u32 lo, hi; + + /* Test for Centaur Extended Feature Flags presence */ + if (cpuid_eax(0xC0000000) >= 0xC0000001) { + /* store Centaur Extended Feature Flags as + * word 5 of the CPU capability bit array + */ + c->x86_capability[5] = cpuid_edx(0xC0000001); + } + + switch (c->x86_model) { + case 6 ... 8: /* Cyrix III family */ + rdmsr (MSR_VIA_FCR, lo, hi); + lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ + wrmsr (MSR_VIA_FCR, lo, hi); + + set_bit(X86_FEATURE_CX8, c->x86_capability); + set_bit(X86_FEATURE_3DNOW, c->x86_capability); + + /* fall through */ + + case 9: /* Nehemiah */ + default: + get_model_name(c); + display_cacheinfo(c); + break; + } +} + static void __init init_centaur(struct cpuinfo_x86 *c) { enum { @@ -386,21 +417,7 @@ static void __init init_centaur(struct cpuinfo_x86 *c) break; case 6: - switch (c->x86_model) { - case 6 ... 8: /* Cyrix III family */ - rdmsr (MSR_VIA_FCR, lo, hi); - lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ - wrmsr (MSR_VIA_FCR, lo, hi); - - set_bit(X86_FEATURE_CX8, c->x86_capability); - set_bit(X86_FEATURE_3DNOW, c->x86_capability); - - case 9: /* Nehemiah */ - default: - get_model_name(c); - display_cacheinfo(c); - break; - } + init_c3(c); break; } } diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 6a99f5176210..0d1f8e1a8343 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -211,9 +211,10 @@ void __init generic_identify(struct cpuinfo_x86 * c) /* Intel-defined flags: level 0x00000001 */ if ( c->cpuid_level >= 0x00000001 ) { - u32 capability; - cpuid(0x00000001, &tfms, &junk, &junk, &capability); + u32 capability, excap; + cpuid(0x00000001, &tfms, &junk, &excap, &capability); c->x86_capability[0] = capability; + c->x86_capability[4] = excap; c->x86 = (tfms >> 8) & 15; c->x86_model = (tfms >> 4) & 15; c->x86_mask = tfms & 15; diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index 42b6aeff2028..6d6f2212ecac 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c @@ -444,7 +444,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) /* * cpufreq_gx_init: - * MediaGX/Geode GX initilize cpufreq driver + * MediaGX/Geode GX initialize cpufreq driver */ static struct cpufreq_driver gx_suspmod_driver = { .verify = cpufreq_gx_verify, diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index bdce330026df..8eec14e404bd 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -40,18 +40,15 @@ #define dprintk(msg...) do { } while(0); #endif -static int numscales=16, numvscales; +static unsigned int numscales=16, numvscales; static int minvid, maxvid; static int can_scale_voltage; -static int can_scale_fsb; static int vrmrev; /* Module parameters */ -static int prefer_slow_fsb; static int dont_scale_voltage; -static int dont_scale_fsb; -static int current_fsb; +static unsigned int fsb; #define __hlt() __asm__ __volatile__("hlt": : :"memory") @@ -231,14 +228,6 @@ static int __initdata c5m_eblcr[32] = { 145, /* 1111 -> 14.5x */ }; -/* fsb values as defined in CPU */ -static unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; -/* fsb values to favour low fsb speed (lower power) */ -static unsigned int power_fsb_table[] = { 66, 100, 133, -1 }; -/* fsb values to favour high fsb speed (for e.g. if lowering CPU - freq because of heat, but want to maintain highest performance possible) */ -static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 }; - /* Voltage scales. Div by 1000 to get actual voltage. */ static int __initdata vrm85scales[32] = { 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, @@ -258,21 +247,22 @@ static int __initdata mobilevrmscales[32] = { static int clock_ratio[32]; static int eblcr_table[32]; static int voltage_table[32]; -static int highest_speed, lowest_speed; /* kHz */ +static unsigned int highest_speed, lowest_speed; /* kHz */ static int longhaul; /* version. */ static struct cpufreq_frequency_table *longhaul_table; static int longhaul_get_cpu_fsb (void) { + unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; unsigned long invalue=0,lo, hi; - if (current_fsb == 0) { + if (fsb == 0) { rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; return eblcr_fsb_table[invalue]; } else { - return current_fsb; + return fsb; } } @@ -294,12 +284,11 @@ static int longhaul_get_cpu_mult (void) /** * longhaul_set_cpu_frequency() * @clock_ratio_index : index of clock_ratio[] for new frequency - * @newfsb: the new FSB * * Sets a new clock ratio, and -if applicable- a new Front Side Bus */ -static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newfsb) +static void longhaul_setstate (unsigned int clock_ratio_index) { unsigned long lo, hi; unsigned int bits; @@ -307,24 +296,21 @@ static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newf int vidindex, i; struct cpufreq_freqs freqs; - if (!newfsb || (clock_ratio[clock_ratio_index] == -1)) - return; - - if ((!can_scale_fsb) && (newfsb != current_fsb)) + if (clock_ratio[clock_ratio_index] == -1) return; - if (((clock_ratio[clock_ratio_index] * newfsb * 100) > highest_speed) || - ((clock_ratio[clock_ratio_index] * newfsb * 100) < lowest_speed)) + if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) || + ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed)) return; freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100; - freqs.new = clock_ratio[clock_ratio_index] * newfsb * 100; + freqs.new = clock_ratio[clock_ratio_index] * fsb * 100; freqs.cpu = 0; /* longhaul.c is UP only driver */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO "longhaul: New FSB:%d Mult(x10):%d\n", - newfsb, clock_ratio[clock_ratio_index]); + dprintk (KERN_INFO "longhaul: FSB:%d Mult(x10):%d\n", + fsb * 100, clock_ratio[clock_ratio_index]); bits = clock_ratio_index; /* "bits" contains the bitpattern of the new multiplier. @@ -358,14 +344,9 @@ static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newf lo |= revkey; if (can_scale_voltage) { - if (can_scale_fsb==1) { - dprintk (KERN_INFO "longhaul: Voltage scaling + FSB scaling not done yet.\n"); - goto bad_voltage; - } else { - /* PB: TODO fix this up */ - vidindex = (((highest_speed-lowest_speed) / (newfsb/2)) - - ((highest_speed-((clock_ratio[clock_ratio_index] * newfsb * 100)/1000)) / (newfsb/2))); - } + /* PB: TODO fix this up */ + vidindex = (((highest_speed-lowest_speed) / (fsb/2)) - + ((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2))); for (i=0;i<32;i++) { dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n", minvid+(vidindex*25), voltage_table[i]); @@ -403,17 +384,6 @@ bad_voltage: lo |= (1<<8); /* EnableSoftBusRatio */ lo |= revkey; - /* Set FSB */ - if (can_scale_fsb==1) { - lo &= ~(1<<28|1<<29); - switch (newfsb) { - case 66: lo |= (1<<28|1<<29); /* 11 */ - break; - case 100: lo |= 1<<28; /* 01 */ - break; - case 133: break; /* 00*/ - } - } wrmsr (MSR_VIA_LONGHAUL, lo, hi); __hlt(); @@ -431,14 +401,11 @@ bad_voltage: static int __init longhaul_get_ranges (void) { unsigned long lo, hi, invalue; - unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0; + unsigned int minmult=0, maxmult=0; unsigned int multipliers[32]= { 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; - unsigned int fsb_table[4] = { 133, 100, -1, 66 }; - unsigned int fsbcount = 1; - unsigned int i, j, k = 0; - static unsigned int *fsb_search_table; + unsigned int j, k = 0; switch (longhaul) { case 1: @@ -446,7 +413,6 @@ static int __init longhaul_get_ranges (void) Assume min=3.0x & max = whatever we booted at. */ minmult = 30; maxmult = longhaul_get_cpu_mult(); - minfsb = maxfsb = current_fsb; break; case 2 ... 3: @@ -465,55 +431,30 @@ static int __init longhaul_get_ranges (void) #else minmult = 30; /* as per spec */ #endif - - if (can_scale_fsb==1) { - invalue = (hi & (1<<9|1<<10)) >> 9; - maxfsb = fsb_table[invalue]; - - invalue = (hi & (1<<25|1<<26)) >> 25; - minfsb = fsb_table[invalue]; - - dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n", - minfsb, maxfsb); - fsbcount = 0; - for (i=0;i<4;i++) { - if((fsb_table[i] >= minfsb) && (fsb_table[i] <= maxfsb)) - fsbcount++; - } - } else { - minfsb = maxfsb = current_fsb; - } break; } - highest_speed = maxmult * maxfsb * 100; - lowest_speed = minmult * minfsb * 100; + highest_speed = maxmult * fsb * 100; + lowest_speed = minmult * fsb * 100; dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n", minmult, maxmult); dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n", lowest_speed, highest_speed); - longhaul_table = kmalloc((numscales * fsbcount + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); + longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) return -ENOMEM; - if (prefer_slow_fsb) - fsb_search_table = perf_fsb_table; // yep, this is right: the last entry is preferred by cpufreq_frequency_table_* ... - else - fsb_search_table = power_fsb_table; - - for (i=0; (i<4); i++) { - if ((fsb_search_table[i] > maxfsb) || (fsb_search_table[i] < minfsb) || (fsb_search_table[i] == -1)) + for (j=0; (j<numscales); j++) { + if (clock_ratio[j] == -1) continue; - for (j=0; (j<numscales); j++) { - if ((clock_ratio[j] > maxmult) || (clock_ratio[j] < minmult) || (clock_ratio[j] == -1)) - continue; - longhaul_table[k].frequency= clock_ratio[j] * fsb_search_table[i] * 100; - longhaul_table[k].index = (j << 8) | (i); - k++; - } + if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult)) + continue; + longhaul_table[k].frequency= clock_ratio[j] * fsb * 100; + longhaul_table[k].index = (j << 8); + k++; } - + longhaul_table[k].frequency = CPUFREQ_TABLE_END; if (!k) return -EINVAL; @@ -568,16 +509,14 @@ static int longhaul_target (struct cpufreq_policy *policy, unsigned int relation) { unsigned int table_index = 0; - unsigned int new_fsb = 0; unsigned int new_clock_ratio = 0; if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index)) return -EINVAL; new_clock_ratio = longhaul_table[table_index].index & 0xFF; - new_fsb = power_fsb_table[(longhaul_table[table_index].index & 0xFF00) >> 8]; - longhaul_setstate(new_clock_ratio, new_fsb); + longhaul_setstate(new_clock_ratio); return 0; } @@ -628,9 +567,6 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) rdmsr (MSR_VIA_LONGHAUL, lo, hi); if ((lo & (1<<0)) && (dont_scale_voltage==0)) longhaul_setup_voltagescaling (lo, hi); - - if ((lo & (1<<1)) && (dont_scale_fsb==0) && (current_fsb==0)) - can_scale_fsb = 1; } if (longhaul_get_ranges()) @@ -639,7 +575,7 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); + policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); return cpufreq_frequency_table_cpuinfo(policy, longhaul_table); } @@ -677,10 +613,7 @@ static void __exit longhaul_exit (void) kfree(longhaul_table); } -MODULE_PARM (dont_scale_fsb, "i"); MODULE_PARM (dont_scale_voltage, "i"); -MODULE_PARM (current_fsb, "i"); -MODULE_PARM (prefer_slow_fsb, "i"); MODULE_AUTHOR ("Dave Jones <davej@suse.de>"); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 43562ebfd2a5..a8e015a5db7d 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -151,7 +151,7 @@ static int check_powernow(void) } if (!(edx & (1 << 1 | 1 << 2))) { - printk (" nothing.\n"); + printk ("nothing.\n"); return 0; } @@ -162,9 +162,8 @@ static int check_powernow(void) static int get_ranges (unsigned char *pst) { - int j; + unsigned int j, speed; u8 fid, vid; - unsigned int speed; powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL); if (!powernow_table) @@ -258,7 +257,7 @@ static void change_speed (unsigned int index) } -int powernow_decode_bios (int maxfid, int startvid) +static int powernow_decode_bios (int maxfid, int startvid) { struct psb_s *psb; struct pst_s *pst; diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 722d29cc1b3a..7ef4a75bd322 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -37,7 +37,20 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Other (Linux-defined) */ - "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, + "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel-defined (#2) */ + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, NULL, + "tm2", NULL, "cnxt_id", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* VIA/Cyrix/Centaur-defined */ + NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index 179579a1df20..6f755378def8 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -3,6 +3,7 @@ #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> +#include <linux/module.h> #include <linux/apm_bios.h> #include <linux/slab.h> #include <asm/io.h> @@ -893,3 +894,5 @@ void __init dmi_scan_machine(void) if(err == 0) dmi_check_blacklist(); } + +EXPORT_SYMBOL(is_unsafe_smbus); diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index c03351ac5a39..c5b7a5c4e3d2 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -130,7 +130,7 @@ ENTRY(startup_32) popfl jmp checkCPUtype 1: -#endif CONFIG_SMP +#endif /* CONFIG_SMP */ /* * Clear BSS first so that there are no surprises... diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 86764ff656a3..749e1b1ea56a 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -116,40 +116,84 @@ static void __init replace_pin_at_irq(unsigned int irq, } } -#define __DO_ACTION(R, ACTION, FINAL) \ - \ -{ \ - int pin; \ - struct irq_pin_list *entry = irq_2_pin + irq; \ - \ - for (;;) { \ - unsigned int reg; \ - pin = entry->pin; \ - if (pin == -1) \ - break; \ - reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \ - reg ACTION; \ - io_apic_modify(entry->apic, 0x10 + R + pin*2, reg); \ - if (!entry->next) \ - break; \ - entry = irq_2_pin + entry->next; \ - } \ - FINAL; \ +/* mask = 1 */ +static void __mask_IO_APIC_irq (unsigned int irq) +{ + int pin; + struct irq_pin_list *entry = irq_2_pin + irq; + + for (;;) { + unsigned int reg; + pin = entry->pin; + if (pin == -1) + break; + reg = io_apic_read(entry->apic, 0x10 + pin*2); + io_apic_modify(entry->apic, 0x10 + pin*2, reg |= 0x00010000); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } + io_apic_sync(entry->apic); +} + +/* mask = 0 */ +static void __unmask_IO_APIC_irq (unsigned int irq) +{ + int pin; + struct irq_pin_list *entry = irq_2_pin + irq; + + for (;;) { + unsigned int reg; + pin = entry->pin; + if (pin == -1) + break; + reg = io_apic_read(entry->apic, 0x10 + pin*2); + io_apic_modify(entry->apic, 0x10 + pin*2, reg &= 0xfffeffff); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } +} + +/* mask = 1, trigger = 0 */ +static void __mask_and_edge_IO_APIC_irq (unsigned int irq) +{ + int pin; + struct irq_pin_list *entry = irq_2_pin + irq; + + for (;;) { + unsigned int reg; + pin = entry->pin; + if (pin == -1) + break; + reg = io_apic_read(entry->apic, 0x10 + pin*2); + reg = (reg & 0xffff7fff) | 0x00010000; + io_apic_modify(entry->apic, 0x10 + pin*2, reg); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } } -#define DO_ACTION(name,R,ACTION, FINAL) \ - \ - static void name##_IO_APIC_irq (unsigned int irq) \ - __DO_ACTION(R, ACTION, FINAL) +/* mask = 0, trigger = 1 */ +static void __unmask_and_level_IO_APIC_irq (unsigned int irq) +{ + int pin; + struct irq_pin_list *entry = irq_2_pin + irq; -DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) - /* mask = 1 */ -DO_ACTION( __unmask, 0, &= 0xfffeffff, ) - /* mask = 0 */ -DO_ACTION( __mask_and_edge, 0, = (reg & 0xffff7fff) | 0x00010000, ) - /* mask = 1, trigger = 0 */ -DO_ACTION( __unmask_and_level, 0, = (reg & 0xfffeffff) | 0x00008000, ) - /* mask = 0, trigger = 1 */ + for (;;) { + unsigned int reg; + pin = entry->pin; + if (pin == -1) + break; + reg = io_apic_read(entry->apic, 0x10 + pin*2); + reg = (reg & 0xfffeffff) | 0x00008000; + io_apic_modify(entry->apic, 0x10 + pin*2, reg); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } +} static void mask_IO_APIC_irq (unsigned int irq) { @@ -197,13 +241,23 @@ static void clear_IO_APIC (void) static void set_ioapic_affinity (unsigned int irq, unsigned long mask) { unsigned long flags; + int pin; + struct irq_pin_list *entry = irq_2_pin + irq; /* * Only the first 8 bits are valid. */ mask = mask << 24; spin_lock_irqsave(&ioapic_lock, flags); - __DO_ACTION(1, = mask, ) + for (;;) { + pin = entry->pin; + if (pin == -1) + break; + io_apic_write(entry->apic, 0x10 + 1 + pin*2, mask); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -743,6 +797,30 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) } /* + * This function currently is only a helper for the i386 smp boot process where + * we need to reprogram the ioredtbls to cater for the cpus which have come online + * so mask in all cases should simply be TARGET_CPUS + */ +void __init setup_ioapic_dest (unsigned long mask) +{ + int pin, ioapic, irq, irq_entry; + + if (skip_ioapic_setup == 1) + return; + + for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { + for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { + irq_entry = find_irq_entry(ioapic, pin, mp_INT); + if (irq_entry == -1) + continue; + irq = pin_2_irq(irq_entry, ioapic, pin); + set_ioapic_affinity(irq, mask); + } + + } +} + +/* * EISA Edge/Level control register, ELCR */ static int __init EISA_ELCR(unsigned int irq) diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 067d2611bd4e..f33bf3963da7 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -290,6 +290,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, { struct pt_regs * childregs; struct task_struct *tsk; + int err; childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; struct_cpy(childregs, regs); @@ -322,20 +323,27 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, struct user_desc info; int idx; + err = -EFAULT; if (copy_from_user(&info, (void *)childregs->esi, sizeof(info))) - return -EFAULT; + goto out; + err = -EINVAL; if (LDT_empty(&info)) - return -EINVAL; + goto out; idx = info.entry_number; if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; + goto out; desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; desc->a = LDT_entry_a(&info); desc->b = LDT_entry_b(&info); } - return 0; + + err = 0; + out: + if (err && p->thread.ts_io_bitmap) + kfree(p->thread.ts_io_bitmap); + return err; } /* diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index e629e6bc44f1..c3fb8f0602cd 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -525,8 +525,11 @@ static void __init parse_cmdline_early (char ** cmdline_p) * "mem=nopentium" disables the 4MB page tables. * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM * to <mem>, overriding the bios size. - * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from + * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from * <start> to <start>+<mem>, overriding the bios size. + * + * HPA tells me bootloaders need to parse mem=, so no new + * option should be mem= [also see Documentation/i386/boot.txt] */ if (c == ' ' && !memcmp(from, "mem=", 4)) { if (to != command_line) @@ -535,8 +538,26 @@ static void __init parse_cmdline_early (char ** cmdline_p) from += 9+4; clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); disable_pse = 1; - } else if (!memcmp(from+4, "exactmap", 8)) { - from += 8+4; + } else { + /* If the user specifies memory size, we + * limit the BIOS-provided memory map to + * that size. exactmap can be used to specify + * the exact map. mem=number can be used to + * trim the existing memory map. + */ + unsigned long long mem_size; + + mem_size = memparse(from+4, &from); + limit_regions(mem_size); + userdef=1; + } + } + + if (c == ' ' && !memcmp(from, "memmap=", 7)) { + if (to != command_line) + to--; + if (!memcmp(from+7, "exactmap", 8)) { + from += 8+7; e820.nr_map = 0; userdef = 1; } else { @@ -548,7 +569,7 @@ static void __init parse_cmdline_early (char ** cmdline_p) */ unsigned long long start_at, mem_size; - mem_size = memparse(from+4, &from); + mem_size = memparse(from+7, &from); if (*from == '@') { start_at = memparse(from+1, &from); add_memory_region(start_at, mem_size, E820_RAM); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 77bfe6723dcc..803c3fb80911 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1155,6 +1155,7 @@ int __devinit __cpu_up(unsigned int cpu) void __init smp_cpus_done(unsigned int max_cpus) { + setup_ioapic_dest(TARGET_CPUS); zap_low_mappings(); } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 4f5b8cf5e457..79aa129a6bc4 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -247,11 +247,13 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * regs, long err) { + static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); handle_BUG(regs); - printk("%s: %04lx\n", str, err & 0xffff); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); show_registers(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 6d65faac8ec7..290770516833 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -90,11 +90,6 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) } } -void __devinit -pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges) -{ -} - /* * Called after each bus is probed, but before its children * are examined. diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index 9cfc595855de..b81cf06d9bea 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -33,34 +33,6 @@ #include "pci.h" -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the diff --git a/arch/ia64/boot/Makefile b/arch/ia64/boot/Makefile index 10978d8d1428..a724c454ed4b 100644 --- a/arch/ia64/boot/Makefile +++ b/arch/ia64/boot/Makefile @@ -8,16 +8,14 @@ # Copyright (C) 1998 by David Mosberger-Tang <davidm@hpl.hp.com> # -EXTRA_TARGETS := vmlinux.bin vmlinux.gz - targets-$(CONFIG_IA64_HP_SIM) += bootloader targets-$(CONFIG_IA64_GENERIC) += bootloader -EXTRA_TARGETS += $(sort $(targets-y)) +targets := vmlinux.bin vmlinux.gz $(targets-y) quiet_cmd_cptotop = LN $@ cmd_cptotop = ln -f $< $@ -vmlinux.gz: $(obj)/vmlinux.gz $(targets-y) +vmlinux.gz: $(obj)/vmlinux.gz $(addprefix $(obj)/,$(targets-y)) $(call cmd,cptotop) @echo ' Kernel: $@ is ready' diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index e37fa087ffe5..583fb849c957 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o \ irq.o irq_ia64.o irq_lsapic.o ivt.o \ diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 768dd70cb596..5f811d5b3809 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -101,6 +101,7 @@ die (const char *str, struct pt_regs *regs, long err) .lock_owner = -1, .lock_owner_depth = 0 }; + static int die_counter; if (die.lock_owner != smp_processor_id()) { console_verbose(); @@ -111,7 +112,8 @@ die (const char *str, struct pt_regs *regs, long err) } if (++die.lock_owner_depth < 3) { - printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err); + printk("%s[%d]: %s %ld [%d]\n", + current->comm, current->pid, str, err, ++die_counter); show_regs(regs); } else printk(KERN_ERR "Recursive die() failure, output suppressed\n"); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index c0e7bac3b123..27757a02feda 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -143,21 +143,7 @@ pcibios_fixup_bus (struct pci_bus *b) return; } -void __devinit -pcibios_update_resource (struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - unsigned long where, size; - u32 reg; - - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); - - /* ??? FIXME -- record old value for shutdown. */ -} +#warning pcibios_update_resource() is now a generic implementation - please check void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) @@ -167,11 +153,6 @@ pcibios_update_irq (struct pci_dev *dev, int irq) /* ??? FIXME -- record old value for shutdown. */ } -void __devinit -pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges) -{ -} - static inline int pcibios_enable_resources (struct pci_dev *dev, int mask) { diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 9ab6bc3cac77..d69bb917811a 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -3,9 +3,9 @@ # ifndef CONFIG_SUN3 - EXTRA_TARGETS := head.o + extra-y := head.o else - EXTRA_TARGETS := sun3-head.o + extra-y := sun3-head.o endif obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile index 78828e79ea39..d8aefe18c518 100644 --- a/arch/m68knommu/Makefile +++ b/arch/m68knommu/Makefile @@ -86,8 +86,7 @@ LDFLAGS_BLOB := --format binary --oformat elf32-m68k head-y := arch/m68knommu/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o -CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h.tmp \ - include/asm-$(ARCH)/asm-offsets.h \ +CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h \ arch/$(ARCH)/kernel/asm-offsets.s core-y += arch/m68knommu/kernel/ \ @@ -104,6 +103,4 @@ archclean: include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \ include/asm include/linux/version.h \ include/config/MARKER - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c index b5c2d4708045..ea3fa6367860 100644 --- a/arch/m68knommu/kernel/comempci.c +++ b/arch/m68knommu/kernel/comempci.c @@ -60,8 +60,8 @@ unsigned long pci_slotmask = 0; * really assign any resources we like to devices, as long as * they do not clash with other PCI devices. */ -unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitary start address */ -unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitary start address */ +unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitrary start address */ +unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitrary start address */ #define PCI_MINIO 0x100 /* 256 byte minimum I/O */ #define PCI_MINMEM 0x00010000 /* 64k minimum chunk */ diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 81e506f63b56..4271a229b62c 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c @@ -16,7 +16,7 @@ * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab * * mathemu support by Roman Zippel - * (Note: fpstate in the signal context is completly ignored for the emulator + * (Note: fpstate in the signal context is completely ignored for the emulator * and the internal floating point format is put on stack) */ diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile index d1d35fa50266..74281a5d6bea 100644 --- a/arch/m68knommu/platform/5206/Makefile +++ b/arch/m68knommu/platform/5206/Makefile @@ -18,4 +18,4 @@ endif obj-y := config.o -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile index d1d35fa50266..74281a5d6bea 100644 --- a/arch/m68knommu/platform/5206e/Makefile +++ b/arch/m68knommu/platform/5206e/Makefile @@ -18,4 +18,4 @@ endif obj-y := config.o -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile index d1d35fa50266..74281a5d6bea 100644 --- a/arch/m68knommu/platform/5249/Makefile +++ b/arch/m68knommu/platform/5249/Makefile @@ -18,4 +18,4 @@ endif obj-y := config.o -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile index 444e092c389b..e49335fcd9c5 100644 --- a/arch/m68knommu/platform/5272/Makefile +++ b/arch/m68knommu/platform/5272/Makefile @@ -18,4 +18,4 @@ endif obj-y := config.o -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile index 9d53f86e8140..cf63cb941ab5 100644 --- a/arch/m68knommu/platform/5307/Makefile +++ b/arch/m68knommu/platform/5307/Makefile @@ -20,5 +20,5 @@ obj-$(CONFIG_COLDFIRE) += entry.o timers.o vectors.o obj-$(CONFIG_M5307) += config.o ifeq ($(CONFIG_M5307),y) -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o endif diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile index 8b1fa5d3302d..dcfae2890c7d 100644 --- a/arch/m68knommu/platform/5407/Makefile +++ b/arch/m68knommu/platform/5407/Makefile @@ -18,4 +18,4 @@ endif obj-y := config.o -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o diff --git a/arch/m68knommu/platform/68328/Makefile b/arch/m68knommu/platform/68328/Makefile index 225eeb093fa7..80bf9bf50a65 100644 --- a/arch/m68knommu/platform/68328/Makefile +++ b/arch/m68knommu/platform/68328/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_M68EZ328) += entry.o ints.o obj-$(CONFIG_M68VZ328) += entry.o ints.o ifeq ($(CONFIG_M68328),y) -EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o endif $(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h diff --git a/arch/m68knommu/platform/68360/Makefile b/arch/m68knommu/platform/68360/Makefile index 69a88fb7d42e..3f21c1f48804 100644 --- a/arch/m68knommu/platform/68360/Makefile +++ b/arch/m68knommu/platform/68360/Makefile @@ -4,4 +4,4 @@ obj-y := config.o commproc.o entry.o ints.o -EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/crt0_$(MODEL).o diff --git a/arch/m68knommu/platform/68EZ328/Makefile b/arch/m68knommu/platform/68EZ328/Makefile index babf22ea01ee..17b573d1ca11 100644 --- a/arch/m68knommu/platform/68EZ328/Makefile +++ b/arch/m68knommu/platform/68EZ328/Makefile @@ -4,7 +4,7 @@ obj-y := config.o -EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o +extra-y := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o $(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \ diff --git a/arch/m68knommu/vmlinux.lds.S b/arch/m68knommu/vmlinux.lds.S index 0aa6099a5b1d..4f936da88b7f 100644 --- a/arch/m68knommu/vmlinux.lds.S +++ b/arch/m68knommu/vmlinux.lds.S @@ -126,7 +126,7 @@ /* * The standard Arnewsh 5206 board only has 1MiB of ram. Not normally - * enough to be usefull. Assume the user has fitted something larger, + * enough to be useful. Assume the user has fitted something larger, * at least 4MiB in size. No point in not letting the kernel completely * link, it will be obvious if it is too big when they go to load it. */ @@ -300,6 +300,9 @@ SECTIONS { *(.initcall6.init) *(.initcall7.init) __initcall_end = .; + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; . = ALIGN(4); __initramfs_start = .; *(.init.ramfs) diff --git a/arch/mips/ddb5074/pci.c b/arch/mips/ddb5074/pci.c index 57a0b09ea24f..d57926842c6f 100644 --- a/arch/mips/ddb5074/pci.c +++ b/arch/mips/ddb5074/pci.c @@ -297,11 +297,6 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, - struct pbus_set_ranges_data *ranges) -{ -} - int pcibios_enable_resources(struct pci_dev *dev) { u16 cmd, old_cmd; @@ -341,37 +336,6 @@ int pcibios_enable_device(struct pci_dev *dev) return pcibios_enable_resources(dev); } -void pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4 * resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* - * Somebody might have asked allocation of a non-standard - * resource - */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & - ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : - PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { diff --git a/arch/mips/ddb5476/pci.c b/arch/mips/ddb5476/pci.c index d8f2c6d57f0d..6290eff02793 100644 --- a/arch/mips/ddb5476/pci.c +++ b/arch/mips/ddb5476/pci.c @@ -341,8 +341,10 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, - struct pbus_set_ranges_data *ranges) +#if 0 /* original DDB5074 code */ +void __devinit +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) { /* * our caller figure out range by going through the dev structures. @@ -350,15 +352,14 @@ void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, * different view of the addressing space. */ -#if 0 /* original DDB5074 code */ if (bus->number == 0) { ranges->io_start -= bus->resource[0]->start; ranges->io_end -= bus->resource[0]->start; ranges->mem_start -= bus->resource[1]->start; ranges->mem_end -= bus->resource[1]->start; } -#endif } +#endif int pcibios_enable_resources(struct pci_dev *dev) { @@ -399,37 +400,6 @@ int pcibios_enable_device(struct pci_dev *dev) return pcibios_enable_resources(dev); } -void pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4 * resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* - * Somebody might have asked allocation of a non-standard - * resource - */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & - ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : - PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { diff --git a/arch/mips/ddb5xxx/common/pci.c b/arch/mips/ddb5xxx/common/pci.c index 5c1e07f6edbb..4c8457fbbbd1 100644 --- a/arch/mips/ddb5xxx/common/pci.c +++ b/arch/mips/ddb5xxx/common/pci.c @@ -170,11 +170,3 @@ pcibios_align_resource(void *data, struct resource *res, /* this should not be called */ MIPS_ASSERT(1 == 0); } - -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - /* this should not be called */ - MIPS_ASSERT(1 == 0); -} diff --git a/arch/mips/gt64120/common/pci.c b/arch/mips/gt64120/common/pci.c index c8615e9043a2..8350b9dad0b1 100644 --- a/arch/mips/gt64120/common/pci.c +++ b/arch/mips/gt64120/common/pci.c @@ -785,39 +785,6 @@ int pcibios_enable_device(struct pci_dev *dev) return pcibios_enable_resources(dev); } -void pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - return; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4 * resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* - * Somebody might have asked allocation of a non-standard - * resource - */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & - ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : - PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { diff --git a/arch/mips/ite-boards/generic/it8172_pci.c b/arch/mips/ite-boards/generic/it8172_pci.c index 7a7075b1d728..6073dfcb36b8 100644 --- a/arch/mips/ite-boards/generic/it8172_pci.c +++ b/arch/mips/ite-boards/generic/it8172_pci.c @@ -196,19 +196,7 @@ pcibios_setup(char *str) return str; } -void __init -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - unsigned long where, size; - u32 reg; - - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); -} +#warning pcibios_update_resource() is now a generic implementation - please check void __init pcibios_fixup_bus(struct pci_bus *b) { diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index a68de9935eac..d2761db3285c 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -4,7 +4,7 @@ # EXTRA_AFLAGS = -mips3 -mcpu=r4000 # not used? -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y += branch.o process.o signal.o entry.o \ traps.o ptrace.o vm86.o ioport.o reset.o \ semaphore.o setup.o syscall.o sysmips.o \ diff --git a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c index 81aea7026fa2..b7b72fd1a267 100644 --- a/arch/mips/kernel/pci.c +++ b/arch/mips/kernel/pci.c @@ -166,10 +166,3 @@ pcibios_align_resource(void *data, struct resource *res, { /* this should not be called */ } - -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - /* this should not be called */ -} diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index ea3d490934f0..f3c333596d00 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -191,12 +191,13 @@ spinlock_t die_lock; extern void __die(const char * str, struct pt_regs * regs, const char *where, unsigned long line) { + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); printk("%s", str); if (where) printk(" in %s, line %ld", where, line); - printk(":\n"); + printk("[#%d]:\n", ++die_counter); show_regs(regs); printk("Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, (unsigned long) current); diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c index c9e84b11d87e..2faf1bc5376c 100644 --- a/arch/mips/mips-boards/generic/pci.c +++ b/arch/mips/mips-boards/generic/pci.c @@ -248,19 +248,7 @@ struct pci_fixup pcibios_fixups[] = { { 0 } }; -void __init -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - unsigned long where, size; - u32 reg; - - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); -} +#warning pcibios_update_resource() is now a generic implementation - please check /* * Called after each bus is probed, but before its children diff --git a/arch/mips/sni/pci.c b/arch/mips/sni/pci.c index 008f36a4e4ed..8bdc9324559d 100644 --- a/arch/mips/sni/pci.c +++ b/arch/mips/sni/pci.c @@ -137,34 +137,6 @@ pcibios_fixup_bus(struct pci_bus *b) { } -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - void __init pcibios_init(void) { struct pci_ops *ops = &sni_pci_ops; diff --git a/arch/mips64/kernel/Makefile b/arch/mips64/kernel/Makefile index 809a5631f607..8551df9530f4 100644 --- a/arch/mips64/kernel/Makefile +++ b/arch/mips64/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/MIPS kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y := branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \ r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \ diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c index 023435ac92aa..fd4e77663cb5 100644 --- a/arch/mips64/kernel/traps.c +++ b/arch/mips64/kernel/traps.c @@ -161,12 +161,13 @@ spinlock_t die_lock; void die(const char * str, struct pt_regs * regs, unsigned long err) { + static int die_counter; if (user_mode(regs)) /* Just return if in user mode. */ return; console_verbose(); spin_lock_irq(&die_lock); - printk("%s: %04lx\n", str, err & 0xffff); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); show_regs(regs); printk("Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, (unsigned long) current); diff --git a/arch/mips64/mips-boards/generic/pci.c b/arch/mips64/mips-boards/generic/pci.c index 4e377c3e9716..93ffe1ff3f7f 100644 --- a/arch/mips64/mips-boards/generic/pci.c +++ b/arch/mips64/mips-boards/generic/pci.c @@ -307,19 +307,7 @@ struct pci_fixup pcibios_fixups[] = { { 0 } }; -void __init -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - unsigned long where, size; - u32 reg; - - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); -} +#warning pcibios_update_resource() is now a generic implementation - please check unsigned __init int pcibios_assign_all_busses(void) { diff --git a/arch/mips64/sgi-ip27/ip27-pci.c b/arch/mips64/sgi-ip27/ip27-pci.c index 61decb894697..55f0234e87e0 100644 --- a/arch/mips64/sgi-ip27/ip27-pci.c +++ b/arch/mips64/sgi-ip27/ip27-pci.c @@ -214,19 +214,7 @@ pcibios_update_irq(struct pci_dev *dev, int irq) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -void __init -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - unsigned long where, size; - u32 reg; - - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); -} +#warning pcibios_update_resource() is now a generic implementation - please check void __init pcibios_fixup_bus(struct pci_bus *b) @@ -234,12 +222,6 @@ pcibios_fixup_bus(struct pci_bus *b) pci_fixup_irqs(pci_swizzle, pci_map_irq); } -void __devinit -pcibios_fixup_pbus_ranges(struct pci_bus * bus, - struct pbus_set_ranges_data * ranges) -{ -} - int __init pcibios_enable_device(struct pci_dev *dev) { diff --git a/arch/mips64/sgi-ip32/Makefile b/arch/mips64/sgi-ip32/Makefile index 59174e2cf082..1a1c007beac1 100644 --- a/arch/mips64/sgi-ip32/Makefile +++ b/arch/mips64/sgi-ip32/Makefile @@ -3,7 +3,7 @@ # under Linux. # -EXTRA_TARGETS := ip32-irq-glue.o +extra-y := ip32-irq-glue.o obj-y += ip32-irq.o ip32-rtc.o ip32-setup.o ip32-irq-glue.o \ ip32-berr.o ip32-timer.o crime.o diff --git a/arch/mips64/sgi-ip32/ip32-pci.c b/arch/mips64/sgi-ip32/ip32-pci.c index f3f2be83974d..d4af201dc975 100644 --- a/arch/mips64/sgi-ip32/ip32-pci.c +++ b/arch/mips64/sgi-ip32/ip32-pci.c @@ -333,11 +333,6 @@ void __init pcibios_align_resource (void *data, struct resource *res, { } -void __init pcibios_update_resource (struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ -} - void __init pcibios_update_irq (struct pci_dev *dev, int irq) { pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); @@ -348,12 +343,6 @@ void __init pcibios_fixup_bus (struct pci_bus *b) pci_fixup_irqs (macepci_swizzle, macepci_map_irq); } -/* XXX anybody know what this is supposed to do? */ -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus * bus, - struct pbus_set_ranges_data * ranges) -{ -} - /* * Handle errors from the bridge. This includes master and target aborts, * various command and address errors, and the interrupt test. This gets diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 973d26aeabd9..09179d4de120 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -91,12 +91,10 @@ arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-parisc/offsets.h: arch/parisc/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) -CLEAN_FILES += palo.conf lifimage include/asm-parisc/offsets.h \ - include/asm-parisc/offsets.h.tmp +CLEAN_FILES += lifimage include/asm-parisc/offsets.h +MRPROPER_FILES += palo.conf define archhelp @echo '* vmlinux - Uncompressed kernel image (./vmlinux)' diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 5edb1d848545..d2a7d8813f45 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -4,7 +4,8 @@ head-y := head.o head-$(CONFIG_PARISC64) := head64.o -EXTRA_TARGETS := init_task.o pdc_cons.o process.o unaligned.o $(head-y) +extra-y := init_task.o pdc_cons.o process.o \ + unaligned.o $(head-y) AFLAGS_entry.o := -traditional AFLAGS_pacache.o := -traditional diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c index a99a6e321c10..6a994d1c35e5 100644 --- a/arch/parisc/kernel/binfmt_elf32.c +++ b/arch/parisc/kernel/binfmt_elf32.c @@ -12,6 +12,26 @@ #define ELF_CLASS ELFCLASS32 +#define ELF_CORE_COPY_REGS(dst, pt) \ + memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \ + { int i; \ + for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \ + for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \ + } \ + dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \ + dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \ + dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \ + dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \ + dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \ + dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \ + dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \ + dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \ + dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \ + dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \ + dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \ + dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15); + + typedef unsigned int elf_greg_t; #include <linux/spinlock.h> @@ -61,25 +81,6 @@ struct elf_prpsinfo32 #define ELF_PLATFORM ("PARISC32\0") -#define ELF_CORE_COPY_REGS(dst, pt) \ - memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \ - { int i; \ - for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \ - for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \ - } \ - dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \ - dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \ - dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \ - dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \ - dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \ - dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \ - dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \ - dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \ - dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \ - dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \ - dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \ - dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15); - /* * We should probably use this macro to set a flag somewhere to indicate * this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index bf551a9745af..a54ff14f1d29 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -114,7 +114,7 @@ show_cache_info(struct seq_file *m) void __init parisc_cache_init(void) { - if(pdc_cache_info(&cache_info)<0) + if (pdc_cache_info(&cache_info) < 0) panic("parisc_cache_init: pdc_cache_info failed"); #if 0 @@ -167,25 +167,25 @@ parisc_cache_init(void) split_tlb = 0; if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) { - - if (cache_info.dt_conf.tc_sh == 2) - printk(KERN_WARNING "Unexpected TLB configuration. " + if (cache_info.dt_conf.tc_sh == 2) + printk(KERN_WARNING "Unexpected TLB configuration. " "Will flush I/D separately (could be optimized).\n"); - split_tlb = 1; + split_tlb = 1; } - dcache_stride = ( (1<<(cache_info.dc_conf.cc_block+3)) * - cache_info.dc_conf.cc_line ); - icache_stride = ( (1<<(cache_info.ic_conf.cc_block+3)) * - cache_info.ic_conf.cc_line ); + dcache_stride = (1 << (cache_info.dc_conf.cc_block + 3)) * + cache_info.dc_conf.cc_line; + icache_stride = (1 << (cache_info.ic_conf.cc_block + 3)) * + cache_info.ic_conf.cc_line; #ifndef CONFIG_PA20 - if(pdc_btlb_info(&btlb_info)<0) { + if (pdc_btlb_info(&btlb_info) < 0) { memset(&btlb_info, 0, sizeof btlb_info); } #endif - if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) { + if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == + PDC_MODEL_NVA_UNSUPPORTED) { printk(KERN_WARNING "Only equivalent aliasing supported\n"); #ifndef CONFIG_SMP panic("SMP kernel required to avoid non-equivalent aliasing"); @@ -195,31 +195,69 @@ parisc_cache_init(void) void disable_sr_hashing(void) { - int srhash_type; + int srhash_type; + + switch (boot_cpu_data.cpu_type) { + case pcx: /* We shouldn't get this far. setup.c should prevent it. */ + BUG(); + return; + + case pcxs: + case pcxt: + case pcxt_: + srhash_type = SRHASH_PCXST; + break; + + case pcxl: + srhash_type = SRHASH_PCXL; + break; - if (boot_cpu_data.cpu_type == pcxl2) - return; /* pcxl2 doesn't support space register hashing */ + case pcxl2: /* pcxl2 doesn't support space register hashing */ + return; - switch (boot_cpu_data.cpu_type) { + default: /* Currently all PA2.0 machines use the same ins. sequence */ + srhash_type = SRHASH_PA20; + break; + } + + disable_sr_hashing_asm(srhash_type); +} - case pcx: - BUG(); /* We shouldn't get here. code in setup.c should prevent it */ - return; +void __flush_dcache_page(struct page *page) +{ + struct mm_struct *mm = current->active_mm; + struct list_head *l; - case pcxs: - case pcxt: - case pcxt_: - srhash_type = SRHASH_PCXST; - break; + flush_kernel_dcache_page(page_address(page)); - case pcxl: - srhash_type = SRHASH_PCXL; - break; + if (!page->mapping) + return; - default: /* Currently all PA2.0 machines use the same ins. sequence */ - srhash_type = SRHASH_PA20; - break; - } + list_for_each(l, &page->mapping->i_mmap_shared) { + struct vm_area_struct *mpnt; + unsigned long off; - disable_sr_hashing_asm(srhash_type); + mpnt = list_entry(l, struct vm_area_struct, shared); + + /* + * If this VMA is not in our MM, we can ignore it. + */ + if (mpnt->vm_mm != mm) + continue; + + if (page->index < mpnt->vm_pgoff) + continue; + + off = page->index - mpnt->vm_pgoff; + if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + continue; + + flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); + + /* All user shared mappings should be equivalently mapped, + * so once we've flushed one we should be ok + */ + break; + } } + diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 84064c3a02bd..4e898b9a43b3 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -558,11 +558,9 @@ __kernel_thread: .export ret_from_kernel_thread ret_from_kernel_thread: -#if CONFIG_PREEMPT || CONFIG_SMP /* Call schedule_tail first though */ bl schedule_tail, %r2 nop -#endif LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 LDREG TASK_PT_GR25(%r1), %r26 @@ -2014,10 +2012,8 @@ wrapper_exit: /* Set the return value for the child */ child_return: -#if CONFIG_SMP || CONFIG_PREEMPT bl schedule_tail, %r2 nop -#endif LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 LDREG TASK_PT_GR19(%r1),%r2 diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index db4720d7b8ec..71845a6c51c4 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c @@ -99,8 +99,8 @@ static struct hp_hardware hp_hardware_list[] __initdata = { {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"}, {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"}, {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"}, - {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-100 (811/D210,D310)"}, - {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-75 (801/D200)"}, + {HPHW_NPROC,0x484,0x4,0x81,"UL Proc L-100 (811/D210,D310)"}, + {HPHW_NPROC,0x485,0x4,0x81,"UL Proc L-75 (801/D200)"}, {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"}, {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"}, {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"}, diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c index 47c599d45c30..76a650c4a16a 100644 --- a/arch/parisc/kernel/init_task.c +++ b/arch/parisc/kernel/init_task.c @@ -10,6 +10,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c index 8332a7d5016b..2a3b4f0f485b 100644 --- a/arch/parisc/kernel/ioctl32.c +++ b/arch/parisc/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.6 2002/10/21 16:13:22 varenet Exp $ +/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -66,6 +66,9 @@ #define __KERNEL__ #include <scsi/sg.h> +#include <linux/raid/md_u.h> +#include <linux/dm-ioctl.h> + #include <asm/types.h> #include <asm/uaccess.h> #include <asm/perf.h> @@ -2824,6 +2827,27 @@ static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioc return err; } +/* Fix sizeof(sizeof()) breakage */ +#define BLKBSZGET_32 _IOR(0x12,112,int) +#define BLKBSZSET_32 _IOW(0x12,113,int) +#define BLKGETSIZE64_32 _IOR(0x12,114,int) + +static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return sys_ioctl(fd, BLKBSZGET, arg); +} + +static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return sys_ioctl(fd, BLKBSZSET, arg); +} + +static int do_blkgetsize64(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + return sys_ioctl(fd, BLKGETSIZE64, arg); +} + static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) { return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); @@ -2997,14 +3021,13 @@ COMPATIBLE_IOCTL(BLKROGET) COMPATIBLE_IOCTL(BLKRRPART) COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) -COMPATIBLE_IOCTL(BLKBSZGET) /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) COMPATIBLE_IOCTL(GET_ARRAY_INFO) COMPATIBLE_IOCTL(GET_DISK_INFO) COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) +COMPATIBLE_IOCTL(RAID_AUTORUN) COMPATIBLE_IOCTL(CLEAR_ARRAY) COMPATIBLE_IOCTL(ADD_NEW_DISK) COMPATIBLE_IOCTL(HOT_REMOVE_DISK) @@ -3015,12 +3038,26 @@ COMPATIBLE_IOCTL(UNPROTECT_ARRAY) COMPATIBLE_IOCTL(PROTECT_ARRAY) COMPATIBLE_IOCTL(HOT_ADD_DISK) COMPATIBLE_IOCTL(SET_DISK_FAULTY) +COMPATIBLE_IOCTL(HOT_GENERATE_ERROR) COMPATIBLE_IOCTL(RUN_ARRAY) COMPATIBLE_IOCTL(START_ARRAY) COMPATIBLE_IOCTL(STOP_ARRAY) COMPATIBLE_IOCTL(STOP_ARRAY_RO) COMPATIBLE_IOCTL(RESTART_ARRAY_RW) +/* DM */ +COMPATIBLE_IOCTL(DM_VERSION) +COMPATIBLE_IOCTL(DM_REMOVE_ALL) +COMPATIBLE_IOCTL(DM_DEV_CREATE) +COMPATIBLE_IOCTL(DM_DEV_REMOVE) +COMPATIBLE_IOCTL(DM_DEV_RELOAD) +COMPATIBLE_IOCTL(DM_DEV_SUSPEND) +COMPATIBLE_IOCTL(DM_DEV_RENAME) +COMPATIBLE_IOCTL(DM_DEV_DEPS) +COMPATIBLE_IOCTL(DM_DEV_STATUS) +COMPATIBLE_IOCTL(DM_TARGET_STATUS) +COMPATIBLE_IOCTL(DM_TARGET_WAIT) + /* Big K */ COMPATIBLE_IOCTL(PIO_FONT) COMPATIBLE_IOCTL(GIO_FONT) @@ -3570,6 +3607,11 @@ HANDLE_IOCTL(BLKGETSIZE, w_long) HANDLE_IOCTL(0x1260, broken_blkgetsize) HANDLE_IOCTL(BLKSECTGET, w_long) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) +/* take care of sizeof(sizeof()) breakage */ +/* block stuff */ +HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) +HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) +HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans) HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans) diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index b8e33137ccff..703991db6276 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -562,10 +562,8 @@ int module_finalize(const Elf_Ehdr *hdr, #ifdef __LP64__ me->init = (void *)get_fdesc(me, (Elf_Addr)me->init); #ifdef CONFIG_MODULE_UNLOAD - if (me->cleanup) - me->cleanup = (void *)get_fdesc(me, (Elf_Addr)me->cleanup); - if (me->destroy) - me->destroy = (void *)get_fdesc(me, (Elf_Addr)me->destroy); + if (me->exit) + me->exit = (void *)get_fdesc(me, (Elf_Addr)me->exit); #endif #endif return 0; diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 52eeb2434cd7..8fb96ebb43a0 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -83,16 +83,9 @@ struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; u##size in##type (int addr) \ { \ int b = PCI_PORT_HBA(addr); \ - u##size d = (u##size) -1; \ EISA_IN(size); \ - ASSERT(pci_port); /* make sure services are defined */ \ - ASSERT(parisc_pci_hba[b]); /* make sure ioaddr are "fixed up" */ \ - if (parisc_pci_hba[b] == NULL) { \ - printk(KERN_WARNING "\nPCI or EISA Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \ - } else { \ - d = pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \ - } \ - return d; \ + if (!parisc_pci_hba[b]) return (u##size) -1; \ + return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \ } PCI_PORT_IN(b, 8) @@ -105,7 +98,7 @@ void out##type (u##size d, int addr) \ { \ int b = PCI_PORT_HBA(addr); \ EISA_OUT(size); \ - ASSERT(pci_port); \ + if (!parisc_pci_hba[b]) return; \ pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \ } @@ -192,74 +185,6 @@ void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) } -/* ------------------------------------ -** -** Program one BAR in PCI config space. -** -** ------------------------------------ -** PAT PDC systems need this routine. PA legacy PDC does not. -** -** When BAR's are configured by linux, this routine will update -** configuration space with the "normalized" address. "root" indicates -** where the range starts and res is some portion of that range. -** -** VCLASS: For all PA-RISC systems except V-class, root->start would be zero. -** -** PAT PDC can tell us which MMIO ranges are available or already in use. -** I/O port space and such are not memory mapped anyway for PA-Risc. -*/ -void __devinit -pcibios_update_resource( - struct pci_dev *dev, - struct resource *root, - struct resource *res, - int barnum - ) -{ - int where; - u32 barval = 0; - - DBG_RES("pcibios_update_resource(%s, ..., %d) [%lx,%lx]/%x\n", - dev->slot_name, - barnum, res->start, res->end, (int) res->flags); - - if (barnum >= PCI_BRIDGE_RESOURCES) { - /* handled in PCI-PCI bridge specific support */ - return; - } - - if (barnum == PCI_ROM_RESOURCE) { - where = PCI_ROM_ADDRESS; - } else { - /* 0-5 standard PCI "regions" */ - where = PCI_BASE_ADDRESS_0 + (barnum * 4); - } - - if (res->flags & IORESOURCE_IO) { - barval = PCI_PORT_ADDR(res->start); - } else if (res->flags & IORESOURCE_MEM) { - barval = PCI_BUS_ADDR(HBA_DATA(dev->bus->dev->platform_data), res->start); - } else { - panic("pcibios_update_resource() WTF? flags not IO or MEM"); - } - - pci_write_config_dword(dev, where, barval); - -/* XXX FIXME - Elroy does support 64-bit (dual cycle) addressing. -** But at least one device (Symbios 53c896) which has 64-bit BAR -** doesn't actually work right with dual cycle addresses. -** So ignore the whole mess for now. -*/ - - if ((res->flags & (PCI_BASE_ADDRESS_SPACE - | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) - == (PCI_BASE_ADDRESS_SPACE_MEMORY - | PCI_BASE_ADDRESS_MEM_TYPE_64)) { - pci_write_config_dword(dev, where+4, 0); - DBGC("PCIBIOS: dev %s type 64-bit\n", dev->name); - } -} - /* ** Called by pci_set_master() - a driver interface. ** @@ -345,30 +270,34 @@ pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) /* ** called by drivers/pci/setup-res.c:pci_setup_bridge(). */ -void __devinit pcibios_fixup_pbus_ranges( - struct pci_bus *bus, - struct pbus_set_ranges_data *ranges +void __devinit pcibios_resource_to_bus( + struct pci_dev *dev, + struct pci_bus_region *region, + struct resource *res ) { + struct pci_bus *bus = dev->bus; struct pci_hba_data *hba = HBA_DATA(bus->dev->platform_data); - /* - ** I/O space may see busnumbers here. Something - ** in the form of 0xbbxxxx where bb is the bus num - ** and xxxx is the I/O port space address. - ** Remaining address translation are done in the - ** PCI Host adapter specific code - ie dino_out8. - */ - ranges->io_start = PCI_PORT_ADDR(ranges->io_start); - ranges->io_end = PCI_PORT_ADDR(ranges->io_end); - - /* Convert MMIO addr to PCI addr (undo global virtualization) */ - ranges->mem_start = PCI_BUS_ADDR(hba, ranges->mem_start); - ranges->mem_end = PCI_BUS_ADDR(hba, ranges->mem_end); + if (res->flags & IORESOURCE_IO) { + /* + ** I/O space may see busnumbers here. Something + ** in the form of 0xbbxxxx where bb is the bus num + ** and xxxx is the I/O port space address. + ** Remaining address translation are done in the + ** PCI Host adapter specific code - ie dino_out8. + */ + region->start = PCI_PORT_ADDR(res->start); + region->end = PCI_PORT_ADDR(res->end); + } else if (res->flags & IORESOURCE_MEM) { + /* Convert MMIO addr to PCI addr (undo global virtualization) */ + region->start = PCI_BUS_ADDR(hba, res->start); + region->end = PCI_BUS_ADDR(hba, res->end); + } - DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number, - ranges->io_start, ranges->io_end, - ranges->mem_start, ranges->mem_end); + DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n", + bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM", + region->start, region->end); /* KLUGE ALERT ** if this resource isn't linked to a "parent", then it seems @@ -378,8 +307,9 @@ void __devinit pcibios_fixup_pbus_ranges( pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]); } -#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) - +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_resource_to_bus); +#endif /* ** pcibios align resources() is called everytime generic PCI code @@ -409,7 +339,7 @@ pcibios_align_resource(void *data, struct resource *res, align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; /* Align to largest of MIN or input size */ - mask = MAX(alignment, align) - 1; + mask = max(alignment, align) - 1; res->start += mask; res->start &= ~mask; diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 838997084e2d..073a66456867 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -205,10 +205,19 @@ void release_thread(struct task_struct *dead_task) int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r) { + if (regs == NULL) + return 0; + memcpy(r, regs->fr, sizeof *r); return 1; } +int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) +{ + memcpy(r, tsk->thread.regs.fr, sizeof(*r)); + return 1; +} + /* Note that "fork()" is implemented in terms of clone, with parameters (SIGCHLD, regs->gr[30], regs). */ int diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 8c8f67e97fbc..3dd43f06820c 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -310,7 +310,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, #endif #if CACHE_FLUSHING_IS_NOT_BROKEN - flush_icache_range((unsigned long) &frame->tramp[0], + flush_user_icache_range((unsigned long) &frame->tramp[0], (unsigned long) &frame->tramp[4]); #else /* It should *always* be cache line-aligned, but the compiler @@ -395,7 +395,7 @@ static long handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, int in_syscall) { - struct k_sigaction *ka = ¤t->sig->action[sig-1]; + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; DBG(("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n", sig, ka, info, oldset, regs)); @@ -451,7 +451,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) oldset->sig[0], oldset->sig[1])); - signr = get_signal_to_deliver(&info, regs); + signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { /* Restart a system call if necessary. */ if (in_syscall) { @@ -463,7 +463,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) break; case -ERESTARTSYS: - ka = ¤t->sig->action[signr-1]; + ka = ¤t->sighand->action[signr-1]; if (!(ka->sa.sa_flags & SA_RESTART)) { DBG(("ERESTARTSYS: putting -EINTR\n")); regs->gr[28] = -EINTR; diff --git a/arch/parisc/kernel/sys32.h b/arch/parisc/kernel/sys32.h index 4a2850dcbeb8..cdb196bb8817 100644 --- a/arch/parisc/kernel/sys32.h +++ b/arch/parisc/kernel/sys32.h @@ -1,6 +1,8 @@ #ifndef _PARISC64_KERNEL_SYS32_H #define _PARISC64_KERNEL_SYS32_H +#include <linux/compat.h> + /* Call a kernel syscall which will use kernel space instead of user * space for its copy_to/from_user. */ @@ -12,6 +14,8 @@ set_fs (old_fs); \ } +#ifdef CONFIG_COMPAT + typedef __u32 __sighandler_t32; struct sigaction32 { @@ -21,3 +25,5 @@ struct sigaction32 { }; #endif + +#endif diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index fca4f7ddcac6..39b77b5db5fb 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -309,25 +309,6 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) return -ENOSYS; } -/* - * Set a given TLS descriptor: - */ -asmlinkage int sys_set_thread_area(struct user_desc *u_info) -{ - return -ENOSYS; -} - - -/* - * Get the current Thread-Local Storage area: - */ - -asmlinkage int sys_get_thread_area(struct user_desc *u_info) -{ - return -ENOSYS; -} - - asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag) { return -ENOMEM; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 2e313c898469..c0883e270f3c 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -567,10 +567,10 @@ sys_call_table: ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */ ENTRY_SAME(chown) /* 180 */ /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */ - ENTRY_DIFF(setsockopt) + ENTRY_COMP(setsockopt) ENTRY_SAME(getsockopt) - ENTRY_DIFF(sendmsg) - ENTRY_DIFF(recvmsg) + ENTRY_COMP(sendmsg) + ENTRY_COMP(recvmsg) ENTRY_SAME(semop) /* 185 */ ENTRY_SAME(semget) ENTRY_DIFF(semctl_broken) @@ -600,8 +600,8 @@ sys_call_table: ENTRY_COMP(futex) /* 210 */ ENTRY_SAME(sched_setaffinity) ENTRY_SAME(sched_getaffinity) - ENTRY_SAME(set_thread_area) - ENTRY_SAME(get_thread_area) + ENTRY_SAME(ni_syscall) + ENTRY_SAME(ni_syscall) ENTRY_SAME(io_setup) /* 215 */ ENTRY_SAME(io_destroy) ENTRY_SAME(io_getevents) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index e04f3ed3810d..6174ad652c5b 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -27,6 +27,7 @@ #include <linux/console.h> #include <linux/kallsyms.h> +#include <asm/assembly.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -165,9 +166,11 @@ void show_trace(unsigned long *stack) startstack = (unsigned long *)((unsigned long)stack & ~(THREAD_SIZE - 1)); i = 1; + stack = (long *)((long)(stack + 32) &~ (FRAME_SIZE-1)); /* Align */ printk("Kernel addresses on the stack:\n"); - while (stack >= startstack) { - addr = *stack--; + while (stack > startstack) { + stack -= 16; /* Stack frames are a multiple of 16 words */ + addr = stack[16 - RP_OFFSET / sizeof(long)]; /* * If the address is either in the text segment of the * kernel, or in the region which contains vmalloc'ed diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index eba801d82836..760f00e2780c 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -80,12 +80,8 @@ prepare: include/asm-$(ARCH)/offsets.h checkbin arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER -include/asm-$(ARCH)/offsets.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s - @$(generate-asm-offsets.h) < $< > $@ - -include/asm-$(ARCH)/offsets.h: include/asm-$(ARCH)/offsets.h.tmp - @echo -n ' Generating $@' - @$(update-if-changed) +include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s + $(call filechk,gen-asm-offsets) ifdef CONFIG_6xx # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later @@ -106,6 +102,5 @@ checkbin: @true endif -CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \ - include/asm-$(ARCH)/offsets.h \ +CLEAN_FILES += include/asm-$(ARCH)/offsets.h \ arch/$(ARCH)/kernel/asm-offsets.s diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S index 9d3b34de0b87..9f3fc6193a48 100644 --- a/arch/ppc/boot/common/util.S +++ b/arch/ppc/boot/common/util.S @@ -14,7 +14,7 @@ * trini@mvista.com * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -98,7 +98,7 @@ _setup_L2CR: isync mfspr r8,L2CR rlwinm r8,r8,0,1,31 - oris r8,r8,0x0020 + oris r8,r8,L2CR_L2I@h sync isync mtspr L2CR,r8 @@ -106,11 +106,25 @@ _setup_L2CR: isync /* Wait for the invalidation to complete */ -1: mfspr r8,L2CR - rlwinm. r9,r8,0,31,31 + mfspr r8,PVR + srwi r8,r8,16 + cmpli cr0,r8,0x8000 /* 7450 */ + cmpli cr1,r8,0x8001 /* 7455 */ + cmpli cr2,r8,0x8002 /* 7457 */ + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */ + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq + bne 2f + +1: mfspr r8,L2CR /* On 745x, poll L2I bit (bit 10) */ + rlwinm. r9,r8,0,10,10 bne 1b + b 3f + +2: mfspr r8,L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */ + rlwinm. r9,r8,0,31,31 + bne 2b - rlwinm r8,r8,0,11,9 /* Turn off L2I bit */ +3: rlwinm r8,r8,0,11,9 /* Turn off L2I bit */ sync isync mtspr L2CR,r8 @@ -118,6 +132,33 @@ _setup_L2CR: isync blr + .globl _setup_L3CR +_setup_L3CR: + /* Invalidate/disable L3 cache */ + sync + isync + mfspr r8,L3CR + rlwinm r8,r8,0,1,31 + ori r8,r8,L3CR_L3I@l + sync + isync + mtspr L3CR,r8 + sync + isync + + /* Wait for the invalidation to complete */ +1: mfspr r8,L3CR + rlwinm. r9,r8,0,21,21 + bne 1b + + rlwinm r8,r8,0,22,20 /* Turn off L3I bit */ + sync + isync + mtspr L3CR,r8 + sync + isync + blr + /* * Delay for a number of microseconds diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile index e64447c760f0..0b75247f4806 100644 --- a/arch/ppc/boot/images/Makefile +++ b/arch/ppc/boot/images/Makefile @@ -2,9 +2,8 @@ # This dir holds all of the images for PPC machines. # Tom Rini January 2001 -EXTRA_TARGETS := vmlinux.gz - -GZIP_FLAGS = -v9f +targets := vmlinux.gz +GZIP_FLAGS := -v9f $(obj)/vmlinux.gz: vmlinux $(OBJCOPY) -O binary $< $(@:.gz=) diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S index d4d2dbf016c2..d1729f3fbe30 100644 --- a/arch/ppc/boot/simple/head.S +++ b/arch/ppc/boot/simple/head.S @@ -7,7 +7,7 @@ * trini@mvista.com * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -74,6 +74,17 @@ start_: #if defined(CONFIG_FORCE) || defined(CONFIG_K2) \ || defined(CONFIG_EV64260) || defined(CONFIG_PAL4) bl _setup_L2CR + + /* If 745x, turn off L3CR as well */ + mfspr r8,PVR + srwi r8,r8,16 + + cmpli cr0,r8,0x8000 /* 7450 */ + cmpli cr1,r8,0x8001 /* 7455 */ + cmpli cr2,r8,0x8002 /* 7457 */ + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */ + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq + beql _setup_L3CR #endif #endif diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 0017345edaad..7ddf2ebb93bd 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -15,7 +15,7 @@ HEAD-$(CONFIG_40x) := head_4xx.o HEAD-$(CONFIG_8xx) := head_8xx.o HEAD-$(CONFIG_6xx) += idle_6xx.o -EXTRA_TARGETS := $(HEAD-y) +extra-y := $(HEAD-y) obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o align.o \ diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index f0130aa39421..24965586025c 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -375,7 +375,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); + seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); @@ -684,7 +684,7 @@ static void register_irq_proc (unsigned int irq) struct proc_dir_entry *entry; char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc[irq].handler == NULL)) + if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index ee68f236114b..c9b0d0490058 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -93,46 +93,6 @@ fixup_broken_pcnet32(struct pci_dev* dev) } } -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - struct pci_controller* hose = dev->sysdata; - unsigned long io_offset; - - new = res->start; - res->flags &= ~IORESOURCE_UNSET; - if (hose && res->flags & IORESOURCE_IO) { - io_offset = (unsigned long)hose->io_base_virt - isa_io_base; - new -= io_offset; - } - if (hose && res->flags & IORESOURCE_MEM) - new -= hose->pci_mem_offset; - new |= (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } - printk(KERN_INFO "PCI: moved device %s resource %d (%lx) to %x\n", - dev->slot_name, resource, res->flags, - new & ~PCI_REGION_FLAG_MASK); -} - static void pcibios_fixup_resources(struct pci_dev *dev) { @@ -1107,11 +1067,6 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp) return PCI_SLOT(dev->devfn); } -void __devinit -pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) -{ -} - unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, unsigned long start, unsigned long size) { diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c index 3a048ee52736..acc76c5f264b 100644 --- a/arch/ppc/kernel/ppc-stub.c +++ b/arch/ppc/kernel/ppc-stub.c @@ -420,18 +420,6 @@ static void kgdb_flush_cache_all(void) flush_instruction_cache(); } -static inline int get_msr(void) -{ - int msr; - asm volatile("mfmsr %0" : "=r" (msr):); - return msr; -} - -static inline void set_msr(int msr) -{ - asm volatile("mtmsr %0" : : "r" (msr)); -} - /* Set up exception handlers for tracing and breakpoints * [could be called kgdb_init()] */ @@ -598,8 +586,8 @@ handle_exception (struct pt_regs *regs) kgdb_interruptible(0); lock_kernel(); - msr = get_msr(); - set_msr(msr & ~MSR_EE); /* disable interrupts */ + msr = mfmsr(); + mtmsr(msr & ~MSR_EE); /* disable interrupts */ if (regs->nip == (unsigned long)breakinst) { /* Skip over breakpoint trap insn */ @@ -626,7 +614,7 @@ handle_exception (struct pt_regs *regs) *ptr++ = hexchars[SP_REGNUM >> 4]; *ptr++ = hexchars[SP_REGNUM & 0xf]; *ptr++ = ':'; - ptr = mem2hex(((char *)®s) + SP_REGNUM*4, ptr, 4); + ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4); *ptr++ = ';'; #endif @@ -786,7 +774,7 @@ handle_exception (struct pt_regs *regs) strcpy(remcomOutBuffer, "OK"); putpacket(remcomOutBuffer); #endif - set_msr(msr); + mtmsr(msr); kgdb_interruptible(1); unlock_kernel(); @@ -802,10 +790,9 @@ handle_exception (struct pt_regs *regs) #if defined(CONFIG_40x) regs->msr |= MSR_DE; regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC); - set_msr(msr); + mtmsr(msr); #else regs->msr |= MSR_SE; - set_msr(msr | MSR_SE); #endif unlock_kernel(); kgdb_active = 0; diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 803c73301b9d..a821de275080 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -321,6 +321,24 @@ release_thread(struct task_struct *t) } /* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + struct pt_regs *regs = tsk->thread.regs; + + if (regs == NULL) + return; + if (regs->msr & MSR_FP) + giveup_fpu(current); +#ifdef CONFIG_ALTIVEC + if (regs->msr & MSR_VEC) + giveup_altivec(current); +#endif /* CONFIG_ALTIVEC */ +} + +/* * Copy a thread.. */ int @@ -348,6 +366,8 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, } else { childregs->gpr[1] = usp; p->thread.regs = childregs; + if (clone_flags & CLONE_SETTLS) + childregs->gpr[2] = childregs->gpr[6]; } childregs->gpr[3] = 0; /* Result from fork() */ sp -= STACK_FRAME_OVERHEAD; @@ -367,29 +387,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, p->thread.ksp = sp; kregs->nip = (unsigned long)ret_from_fork; - /* - * copy fpu info - assume lazy fpu switch now always - * -- Cort - */ - if (regs->msr & MSR_FP) { - giveup_fpu(current); - childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); - } - memcpy(&p->thread.fpr, ¤t->thread.fpr, sizeof(p->thread.fpr)); - p->thread.fpscr = current->thread.fpscr; - -#ifdef CONFIG_ALTIVEC - /* - * copy altiVec info - assume lazy altiVec switch - * - kumar - */ - if (regs->msr & MSR_VEC) - giveup_altivec(current); - memcpy(&p->thread.vr, ¤t->thread.vr, sizeof(p->thread.vr)); - p->thread.vscr = current->thread.vscr; - childregs->msr &= ~MSR_VEC; -#endif /* CONFIG_ALTIVEC */ - p->thread.last_syscall = -1; return 0; @@ -444,15 +441,17 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) return put_user(val, (unsigned int *) adr); } -int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, +int sys_clone(unsigned long clone_flags, unsigned long usp, int *parent_tidp, + void *child_threadptr, int *child_tidp, int p6, struct pt_regs *regs) { struct task_struct *p; CHECK_FULL_REGS(regs); - if (p2 == 0) - p2 = regs->gpr[1]; /* stack pointer for child */ - p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4); + if (usp == 0) + usp = regs->gpr[1]; /* stack pointer for child */ + p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, + parent_tidp, child_tidp); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index a0147b2090e1..91afc431e045 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -86,13 +86,14 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * fp, long err) { + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); #ifdef CONFIG_PMAC_BACKLIGHT set_backlight_enable(1); set_backlight_level(BACKLIGHT_MAX); #endif - printk("Oops: %s, sig: %ld\n", str, err); + printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); show_regs(fp); spin_unlock_irq(&die_lock); /* do_exit() should take care of panic'ing from an interrupt diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 686745055096..22b3e384147a 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -57,6 +57,41 @@ void do_page_fault(struct pt_regs *, unsigned long, unsigned long); extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); /* + * Check whether the instruction at regs->nip is a store using + * an update addressing form which will update r1. + */ +static int store_updates_sp(struct pt_regs *regs) +{ + unsigned int inst; + + if (get_user(inst, (unsigned int *)regs->nip)) + return 0; + /* check for 1 in the rA field */ + if (((inst >> 16) & 0x1f) != 1) + return 0; + /* check major opcode */ + switch (inst >> 26) { + case 37: /* stwu */ + case 39: /* stbu */ + case 45: /* sthu */ + case 53: /* stfsu */ + case 55: /* stfdu */ + return 1; + case 31: + /* check minor opcode */ + switch ((inst >> 1) & 0x3ff) { + case 183: /* stwux */ + case 247: /* stbux */ + case 439: /* sthux */ + case 695: /* stfsux */ + case 759: /* stfdux */ + return 1; + } + } + return 0; +} + +/* * For 600- and 800-family processors, the error_code parameter is DSISR * for a data fault, SRR1 for an instruction fault. For 400-family processors * the error_code parameter is ESR for a data fault, 0 for an instruction @@ -112,6 +147,40 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; + if (!is_write) + goto bad_area; + + /* + * N.B. The rs6000/xcoff ABI allows programs to access up to + * a few hundred bytes below the stack pointer. + * The kernel signal delivery code writes up to about 1.5kB + * below the stack pointer (r1) before decrementing it. + * The exec code can write slightly over 640kB to the stack + * before setting the user r1. Thus we allow the stack to + * expand to 1MB without further checks. + */ + if (address + 0x100000 < vma->vm_end) { + /* get user regs even if this fault is in kernel mode */ + struct pt_regs *uregs = current->thread.regs; + if (uregs == NULL) + goto bad_area; + + /* + * A user-mode access to an address a long way below + * the stack pointer is only valid if the instruction + * is one which would update the stack pointer to the + * address accessed if the instruction completed, + * i.e. either stwu rs,n(r1) or stwux rs,r1,rb + * (or the byte, halfword, float or double forms). + * + * If we don't check this then any write to the area + * between the last mapped region and the stack will + * expand the stack rather than segfaulting. + */ + if (address + 2048 < uregs->gpr[1] + && (!user_mode(regs) || !store_updates_sp(regs))) + goto bad_area; + } if (expand_stack(vma, address)) goto bad_area; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 3f83000e9d4b..670bc174261b 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -338,6 +338,7 @@ void __init do_init_bootmem(void) min_low_pfn = start >> PAGE_SHIFT; max_low_pfn = (PPC_MEMSTART + total_lowmem) >> PAGE_SHIFT; + max_pfn = (PPC_MEMSTART + total_memory) >> PAGE_SHIFT; boot_mapsize = init_bootmem_node(&contig_page_data, min_low_pfn, PPC_MEMSTART >> PAGE_SHIFT, max_low_pfn); diff --git a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c index 4d929ec1f331..029ef110d2c7 100644 --- a/arch/ppc/platforms/lopec_setup.c +++ b/arch/ppc/platforms/lopec_setup.c @@ -324,7 +324,7 @@ lopec_setup_arch(void) ROOT_DEV = Root_SDA1; #endif -#ifdef CONFIG_DUMMY_CONSOLE +#ifdef CONFIG_VT conswitchp = &dummy_con; #endif #ifdef CONFIG_PPCBUG_NVRAM @@ -378,7 +378,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_ID_MODULE) +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ppc_ide_md.default_irq = lopec_ide_default_irq; ppc_ide_md.default_io_base = lopec_ide_default_io_base; ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports; diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index a6efd2c9a611..33798a25a470 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -580,14 +580,19 @@ void openpic_request_IPIs(void) if (OpenPIC == NULL) return; + /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset, - openpic_ipi_action, 0, "IPI0 (call function)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI0 (call function)", 0); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1, - openpic_ipi_action, 0, "IPI1 (reschedule)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI1 (reschedule)", 0); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2, - openpic_ipi_action, 0, "IPI2 (invalidate tlb)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI2 (invalidate tlb)", 0); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3, - openpic_ipi_action, 0, "IPI3 (xmon break)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI3 (xmon break)", 0); for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i); diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile index 169b5308b818..ae50e8ab853c 100644 --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -18,9 +18,8 @@ KERNELLOAD = 0xc000000000000000 LDFLAGS := -m elf64ppc LDFLAGS_vmlinux = -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) LDFLAGS_BLOB := --format binary --oformat elf64-powerpc -CFLAGS += -msoft-float -pipe \ - -Wno-uninitialized -mminimal-toc -mtraceback=full \ - -finline-limit-2000 -mcpu=power4 +CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ + -mtraceback=full -mcpu=power4 head-y := arch/ppc64/kernel/head.o @@ -52,10 +51,6 @@ arch/ppc64/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) - -CLEAN_FILES += include/asm-ppc64/offsets.h.tmp \ - include/asm-ppc64/offsets.h + $(call filechk,gen-asm-offsets) +CLEAN_FILES += include/asm-ppc64/offsets.h diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile index 8024fa77ca78..de26ec95e726 100644 --- a/arch/ppc64/boot/Makefile +++ b/arch/ppc64/boot/Makefile @@ -59,12 +59,12 @@ src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) host-progs := piggy addnote addSystemMap addRamDisk -EXTRA_TARGETS += zImage zImage.initrd imagesize.c \ +targets += zImage zImage.initrd imagesize.c \ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ - vmlinux.sm vmlinux.initrd vmlinux.sminitrd \ - sysmap.o initrd.o + vmlinux.sm vmlinux.initrd vmlinux.sminitrd +extra-y := sysmap.o initrd.o quiet_cmd_sysmap = SYSMAP $@ cmd_sysmap = $(obj)/addSystemMap System.map $< $@ diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index 0d97adb24d83..4b0141ea676a 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -12,12 +12,11 @@ #include "ppc32-types.h" #include "zlib.h" #include <linux/elf.h> +#include <linux/string.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/bootinfo.h> -void memmove(void *dst, void *im, int len); - extern void *finddevice(const char *); extern int getprop(void *, const char *, void *, int); extern void printk(char *fmt, ...); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 73267d76039a..07ce29f83b0a 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -3,7 +3,7 @@ # EXTRA_CFLAGS += -mno-minimal-toc -EXTRA_TARGETS := head.o +extra-y := head.o obj-y := setup.o entry.o traps.o irq.o idle.o \ time.o process.o signal.o syscalls.o misc.o ptrace.o \ align.o semaphore.o bitops.o stab.o htab.o pacaData.o \ diff --git a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c index a387af93058d..98fd34f9d8e2 100644 --- a/arch/ppc64/kernel/chrp_setup.c +++ b/arch/ppc64/kernel/chrp_setup.c @@ -72,6 +72,7 @@ extern void init_ras_IRQ(void); extern void find_and_init_phbs(void); extern void pSeries_pcibios_fixup(void); +extern void pSeries_pcibios_fixup_bus(struct pci_bus *bus); extern void iSeries_pcibios_fixup(void); extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); @@ -245,6 +246,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, #ifndef CONFIG_PPC_ISERIES ppc_md.pcibios_fixup = pSeries_pcibios_fixup; + ppc_md.pcibios_fixup_bus = pSeries_pcibios_fixup_bus; #else ppc_md.pcibios_fixup = NULL; // ppc_md.pcibios_fixup = iSeries_pcibios_fixup; diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index 19f0fe6ebd06..93d4ec05858c 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c @@ -26,6 +26,7 @@ #include <linux/pci.h> #include <linux/proc_fs.h> #include <linux/bootmem.h> +#include <linux/mm.h> #include <asm/paca.h> #include <asm/processor.h> #include <asm/naca.h> diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index 3a2fbbae70b7..ff2ddbffd627 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S @@ -344,8 +344,8 @@ irq_recheck: recheck: mfmsr r10 /* Get current interrupt state */ li r4,0 - ori r4,r4,MSR_EE|MSR_RI - andc r10,r10,r4 /* clear MSR_EE and MSR_RI */ + ori r4,r4,MSR_EE + andc r10,r10,r4 /* clear MSR_EE */ mtmsrd r10,1 /* Update machine state */ #ifdef CONFIG_PPC_ISERIES @@ -396,7 +396,7 @@ restore: mfmsr r0 li r2, MSR_RI andc r0,r0,r2 - mtmsrd r0 + mtmsrd r0,1 ld r0,_MSR(r1) mtspr SRR1,r0 @@ -422,7 +422,7 @@ restore: /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: /* Enable interrupts */ - ori r10,r10,MSR_EE|MSR_RI + ori r10,r10,MSR_EE mtmsrd r10,1 andi. r0,r3,_TIF_NEED_RESCHED diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 8a36c641f07e..5ad7bf24795b 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -562,7 +562,7 @@ fast_exception_return: mfmsr r20 li r21, MSR_RI andc r20,r20,r21 - mtmsrd r20 + mtmsrd r20,1 mtspr SRR1,r23 mtspr SRR0,r22 @@ -989,7 +989,7 @@ _GLOBAL(do_stab_bolted) mfmsr r22 li r23, MSR_RI andc r22,r22,r23 - mtmsrd r22 + mtmsrd r22,1 ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ @@ -1094,7 +1094,7 @@ SLB_NUM_ENTRIES = 64 mfmsr r22 li r23, MSR_RI andc r22,r22,r23 - mtmsrd r22 + mtmsrd r22,1 ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ diff --git a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c index a4e05fc240ab..41e382f003db 100644 --- a/arch/ppc64/kernel/htab.c +++ b/arch/ppc64/kernel/htab.c @@ -18,7 +18,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/sched.h> diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 41cd99049cd3..20ad3eb80eae 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -398,81 +398,6 @@ handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action) local_irq_disable(); } -#ifdef CONFIG_SMP -extern unsigned long irq_affinity [NR_IRQS]; - -typedef struct { - unsigned long cpu; - unsigned long timestamp; -} ____cacheline_aligned irq_balance_t; - -static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned - = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } }; - -#define IDLE_ENOUGH(cpu,now) \ - (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1)) - -#define IRQ_ALLOWED(cpu,allowed_mask) \ - ((1UL << cpu) & (allowed_mask)) - -#define IRQ_BALANCE_INTERVAL (HZ/50) - -static unsigned long move(unsigned long curr_cpu, unsigned long allowed_mask, - unsigned long now, int direction) -{ - int search_idle = 1; - int cpu = curr_cpu; - - goto inside; - - do { - if (unlikely(cpu == curr_cpu)) - search_idle = 0; -inside: - if (direction == 1) { - cpu++; - if (cpu >= NR_CPUS) - cpu = 0; - } else { - cpu--; - if (cpu == -1) - cpu = NR_CPUS-1; - } - } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || - (search_idle && !IDLE_ENOUGH(cpu,now))); - - return cpu; -} - -static inline void balance_irq(int irq) -{ - irq_balance_t *entry = irq_balance + irq; - unsigned long now = jiffies; - - if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) { - unsigned long allowed_mask; - unsigned int new_cpu; - unsigned long random_number; - - if (!irq_desc[irq].handler->set_affinity) - return; - - random_number = mftb(); - random_number &= 1; - - allowed_mask = cpu_online_map & irq_affinity[irq]; - entry->timestamp = now; - new_cpu = move(entry->cpu, allowed_mask, now, random_number); - if (entry->cpu != new_cpu) { - entry->cpu = new_cpu; - irq_desc[irq].handler->set_affinity(irq, 1UL << new_cpu); - } - } -} -#else -#define balance_irq(irq) do { } while (0) -#endif - /* * Eventually, this should take an array of interrupts and an array size * so it can dispatch multiple interrupts. @@ -484,10 +409,6 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; - /* XXX This causes bad performance and lockups on XICS - Anton */ - if (naca->interrupt_controller == IC_OPEN_PIC) - balance_irq(irq); - kstat_cpu(cpu).irqs[irq]++; spin_lock(&desc->lock); ack_irq(irq); diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 3c5120349922..81200e28f16b 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -557,7 +557,7 @@ _GLOBAL(sys_call_table32) .llong .sys32_umount .llong .sys_ni_syscall /* old lock syscall */ .llong .sys32_ioctl - .llong .sys32_fcntl /* 55 */ + .llong .compat_sys_fcntl /* 55 */ .llong .sys_ni_syscall /* old mpx syscall */ .llong .sys32_setpgid .llong .sys_ni_syscall /* old ulimit syscall */ @@ -706,7 +706,7 @@ _GLOBAL(sys_call_table32) .llong .sys_ni_syscall /* reserved for MacOnLinux */ .llong .sys_getdents64 .llong .sys_pivot_root - .llong .sys32_fcntl64 + .llong .compat_sys_fcntl64 .llong .sys_madvise /* 205 */ .llong .sys_mincore .llong .sys_gettid diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index df3609a8c019..f4046930e176 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -43,12 +43,6 @@ #include "open_pic.h" #include "pci.h" -/******************************************************************* - * Forward declares of prototypes. - *******************************************************************/ -struct pci_controller *alloc_phb(struct device_node *dev, char *model, - unsigned int addr_size_words) ; - /* RTAS tokens */ static int read_pci_config; static int write_pci_config; @@ -144,242 +138,173 @@ struct pci_ops rtas_pci_ops = { * openfirmware and sets it in the pci_dev and pci_config line. * ******************************************************************/ -int -pci_read_irq_line(struct pci_dev *Pci_Dev) +int pci_read_irq_line(struct pci_dev *pci_dev) { - u8 InterruptPin; - struct device_node *Node; + u8 intpin; + struct device_node *node; + + pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin); - pci_read_config_byte(Pci_Dev, PCI_INTERRUPT_PIN, &InterruptPin); - if (InterruptPin == 0) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",Pci_Dev->slot_name); + if (intpin == 0) { + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_dev->slot_name); return 0; } - Node = pci_device_to_OF_node(Pci_Dev); - if ( Node == NULL) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",Pci_Dev->slot_name); + + node = pci_device_to_OF_node(pci_dev); + if (node == NULL) { + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n", + pci_dev->slot_name); return -1; } - if (Node->n_intrs == 0) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",Pci_Dev->slot_name); + if (node->n_intrs == 0) { + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_dev->slot_name); return -1; } - Pci_Dev->irq = Node->intrs[0].line; + pci_dev->irq = node->intrs[0].line; if (s7a_workaround) { - if (Pci_Dev->irq > 16) - Pci_Dev->irq -= 3; + if (pci_dev->irq > 16) + pci_dev->irq -= 3; } - pci_write_config_byte(Pci_Dev, PCI_INTERRUPT_LINE, Pci_Dev->irq); + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq); - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",Pci_Dev->slot_name,Pci_Dev->irq); + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n", + pci_dev->slot_name, pci_dev->irq); return 0; } -/****************************************************************** - * Find all PHBs in the system and initialize a set of data - * structures to represent them. - ******************************************************************/ -unsigned long __init -find_and_init_phbs(void) +static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev, + int primary) { - struct device_node *Pci_Node; - struct pci_controller *phb; - unsigned int root_addr_size_words = 0, this_addr_size_words = 0; - unsigned int this_addr_count = 0, range_stride; - unsigned int *ui_ptr = NULL, *ranges; - char *model; - struct pci_range64 range; + unsigned int *ranges; + unsigned long size; + int rlen = 0; + int memno = 0; struct resource *res; - unsigned int memno, rlen, i, index; - unsigned int *opprop; - int has_isa = 0; - PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n"); - - read_pci_config = rtas_token("read-pci-config"); - write_pci_config = rtas_token("write-pci-config"); - ibm_read_pci_config = rtas_token("ibm,read-pci-config"); - ibm_write_pci_config = rtas_token("ibm,write-pci-config"); + int np, na = prom_n_addr_cells(dev); + unsigned long pci_addr, cpu_phys_addr; + + np = na + 5; + + /* + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 2: a PCI address + * cells 3 or 3+4: a CPU physical address + * (size depending on dev->n_addr_cells) + * cells 4+5 or 5+6: the size of the range + */ + rlen = 0; + hose->io_base_phys = 0; + ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + while ((rlen -= np * sizeof(unsigned int)) >= 0) { + res = NULL; + pci_addr = (unsigned long)ranges[1] << 32 | ranges[2]; + + cpu_phys_addr = ranges[3]; + if (na == 2) + cpu_phys_addr = cpu_phys_addr << 32 | ranges[4]; + + size = (unsigned long)ranges[na+3] << 32 | ranges[na+4]; + + switch (ranges[0] >> 24) { + case 1: /* I/O space */ + hose->io_base_phys = cpu_phys_addr; + hose->io_base_virt = __ioremap(hose->io_base_phys, + size, _PAGE_NO_CACHE); + if (primary) { + pci_io_base = (unsigned long)hose->io_base_virt; + if (find_type_devices("isa")) + isa_io_base = pci_io_base; + } - if (naca->interrupt_controller == IC_OPEN_PIC) { - opprop = (unsigned int *)get_property(find_path_device("/"), - "platform-open-pic", NULL); + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + res->start = pci_addr; + res->start += (unsigned long)hose->io_base_virt - + pci_io_base; + break; + case 2: /* memory space */ + memno = 0; + while (memno < 3 && hose->mem_resources[memno].flags) + ++memno; + + if (memno == 0) + hose->pci_mem_offset = cpu_phys_addr - pci_addr; + if (memno < 3) { + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + res->start = cpu_phys_addr; + } + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += np; } +} - /* Get the root address word size. */ - ui_ptr = (unsigned int *) get_property(find_path_device("/"), - "#size-cells", NULL); - if (ui_ptr) { - root_addr_size_words = *ui_ptr; - } else { - PPCDBG(PPCDBG_PHBINIT, "\tget #size-cells failed.\n"); - return(-1); - } +static void python_countermeasures(unsigned long addr) +{ + void *chip_regs; + volatile u32 *tmp, i; - if (find_type_devices("isa")) { - has_isa = 1; - PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n"); - } + /* Python's register file is 1 MB in size. */ + chip_regs = ioremap(addr & ~(0xfffffUL), 0x100000); - index = 0; + /* + * Firmware doesn't always clear this bit which is critical + * for good performance - Anton + */ - /****************************************************************** - * Find all PHB devices and create an object for them. - ******************************************************************/ - for (Pci_Node = find_devices("pci"); Pci_Node != NULL; Pci_Node = Pci_Node->next) { - model = (char *) get_property(Pci_Node, "model", NULL); - if (model != NULL) { - phb = alloc_phb(Pci_Node, model, root_addr_size_words); - if (phb == NULL) return(-1); - } - else { - continue; - } - - /* Get this node's address word size. */ - ui_ptr = (unsigned int *) get_property(Pci_Node, "#size-cells", NULL); - if (ui_ptr) - this_addr_size_words = *ui_ptr; - else - this_addr_size_words = 1; - /* Get this node's address word count. */ - ui_ptr = (unsigned int *) get_property(Pci_Node, "#address-cells", NULL); - if (ui_ptr) - this_addr_count = *ui_ptr; - else - this_addr_count = 3; - - range_stride = this_addr_count + root_addr_size_words + this_addr_size_words; - - memno = 0; - phb->io_base_phys = 0; - - ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen); - PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen); - - for (i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) { - /* Put the PCI addr part of the current element into a - * '64' struct. - */ - range = *((struct pci_range64 *)(ranges + i)); - - /* If this is a '32' element, map into a 64 struct. */ - if ((range_stride * sizeof(int)) == - sizeof(struct pci_range32)) { - range.parent_addr = - (unsigned long)(*(ranges + i + 3)); - range.size = - (((unsigned long)(*(ranges + i + 4)))<<32) | - (*(ranges + i + 5)); - } else { - range.parent_addr = - (((unsigned long)(*(ranges + i + 3)))<<32) | - (*(ranges + i + 4)); - range.size = - (((unsigned long)(*(ranges + i + 5)))<<32) | - (*(ranges + i + 6)); - } - - PPCDBG(PPCDBG_PHBINIT, "\trange.parent_addr = 0x%lx\n", - range.parent_addr); - PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.hi = 0x%lx\n", - range.child_addr.a_hi); - PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.mid = 0x%lx\n", - range.child_addr.a_mid); - PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.lo = 0x%lx\n", - range.child_addr.a_lo); - PPCDBG(PPCDBG_PHBINIT, "\trange.size = 0x%lx\n", - range.size); - - res = NULL; - switch ((range.child_addr.a_hi >> 24) & 0x3) { - case 1: /* I/O space */ - PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n"); - phb->io_base_phys = range.parent_addr; - res = &phb->io_resource; - res->name = Pci_Node->full_name; - res->flags = IORESOURCE_IO; - phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE); - if (!pci_io_base) { - pci_io_base = (unsigned long)phb->io_base_virt; - if (has_isa) - isa_io_base = pci_io_base; - } - res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo)); - res->start += (unsigned long)phb->io_base_virt - pci_io_base; - res->end = res->start + range.size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - phb->pci_io_offset = range.parent_addr - - ((((unsigned long) - range.child_addr.a_mid) << 32) | - (range.child_addr.a_lo)); - PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset = 0x%lx\n", - phb->pci_io_offset); - break; - case 2: /* mem space */ - PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n"); - phb->pci_mem_offset = range.parent_addr - - ((((unsigned long) - range.child_addr.a_mid) << 32) | - (range.child_addr.a_lo)); - PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n", - phb->pci_mem_offset); - if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) { - res = &(phb->mem_resources[memno]); - ++memno; - res->name = Pci_Node->full_name; - res->flags = IORESOURCE_MEM; - res->start = range.parent_addr; - res->end = range.parent_addr + range.size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } - break; - } - } - PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys = 0x%lx\n", - phb->io_base_phys); - PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n", - phb->pci_mem_offset); +#define PRG_CL_RESET_VALID 0x00010000 - if (naca->interrupt_controller == IC_OPEN_PIC) { - int addr = root_addr_size_words * (index + 2) - 1; - openpic_setup_ISU(index, opprop[addr]); - } - index++; + tmp = (u32 *)((unsigned long)chip_regs + 0xf6030); + + if (*tmp & PRG_CL_RESET_VALID) { + printk(KERN_INFO "Python workaround: "); + *tmp &= ~PRG_CL_RESET_VALID; + /* + * We must read it back for changes to + * take effect + */ + i = *tmp; + printk("reg0: %x\n", i); } - pci_devs_phb_init(); - return 0; /*Success */ + + iounmap(chip_regs); } -/****************************************************************** - * - * Allocate and partially initialize a structure to represent a PHB. - * - ******************************************************************/ -struct pci_controller * -alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) +struct pci_controller *alloc_phb(struct device_node *dev, + unsigned int addr_size_words) { struct pci_controller *phb; unsigned int *ui_ptr = NULL, len; struct reg_property64 reg_struct; int *bus_range; int *buid_vals; + char *model; + enum phb_types phb_type; + + model = (char *)get_property(dev, "model", NULL); + + if (!model) { + printk(KERN_ERR "alloc_phb: phb has no model property\n"); + model = "<empty>"; + } - PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name); - PPCDBG(PPCDBG_PHBINIT, "\tdev = 0x%lx\n", dev); - PPCDBG(PPCDBG_PHBINIT, "\tmodel = 0x%lx\n", model); - PPCDBG(PPCDBG_PHBINIT, "\taddr_size_words = 0x%lx\n", addr_size_words); - /* Found a PHB, now figure out where his registers are mapped. */ ui_ptr = (unsigned int *) get_property(dev, "reg", &len); if (ui_ptr == NULL) { PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n"); - return(NULL); + return NULL; } if (addr_size_words == 1) { @@ -389,83 +314,30 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) reg_struct = *((struct reg_property64 *)ui_ptr); } - PPCDBG(PPCDBG_PHBINIT, "\treg_struct.address = 0x%lx\n", reg_struct.address); - PPCDBG(PPCDBG_PHBINIT, "\treg_struct.size = 0x%lx\n", reg_struct.size); - - /*************************************************************** - * Set chip specific data in the phb, including types & - * register pointers. - ***************************************************************/ - - /**************************************************************** - * Python - ***************************************************************/ if (strstr(model, "Python")) { - void *chip_regs; - volatile u32 *tmp, i; - - PPCDBG(PPCDBG_PHBINIT, "\tCreate python\n"); - - phb = pci_alloc_pci_controller("PHB PY", phb_type_python); - if (phb == NULL) - return NULL; - - /* Python's register file is 1 MB in size. */ - chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), - 0x100000); - - /* - * Firmware doesn't always clear this bit which is critical - * for good performance - Anton - */ - -#define PRG_CL_RESET_VALID 0x00010000 - - tmp = (u32 *)((unsigned long)chip_regs + 0xf6030); - - if (*tmp & PRG_CL_RESET_VALID) { - printk("Python workaround: "); - *tmp &= ~PRG_CL_RESET_VALID; - /* - * We must read it back for changes to - * take effect - */ - i = *tmp; - printk("reg0: %x\n", i); - } + phb_type = phb_type_python; + } else if (strstr(model, "Speedwagon")) { + phb_type = phb_type_speedwagon; + } else if (strstr(model, "Winnipeg")) { + phb_type = phb_type_winnipeg; + } else { + printk(KERN_ERR "alloc_phb: unknown PHB %s\n", model); + phb_type = phb_type_unknown; + } - /*************************************************************** - * Speedwagon - * include Winnipeg as well for the time being. - ***************************************************************/ - } else if ((strstr(model, "Speedwagon")) || - (strstr(model, "Winnipeg"))) { - PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n"); - phb = pci_alloc_pci_controller("PHB SW", phb_type_speedwagon); - if (phb == NULL) - return NULL; - - phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8; - - /*************************************************************** - * Trying to build a known just gets the code in trouble. - ***************************************************************/ - } else { - PPCDBG(PPCDBG_PHBINIT, "\tUnknown PHB Type!\n"); - printk("PCI: Unknown Phb Type!\n"); + phb = pci_alloc_pci_controller(phb_type); + if (phb == NULL) return NULL; - } + + if (phb_type == phb_type_python) + python_countermeasures(reg_struct.address); bus_range = (int *) get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { - PPCDBG(PPCDBG_PHBINIT, "Can't get bus-range for %s\n", dev->full_name); kfree(phb); - return(NULL); + return NULL; } - /*************************************************************** - * Finished with the initialization - ***************************************************************/ phb->first_busno = bus_range[0]; phb->last_busno = bus_range[1]; @@ -473,7 +345,7 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) phb->ops = &rtas_pci_ops; buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len); - + if (buid_vals == NULL) { phb->buid = 0; } else { @@ -486,24 +358,71 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) panic("pSeries_pci: this system has large bus numbers and the kernel was not\n" "built with the patch that fixes include/linux/pci.h struct pci_bus so\n" "number, primary, secondary and subordinate are ints.\n"); - } - - if (len < 2 * sizeof(int)) - phb->buid = (unsigned long)buid_vals[0]; // Support for new OF that only has 1 integer for buid. - else - phb->buid = (((unsigned long)buid_vals[0]) << 32UL) | - (((unsigned long)buid_vals[1]) & 0xffffffff); - + } + + if (len < 2 * sizeof(int)) + // Support for new OF that only has 1 integer for buid. + phb->buid = (unsigned long)buid_vals[0]; + else + phb->buid = (((unsigned long)buid_vals[0]) << 32UL) | + (((unsigned long)buid_vals[1]) & 0xffffffff); + phb->first_busno += (phb->global_number << 8); phb->last_busno += (phb->global_number << 8); } /* Dump PHB information for Debug */ - PPCDBGCALL(PPCDBG_PHBINIT,dumpPci_Controller(phb) ); + PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Controller(phb)); return phb; } +unsigned long __init find_and_init_phbs(void) +{ + struct device_node *node; + struct pci_controller *phb; + unsigned int root_size_cells = 0; + unsigned int index; + unsigned int *opprop; + struct device_node *root = find_path_device("/"); + + read_pci_config = rtas_token("read-pci-config"); + write_pci_config = rtas_token("write-pci-config"); + ibm_read_pci_config = rtas_token("ibm,read-pci-config"); + ibm_write_pci_config = rtas_token("ibm,write-pci-config"); + + if (naca->interrupt_controller == IC_OPEN_PIC) { + opprop = (unsigned int *)get_property(root, + "platform-open-pic", NULL); + } + + root_size_cells = prom_n_size_cells(root); + + index = 0; + + for (node = root->child; node != NULL; node = node->sibling) { + if (node->type == NULL || strcmp(node->type, "pci") != 0) + continue; + + phb = alloc_phb(node, root_size_cells); + if (!phb) + continue; + + pci_process_bridge_OF_ranges(phb, node, index == 0); + + if (naca->interrupt_controller == IC_OPEN_PIC) { + int addr = root_size_cells * (index + 2) - 1; + openpic_setup_ISU(index, opprop[addr]); + } + + index++; + } + + pci_devs_phb_init(); + + return 0; +} + void fixup_resources(struct pci_dev *dev) { @@ -581,6 +500,55 @@ fixup_resources(struct pci_dev *dev) } } +void __init pSeries_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_controller *phb = PCI_GET_PHB_PTR(bus); + struct resource *res; + int i; + + if (bus->parent == NULL) { + /* This is a host bridge - fill in its resources */ + phb->bus = bus; + bus->resource[0] = res = &phb->io_resource; + if (!res->flags) + BUG(); /* No I/O resource for this PHB? */ + + for (i = 0; i < 3; ++i) { + res = &phb->mem_resources[i]; + if (!res->flags) { + if (i == 0) + BUG(); /* No memory resource for this PHB? */ + } + bus->resource[i+1] = res; + } + } else { + /* This is a subordinate bridge */ + pci_read_bridge_bases(bus); + + for (i = 0; i < 4; ++i) { + if ((res = bus->resource[i]) == NULL) + continue; + if (!res->flags) + continue; + if (res == pci_find_parent_resource(bus->self, res)) { + /* Transparent resource -- don't try to "fix" it. */ + continue; + } + if (res->flags & IORESOURCE_IO) { + unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base; + res->start += offset; + res->end += offset; + } else if (phb->pci_mem_offset + && (res->flags & IORESOURCE_MEM)) { + if (res->start < phb->pci_mem_offset) { + res->start += phb->pci_mem_offset; + res->end += phb->pci_mem_offset; + } + } + } + } +} + static void check_s7a(void) { struct device_node *root; @@ -629,17 +597,6 @@ pci_find_hose_for_OF_device(struct device_node *node) return NULL; } -/*********************************************************************** - * ppc64_pcibios_init - * - * Chance to initialize and structures or variable before PCI Bus walk. - * - ***********************************************************************/ -void -pSeries_pcibios_init(void) -{ -} - /* * This is called very early before the page table is setup. */ diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index c459ee120097..ba9a6feaeb50 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -49,7 +49,6 @@ static void fixup_windbond_82c105(struct pci_dev* dev); void fixup_resources(struct pci_dev* dev); void iSeries_pcibios_init(void); -void pSeries_pcibios_init(void); struct pci_controller* hose_head; struct pci_controller** hose_tail = &hose_head; @@ -128,42 +127,6 @@ struct pci_dev *pci_find_dev_by_addr(unsigned long addr) return NULL; } -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus, - struct pbus_set_ranges_data *pranges) -{ -} - -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - struct pci_controller* hose = PCI_GET_PHB_PTR(dev); - - new = res->start; - if (hose && res->flags & IORESOURCE_MEM) - new -= hose->pci_mem_offset; - new |= (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - static void pcibios_fixup_resources(struct pci_dev* dev) { @@ -363,16 +326,33 @@ pcibios_assign_resources(void) * Allocate pci_controller(phb) initialized common variables. */ struct pci_controller * __init -pci_alloc_pci_controller(char *model, enum phb_types controller_type) +pci_alloc_pci_controller(enum phb_types controller_type) { struct pci_controller *hose; - PPCDBG(PPCDBG_PHBINIT, "PCI: Allocate pci_controller for %s\n",model); + char *model; + hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); if(hose == NULL) { printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); return NULL; } memset(hose, 0, sizeof(struct pci_controller)); + + switch(controller_type) { + case phb_type_python: + model = "PHB PY"; + break; + case phb_type_speedwagon: + model = "PHB SW"; + break; + case phb_type_winnipeg: + model = "PHB WP"; + break; + default: + model = "PHB UK"; + break; + } + if(strlen(model) < 8) strcpy(hose->what,model); else @@ -393,9 +373,7 @@ pcibios_init(void) struct pci_bus *bus; int next_busno; -#ifndef CONFIG_PPC_ISERIES - pSeries_pcibios_init(); -#else +#ifdef CONFIG_PPC_ISERIES iSeries_pcibios_init(); #endif @@ -450,54 +428,7 @@ subsys_initcall(pcibios_init); void __init pcibios_fixup_bus(struct pci_bus *bus) { -#ifndef CONFIG_PPC_ISERIES - struct pci_controller *phb = PCI_GET_PHB_PTR(bus); - struct resource *res; - int i; - - if (bus->parent == NULL) { - /* This is a host bridge - fill in its resources */ - phb->bus = bus; - bus->resource[0] = res = &phb->io_resource; - if (!res->flags) - BUG(); /* No I/O resource for this PHB? */ - - for (i = 0; i < 3; ++i) { - res = &phb->mem_resources[i]; - if (!res->flags) { - if (i == 0) - BUG(); /* No memory resource for this PHB? */ - } - bus->resource[i+1] = res; - } - } else { - /* This is a subordinate bridge */ - pci_read_bridge_bases(bus); - - for (i = 0; i < 4; ++i) { - if ((res = bus->resource[i]) == NULL) - continue; - if (!res->flags) - continue; - if (res == pci_find_parent_resource(bus->self, res)) { - /* Transparent resource -- don't try to "fix" it. */ - continue; - } - if (res->flags & IORESOURCE_IO) { - unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base; - res->start += offset; - res->end += offset; - } else if (phb->pci_mem_offset - && (res->flags & IORESOURCE_MEM)) { - if (res->start < phb->pci_mem_offset) { - res->start += phb->pci_mem_offset; - res->end += phb->pci_mem_offset; - } - } - } - } -#endif - if ( ppc_md.pcibios_fixup_bus ) + if (ppc_md.pcibios_fixup_bus) ppc_md.pcibios_fixup_bus(bus); } diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h index dec5e05a397c..426972b0ad34 100644 --- a/arch/ppc64/kernel/pci.h +++ b/arch/ppc64/kernel/pci.h @@ -14,7 +14,7 @@ extern unsigned long isa_io_base; -extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type); +extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type); extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); extern struct pci_controller* hose_head; diff --git a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c index ac815895bf2a..a617d2103971 100644 --- a/arch/ppc64/kernel/pci_dma.c +++ b/arch/ppc64/kernel/pci_dma.c @@ -21,6 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/config.h> #include <linux/init.h> #include <linux/types.h> #include <linux/slab.h> diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index ebde1f0c2920..7503c2c3ba01 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -2040,11 +2040,11 @@ prom_bi_rec_verify(struct bi_record *bi_recs) if ( bi_recs == NULL || bi_recs->tag != BI_FIRST ) return NULL; - last = (struct bi_record *)bi_recs->data[0]; + last = (struct bi_record *)(long)bi_recs->data[0]; if ( last == NULL || last->tag != BI_LAST ) return NULL; - first = (struct bi_record *)last->data[0]; + first = (struct bi_record *)(long)last->data[0]; if ( first == NULL || first != bi_recs ) return NULL; diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c index 20e1d2bc0e2d..a6e226043b9c 100644 --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c @@ -21,6 +21,7 @@ #define RTC_VERSION "1.1" +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> diff --git a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S index cb924eb538a2..6c7888abb88d 100644 --- a/arch/ppc64/kernel/sys32.S +++ b/arch/ppc64/kernel/sys32.S @@ -25,287 +25,3 @@ _GLOBAL(ppc32_lseek) extsw r4,r4 /* sign extend off_t offset parm */ b .sys_lseek -_GLOBAL(compat_sys_socketcall) /* r3=call, r4=args */ - cmpwi r3, 1 - blt- .do_einval - cmpwi r3, 17 - bgt- .do_einval - subi r3, r3, 1 /* index into socketcall_table vectors and jmp */ - sldi r3, r3, 3 /* each entry is 8 bytes */ - LOADADDR(r10,.socketcall_table_begin) - ldx r10, r10, r3 - mtctr r10 - bctr - -/* Socket function vectored fix ups for 32 bit */ -_STATIC(do_sys_socket) /* sys_socket(int, int, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) - b .sys_socket - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_bind) /* sys_bind(int fd, struct sockaddr *, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .sys_bind - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_connect) /* sys_connect(int, struct sockaddr *, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .sys_connect - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_listen) /* sys_listen(int, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) - b .sys_listen - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .previous - -_STATIC(do_sys_accept) /* sys_accept(int, struct sockaddr *, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) - b .sys_accept - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_getsockname) /* sys_getsockname(int, struct sockaddr *, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) - b .sys_getsockname - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_getpeername) /* sys_getpeername(int, struct sockaddr *, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) - b .sys_getpeername - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_socketpair) /* sys_socketpair(int, int, int, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) -4: lwz r6,12(r10) - b .sys_socketpair - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .previous - -_STATIC(do_sys_send) /* sys_send(int, void *, size_t, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) - b .sys_send - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .previous - -_STATIC(do_sys_recv) /* sys_recv(int, void *, size_t, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) - b .sys_recv - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .previous - -_STATIC(do_sys_sendto) /* sys32_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) -5: lwz r7,16(r10) -6: lwz r8,20(r10) - b .sys_sendto - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .llong 6b,.do_efault - .previous - -_STATIC(do_sys_recvfrom) /* sys32_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) -5: lwz r7,16(r10) -6: lwz r8,20(r10) - b .sys_recvfrom - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .llong 6b,.do_efault - .previous - -_STATIC(do_sys_shutdown) /* sys_shutdown(int, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) - b .sys_shutdown - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .previous - -_STATIC(do_sys_setsockopt) /* compat_sys_setsockopt(int, int, int, char *, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) -4: lwz r6,12(r10) -5: lwa r7,16(r10) - b .compat_sys_setsockopt - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .previous - -_STATIC(do_sys_getsockopt) /* compat_sys_getsockopt(int, int, int, u32, u32) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) -4: lwz r6,12(r10) -5: lwz r7,16(r10) - b .compat_sys_getsockopt - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .previous - -_STATIC(do_sys_sendmsg) /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .compat_sys_sendmsg - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_recvmsg) /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .compat_sys_recvmsg - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_einval) - li r3,-EINVAL - blr - -_STATIC(do_efault) - li r3,-EFAULT - blr - - .balign 8 -_GLOBAL(socketcall_table_begin) - .llong .do_sys_socket - .llong .do_sys_bind - .llong .do_sys_connect - .llong .do_sys_listen - .llong .do_sys_accept - .llong .do_sys_getsockname - .llong .do_sys_getpeername - .llong .do_sys_socketpair - .llong .do_sys_send - .llong .do_sys_recv - .llong .do_sys_sendto - .llong .do_sys_recvfrom - .llong .do_sys_shutdown - .llong .do_sys_setsockopt - .llong .do_sys_getsockopt - .llong .do_sys_sendmsg - .llong .do_sys_recvmsg -_GLOBAL(socketcall_table_end) diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index 1954d4ba1426..c8958d50cea7 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -15,7 +15,6 @@ */ #include <asm/ptrace.h> -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/fs.h> @@ -246,32 +245,6 @@ out: return ret; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if(get_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if(put_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - return ret; - } - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - struct ncp_mount_data32_v3 { int version; unsigned int ncp_fd; @@ -2848,13 +2821,6 @@ asmlinkage long sys32_umount(char * name, u32 flags) return sys_umount(name, (int)flags); } -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - if (cmd >= F_GETLK64 && cmd <= F_SETLKW64) - return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg); - return sys32_fcntl(fd, cmd, arg); -} - struct __sysctl_args32 { u32 name; int nlen; diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index c385adf3bf22..2d8c896dcce7 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -62,10 +62,11 @@ static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char *str, struct pt_regs *regs, long err) { + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); - printk("Oops: %s, sig: %ld\n", str, err); + printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); show_regs(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); diff --git a/arch/ppc64/mm/extable.c b/arch/ppc64/mm/extable.c index 32959ff5af48..af24a6806bf2 100644 --- a/arch/ppc64/mm/extable.c +++ b/arch/ppc64/mm/extable.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <asm/uaccess.h> diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index a2d0f517177b..1ec80f0ffc58 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -1381,16 +1381,23 @@ mread(unsigned long adrs, void *buf, int size) char *p, *q; n = 0; - if( setjmp(bus_error_jmp) == 0 ){ + if (setjmp(bus_error_jmp) == 0) { debugger_fault_handler = handle_fault; sync(); - p = (char *) adrs; - q = (char *) buf; + p = (char *)adrs; + q = (char *)buf; switch (size) { - case 2: *(short *)q = *(short *)p; break; - case 4: *(int *)q = *(int *)p; break; + case 2: + *(short *)q = *(short *)p; + break; + case 4: + *(int *)q = *(int *)p; + break; + case 8: + *(long *)q = *(long *)p; + break; default: - for( ; n < size; ++n ) { + for( ; n < size; ++n) { *q++ = *p++; sync(); } @@ -1411,16 +1418,23 @@ mwrite(unsigned long adrs, void *buf, int size) char *p, *q; n = 0; - if( setjmp(bus_error_jmp) == 0 ){ + if (setjmp(bus_error_jmp) == 0) { debugger_fault_handler = handle_fault; sync(); p = (char *) adrs; q = (char *) buf; switch (size) { - case 2: *(short *)p = *(short *)q; break; - case 4: *(int *)p = *(int *)q; break; + case 2: + *(short *)p = *(short *)q; + break; + case 4: + *(int *)p = *(int *)q; + break; + case 8: + *(long *)p = *(long *)q; + break; default: - for( ; n < size; ++n ) { + for ( ; n < size; ++n) { *p++ = *q++; sync(); } diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 454b8c79d105..687b2d8e7ff1 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -48,9 +48,6 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) -CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \ - include/asm-$(ARCH)/offsets.h +CLEAN_FILES += include/asm-$(ARCH)/offsets.h diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index 44b4d732e978..b2fd41c7fdd2 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -2,8 +2,8 @@ # Makefile for the linux s390-specific parts of the memory manager. # -EXTRA_TARGETS := image listing -EXTRA_AFLAGS := -traditional +targets := image listing +EXTRA_AFLAGS := -traditional quiet_cmd_listing = OBJDUMP $@ cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \ --disassemble-zeroes --reloc vmlinux > $@ diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index ac4839d89882..7a15fab1e035 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o EXTRA_AFLAGS := -traditional obj-y := entry.o bitmap.o traps.o time.o process.o \ diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 5fac68792cd0..13b0dc2f1d3d 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -226,10 +226,11 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * regs, long err) { + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); - printk("%s: %04lx\n", str, err & 0xffff); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); show_regs(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); diff --git a/arch/s390x/Makefile b/arch/s390x/Makefile index 0b07f6ece283..322bba56bba1 100644 --- a/arch/s390x/Makefile +++ b/arch/s390x/Makefile @@ -48,9 +48,6 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) -CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \ - include/asm-$(ARCH)/offsets.h +CLEAN_FILES += include/asm-$(ARCH)/offsets.h diff --git a/arch/s390x/boot/Makefile b/arch/s390x/boot/Makefile index 1c6c9d32fabc..bd9ca0c98892 100644 --- a/arch/s390x/boot/Makefile +++ b/arch/s390x/boot/Makefile @@ -2,8 +2,8 @@ # Makefile for the linux s390-specific parts of the memory manager. # -EXTRA_TARGETS := image listing -EXTRA_AFLAGS := -traditional +targets := image listing +EXTRA_AFLAGS := -traditional quiet_cmd_listing = OBJDUMP $@ cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \ diff --git a/arch/s390x/kernel/Makefile b/arch/s390x/kernel/Makefile index 1bd693d05f0f..c59f5d6a1cc4 100644 --- a/arch/s390x/kernel/Makefile +++ b/arch/s390x/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o EXTRA_AFLAGS := -traditional obj-y := entry.o bitmap.o traps.o time.o process.o \ diff --git a/arch/s390x/kernel/binfmt_elf32.c b/arch/s390x/kernel/binfmt_elf32.c index 6a3e3f21a2b2..afa0d62df611 100644 --- a/arch/s390x/kernel/binfmt_elf32.c +++ b/arch/s390x/kernel/binfmt_elf32.c @@ -36,7 +36,7 @@ /* For SVR4/S390 the function pointer to be registered with `atexit` is passed in R14. */ -#define ELF_PLAT_INIT(_r) \ +#define ELF_PLAT_INIT(_r, load_addr) \ do { \ _r->gprs[14] = 0; \ set_thread_flag(TIF_31BIT); \ diff --git a/arch/s390x/kernel/traps.c b/arch/s390x/kernel/traps.c index ffd9f52a02ca..f90c3602c3b3 100644 --- a/arch/s390x/kernel/traps.c +++ b/arch/s390x/kernel/traps.c @@ -228,10 +228,11 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * regs, long err) { + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); - printk("%s: %04lx\n", str, err & 0xffff); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); show_regs(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 6ca25bf30d8b..cd46351053dc 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y := process.o signal.o entry.o traps.o irq.o irq_ipr.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ diff --git a/arch/sh/kernel/pci-dc.c b/arch/sh/kernel/pci-dc.c index 34ec18b09253..ed3bcf26f810 100644 --- a/arch/sh/kernel/pci-dc.c +++ b/arch/sh/kernel/pci-dc.c @@ -113,10 +113,6 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, } -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) -{ -} - void __init pcibios_fixup_bus(struct pci_bus *bus) { struct list_head *ln; diff --git a/arch/sh/kernel/pci-sh7751.c b/arch/sh/kernel/pci-sh7751.c index 9db302503b0a..19a8291aa359 100644 --- a/arch/sh/kernel/pci-sh7751.c +++ b/arch/sh/kernel/pci-sh7751.c @@ -250,12 +250,6 @@ struct pci_fixup pcibios_fixups[] = { { 0 } }; -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *b, - struct pbus_set_ranges_data *range) -{ - /* No fixups needed */ -} - /* * Called after each bus is probed, but before its children * are examined. diff --git a/arch/sh/kernel/pci_st40.c b/arch/sh/kernel/pci_st40.c index ccef05c9e87c..b1e8e2b1c1f8 100644 --- a/arch/sh/kernel/pci_st40.c +++ b/arch/sh/kernel/pci_st40.c @@ -380,12 +380,6 @@ static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) } -void __devinit -pcibios_fixup_pbus_ranges(struct pci_bus *bus, - struct pbus_set_ranges_data *ranges) -{ -} - void __init pcibios_init(void) { extern unsigned long memory_start, memory_end; diff --git a/arch/sh/kernel/pcibios.c b/arch/sh/kernel/pcibios.c index cfd0adb401fb..f9bb8ce67b94 100644 --- a/arch/sh/kernel/pcibios.c +++ b/arch/sh/kernel/pcibios.c @@ -6,7 +6,6 @@ * This is GPL'd. * * Provided here are generic versions of: - * pcibios_update_resource() * pcibios_align_resource() * pcibios_enable_device() * pcibios_set_master() @@ -19,41 +18,12 @@ * pcibios_fixup_bus() * pcibios_init() * pcibios_setup() - * pcibios_fixup_pbus_ranges() */ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 2608b613834d..daa4acebc216 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -58,9 +58,10 @@ spinlock_t die_lock; void die(const char * str, struct pt_regs * regs, long err) { + static int die_counter; console_verbose(); spin_lock_irq(&die_lock); - printk("%s: %04lx\n", str, err & 0xffff); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); show_regs(regs); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 10b172c35036..e74042a1d0eb 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -68,10 +68,7 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) -CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h.tmp \ - include/asm-$(ARCH)/asm_offsets.h \ +CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h \ arch/$(ARCH)/kernel/asm-offsets.s diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 7efc654d653a..50a46705e08d 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -8,7 +8,7 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout host-progs := piggyback btfixupprep -EXTRA_TARGETS := tftpboot.img btfix.o btfix.s image +targets := tftpboot.img btfix.o btfix.s image quiet_cmd_elftoaout = ELFTOAOUT $@ cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 64f1cade2378..9e29464c17e6 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o EXTRA_AFLAGS := -ansi diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index b7e3c63efd9f..b6e83af5d8a9 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -854,13 +854,6 @@ char * __init pcibios_setup(char *str) return str; } -/* - */ -void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1, - struct resource *res2, int index) -{ -} - void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { diff --git a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile index 51dcc7d12ab0..b948bb97e47a 100644 --- a/arch/sparc64/boot/Makefile +++ b/arch/sparc64/boot/Makefile @@ -7,8 +7,8 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout -host-progs := piggyback -EXTRA_TARGETS := tftpboot.img vmlinux.aout +host-progs := piggyback +targets := tftpboot.img vmlinux.aout quiet_cmd_elftoaout = ELT2AOUT $@ cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@ diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 2d4f332741ac..868bcd26a822 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -5,7 +5,7 @@ EXTRA_AFLAGS := -ansi EXTRA_CFLAGS := -Werror -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y := process.o setup.o cpu.o idprom.o \ traps.o devices.o auxio.o \ diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 89901b4bb74c..917614a36c23 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -470,20 +470,10 @@ int pci_assign_resource(struct pci_dev *pdev, int resource) return err; } -void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1, - struct resource *res2, int index) -{ -} - void pcibios_update_irq(struct pci_dev *pdev, int irq) { } -void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus, - struct pbus_set_ranges_data *pranges) -{ -} - void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile index 9464699ee1c1..439688b0d9e6 100644 --- a/arch/um/kernel/tt/Makefile +++ b/arch/um/kernel/tt/Makefile @@ -3,7 +3,7 @@ # Licensed under the GPL # -EXTRA_TARGETS := unmap_fin.o +extra-y := unmap_fin.o obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile index 442e041747ac..a3eca5f22f08 100644 --- a/arch/um/sys-i386/util/Makefile +++ b/arch/um/sys-i386/util/Makefile @@ -1,6 +1,7 @@ -EXTRA_TARGETS := mk_sc mk_thread mk_thread_kern.o host-progs := mk_sc +always := $(host-progs) mk_thread +targets := mk_thread_kern.o mk_thread_user.o mk_sc-objs := mk_sc.o @@ -11,6 +12,6 @@ $(obj)/mk_thread_user.o : $(src)/mk_thread_user.c $(CC) $(USER_CFLAGS) -c -o $@ $< clean : - $(RM) -f $(EXTRA_TARGETS) + $(RM) -f $(build-targets) archmrproper : clean diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile index a595641bed1b..defd03861eaa 100644 --- a/arch/um/util/Makefile +++ b/arch/um/util/Makefile @@ -1,4 +1,6 @@ -EXTRA_TARGETS := mk_task mk_constants +always := mk_task mk_constants +targets := mk_task_user.o mk_task_kern.o \ + mk_constants_user.o mk_constants_kern.o $(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o $(CC) -o $@ $^ @@ -16,6 +18,6 @@ $(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c $(CC) $(CFLAGS) -c $< -o $@ clean: - $(RM) $(EXTRA_TARGETS) + $(RM) $(build-targets) archmrproper: diff --git a/arch/v850/Makefile b/arch/v850/Makefile index 72ea1fb114d7..f1d21d639998 100644 --- a/arch/v850/Makefile +++ b/arch/v850/Makefile @@ -55,14 +55,10 @@ prepare: include/asm-$(ARCH)/asm-consts.h # Generate constants from C code for use by asm files arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \ include/config/MARKER -include/asm-$(ARCH)/asm-consts.h.tmp: arch/$(ARCH)/kernel/asm-consts.s - @$(generate-asm-offsets.h) < $< > $@ -include/asm-$(ARCH)/asm-consts.h: include/asm-$(ARCH)/asm-consts.h.tmp - @echo -n ' Generating $@' - @$(update-if-changed) +include/asm-$(ARCH)/asm-consts.h: arch/$(ARCH)/kernel/asm-consts.s + $(call filechk,gen-asm-offsets) -CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h.tmp \ - include/asm-$(ARCH)/asm-consts.h \ +CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h \ arch/$(ARCH)/kernel/asm-consts.s \ root_fs_image.o diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile index e316b8472291..9193daf95bbc 100644 --- a/arch/v850/kernel/Makefile +++ b/arch/v850/kernel/Makefile @@ -9,7 +9,7 @@ # for more details. # -EXTRA_TARGETS := head.o init_task.o +extra-y := head.o init_task.o obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \ signal.o irq.o mach.o ptrace.o bug.o diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c index 6fc07ccd955e..8e7c094292f4 100644 --- a/arch/v850/kernel/rte_mb_a_pci.c +++ b/arch/v850/kernel/rte_mb_a_pci.c @@ -287,44 +287,20 @@ void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); } -void __nomods_init -pcibios_update_resource (struct pci_dev *dev, struct resource *root, - struct resource *r, int resource) +void __devinit +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) { - u32 new, check; - int reg; - - if (r->flags & IORESOURCE_IO) - new = (((r->start - MB_A_PCI_IO_ADDR) - & PCI_BASE_ADDRESS_IO_MASK) - | PCI_BASE_ADDRESS_SPACE_IO); - else if (r->flags & IORESOURCE_MEM) - new = (((r->start - MB_A_PCI_MEM_ADDR) - & PCI_BASE_ADDRESS_MEM_MASK) - | PCI_BASE_ADDRESS_MEM_TYPE_32 - | ((r->flags & IORESOURCE_PREFETCH) - ? PCI_BASE_ADDRESS_MEM_PREFETCH - : 0) - | PCI_BASE_ADDRESS_SPACE_MEMORY); - else - panic ("pcibios_update_resource: unknown resource type"); - - if (resource < 6) - reg = PCI_BASE_ADDRESS_0 + 4*resource; - else if (resource == PCI_ROM_RESOURCE) { - r->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else - return; - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk (KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) { + offset = MB_A_PCI_IO_ADDR; + } else if (res->flags & IORESOURCE_MEM) { + offset = MB_A_PCI_MEM_ADDR; } + + region->start = res->start - offset; + region->end = res->end - offset; } diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 2e37ee42a98b..6434c4a2366c 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -86,15 +86,10 @@ prepare: include/asm-$(ARCH)/offset.h arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER -include/asm-$(ARCH)/offset.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s - include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/asm-offsets.s - @echo -n ' Generating $@' - @$(generate-asm-offsets.h) < $< > $@.tmp - @$(update-if-changed) + $(call filechk,gen-asm-offsets) -CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \ - include/asm-$(ARCH)/offset.h +CLEAN_FILES += include/asm-$(ARCH)/offset.h define archhelp echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)' diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile index f0c2676eb94d..46e4960381ca 100644 --- a/arch/x86_64/boot/Makefile +++ b/arch/x86_64/boot/Makefile @@ -25,8 +25,8 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA #RAMDISK := -DRAMDISK=512 -EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \ - setup setup.o bzImage +targets := vmlinux.bin bootsect bootsect.o \ + setup setup.o bzImage mtools.conf EXTRA_CFLAGS := -m32 diff --git a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile index 13287c58eb31..759956d1bf2d 100644 --- a/arch/x86_64/boot/compressed/Makefile +++ b/arch/x86_64/boot/compressed/Makefile @@ -6,7 +6,7 @@ # Note all the files here are compiled/linked as 32bit executables. # -EXTRA_TARGETS := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o EXTRA_AFLAGS := -traditional -m32 # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 9cd341281cb7..8fd01a20417f 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -217,7 +217,7 @@ do { \ # define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE #endif -#define ELF_PLAT_INIT(r) elf32_init(r) +#define ELF_PLAT_INIT(r, load_addr) elf32_init(r) #define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm) int ia32_setup_arg_pages(struct linux_binprm *bprm); diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index c4b84bae061c..4b4ef37305d0 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -2,8 +2,8 @@ # Makefile for the linux kernel. # -EXTRA_TARGETS := head.o head64.o init_task.o -EXTRA_AFLAGS := -traditional +extra-y := head.o head64.o init_task.o +EXTRA_AFLAGS := -traditional obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \ diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index a45bca9515be..5c4c728449b9 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -325,11 +325,12 @@ void die(const char * str, struct pt_regs * regs, long err) { int cpu; struct die_args args = { regs, str, err }; + static int die_counter; console_verbose(); notifier_call_chain(&die_chain, DIE_DIE, &args); bust_spinlocks(1); handle_BUG(regs); - printk("%s: %04lx\n", str, err & 0xffff); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); cpu = safe_smp_processor_id(); /* racy, but better than risking deadlock. */ local_irq_disable(); diff --git a/arch/x86_64/pci/x86-64.c b/arch/x86_64/pci/x86-64.c index 9c29fa694796..ba5a9f09adac 100644 --- a/arch/x86_64/pci/x86-64.c +++ b/arch/x86_64/pci/x86-64.c @@ -33,34 +33,6 @@ #include "pci.h" -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the diff --git a/drivers/base/platform.c b/drivers/base/platform.c index de932ddea39b..4f76511d902e 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -9,7 +9,7 @@ #include <linux/module.h> #include <linux/init.h> -static struct device legacy_bus = { +struct device legacy_bus = { .name = "legacy bus", .bus_id = "legacy", }; @@ -75,5 +75,7 @@ int __init platform_bus_init(void) return bus_register(&platform_bus_type); } +EXPORT_SYMBOL(legacy_bus); +EXPORT_SYMBOL(platform_bus_type); EXPORT_SYMBOL(platform_device_register); EXPORT_SYMBOL(platform_device_unregister); diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index a107ec9682ce..6735d56e2264 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c @@ -608,6 +608,12 @@ deadline_insert_request(request_queue_t *q, struct request *rq, if (unlikely(rq->flags & REQ_HARDBARRIER)) { DL_INVALIDATE_HASH(dd); q->last_merge = NULL; + + while (deadline_dispatch_requests(dd)) + ; + + list_add_tail(&rq->queuelist, dd->dispatch); + return; } if (unlikely(!blk_fs_request(rq))) { diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 04d9cc8a48b5..9812dcf39fe8 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -538,12 +538,20 @@ struct gendisk *alloc_disk(int minors) struct gendisk *get_disk(struct gendisk *disk) { struct module *owner; + struct kobject *kobj; + if (!disk->fops) return NULL; owner = disk->fops->owner; if (owner && !try_module_get(owner)) return NULL; - return to_disk(kobject_get(&disk->kobj)); + kobj = kobject_get(&disk->kobj); + if (kobj == NULL) { + module_put(owner); + return NULL; + } + return to_disk(kobj); + } void put_disk(struct gendisk *disk) diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 691ccc1f0d60..c86baf21c2b2 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -56,11 +56,7 @@ static int batch_requests; unsigned long blk_max_low_pfn, blk_max_pfn; int blk_nohighio = 0; -static struct congestion_state { - wait_queue_head_t wqh; - atomic_t nr_congested_queues; - atomic_t nr_active_queues; -} congestion_states[2]; +static wait_queue_head_t congestion_wqh[2]; /* * Return the threshold (number of free requests) at which the queue is @@ -98,14 +94,12 @@ static inline int queue_congestion_off_threshold(void) static void clear_queue_congested(request_queue_t *q, int rw) { enum bdi_state bit; - struct congestion_state *cs = &congestion_states[rw]; + wait_queue_head_t *wqh = &congestion_wqh[rw]; bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - - if (test_and_clear_bit(bit, &q->backing_dev_info.state)) - atomic_dec(&cs->nr_congested_queues); - if (waitqueue_active(&cs->wqh)) - wake_up(&cs->wqh); + clear_bit(bit, &q->backing_dev_info.state); + if (waitqueue_active(wqh)) + wake_up(wqh); } /* @@ -117,37 +111,7 @@ static void set_queue_congested(request_queue_t *q, int rw) enum bdi_state bit; bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - - if (!test_and_set_bit(bit, &q->backing_dev_info.state)) - atomic_inc(&congestion_states[rw].nr_congested_queues); -} - -/* - * A queue has just put back its last read or write request and has fallen - * idle. - */ -static void clear_queue_active(request_queue_t *q, int rw) -{ - enum bdi_state bit; - - bit = (rw == WRITE) ? BDI_write_active : BDI_read_active; - - if (test_and_clear_bit(bit, &q->backing_dev_info.state)) - atomic_dec(&congestion_states[rw].nr_active_queues); -} - -/* - * A queue has just taken its first read or write request and has become - * active. - */ -static void set_queue_active(request_queue_t *q, int rw) -{ - enum bdi_state bit; - - bit = (rw == WRITE) ? BDI_write_active : BDI_read_active; - - if (!test_and_set_bit(bit, &q->backing_dev_info.state)) - atomic_inc(&congestion_states[rw].nr_active_queues); + set_bit(bit, &q->backing_dev_info.state); } /** @@ -1040,7 +1004,8 @@ void generic_unplug_device(void *data) static void blk_unplug_work(void *data) { - generic_unplug_device(data); + request_queue_t *q = data; + q->unplug_fn(q); } static void blk_unplug_timeout(unsigned long data) @@ -1324,8 +1289,6 @@ static struct request *get_request(request_queue_t *q, int rw) rq = blkdev_free_rq(&rl->free); list_del_init(&rq->queuelist); rq->ref_count = 1; - if (rl->count == queue_nr_requests) - set_queue_active(q, rw); rl->count--; if (rl->count < queue_congestion_on_threshold()) set_queue_congested(q, rw); @@ -1568,8 +1531,6 @@ void __blk_put_request(request_queue_t *q, struct request *req) rl->count++; if (rl->count >= queue_congestion_off_threshold()) clear_queue_congested(q, rw); - if (rl->count == queue_nr_requests) - clear_queue_active(q, rw); if (rl->count >= batch_requests && waitqueue_active(&rl->wait)) wake_up(&rl->wait); } @@ -1604,12 +1565,12 @@ void blk_put_request(struct request *req) void blk_congestion_wait(int rw, long timeout) { DEFINE_WAIT(wait); - struct congestion_state *cs = &congestion_states[rw]; + wait_queue_head_t *wqh = &congestion_wqh[rw]; blk_run_queues(); - prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE); + prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); io_schedule_timeout(timeout); - finish_wait(&cs->wqh, &wait); + finish_wait(wqh, &wait); } /* @@ -2248,11 +2209,8 @@ int __init blk_dev_init(void) blk_max_low_pfn = max_low_pfn; blk_max_pfn = max_pfn; - for (i = 0; i < ARRAY_SIZE(congestion_states); i++) { - init_waitqueue_head(&congestion_states[i].wqh); - atomic_set(&congestion_states[i].nr_congested_queues, 0); - atomic_set(&congestion_states[i].nr_active_queues, 0); - } + for (i = 0; i < ARRAY_SIZE(congestion_wqh); i++) + init_waitqueue_head(&congestion_wqh[i]); return 0; }; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d98a11175015..ebc50ca263d2 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -709,39 +709,20 @@ config NWFLASH If you're not sure, say N. -config INTEL_RNG - tristate "Intel i8x0 Random Number Generator support" +config HW_RANDOM + tristate "Intel/AMD/VIA HW Random Number Generator support" depends on (X86 || IA64) && PCI ---help--- This driver provides kernel-side support for the Random Number - Generator hardware found on Intel i8xx-based motherboards. + Generator hardware found on Intel i8xx-based motherboards, + AMD 76x-based motherboards, and Via Nehemiah CPUs. - Both a character driver, used to read() entropy data, and a timer - function which automatically adds entropy directly into the - kernel pool, are exported by this driver. + Provides a character driver, used to read() entropy data. To compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/modules.txt>. The module will be called - i810_rng. - - If unsure, say N. - -config AMD_RNG - tristate "AMD 768 Random Number Generator support" - depends on X86 && PCI - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on AMD 76x based motherboards. - - Both a character driver, used to read() entropy data, and a timer - function which automatically adds entropy directly into the - kernel pool, are exported by this driver. - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read <file:Documentation/modules.txt>. The module will be called - amd768_rng. + hw_random. If unsure, say N. diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 147b19429bf5..b03db0a153c0 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -59,8 +59,7 @@ endif obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o -obj-$(CONFIG_INTEL_RNG) += i810_rng.o -obj-$(CONFIG_AMD_RNG) += amd768_rng.o +obj-$(CONFIG_HW_RANDOM) += hw_random.o obj-$(CONFIG_QIC02_TAPE) += tpqic02.o obj-$(CONFIG_FTAPE) += ftape/ obj-$(CONFIG_H8) += h8.o diff --git a/drivers/char/amd768_rng.c b/drivers/char/amd768_rng.c deleted file mode 100644 index 6b059eef4556..000000000000 --- a/drivers/char/amd768_rng.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - Hardware driver for the AMD 768 Random Number Generator (RNG) - (c) Copyright 2001 Red Hat Inc <alan@redhat.com> - - derived from - - Hardware driver for Intel i810 Random Number Generator (RNG) - Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> - Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> - - Please read Documentation/i810_rng.txt for details on use. - - ---------------------------------------------------------- - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - */ - - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/random.h> -#include <linux/miscdevice.h> -#include <linux/smp_lock.h> -#include <linux/mm.h> -#include <linux/delay.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - - -/* - * core module and version information - */ -#define RNG_VERSION "0.1.0" -#define RNG_MODULE_NAME "amd768_rng" -#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " - - -/* - * debugging macros - */ -#undef RNG_DEBUG /* define to enable copious debugging info */ - -#ifdef RNG_DEBUG -/* note: prints function name for you */ -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - -#undef RNG_NDEBUG /* define to disable lightweight runtime checks */ -#ifdef RNG_NDEBUG -#define assert(expr) -#else -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - -#define RNG_MISCDEV_MINOR 183 /* official */ - -/* - * various RNG status variables. they are globals - * as we only support a single RNG device - */ - -static u32 pmbase; /* PMxx I/O base */ -static struct semaphore rng_open_sem; /* Semaphore for serializing rng_open/release */ - - -/* - * inlined helper functions for accessing RNG registers - */ - -static inline int rng_data_present (void) -{ - return inl(pmbase+0xF4) & 1; -} - - -static inline int rng_data_read (void) -{ - return inl(pmbase+0xF0); -} - -static int rng_dev_open (struct inode *inode, struct file *filp) -{ - if ((filp->f_mode & FMODE_READ) == 0) - return -EINVAL; - if (filp->f_mode & FMODE_WRITE) - return -EINVAL; - - /* wait for device to become free */ - if (filp->f_flags & O_NONBLOCK) { - if (down_trylock (&rng_open_sem)) - return -EAGAIN; - } else { - if (down_interruptible (&rng_open_sem)) - return -ERESTARTSYS; - } - return 0; -} - - -static int rng_dev_release (struct inode *inode, struct file *filp) -{ - up(&rng_open_sem); - return 0; -} - - -static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, - loff_t * offp) -{ - static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; - int have_data; - u32 data = 0; - ssize_t ret = 0; - - while (size) { - spin_lock(&rng_lock); - - have_data = 0; - if (rng_data_present()) { - data = rng_data_read(); - have_data = 4; - } - - spin_unlock (&rng_lock); - - while (have_data > 0) { - if (put_user((u8)data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - have_data--; - data>>=8; - } - - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; - - if(need_resched()) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - else - udelay(200); /* FIXME: We could poll for 250uS ?? */ - - if (signal_pending (current)) - return ret ? : -ERESTARTSYS; - } - return ret; -} - - -static struct file_operations rng_chrdev_ops = { - .owner = THIS_MODULE, - .open = rng_dev_open, - .release = rng_dev_release, - .read = rng_dev_read, -}; - - -static struct miscdevice rng_miscdev = { - RNG_MISCDEV_MINOR, - RNG_MODULE_NAME, - &rng_chrdev_ops, -}; - - -/* - * rng_init_one - look for and attempt to init a single RNG - */ -static int __init rng_init_one (struct pci_dev *dev) -{ - int rc; - u8 rnen; - - DPRINTK ("ENTER\n"); - - rc = misc_register (&rng_miscdev); - if (rc) { - printk (KERN_ERR PFX "cannot register misc device\n"); - DPRINTK ("EXIT, returning %d\n", rc); - goto err_out; - } - - pci_read_config_dword(dev, 0x58, &pmbase); - - pmbase&=0x0000FF00; - - if(pmbase == 0) - { - printk (KERN_ERR PFX "power management base not set\n"); - DPRINTK ("EXIT, returning %d\n", rc); - goto err_out_free_miscdev; - } - - pci_read_config_byte(dev, 0x40, &rnen); - rnen|=(1<<7); /* RNG on */ - pci_write_config_byte(dev, 0x40, rnen); - - pci_read_config_byte(dev, 0x41, &rnen); - rnen|=(1<<7); /* PMIO enable */ - pci_write_config_byte(dev, 0x41, rnen); - - printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase); - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_free_miscdev: - misc_deregister (&rng_miscdev); -err_out: - return rc; -} - - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id rng_pci_tbl[] __initdata = { - { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, rng_pci_tbl); - - -MODULE_AUTHOR("Alan Cox, Jeff Garzik, Philipp Rumpf, Matt Sottek"); -MODULE_DESCRIPTION("AMD 768 Random Number Generator (RNG) driver"); -MODULE_LICENSE("GPL"); - - -/* - * rng_init - initialize RNG module - */ -static int __init rng_init (void) -{ - int rc; - struct pci_dev *pdev; - - DPRINTK ("ENTER\n"); - - init_MUTEX (&rng_open_sem); - - pci_for_each_dev(pdev) { - if (pci_match_device (rng_pci_tbl, pdev) != NULL) - goto match; - } - - DPRINTK ("EXIT, returning -ENODEV\n"); - return -ENODEV; - -match: - rc = rng_init_one (pdev); - if (rc) - return rc; - - printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); - - DPRINTK ("EXIT, returning 0\n"); - return 0; -} - - -/* - * rng_init - shutdown RNG module - */ -static void __exit rng_cleanup (void) -{ - DPRINTK ("ENTER\n"); - misc_deregister (&rng_miscdev); - DPRINTK ("EXIT\n"); -} - - -module_init (rng_init); -module_exit (rng_cleanup); diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c new file mode 100644 index 000000000000..a3a483e16aeb --- /dev/null +++ b/drivers/char/hw_random.c @@ -0,0 +1,630 @@ +/* + Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> + + derived from + + Hardware driver for the AMD 768 Random Number Generator (RNG) + (c) Copyright 2001 Red Hat Inc <alan@redhat.com> + + derived from + + Hardware driver for Intel i810 Random Number Generator (RNG) + Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + + Please read Documentation/hw_random.txt for details on use. + + ---------------------------------------------------------- + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + */ + + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/random.h> +#include <linux/miscdevice.h> +#include <linux/smp_lock.h> +#include <linux/mm.h> +#include <linux/delay.h> + +#ifdef __i386__ +#include <asm/msr.h> +#include <asm/cpufeature.h> +#endif + +#include <asm/io.h> +#include <asm/uaccess.h> + + +/* + * core module and version information + */ +#define RNG_VERSION "0.9.0" +#define RNG_MODULE_NAME "hw_random" +#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION +#define PFX RNG_MODULE_NAME ": " + + +/* + * debugging macros + */ +#undef RNG_DEBUG /* define to enable copious debugging info */ + +#ifdef RNG_DEBUG +/* note: prints function name for you */ +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define RNG_NDEBUG /* define to disable lightweight runtime checks */ +#ifdef RNG_NDEBUG +#define assert(expr) +#else +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#endif + +#define RNG_MISCDEV_MINOR 183 /* official */ + +static int rng_dev_open (struct inode *inode, struct file *filp); +static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, + loff_t * offp); + +static int __init intel_init (struct pci_dev *dev); +static void intel_cleanup(void); +static unsigned int intel_data_present (void); +static u32 intel_data_read (void); + +static int __init amd_init (struct pci_dev *dev); +static void amd_cleanup(void); +static unsigned int amd_data_present (void); +static u32 amd_data_read (void); + +static int __init via_init(struct pci_dev *dev); +static void via_cleanup(void); +static unsigned int via_data_present (void); +static u32 via_data_read (void); + +struct rng_operations { + int (*init) (struct pci_dev *dev); + void (*cleanup) (void); + unsigned int (*data_present) (void); + u32 (*data_read) (void); + unsigned int n_bytes; /* number of bytes per ->data_read */ +}; +static struct rng_operations *rng_ops; + +static struct file_operations rng_chrdev_ops = { + .owner = THIS_MODULE, + .open = rng_dev_open, + .read = rng_dev_read, +}; + + +static struct miscdevice rng_miscdev = { + RNG_MISCDEV_MINOR, + RNG_MODULE_NAME, + &rng_chrdev_ops, +}; + +enum { + rng_hw_none, + rng_hw_intel, + rng_hw_amd, + rng_hw_via, +}; + +static struct rng_operations rng_vendor_ops[] __initdata = { + /* rng_hw_none */ + { }, + + /* rng_hw_intel */ + { intel_init, intel_cleanup, intel_data_present, + intel_data_read, 1 }, + + /* rng_hw_amd */ + { amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 }, + + /* rng_hw_via */ + { via_init, via_cleanup, via_data_present, via_data_read, 1 }, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id rng_pci_tbl[] __initdata = { + { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, + + { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE (pci, rng_pci_tbl); + + +/*********************************************************************** + * + * Intel RNG operations + * + */ + +/* + * RNG registers (offsets from rng_mem) + */ +#define INTEL_RNG_HW_STATUS 0 +#define INTEL_RNG_PRESENT 0x40 +#define INTEL_RNG_ENABLED 0x01 +#define INTEL_RNG_STATUS 1 +#define INTEL_RNG_DATA_PRESENT 0x01 +#define INTEL_RNG_DATA 2 + +/* + * Magic address at which Intel PCI bridges locate the RNG + */ +#define INTEL_RNG_ADDR 0xFFBC015F +#define INTEL_RNG_ADDR_LEN 3 + +/* token to our ioremap'd RNG register area */ +static void *rng_mem; + +static inline u8 intel_hwstatus (void) +{ + assert (rng_mem != NULL); + return readb (rng_mem + INTEL_RNG_HW_STATUS); +} + +static inline u8 intel_hwstatus_set (u8 hw_status) +{ + assert (rng_mem != NULL); + writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS); + return intel_hwstatus (); +} + +static unsigned int intel_data_present(void) +{ + assert (rng_mem != NULL); + + return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ? + 1 : 0; +} + +static u32 intel_data_read(void) +{ + assert (rng_mem != NULL); + + return readb (rng_mem + INTEL_RNG_DATA); +} + +static int __init intel_init (struct pci_dev *dev) +{ + int rc; + u8 hw_status; + + DPRINTK ("ENTER\n"); + + rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); + if (rng_mem == NULL) { + printk (KERN_ERR PFX "cannot ioremap RNG Memory\n"); + rc = -EBUSY; + goto err_out; + } + + /* Check for Intel 82802 */ + hw_status = intel_hwstatus (); + if ((hw_status & INTEL_RNG_PRESENT) == 0) { + printk (KERN_ERR PFX "RNG not detected\n"); + rc = -ENODEV; + goto err_out_free_map; + } + + /* turn RNG h/w on, if it's off */ + if ((hw_status & INTEL_RNG_ENABLED) == 0) + hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED); + if ((hw_status & INTEL_RNG_ENABLED) == 0) { + printk (KERN_ERR PFX "cannot enable RNG, aborting\n"); + rc = -EIO; + goto err_out_free_map; + } + + DPRINTK ("EXIT, returning 0\n"); + return 0; + +err_out_free_map: + iounmap (rng_mem); + rng_mem = NULL; +err_out: + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + +static void intel_cleanup(void) +{ + u8 hw_status; + + hw_status = intel_hwstatus (); + if (hw_status & INTEL_RNG_ENABLED) + intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED); + else + printk(KERN_WARNING PFX "unusual: RNG already disabled\n"); + iounmap(rng_mem); + rng_mem = NULL; +} + +/*********************************************************************** + * + * AMD RNG operations + * + */ + +static u32 pmbase; /* PMxx I/O base */ +static struct pci_dev *amd_dev; + +static unsigned int amd_data_present (void) +{ + return inl(pmbase + 0xF4) & 1; +} + + +static u32 amd_data_read (void) +{ + return inl(pmbase + 0xF0); +} + +static int __init amd_init (struct pci_dev *dev) +{ + int rc; + u8 rnen; + + DPRINTK ("ENTER\n"); + + pci_read_config_dword(dev, 0x58, &pmbase); + + pmbase &= 0x0000FF00; + + if (pmbase == 0) + { + printk (KERN_ERR PFX "power management base not set\n"); + rc = -EIO; + goto err_out; + } + + pci_read_config_byte(dev, 0x40, &rnen); + rnen |= (1 << 7); /* RNG on */ + pci_write_config_byte(dev, 0x40, rnen); + + pci_read_config_byte(dev, 0x41, &rnen); + rnen |= (1 << 7); /* PMIO enable */ + pci_write_config_byte(dev, 0x41, rnen); + + printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase); + + amd_dev = dev; + + DPRINTK ("EXIT, returning 0\n"); + return 0; + +err_out: + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + +static void amd_cleanup(void) +{ + u8 rnen; + + pci_read_config_byte(amd_dev, 0x40, &rnen); + rnen &= ~(1 << 7); /* RNG off */ + pci_write_config_byte(amd_dev, 0x40, rnen); + + /* FIXME: twiddle pmio, also? */ +} + +/*********************************************************************** + * + * VIA RNG operations + * + */ + +enum { + VIA_STRFILT_CNT_SHIFT = 16, + VIA_STRFILT_FAIL = (1 << 15), + VIA_STRFILT_ENABLE = (1 << 14), + VIA_RAWBITS_ENABLE = (1 << 13), + VIA_RNG_ENABLE = (1 << 6), + VIA_XSTORE_CNT_MASK = 0x0F, + + VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ + VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF, + VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_2_MASK = 0xFFFF, + VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_1_MASK = 0xFF, +}; + +u32 via_rng_datum; + +/* + * Investigate using the 'rep' prefix to obtain 32 bits of random data + * in one insn. The upside is potentially better performance. The + * downside is that the instruction becomes no longer atomic. Due to + * this, just like familiar issues with /dev/random itself, the worst + * case of a 'rep xstore' could potentially pause a cpu for an + * unreasonably long time. In practice, this condition would likely + * only occur when the hardware is failing. (or so we hope :)) + * + * Another possible performance boost may come from simply buffering + * until we have 4 bytes, thus returning a u32 at a time, + * instead of the current u8-at-a-time. + */ + +static inline u32 xstore(u32 *addr, u32 edx_in) +{ + u32 eax_out; + + asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" + :"=m"(*addr), "=a"(eax_out) + :"D"(addr), "d"(edx_in)); + + return eax_out; +} + +static unsigned int via_data_present(void) +{ + u32 bytes_out; + + /* We choose the recommended 1-byte-per-instruction RNG rate, + * for greater randomness at the expense of speed. Larger + * values 2, 4, or 8 bytes-per-instruction yield greater + * speed at lesser randomness. + * + * If you change this to another VIA_CHUNK_n, you must also + * change the ->n_bytes values in rng_vendor_ops[] tables. + * VIA_CHUNK_8 requires further code changes. + * + * A copy of MSR_VIA_RNG is placed in eax_out when xstore + * completes. + */ + via_rng_datum = 0; /* paranoia, not really necessary */ + bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK; + if (bytes_out == 0) + return 0; + + return 1; +} + +static u32 via_data_read(void) +{ + return via_rng_datum; +} + +static int __init via_init(struct pci_dev *dev) +{ + u32 lo, hi, old_lo; + + /* Control the RNG via MSR. Tread lightly and pay very close + * close attention to values written, as the reserved fields + * are documented to be "undefined and unpredictable"; but it + * does not say to write them as zero, so I make a guess that + * we restore the values we find in the register. + */ + rdmsr(MSR_VIA_RNG, lo, hi); + + old_lo = lo; + lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT); + lo &= ~VIA_XSTORE_CNT_MASK; + lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); + lo |= VIA_RNG_ENABLE; + + if (lo != old_lo) + wrmsr(MSR_VIA_RNG, lo, hi); + + /* perhaps-unnecessary sanity check; remove after testing if + unneeded */ + rdmsr(MSR_VIA_RNG, lo, hi); + if ((lo & VIA_RNG_ENABLE) == 0) { + printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n"); + return -ENODEV; + } + + return 0; +} + +static void via_cleanup(void) +{ + u32 lo, hi; + + rdmsr(MSR_VIA_RNG, lo, hi); + lo &= ~VIA_RNG_ENABLE; + wrmsr(MSR_VIA_RNG, lo, hi); +} + + +/*********************************************************************** + * + * /dev/hwrandom character device handling (major 10, minor 183) + * + */ + +static int rng_dev_open (struct inode *inode, struct file *filp) +{ + /* enforce read-only access to this chrdev */ + if ((filp->f_mode & FMODE_READ) == 0) + return -EINVAL; + if (filp->f_mode & FMODE_WRITE) + return -EINVAL; + + return 0; +} + + +static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, + loff_t * offp) +{ + static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; + unsigned int have_data; + u32 data = 0; + ssize_t ret = 0; + + while (size) { + spin_lock(&rng_lock); + + have_data = 0; + if (rng_ops->data_present()) { + data = rng_ops->data_read(); + have_data = rng_ops->n_bytes; + } + + spin_unlock (&rng_lock); + + while (have_data > 0) { + if (put_user((u8)data, buf++)) { + ret = ret ? : -EFAULT; + break; + } + size--; + ret++; + have_data--; + data>>=8; + } + + if (filp->f_flags & O_NONBLOCK) + return ret ? : -EAGAIN; + + if(need_resched()) + { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + else + udelay(200); /* FIXME: We could poll for 250uS ?? */ + + if (signal_pending (current)) + return ret ? : -ERESTARTSYS; + } + return ret; +} + + + +/* + * rng_init_one - look for and attempt to init a single RNG + */ +static int __init rng_init_one (struct pci_dev *dev) +{ + int rc; + + DPRINTK ("ENTER\n"); + + assert(rng_ops != NULL); + + rc = rng_ops->init(dev); + if (rc) + goto err_out; + + rc = misc_register (&rng_miscdev); + if (rc) { + printk (KERN_ERR PFX "misc device register failed\n"); + goto err_out_cleanup_hw; + } + + DPRINTK ("EXIT, returning 0\n"); + return 0; + +err_out_cleanup_hw: + rng_ops->cleanup(); +err_out: + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + + + +MODULE_AUTHOR("The Linux Kernel team"); +MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL"); + + +/* + * rng_init - initialize RNG module + */ +static int __init rng_init (void) +{ + int rc; + struct pci_dev *pdev; + const struct pci_device_id *ent; + + DPRINTK ("ENTER\n"); + + /* Probe for Intel, AMD RNGs */ + pci_for_each_dev(pdev) { + ent = pci_match_device (rng_pci_tbl, pdev); + if (ent) { + rng_ops = &rng_vendor_ops[ent->driver_data]; + goto match; + } + } + +#ifdef __i386__ + /* Probe for VIA RNG */ + if (cpu_has_xstore) { + rng_ops = &rng_vendor_ops[rng_hw_via]; + pdev = NULL; + goto match; + } +#endif + + DPRINTK ("EXIT, returning -ENODEV\n"); + return -ENODEV; + +match: + rc = rng_init_one (pdev); + if (rc) + return rc; + + printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); + + DPRINTK ("EXIT, returning 0\n"); + return 0; +} + + +/* + * rng_init - shutdown RNG module + */ +static void __exit rng_cleanup (void) +{ + DPRINTK ("ENTER\n"); + + misc_deregister (&rng_miscdev); + + if (rng_ops->cleanup) + rng_ops->cleanup(); + + DPRINTK ("EXIT\n"); +} + + +module_init (rng_init); +module_exit (rng_cleanup); diff --git a/drivers/char/i810_rng.c b/drivers/char/i810_rng.c deleted file mode 100644 index 52671e065ede..000000000000 --- a/drivers/char/i810_rng.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - - Hardware driver for Intel i810 Random Number Generator (RNG) - Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> - Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> - - Driver Web site: http://sourceforge.net/projects/gkernel/ - - Please read Documentation/i810_rng.txt for details on use. - - ---------------------------------------------------------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - */ - - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/random.h> -#include <linux/miscdevice.h> -#include <linux/smp_lock.h> -#include <linux/mm.h> -#include <linux/delay.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - - -/* - * core module and version information - */ -#define RNG_VERSION "0.9.8" -#define RNG_MODULE_NAME "i810_rng" -#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " - - -/* - * debugging macros - */ -#undef RNG_DEBUG /* define to enable copious debugging info */ - -#ifdef RNG_DEBUG -/* note: prints function name for you */ -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - -#undef RNG_NDEBUG /* define to disable lightweight runtime checks */ -#ifdef RNG_NDEBUG -#define assert(expr) -#else -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* - * RNG registers (offsets from rng_mem) - */ -#define RNG_HW_STATUS 0 -#define RNG_PRESENT 0x40 -#define RNG_ENABLED 0x01 -#define RNG_STATUS 1 -#define RNG_DATA_PRESENT 0x01 -#define RNG_DATA 2 - -/* - * Magic address at which Intel PCI bridges locate the RNG - */ -#define RNG_ADDR 0xFFBC015F -#define RNG_ADDR_LEN 3 - -#define RNG_MISCDEV_MINOR 183 /* official */ - -/* - * various RNG status variables. they are globals - * as we only support a single RNG device - */ -static void *rng_mem; /* token to our ioremap'd RNG register area */ -static struct semaphore rng_open_sem; /* Semaphore for serializing rng_open/release */ - - -/* - * inlined helper functions for accessing RNG registers - */ -static inline u8 rng_hwstatus (void) -{ - assert (rng_mem != NULL); - return readb (rng_mem + RNG_HW_STATUS); -} - -static inline u8 rng_hwstatus_set (u8 hw_status) -{ - assert (rng_mem != NULL); - writeb (hw_status, rng_mem + RNG_HW_STATUS); - return rng_hwstatus (); -} - - -static inline int rng_data_present (void) -{ - assert (rng_mem != NULL); - - return (readb (rng_mem + RNG_STATUS) & RNG_DATA_PRESENT) ? 1 : 0; -} - - -static inline int rng_data_read (void) -{ - assert (rng_mem != NULL); - - return readb (rng_mem + RNG_DATA); -} - -/* - * rng_enable - enable the RNG hardware - */ - -static int rng_enable (void) -{ - int rc = 0; - u8 hw_status, new_status; - - DPRINTK ("ENTER\n"); - - hw_status = rng_hwstatus (); - - if ((hw_status & RNG_ENABLED) == 0) { - new_status = rng_hwstatus_set (hw_status | RNG_ENABLED); - - if (new_status & RNG_ENABLED) - printk (KERN_INFO PFX "RNG h/w enabled\n"); - else { - printk (KERN_ERR PFX "Unable to enable the RNG\n"); - rc = -EIO; - } - } - - DPRINTK ("EXIT, returning %d\n", rc); - return rc; -} - -/* - * rng_disable - disable the RNG hardware - */ - -static void rng_disable(void) -{ - u8 hw_status, new_status; - - DPRINTK ("ENTER\n"); - - hw_status = rng_hwstatus (); - - if (hw_status & RNG_ENABLED) { - new_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED); - - if ((new_status & RNG_ENABLED) == 0) - printk (KERN_INFO PFX "RNG h/w disabled\n"); - else { - printk (KERN_ERR PFX "Unable to disable the RNG\n"); - } - } - - DPRINTK ("EXIT\n"); -} - -static int rng_dev_open (struct inode *inode, struct file *filp) -{ - int rc; - - if ((filp->f_mode & FMODE_READ) == 0) - return -EINVAL; - if (filp->f_mode & FMODE_WRITE) - return -EINVAL; - - /* wait for device to become free */ - if (filp->f_flags & O_NONBLOCK) { - if (down_trylock (&rng_open_sem)) - return -EAGAIN; - } else { - if (down_interruptible (&rng_open_sem)) - return -ERESTARTSYS; - } - - rc = rng_enable (); - if (rc) { - up (&rng_open_sem); - return rc; - } - - return 0; -} - - -static int rng_dev_release (struct inode *inode, struct file *filp) -{ - rng_disable (); - up (&rng_open_sem); - return 0; -} - - -static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, - loff_t * offp) -{ - static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; - int have_data; - u8 data = 0; - ssize_t ret = 0; - - while (size) { - spin_lock (&rng_lock); - - have_data = 0; - if (rng_data_present ()) { - data = rng_data_read (); - have_data = 1; - } - - spin_unlock (&rng_lock); - - if (have_data) { - if (put_user (data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - } - - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; - - if (need_resched()) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - else - udelay(200); - - if (signal_pending (current)) - return ret ? : -ERESTARTSYS; - } - - return ret; -} - - -static struct file_operations rng_chrdev_ops = { - .owner = THIS_MODULE, - .open = rng_dev_open, - .release = rng_dev_release, - .read = rng_dev_read, -}; - - -static struct miscdevice rng_miscdev = { - RNG_MISCDEV_MINOR, - RNG_MODULE_NAME, - &rng_chrdev_ops, -}; - - -/* - * rng_init_one - look for and attempt to init a single RNG - */ -static int __init rng_init_one (struct pci_dev *dev) -{ - int rc; - u8 hw_status; - - DPRINTK ("ENTER\n"); - - rc = misc_register (&rng_miscdev); - if (rc) { - printk (KERN_ERR PFX "cannot register misc device\n"); - DPRINTK ("EXIT, returning %d\n", rc); - goto err_out; - } - - rng_mem = ioremap (RNG_ADDR, RNG_ADDR_LEN); - if (rng_mem == NULL) { - printk (KERN_ERR PFX "cannot ioremap RNG Memory\n"); - DPRINTK ("EXIT, returning -EBUSY\n"); - rc = -EBUSY; - goto err_out_free_miscdev; - } - - /* Check for Intel 82802 */ - hw_status = rng_hwstatus (); - if ((hw_status & RNG_PRESENT) == 0) { - printk (KERN_ERR PFX "RNG not detected\n"); - DPRINTK ("EXIT, returning -ENODEV\n"); - rc = -ENODEV; - goto err_out_free_map; - } - - /* turn RNG h/w off, if it's on */ - if (hw_status & RNG_ENABLED) - hw_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED); - if (hw_status & RNG_ENABLED) { - printk (KERN_ERR PFX "cannot disable RNG, aborting\n"); - goto err_out_free_map; - } - - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_free_map: - iounmap (rng_mem); -err_out_free_miscdev: - misc_deregister (&rng_miscdev); -err_out: - return rc; -} - - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id rng_pci_tbl[] __initdata = { - { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, rng_pci_tbl); - - -MODULE_AUTHOR("Jeff Garzik, Philipp Rumpf, Matt Sottek"); -MODULE_DESCRIPTION("Intel i8xx chipset Random Number Generator (RNG) driver"); -MODULE_LICENSE("GPL"); - - -/* - * rng_init - initialize RNG module - */ -static int __init rng_init (void) -{ - int rc; - struct pci_dev *pdev; - - DPRINTK ("ENTER\n"); - - init_MUTEX (&rng_open_sem); - - pci_for_each_dev(pdev) { - if (pci_match_device (rng_pci_tbl, pdev) != NULL) - goto match; - } - - DPRINTK ("EXIT, returning -ENODEV\n"); - return -ENODEV; - -match: - rc = rng_init_one (pdev); - if (rc) - return rc; - - printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); - - DPRINTK ("EXIT, returning 0\n"); - return 0; -} - - -/* - * rng_init - shutdown RNG module - */ -static void __exit rng_cleanup (void) -{ - DPRINTK ("ENTER\n"); - - misc_deregister (&rng_miscdev); - - iounmap (rng_mem); - - DPRINTK ("EXIT\n"); -} - - -module_init (rng_init); -module_exit (rng_cleanup); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 32488d71037f..c712200fd2ea 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1034,7 +1034,9 @@ static void release_mem(struct tty_struct *tty, int idx) } o_tty->magic = 0; (*o_tty->driver.refcount)--; + file_list_lock(); list_del(&o_tty->tty_files); + file_list_unlock(); free_tty_struct(o_tty); } @@ -1046,7 +1048,9 @@ static void release_mem(struct tty_struct *tty, int idx) } tty->magic = 0; (*tty->driver.refcount)--; + file_list_lock(); list_del(&tty->tty_files); + file_list_unlock(); module_put(tty->driver.owner); free_tty_struct(tty); } @@ -2235,14 +2239,19 @@ struct device_class tty_devclass = { }; EXPORT_SYMBOL(tty_devclass); +static int __init tty_devclass_init(void) +{ + return devclass_register(&tty_devclass); +} + +postcore_initcall(tty_devclass_init); + /* * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ void __init tty_init(void) { - devclass_register(&tty_devclass); - /* * dev_tty_driver and dev_console_driver are actually magic * devices which get redirected at open time. Nevertheless, diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index cda2f20d8308..b29ecd8bca5f 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -191,38 +191,56 @@ do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm) static inline int do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) { - struct kbsentry tmp; + struct kbsentry *kbs; char *p; u_char *q; int sz; int delta; char *first_free, *fj, *fnw; int i, j, k; + int ret; + + kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); + if (!kbs) { + ret = -ENOMEM; + goto reterr; + } /* we mostly copy too much here (512bytes), but who cares ;) */ - if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry))) - return -EFAULT; - tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0'; - if (tmp.kb_func >= MAX_NR_FUNC) - return -EINVAL; - i = tmp.kb_func; + if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { + ret = -EFAULT; + goto reterr; + } + kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; + if (kbs->kb_func >= MAX_NR_FUNC) { + ret = -EINVAL; + goto reterr; + } + i = kbs->kb_func; switch (cmd) { case KDGKBSENT: - sz = sizeof(tmp.kb_string) - 1; /* sz should have been + sz = sizeof(kbs->kb_string) - 1; /* sz should have been a struct member */ q = user_kdgkb->kb_string; p = func_table[i]; if(p) for ( ; *p && sz; p++, sz--) - if (put_user(*p, q++)) - return -EFAULT; - if (put_user('\0', q)) - return -EFAULT; + if (put_user(*p, q++)) { + ret = -EFAULT; + goto reterr; + } + if (put_user('\0', q)) { + ret = -EFAULT; + goto reterr; + } + kfree(kbs); return ((p && *p) ? -EOVERFLOW : 0); case KDSKBSENT: - if (!perm) - return -EPERM; + if (!perm) { + ret = -EPERM; + goto reterr; + } q = func_table[i]; first_free = funcbufptr + (funcbufsize - funcbufleft); @@ -233,7 +251,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) else fj = first_free; - delta = (q ? -strlen(q) : 1) + strlen(tmp.kb_string); + delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); if (delta <= funcbufleft) { /* it fits in current buf */ if (j < MAX_NR_FUNC) { memmove(fj + delta, fj, first_free - fj); @@ -249,8 +267,10 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) while (sz < funcbufsize - funcbufleft + delta) sz <<= 1; fnw = (char *) kmalloc(sz, GFP_KERNEL); - if(!fnw) - return -ENOMEM; + if(!fnw) { + ret = -ENOMEM; + goto reterr; + } if (!q) func_table[i] = fj; @@ -272,17 +292,19 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) funcbufleft = funcbufleft - delta + sz - funcbufsize; funcbufsize = sz; } - strcpy(func_table[i], tmp.kb_string); + strcpy(func_table[i], kbs->kb_string); break; } - return 0; + ret = 0; +reterr: + kfree(kbs); + return ret; } static inline int -do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm) +do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm, struct console_font_op *op) { struct consolefontdesc cfdarg; - struct console_font_op op; int i; if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) @@ -292,25 +314,25 @@ do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm) case PIO_FONTX: if (!perm) return -EPERM; - op.op = KD_FONT_OP_SET; - op.flags = KD_FONT_FLAG_OLD; - op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - return con_font_op(fg_console, &op); + op->op = KD_FONT_OP_SET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; + return con_font_op(fg_console, op); case GIO_FONTX: { - op.op = KD_FONT_OP_GET; - op.flags = KD_FONT_FLAG_OLD; - op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - i = con_font_op(fg_console, &op); + op->op = KD_FONT_OP_GET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; + i = con_font_op(fg_console, op); if (i) return i; - cfdarg.charheight = op.height; - cfdarg.charcount = op.charcount; + cfdarg.charheight = op->height; + cfdarg.charcount = op->charcount; if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) return -EFAULT; return 0; @@ -355,6 +377,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, unsigned char ucval; struct kbd_struct * kbd; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + struct console_font_op op; /* used in multiple places here */ console = vt->vc_num; @@ -860,7 +883,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, } case PIO_FONT: { - struct console_font_op op; if (!perm) return -EPERM; op.op = KD_FONT_OP_SET; @@ -873,7 +895,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, } case GIO_FONT: { - struct console_font_op op; op.op = KD_FONT_OP_GET; op.flags = KD_FONT_FLAG_OLD; op.width = 8; @@ -893,7 +914,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case PIO_FONTX: case GIO_FONTX: - return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm); + return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm, &op); case PIO_FONTRESET: { @@ -906,7 +927,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return -ENOSYS; #else { - struct console_font_op op; op.op = KD_FONT_OP_SET_DEFAULT; op.data = NULL; i = con_font_op(fg_console, &op); @@ -918,7 +938,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, } case KDFONTOP: { - struct console_font_op op; if (copy_from_user(&op, (void *) arg, sizeof(op))) return -EFAULT; if (!perm && op.op != KD_FONT_OP_GET) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index dcd25b1c59c3..67abe170a8de 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -5,6 +5,20 @@ menu "I2C Hardware Sensors Mainboard support" +config I2C_ALI15X3 + tristate " ALI 15x3" + depends on I2C && I2C_PROC && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. + + This can also be built as a module. If so, the module will be + called i2c-ali15x3. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + config I2C_AMD756 tristate " AMD 756/766" depends on I2C && I2C_PROC @@ -39,5 +53,51 @@ config I2C_AMD8111 in the lm_sensors package, which you can download at http://www.lm-sensors.nu +config I2C_I801 + tristate " Intel 801" + depends on I2C && I2C_PROC && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the Intel + 801 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset is supported: + 82801AA + 82801AB + 82801BA + 82801CA/CAM + 82801DB + + This can also be built as a module which can be inserted and removed + while the kernel is running. If you want to compile it as a module, + say M here and read <file:Documentation/modules.txt>. + + The module will be called i2c-i801. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + +config I2C_PIIX4 + tristate " Intel PIIX4" + depends on I2C && I2C_PROC && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the Intel + PIIX4 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset is supported: + Intel PIIX4 + Intel 440MX + Serverworks OSB4 + Serverworks CSB5 + SMSC Victory66 + + This can also be built as a module which can be inserted and removed + while the kernel is running. If you want to compile it as a module, + say M here and read <file:Documentation/modules.txt>. + + The module will be called i2c-piix4. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 181b1d97e0a9..c8e61d4a6f88 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -2,5 +2,8 @@ # Makefile for the kernel hardware sensors bus drivers. # +obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o +obj-$(CONFIG_I2C_I801) += i2c-i801.o +obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c new file mode 100644 index 000000000000..8d7f372e109f --- /dev/null +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -0,0 +1,575 @@ +/* + ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and + Philip Edelbrock <phil@netroedge.com> and + Mark D. Studebaker <mdsxyz123@yahoo.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + This is the driver for the SMB Host controller on + Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. + + The M1543C is a South bridge for desktop systems. + The M1533 is a South bridge for portable systems. + They are part of the following ALI chipsets: + "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge + with AGP and 100MHz CPU Front Side bus + "Aladdin V": Includes the M1541 Socket 7 North bridge + with AGP and 100MHz CPU Front Side bus + "Aladdin IV": Includes the M1541 Socket 7 North bridge + with host bus up to 83.3 MHz. + For an overview of these chips see http://www.acerlabs.com + + The M1533/M1543C devices appear as FOUR separate devices + on the PCI bus. An output of lspci will show something similar + to the following: + + 00:02.0 USB Controller: Acer Laboratories Inc. M5237 + 00:03.0 Bridge: Acer Laboratories Inc. M7101 + 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 + 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 + + The SMB controller is part of the 7101 device, which is an + ACPI-compliant Power Management Unit (PMU). + + The whole 7101 device has to be enabled for the SMB to work. + You can't just enable the SMB alone. + The SMB and the ACPI have separate I/O spaces. + We make sure that the SMB is enabled. We leave the ACPI alone. + + This driver controls the SMB Host only. + The SMB Slave controller on the M15X3 is not enabled. + + This driver does not use interrupts. +*/ + +/* Note: we assume there can only be one ALI15X3, with one SMBus interface */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <asm/io.h> + +/* ALI15X3 SMBus address offsets */ +#define SMBHSTSTS (0 + ali15x3_smba) +#define SMBHSTCNT (1 + ali15x3_smba) +#define SMBHSTSTART (2 + ali15x3_smba) +#define SMBHSTCMD (7 + ali15x3_smba) +#define SMBHSTADD (3 + ali15x3_smba) +#define SMBHSTDAT0 (4 + ali15x3_smba) +#define SMBHSTDAT1 (5 + ali15x3_smba) +#define SMBBLKDAT (6 + ali15x3_smba) + +/* PCI Address Constants */ +#define SMBCOM 0x004 +#define SMBBA 0x014 +#define SMBATPC 0x05B /* used to unlock xxxBA registers */ +#define SMBHSTCFG 0x0E0 +#define SMBSLVC 0x0E1 +#define SMBCLK 0x0E2 +#define SMBREV 0x008 + +/* Other settings */ +#define MAX_TIMEOUT 200 /* times 1/100 sec */ +#define ALI15X3_SMB_IOSIZE 32 + +/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. + We don't use these here. If the bases aren't set to some value we + tell user to upgrade BIOS and we fail. +*/ +#define ALI15X3_SMB_DEFAULTBASE 0xE800 + +/* ALI15X3 address lock bits */ +#define ALI15X3_LOCK 0x06 + +/* ALI15X3 command constants */ +#define ALI15X3_ABORT 0x02 +#define ALI15X3_T_OUT 0x04 +#define ALI15X3_QUICK 0x00 +#define ALI15X3_BYTE 0x10 +#define ALI15X3_BYTE_DATA 0x20 +#define ALI15X3_WORD_DATA 0x30 +#define ALI15X3_BLOCK_DATA 0x40 +#define ALI15X3_BLOCK_CLR 0x80 + +/* ALI15X3 status register bits */ +#define ALI15X3_STS_IDLE 0x04 +#define ALI15X3_STS_BUSY 0x08 +#define ALI15X3_STS_DONE 0x10 +#define ALI15X3_STS_DEV 0x20 /* device error */ +#define ALI15X3_STS_COLL 0x40 /* collision or no response */ +#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ +#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ + + +/* If force_addr is set to anything different from 0, we forcibly enable + the device at the given address. */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Initialize the base address of the i2c controller"); + + +static void ali15x3_do_pause(unsigned int amount); +static int ali15x3_transaction(void); + +static unsigned short ali15x3_smba = 0; + +int ali15x3_setup(struct pci_dev *ALI15X3_dev) +{ + u16 a; + unsigned char temp; + +/* Check the following things: + - SMB I/O address is initialized + - Device is enabled + - We can use the addresses +*/ + +/* Unlock the register. + The data sheet says that the address registers are read-only + if the lock bits are 1, but in fact the address registers + are zero unless you clear the lock bits. +*/ + pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); + if (temp & ALI15X3_LOCK) { + temp &= ~ALI15X3_LOCK; + pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); + } + +/* Determine the address of the SMBus area */ + pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); + ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); + if (ali15x3_smba == 0 && force_addr == 0) { + printk + ("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + + if(force_addr) + ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); + + if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) { + printk + ("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n", + ali15x3_smba); + return -ENODEV; + } + + if(force_addr) { + printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba); + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba)) + return -ENODEV; + if (PCIBIOS_SUCCESSFUL != + pci_read_config_word(ALI15X3_dev, SMBBA, &a)) + return -ENODEV; + if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { + /* make sure it works */ + printk("i2c-ali15x3.o: force address failed - not supported?\n"); + return -ENODEV; + } + } +/* check if whole device is enabled */ + pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); + if ((temp & 1) == 0) { + printk("i2c-ali15x3: enabling SMBus device\n"); + pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); + } + +/* Is SMB Host controller enabled? */ + pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); + if ((temp & 1) == 0) { + printk("i2c-ali15x3: enabling SMBus controller\n"); + pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); + } + +/* set SMB clock to 74KHz as recommended in data sheet */ + pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); + + /* Everything is happy, let's grab the memory and set things up. */ + request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb"); + +#ifdef DEBUG +/* + The interrupt routing for SMB is set up in register 0x77 in the + 1533 ISA Bridge device, NOT in the 7101 device. + Don't bother with finding the 1533 device and reading the register. + if ((....... & 0x0F) == 1) + printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n"); +*/ + pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); + printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp); + printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba); +#endif /* DEBUG */ + + return 0; +} + + +/* Internally used pause function */ +void ali15x3_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +/* Another internally used function */ +int ali15x3_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " + "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); +#endif + + /* get status */ + temp = inb_p(SMBHSTSTS); + + /* Make sure the SMBus host is ready to start transmitting */ + /* Check the busy bit first */ + if (temp & ALI15X3_STS_BUSY) { +/* + If the host controller is still busy, it may have timed out in the previous transaction, + resulting in a "SMBus Timeout" printk. + I've tried the following to reset a stuck busy bit. + 1. Reset the controller with an ABORT command. + (this doesn't seem to clear the controller if an external device is hung) + 2. Reset the controller and the other SMBus devices with a T_OUT command. + (this clears the host busy bit if an external device is hung, + but it comes back upon a new access to a device) + 3. Disable and reenable the controller in SMBHSTCFG + Worst case, nothing seems to work except power reset. +*/ +/* Abort - reset the host controller */ +/* +#ifdef DEBUG + printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp); +#endif + outb_p(ALI15X3_ABORT, SMBHSTCNT); + temp = inb_p(SMBHSTSTS); + if (temp & ALI15X3_STS_BUSY) { +*/ + +/* + Try resetting entire SMB bus, including other devices - + This may not work either - it clears the BUSY bit but + then the BUSY bit may come back on when you try and use the chip again. + If that's the case you are stuck. +*/ + printk + ("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n", + temp); + outb_p(ALI15X3_T_OUT, SMBHSTCNT); + temp = inb_p(SMBHSTSTS); + } +/* + } +*/ + + /* now check the error bits and the busy bit */ + if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { + /* do a clear-on-write */ + outb_p(0xFF, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) & + (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { + /* this is probably going to be correctable only by a power reset + as one of the bits now appears to be stuck */ + /* This may be a bus or device with electrical problems. */ + printk + ("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n", + temp); + return -1; + } + } else { + /* check and clear done bit */ + if (temp & ALI15X3_STS_DONE) { + outb_p(temp, SMBHSTSTS); + } + } + + /* start the transaction by writing anything to the start register */ + outb_p(0xFF, SMBHSTSTART); + + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + ali15x3_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) + && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + result = -1; + printk("i2c-ali15x3.o: SMBus Timeout!\n"); + } + + if (temp & ALI15X3_STS_TERM) { + result = -1; +#ifdef DEBUG + printk("i2c-ali15x3.o: Error: Failed bus transaction\n"); +#endif + } + +/* + Unfortunately the ALI SMB controller maps "no response" and "bus collision" + into a single bit. No reponse is the usual case so don't + do a printk. + This means that bus collisions go unreported. +*/ + if (temp & ALI15X3_STS_COLL) { + result = -1; +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n", + inb_p(SMBHSTADD)); +#endif + } + +/* haven't ever seen this */ + if (temp & ALI15X3_STS_DEV) { + result = -1; + printk("i2c-ali15x3.o: Error: device error\n"); + } +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); +#endif + return result; +} + +/* Return -1 on error. */ +s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data * data) +{ + int i, len; + int temp; + int timeout; + +/* clear all the bits (clear-on-write) */ + outb_p(0xFF, SMBHSTSTS); +/* make sure SMBus is idle */ + temp = inb_p(SMBHSTSTS); + for (timeout = 0; + (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); + timeout++) { + ali15x3_do_pause(1); + temp = inb_p(SMBHSTSTS); + } + if (timeout >= MAX_TIMEOUT) { + printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n", + temp); + } + + switch (size) { + case I2C_SMBUS_PROC_CALL: + printk + ("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n"); + return -1; + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI15X3_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + size = ALI15X3_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + size = ALI15X3_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + size = ALI15X3_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 0) { + len = 0; + data->block[0] = len; + } + if (len > 32) { + len = 32; + data->block[0] = len; + } + outb_p(len, SMBHSTDAT0); + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= len; i++) + outb_p(data->block[i], SMBBLKDAT); + } + size = ALI15X3_BLOCK_DATA; + break; + } + + outb_p(size, SMBHSTCNT); /* output command */ + + if (ali15x3_transaction()) /* Error in transaction */ + return -1; + + if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) + return 0; + + + switch (size) { + case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */ + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI15X3_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI15X3_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + case ALI15X3_BLOCK_DATA: + len = inb_p(SMBHSTDAT0); + if (len > 32) + len = 32; + data->block[0] = len; + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= data->block[0]; i++) { + data->block[i] = inb_p(SMBBLKDAT); +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n", + len, i, data->block[i]); +#endif /* DEBUG */ + } + break; + } + return 0; +} + + +u32 ali15x3_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = ali15x3_access, + .functionality = ali15x3_func, +}; + +static struct i2c_adapter ali15x3_adapter = { + .owner = THIS_MODULE, + .name = "unset", + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, + .algo = &smbus_algorithm, +}; + + + +static struct pci_device_id ali15x3_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_AL, + .device = PCI_DEVICE_ID_AL_M7101, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, } +}; + +static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + if (ali15x3_setup(dev)) { + printk + ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n"); + + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + ali15x3_adapter.dev.parent = &dev->dev; + + sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x", + ali15x3_smba); + return i2c_add_adapter(&ali15x3_adapter); +} + +static void __devexit ali15x3_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&ali15x3_adapter); +} + +static struct pci_driver ali15x3_driver = { + .name = "ali15x3 smbus", + .id_table = ali15x3_ids, + .probe = ali15x3_probe, + .remove = __devexit_p(ali15x3_remove), +}; + +static int __init i2c_ali15x3_init(void) +{ + printk("i2c-ali15x3.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&ali15x3_driver); +} + + +static void __exit i2c_ali15x3_exit(void) +{ + pci_unregister_driver(&ali15x3_driver); + release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); +} + + + +MODULE_AUTHOR + ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>"); +MODULE_DESCRIPTION("ALI15X3 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_ali15x3_init); +module_exit(i2c_ali15x3_exit); diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index b2627572924e..d4bc60ebac3d 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -375,6 +375,9 @@ static int __devinit amd756_probe(struct pci_dev *pdev, printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport); #endif + /* set up the driverfs linkage to our parent device */ + amd756_adapter.dev.parent = &pdev->dev; + sprintf(amd756_adapter.name, "SMBus AMD75x adapter at %04x", amd756_ioport); diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index a3adbe770f8c..07f22e6e8495 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -363,6 +363,9 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_ smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; + /* set up the driverfs linkage to our parent device */ + smbus->adapter.dev.parent = &dev->dev; + error = i2c_add_adapter(&smbus->adapter); if (error) goto out_release_region; @@ -389,7 +392,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev) } static struct pci_driver amd8111_driver = { - .name = "amd8111 smbus 2.0", + .name = "amd8111 smbus", .id_table = amd8111_ids, .probe = amd8111_probe, .remove = __devexit_p(amd8111_remove), diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c new file mode 100644 index 000000000000..b1556e08ce54 --- /dev/null +++ b/drivers/i2c/busses/i2c-i801.c @@ -0,0 +1,715 @@ +/* + i801.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, + Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker + <mdsxyz123@yahoo.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + SUPPORTED DEVICES PCI ID + 82801AA 2413 + 82801AB 2423 + 82801BA 2443 + 82801CA/CAM 2483 + 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) + + This driver supports several versions of Intel's I/O Controller Hubs (ICH). + For SMBus support, they are similar to the PIIX4 and are part + of Intel's '810' and other chipsets. + See the doc/busses/i2c-i801 file for details. + I2C Block Read and Process Call are not supported. +*/ + +/* Note: we assume there can only be one I801, with one SMBus interface */ + +/* #define DEBUG 1 */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <asm/io.h> + +MODULE_LICENSE("GPL"); + +#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC +#define HAVE_PEC +#endif + +#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS +#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS 0x2483 +#endif + +#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS +#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS 0x24C3 +#endif + +static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3, + PCI_DEVICE_ID_INTEL_82801AB_3, + PCI_DEVICE_ID_INTEL_82801BA_2, + PCI_DEVICE_ID_INTEL_82801CA_SMBUS, + PCI_DEVICE_ID_INTEL_82801DB_SMBUS, + 0 }; + +/* I801 SMBus address offsets */ +#define SMBHSTSTS (0 + i801_smba) +#define SMBHSTCNT (2 + i801_smba) +#define SMBHSTCMD (3 + i801_smba) +#define SMBHSTADD (4 + i801_smba) +#define SMBHSTDAT0 (5 + i801_smba) +#define SMBHSTDAT1 (6 + i801_smba) +#define SMBBLKDAT (7 + i801_smba) +#define SMBPEC (8 + i801_smba) /* ICH4 only */ +#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ +#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ + +/* PCI Address Constants */ +#define SMBBA 0x020 +#define SMBHSTCFG 0x040 +#define SMBREV 0x008 + +/* Host configuration bits for SMBHSTCFG */ +#define SMBHSTCFG_HST_EN 1 +#define SMBHSTCFG_SMB_SMI_EN 2 +#define SMBHSTCFG_I2C_EN 4 + +/* Other settings */ +#define MAX_TIMEOUT 100 +#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ + +/* I801 command constants */ +#define I801_QUICK 0x00 +#define I801_BYTE 0x04 +#define I801_BYTE_DATA 0x08 +#define I801_WORD_DATA 0x0C +#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ +#define I801_BLOCK_DATA 0x14 +#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ +#define I801_BLOCK_LAST 0x34 +#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ +#define I801_START 0x40 +#define I801_PEC_EN 0x80 /* ICH4 only */ + +/* insmod parameters */ + +/* If force_addr is set to anything different from 0, we forcibly enable + the I801 at the given address. VERY DANGEROUS! */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Forcibly enable the I801 at the given address. " + "EXTREMELY DANGEROUS!"); + + + + + +static void i801_do_pause(unsigned int amount); +static int i801_transaction(void); +static int i801_block_transaction(union i2c_smbus_data *data, + char read_write, int command); + +static unsigned short i801_smba; +static struct pci_dev *I801_dev; +static int isich4; + +static int i801_setup(struct pci_dev *dev) +{ + int error_return = 0; + int *num = supported; + unsigned char temp; + + /* Note: we keep on searching until we have found 'function 3' */ + if(PCI_FUNC(dev->devfn) != 3) + return -ENODEV; + + I801_dev = dev; + isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS; + +/* Determine the address of the SMBus areas */ + if (force_addr) { + i801_smba = force_addr & 0xfff0; + } else { + pci_read_config_word(I801_dev, SMBBA, &i801_smba); + i801_smba &= 0xfff0; + if(i801_smba == 0) { + printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + } + + if (check_region(i801_smba, (isich4 ? 16 : 8))) { + printk + (KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n", + i801_smba); + error_return = -ENODEV; + goto END; + } + + pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); + temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ + pci_write_config_byte(I801_dev, SMBHSTCFG, temp); +/* If force_addr is set, we program the new address here. Just to make + sure, we disable the device first. */ + if (force_addr) { + pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); + pci_write_config_word(I801_dev, SMBBA, i801_smba); + pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); + printk + (KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new " + "address %04x!\n", i801_smba); + } else if ((temp & 1) == 0) { + pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); + printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n"); + } + + request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus"); + +#ifdef DEBUG + if (temp & 0x02) + printk + (KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n"); + else + printk + (KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n"); + + pci_read_config_byte(I801_dev, SMBREV, &temp); + printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp); + printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba); +#endif /* DEBUG */ + + END: + return error_return; +} + + +void i801_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +int i801_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " + "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + + /* Make sure the SMBus host is ready to start transmitting */ + /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", + temp); +#endif + outb_p(temp, SMBHSTSTS); + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp); +#endif + return -1; + } else { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Successfull!\n"); +#endif + } + } + + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + + /* We will always wait for a fraction of a second! */ + do { + i801_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n"); + result = -1; +#endif + } + + if (temp & 0x10) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n"); +#endif + } + + if (temp & 0x08) { + result = -1; + printk + (KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n" + "reset. (sorry!)\n"); + /* Clock stops and slave is stuck in mid-transmission */ + } + + if (temp & 0x04) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n"); +#endif + } + + if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) + outb_p(inb(SMBHSTSTS), SMBHSTSTS); + + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n", + temp); +#endif + } +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + return result; +} + +/* All-inclusive block transaction function */ +int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command) +{ + int i, len; + int smbcmd; + int temp; + int result = 0; + int timeout; + unsigned char hostc, errmask; + + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ + pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(I801_dev, SMBHSTCFG, + hostc | SMBHSTCFG_I2C_EN); + } else { + printk("i2c-i801.o: " + "I2C_SMBUS_I2C_BLOCK_READ not supported!\n"); + return -1; + } + } + + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 1) + len = 1; + if (len > 32) + len = 32; + outb_p(len, SMBHSTDAT0); + outb_p(data->block[1], SMBBLKDAT); + } else { + len = 32; /* max for reads */ + } + + if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { + /* set 32 byte buffer */ + } + + for (i = 1; i <= len; i++) { + if (i == len && read_write == I2C_SMBUS_READ) + smbcmd = I801_BLOCK_LAST; + else + smbcmd = I801_BLOCK_DATA; +#if 0 /* now using HW PEC */ + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) + smbcmd |= I801_PEC_EN; +#endif + outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); + +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBBLKDAT)); +#endif + + /* Make sure the SMBus host is ready to start transmitting */ + temp = inb_p(SMBHSTSTS); + if (i == 1) { + /* Erronenous conditions before transaction: + * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ + errmask=0x9f; + } else { + /* Erronenous conditions during transaction: + * Failed, Bus_Err, Dev_Err, Intr */ + errmask=0x1e; + } + if (temp & errmask) { +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", + temp); +#endif + outb_p(temp, SMBHSTSTS); + if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { + printk + (KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n", + temp); + result = -1; + goto END; + } + if (i != 1) { + result = -1; /* if die in middle of block transaction, fail */ + goto END; + } + } + + if (i == 1) { +#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */ + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { + if(read_write == I2C_SMBUS_WRITE) + outb_p(data->block[len + 1], SMBPEC); + } +#endif + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + } + + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + temp = inb_p(SMBHSTSTS); + i801_do_pause(1); + } + while ((!(temp & 0x80)) + && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n"); +#endif + } + + if (temp & 0x10) { + result = -1; +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n"); +#endif + } else if (temp & 0x08) { + result = -1; + printk(KERN_ERR "i2c-i801.o: Bus collision!\n"); + } else if (temp & 0x04) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n"); +#endif + } + + if (i == 1 && read_write == I2C_SMBUS_READ) { + len = inb_p(SMBHSTDAT0); + if (len < 1) + len = 1; + if (len > 32) + len = 32; + data->block[0] = len; + } + + /* Retrieve/store value in SMBBLKDAT */ + if (read_write == I2C_SMBUS_READ) + data->block[i] = inb_p(SMBBLKDAT); + if (read_write == I2C_SMBUS_WRITE && i+1 <= len) + outb_p(data->block[i+1], SMBBLKDAT); + if ((temp & 0x9e) != 0x00) + outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ + +#ifdef DEBUG + if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { + printk + (KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n", + temp); + } + printk + (KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBBLKDAT)); +#endif + + if (result < 0) + goto END; + } + +#ifdef HAVE_PEC + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { + /* wait for INTR bit as advised by Intel */ + timeout = 0; + do { + temp = inb_p(SMBHSTSTS); + i801_do_pause(1); + } while ((!(temp & 0x02)) + && (timeout++ < MAX_TIMEOUT)); + + if (timeout >= MAX_TIMEOUT) { + printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n"); + } +#if 0 /* now using HW PEC */ + if(read_write == I2C_SMBUS_READ) { + data->block[len + 1] = inb_p(SMBPEC); + } +#endif + outb_p(temp, SMBHSTSTS); + } +#endif + result = 0; +END: + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + /* restore saved configuration register value */ + pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); + } + return result; +} + +/* Return -1 on error. */ +s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, + union i2c_smbus_data * data) +{ + int hwpec = 0; + int block = 0; + int ret, xact = 0; + +#ifdef HAVE_PEC + if(isich4) + hwpec = (flags & I2C_CLIENT_PEC) != 0; +#endif + + switch (size) { + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + xact = I801_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + xact = I801_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + xact = I801_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + xact = I801_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: +#ifdef HAVE_PEC + case I2C_SMBUS_BLOCK_DATA_PEC: + if(hwpec && size == I2C_SMBUS_BLOCK_DATA) + size = I2C_SMBUS_BLOCK_DATA_PEC; +#endif + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + block = 1; + break; + case I2C_SMBUS_PROC_CALL: + default: + printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size); + return -1; + } + +#ifdef HAVE_PEC + if(isich4 && hwpec) { + if(size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) + outb_p(1, SMBAUXCTL); /* enable HW PEC */ + } +#endif + if(block) + ret = i801_block_transaction(data, read_write, size); + else { + outb_p(xact | ENABLE_INT9, SMBHSTCNT); + ret = i801_transaction(); + } + +#ifdef HAVE_PEC + if(isich4 && hwpec) { + if(size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) + outb_p(0, SMBAUXCTL); + } +#endif + + if(block) + return ret; + if(ret) + return -1; + if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) + return 0; + + switch (xact & 0x7f) { + case I801_BYTE: /* Result put in SMBHSTDAT0 */ + case I801_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case I801_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + } + return 0; +} + + +u32 i801_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK +#ifdef HAVE_PEC + | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC | + I2C_FUNC_SMBUS_HWPEC_CALC + : 0) +#endif + ; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = i801_access, + .functionality = i801_func, +}; + +static struct i2c_adapter i801_adapter = { + .owner = THIS_MODULE, + .name = "unset", + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, + .algo = &smbus_algorithm, +}; + + + +static struct pci_device_id i801_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801AA_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801AB_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801BA_2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_SMBUS, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_SMBUS, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, } +}; + +static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + + if (i801_setup(dev)) { + printk + (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n"); + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + i801_adapter.dev.parent = &dev->dev; + + sprintf(i801_adapter.name, "SMBus I801 adapter at %04x", + i801_smba); + return i2c_add_adapter(&i801_adapter); +} + +static void __devexit i801_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&i801_adapter); +} + +static struct pci_driver i801_driver = { + .name = "i801 smbus", + .id_table = i801_ids, + .probe = i801_probe, + .remove = __devexit_p(i801_remove), +}; + +static int __init i2c_i801_init(void) +{ + printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&i801_driver); +} + + +static void __exit i2c_i801_exit(void) +{ + pci_unregister_driver(&i801_driver); + release_region(i801_smba, (isich4 ? 16 : 8)); +} + + + +MODULE_AUTHOR + ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>"); +MODULE_DESCRIPTION("I801 SMBus driver"); + +module_init(i2c_i801_init); +module_exit(i2c_i801_exit); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c new file mode 100644 index 000000000000..5acd8211b1d6 --- /dev/null +++ b/drivers/i2c/busses/i2c-piix4.c @@ -0,0 +1,521 @@ +/* + piix4.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and + Philip Edelbrock <phil@netroedge.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports: + Intel PIIX4, 440MX + Serverworks OSB4, CSB5 + SMSC Victory66 + + Note: we assume there can only be one device, with one SMBus interface. +*/ + +#include <linux/module.h> +#include <linux/config.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/apm_bios.h> +#include <asm/io.h> + + +struct sd { + const unsigned short mfr; + const unsigned short dev; + const unsigned char fn; + const char *name; +}; + +/* PIIX4 SMBus address offsets */ +#define SMBHSTSTS (0 + piix4_smba) +#define SMBHSLVSTS (1 + piix4_smba) +#define SMBHSTCNT (2 + piix4_smba) +#define SMBHSTCMD (3 + piix4_smba) +#define SMBHSTADD (4 + piix4_smba) +#define SMBHSTDAT0 (5 + piix4_smba) +#define SMBHSTDAT1 (6 + piix4_smba) +#define SMBBLKDAT (7 + piix4_smba) +#define SMBSLVCNT (8 + piix4_smba) +#define SMBSHDWCMD (9 + piix4_smba) +#define SMBSLVEVT (0xA + piix4_smba) +#define SMBSLVDAT (0xC + piix4_smba) + +/* PCI Address Constants */ +#define SMBBA 0x090 +#define SMBHSTCFG 0x0D2 +#define SMBSLVC 0x0D3 +#define SMBSHDW1 0x0D4 +#define SMBSHDW2 0x0D5 +#define SMBREV 0x0D6 + +/* Other settings */ +#define MAX_TIMEOUT 500 +#define ENABLE_INT9 0 + +/* PIIX4 constants */ +#define PIIX4_QUICK 0x00 +#define PIIX4_BYTE 0x04 +#define PIIX4_BYTE_DATA 0x08 +#define PIIX4_WORD_DATA 0x0C +#define PIIX4_BLOCK_DATA 0x14 + +/* insmod parameters */ + +/* If force is set to anything different from 0, we forcibly enable the + PIIX4. DANGEROUS! */ +static int force = 0; +MODULE_PARM(force, "i"); +MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!"); + +/* If force_addr is set to anything different from 0, we forcibly enable + the PIIX4 at the given address. VERY DANGEROUS! */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Forcibly enable the PIIX4 at the given address. " + "EXTREMELY DANGEROUS!"); + +static void piix4_do_pause(unsigned int amount); +static int piix4_transaction(void); + + +static unsigned short piix4_smba = 0; + +/* + * Get DMI information. + */ +static int ibm_dmi_probe(void) +{ +#ifdef CONFIG_X86 + extern int is_unsafe_smbus; + return is_unsafe_smbus; +#else + return 0; +#endif +} + +static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id) +{ + int error_return = 0; + unsigned char temp; + + /* match up the function */ + if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) + return -ENODEV; + + printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name); + + if(ibm_dmi_probe()) { + printk + (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n"); + printk + (KERN_ERR " your serial eeprom! Refusing to load module!\n"); + error_return = -EPERM; + goto END; + } + +/* Determine the address of the SMBus areas */ + if (force_addr) { + piix4_smba = force_addr & 0xfff0; + force = 0; + } else { + pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); + piix4_smba &= 0xfff0; + if(piix4_smba == 0) { + printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + } + + if (check_region(piix4_smba, 8)) { + printk + (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n", + piix4_smba); + error_return = -ENODEV; + goto END; + } + + pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); +/* If force_addr is set, we program the new address here. Just to make + sure, we disable the PIIX4 first. */ + if (force_addr) { + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); + pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); + printk + (KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new " + "address %04x!\n", piix4_smba); + } else if ((temp & 1) == 0) { + if (force) { +/* This should never need to be done, but has been noted that + many Dell machines have the SMBus interface on the PIIX4 + disabled!? NOTE: This assumes I/O space and other allocations WERE + done by the Bios! Don't complain if your hardware does weird + things after enabling this. :') Check for Bios updates before + resorting to this. */ + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, + temp | 1); + printk + (KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY " + "ENABLED!\n"); + } else { + printk + (KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n"); + error_return = -ENODEV; + goto END; + } + } + + /* Everything is happy, let's grab the memory and set things up. */ + request_region(piix4_smba, 8, "piix4-smbus"); + +#ifdef DEBUG + if ((temp & 0x0E) == 8) + printk + (KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n"); + else if ((temp & 0x0E) == 0) + printk + (KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n"); + else + printk + (KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out " + "of date)!\n"); + + pci_read_config_byte(PIIX4_dev, SMBREV, &temp); + printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp); + printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba); +#endif /* DEBUG */ + + END: + return error_return; +} + + +/* Internally used pause function */ +static void piix4_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +/* Another internally used function */ +static int piix4_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " + "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + + /* Make sure the SMBus host is ready to start transmitting */ + if ((temp = inb_p(SMBHSTSTS)) != 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n", + temp); +#endif + outb_p(temp, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) != 0x00) { +#ifdef DEBUG + printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp); +#endif + return -1; + } else { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n"); +#endif + } + } + + /* start the transaction by setting bit 6 */ + outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); + + /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ + do { + piix4_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + +#ifdef DEBUG + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n"); + result = -1; + } +#endif + + if (temp & 0x10) { + result = -1; +#ifdef DEBUG + printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n"); +#endif + } + + if (temp & 0x08) { + result = -1; + printk + (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n" + "reset. (sorry!)\n"); + /* Clock stops and slave is stuck in mid-transmission */ + } + + if (temp & 0x04) { + result = -1; +#ifdef DEBUG + printk(KERN_ERR "i2c-piix4.o: Error: no response!\n"); +#endif + } + + if (inb_p(SMBHSTSTS) != 0x00) + outb_p(inb(SMBHSTSTS), SMBHSTSTS); + +#ifdef DEBUG + if ((temp = inb_p(SMBHSTSTS)) != 0x00) { + printk + (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n", + temp); + } + printk + (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + return result; +} + +/* Return -1 on error. */ +static s32 piix4_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data * data) +{ + int i, len; + + switch (size) { + case I2C_SMBUS_PROC_CALL: + printk + (KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n"); + return -1; + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = PIIX4_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + size = PIIX4_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + size = PIIX4_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + size = PIIX4_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 0) + len = 0; + if (len > 32) + len = 32; + outb_p(len, SMBHSTDAT0); + i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= len; i++) + outb_p(data->block[i], SMBBLKDAT); + } + size = PIIX4_BLOCK_DATA; + break; + } + + outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); + + if (piix4_transaction()) /* Error in transaction */ + return -1; + + if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) + return 0; + + + switch (size) { + case PIIX4_BYTE: /* Where is the result put? I assume here it is in + SMBHSTDAT0 but it might just as well be in the + SMBHSTCMD. No clue in the docs */ + + data->byte = inb_p(SMBHSTDAT0); + break; + case PIIX4_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case PIIX4_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + case PIIX4_BLOCK_DATA: + data->block[0] = inb_p(SMBHSTDAT0); + i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= data->block[0]; i++) + data->block[i] = inb_p(SMBBLKDAT); + break; + } + return 0; +} + + +static u32 piix4_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = piix4_access, + .functionality = piix4_func, +}; + +static struct i2c_adapter piix4_adapter = { + .owner = THIS_MODULE, + .name = "unset", + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, + .algo = &smbus_algorithm, +}; + + + +static struct pci_device_id piix4_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371AB_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 3 + }, + { + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_OSB4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 0, + }, + { + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_CSB5, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 0, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82443MX_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 3, + }, + { + .vendor = PCI_VENDOR_ID_EFAR, + .device = PCI_DEVICE_ID_EFAR_SLC90E66_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 0, + }, + { 0, } +}; + +static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int retval; + + retval = piix4_setup(dev, id); + if (retval) + return retval; + + /* set up the driverfs linkage to our parent device */ + piix4_adapter.dev.parent = &dev->dev; + + sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x", + piix4_smba); + + retval = i2c_add_adapter(&piix4_adapter); + + return retval; +} + +static void __devexit piix4_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&piix4_adapter); +} + + +static struct pci_driver piix4_driver = { + .name = "piix4 smbus", + .id_table = piix4_ids, + .probe = piix4_probe, + .remove = __devexit_p(piix4_remove), +}; + +static int __init i2c_piix4_init(void) +{ + printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&piix4_driver); +} + + +static void __exit i2c_piix4_exit(void) +{ + pci_unregister_driver(&piix4_driver); + release_region(piix4_smba, 8); +} + + + +MODULE_AUTHOR + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>"); +MODULE_DESCRIPTION("PIIX4 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_piix4_init); +module_exit(i2c_piix4_exit); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 238c5a31e4f3..28cc3ec02277 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -30,6 +30,7 @@ #include <linux/proc_fs.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/seq_file.h> #include <asm/uaccess.h> @@ -87,6 +88,16 @@ int i2c_add_adapter(struct i2c_adapter *adap) init_MUTEX(&adap->bus); init_MUTEX(&adap->list); + /* Add the adapter to the driver core. + * If the parent pointer is not set up, + * we add this adapter to the legacy bus. + */ + if (adap->dev.parent == NULL) + adap->dev.parent = &legacy_bus; + sprintf(adap->dev.bus_id, "i2c-%d", i); + strcpy(adap->dev.name, "i2c controller"); + device_register(&adap->dev); + /* inform drivers of new adapters */ for (j=0;j<I2C_DRIVER_MAX;j++) if (drivers[j]!=NULL && @@ -154,6 +165,9 @@ int i2c_del_adapter(struct i2c_adapter *adap) i2cproc_remove(i); + /* clean up the sysfs representation */ + device_unregister(&adap->dev); + adapters[i] = NULL; DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name)); @@ -313,42 +327,45 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int res = -EBUSY, i; + int i; down(&adapter->list); - if (__i2c_check_addr(client->adapter,client->addr)) + if (__i2c_check_addr(client->adapter, client->addr)) goto out_unlock_list; - for (i = 0; i < I2C_CLIENT_MAX; i++) - if (NULL == adapter->clients[i]) - break; - if (I2C_CLIENT_MAX == i) { - printk(KERN_WARNING - " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->name); - res = -ENOMEM; - goto out_unlock_list; + for (i = 0; i < I2C_CLIENT_MAX; i++) { + if (!adapter->clients[i]) + goto free_slot; } + printk(KERN_WARNING + " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", + client->name); + + out_unlock_list: + up(&adapter->list); + return -EBUSY; + + free_slot: adapter->clients[i] = client; up(&adapter->list); - if (adapter->client_register) - if (adapter->client_register(client)) - printk(KERN_DEBUG "i2c-core.o: warning: client_register seems " + if (adapter->client_register) { + if (adapter->client_register(client)) { + printk(KERN_DEBUG + "i2c-core.o: warning: client_register seems " "to have failed for client %02x at adapter %s\n", - client->addr,adapter->name); - DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n", - client->name, adapter->name,i)); + client->addr, adapter->name); + } + } + + DEB(printk(KERN_DEBUG + "i2c-core.o: client [%s] registered to adapter [%s] " + "(pos. %d).\n", client->name, adapter->name, i)); - if(client->flags & I2C_CLIENT_ALLOW_USE) + if (client->flags & I2C_CLIENT_ALLOW_USE) client->usage_count = 0; - return 0; - - out_unlock_list: - up(&adapter->list); - return res; } @@ -363,28 +380,30 @@ int i2c_detach_client(struct i2c_client *client) if (adapter->client_unregister) { res = adapter->client_unregister(client); if (res) { - printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, " - "client not detached",client->name); - return res; + printk(KERN_ERR + "i2c-core.o: client_unregister [%s] failed, " + "client not detached", client->name); + goto out; } } down(&adapter->list); for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (client == adapter->clients[i]) - break; + if (client == adapter->clients[i]) { + adapter->clients[i] = NULL; + goto out_unlock; + } } - if (I2C_CLIENT_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_client " - "[%s] not found\n", - client->name); - return -ENODEV; - } else - adapter->clients[i] = NULL; - up(&adapter->list); + printk(KERN_WARNING + " i2c-core.o: unregister_client [%s] not found\n", + client->name); + res = -ENODEV; - return 0; + out_unlock: + up(&adapter->list); + out: + return res; } static int i2c_inc_use_client(struct i2c_client *client) @@ -443,45 +462,7 @@ int i2c_release_client(struct i2c_client *client) return 0; } -/* ---------------------------------------------------- - * The /proc functions - * ---------------------------------------------------- - */ - #ifdef CONFIG_PROC_FS -/* This function generates the output for /proc/bus/i2c */ -static int read_bus_i2c(char *buf, char **start, off_t offset, - int len, int *eof, void *private) -{ - int i; - int nr = 0; - - /* Note that it is safe to write a `little' beyond len. Yes, really. */ - /* Fuck you. Will convert this to seq_file later. --hch */ - - down(&core_lists); - for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++) { - if (adapters[i]) { - nr += sprintf(buf+nr, "i2c-%d\t", i); - if (adapters[i]->algo->smbus_xfer) { - if (adapters[i]->algo->master_xfer) - nr += sprintf(buf+nr,"smbus/i2c"); - else - nr += sprintf(buf+nr,"smbus "); - } else if (adapters[i]->algo->master_xfer) - nr += sprintf(buf+nr,"i2c "); - else - nr += sprintf(buf+nr,"dummy "); - nr += sprintf(buf+nr,"\t%-32s\t%-32s\n", - adapters[i]->name, - adapters[i]->algo->name); - } - } - up(&core_lists); - - return nr; -} - /* This function generates the output for /proc/bus/i2c-? */ static ssize_t i2cproc_bus_read(struct file *file, char *buf, size_t count, loff_t *ppos) @@ -551,6 +532,50 @@ static struct file_operations i2cproc_operations = { .read = i2cproc_bus_read, }; +/* This function generates the output for /proc/bus/i2c */ +static int bus_i2c_show(struct seq_file *s, void *p) +{ + int i; + + down(&core_lists); + for (i = 0; i < I2C_ADAP_MAX; i++) { + struct i2c_adapter *adapter = adapters[i]; + + if (!adapter) + continue; + + seq_printf(s, "i2c-%d\t", i); + + if (adapter->algo->smbus_xfer) { + if (adapter->algo->master_xfer) + seq_printf(s, "smbus/i2c"); + else + seq_printf(s, "smbus "); + } else if (adapter->algo->master_xfer) + seq_printf(s ,"i2c "); + else + seq_printf(s, "dummy "); + + seq_printf(s, "\t%-32s\t%-32s\n", + adapter->name, adapter->algo->name); + } + up(&core_lists); + + return 0; +} + +static int bus_i2c_open(struct inode *inode, struct file *file) +{ + return single_open(file, bus_i2c_show, NULL); +} + +static struct file_operations bus_i2c_fops = { + .open = bus_i2c_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + }; + static int i2cproc_register(struct i2c_adapter *adap, int bus) { struct proc_dir_entry *proc_entry; @@ -563,7 +588,7 @@ static int i2cproc_register(struct i2c_adapter *adap, int bus) goto fail; proc_entry->proc_fops = &i2cproc_operations; - proc_entry->owner = THIS_MODULE; + proc_entry->owner = adap->owner; adap->inode = proc_entry->low_ino; return 0; fail: @@ -583,25 +608,53 @@ static int __init i2cproc_init(void) { struct proc_dir_entry *proc_bus_i2c; - proc_bus_i2c = create_proc_entry("i2c",0,proc_bus); - if (!proc_bus_i2c) { - printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c"); - return -ENOENT; - } + proc_bus_i2c = create_proc_entry("i2c", 0, proc_bus); + if (!proc_bus_i2c) + goto fail; + proc_bus_i2c->proc_fops = &bus_i2c_fops; + proc_bus_i2c->owner = THIS_MODULE; + return 0; - proc_bus_i2c->read_proc = &read_bus_i2c; - proc_bus_i2c->owner = THIS_MODULE; - return 0; + fail: + printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c"); + return -ENOENT; } static void __exit i2cproc_cleanup(void) { remove_proc_entry("i2c",proc_bus); } +#else +static int __init i2cproc_init(void) { return 0; } +static void __exit i2cproc_cleanup(void) { } +#endif /* CONFIG_PROC_FS */ + +/* match always succeeds, as we want the probe() to tell if we really accept this match */ +static int i2c_device_match(struct device *dev, struct device_driver *drv) +{ + return 1; +} + +struct bus_type i2c_bus_type = { + .name = "i2c", + .match = i2c_device_match, +}; + + +static int __init i2c_init(void) +{ + bus_register(&i2c_bus_type); + return i2cproc_init(); +} + +static void __exit i2c_exit(void) +{ + i2cproc_cleanup(); + bus_unregister(&i2c_bus_type); +} -module_init(i2cproc_init); -module_exit(i2cproc_cleanup); -#endif /* def CONFIG_PROC_FS */ +module_init(i2c_init); +module_exit(i2c_exit); /* ---------------------------------------------------- * the functional interface to the i2c busses. diff --git a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c index 2b2e752e0769..73bb33815907 100644 --- a/drivers/i2c/i2c-proc.c +++ b/drivers/i2c/i2c-proc.c @@ -35,8 +35,6 @@ #include <linux/i2c-proc.h> #include <asm/uaccess.h> -static int i2c_create_name(char **name, const char *prefix, - struct i2c_adapter *adapter, int addr); static int i2c_parse_reals(int *nrels, void *buffer, int bufsize, long *results, int magnitude); static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize, @@ -54,15 +52,6 @@ static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX]; static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX]; -static ctl_table sysctl_table[] = { - {CTL_DEV, "dev", NULL, 0, 0555}, - {0}, - {DEV_SENSORS, "sensors", NULL, 0, 0555}, - {0}, - {0, NULL, NULL, 0, 0555}, - {0} -}; - static ctl_table i2c_proc_dev_sensors[] = { {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips, &i2c_sysctl_chips}, @@ -87,36 +76,40 @@ static struct ctl_table_header *i2c_proc_header; (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for a LM75 chip on the third i2c bus at address 0x4e). name is allocated first. */ -static int i2c_create_name(char **name, const char *prefix, - struct i2c_adapter *adapter, int addr) +static char *generate_name(struct i2c_client *client, const char *prefix) { - char name_buffer[50]; - int id, i, end; - if (i2c_is_isa_adapter(adapter)) + struct i2c_adapter *adapter = client->adapter; + int addr = client->addr; + char name_buffer[50], *name; + + if (i2c_is_isa_adapter(adapter)) { sprintf(name_buffer, "%s-isa-%04x", prefix, addr); - else if (!adapter->algo->smbus_xfer && !adapter->algo->master_xfer) { - /* dummy adapter, generate prefix */ + } else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) { + int id = i2c_adapter_id(adapter); + if (id < 0) + return ERR_PTR(-ENOENT); + sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr); + } else { /* dummy adapter, generate prefix */ + int end, i; + sprintf(name_buffer, "%s-", prefix); end = strlen(name_buffer); - for(i = 0; i < 32; i++) { - if(adapter->algo->name[i] == ' ') + + for (i = 0; i < 32; i++) { + if (adapter->algo->name[i] == ' ') break; name_buffer[end++] = tolower(adapter->algo->name[i]); } + name_buffer[end] = 0; sprintf(name_buffer + end, "-%04x", addr); - } else { - if ((id = i2c_adapter_id(adapter)) < 0) - return -ENOENT; - sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr); - } - *name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL); - if (!*name) { - printk (KERN_WARNING "i2c_create_name: not enough memory\n"); - return -ENOMEM; } - strcpy(*name, name_buffer); - return 0; + + name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL); + if (unlikely(!name)) + return ERR_PTR(-ENOMEM); + strcpy(name, name_buffer); + return name; } /* This rather complex function must be called when you want to add an entry @@ -127,93 +120,80 @@ static int i2c_create_name(char **name, const char *prefix, If any driver wants subdirectories within the newly created directory, this function must be updated! */ int i2c_register_entry(struct i2c_client *client, const char *prefix, - ctl_table * ctl_template) + struct ctl_table *leaf) { - int i, res, len, id; - ctl_table *new_table, *client_tbl, *tbl; - char *name; - struct ctl_table_header *new_header; + struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl; + struct ctl_table_header *hdr; + struct ctl_table *tmp; + const char *name; + int id; + + name = generate_name(client, prefix); + if (IS_ERR(name)) + return PTR_ERR(name); + + for (id = 0; id < SENSORS_ENTRY_MAX; id++) { + if (!i2c_entries[id]) + goto free_slot; + } - if ((res = i2c_create_name(&name, prefix, client->adapter, - client->addr))) return res; + goto out_free_name; - for (id = 0; id < SENSORS_ENTRY_MAX; id++) - if (!i2c_entries[id]) { - break; - } - if (id == SENSORS_ENTRY_MAX) { - kfree(name); - return -ENOMEM; - } + free_slot: + tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); + if (unlikely(!tbl)) + goto out_free_name; + memset(tbl, 0, sizeof(*tbl)); - id += 256; - - len = 0; - while (ctl_template[len].procname) - len++; - if (!(new_table = kmalloc(sizeof(sysctl_table) + sizeof(ctl_table) * (len + 1), - GFP_KERNEL))) { - kfree(name); - return -ENOMEM; - } + for (tmp = leaf; tmp->ctl_name; tmp++) + tmp->extra2 = client; - memcpy(new_table, sysctl_table, sizeof(sysctl_table)); - tbl = new_table; /* sys/ */ - tbl = tbl->child = tbl + 2; /* dev/ */ - tbl = tbl->child = tbl + 2; /* sensors/ */ - client_tbl = tbl->child = tbl + 2; /* XX-chip-YY-ZZ/ */ + tbl->sensors->ctl_name = id+256; + tbl->sensors->procname = name; + tbl->sensors->mode = 0555; + tbl->sensors->child = leaf; - client_tbl->procname = name; - client_tbl->ctl_name = id; - client_tbl->child = client_tbl + 2; + tbl->dev->ctl_name = DEV_SENSORS; + tbl->dev->procname = "sensors"; + tbl->dev->mode = 0555; + tbl->dev->child = tbl->sensors; - /* Next the client sysctls. --km */ - tbl = client_tbl->child; - memcpy(tbl, ctl_template, sizeof(ctl_table) * (len+1)); - for (i = 0; i < len; i++) - tbl[i].extra2 = client; + tbl->root->ctl_name = CTL_DEV; + tbl->root->procname = "dev"; + tbl->root->mode = 0555; + tbl->root->child = tbl->dev; - if (!(new_header = register_sysctl_table(new_table, 0))) { - printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n"); - kfree(new_table); - kfree(name); - return -EPERM; - } + hdr = register_sysctl_table(tbl->root, 0); + if (unlikely(!hdr)) + goto out_free_tbl; - i2c_entries[id - 256] = new_header; + i2c_entries[id] = hdr; + i2c_clients[id] = client; - i2c_clients[id - 256] = client; + return (id + 256); /* XXX(hch) why?? */ -#ifdef DEBUG - if (!new_header || !new_header->ctl_table || - !new_header->ctl_table->child || - !new_header->ctl_table->child->child || - !new_header->ctl_table->child->child->de ) { - printk - (KERN_ERR "i2c-proc.o: NULL pointer when trying to install fill_inode fix!\n"); - return id; - } -#endif /* DEBUG */ - client_tbl->de->owner = client->driver->owner; - return id; + out_free_tbl: + kfree(tbl); + out_free_name: + kfree(name); + return -ENOMEM; } void i2c_deregister_entry(int id) { - ctl_table *table; - char *temp; + id -= 256; - id -= 256; if (i2c_entries[id]) { - table = i2c_entries[id]->ctl_table; - unregister_sysctl_table(i2c_entries[id]); - /* 2-step kfree needed to keep gcc happy about const points */ - (const char *) temp = table[4].procname; - kfree(temp); - kfree(table); - i2c_entries[id] = NULL; - i2c_clients[id] = NULL; + struct ctl_table_header *hdr = i2c_entries[id]; + struct ctl_table *tbl = hdr->ctl_table; + + unregister_sysctl_table(hdr); + kfree(tbl->child->child->procname); + kfree(tbl); /* actually the whole anonymous struct */ } + + i2c_entries[id] = NULL; + i2c_clients[id] = NULL; } static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp, diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 1c94ad6ff2a5..00e9abe0f015 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -203,36 +203,34 @@ static int linear_make_request (request_queue_t *q, struct bio *bio) return 0; } bio->bi_bdev = tmp_dev->rdev->bdev; - bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1); + bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset; return 1; } -static int linear_status (char *page, mddev_t *mddev) +static void linear_status (struct seq_file *seq, mddev_t *mddev) { - int sz = 0; #undef MD_DEBUG #ifdef MD_DEBUG int j; linear_conf_t *conf = mddev_to_conf(mddev); - sz += sprintf(page+sz, " "); + seq_printf(seq, " "); for (j = 0; j < conf->nr_zones; j++) { - sz += sprintf(page+sz, "[%s", + seq_printf(seq, "[%s", bdev_partition_name(conf->hash_table[j].dev0->rdev->bdev)); if (conf->hash_table[j].dev1) - sz += sprintf(page+sz, "/%s] ", + seq_printf(seq, "/%s] ", bdev_partition_name(conf->hash_table[j].dev1->rdev->bdev)); else - sz += sprintf(page+sz, "] "); + seq_printf(seq, "] "); } - sz += sprintf(page+sz, "\n"); + seq_printf(seq, "\n"); #endif - sz += sprintf(page+sz, " %dk rounding", mddev->chunk_size/1024); - return sz; + seq_printf(seq, " %dk rounding", mddev->chunk_size/1024); } diff --git a/drivers/md/md.c b/drivers/md/md.c index cd65d8960c39..cefd2423f1c7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -124,9 +124,6 @@ static ctl_table raid_root_table[] = { { .ctl_name = 0 } }; -static void md_recover_arrays(void); -static mdk_thread_t *md_recovery_thread; - sector_t md_size[MAX_MD_DEVS]; static struct block_device_operations md_fops; @@ -222,6 +219,7 @@ static mddev_t * mddev_find(int unit) init_MUTEX(&new->reconfig_sem); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); + init_timer(&new->safemode_timer); atomic_set(&new->active, 1); blk_queue_make_request(&new->queue, md_fail_request); @@ -272,40 +270,35 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev) return NULL; } -static sector_t calc_dev_sboffset(struct block_device *bdev) +inline static sector_t calc_dev_sboffset(struct block_device *bdev) { sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; return MD_NEW_SIZE_BLOCKS(size); } -static sector_t calc_dev_size(struct block_device *bdev, mddev_t *mddev) +static sector_t calc_dev_size(mdk_rdev_t *rdev, unsigned chunk_size) { sector_t size; - if (mddev->persistent) - size = calc_dev_sboffset(bdev); - else - size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; - if (mddev->chunk_size) - size &= ~((sector_t)mddev->chunk_size/1024 - 1); + size = rdev->sb_offset; + + if (chunk_size) + size &= ~((sector_t)chunk_size/1024 - 1); return size; } static sector_t zoned_raid_size(mddev_t *mddev) { - sector_t mask; mdk_rdev_t * rdev; struct list_head *tmp; /* * do size and offset calculations. */ - mask = ~((sector_t)mddev->chunk_size/1024 - 1); - ITERATE_RDEV(mddev,rdev,tmp) { - rdev->size &= mask; + ITERATE_RDEV(mddev,rdev,tmp) md_size[mdidx(mddev)] += rdev->size; - } + return 0; } @@ -389,7 +382,6 @@ static int sync_page_io(struct block_device *bdev, sector_t sector, int size, static int read_disk_sb(mdk_rdev_t * rdev) { - sector_t sb_offset; if (!rdev->sb_page) { MD_BUG(); @@ -398,16 +390,8 @@ static int read_disk_sb(mdk_rdev_t * rdev) if (rdev->sb_loaded) return 0; - /* - * Calculate the position of the superblock, - * it's at the end of the disk. - * - * It also happens to be a multiple of 4Kb. - */ - sb_offset = calc_dev_sboffset(rdev->bdev); - rdev->sb_offset = sb_offset; - if (!sync_page_io(rdev->bdev, sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ)) + if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ)) goto fail; rdev->sb_loaded = 1; return 0; @@ -486,7 +470,7 @@ static unsigned int calc_sb_csum(mdp_super_t * sb) * We rely on user-space to write the initial superblock, and support * reading and updating of superblocks. * Interface methods are: - * int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev) + * int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version) * loads and validates a superblock on dev. * if refdev != NULL, compare superblocks on both devices * Return: @@ -511,7 +495,7 @@ static unsigned int calc_sb_csum(mdp_super_t * sb) struct super_type { char *name; struct module *owner; - int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev); + int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version); int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev); void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev); }; @@ -519,10 +503,20 @@ struct super_type { /* * load_super for 0.90.0 */ -static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev) +static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) { mdp_super_t *sb; int ret; + sector_t sb_offset; + + /* + * Calculate the position of the superblock, + * it's at the end of the disk. + * + * It also happens to be a multiple of 4Kb. + */ + sb_offset = calc_dev_sboffset(rdev->bdev); + rdev->sb_offset = sb_offset; ret = read_disk_sb(rdev); if (ret) return ret; @@ -557,6 +551,12 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev) } rdev->preferred_minor = sb->md_minor; + rdev->data_offset = 0; + + if (sb->level == MULTIPATH) + rdev->desc_nr = -1; + else + rdev->desc_nr = sb->this_disk.number; if (refdev == 0) ret = 1; @@ -582,7 +582,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev) else ret = 0; } - + rdev->size = calc_dev_size(rdev, sb->chunk_size); abort: return ret; @@ -597,7 +597,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page); if (mddev->raid_disks == 0) { - mddev->major_version = sb->major_version; + mddev->major_version = 0; mddev->minor_version = sb->minor_version; mddev->patch_version = sb->patch_version; mddev->persistent = ! sb->not_persistent; @@ -634,7 +634,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) return -EINVAL; } if (mddev->level != LEVEL_MULTIPATH) { - rdev->desc_nr = sb->this_disk.number; rdev->raid_disk = -1; rdev->in_sync = rdev->faulty = 0; desc = sb->disks + rdev->desc_nr; @@ -704,10 +703,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->recovery_cp = mddev->recovery_cp; sb->cp_events_hi = (mddev->events>>32); sb->cp_events_lo = (u32)mddev->events; - if (mddev->recovery_cp == MaxSector) { - printk(KERN_INFO "md: marking sb clean...\n"); + if (mddev->recovery_cp == MaxSector) sb->state = (1<< MD_SB_CLEAN); - } } else sb->recovery_cp = 0; @@ -717,7 +714,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->disks[0].state = (1<<MD_DISK_REMOVED); ITERATE_RDEV(mddev,rdev2,tmp) { mdp_disk_t *d; - if (rdev2->raid_disk >= 0) + if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) rdev2->desc_nr = rdev2->raid_disk; else rdev2->desc_nr = next_spare++; @@ -726,7 +723,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); - if (rdev2->raid_disk >= 0) + if (rdev2->raid_disk >= 0 && rdev->in_sync && !rdev2->faulty) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ @@ -766,6 +763,210 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->sb_csum = calc_sb_csum(sb); } +/* + * version 1 superblock + */ + +static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) +{ + unsigned int disk_csum, csum; + int size = 256 + sb->max_dev*2; + + disk_csum = sb->sb_csum; + sb->sb_csum = 0; + csum = csum_partial((void *)sb, size, 0); + sb->sb_csum = disk_csum; + return csum; +} + +static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) +{ + struct mdp_superblock_1 *sb; + int ret; + sector_t sb_offset; + + /* + * Calculate the position of the superblock. + * It is always aligned to a 4K boundary and + * depeding on minor_version, it can be: + * 0: At least 8K, but less than 12K, from end of device + * 1: At start of device + * 2: 4K from start of device. + */ + switch(minor_version) { + case 0: + sb_offset = rdev->bdev->bd_inode->i_size >> 9; + sb_offset -= 8*2; + sb_offset &= ~(4*2); + /* convert from sectors to K */ + sb_offset /= 2; + break; + case 1: + sb_offset = 0; + break; + case 2: + sb_offset = 4; + break; + default: + return -EINVAL; + } + rdev->sb_offset = sb_offset; + + ret = read_disk_sb(rdev); + if (ret) return ret; + + + sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + + if (sb->magic != cpu_to_le32(MD_SB_MAGIC) || + sb->major_version != cpu_to_le32(1) || + le32_to_cpu(sb->max_dev) > (4096-256)/2 || + le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) || + sb->feature_map != 0) + return -EINVAL; + + if (calc_sb_1_csum(sb) != sb->sb_csum) { + printk(BAD_CSUM, bdev_partition_name(rdev->bdev)); + return -EINVAL; + } + rdev->preferred_minor = 0xffff; + rdev->data_offset = le64_to_cpu(sb->data_offset); + + if (refdev == 0) + return 1; + else { + __u64 ev1, ev2; + struct mdp_superblock_1 *refsb = + (struct mdp_superblock_1*)page_address(refdev->sb_page); + + if (memcmp(sb->set_uuid, refsb->set_uuid, 16) != 0 || + sb->level != refsb->level || + sb->layout != refsb->layout || + sb->chunksize != refsb->chunksize) { + printk(KERN_WARNING "md: %s has strangely different superblock to %s\n", + bdev_partition_name(rdev->bdev), + bdev_partition_name(refdev->bdev)); + return -EINVAL; + } + ev1 = le64_to_cpu(sb->events); + ev2 = le64_to_cpu(refsb->events); + + if (ev1 > ev2) + return 1; + } + if (minor_version) + rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; + else + rdev->size = rdev->sb_offset; + if (rdev->size < le64_to_cpu(sb->data_size)/2) + return -EINVAL; + rdev->size = le64_to_cpu(sb->data_size)/2; + if (le32_to_cpu(sb->chunksize)) + rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1); + return 0; +} + +static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) +{ + struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + + if (mddev->raid_disks == 0) { + mddev->major_version = 1; + mddev->minor_version = 0; + mddev->patch_version = 0; + mddev->persistent = 1; + mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; + mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); + mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); + mddev->level = le32_to_cpu(sb->level); + mddev->layout = le32_to_cpu(sb->layout); + mddev->raid_disks = le32_to_cpu(sb->raid_disks); + mddev->size = (u32)le64_to_cpu(sb->size); + mddev->events = le64_to_cpu(sb->events); + + mddev->recovery_cp = le64_to_cpu(sb->resync_offset); + memcpy(mddev->uuid, sb->set_uuid, 16); + + mddev->max_disks = (4096-256)/2; + } else { + __u64 ev1; + ev1 = le64_to_cpu(sb->events); + ++ev1; + if (ev1 < mddev->events) + return -EINVAL; + } + + if (mddev->level != LEVEL_MULTIPATH) { + int role; + rdev->desc_nr = le32_to_cpu(sb->dev_number); + role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); + switch(role) { + case 0xffff: /* spare */ + rdev->in_sync = 0; + rdev->faulty = 0; + rdev->raid_disk = -1; + break; + case 0xfffe: /* faulty */ + rdev->in_sync = 0; + rdev->faulty = 1; + rdev->raid_disk = -1; + break; + default: + rdev->in_sync = 1; + rdev->faulty = 0; + rdev->raid_disk = role; + break; + } + } + return 0; +} + +static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) +{ + struct mdp_superblock_1 *sb; + struct list_head *tmp; + mdk_rdev_t *rdev2; + int max_dev, i; + /* make rdev->sb match mddev and rdev data. */ + + sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + + sb->feature_map = 0; + sb->pad0 = 0; + memset(sb->pad1, 0, sizeof(sb->pad1)); + memset(sb->pad2, 0, sizeof(sb->pad2)); + memset(sb->pad3, 0, sizeof(sb->pad3)); + + sb->utime = cpu_to_le64((__u64)mddev->utime); + sb->events = cpu_to_le64(mddev->events); + if (mddev->in_sync) + sb->resync_offset = cpu_to_le64(mddev->recovery_cp); + else + sb->resync_offset = cpu_to_le64(0); + + max_dev = 0; + ITERATE_RDEV(mddev,rdev2,tmp) + if (rdev2->desc_nr > max_dev) + max_dev = rdev2->desc_nr; + + sb->max_dev = max_dev; + for (i=0; i<max_dev;i++) + sb->dev_roles[max_dev] = cpu_to_le16(0xfffe); + + ITERATE_RDEV(mddev,rdev2,tmp) { + i = rdev2->desc_nr; + if (rdev2->faulty) + sb->dev_roles[i] = cpu_to_le16(0xfffe); + else if (rdev2->in_sync) + sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); + else + sb->dev_roles[i] = cpu_to_le16(0xffff); + } + + sb->recovery_offset = cpu_to_le64(0); /* not supported yet */ +} + + struct super_type super_types[] = { [0] = { .name = "0.90.0", @@ -774,9 +975,14 @@ struct super_type super_types[] = { .validate_super = super_90_validate, .sync_super = super_90_sync, }, + [1] = { + .name = "md-1", + .owner = THIS_MODULE, + .load_super = super_1_load, + .validate_super = super_1_validate, + .sync_super = super_1_sync, + }, }; - - static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev) { @@ -804,13 +1010,13 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) static LIST_HEAD(pending_raid_disks); -static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) +static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) { mdk_rdev_t *same_pdev; if (rdev->mddev) { MD_BUG(); - return; + return -EINVAL; } same_pdev = match_dev_unit(mddev, rdev); if (same_pdev) @@ -820,9 +1026,25 @@ static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) mdidx(mddev), bdev_partition_name(rdev->bdev), bdev_partition_name(same_pdev->bdev)); + /* Verify rdev->desc_nr is unique. + * If it is -1, assign a free number, else + * check number is not in use + */ + if (rdev->desc_nr < 0) { + int choice = 0; + if (mddev->pers) choice = mddev->raid_disks; + while (find_rdev_nr(mddev, choice)) + choice++; + rdev->desc_nr = choice; + } else { + if (find_rdev_nr(mddev, rdev->desc_nr)) + return -EBUSY; + } + list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; printk(KERN_INFO "md: bind<%s>\n", bdev_partition_name(rdev->bdev)); + return 0; } static void unbind_rdev_from_array(mdk_rdev_t * rdev) @@ -910,6 +1132,7 @@ static void export_array(mddev_t *mddev) if (!list_empty(&mddev->disks)) MD_BUG(); mddev->raid_disks = 0; + mddev->major_version = 0; } #undef BAD_CSUM @@ -994,8 +1217,6 @@ void md_print_devices(void) static int write_disk_sb(mdk_rdev_t * rdev) { - sector_t sb_offset; - sector_t size; if (!rdev->sb_loaded) { MD_BUG(); @@ -1006,35 +1227,12 @@ static int write_disk_sb(mdk_rdev_t * rdev) return 1; } - sb_offset = calc_dev_sboffset(rdev->bdev); - if (rdev->sb_offset != sb_offset) { - printk(KERN_INFO "%s's sb offset has changed from %llu to %llu, skipping\n", - bdev_partition_name(rdev->bdev), - (unsigned long long)rdev->sb_offset, - (unsigned long long)sb_offset); - goto skip; - } - /* - * If the disk went offline meanwhile and it's just a spare, then - * its size has changed to zero silently, and the MD code does - * not yet know that it's faulty. - */ - size = calc_dev_size(rdev->bdev, rdev->mddev); - if (size != rdev->size) { - printk(KERN_INFO "%s's size has changed from %llu to %llu since import, skipping\n", - bdev_partition_name(rdev->bdev), - (unsigned long long)rdev->size, - (unsigned long long)size); - goto skip; - } - - printk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev), (unsigned long long)sb_offset); + dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev), + (unsigned long long)rdev->sb_offset); + + if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE)) + return 0; - if (!sync_page_io(rdev->bdev, sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE)) - goto fail; -skip: - return 0; -fail: printk("md: write_disk_sb failed for device %s\n", bdev_partition_name(rdev->bdev)); return 1; } @@ -1045,7 +1243,8 @@ static void sync_sbs(mddev_t * mddev) struct list_head *tmp; ITERATE_RDEV(mddev,rdev,tmp) { - super_90_sync(mddev, rdev); + super_types[mddev->major_version]. + sync_super(mddev, rdev); rdev->sb_loaded = 1; } } @@ -1079,20 +1278,20 @@ repeat: if (!mddev->persistent) return; - printk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n", + dprintk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n", mdidx(mddev),mddev->in_sync); err = 0; ITERATE_RDEV(mddev,rdev,tmp) { - printk(KERN_INFO "md: "); + dprintk(KERN_INFO "md: "); if (rdev->faulty) - printk("(skipping faulty "); + dprintk("(skipping faulty "); - printk("%s ", bdev_partition_name(rdev->bdev)); + dprintk("%s ", bdev_partition_name(rdev->bdev)); if (!rdev->faulty) { err += write_disk_sb(rdev); } else - printk(")\n"); + dprintk(")\n"); if (!err && mddev->level == LEVEL_MULTIPATH) /* only need to write one superblock... */ break; @@ -1107,7 +1306,7 @@ repeat: } /* - * Import a device. If 'on_disk', then sanity check the superblock + * Import a device. If 'super_format' >= 0, then sanity check the superblock * * mark the device faulty if: * @@ -1116,7 +1315,7 @@ repeat: * * a faulty rdev _never_ has rdev->sb set. */ -static mdk_rdev_t *md_import_device(dev_t newdev, int on_disk) +static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor) { int err; mdk_rdev_t *rdev; @@ -1141,6 +1340,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int on_disk) rdev->desc_nr = -1; rdev->faulty = 0; rdev->in_sync = 0; + rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; @@ -1152,8 +1352,9 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int on_disk) goto abort_free; } - if (on_disk) { - err = super_90_load(rdev, NULL); + if (super_format >= 0) { + err = super_types[super_format]. + load_super(rdev, NULL, super_minor); if (err == -EINVAL) { printk(KERN_WARNING "md: %s has invalid sb, not importing!\n", bdev_partition_name(rdev->bdev)); @@ -1206,7 +1407,8 @@ static int analyze_sbs(mddev_t * mddev) freshest = NULL; ITERATE_RDEV(mddev,rdev,tmp) - switch (super_90_load(rdev, freshest)) { + switch (super_types[mddev->major_version]. + load_super(rdev, freshest, mddev->minor_version)) { case 1: freshest = rdev; break; @@ -1218,12 +1420,14 @@ static int analyze_sbs(mddev_t * mddev) } - super_90_validate(mddev, freshest); + super_types[mddev->major_version]. + validate_super(mddev, freshest); i = 0; ITERATE_RDEV(mddev,rdev,tmp) { if (rdev != freshest) - if (super_90_validate(mddev, rdev)) { + if (super_types[mddev->major_version]. + validate_super(mddev, rdev)) { printk(KERN_WARNING "md: kicking non-fresh %s from array!\n", bdev_partition_name(rdev->bdev)); kick_rdev_from_array(rdev); @@ -1278,11 +1482,6 @@ static int device_size_calculation(mddev_t * mddev) ITERATE_RDEV(mddev,rdev,tmp) { if (rdev->faulty) continue; - if (rdev->size) { - MD_BUG(); - continue; - } - rdev->size = calc_dev_size(rdev->bdev, mddev); if (rdev->size < mddev->chunk_size / 1024) { printk(KERN_WARNING "md: Dev %s smaller than chunk_size: %lluk < %dk\n", @@ -1380,6 +1579,16 @@ static struct gendisk *md_probe(dev_t dev, int *part, void *data) return NULL; } +void md_wakeup_thread(mdk_thread_t *thread); + +static void md_safemode_timeout(unsigned long data) +{ + mddev_t *mddev = (mddev_t *) data; + + mddev->safemode = 1; + md_wakeup_thread(mddev->thread); +} + #define TOO_BIG_CHUNKSIZE KERN_ERR \ "too big chunk_size: %d > %d\n" @@ -1521,13 +1730,14 @@ static int do_md_run(mddev_t * mddev) } atomic_set(&mddev->writes_pending,0); mddev->safemode = 0; - if (mddev->pers->sync_request) - mddev->in_sync = 0; - else - mddev->in_sync = 1; + mddev->safemode_timer.function = md_safemode_timeout; + mddev->safemode_timer.data = (unsigned long) mddev; + mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */ + mddev->in_sync = 1; md_update_sb(mddev); - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); set_capacity(disk, md_size[mdidx(mddev)]<<1); return (0); } @@ -1553,7 +1763,6 @@ static int restart_array(mddev_t *mddev) goto out; mddev->safemode = 0; - mddev->in_sync = 0; md_update_sb(mddev); mddev->ro = 0; set_disk_ro(disk, 0); @@ -1563,7 +1772,8 @@ static int restart_array(mddev_t *mddev) /* * Kick recovery or resync if necessary */ - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); err = 0; } else { printk(KERN_ERR "md: md%d has no personality assigned.\n", @@ -1593,12 +1803,13 @@ static int do_md_stop(mddev_t * mddev, int ro) if (mddev->pers) { if (mddev->sync_thread) { - if (mddev->recovery_running > 0) - mddev->recovery_running = -1; + set_bit(MD_RECOVERY_INTR, &mddev->recovery); md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; } + del_timer_sync(&mddev->safemode_timer); + invalidate_device(mk_kdev(disk->major, disk->first_minor), 1); if (ro) { @@ -1699,7 +1910,7 @@ static void autorun_devices(void) printk(KERN_INFO "md: considering %s ...\n", bdev_partition_name(rdev0->bdev)); INIT_LIST_HEAD(&candidates); ITERATE_RDEV_PENDING(rdev,tmp) - if (super_90_load(rdev, rdev0) >= 0) { + if (super_90_load(rdev, rdev0, 0) >= 0) { printk(KERN_INFO "md: adding %s ...\n", bdev_partition_name(rdev->bdev)); list_move(&rdev->same_set, &candidates); } @@ -1717,7 +1928,8 @@ static void autorun_devices(void) if (mddev_lock(mddev)) printk(KERN_WARNING "md: md%d locked, cannot run\n", mdidx(mddev)); - else if (mddev->raid_disks || !list_empty(&mddev->disks)) { + else if (mddev->raid_disks || mddev->major_version + || !list_empty(&mddev->disks)) { printk(KERN_WARNING "md: md%d already running, cannot run %s\n", mdidx(mddev), bdev_partition_name(rdev0->bdev)); mddev_unlock(mddev); @@ -1725,7 +1937,8 @@ static void autorun_devices(void) printk(KERN_INFO "md: created md%d\n", mdidx(mddev)); ITERATE_RDEV_GENERIC(candidates,rdev,tmp) { list_del_init(&rdev->same_set); - bind_rdev_to_array(rdev, mddev); + if (bind_rdev_to_array(rdev, mddev)) + export_rdev(rdev); } autorun_array(mddev); mddev_unlock(mddev); @@ -1778,7 +1991,7 @@ static int autostart_array(dev_t startdev) mdp_super_t *sb = NULL; mdk_rdev_t *start_rdev = NULL, *rdev; - start_rdev = md_import_device(startdev, 1); + start_rdev = md_import_device(startdev, 0, 0); if (IS_ERR(start_rdev)) { printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev)); return err; @@ -1812,7 +2025,7 @@ static int autostart_array(dev_t startdev) continue; if (dev == startdev) continue; - rdev = md_import_device(dev, 1); + rdev = md_import_device(dev, 0, 0); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n", partition_name(dev)); @@ -1875,9 +2088,8 @@ static int get_array_info(mddev_t * mddev, void * arg) } info.major_version = mddev->major_version; - info.major_version = mddev->major_version; info.minor_version = mddev->minor_version; - info.patch_version = mddev->patch_version; + info.patch_version = 1; info.ctime = mddev->ctime; info.level = mddev->level; info.size = mddev->size; @@ -1888,7 +2100,7 @@ static int get_array_info(mddev_t * mddev, void * arg) info.utime = mddev->utime; info.state = 0; - if (mddev->recovery_cp == MaxSector) + if (mddev->in_sync) info.state = (1<<MD_SB_CLEAN); info.active_disks = active; info.working_disks = working; @@ -1943,13 +2155,13 @@ static int get_disk_info(mddev_t * mddev, void * arg) static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) { - sector_t size; mdk_rdev_t *rdev; dev_t dev; dev = MKDEV(info->major,info->minor); if (!mddev->raid_disks) { + int err; /* expecting a device which has a superblock */ - rdev = md_import_device(dev, 1); + rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); return PTR_ERR(rdev); @@ -1957,7 +2169,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) if (!list_empty(&mddev->disks)) { mdk_rdev_t *rdev0 = list_entry(mddev->disks.next, mdk_rdev_t, same_set); - int err = super_90_load(rdev, rdev0); + int err = super_types[mddev->major_version] + .load_super(rdev, rdev0, mddev->minor_version); if (err < 0) { printk(KERN_WARNING "md: %s has different UUID to %s\n", bdev_partition_name(rdev->bdev), bdev_partition_name(rdev0->bdev)); @@ -1965,12 +2178,52 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) return -EINVAL; } } - bind_rdev_to_array(rdev, mddev); - return 0; + err = bind_rdev_to_array(rdev, mddev); + if (err) + export_rdev(rdev); + return err; + } + + /* + * add_new_disk can be used once the array is assembled + * to add "hot spares". They must already have a superblock + * written + */ + if (mddev->pers) { + int err; + if (!mddev->pers->hot_add_disk) { + printk(KERN_WARNING "md%d: personality does not support diskops!\n", + mdidx(mddev)); + return -EINVAL; + } + rdev = md_import_device(dev, mddev->major_version, + mddev->minor_version); + if (IS_ERR(rdev)) { + printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); + return PTR_ERR(rdev); + } + rdev->in_sync = 0; /* just to be sure */ + rdev->raid_disk = -1; + err = bind_rdev_to_array(rdev, mddev); + if (err) + export_rdev(rdev); + if (mddev->thread) + md_wakeup_thread(mddev->thread); + return err; + } + + /* otherwise, add_new_disk is only allowed + * for major_version==0 superblocks + */ + if (mddev->major_version != 0) { + printk(KERN_WARNING "md%d: ADD_NEW_DISK not supported\n", + mdidx(mddev)); + return -EINVAL; } if (!(info->state & (1<<MD_DISK_FAULTY))) { - rdev = md_import_device (dev, 0); + int err; + rdev = md_import_device (dev, -1, 0); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); return PTR_ERR(rdev); @@ -1987,16 +2240,21 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) else rdev->in_sync = 0; - bind_rdev_to_array(rdev, mddev); + err = bind_rdev_to_array(rdev, mddev); + if (err) { + export_rdev(rdev); + return err; + } - if (!mddev->persistent) + if (!mddev->persistent) { printk(KERN_INFO "md: nonpersistent superblock ...\n"); + rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; + } else + rdev->sb_offset = calc_dev_sboffset(rdev->bdev); + rdev->size = calc_dev_size(rdev, mddev->chunk_size); - size = calc_dev_size(rdev->bdev, mddev); - rdev->sb_offset = calc_dev_sboffset(rdev->bdev); - - if (!mddev->size || (mddev->size > size)) - mddev->size = size; + if (!mddev->size || (mddev->size > rdev->size)) + mddev->size = rdev->size; } return 0; @@ -2066,7 +2324,7 @@ busy: static int hot_add_disk(mddev_t * mddev, dev_t dev) { - int i, err; + int err; unsigned int size; mdk_rdev_t *rdev; @@ -2076,19 +2334,26 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", partition_name(dev), mdidx(mddev)); + if (mddev->major_version != 0) { + printk(KERN_WARNING "md%d: HOT_ADD may only be used with version-0 superblocks.\n", + mdidx(mddev)); + return -EINVAL; + } if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING "md%d: personality does not support diskops!\n", mdidx(mddev)); return -EINVAL; } - rdev = md_import_device (dev, 0); + rdev = md_import_device (dev, -1, 0); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); return -EINVAL; } - size = calc_dev_size(rdev->bdev, mddev); + rdev->sb_offset = calc_dev_sboffset(rdev->bdev); + size = calc_dev_size(rdev, mddev->chunk_size); + rdev->size = size; if (size < mddev->size) { printk(KERN_WARNING "md%d: disk size %llu blocks < array size %llu\n", @@ -2105,27 +2370,21 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) goto abort_export; } rdev->in_sync = 0; + rdev->desc_nr = -1; bind_rdev_to_array(rdev, mddev); /* * The rest should better be atomic, we can have disk failures * noticed in interrupt contexts ... */ - rdev->size = size; - rdev->sb_offset = calc_dev_sboffset(rdev->bdev); - for (i = mddev->raid_disks; i < mddev->max_disks; i++) - if (find_rdev_nr(mddev,i)==NULL) - break; - - if (i == mddev->max_disks) { + if (rdev->desc_nr == mddev->max_disks) { printk(KERN_WARNING "md%d: can not hot-add to full array!\n", mdidx(mddev)); err = -EBUSY; goto abort_unbind_export; } - rdev->desc_nr = i; rdev->raid_disk = -1; md_update_sb(mddev); @@ -2134,7 +2393,8 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) * Kick recovery, maybe this spare has to be added to the * array immediately. */ - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); return 0; @@ -2146,9 +2406,37 @@ abort_export: return err; } +/* + * set_array_info is used two different ways + * The original usage is when creating a new array. + * In this usage, raid_disks is > = and it together with + * level, size, not_persistent,layout,chunksize determine the + * shape of the array. + * This will always create an array with a type-0.90.0 superblock. + * The newer usage is when assembling an array. + * In this case raid_disks will be 0, and the major_version field is + * use to determine which style super-blocks are to be found on the devices. + * The minor and patch _version numbers are also kept incase the + * super_block handler wishes to interpret them. + */ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) { + if (info->raid_disks == 0) { + /* just setting version number for superblock loading */ + if (info->major_version < 0 || + info->major_version >= sizeof(super_types)/sizeof(super_types[0]) || + super_types[info->major_version].name == NULL) { + /* maybe try to auto-load a module? */ + printk(KERN_INFO "md: superblock version %d not known\n", + info->major_version); + return -EINVAL; + } + mddev->major_version = info->major_version; + mddev->minor_version = info->minor_version; + mddev->patch_version = info->patch_version; + return 0; + } mddev->major_version = MD_MAJOR_VERSION; mddev->minor_version = MD_MINOR_VERSION; mddev->patch_version = MD_PATCHLEVEL_VERSION; @@ -2169,6 +2457,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->layout = info->layout; mddev->chunk_size = info->chunk_size; + mddev->max_disks = MD_SB_DISKS; /* @@ -2282,9 +2571,11 @@ static int md_ioctl(struct inode *inode, struct file *file, err = -EBUSY; goto abort_unlock; } - if (arg) { + { mdu_array_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) { + if (!arg) + memset(&info, 0, sizeof(info)); + else if (copy_from_user(&info, (void*)arg, sizeof(info))) { err = -EFAULT; goto abort_unlock; } @@ -2473,12 +2764,6 @@ static struct block_device_operations md_fops = .ioctl = md_ioctl, }; - -static inline void flush_curr_signals(void) -{ - flush_signals(current); -} - int md_thread(void * arg) { mdk_thread_t *thread = arg; @@ -2489,7 +2774,7 @@ int md_thread(void * arg) * Detach thread */ - daemonize(thread->name); + daemonize(thread->name, mdidx(thread->mddev)); current->exit_signal = SIGCHLD; allow_signal(SIGKILL); @@ -2510,7 +2795,7 @@ int md_thread(void * arg) complete(thread->event); while (thread->run) { - void (*run)(void *data); + void (*run)(mddev_t *); wait_event_interruptible(thread->wqueue, test_bit(THREAD_WAKEUP, &thread->flags)); @@ -2521,11 +2806,11 @@ int md_thread(void * arg) run = thread->run; if (run) { - run(thread->data); + run(thread->mddev); blk_run_queues(); } if (signal_pending(current)) - flush_curr_signals(); + flush_signals(current); } complete(thread->event); return 0; @@ -2533,13 +2818,15 @@ int md_thread(void * arg) void md_wakeup_thread(mdk_thread_t *thread) { - dprintk("md: waking up MD thread %p.\n", thread); - set_bit(THREAD_WAKEUP, &thread->flags); - wake_up(&thread->wqueue); + if (thread) { + dprintk("md: waking up MD thread %p.\n", thread); + set_bit(THREAD_WAKEUP, &thread->flags); + wake_up(&thread->wqueue); + } } -mdk_thread_t *md_register_thread(void (*run) (void *), - void *data, const char *name) +mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, + const char *name) { mdk_thread_t *thread; int ret; @@ -2556,7 +2843,7 @@ mdk_thread_t *md_register_thread(void (*run) (void *), init_completion(&event); thread->event = &event; thread->run = run; - thread->data = data; + thread->mddev = mddev; thread->name = name; ret = kernel_thread(md_thread, thread, 0); if (ret < 0) { @@ -2591,16 +2878,6 @@ void md_unregister_thread(mdk_thread_t *thread) kfree(thread); } -static void md_recover_arrays(void) -{ - if (!md_recovery_thread) { - MD_BUG(); - return; - } - md_wakeup_thread(md_recovery_thread); -} - - void md_error(mddev_t *mddev, mdk_rdev_t *rdev) { dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", @@ -2618,33 +2895,34 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) if (!mddev->pers->error_handler) return; mddev->pers->error_handler(mddev,rdev); - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); } -static int status_unused(char * page) +/* seq_file implementation /proc/mdstat */ + +static void status_unused(struct seq_file *seq) { - int sz = 0, i = 0; + int i = 0; mdk_rdev_t *rdev; struct list_head *tmp; - sz += sprintf(page + sz, "unused devices: "); + seq_printf(seq, "unused devices: "); ITERATE_RDEV_PENDING(rdev,tmp) { i++; - sz += sprintf(page + sz, "%s ", + seq_printf(seq, "%s ", bdev_partition_name(rdev->bdev)); } if (!i) - sz += sprintf(page + sz, "<none>"); + seq_printf(seq, "<none>"); - sz += sprintf(page + sz, "\n"); - return sz; + seq_printf(seq, "\n"); } -static int status_resync(char * page, mddev_t * mddev) +static void status_resync(struct seq_file *seq, mddev_t * mddev) { - int sz = 0; unsigned long max_blocks, resync, res, dt, db, rt; resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; @@ -2655,21 +2933,22 @@ static int status_resync(char * page, mddev_t * mddev) */ if (!max_blocks) { MD_BUG(); - return 0; + return; } res = (resync/1024)*1000/(max_blocks/1024 + 1); { int i, x = res/50, y = 20-x; - sz += sprintf(page + sz, "["); + seq_printf(seq, "["); for (i = 0; i < x; i++) - sz += sprintf(page + sz, "="); - sz += sprintf(page + sz, ">"); + seq_printf(seq, "="); + seq_printf(seq, ">"); for (i = 0; i < y; i++) - sz += sprintf(page + sz, "."); - sz += sprintf(page + sz, "] "); + seq_printf(seq, "."); + seq_printf(seq, "] "); } - sz += sprintf(page + sz, " %s =%3lu.%lu%% (%lu/%lu)", - (mddev->spares ? "recovery" : "resync"), + seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)", + (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? + "resync" : "recovery"), res/10, res % 10, resync, max_blocks); /* @@ -2686,44 +2965,110 @@ static int status_resync(char * page, mddev_t * mddev) db = resync - (mddev->resync_mark_cnt/2); rt = (dt * ((max_blocks-resync) / (db/100+1)))/100; - sz += sprintf(page + sz, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); + seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); - sz += sprintf(page + sz, " speed=%ldK/sec", db/dt); + seq_printf(seq, " speed=%ldK/sec", db/dt); +} - return sz; +static void *md_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct list_head *tmp; + loff_t l = *pos; + mddev_t *mddev; + + if (l > 0x10000) + return NULL; + if (!l--) + /* header */ + return (void*)1; + + spin_lock(&all_mddevs_lock); + list_for_each(tmp,&all_mddevs) + if (!l--) { + mddev = list_entry(tmp, mddev_t, all_mddevs); + mddev_get(mddev); + spin_unlock(&all_mddevs_lock); + return mddev; + } + spin_unlock(&all_mddevs_lock); + return (void*)2;/* tail */ +} + +static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct list_head *tmp; + mddev_t *next_mddev, *mddev = v; + + ++*pos; + if (v == (void*)2) + return NULL; + + spin_lock(&all_mddevs_lock); + if (v == (void*)1) + tmp = all_mddevs.next; + else + tmp = mddev->all_mddevs.next; + if (tmp != &all_mddevs) + next_mddev = mddev_get(list_entry(tmp,mddev_t,all_mddevs)); + else { + next_mddev = (void*)2; + *pos = 0x10000; + } + spin_unlock(&all_mddevs_lock); + + if (v != (void*)1) + mddev_put(mddev); + return next_mddev; + +} + +static void md_seq_stop(struct seq_file *seq, void *v) +{ + mddev_t *mddev = v; + + if (mddev && v != (void*)1 && v != (void*)2) + mddev_put(mddev); } -static int md_status_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int md_seq_show(struct seq_file *seq, void *v) { - int sz = 0, j; + mddev_t *mddev = v; sector_t size; - struct list_head *tmp, *tmp2; + struct list_head *tmp2; mdk_rdev_t *rdev; - mddev_t *mddev; + int i; - sz += sprintf(page + sz, "Personalities : "); - for (j = 0; j < MAX_PERSONALITY; j++) - if (pers[j]) - sz += sprintf(page+sz, "[%s] ", pers[j]->name); + if (v == (void*)1) { + seq_printf(seq, "Personalities : "); + for (i = 0; i < MAX_PERSONALITY; i++) + if (pers[i]) + seq_printf(seq, "[%s] ", pers[i]->name); - sz += sprintf(page+sz, "\n"); + seq_printf(seq, "\n"); + return 0; + } + if (v == (void*)2) { + status_unused(seq); + return 0; + } - ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) { - sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev), + if (mddev_lock(mddev)!=0) + return -EINTR; + if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) { + seq_printf(seq, "md%d : %sactive", mdidx(mddev), mddev->pers ? "" : "in"); if (mddev->pers) { if (mddev->ro) - sz += sprintf(page + sz, " (read-only)"); - sz += sprintf(page + sz, " %s", mddev->pers->name); + seq_printf(seq, " (read-only)"); + seq_printf(seq, " %s", mddev->pers->name); } size = 0; ITERATE_RDEV(mddev,rdev,tmp2) { - sz += sprintf(page + sz, " %s[%d]", + seq_printf(seq, " %s[%d]", bdev_partition_name(rdev->bdev), rdev->desc_nr); if (rdev->faulty) { - sz += sprintf(page + sz, "(F)"); + seq_printf(seq, "(F)"); continue; } size += rdev->size; @@ -2731,34 +3076,50 @@ static int md_status_read_proc(char *page, char **start, off_t off, if (!list_empty(&mddev->disks)) { if (mddev->pers) - sz += sprintf(page + sz, "\n %llu blocks", + seq_printf(seq, "\n %llu blocks", (unsigned long long)md_size[mdidx(mddev)]); else - sz += sprintf(page + sz, "\n %llu blocks", (unsigned long long)size); + seq_printf(seq, "\n %llu blocks", (unsigned long long)size); } - if (!mddev->pers) { - sz += sprintf(page+sz, "\n"); - mddev_unlock(mddev); - continue; + if (mddev->pers) { + mddev->pers->status (seq, mddev); + seq_printf(seq, "\n "); + if (mddev->curr_resync > 2) + status_resync (seq, mddev); + else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) + seq_printf(seq, " resync=DELAYED"); } - sz += mddev->pers->status (page+sz, mddev); + seq_printf(seq, "\n"); + } + mddev_unlock(mddev); + + return 0; +} - sz += sprintf(page+sz, "\n "); - if (mddev->curr_resync > 2) - sz += status_resync (page+sz, mddev); - else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) - sz += sprintf(page + sz, " resync=DELAYED"); +static struct seq_operations md_seq_ops = { + .start = md_seq_start, + .next = md_seq_next, + .stop = md_seq_stop, + .show = md_seq_show, +}; - sz += sprintf(page + sz, "\n"); - mddev_unlock(mddev); - } - sz += status_unused(page + sz); +static int md_seq_open(struct inode *inode, struct file *file) +{ + int error; - return sz; + error = seq_open(file, &md_seq_ops); + return error; } +static struct file_operations md_seq_fops = { + .open = md_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + int register_md_personality(int pnum, mdk_personality_t *p) { if (pnum >= MAX_PERSONALITY) { @@ -2820,9 +3181,8 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok) atomic_sub(blocks, &mddev->recovery_active); wake_up(&mddev->recovery_wait); if (!ok) { - mddev->recovery_error = -EIO; - mddev->recovery_running = -1; - md_recover_arrays(); + set_bit(MD_RECOVERY_ERR, &mddev->recovery); + md_wakeup_thread(mddev->thread); // stop recovery, signal do_sync .... } } @@ -2830,40 +3190,49 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok) void md_write_start(mddev_t *mddev) { - if (mddev->safemode && !atomic_read(&mddev->writes_pending)) { + if (!atomic_read(&mddev->writes_pending)) { mddev_lock_uninterruptible(mddev); - atomic_inc(&mddev->writes_pending); if (mddev->in_sync) { mddev->in_sync = 0; + del_timer(&mddev->safemode_timer); md_update_sb(mddev); } + atomic_inc(&mddev->writes_pending); mddev_unlock(mddev); } else atomic_inc(&mddev->writes_pending); } -void md_write_end(mddev_t *mddev, mdk_thread_t *thread) +void md_write_end(mddev_t *mddev) { - if (atomic_dec_and_test(&mddev->writes_pending) && mddev->safemode) - md_wakeup_thread(thread); + if (atomic_dec_and_test(&mddev->writes_pending)) { + if (mddev->safemode == 2) + md_wakeup_thread(mddev->thread); + else + mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); + } } + static inline void md_enter_safemode(mddev_t *mddev) { - mddev_lock_uninterruptible(mddev); - if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && !mddev->recovery_running) { + if (mddev->safemode && !atomic_read(&mddev->writes_pending) && + !mddev->in_sync && mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; md_update_sb(mddev); } mddev_unlock(mddev); + + if (mddev->safemode == 1) + mddev->safemode = 0; } void md_handle_safemode(mddev_t *mddev) { if (signal_pending(current)) { - printk(KERN_INFO "md: md%d in safe mode\n",mdidx(mddev)); - mddev->safemode= 1; - flush_curr_signals(); + printk(KERN_INFO "md: md%d in immediate safe mode\n",mdidx(mddev)); + mddev->safemode = 2; + flush_signals(current); } if (mddev->safemode) md_enter_safemode(mddev); @@ -2874,9 +3243,8 @@ DECLARE_WAIT_QUEUE_HEAD(resync_wait); #define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) -static void md_do_sync(void *data) +static void md_do_sync(mddev_t *mddev) { - mddev_t *mddev = data; mddev_t *mddev2; unsigned int max_sectors, currspeed = 0, j, window, err; @@ -2887,7 +3255,7 @@ static void md_do_sync(void *data) unsigned long last_check; /* just incase thread restarts... */ - if (mddev->recovery_running <= 0) + if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) return; /* we overload curr_resync somewhat here. @@ -2914,14 +3282,16 @@ static void md_do_sync(void *data) } if (wait_event_interruptible(resync_wait, mddev2->curr_resync < mddev->curr_resync)) { - flush_curr_signals(); + flush_signals(current); err = -EINTR; mddev_put(mddev2); goto skip; } } - if (mddev->curr_resync == 1) + if (mddev->curr_resync == 1) { + mddev_put(mddev2); break; + } } } while (mddev->curr_resync < 2); @@ -2934,9 +3304,13 @@ static void md_do_sync(void *data) sysctl_speed_limit_max); is_mddev_idle(mddev); /* this also initializes IO event counters */ + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + j = mddev->recovery_cp; + else + j = 0; for (m = 0; m < SYNC_MARKS; m++) { mark[m] = jiffies; - mark_cnt[m] = mddev->recovery_cp; + mark_cnt[m] = j; } last_mark = 0; mddev->resync_mark = mark[last_mark]; @@ -2953,12 +3327,10 @@ static void md_do_sync(void *data) init_waitqueue_head(&mddev->recovery_wait); last_check = 0; - mddev->recovery_error = 0; - - if (mddev->recovery_cp) + if (j) printk(KERN_INFO "md: resuming recovery of md%d from checkpoint.\n", mdidx(mddev)); - for (j = mddev->recovery_cp; j < max_sectors;) { + while (j < max_sectors) { int sectors; sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min); @@ -2975,6 +3347,10 @@ static void md_do_sync(void *data) last_check = j; + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) || + test_bit(MD_RECOVERY_ERR, &mddev->recovery)) + break; + blk_run_queues(); repeat: @@ -2995,7 +3371,7 @@ static void md_do_sync(void *data) * got a signal, exit. */ printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n"); - flush_curr_signals(); + flush_signals(current); err = -EINTR; goto out; } @@ -3029,39 +3405,42 @@ static void md_do_sync(void *data) out: wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); - if (mddev->recovery_running < 0 && - !mddev->recovery_error && mddev->curr_resync > 2) - { - /* interrupted but no write errors */ - printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev)); - mddev->recovery_cp = mddev->curr_resync; - } - /* tell personality that we are finished */ mddev->pers->sync_request(mddev, max_sectors, 1); - skip: - mddev->curr_resync = 0; + if (err) - mddev->recovery_running = -1; - if (mddev->recovery_running > 0) - mddev->recovery_running = 0; - if (mddev->recovery_running == 0) - mddev->recovery_cp = MaxSector; + set_bit(MD_RECOVERY_ERR, &mddev->recovery); + if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && + mddev->curr_resync > 2 && + mddev->curr_resync > mddev->recovery_cp) { + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev)); + mddev->recovery_cp = mddev->curr_resync; + } else + mddev->recovery_cp = MaxSector; + } + if (mddev->safemode) md_enter_safemode(mddev); - md_recover_arrays(); + skip: + mddev->curr_resync = 0; + set_bit(MD_RECOVERY_DONE, &mddev->recovery); + md_wakeup_thread(mddev->thread); } /* - * This is the kernel thread that watches all md arrays for re-sync and other - * action that might be needed. + * This routine is regularly called by all per-raid-array threads to + * deal with generic issues like resync and super-block update. + * Raid personalities that don't have a thread (linear/raid0) do not + * need this as they never do any recovery or update the superblock. + * * It does not do any resync itself, but rather "forks" off other threads * to do that as needed. - * When it is determined that resync is needed, we set "->recovery_running" and - * create a thread at ->sync_thread. - * When the thread finishes it clears recovery_running (or sets an error) - * and wakeup up this thread which will reap the thread and finish up. + * When it is determined that resync is needed, we set MD_RECOVERY_RUNNING in + * "->recovery" and create a thread at ->sync_thread. + * When the thread finishes it sets MD_RECOVERY_DONE (and might set MD_RECOVERY_ERR) + * and wakeups up this thread which will reap the thread and finish up. * This thread also removes any faulty devices (with nr_pending == 0). * * The overall approach is: @@ -3072,41 +3451,47 @@ static void md_do_sync(void *data) * 5/ If array is degraded, try to add spares devices * 6/ If array has spares or is not in-sync, start a resync thread. */ -void md_do_recovery(void *data) +void md_check_recovery(mddev_t *mddev) { - mddev_t *mddev; mdk_rdev_t *rdev; - struct list_head *tmp, *rtmp; + struct list_head *rtmp; dprintk(KERN_INFO "md: recovery thread got woken up ...\n"); - ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) { - if (!mddev->raid_disks || !mddev->pers || mddev->ro) - goto unlock; + if (mddev->ro) + return; + if ( ! ( + mddev->sb_dirty || + test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || + test_bit(MD_RECOVERY_DONE, &mddev->recovery) + )) + return; + if (mddev_trylock(mddev)==0) { + int spares =0; if (mddev->sb_dirty) md_update_sb(mddev); - if (mddev->recovery_running > 0) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && + !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) /* resync/recovery still happening */ goto unlock; if (mddev->sync_thread) { /* resync has finished, collect result */ md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; - if (mddev->recovery_running == 0) { + if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery)) { /* success...*/ /* activate any spares */ mddev->pers->spare_active(mddev); - mddev->spares = 0; } md_update_sb(mddev); - mddev->recovery_running = 0; + mddev->recovery = 0; wake_up(&resync_wait); goto unlock; } - if (mddev->recovery_running) { + if (mddev->recovery) { /* that's odd.. */ - mddev->recovery_running = 0; + mddev->recovery = 0; wake_up(&resync_wait); } @@ -3114,7 +3499,6 @@ void md_do_recovery(void *data) * remove any failed drives, then * add spares if possible */ - mddev->spares = 0; ITERATE_RDEV(mddev,rdev,rtmp) { if (rdev->raid_disk >= 0 && rdev->faulty && @@ -3123,43 +3507,41 @@ void md_do_recovery(void *data) rdev->raid_disk = -1; } if (!rdev->faulty && rdev->raid_disk >= 0 && !rdev->in_sync) - mddev->spares++; + spares++; } if (mddev->degraded) { ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 && !rdev->faulty) { - if (mddev->pers->hot_add_disk(mddev,rdev)) { - mddev->spares++; - mddev->recovery_cp = 0; - } + if (mddev->pers->hot_add_disk(mddev,rdev)) + spares++; else break; } } - if (!mddev->spares && (mddev->recovery_cp == MaxSector )) { + if (!spares && (mddev->recovery_cp == MaxSector )) { /* nothing we can do ... */ goto unlock; } if (mddev->pers->sync_request) { + set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + if (!spares) + set_bit(MD_RECOVERY_SYNC, &mddev->recovery); mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "md_resync"); + "md%d_resync"); if (!mddev->sync_thread) { printk(KERN_ERR "md%d: could not start resync thread...\n", mdidx(mddev)); /* leave the spares where they are, it shouldn't hurt */ - mddev->recovery_running = 0; + mddev->recovery = 0; } else { - mddev->recovery_running = 1; md_wakeup_thread(mddev->sync_thread); } } unlock: mddev_unlock(mddev); } - dprintk(KERN_INFO "md: recovery thread finished ...\n"); - } int md_notify_reboot(struct notifier_block *this, @@ -3194,6 +3576,7 @@ struct notifier_block md_notifier = { static void md_geninit(void) { + struct proc_dir_entry *p; int i; for(i = 0; i < MAX_MD_DEVS; i++) { @@ -3203,13 +3586,14 @@ static void md_geninit(void) dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); #ifdef CONFIG_PROC_FS - create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL); + p = create_proc_entry("mdstat", S_IRUGO, NULL); + if (p) + p->proc_fops = &md_seq_fops; #endif } int __init md_init(void) { - static char * name = "mdrecoveryd"; int minor; printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n", @@ -3229,11 +3613,6 @@ int __init md_init(void) S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL); } - md_recovery_thread = md_register_thread(md_do_recovery, NULL, name); - if (!md_recovery_thread) - printk(KERN_ALERT - "md: bug: couldn't allocate md_recovery_thread\n"); - register_reboot_notifier(&md_notifier); raid_table_header = register_sysctl_table(raid_root_table, 1); @@ -3268,7 +3647,7 @@ static void autostart_arrays(void) for (i = 0; i < dev_cnt; i++) { dev_t dev = detected_devices[i]; - rdev = md_import_device(dev,1); + rdev = md_import_device(dev,0, 0); if (IS_ERR(rdev)) { printk(KERN_ALERT "md: could not import %s!\n", partition_name(dev)); @@ -3291,7 +3670,6 @@ static __exit void md_exit(void) { int i; blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS); - md_unregister_thread(md_recovery_thread); for (i=0; i < MAX_MD_DEVS; i++) devfs_remove("md/%d", i); devfs_remove("md"); @@ -3331,4 +3709,5 @@ EXPORT_SYMBOL(md_unregister_thread); EXPORT_SYMBOL(md_wakeup_thread); EXPORT_SYMBOL(md_print_devices); EXPORT_SYMBOL(md_interrupt_thread); +EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 5b96e4a42d21..bff6174d8782 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -86,7 +86,6 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh) { unsigned long flags; mddev_t *mddev = mp_bh->mddev; - multipath_conf_t *conf = mddev_to_conf(mddev); spin_lock_irqsave(&retry_list_lock, flags); if (multipath_retry_list == NULL) @@ -95,7 +94,7 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh) multipath_retry_tail = &mp_bh->next_mp; mp_bh->next_mp = NULL; spin_unlock_irqrestore(&retry_list_lock, flags); - md_wakeup_thread(conf->thread); + md_wakeup_thread(mddev->thread); } @@ -185,19 +184,18 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio) return 0; } -static int multipath_status (char *page, mddev_t *mddev) +static void multipath_status (struct seq_file *seq, mddev_t *mddev) { multipath_conf_t *conf = mddev_to_conf(mddev); - int sz = 0, i; + int i; - sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, + seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", + seq_printf (seq, "%s", conf->multipaths[i].rdev && conf->multipaths[i].rdev->in_sync ? "U" : "_"); - sz += sprintf (page+sz, "]"); - return sz; + seq_printf (seq, "]"); } #define LAST_DISK KERN_ALERT \ @@ -334,14 +332,14 @@ abort: * 3. Performs writes following reads for array syncronising. */ -static void multipathd (void *data) +static void multipathd (mddev_t *mddev) { struct multipath_bh *mp_bh; struct bio *bio; unsigned long flags; - mddev_t *mddev; mdk_rdev_t *rdev; + md_check_recovery(mddev); for (;;) { spin_lock_irqsave(&retry_list_lock, flags); mp_bh = multipath_retry_list; @@ -471,10 +469,10 @@ static int multipath_run (mddev_t *mddev) } { - const char * name = "multipathd"; + const char * name = "md%d_multipath"; - conf->thread = md_register_thread(multipathd, conf, name); - if (!conf->thread) { + mddev->thread = md_register_thread(multipathd, mddev, name); + if (!mddev->thread) { printk(THREAD_ERROR, mdidx(mddev)); goto out_free_conf; } @@ -513,7 +511,7 @@ static int multipath_stop (mddev_t *mddev) { multipath_conf_t *conf = mddev_to_conf(mddev); - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); mempool_destroy(conf->pool); kfree(conf); mddev->private = NULL; diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 0d83f3647f93..99de04b380a3 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -349,7 +349,7 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio) * is the only IO operation happening on this bh. */ bio->bi_bdev = tmp_dev->bdev; - bio->bi_sector = rsect; + bio->bi_sector = rsect + tmp_dev->data_offset; /* * Let the main block layer submit the IO and resolve recursion: @@ -372,41 +372,40 @@ bad_zone1: return 0; } -static int raid0_status (char *page, mddev_t *mddev) +static void raid0_status (struct seq_file *seq, mddev_t *mddev) { - int sz = 0; #undef MD_DEBUG #ifdef MD_DEBUG int j, k; raid0_conf_t *conf = mddev_to_conf(mddev); - sz += sprintf(page + sz, " "); + seq_printf(seq, " "); for (j = 0; j < conf->nr_zones; j++) { - sz += sprintf(page + sz, "[z%d", + seq_printf(seq, "[z%d", conf->hash_table[j].zone0 - conf->strip_zone); if (conf->hash_table[j].zone1) - sz += sprintf(page+sz, "/z%d] ", + seq_printf(seq, "/z%d] ", conf->hash_table[j].zone1 - conf->strip_zone); else - sz += sprintf(page+sz, "] "); + seq_printf(seq, "] "); } - sz += sprintf(page + sz, "\n"); + seq_printf(seq, "\n"); for (j = 0; j < conf->nr_strip_zones; j++) { - sz += sprintf(page + sz, " z%d=[", j); + seq_printf(seq, " z%d=[", j); for (k = 0; k < conf->strip_zone[j].nb_dev; k++) - sz += sprintf (page+sz, "%s/", bdev_partition_name( + seq_printf (seq, "%s/", bdev_partition_name( conf->strip_zone[j].dev[k]->bdev)); - sz--; - sz += sprintf (page+sz, "] zo=%d do=%d s=%d\n", + + seq_printf (seq, "] zo=%d do=%d s=%d\n", conf->strip_zone[j].zone_offset, conf->strip_zone[j].dev_offset, conf->strip_zone[j].size); } #endif - sz += sprintf(page + sz, " %dk chunks", mddev->chunk_size/1024); - return sz; + seq_printf(seq, " %dk chunks", mddev->chunk_size/1024); + return; } static mdk_personality_t raid0_personality= diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 83ee73ef172f..0dd391e3d3b1 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -225,13 +225,12 @@ static void reschedule_retry(r1bio_t *r1_bio) { unsigned long flags; mddev_t *mddev = r1_bio->mddev; - conf_t *conf = mddev_to_conf(mddev); spin_lock_irqsave(&retry_list_lock, flags); list_add(&r1_bio->retry_list, &retry_list_head); spin_unlock_irqrestore(&retry_list_lock, flags); - md_wakeup_thread(conf->thread); + md_wakeup_thread(mddev->thread); } /* @@ -320,7 +319,7 @@ static int end_request(struct bio *bio, unsigned int bytes_done, int error) * already. */ if (atomic_dec_and_test(&r1_bio->remaining)) { - md_write_end(r1_bio->mddev,conf->thread); + md_write_end(r1_bio->mddev); raid_end_bio_io(r1_bio, uptodate); } } @@ -494,7 +493,7 @@ static int make_request(request_queue_t *q, struct bio * bio) BUG(); r1_bio->read_bio = read_bio; - read_bio->bi_sector = r1_bio->sector; + read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = end_request; read_bio->bi_rw = r1_bio->cmd; @@ -529,7 +528,7 @@ static int make_request(request_queue_t *q, struct bio * bio) mbio = bio_clone(bio, GFP_NOIO); r1_bio->write_bios[i] = mbio; - mbio->bi_sector = r1_bio->sector; + mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = end_request; mbio->bi_rw = r1_bio->cmd; @@ -542,7 +541,7 @@ static int make_request(request_queue_t *q, struct bio * bio) * If all mirrors are non-operational * then return an IO error: */ - md_write_end(mddev,conf->thread); + md_write_end(mddev); raid_end_bio_io(r1_bio, 0); return 0; } @@ -571,19 +570,18 @@ static int make_request(request_queue_t *q, struct bio * bio) return 0; } -static int status(char *page, mddev_t *mddev) +static void status(struct seq_file *seq, mddev_t *mddev) { conf_t *conf = mddev_to_conf(mddev); - int sz = 0, i; + int i; - sz += sprintf(page+sz, " [%d/%d] [", conf->raid_disks, + seq_printf(seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) - sz += sprintf(page+sz, "%s", + seq_printf(seq, "%s", conf->mirrors[i].rdev && conf->mirrors[i].rdev->in_sync ? "U" : "_"); - sz += sprintf (page+sz, "]"); - return sz; + seq_printf(seq, "]"); } #define LAST_DISK KERN_ALERT \ @@ -624,10 +622,9 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) mddev->degraded++; conf->working_disks--; /* - * if recovery was running, stop it now. + * if recovery is running, make sure it aborts. */ - if (mddev->recovery_running) - mddev->recovery_running = -EIO; + set_bit(MD_RECOVERY_ERR, &mddev->recovery); } rdev->in_sync = 0; rdev->faulty = 1; @@ -859,7 +856,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) mbio = bio_clone(bio, GFP_NOIO); r1_bio->write_bios[i] = mbio; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; - mbio->bi_sector = r1_bio->sector; + mbio->bi_sector = r1_bio->sector | conf->mirrors[i].rdev->data_offset; mbio->bi_end_io = end_sync_write; mbio->bi_rw = WRITE; mbio->bi_private = r1_bio; @@ -900,17 +897,17 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) * 3. Performs writes following reads for array syncronising. */ -static void raid1d(void *data) +static void raid1d(mddev_t *mddev) { struct list_head *head = &retry_list_head; r1bio_t *r1_bio; struct bio *bio; unsigned long flags; - mddev_t *mddev; - conf_t *conf = data; + conf_t *conf = mddev_to_conf(mddev); mdk_rdev_t *rdev; - md_handle_safemode(conf->mddev); + md_check_recovery(mddev); + md_handle_safemode(mddev); for (;;) { spin_lock_irqsave(&retry_list_lock, flags); @@ -937,7 +934,7 @@ static void raid1d(void *data) printk(REDIRECT_SECTOR, bdev_partition_name(rdev->bdev), (unsigned long long)r1_bio->sector); bio->bi_bdev = rdev->bdev; - bio->bi_sector = r1_bio->sector; + bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_rw = r1_bio->cmd; generic_make_request(bio); @@ -1048,7 +1045,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) read_bio = bio_clone(r1_bio->master_bio, GFP_NOIO); - read_bio->bi_sector = sector_nr; + read_bio->bi_sector = sector_nr + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = end_sync_read; read_bio->bi_rw = READ; @@ -1190,10 +1187,8 @@ static int run(mddev_t *mddev) { - snprintf(conf->thread_name,MD_THREAD_NAME_MAX,"raid1d_md%d",mdidx(mddev)); - - conf->thread = md_register_thread(raid1d, conf, conf->thread_name); - if (!conf->thread) { + mddev->thread = md_register_thread(raid1d, mddev, "md%d_raid1"); + if (!mddev->thread) { printk(THREAD_ERROR, mdidx(mddev)); goto out_free_conf; } @@ -1219,7 +1214,8 @@ static int stop(mddev_t *mddev) { conf_t *conf = mddev_to_conf(mddev); - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); + mddev->thread = NULL; if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); kfree(conf); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 7949de5f8e87..51a8e2d721d6 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -71,12 +71,12 @@ static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) list_add_tail(&sh->lru, &conf->delayed_list); else list_add_tail(&sh->lru, &conf->handle_list); - md_wakeup_thread(conf->thread); + md_wakeup_thread(conf->mddev->thread); } else { if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { atomic_dec(&conf->preread_active_stripes); if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) - md_wakeup_thread(conf->thread); + md_wakeup_thread(conf->mddev->thread); } list_add_tail(&sh->lru, &conf->inactive_list); atomic_dec(&conf->active_stripes); @@ -463,10 +463,9 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) conf->failed_disks++; rdev->in_sync = 0; /* - * if recovery was running, stop it now. + * if recovery was running, make sure it aborts. */ - if (mddev->recovery_running) - mddev->recovery_running = -EIO; + set_bit(MD_RECOVERY_ERR, &mddev->recovery); } rdev->faulty = 1; printk (KERN_ALERT @@ -913,7 +912,7 @@ static void handle_stripe(struct stripe_head *sh) struct bio *nextbi = bi->bi_next; clear_bit(BIO_UPTODATE, &bi->bi_flags); if (--bi->bi_phys_segments == 0) { - md_write_end(conf->mddev, conf->thread); + md_write_end(conf->mddev); bi->bi_next = return_bi; return_bi = bi; } @@ -970,7 +969,7 @@ static void handle_stripe(struct stripe_head *sh) while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) { wbi2 = wbi->bi_next; if (--wbi->bi_phys_segments == 0) { - md_write_end(conf->mddev, conf->thread); + md_write_end(conf->mddev); wbi->bi_next = return_bi; return_bi = wbi; } @@ -1113,7 +1112,7 @@ static void handle_stripe(struct stripe_head *sh) if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { atomic_dec(&conf->preread_active_stripes); if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) - md_wakeup_thread(conf->thread); + md_wakeup_thread(conf->mddev->thread); } } } @@ -1207,7 +1206,7 @@ static void handle_stripe(struct stripe_head *sh) bi->bi_bdev = rdev->bdev; PRINTK("for %llu schedule op %ld on disc %d\n", (unsigned long long)sh->sector, bi->bi_rw, i); atomic_inc(&sh->count); - bi->bi_sector = sh->sector; + bi->bi_sector = sh->sector + rdev->data_offset; bi->bi_flags = 1 << BIO_UPTODATE; bi->bi_vcnt = 1; bi->bi_idx = 0; @@ -1251,7 +1250,7 @@ static void raid5_unplug_device(void *data) if (blk_remove_plug(q)) raid5_activate_delayed(conf); - md_wakeup_thread(conf->thread); + md_wakeup_thread(mddev->thread); spin_unlock_irqrestore(&conf->device_lock, flags); } @@ -1304,7 +1303,7 @@ static int make_request (request_queue_t *q, struct bio * bi) int bytes = bi->bi_size; if ( bio_data_dir(bi) == WRITE ) - md_write_end(mddev,conf->thread); + md_write_end(mddev); bi->bi_size = 0; bi->bi_end_io(bi, bytes, 0); } @@ -1356,16 +1355,17 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster) * During the scan, completed stripes are saved for us by the interrupt * handler, so that they will not have to wait for our next wakeup. */ -static void raid5d (void *data) +static void raid5d (mddev_t *mddev) { struct stripe_head *sh; - raid5_conf_t *conf = data; - mddev_t *mddev = conf->mddev; + raid5_conf_t *conf = mddev_to_conf(mddev); int handled; PRINTK("+++ raid5d active\n"); + md_check_recovery(mddev); md_handle_safemode(mddev); + handled = 0; spin_lock_irq(&conf->device_lock); while (1) { @@ -1486,10 +1486,8 @@ static int run (mddev_t *mddev) } { - snprintf(conf->thread_name,MD_THREAD_NAME_MAX,"raid5d_md%d",mdidx(mddev)); - - conf->thread = md_register_thread(raid5d, conf, conf->thread_name); - if (!conf->thread) { + mddev->thread = md_register_thread(raid5d, mddev, "md%d_raid5"); + if (!mddev->thread) { printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); goto abort; } @@ -1500,7 +1498,7 @@ static int run (mddev_t *mddev) if (grow_stripes(conf, conf->max_nr_stripes)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); shrink_stripes(conf); - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); goto abort; } else printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); @@ -1536,7 +1534,8 @@ static int stop (mddev_t *mddev) { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); + mddev->thread = NULL; shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); kfree(conf); @@ -1574,29 +1573,26 @@ static void printall (raid5_conf_t *conf) } } spin_unlock_irq(&conf->device_lock); - - PRINTK("--- raid5d inactive\n"); } #endif -static int status (char *page, mddev_t *mddev) +static void status (struct seq_file *seq, mddev_t *mddev) { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; - int sz = 0, i; + int i; - sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout); - sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks); + seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout); + seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", + seq_printf (seq, "%s", conf->disks[i].rdev && conf->disks[i].rdev->in_sync ? "U" : "_"); - sz += sprintf (page+sz, "]"); + seq_printf (seq, "]"); #if RAID5_DEBUG #define D(x) \ - sz += sprintf (page+sz, "<"#x":%d>", atomic_read(&conf->x)) + seq_printf (seq, "<"#x":%d>", atomic_read(&conf->x)) printall(conf); #endif - return sz; } static void print_raid5_conf (raid5_conf_t *conf) diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index fa2eebe2ecd0..dd08c51cae80 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -113,7 +113,7 @@ static struct file_operations rds_fops = { static struct miscdevice rds_miscdev = { .minor = MISC_DYNAMIC_MINOR, - .name = "radiotext" + .name = "radiotext", .fops = &rds_fops, }; @@ -128,7 +128,7 @@ static int __init miropcm20_rds_init(void) error = devfs_mk_symlink(NULL, "v4l/rds/radiotext", 0, "../misc/radiotext", NULL, NULL); if (error) - misc_deregister(&rds_miscdev) + misc_deregister(&rds_miscdev); return error; } @@ -136,7 +136,7 @@ static int __init miropcm20_rds_init(void) static void __exit miropcm20_rds_cleanup(void) { devfs_remove("v4l/rds/radiotext"); - misc_deregister(&rds_miscdev) + misc_deregister(&rds_miscdev); } module_init(miropcm20_rds_init); diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 2ed590fc87c1..0f823e82d5e3 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -36,7 +36,6 @@ #include <asm/io.h> #include "bttvp.h" -#include "tuner.h" #include "bt832.h" /* fwd decl */ diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index b9d3949f9857..ed8d3b0f03f6 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -37,7 +37,6 @@ #include <asm/io.h> #include "bttvp.h" -#include "tuner.h" int bttv_num; /* number of Bt848s in use */ struct bttv bttvs[BTTV_MAX]; diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c index 01ea37beac5f..1b3c83e16fe0 100644 --- a/drivers/media/video/bttv-if.c +++ b/drivers/media/video/bttv-if.c @@ -34,7 +34,6 @@ #include <asm/io.h> #include "bttvp.h" -#include "tuner.h" static struct i2c_algo_bit_data bttv_i2c_algo_template; static struct i2c_adapter bttv_i2c_adap_template; diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 49882b03769e..65f8d54e1816 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -34,10 +34,12 @@ #include <linux/pci.h> #include <asm/scatterlist.h> +#include <media/video-buf.h> +#include <media/audiochip.h> +#include <media/tuner.h> + #include "bt848.h" #include "bttv.h" -#include "video-buf.h" -#include "audiochip.h" #ifdef __KERNEL__ diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index d91d04f97f4f..9000e6f107c3 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -56,7 +56,7 @@ #define __KERNEL_SYSCALLS__ #include <linux/unistd.h> -#include "audiochip.h" +#include <media/audiochip.h> #include "msp3400.h" /* Addresses to scan */ @@ -1495,8 +1495,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) VIDEO_AUDIO_MUTABLE; if (msp->muted) va->flags |= VIDEO_AUDIO_MUTE; - va->volume=MAX(msp->left,msp->right); - va->balance=(32768*MIN(msp->left,msp->right))/ + va->volume=max(msp->left,msp->right); + va->balance=(32768*min(msp->left,msp->right))/ (va->volume ? va->volume : 1); va->balance=(msp->left<msp->right)? (65535-va->balance) : va->balance; @@ -1517,9 +1517,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk(KERN_DEBUG "msp34xx: VIDIOCSAUDIO\n"); msp->muted = (va->flags & VIDEO_AUDIO_MUTE); - msp->left = (MIN(65536 - va->balance,32768) * + msp->left = (min(65536 - va->balance,32768) * va->volume) / 32768; - msp->right = (MIN(va->balance,32768) * + msp->right = (min(va->balance,(__u16)32768) * va->volume) / 32768; msp->bass = va->bass; msp->treble = va->treble; diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index bc8b98bfd062..d2d58ec70da1 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -24,7 +24,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" /* commly used strings */ static char name_mute[] = "mute"; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 07b31bc2f848..e88367522cdb 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -30,7 +30,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 438ee56ae0c3..72463f5cb7b3 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -30,8 +30,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" -#include "id.h" /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 562ebf3332ee..9d22bf8a348b 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -29,8 +29,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" -#include "audiochip.h" /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index aa3ef2596b62..57f1fc42ed0a 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -22,7 +22,11 @@ #include <linux/i2c.h> #include <linux/videodev.h> #include <linux/kdev_t.h> -#include "video-buf.h" + +#include <media/video-buf.h> +#include <media/tuner.h> +#include <media/audiochip.h> +#include <media/id.h> #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,2) diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 4b96ec8af1f7..8ba55c0a6644 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -49,8 +49,8 @@ #include <linux/i2c-algo-bit.h> #include "bttv.h" -#include "audiochip.h" -#include "id.h" +#include <media/audiochip.h> +#include <media/id.h> #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index d2d0917ececf..28a9c2f60c7d 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -31,8 +31,8 @@ #include <linux/init.h> #include "bttv.h" -#include "audiochip.h" -#include "id.h" +#include <media/audiochip.h> +#include <media/id.h> MODULE_PARM(debug,"i"); MODULE_LICENSE("GPL"); @@ -316,17 +316,15 @@ static int tda9875_command(struct i2c_client *client, /* min is -84 max is 24 */ left = (t->lvol+84)*606; right = (t->rvol+84)*606; - va->volume=MAX(left,right); - va->balance=(32768*MIN(left,right))/ + va->volume=max(left,right); + va->balance=(32768*min(left,right))/ (va->volume ? va->volume : 1); va->balance=(left<right)? (65535-va->balance) : va->balance; va->bass = (t->bass+12)*2427; /* min -12 max +15 */ va->treble = (t->treble+12)*2730;/* min -12 max +12 */ - va->mode |= VIDEO_SOUND_MONO; - break; /* VIDIOCGAUDIO case */ } @@ -336,9 +334,9 @@ static int tda9875_command(struct i2c_client *client, int left,right; dprintk("VIDEOCSAUDIO...\n"); - left = (MIN(65536 - va->balance,32768) * + left = (min(65536 - va->balance,32768) * va->volume) / 32768; - right = (MIN(va->balance,32768) * + right = (min(va->balance,(__u16)32768) * va->volume) / 32768; t->lvol = ((left/606)-84) & 0xff; if (t->lvol > 24) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 3d8c6fa0b20f..fb20ba56c24e 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -7,8 +7,8 @@ #include <linux/errno.h> #include <linux/slab.h> -#include "id.h" -#include "audiochip.h" +#include <media/audiochip.h> +#include <media/id.h> /* Chips: TDA9885 (PAL, NTSC) diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c index 4319f317cb30..5c4328d6a1ab 100644 --- a/drivers/media/video/tuner-3036.c +++ b/drivers/media/video/tuner-3036.c @@ -27,7 +27,7 @@ #include <linux/i2c.h> #include <linux/videodev.h> -#include "tuner.h" +#include <media/tuner.h> static int debug; /* insmod parameter */ static int this_adap; diff --git a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c index 0638747257c5..f83309c257d8 100644 --- a/drivers/media/video/tuner.c +++ b/drivers/media/video/tuner.c @@ -12,8 +12,8 @@ #include <linux/videodev.h> #include <linux/init.h> -#include "tuner.h" -#include "audiochip.h" +#include <media/tuner.h> +#include <media/audiochip.h> /* Addresses to scan */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index b077e42ef792..bf68fc0d6874 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -29,9 +29,10 @@ #include <linux/init.h> #include <linux/smp_lock.h> -#include "audiochip.h" +#include <media/audiochip.h> +#include <media/id.h> + #include "tvaudio.h" -#include "id.h" /* ---------------------------------------------------------------------- */ @@ -1477,8 +1478,8 @@ static int chip_command(struct i2c_client *client, if (desc->flags & CHIP_HAS_VOLUME) { va->flags |= VIDEO_AUDIO_VOLUME; - va->volume = MAX(chip->left,chip->right); - va->balance = (32768*MIN(chip->left,chip->right))/ + va->volume = max(chip->left,chip->right); + va->balance = (32768*min(chip->left,chip->right))/ (va->volume ? va->volume : 1); } if (desc->flags & CHIP_HAS_BASSTREBLE) { @@ -1500,9 +1501,9 @@ static int chip_command(struct i2c_client *client, struct video_audio *va = arg; if (desc->flags & CHIP_HAS_VOLUME) { - chip->left = (MIN(65536 - va->balance,32768) * + chip->left = (min(65536 - va->balance,32768) * va->volume) / 32768; - chip->right = (MIN(va->balance,32768) * + chip->right = (min(va->balance,(__u16)32768) * va->volume) / 32768; chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index 73aba5038825..ff50ba8bb249 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -16,8 +16,6 @@ #include <linux/soundcard.h> #include <asm/uaccess.h> -#include "audiochip.h" -#include "id.h" #define DEV_MAX 4 @@ -136,16 +134,16 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm case MIXER_WRITE(SOUND_MIXER_VOLUME): left = mix_to_v4l(val); right = mix_to_v4l(val >> 8); - va.volume = MAX(left,right); - va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1); + va.volume = max(left,right); + va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1); va.balance = (left<right) ? (65535-va.balance) : va.balance; client->driver->command(client,VIDIOCSAUDIO,&va); client->driver->command(client,VIDIOCGAUDIO,&va); /* fall throuth */ case MIXER_READ(SOUND_MIXER_VOLUME): - left = (MIN(65536 - va.balance,32768) * + left = (min(65536 - va.balance,32768) * va.volume) / 32768; - right = (MIN(va.balance,32768) * + right = (min(va.balance,32768) * va.volume) / 32768; ret = v4l_to_mix2(left,right); break; diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 20e2c2e6f692..36c155bfd42f 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -31,7 +31,7 @@ # define TryLockPage TestSetPageLocked #endif -#include "video-buf.h" +#include <media/video-buf.h> static int debug = 0; diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 523e83f771da..1f1f70caca21 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -3784,11 +3784,15 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) return -EOPNOTSUPP; } - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) + if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) { + kfree(strings); return -EFAULT; + } - if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) + if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) { + kfree(strings); return -EFAULT; + } kfree(strings); return 0; diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index c2b0b6a833a2..9162f38d8395 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -82,9 +82,16 @@ static struct notifier_block exit_mmap_nb = { int sync_start(void) { - int err = profile_event_register(EXIT_TASK, &exit_task_nb); + int err; + + init_timer(&sync_timer); + sync_timer.function = timer_ping; + sync_timer.expires = jiffies + DEFAULT_EXPIRE; + add_timer(&sync_timer); + + err = profile_event_register(EXIT_TASK, &exit_task_nb); if (err) - goto out; + goto out1; err = profile_event_register(EXIT_MMAP, &exit_mmap_nb); if (err) goto out2; @@ -92,16 +99,14 @@ int sync_start(void) if (err) goto out3; - init_timer(&sync_timer); - sync_timer.function = timer_ping; - sync_timer.expires = jiffies + DEFAULT_EXPIRE; - add_timer(&sync_timer); out: return err; out3: profile_event_unregister(EXIT_MMAP, &exit_mmap_nb); out2: profile_event_unregister(EXIT_TASK, &exit_task_nb); +out1: + del_timer_sync(&sync_timer); goto out; } diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids index 60d3a51f93a3..0ee6b158705c 100644 --- a/drivers/pci/pci.ids +++ b/drivers/pci/pci.ids @@ -5440,6 +5440,11 @@ 14f1 2004 Dynalink 56PMi 8234 RS8234 ATM SAR Controller [ServiceSAR Plus] 14f2 MOBILITY Electronics + 0120 EV1000 bridge + 0121 EV1000 Parallel port + 0122 EV1000 Serial port + 0123 EV1000 Keyboard controller + 0124 EV1000 Mouse controller 14f3 BROADLOGIC 14f4 TOKYO Electronic Industry CO Ltd 14f5 SOPAC Ltd diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 1c66d319f420..88b30de4726a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -15,6 +15,9 @@ #define DBG(x...) #endif +#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ +#define CARDBUS_RESERVE_BUSNR 3 + LIST_HEAD(pci_root_buses); LIST_HEAD(pci_devices); @@ -291,12 +294,15 @@ static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); */ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) { - unsigned int buses; struct pci_bus *child; int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); + u32 buses; pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); - DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass); + + DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", + dev->slot_name, buses & 0xffffff, pass); + if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { unsigned int cmax; /* @@ -333,8 +339,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max * yenta.c forces a secondary latency timer of 176. * Copy that behaviour here. */ - if (is_cardbus) - buses = (buses & 0x00ffffff) | (176 << 24); + if (is_cardbus) { + buses &= ~0xff000000; + buses |= CARDBUS_LATENCY_TIMER << 24; + } /* * We need to blast all three values with a single write. @@ -350,7 +358,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max * as cards with a PCI-to-PCI bridge can be * inserted later. */ - max += 3; + max += CARDBUS_RESERVE_BUSNR; } /* * Set the subordinate bus number to its real value. @@ -358,6 +366,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max child->subordinate = max; pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } + sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); return max; @@ -391,17 +400,20 @@ int pci_setup_device(struct pci_dev * dev) { u32 class; - sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - sprintf(dev->dev.name, "PCI device %04x:%04x", dev->vendor, dev->device); + sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + sprintf(dev->dev.name, "PCI device %04x:%04x", + dev->vendor, dev->device); + INIT_LIST_HEAD(&dev->pools); - + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); class >>= 8; /* upper 3 bytes */ dev->class = class; class >>= 8; - DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, - dev->vendor, dev->device, class, dev->hdr_type); + DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, + dev->devfn, dev->vendor, dev->device, class, dev->hdr_type); /* "Unknown power state" */ dev->current_state = 4; @@ -468,7 +480,8 @@ pci_scan_device(struct pci_bus *bus, int devfn) return NULL; /* some broken boards return 0 or ~0 if a slot is empty: */ - if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) + if (l == 0xffffffff || l == 0x00000000 || + l == 0x0000ffff || l == 0xffff0000) return NULL; dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); @@ -520,11 +533,14 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) struct pci_dev *dev; dev = pci_scan_device(bus, devfn); - if (!dev) - continue; - - if (func != 0) + if (func == 0) { + if (!dev) + break; + } else { + if (!dev) + continue; dev->multifunction = 1; + } /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); @@ -647,7 +663,8 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, if (b) { b->sysdata = sysdata; b->ops = ops; - b->subordinate = pci_do_scan_bus(b); + b->subordinate = pci_scan_child_bus(b); + pci_bus_add_devices(b); } return b; } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index b796e2270a65..172174f9c61e 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -72,40 +72,29 @@ pbus_assign_resources_sorted(struct pci_bus *bus) requires that if there is no I/O ports or memory behind the bridge, corresponding range must be turned off by writing base value greater than limit to the bridge's base/limit registers. */ -static void __devinit -pci_setup_bridge(struct pci_bus *bus) +static void __devinit pci_setup_bridge(struct pci_bus *bus) { - struct pbus_set_ranges_data ranges; struct pci_dev *bridge = bus->self; + struct pci_bus_region region; u32 l; - if (!bridge || (bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI) - return; - - ranges.io_start = bus->resource[0]->start; - ranges.io_end = bus->resource[0]->end; - ranges.mem_start = bus->resource[1]->start; - ranges.mem_end = bus->resource[1]->end; - ranges.prefetch_start = bus->resource[2]->start; - ranges.prefetch_end = bus->resource[2]->end; - pcibios_fixup_pbus_ranges(bus, &ranges); - DBGC((KERN_INFO "PCI: Bus %d, bridge: %s\n", bus->number, bridge->dev.name)); /* Set up the top and bottom of the PCI I/O segment for this bus. */ + pcibios_resource_to_bus(bridge, ®ion, bus->resource[0]); if (bus->resource[0]->flags & IORESOURCE_IO) { pci_read_config_dword(bridge, PCI_IO_BASE, &l); l &= 0xffff0000; - l |= (ranges.io_start >> 8) & 0x00f0; - l |= ranges.io_end & 0xf000; + l |= (region.start >> 8) & 0x00f0; + l |= region.end & 0xf000; /* Set up upper 16 bits of I/O base/limit. */ pci_write_config_word(bridge, PCI_IO_BASE_UPPER16, - ranges.io_start >> 16); + region.start >> 16); pci_write_config_word(bridge, PCI_IO_LIMIT_UPPER16, - ranges.io_end >> 16); + region.end >> 16); DBGC((KERN_INFO " IO window: %04lx-%04lx\n", - ranges.io_start, ranges.io_end)); + region.start, region.end)); } else { /* Clear upper 16 bits of I/O base/limit. */ @@ -117,11 +106,12 @@ pci_setup_bridge(struct pci_bus *bus) /* Set up the top and bottom of the PCI Memory segment for this bus. */ + pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]); if (bus->resource[1]->flags & IORESOURCE_MEM) { - l = (ranges.mem_start >> 16) & 0xfff0; - l |= ranges.mem_end & 0xfff00000; + l = (region.start >> 16) & 0xfff0; + l |= region.end & 0xfff00000; DBGC((KERN_INFO " MEM window: %08lx-%08lx\n", - ranges.mem_start, ranges.mem_end)); + region.start, region.end)); } else { l = 0x0000fff0; @@ -134,11 +124,12 @@ pci_setup_bridge(struct pci_bus *bus) pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); /* Set up PREF base/limit. */ + pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { - l = (ranges.prefetch_start >> 16) & 0xfff0; - l |= ranges.prefetch_end & 0xfff00000; + l = (region.start >> 16) & 0xfff0; + l |= region.end & 0xfff00000; DBGC((KERN_INFO " PREFETCH window: %08lx-%08lx\n", - ranges.prefetch_start, ranges.prefetch_end)); + region.start, region.end)); } else { l = 0x0000fff0; @@ -284,7 +275,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) order = 0; /* Exclude ranges with size > align from calculation of the alignment. */ - if (size == align) + if (r_size == align) aligns[order] += align; if (order > max_order) max_order = order; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 3331a411db7b..4989b88b45d3 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -33,6 +33,59 @@ #endif +static void +pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) +{ + struct pci_bus_region region; + u32 new, check, mask; + int reg; + + pcibios_resource_to_bus(dev, ®ion, res); + + DBGC((KERN_ERR " got res [%lx:%lx] bus [%lx:%lx] for " + "resource %d of %s\n", res->start, res->end, + region.start, region.end, resno, dev->dev.name)); + + new = region.start | (res->flags & PCI_REGION_FLAG_MASK); + if (res->flags & IORESOURCE_IO) + mask = (u32)PCI_BASE_ADDRESS_IO_MASK; + else + mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; + + if (resno < 6) { + reg = PCI_BASE_ADDRESS_0 + 4 * resno; + } else if (resno == PCI_ROM_RESOURCE) { + new |= res->flags & PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Hmm, non-standard resource. */ + printk("PCI: trying to set non-standard region %s/%d\n", + dev->slot_name, resno); + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + + if ((new ^ check) & mask) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resno, + new, check); + } + + if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == + (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) { + new = 0; /* currently everyone zeros the high address */ + pci_write_config_dword(dev, reg + 4, new); + pci_read_config_dword(dev, reg + 4, &check); + if (check != new) { + printk(KERN_ERR "PCI: Error updating region " + "%s/%d (high %08x != %08x)\n", + dev->slot_name, resno, new, check); + } + } +} + int __init pci_claim_resource(struct pci_dev *dev, int resource) { @@ -89,10 +142,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", resno, res->start, res->end, dev->slot_name); } else { - DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", - res->start, res->end, i, dev->dev.name)); - /* Update PCI config space. */ - pcibios_update_resource(dev, res->parent, res, resno); + pci_update_resource(dev, res, resno); } return ret; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 95af5d5f81d0..9f5ace7ae222 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -679,27 +679,26 @@ static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int */ static Scsi_Host_Template driver_template = { - module: THIS_MODULE, - name: "AAC", - proc_info: aac_procinfo, - detect: aac_detect, - release: aac_release, - info: aac_driverinfo, - ioctl: aac_ioctl, - queuecommand: aac_queuecommand, - bios_param: aac_biosparm, - slave_configure: aac_slave_configure, - can_queue: AAC_NUM_IO_FIB, - this_id: 16, - sg_tablesize: 16, - max_sectors: 128, - cmd_per_lun: AAC_NUM_IO_FIB, - eh_abort_handler: aac_eh_abort, - eh_device_reset_handler:aac_eh_device_reset, - eh_bus_reset_handler: aac_eh_bus_reset, - eh_host_reset_handler: aac_eh_reset, - - use_clustering: ENABLE_CLUSTERING, + .module = THIS_MODULE, + .name = "AAC", + .proc_info = aac_procinfo, + .detect = aac_detect, + .release = aac_release, + .info = aac_driverinfo, + .ioctl = aac_ioctl, + .queuecommand = aac_queuecommand, + .bios_param = aac_biosparm, + .slave_configure = aac_slave_configure, + .can_queue = AAC_NUM_IO_FIB, + .this_id = 16, + .sg_tablesize = 16, + .max_sectors = 128, + .cmd_per_lun = 1, + .eh_abort_handler = aac_eh_abort, + .eh_device_reset_handler = aac_eh_device_reset, + .eh_bus_reset_handler = aac_eh_bus_reset, + .eh_host_reset_handler = aac_eh_reset, + .use_clustering = ENABLE_CLUSTERING, }; #include "scsi_module.c" diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h index c8098010e86b..f5f428711b34 100644 --- a/drivers/scsi/hosts.h +++ b/drivers/scsi/hosts.h @@ -549,6 +549,7 @@ struct Scsi_Device_Template void (*detach)(Scsi_Device *); int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code. Selects command for blkdevs */ + void (*rescan)(Scsi_Device *); struct device_driver scsi_driverfs_driver; }; diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 1c5ca7e8ad02..8ccfb9e3642b 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -606,7 +606,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned { unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; - long startwait = jiffies; + unsigned long startwait = jiffies; #if DEBUG int dbg = debugging; char * name = tape_name(STp); @@ -673,7 +673,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi { unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; - long startwait = jiffies; + unsigned long startwait = jiffies; #if DEBUG int dbg = debugging; char * name = tape_name(STp); @@ -777,8 +777,8 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) #define OSST_POLL_PER_SEC 10 static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to) { - long startwait = jiffies; - char * name = tape_name(STp); + unsigned long startwait = jiffies; + char * name = tape_name(STp); #if DEBUG char notyetprinted = 1; #endif @@ -1288,7 +1288,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num) - (nframes + pending - 1) * blks_per_frame; char * name = tape_name(STp); - long startwait = jiffies; + unsigned long startwait = jiffies; #if DEBUG int dbg = debugging; #endif @@ -1477,7 +1477,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int expected = 0; int attempts = 1000 / skip; int flag = 1; - long startwait = jiffies; + unsigned long startwait = jiffies; #if DEBUG int dbg = debugging; #endif diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 7b966c63bb9e..3cf04a66dc5d 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -836,14 +836,22 @@ static int isp2x00_make_portdb(struct Scsi_Host *host) short param[8]; int i, j; - struct id_name_map temp[QLOGICFC_MAX_ID + 1]; + struct id_name_map *map; /* base of array [QLOGICFC_MAX_ID + 1] */ + struct id_name_map *mapx; /* array entry pointer */ struct isp2x00_hostdata *hostdata; - isp2x00_disable_irqs(host); - - memset(temp, 0, sizeof(temp)); hostdata = (struct isp2x00_hostdata *) host->hostdata; + map = kmalloc((QLOGICFC_MAX_ID + 1) * sizeof(struct id_name_map), GFP_ATOMIC); + if (!map) { + printk("qlogicfc%d : error getting memory -- cannot make port database.\n", + hostdata->host_id); + goto fini; + } + memset(map, 0, (QLOGICFC_MAX_ID + 1) * sizeof(struct id_name_map)); + + isp2x00_disable_irqs(host); + #if ISP2x00_FABRIC for (i = 0x81; i < QLOGICFC_MAX_ID; i++) { param[0] = MBOX_PORT_LOGOUT; @@ -868,72 +876,74 @@ static int isp2x00_make_portdb(struct Scsi_Host *host) if (param[0] == MBOX_COMMAND_COMPLETE) { hostdata->port_id = ((u_int) param[3]) << 16; hostdata->port_id |= param[2]; - temp[0].loop_id = param[1]; - temp[0].wwn = hostdata->wwn; + map->loop_id = param[1]; + map->wwn = hostdata->wwn; } else { printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id); } - for (i = 0; i <=QLOGICFC_MAX_ID; i++) - temp[i].loop_id = temp[0].loop_id; + for (i = 0, mapx = map; i <= QLOGICFC_MAX_ID; i++, mapx++) + mapx->loop_id = map->loop_id; - for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) { + for (i = 0, j = 1, mapx = map + 1; i <= QLOGICFC_MAX_LOOP_ID; i++) { param[0] = MBOX_GET_PORT_NAME; param[1] = (i << 8) & 0xff00; isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { - temp[j].loop_id = i; - temp[j].wwn = ((u64) (param[2] & 0xff)) << 56; - temp[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48; - temp[j].wwn |= ((u64) (param[3] & 0xff)) << 40; - temp[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32; - temp[j].wwn |= ((u64) (param[6] & 0xff)) << 24; - temp[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16; - temp[j].wwn |= ((u64) (param[7] & 0xff)) << 8; - temp[j].wwn |= ((u64) ((param[7] >> 8) & 0xff)); + mapx->loop_id = i; + mapx->wwn = ((u64) (param[2] & 0xff)) << 56; + mapx->wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48; + mapx->wwn |= ((u64) (param[3] & 0xff)) << 40; + mapx->wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32; + mapx->wwn |= ((u64) (param[6] & 0xff)) << 24; + mapx->wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16; + mapx->wwn |= ((u64) (param[7] & 0xff)) << 8; + mapx->wwn |= ((u64) ((param[7] >> 8) & 0xff)); j++; - + mapx++; } } #if ISP2x00_FABRIC - isp2x00_init_fabric(host, temp, j); + isp2x00_init_fabric(host, map, j); #endif - for (i = 0; i <= QLOGICFC_MAX_ID; i++) { - if (temp[i].wwn != hostdata->port_db[i].wwn) { - for (j = 0; j <= QLOGICFC_MAX_ID; j++) { - if (temp[j].wwn == hostdata->port_db[i].wwn) { - hostdata->port_db[i].loop_id = temp[j].loop_id; + for (i = 0, mapx = map; i <= QLOGICFC_MAX_ID; i++, mapx++) { + struct id_name_map *tmap; /* second array entry pointer */ + if (mapx->wwn != hostdata->port_db[i].wwn) { + for (j = 0, tmap = map; j <= QLOGICFC_MAX_ID; j++, tmap++) { + if (tmap->wwn == hostdata->port_db[i].wwn) { + hostdata->port_db[i].loop_id = tmap->loop_id; break; } } if (j == QLOGICFC_MAX_ID + 1) - hostdata->port_db[i].loop_id = temp[0].loop_id; + hostdata->port_db[i].loop_id = map->loop_id; for (j = 0; j <= QLOGICFC_MAX_ID; j++) { - if (hostdata->port_db[j].wwn == temp[i].wwn || !hostdata->port_db[j].wwn) { + if (hostdata->port_db[j].wwn == mapx->wwn || !hostdata->port_db[j].wwn) { break; } } if (j == QLOGICFC_MAX_ID + 1) printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id); if (!hostdata->port_db[j].wwn) { - hostdata->port_db[j].loop_id = temp[i].loop_id; - hostdata->port_db[j].wwn = temp[i].wwn; + hostdata->port_db[j].loop_id = mapx->loop_id; + hostdata->port_db[j].wwn = mapx->wwn; } } else - hostdata->port_db[i].loop_id = temp[i].loop_id; + hostdata->port_db[i].loop_id = mapx->loop_id; } isp2x00_enable_irqs(host); - + kfree(map); +fini: return 0; } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 5632d669ca7a..78577c181884 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -96,12 +96,7 @@ unsigned long scsi_pid; Scsi_Cmnd *last_cmnd; static unsigned long serial_number; -struct softscsi_data { - Scsi_Cmnd *head; - Scsi_Cmnd *tail; -}; - -static struct softscsi_data softscsi_data[NR_CPUS] __cacheline_aligned; +static struct list_head done_q[NR_CPUS] __cacheline_aligned; /* * List of all highlevel drivers. @@ -637,79 +632,60 @@ void scsi_init_cmd_from_req(Scsi_Cmnd * SCpnt, Scsi_Request * SRpnt) } /** - * scsi_done - Mark this command as done - * @SCpnt: The SCSI Command which we think we've completed. + * scsi_done - Enqueue the finished SCSI command into the done queue. + * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives + * ownership back to SCSI Core -- i.e. the LLDD has finished with it. * - * This function is the mid-level interrupt routine, which decides how - * to handle error conditions. Each invocation of this function must - * do one and *only* one of the following: + * This function is the mid-level's (SCSI Core) interrupt routine, which + * regains ownership of the SCSI command (de facto) from a LLDD, and enqueues + * the command to the done queue for further processing. * - * 1) Insert command in BH queue. - * 2) Activate error handler for host. + * This is the producer of the done queue who enqueues at the tail. * - * There is no longer a problem with stack overflow. Interrupts queue - * Scsi_Cmnd on a per-CPU queue and the softirq handler removes them - * from the queue one at a time. - * - * This function is sometimes called from interrupt context, but sometimes - * from task context. + * This function is interrupt context safe. */ -void scsi_done(Scsi_Cmnd * SCpnt) +void scsi_done(struct scsi_cmnd *cmd) { + int cpu; unsigned long flags; - int cpu, tstatus; - struct softscsi_data *queue; + struct list_head *pdone_q; /* * We don't have to worry about this one timing out any more. - */ - tstatus = scsi_delete_timer(SCpnt); - - /* - * If we are unable to remove the timer, it means that the command - * has already timed out. In this case, we have no choice but to + * If we are unable to remove the timer, then the command + * has already timed out. In which case, we have no choice but to * let the timeout function run, as we have no idea where in fact * that function could really be. It might be on another processor, * etc, etc. */ - if (!tstatus) { + if (!scsi_delete_timer(cmd)) return; - } /* Set the serial numbers back to zero */ - SCpnt->serial_number = 0; - SCpnt->serial_number_at_timeout = 0; - SCpnt->state = SCSI_STATE_BHQUEUE; - SCpnt->owner = SCSI_OWNER_BH_HANDLER; - SCpnt->bh_next = NULL; + cmd->serial_number = 0; + cmd->serial_number_at_timeout = 0; + cmd->state = SCSI_STATE_BHQUEUE; + cmd->owner = SCSI_OWNER_BH_HANDLER; /* - * Next, put this command in the softirq queue. - * - * This is a per-CPU queue, so we just disable local interrupts + * Next, enqueue the command into the done queue. + * It is a per-CPU queue, so we just disable local interrupts * and need no spinlock. */ - local_irq_save(flags); cpu = smp_processor_id(); - queue = &softscsi_data[cpu]; - - if (!queue->head) { - queue->head = SCpnt; - queue->tail = SCpnt; - } else { - queue->tail->bh_next = SCpnt; - queue->tail = SCpnt; - } - + pdone_q = &done_q[cpu]; + list_add_tail(&cmd->eh_entry, pdone_q); cpu_raise_softirq(cpu, SCSI_SOFTIRQ); local_irq_restore(flags); } /** - * scsi_softirq - Perform post-interrupt handling for completed commands + * scsi_softirq - Perform post-interrupt processing of finished SCSI commands. + * + * This is the consumer of the done queue. * * This is called with all interrupts enabled. This should reduce * interrupt latency, stack depth, and reentrancy of the low-level @@ -717,88 +693,92 @@ void scsi_done(Scsi_Cmnd * SCpnt) */ static void scsi_softirq(struct softirq_action *h) { - int cpu = smp_processor_id(); - struct softscsi_data *queue = &softscsi_data[cpu]; + LIST_HEAD(local_q); - while (queue->head) { - Scsi_Cmnd *SCpnt, *SCnext; + local_irq_disable(); + list_splice_init(&done_q[smp_processor_id()], &local_q); + local_irq_enable(); - local_irq_disable(); - SCpnt = queue->head; - queue->head = NULL; - local_irq_enable(); + while (!list_empty(&local_q)) { + struct scsi_cmnd *cmd = list_entry(local_q.next, + struct scsi_cmnd, eh_entry); + list_del_init(&cmd->eh_entry); - for (; SCpnt; SCpnt = SCnext) { - SCnext = SCpnt->bh_next; + switch (scsi_decide_disposition(cmd)) { + case SUCCESS: + /* + * Add to BH queue. + */ + SCSI_LOG_MLCOMPLETE(3, + printk("Command finished %d %d " + "0x%x\n", + cmd->device->host->host_busy, + cmd->device->host->host_failed, + cmd->result)); + + scsi_finish_command(cmd); + break; + case NEEDS_RETRY: + /* + * We only come in here if we want to retry a + * command. The test to see whether the + * command should be retried should be keeping + * track of the number of tries, so we don't + * end up looping, of course. + */ + SCSI_LOG_MLCOMPLETE(3, printk("Command needs retry " + "%d %d 0x%x\n", + cmd->device->host->host_busy, + cmd->device->host->host_failed, + cmd->result)); - switch (scsi_decide_disposition(SCpnt)) { - case SUCCESS: - /* - * Add to BH queue. - */ - SCSI_LOG_MLCOMPLETE(3, printk("Command finished %d %d 0x%x\n", SCpnt->device->host->host_busy, - SCpnt->device->host->host_failed, - SCpnt->result)); + scsi_retry_command(cmd); + break; + case ADD_TO_MLQUEUE: + /* + * This typically happens for a QUEUE_FULL + * message - typically only when the queue + * depth is only approximate for a given + * device. Adding a command to the queue for + * the device will prevent further commands + * from being sent to the device, so we + * shouldn't end up with tons of things being + * sent down that shouldn't be. + */ + SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as " + "device queue full, " + "put on ml queue %p\n", + cmd)); + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); + break; + default: + /* + * Here we have a fatal error of some sort. + * Turn it over to the error handler. + */ + SCSI_LOG_MLCOMPLETE(3, + printk("Command failed %p %x " + "busy=%d failed=%d\n", + cmd, cmd->result, + cmd->device->host->host_busy, + cmd->device->host->host_failed)); - scsi_finish_command(SCpnt); - break; - case NEEDS_RETRY: - /* - * We only come in here if we want to retry a - * command. The test to see whether the - * command should be retried should be keeping - * track of the number of tries, so we don't - * end up looping, of course. - */ - SCSI_LOG_MLCOMPLETE(3, printk("Command needs retry %d %d 0x%x\n", SCpnt->device->host->host_busy, - SCpnt->device->host->host_failed, SCpnt->result)); - - scsi_retry_command(SCpnt); - break; - case ADD_TO_MLQUEUE: - /* - * This typically happens for a QUEUE_FULL - * message - typically only when the queue - * depth is only approximate for a given - * device. Adding a command to the queue for - * the device will prevent further commands - * from being sent to the device, so we - * shouldn't end up with tons of things being - * sent down that shouldn't be. - */ - SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as device queue full, put on ml queue %p\n", - SCpnt)); - scsi_queue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY); - break; - default: - /* - * Here we have a fatal error of some sort. - * Turn it over to the error handler. - */ - SCSI_LOG_MLCOMPLETE(3, - printk("Command failed %p %x busy=%d failed=%d\n", - SCpnt, SCpnt->result, - SCpnt->device->host->host_busy, - SCpnt->device->host->host_failed)); + /* + * Dump the sense information too. + */ + if ((status_byte(cmd->result)&CHECK_CONDITION) != 0) { + SCSI_LOG_MLCOMPLETE(3, print_sense("bh", cmd)); + } + if (!scsi_eh_scmd_add(cmd, 0)) { /* - * Dump the sense information too. + * We only get here if the error + * recovery thread has died. */ - if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) { - SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt)); - } - - if (!scsi_eh_scmd_add(SCpnt, 0)) - { - /* - * We only get here if the error - * recovery thread has died. - */ - scsi_finish_command(SCpnt); - } - } /* switch */ - } /* for(; SCpnt...) */ - } /* while(queue->head) */ + scsi_finish_command(cmd); + } + } + } } /* @@ -1284,6 +1264,21 @@ void scsi_detach_device(struct scsi_device *sdev) up_read(&scsi_devicelist_mutex); } +void scsi_rescan_device(struct scsi_device *sdev) +{ + struct Scsi_Device_Template *sdt; + + down_read(&scsi_devicelist_mutex); + list_for_each_entry(sdt, &scsi_devicelist, list) { + if (!try_module_get(sdt->module)) + continue; + if (*sdt->rescan) + (*sdt->rescan)(sdev); + module_put(sdt->module); + } + up_read(&scsi_devicelist_mutex); +} + int scsi_device_get(struct scsi_device *sdev) { if (!try_module_get(sdev->host->hostt->module)) @@ -1481,7 +1476,7 @@ __setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); static int __init init_scsi(void) { - int error; + int error, i; error = scsi_init_queue(); if (error) @@ -1496,6 +1491,9 @@ static int __init init_scsi(void) if (error) goto cleanup_devlist; + for (i = 0; i < NR_CPUS; i++) + INIT_LIST_HEAD(&done_q[i]); + scsi_host_init(); devfs_mk_dir(NULL, "scsi", NULL); open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL); diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index 12d9783b9c77..96f92ae21c32 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -741,8 +741,7 @@ struct scsi_cmnd { * abort, etc are in process. */ unsigned volatile char internal_timeout; - struct scsi_cmnd *bh_next; /* To enumerate the commands waiting - to be processed. */ + unsigned char cmd_len; unsigned char old_cmd_len; unsigned char sc_data_direction; diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index e16e70bcad90..eed0e0583619 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -11,7 +11,7 @@ * (or disk like devices) sharing a common amount of RAM * * - * For documentation see http://www.torque.net/sg/sdebug.html + * For documentation see http://www.torque.net/sg/sdebug25.html * * D. Gilbert (dpg) work for Magneto-Optical device test [20010421] * dpg: work for devfs large number of disks [20010809] @@ -54,38 +54,37 @@ #include "scsi_debug.h" -static const char * scsi_debug_version_str = "Version: 1.67 (20021221)"; - -#ifndef SCSI_CMD_READ_16 -#define SCSI_CMD_READ_16 0x88 -#endif -#ifndef SCSI_CMD_WRITE_16 -#define SCSI_CMD_WRITE_16 0x8a -#endif +static const char * scsi_debug_version_str = "Version: 1.68 (20030314)"; #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */ #define DEF_NUM_DEVS 1 #define DEF_DEV_SIZE_MB 8 -#define DEF_EVERY_NTH 100 +#define DEF_EVERY_NTH 0 #define DEF_DELAY 1 #define DEF_MAX_LUNS 2 #define DEF_SCSI_LEVEL 3 #define DEF_NUM_HOST 1 #define DEF_OPTS 0 -#define MAX_NUM_HOSTS 128 - /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 -#define SCSI_DEBUG_OPT_EVERY_NTH 4 +#define SCSI_DEBUG_OPT_TIMEOUT 4 +#define SCSI_DEBUG_OPT_RECOVERED_ERR 8 +/* When "every_nth" > 0 then modulo "every_nth" commands: + * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set + * - a RECOVERED_ERROR is simulated on successful read and write + * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + */ -#define OPT_MEDIUM_ERR_ADDR 0x1234 +/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this + * sector on read commands: */ +#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; -static int scsi_debug_num_devs = DEF_NUM_DEVS; +static int scsi_debug_num_devs = DEF_NUM_DEVS; /* max devs per host */ static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_every_nth = DEF_EVERY_NTH; static int scsi_debug_cmnd_count = 0; @@ -112,25 +111,28 @@ static int sdebug_sectors_per; /* sectors per cylinder */ #define SECT_SIZE (1 << POW2_SECT_SIZE) #define SECT_SIZE_PER(TGT) SECT_SIZE -struct sdebug_host_info { - struct Scsi_Host *shost; - struct device *dev; -}; - -struct sdebug_host_info * scsi_debug_hosts; - #define SDEBUG_SENSE_LEN 32 struct sdebug_dev_info { + struct list_head dev_list; unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ unsigned int channel; unsigned int target; unsigned int lun; - struct Scsi_Host *host; + struct sdebug_host_info *sdbg_host; char reset; char used; }; -static struct sdebug_dev_info * devInfop; + +struct sdebug_host_info { + struct list_head host_list; + struct Scsi_Host *shost; + struct device *dev; + struct list_head dev_info_list; +}; + +static LIST_HEAD(sdebug_host_list); +static spinlock_t sdebug_host_list_lock = SPIN_LOCK_UNLOCKED; typedef void (* done_funct_t) (struct scsi_cmnd *); @@ -156,11 +158,20 @@ static spinlock_t queued_arr_lock = SPIN_LOCK_UNLOCKED; static rwlock_t atomic_rw = RW_LOCK_UNLOCKED; static char sdebug_proc_name[] = "scsi_debug"; + +static int sdebug_driver_probe(struct device *); +static int sdebug_driver_remove(struct device *); + static struct device_driver sdebug_driverfs_driver = { - .name = sdebug_proc_name, - .devclass = &shost_devclass, + .name = sdebug_proc_name, + .probe = sdebug_driver_probe, + .remove = sdebug_driver_remove, + .devclass = &shost_devclass, }; +static const int check_condition_result = + (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; + /* function declarations */ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, int bufflen, struct sdebug_dev_info * devip); @@ -174,7 +185,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, 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(struct scsi_cmnd *scmd); +static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev); static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, int asc, int asq, int inbandLen); static int check_reset(struct scsi_cmnd * SCpnt, @@ -189,15 +200,29 @@ static int inquiry_evpd_83(unsigned char * arr, int dev_id_num, const char * dev_id_str, int dev_id_str_len); static void do_create_driverfs_files(void); static void do_remove_driverfs_files(void); -static void sdebug_add_shost(int num); -static void sdebug_remove_shost(int num); -static int sdebug_add_adapter(int num); -static void sdebug_remove_adapter(int num); +static int sdebug_add_adapter(void); +static void sdebug_remove_adapter(void); static struct device pseudo_primary; static struct bus_type pseudo_lld_bus; -int scsi_debug_register_driver(struct device_driver *); -int scsi_debug_unregister_driver(struct device_driver *); +static int scsi_debug_register_driver(struct device_driver *); +static int scsi_debug_unregister_driver(struct device_driver *); + +static struct sdebug_host_info * + sdebug_shost_to_host_info(struct Scsi_Host *shost) +{ + struct sdebug_host_info * sdbg_host, * found = NULL; + + spin_lock(&sdebug_host_list_lock); + list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { + if (sdbg_host->shost == shost) { + found = sdbg_host; + break; + } + } + spin_unlock(&sdebug_host_list_lock); + return found; +} static unsigned char * scatg2virt(const struct scatterlist * sclp) { @@ -222,6 +247,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) unsigned long capac; struct sdebug_dev_info * devip = NULL; unsigned char * sbuff; + int inj_recovered = 0; if (done == NULL) return 0; /* assume mid level reprocessing command */ @@ -250,16 +276,18 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) if (SCpnt->device->lun >= scsi_debug_max_luns) return schedule_resp(SCpnt, NULL, done, DID_NO_CONNECT << 16, 0); - devip = devInfoReg(SCpnt); + devip = devInfoReg(SCpnt->device); 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) && + if ((scsi_debug_every_nth > 0) && (++scsi_debug_cmnd_count >= scsi_debug_every_nth)) { scsi_debug_cmnd_count =0; - return 0; /* ignore command causing timeout */ + if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) + return 0; /* ignore command causing timeout */ + else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) + inj_recovered = 1; /* to reads and writes below */ } switch (*cmd) { @@ -269,8 +297,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) case REQUEST_SENSE: /* mandatory */ /* Since this driver indicates autosense by placing the * sense buffer in the scsi_cmnd structure in the response - * (when CHECK_CONDITION is set), the mid level shouldn't - * need to call REQUEST_SENSE */ + * (when SAM_STAT_CHECK_CONDITION is set), the mid level + * shouldn't need to call REQUEST_SENSE */ if (devip) { sbuff = devip->sense_buff; memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? @@ -326,14 +354,14 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) buff[7] = SECT_SIZE_PER(target) & 0xff; } break; - case SCSI_CMD_READ_16: /* SBC-2 */ + case READ_16: case READ_12: case READ_10: case READ_6: if ((errsts = check_reset(SCpnt, devip))) break; upper_blk = 0; - if ((*cmd) == SCSI_CMD_READ_16) { + if ((*cmd) == READ_16) { upper_blk = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); block = cmd[9] + (cmd[8] << 8) + @@ -355,18 +383,22 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) num = cmd[4]; } errsts = resp_read(SCpnt, upper_blk, block, num, devip); + if (inj_recovered && (0 == errsts)) { + mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14); + errsts = check_condition_result; + } break; case REPORT_LUNS: errsts = resp_report_luns(cmd, buff, bufflen, devip); break; - case SCSI_CMD_WRITE_16: /* SBC-2 */ + case WRITE_16: case WRITE_12: case WRITE_10: case WRITE_6: if ((errsts = check_reset(SCpnt, devip))) break; upper_blk = 0; - if ((*cmd) == SCSI_CMD_WRITE_16) { + if ((*cmd) == WRITE_16) { upper_blk = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); block = cmd[9] + (cmd[8] << 8) + @@ -388,6 +420,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) num = cmd[4]; } errsts = resp_write(SCpnt, upper_blk, block, num, devip); + if (inj_recovered && (0 == errsts)) { + mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14); + errsts = check_condition_result; + } break; case MODE_SENSE: case MODE_SENSE_10: @@ -400,7 +436,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) if ((errsts = check_reset(SCpnt, devip))) break; mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); - errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + errsts = check_condition_result; break; } return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay); @@ -420,7 +456,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) if (devip->reset) { devip->reset = 0; mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } return 0; } @@ -481,12 +517,12 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, arr[0] = pq_pdt; if (0x2 & cmd[1]) { /* CMDDT bit set */ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } else if (0x1 & cmd[1]) { /* EVPD bit set */ int dev_id_num, len; char dev_id_str[6]; - dev_id_num = ((devip->host->host_no + 1) * 2000) + + dev_id_num = ((devip->sdbg_host->shost->host_no + 1) * 2000) + (devip->target * 1000) + devip->lun; len = snprintf(dev_id_str, 6, "%d", dev_id_num); len = (len > 6) ? 6 : len; @@ -506,7 +542,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, } else { /* Illegal request, invalid field in cdb */ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } memcpy(buff, arr, min_len); return 0; @@ -619,7 +655,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); if (0x3 == pcontrol) { /* Saving values not supported */ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; if (msense_6) { @@ -662,7 +698,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, break; default: mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } if (msense_6) arr[0] = offset - 1; @@ -686,14 +722,14 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, if (upper_blk || (block + num > sdebug_capacity)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && - (block >= OPT_MEDIUM_ERR_ADDR) && - (block < (OPT_MEDIUM_ERR_ADDR + num))) { + (block <= OPT_MEDIUM_ERR_ADDR) && + ((block + num) > OPT_MEDIUM_ERR_ADDR)) { mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14); /* claim unrecoverable read error */ - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } read_lock_irqsave(&atomic_rw, iflags); sgcount = 0; @@ -735,7 +771,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, if (upper_blk || (block + num > sdebug_capacity)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } write_lock_irqsave(&atomic_rw, iflags); @@ -776,7 +812,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff, alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); if ((alloc_len < 16) || (select_report > 2)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); + return check_condition_result; } if (bufflen > 3) { lun_cnt = min((int)(bufflen / sizeof(ScsiLun)), @@ -810,15 +846,24 @@ static void timer_intr_handler(unsigned long indx) return; } sqcp->in_use = 0; - if (sqcp->done_funct) + if (sqcp->done_funct) { + sqcp->a_cmnd->result = sqcp->scsi_result; sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */ + } sqcp->done_funct = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); } +static int scsi_debug_slave_alloc(struct scsi_device * sdp) +{ + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", + sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); + return 0; +} + static int scsi_debug_slave_configure(struct scsi_device * sdp) { - int k; struct sdebug_dev_info * devip; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) @@ -826,16 +871,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp) sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; - for (k = 0; k < scsi_debug_num_devs; ++k) { - devip = &devInfop[k]; - if ((devip->channel == sdp->channel) && - (devip->target == sdp->id) && - (devip->lun == sdp->lun) && - (devip->host == sdp->host)) { - sdp->hostdata = devip; - break; - } - } + devip = devInfoReg(sdp); + sdp->hostdata = devip; if (sdp->host->cmd_per_lun) scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, sdp->host->cmd_per_lun); @@ -852,43 +889,47 @@ static void scsi_debug_slave_destroy(struct scsi_device * sdp) sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (devip) { /* make this slot avaliable for re-use */ - memset(devip, 0, sizeof(struct sdebug_dev_info)); + devip->used = 0; sdp->hostdata = NULL; } } -static struct sdebug_dev_info * devInfoReg(struct scsi_cmnd *scmd) +static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) { - int k; - struct scsi_device * sdp = scmd->device; + struct sdebug_host_info * sdbg_host; + struct sdebug_dev_info * open_devip = NULL; struct sdebug_dev_info * devip = - (struct sdebug_dev_info *)sdp->hostdata; + (struct sdebug_dev_info *)sdev->hostdata; if (devip) return devip; - for (k = 0; k < scsi_debug_num_devs; ++k) { - devip = &devInfop[k]; - if ((devip->channel == scmd->device->channel) && - (devip->target == scmd->device->id) && - (devip->lun == scmd->device->lun) && - (devip->host == scmd->device->host)) - return devip; - } - for (k = 0; k < scsi_debug_num_devs; ++k) { - devip = &devInfop[k]; - if (!devip->used) { - devip->channel = scmd->device->channel; - devip->target = scmd->device->id; - devip->lun = scmd->device->lun; - devip->host = scmd->device->host; - devip->reset = 1; - devip->used = 1; - memset(devip->sense_buff, 0, SDEBUG_SENSE_LEN); - devip->sense_buff[0] = 0x70; - return devip; + sdbg_host = sdebug_shost_to_host_info(sdev->host); + if(! sdbg_host) { + printk(KERN_ERR "Unable to locate host info\n"); + return NULL; + } + list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { + if ((devip->used) && (devip->channel == sdev->channel) && + (devip->target == sdev->id) && + (devip->lun == sdev->lun)) + return devip; + else { + if ((!devip->used) && (!open_devip)) + open_devip = devip; } } - return NULL; + if (open_devip) { + open_devip->channel = sdev->channel; + open_devip->target = sdev->id; + open_devip->lun = sdev->lun; + open_devip->sdbg_host = sdbg_host; + open_devip->reset = 1; + open_devip->used = 1; + memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN); + open_devip->sense_buff[0] = 0x70; + return open_devip; + } + return NULL; } static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, @@ -946,7 +987,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) printk(KERN_INFO "scsi_debug: device_reset\n"); ++num_dev_resets; if (SCpnt) { - devip = devInfoReg(SCpnt); + devip = devInfoReg(SCpnt->device); if (devip) devip->reset = 1; } @@ -955,17 +996,21 @@ static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) { - struct scsi_device * sdp; - struct Scsi_Host * hp; - int k; + struct sdebug_host_info *sdbg_host; + struct sdebug_dev_info * dev_info; + struct scsi_device * sdp; + struct Scsi_Host * hp; 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 = SCpnt->device->host))) { - for (k = 0; k < scsi_debug_num_devs; ++k) { - if (hp == devInfop[k].host) - devInfop[k].reset = 1; + if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { + sdbg_host = sdebug_shost_to_host_info(hp); + if (sdbg_host) { + list_for_each_entry(dev_info, + &sdbg_host->dev_info_list, + dev_list) + dev_info->reset = 1; } } return SUCCESS; @@ -973,15 +1018,20 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) { - int k; + struct sdebug_host_info * sdbg_host; + struct sdebug_dev_info * dev_info; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: host_reset\n"); ++num_host_resets; - for (k = 0; k < scsi_debug_num_devs; ++k) - devInfop[k].reset = 1; + spin_lock(&sdebug_host_list_lock); + list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { + list_for_each_entry(dev_info, &sdbg_host->dev_info_list, + dev_list) + dev_info->reset = 1; + } + spin_unlock(&sdebug_host_list_lock); stop_all_queued(); - return SUCCESS; } @@ -1063,7 +1113,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd, } if (cmnd && devip) { /* simulate autosense by this driver */ - if (CHECK_CONDITION == status_byte(scsi_result)) + if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff)) memcpy(cmnd->sense_buffer, devip->sense_buff, (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ? SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE); @@ -1099,6 +1149,8 @@ static int schedule_resp(struct scsi_cmnd * cmnd, sqcp->cmnd_timer.expires = jiffies + delta_jiff; add_timer(&sqcp->cmnd_timer); spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (cmnd) + cmnd->result = 0; return 0; } } @@ -1120,7 +1172,7 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(num_devs, "number of SCSI devices to simulate"); +MODULE_PARM_DESC(num_devs, "number of SCSI devices per host to simulate"); MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs"); @@ -1163,7 +1215,7 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset, if (1 != sscanf(arr, "%d", &pos)) return -EINVAL; scsi_debug_opts = pos; - if (SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts) + if (scsi_debug_every_nth > 0) scsi_debug_cmnd_count = 0; return length; } @@ -1192,12 +1244,12 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset, return len; } -static ssize_t sdebug_delay_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "%d\n", scsi_debug_delay); + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); } -static ssize_t sdebug_delay_write(struct device_driver * ddp, +static ssize_t sdebug_delay_store(struct device_driver * ddp, const char * buf, size_t count) { int delay; @@ -1211,15 +1263,15 @@ static ssize_t sdebug_delay_write(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_read, - sdebug_delay_write) +DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, + sdebug_delay_store) -static ssize_t sdebug_opts_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "0x%x\n", scsi_debug_opts); + return snprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); } -static ssize_t sdebug_opts_write(struct device_driver * ddp, +static ssize_t sdebug_opts_store(struct device_driver * ddp, const char * buf, size_t count) { int opts; @@ -1237,50 +1289,76 @@ static ssize_t sdebug_opts_write(struct device_driver * ddp, return -EINVAL; opts_done: scsi_debug_opts = opts; + scsi_debug_cmnd_count = 0; return count; } -DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_read, - sdebug_opts_write) +DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, + sdebug_opts_store) -static ssize_t sdebug_num_devs_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_num_devs_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "%d\n", scsi_debug_num_devs); + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_devs); } -DRIVER_ATTR(num_devs, S_IRUGO, sdebug_num_devs_read, NULL) +static ssize_t sdebug_num_devs_store(struct device_driver * ddp, + const char * buf, size_t count) +{ + int n; + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { + scsi_debug_num_devs = n; + return count; + } + return -EINVAL; +} +DRIVER_ATTR(num_devs, S_IRUGO | S_IWUSR, sdebug_num_devs_show, + sdebug_num_devs_store) -static ssize_t sdebug_dev_size_mb_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "%d\n", scsi_debug_dev_size_mb); + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); } -DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_read, NULL) +DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) -static ssize_t sdebug_every_nth_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); +} +static ssize_t sdebug_every_nth_store(struct device_driver * ddp, + const char * buf, size_t count) { - return sprintf(buf, "%d\n", scsi_debug_every_nth); + int nth; + + if ((count > 0) && (1 == sscanf(buf, "%d", &nth)) && (nth >= 0)) { + scsi_debug_every_nth = nth; + scsi_debug_cmnd_count = 0; + return count; + } + return -EINVAL; } -DRIVER_ATTR(every_nth, S_IRUGO, sdebug_every_nth_read, NULL) +DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show, + sdebug_every_nth_store) -static ssize_t sdebug_max_luns_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "%d\n", scsi_debug_max_luns); + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); } -DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_read, NULL) +DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_show, NULL) -static ssize_t sdebug_scsi_level_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "%d\n", scsi_debug_scsi_level); + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); } -DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_read, NULL) +DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) -static ssize_t sdebug_add_host_read(struct device_driver * ddp, char * buf) +static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) { - return sprintf(buf, "%d\n", scsi_debug_add_host); + return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); } -static ssize_t sdebug_add_host_write(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t sdebug_add_host_store(struct device_driver * ddp, + const char * buf, size_t count) { - int delta_hosts, k; + int delta_hosts; char work[20]; if (1 != sscanf(buf, "%10s", work)) @@ -1297,33 +1375,17 @@ static ssize_t sdebug_add_host_write(struct device_driver * ddp, } if (delta_hosts > 0) { do { - for (k = 0; k < MAX_NUM_HOSTS; ++k) { - if (NULL == scsi_debug_hosts[k].shost) { - sdebug_add_shost(k); - break; - } - } - if (k == MAX_NUM_HOSTS) - break; - ++scsi_debug_add_host; + sdebug_add_adapter(); } while (--delta_hosts); } else if (delta_hosts < 0) { do { - for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) { - if (scsi_debug_hosts[k].shost) { - sdebug_remove_shost(k); - break; - } - } - if (k < 0) - break; - --scsi_debug_add_host; + sdebug_remove_adapter(); } while (++delta_hosts); } return count; } -DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_read, - sdebug_add_host_write) +DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, + sdebug_add_host_store) static void do_create_driverfs_files() { @@ -1349,44 +1411,10 @@ static void do_remove_driverfs_files() driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); } -static void sdebug_add_shost(int num) -{ - struct Scsi_Host * hpnt; - int err; - - if (sdebug_add_adapter(num)){ - printk(KERN_ERR "sdebug_add_shost: sdebug_add_adapter failed\n"); - return; - } - hpnt = scsi_register(&sdebug_driver_template, 0); - if (NULL == hpnt) { - sdebug_remove_adapter(num); - printk(KERN_ERR "sdebug_add_shost: scsi_register failed\n"); - return; - } - err = scsi_add_host(hpnt, scsi_debug_hosts[num].dev); - if (err) { - printk(KERN_ERR "sdebug_add_shost: scsi_add_host failed\n"); - scsi_unregister(hpnt); - sdebug_remove_adapter(num); - return; - } - hpnt->max_lun = scsi_debug_max_luns; - - scsi_debug_hosts[num].shost = hpnt; -} - -static void sdebug_remove_shost(int num) -{ - scsi_remove_host(scsi_debug_hosts[num].shost); - scsi_unregister(scsi_debug_hosts[num].shost); - sdebug_remove_adapter(num); - scsi_debug_hosts[num].shost = NULL; -} - static int __init scsi_debug_init(void) { unsigned long sz; + int host_to_add; int k; sdebug_store_size = (unsigned long)scsi_debug_dev_size_mb * 1048576; @@ -1409,30 +1437,10 @@ static int __init scsi_debug_init(void) (sdebug_sectors_per * sdebug_heads); } - if (scsi_debug_num_devs > 0) { - sz = sizeof(struct sdebug_dev_info) * scsi_debug_num_devs; - devInfop = vmalloc(sz); - if (NULL == devInfop) { - printk(KERN_ERR "scsi_debug_init: out of memory\n"); - return -ENOMEM; - } - memset(devInfop, 0, sz); - } - - sz = sizeof(struct sdebug_host_info) * MAX_NUM_HOSTS; - scsi_debug_hosts = vmalloc(sz); - if (NULL == scsi_debug_hosts) { - printk(KERN_ERR "scsi_debug_init: out of memory 1\n"); - return -ENOMEM; - } - memset(scsi_debug_hosts, 0, sz); - sz = sdebug_store_size; fake_storep = vmalloc(sz); if (NULL == fake_storep) { printk(KERN_ERR "scsi_debug_init: out of memory, 1\n"); - if (devInfop) - vfree(devInfop); return -ENOMEM; } memset(fake_storep, 0, sz); @@ -1446,15 +1454,16 @@ static int __init scsi_debug_init(void) sdebug_driver_template.proc_name = (char *)sdebug_proc_name; - for (k = 0; (k < scsi_debug_add_host) && (k < MAX_NUM_HOSTS); k++) { - sdebug_add_shost(k); - if (NULL == scsi_debug_hosts[k].shost) { - printk(KERN_ERR "scsi_debug_init: " - "sdebug_add_shost failed k=%d\n", k); - break; - } - } - scsi_debug_add_host = k; // number of hosts actually present + host_to_add = scsi_debug_add_host; + scsi_debug_add_host = 0; + + for (k = 0; k < host_to_add; k++) { + if (sdebug_add_adapter()) { + printk(KERN_ERR "scsi_debug_init: " + "sdebug_add_adapter failed k=%d\n", k); + break; + } + } if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { printk(KERN_INFO "scsi_debug: ... built %d host(s)\n", @@ -1465,13 +1474,7 @@ static int __init scsi_debug_init(void) static void __exit scsi_debug_exit(void) { - int k; - - for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) { - if (scsi_debug_hosts[k].shost) { - sdebug_remove_shost(k); - } - } + /* free up adapters here ?? */ stop_all_queued(); do_remove_driverfs_files(); scsi_debug_unregister_driver(&sdebug_driverfs_driver); @@ -1479,8 +1482,6 @@ static void __exit scsi_debug_exit(void) device_unregister(&pseudo_primary); vfree(fake_storep); - if (devInfop) - vfree(devInfop); } device_initcall(scsi_debug_init); @@ -1502,7 +1503,7 @@ static struct bus_type pseudo_lld_bus = { .match = pseudo_lld_bus_match, }; -int scsi_debug_register_driver(struct device_driver *dev_driver) +static int scsi_debug_register_driver(struct device_driver *dev_driver) { dev_driver->bus = &pseudo_lld_bus; driver_register(dev_driver); @@ -1510,36 +1511,168 @@ int scsi_debug_register_driver(struct device_driver *dev_driver) return 0; } -int scsi_debug_unregister_driver(struct device_driver *dev_driver) +static int scsi_debug_unregister_driver(struct device_driver *dev_driver) { driver_unregister(dev_driver); return 0; } -static int sdebug_add_adapter(int num) +static void sdebug_release_adapter(struct device * dev) { - struct device * dev; + kfree(dev); +} - dev = kmalloc(sizeof(*dev),GFP_KERNEL); - if (NULL == dev) { - printk(KERN_ERR "%s: out of memory\n", __FUNCTION__); - return 1; - } +static int sdebug_add_adapter() +{ + struct device * dev; + int error; + + dev = kmalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) { + printk(KERN_ERR "%s: out of memory at line %d\n", + __FUNCTION__, __LINE__); + return -ENOMEM; + } + memset(dev, 0, sizeof(*dev)); - memset(dev, 0, sizeof(*dev)); - dev->bus = &pseudo_lld_bus; - dev->parent = &pseudo_primary; - sprintf(dev->name, "scsi debug adapter"); - sprintf(dev->bus_id, "adapter%d", num); + dev->bus = &pseudo_lld_bus; + dev->parent = &pseudo_primary; + dev->release = &sdebug_release_adapter; + sprintf(dev->name, "scsi debug adapter"); + sprintf(dev->bus_id, "adapter%d", scsi_debug_add_host); - device_register(dev); + error = device_register(dev); - scsi_debug_hosts[num].dev = dev; + if (error) + kfree(dev); + else + ++scsi_debug_add_host; - return 0; + return error; } -static void sdebug_remove_adapter(int num) +static void sdebug_remove_adapter() { - device_unregister(scsi_debug_hosts[num].dev); + struct sdebug_host_info * sdbg_host = NULL; + + spin_lock(&sdebug_host_list_lock); + if (!list_empty(&sdebug_host_list)) + sdbg_host = list_entry(sdebug_host_list.prev, + struct sdebug_host_info, host_list); + spin_unlock(&sdebug_host_list_lock); + + device_unregister(sdbg_host->dev); + --scsi_debug_add_host; +} + +static int sdebug_driver_probe(struct device * dev) +{ + int k; + int error = 0; + struct sdebug_host_info *sdbg_host; + struct sdebug_dev_info *sdbg_devinfo; + struct list_head *lh, *lh_sf; + struct Scsi_Host *hpnt; + + sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL); + if (NULL == sdbg_host) { + printk(KERN_ERR "%s: out of memory at line %d\n", + __FUNCTION__, __LINE__); + return -ENOMEM; + } + memset(sdbg_host, 0, sizeof(*sdbg_host)); + + INIT_LIST_HEAD(&sdbg_host->dev_info_list); + + for (k = 0; k < scsi_debug_num_devs; k++) { + sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); + if (NULL == sdbg_devinfo) { + printk(KERN_ERR "%s: out of memory at line %d\n", + __FUNCTION__, __LINE__); + error = -ENOMEM; + } + memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo)); + sdbg_devinfo->sdbg_host = sdbg_host; + list_add_tail(&sdbg_devinfo->dev_list, + &sdbg_host->dev_info_list); + } + + list_add_tail(&sdbg_host->host_list, &sdebug_host_list); + + hpnt = scsi_register(&sdebug_driver_template, 0); + if (NULL == hpnt) { + printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__); + error = -ENODEV; + goto clean1; + } + + sdbg_host->shost = hpnt; + sdbg_host->dev = dev; + hpnt->max_lun = scsi_debug_max_luns; + + error = scsi_add_host(hpnt, sdbg_host->dev); + if (error) { + printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); + error = -ENODEV; + goto clean2; + } + + + return 0; + +clean2: + scsi_unregister(hpnt); +clean1: + list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { + sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, + dev_list); + list_del(&sdbg_devinfo->dev_list); + kfree(sdbg_devinfo); + } + + kfree(sdbg_host); + + return error; +} + +static int sdebug_driver_remove(struct device * dev) +{ + struct list_head *lh, *lh_sf; + struct sdebug_dev_info *sdbg_devinfo; + struct sdebug_host_info *sdbg_host, *found = NULL; + + spin_lock(&sdebug_host_list_lock); + list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { + if (sdbg_host->dev == dev) { + list_del(&sdbg_host->host_list); + found = sdbg_host; + break; + } + } + spin_unlock(&sdebug_host_list_lock); + + if (!found) { + printk(KERN_ERR "%s: sdebug_host_info not found\n", + __FUNCTION__); + return -ENODEV; + } + + + if (scsi_remove_host(sdbg_host->shost)) { + printk(KERN_ERR "%s: scsi_remove_host failed\n", __FUNCTION__); + return -EBUSY; + } + + scsi_unregister(sdbg_host->shost); + + list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { + sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, + dev_list); + list_del(&sdbg_devinfo->dev_list); + kfree(sdbg_devinfo); + } + + kfree(sdbg_host); + + return 0; } diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h index 36d7bbebc9cd..2d9ab66993e2 100644 --- a/drivers/scsi/scsi_debug.h +++ b/drivers/scsi/scsi_debug.h @@ -2,6 +2,7 @@ #include <linux/types.h> +static int scsi_debug_slave_alloc(struct scsi_device *); static int scsi_debug_slave_configure(struct scsi_device *); static void scsi_debug_slave_destroy(struct scsi_device *); static int scsi_debug_queuecommand(struct scsi_cmnd *, @@ -27,8 +28,9 @@ static Scsi_Host_Template sdebug_driver_template = { .proc_info = scsi_debug_proc_info, .name = "SCSI DEBUG", .info = scsi_debug_info, + .slave_alloc = scsi_debug_slave_alloc, .slave_configure = scsi_debug_slave_configure, - .slave_destroy = scsi_debug_slave_destroy, + .slave_destroy = scsi_debug_slave_destroy, .ioctl = scsi_debug_ioctl, .queuecommand = scsi_debug_queuecommand, .eh_abort_handler = scsi_debug_abort, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index eec12d6a61ba..b9c826ed12eb 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -597,28 +597,6 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) } /** - * scsi_eh_retry_cmd - Retry the original command - * @scmd: Original failed SCSI cmd. - * - * Notes: - * This function will *not* return until the command either times out, - * or it completes. - **/ -static int scsi_eh_retry_cmd(struct scsi_cmnd *scmd) -{ - int rtn = SUCCESS; - - for (; scmd->retries < scmd->allowed; scmd->retries++) { - scsi_setup_cmd_retry(scmd); - rtn = scsi_send_eh_cmnd(scmd, scmd->timeout_per_command); - if (rtn != NEEDS_RETRY) - break; - } - - return rtn; -} - -/** * scsi_eh_finish_cmd - Handle a cmd that eh is finished with. * @scmd: Original SCSI cmd that eh has finished. * @done_q: Queue for processed commands. diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5ee88b47014b..a06341945483 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -125,7 +125,6 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) */ cmd->state = SCSI_STATE_MLQUEUE; cmd->owner = SCSI_OWNER_MIDLEVEL; - cmd->bh_next = NULL; /* * Decrement the counters, since these commands are no longer diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 185fec2e14c8..20115e69dc05 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -385,83 +385,92 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, struct scsi_device *sdev, *device; sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC); - if (sdev != NULL) { - memset(sdev, 0, sizeof(Scsi_Device)); - sdev->vendor = scsi_null_device_strs; - sdev->model = scsi_null_device_strs; - sdev->rev = scsi_null_device_strs; - sdev->host = shost; - sdev->id = id; - sdev->lun = lun; - sdev->channel = channel; - sdev->online = TRUE; - INIT_LIST_HEAD(&sdev->siblings); - INIT_LIST_HEAD(&sdev->same_target_siblings); - INIT_LIST_HEAD(&sdev->cmd_list); - spin_lock_init(&sdev->list_lock); - /* - * Some low level driver could use device->type - */ - sdev->type = -1; - /* - * Assume that the device will have handshaking problems, - * and then fix this field later if it turns out it - * doesn't - */ - sdev->borken = 1; + if (!sdev) + goto out; - if (!q || *q == NULL) { - sdev->request_queue = scsi_alloc_queue(shost); - if (!sdev->request_queue) - goto out_bail; - } else { - sdev->request_queue = *q; - *q = NULL; - } + memset(sdev, 0, sizeof(*sdev)); + sdev->vendor = scsi_null_device_strs; + sdev->model = scsi_null_device_strs; + sdev->rev = scsi_null_device_strs; + sdev->host = shost; + sdev->id = id; + sdev->lun = lun; + sdev->channel = channel; + sdev->online = TRUE; + INIT_LIST_HEAD(&sdev->siblings); + INIT_LIST_HEAD(&sdev->same_target_siblings); + INIT_LIST_HEAD(&sdev->cmd_list); + spin_lock_init(&sdev->list_lock); - sdev->request_queue->queuedata = sdev; - scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); - init_waitqueue_head(&sdev->scpnt_wait); + /* + * Some low level driver could use device->type + */ + sdev->type = -1; - if (shost->hostt->slave_alloc) - if (shost->hostt->slave_alloc(sdev)) { - goto out_bail; - } - /* - * If there are any same target siblings, add this to the - * sibling list - */ - list_for_each_entry(device, &shost->my_devices, siblings) { - if(device->id == sdev->id && - device->channel == sdev->channel) { - list_add_tail(&sdev->same_target_siblings, - &device->same_target_siblings); - sdev->scsi_level = device->scsi_level; - break; - } + /* + * Assume that the device will have handshaking problems, + * and then fix this field later if it turns out it + * doesn't + */ + sdev->borken = 1; + + if (!q || *q == NULL) { + sdev->request_queue = scsi_alloc_queue(shost); + if (!sdev->request_queue) + goto out_free_dev; + } else { + sdev->request_queue = *q; + *q = NULL; + } + + sdev->request_queue->queuedata = sdev; + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + init_waitqueue_head(&sdev->scpnt_wait); + + if (shost->hostt->slave_alloc) { + if (shost->hostt->slave_alloc(sdev)) + goto out_free_queue; + } + + /* + * If there are any same target siblings, add this to the + * sibling list + */ + list_for_each_entry(device, &shost->my_devices, siblings) { + if (device->id == sdev->id && + device->channel == sdev->channel) { + list_add_tail(&sdev->same_target_siblings, + &device->same_target_siblings); + sdev->scsi_level = device->scsi_level; + break; } - /* - * If there wasn't another lun already configured at this - * target, then default this device to SCSI_2 until we - * know better - */ - if(!sdev->scsi_level) - sdev->scsi_level = SCSI_2; - /* - * Add it to the end of the shost->my_devices list. - */ - list_add_tail(&sdev->siblings, &shost->my_devices); - return (sdev); } -out_bail: - printk(ALLOC_FAILURE_MSG, __FUNCTION__); + + /* + * If there wasn't another lun already configured at this + * target, then default this device to SCSI_2 until we + * know better + */ + if (!sdev->scsi_level) + sdev->scsi_level = SCSI_2; + + /* + * Add it to the end of the shost->my_devices list. + */ + list_add_tail(&sdev->siblings, &shost->my_devices); + return sdev; + +out_free_queue: if (q && sdev->request_queue) { *q = sdev->request_queue; sdev->request_queue = NULL; } else if (sdev->request_queue) scsi_free_queue(sdev->request_queue); +out_free_dev: kfree(sdev); +out: + printk(ALLOC_FAILURE_MSG, __FUNCTION__); return NULL; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index eade9fd9b026..4ecaa390ebdc 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -266,6 +266,25 @@ sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); sdev_rw_attr_bit (online); +static ssize_t +show_rescan_field (struct device *dev, char *buf) +{ + return 0; +} + +static ssize_t +store_rescan_field (struct device *dev, const char *buf, size_t count) +{ + int ret = ENODEV; + struct scsi_device *sdev; + sdev = to_scsi_device(dev); + if (sdev) + ret = scsi_rescan_device(sdev); + return ret; +} + +static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field) + static struct device_attribute * const sdev_attrs[] = { &dev_attr_device_blocked, &dev_attr_queue_depth, @@ -276,6 +295,7 @@ static struct device_attribute * const sdev_attrs[] = { &dev_attr_model, &dev_attr_rev, &dev_attr_online, + &dev_attr_rescan, }; /** diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 12d4a6839639..eadc8315551a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -93,10 +93,12 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt); static int sd_attach(struct scsi_device *); static void sd_detach(struct scsi_device *); +static void sd_rescan(struct scsi_device *); static int sd_init_command(struct scsi_cmnd *); static int sd_synchronize_cache(struct scsi_disk *, int); static int sd_notifier(struct notifier_block *, unsigned long, void *); - +static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, + struct scsi_request *SRpnt, unsigned char *buffer); static struct notifier_block sd_notifier_block = {sd_notifier, NULL, 0}; static struct Scsi_Device_Template sd_template = { @@ -106,6 +108,7 @@ static struct Scsi_Device_Template sd_template = { .scsi_type = TYPE_DISK, .attach = sd_attach, .detach = sd_detach, + .rescan = sd_rescan, .init_command = sd_init_command, .scsi_driverfs_driver = { .name = "sd", @@ -629,6 +632,38 @@ not_present: return 1; } +static void sd_rescan(struct scsi_device * sdp) +{ + unsigned char *buffer; + struct scsi_disk *sdkp = sd_find_by_sdev(sdp); + struct gendisk *gd; + struct scsi_request *SRpnt; + + if (!sdkp || sdp->online == FALSE || !sdkp->media_present) + return; + + gd = sdkp->disk; + + SCSI_LOG_HLQUEUE(3, printk("sd_rescan: disk=%s\n", gd->disk_name)); + + SRpnt = scsi_allocate_request(sdp); + if (!SRpnt) { + printk(KERN_WARNING "(sd_rescan:) Request allocation " + "failure.\n"); + return; + } + + if (sdkp->device->host->unchecked_isa_dma) + buffer = kmalloc(512, GFP_DMA); + else + buffer = kmalloc(512, GFP_KERNEL); + + sd_read_capacity(sdkp, gd->disk_name, SRpnt, buffer); + set_capacity(gd, sdkp->capacity); + scsi_release_request(SRpnt); + kfree(buffer); +} + static int sd_revalidate_disk(struct gendisk *disk) { struct scsi_disk *sdkp = scsi_disk(disk); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 91dace681ba1..bd6d50025126 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -18,10 +18,8 @@ * */ #include <linux/config.h> -#ifdef CONFIG_PROC_FS -static char *sg_version_str = "Version: 3.5.27 (20030130)"; -#endif -static int sg_version_num = 30527; /* 2 digits for each component */ +static char *sg_version_str = "3.5.28 [20030308]"; +static int sg_version_num = 30528; /* 2 digits for each component */ /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First @@ -56,6 +54,7 @@ static int sg_version_num = 30527; /* 2 digits for each component */ #include <linux/poll.h> #include <linux/vmalloc.h> #include <linux/smp_lock.h> +#include <linux/moduleparam.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -1327,27 +1326,6 @@ static struct file_operations sg_fops = { .fasync = sg_fasync, }; -#ifndef MODULE -static int __init -sg_def_reserved_size_setup(char *str) -{ - int tmp; - - if (get_option(&str, &tmp) == 1) { - def_reserved_size = tmp; - if (tmp >= 0) - sg_big_buff = tmp; - return 1; - } else { - printk(KERN_WARNING "sg_def_reserved_size : usage " - "sg_def_reserved_size=n (n could be 65536, 131072 or 262144)\n"); - return 0; - } -} - -__setup("sg_def_reserved_size=", sg_def_reserved_size_setup); -#endif - /* Driverfs file support */ static ssize_t sg_device_kdev_read(struct device *driverfs_dev, char *page) @@ -1564,16 +1542,77 @@ sg_detach(Scsi_Device * scsidp) scsi_sleep(2); /* dirty detach so delay device destruction */ } +/* Set 'perm' (4th argument) to 0 to disable module_param's definition + * of sysfs parameters (which module_param doesn't yet support). + * Sysfs parameters defined explicitly below. + */ +module_param_named(def_reserved_size, def_reserved_size, int, 0); +module_param_named(allow_dio, sg_allow_dio, int, 0); + MODULE_AUTHOR("Douglas Gilbert"); MODULE_DESCRIPTION("SCSI generic (sg) driver"); - -#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); -#endif -MODULE_PARM(def_reserved_size, "i"); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); +static ssize_t sg_allow_dio_show(struct device_driver * ddp, char * buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", sg_allow_dio); +} +static ssize_t sg_allow_dio_store(struct device_driver * ddp, + const char * buf, size_t count) +{ + if (1 == sscanf(buf, "%d", &sg_allow_dio)) { + sg_allow_dio = sg_allow_dio ? 1 : 0; + return count; + } + return -EINVAL; +} +DRIVER_ATTR(allow_dio, S_IRUGO | S_IWUSR, sg_allow_dio_show, + sg_allow_dio_store) + +static ssize_t sg_def_reserved_show(struct device_driver * ddp, char * buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", sg_big_buff); +} +static ssize_t sg_def_reserved_store(struct device_driver * ddp, + const char * buf, size_t count) +{ + if (1 == sscanf(buf, "%d", &def_reserved_size)) { + if (def_reserved_size >= 0) { + sg_big_buff = def_reserved_size; + return count; + } + } + return -EINVAL; +} +DRIVER_ATTR(def_reserved_size, S_IRUGO | S_IWUSR, sg_def_reserved_show, + sg_def_reserved_store) + +static ssize_t sg_version_show(struct device_driver * ddp, char * buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", sg_version_str); +} +DRIVER_ATTR(version, S_IRUGO, sg_version_show, NULL) + +static void do_create_driverfs_files(void) +{ + struct device_driver * driverfs = &sg_template.scsi_driverfs_driver; + + driver_create_file(driverfs, &driver_attr_allow_dio); + driver_create_file(driverfs, &driver_attr_def_reserved_size); + driver_create_file(driverfs, &driver_attr_version); +} + +static void do_remove_driverfs_files(void) +{ + struct device_driver * driverfs = &sg_template.scsi_driverfs_driver; + + driver_remove_file(driverfs, &driver_attr_version); + driver_remove_file(driverfs, &driver_attr_def_reserved_size); + driver_remove_file(driverfs, &driver_attr_allow_dio); +} + static int __init init_sg(void) { @@ -1591,12 +1630,14 @@ init_sg(void) #ifdef CONFIG_PROC_FS sg_proc_init(); #endif /* CONFIG_PROC_FS */ + do_create_driverfs_files(); return 0; } static void __exit exit_sg(void) { + do_remove_driverfs_files(); #ifdef CONFIG_PROC_FS sg_proc_cleanup(); #endif /* CONFIG_PROC_FS */ @@ -2656,10 +2697,6 @@ sg_get_dev(int dev) static struct proc_dir_entry *sg_proc_sgp = NULL; static char sg_proc_sg_dirname[] = "sg"; -static const char *sg_proc_leaf_names[] = { "allow_dio", "def_reserved_size", - "debug", "devices", "device_hdr", "device_strs", - "hosts", "host_hdr", "host_strs", "version" -}; static int sg_proc_adio_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data); @@ -2693,13 +2730,21 @@ static int sg_proc_version_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data); static int sg_proc_version_info(char *buffer, int *len, off_t * begin, off_t offset, int size); -static read_proc_t *sg_proc_leaf_reads[] = { - sg_proc_adio_read, sg_proc_dressz_read, sg_proc_debug_read, - sg_proc_dev_read, sg_proc_devhdr_read, sg_proc_devstrs_read, - sg_proc_version_read + +struct sg_proc_leaf { + const char * name; + read_proc_t * rf; + write_proc_t * wf; }; -static write_proc_t *sg_proc_leaf_writes[] = { - sg_proc_adio_write, sg_proc_dressz_write, 0, 0, 0, 0, 0, 0, 0, 0 + +static struct sg_proc_leaf sg_proc_leaf_arr[] = { + {"allow_dio", sg_proc_adio_read, sg_proc_adio_write}, + {"def_reserved_size", sg_proc_dressz_read, sg_proc_dressz_write}, + {"debug", sg_proc_debug_read, NULL}, + {"devices", sg_proc_dev_read, NULL}, + {"device_hdr", sg_proc_devhdr_read, NULL}, + {"device_strs", sg_proc_devstrs_read, NULL}, + {"version", sg_proc_version_read, NULL} }; #define PRINT_PROC(fmt,args...) \ @@ -2729,9 +2774,10 @@ static int sg_proc_init() { int k, mask; - int leaves = - sizeof (sg_proc_leaf_names) / sizeof (sg_proc_leaf_names[0]); + int num_leaves = + sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); struct proc_dir_entry *pdep; + struct sg_proc_leaf * leaf; if (!proc_scsi) return 1; @@ -2739,14 +2785,14 @@ sg_proc_init() S_IFDIR | S_IRUGO | S_IXUGO, proc_scsi); if (!sg_proc_sgp) return 1; - for (k = 0; k < leaves; ++k) { - mask = sg_proc_leaf_writes[k] ? S_IRUGO | S_IWUSR : S_IRUGO; - pdep = - create_proc_entry(sg_proc_leaf_names[k], mask, sg_proc_sgp); + for (k = 0; k < num_leaves; ++k) { + leaf = &sg_proc_leaf_arr[k]; + mask = leaf->wf ? S_IRUGO | S_IWUSR : S_IRUGO; + pdep = create_proc_entry(leaf->name, mask, sg_proc_sgp); if (pdep) { - pdep->read_proc = sg_proc_leaf_reads[k]; - if (sg_proc_leaf_writes[k]) - pdep->write_proc = sg_proc_leaf_writes[k]; + pdep->read_proc = leaf->rf; + if (leaf->wf) + pdep->write_proc = leaf->wf; } } return 0; @@ -2756,13 +2802,13 @@ static void sg_proc_cleanup() { int k; - int leaves = - sizeof (sg_proc_leaf_names) / sizeof (sg_proc_leaf_names[0]); + int num_leaves = + sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); if ((!proc_scsi) || (!sg_proc_sgp)) return; - for (k = 0; k < leaves; ++k) - remove_proc_entry(sg_proc_leaf_names[k], sg_proc_sgp); + for (k = 0; k < num_leaves; ++k) + remove_proc_entry(sg_proc_leaf_arr[k].name, sg_proc_sgp); remove_proc_entry(sg_proc_sg_dirname, proc_scsi); } diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d0949c6b6a1e..09e0165f45a9 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -93,13 +93,15 @@ unsigned int share_irqs = SERIAL8250_SHARE_IRQS; #ifdef CONFIG_SERIAL_8250_MULTIPORT #define CONFIG_SERIAL_MULTIPORT 1 #endif +#ifdef CONFIG_SERIAL_8250_MANY_PORTS +#define CONFIG_SERIAL_MANY_PORTS 1 +#endif /* * HUB6 is always on. This will be removed once the header * files have been cleaned. */ #define CONFIG_HUB6 1 -#define CONFIG_SERIAL_MANY_PORTS 1 #include <asm/serial.h> @@ -2095,6 +2097,28 @@ void serial8250_get_irq_map(unsigned int *map) } } +/** + * serial8250_suspend_port - suspend one serial port + * @line: serial line number + * + * Suspend one serial port. + */ +void serial8250_suspend_port(int line, u32 level) +{ + uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port, level); +} + +/** + * serial8250_resume_port - resume one serial port + * @line: serial line number + * + * Resume one serial port. + */ +void serial8250_resume_port(int line, u32 level) +{ + uart_resume_port(&serial8250_reg, &serial8250_ports[line].port, level); +} + static int __init serial8250_init(void) { int ret, i; @@ -2128,6 +2152,8 @@ module_exit(serial8250_exit); EXPORT_SYMBOL(register_serial); EXPORT_SYMBOL(unregister_serial); EXPORT_SYMBOL(serial8250_get_irq_map); +EXPORT_SYMBOL(serial8250_suspend_port); +EXPORT_SYMBOL(serial8250_resume_port); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $"); diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index 030116e6ebf6..cc206f9476ac 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -27,6 +27,8 @@ struct serial8250_probe { int serial8250_register_probe(struct serial8250_probe *probe); void serial8250_unregister_probe(struct serial8250_probe *probe); void serial8250_get_irq_map(unsigned int *map); +void serial8250_suspend_port(int line, u32 level); +void serial8250_resume_port(int line, u32 level); struct old_serial_port { unsigned int uart; diff --git a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c index 0065a31a418a..db4666f894e5 100644 --- a/drivers/serial/8250_acorn.c +++ b/drivers/serial/8250_acorn.c @@ -1,7 +1,7 @@ /* * linux/drivers/serial/acorn.c * - * Copyright (C) 1996-2002 Russell King. + * Copyright (C) 1996-2003 Russell King. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,6 +9,8 @@ */ #include <linux/module.h> #include <linux/types.h> +#include <linux/tty.h> +#include <linux/serial_core.h> #include <linux/serial.h> #include <linux/errno.h> #include <linux/ioport.h> @@ -16,6 +18,7 @@ #include <linux/device.h> #include <linux/init.h> +#include <asm/io.h> #include <asm/ecard.h> #include <asm/string.h> @@ -24,36 +27,41 @@ struct serial_card_type { unsigned int num_ports; unsigned int baud_base; - int type; - int speed; - int offset[MAX_PORTS]; + unsigned int type; + unsigned int offset[MAX_PORTS]; }; struct serial_card_info { unsigned int num_ports; int ports[MAX_PORTS]; - unsigned long base[MAX_PORTS]; }; -static inline int serial_register_onedev(unsigned long port, int irq, unsigned int baud_base) +static inline int +serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base) { struct serial_struct req; memset(&req, 0, sizeof(req)); - req.baud_base = baud_base; - req.irq = irq; - req.port = port; - req.flags = 0; + req.irq = irq; + req.flags = UPF_AUTOPROBE | UPF_RESOURCES | + UPF_SHARE_IRQ; + req.baud_base = baud_base; + req.io_type = UPIO_MEM; + req.iomem_base = vaddr; + req.iomem_reg_shift = 2; + req.iomap_base = baddr; return register_serial(&req); } -static int __devinit serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) +static int __devinit +serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) { struct serial_card_info *info; struct serial_card_type *type = id->data; - unsigned long cardaddr, address; - int port; + unsigned long bus_addr; + unsigned char *virt_addr; + unsigned int port; info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL); if (!info) @@ -64,20 +72,19 @@ static int __devinit serial_card_probe(struct expansion_card *ec, const struct e ecard_set_drvdata(ec, info); - cardaddr = ecard_address(ec, type->type, type->speed); + bus_addr = ec->resource[type->type].start; + virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1); + if (!virt_addr) { + kfree(info); + return -ENOMEM; + } for (port = 0; port < info->num_ports; port ++) { - address = cardaddr + type->offset[port]; - - info->ports[port] = -1; - info->base[port] = address; + unsigned long baddr = bus_addr + type->offset[port]; + unsigned char *vaddr = virt_addr + type->offset[port]; - if (!request_region(address, 8, "acornserial")) - continue; - - info->ports[port] = serial_register_onedev(address, ec->irq, type->baud_base); - if (info->ports[port] < 0) - break; + info->ports[port] = serial_register_onedev(baddr, vaddr, + ec->irq, type->baud_base); } return 0; @@ -90,12 +97,9 @@ static void __devexit serial_card_remove(struct expansion_card *ec) ecard_set_drvdata(ec, NULL); - for (i = 0; i < info->num_ports; i++) { - if (info->ports[i] > 0) { + for (i = 0; i < info->num_ports; i++) + if (info->ports[i] > 0) unregister_serial(info->ports[i]); - release_region(info->base[i], 8); - } - } kfree(info); } @@ -103,17 +107,15 @@ static void __devexit serial_card_remove(struct expansion_card *ec) static struct serial_card_type atomwide_type = { .num_ports = 3, .baud_base = 7372800 / 16, - .type = ECARD_IOC, - .speed = ECARD_SLOW, - .offset = { 0xa00, 0x900, 0x800 }, + .type = ECARD_RES_IOCSLOW, + .offset = { 0x2800, 0x2400, 0x2000 }, }; static struct serial_card_type serport_type = { .num_ports = 2, .baud_base = 3686400 / 16, - .type = ECARD_IOC, - .speed = ECARD_SLOW, - .offset = { 0x800, 0x808 }, + .type = ECARD_RES_IOCSLOW, + .offset = { 0x2000, 0x2020 }, }; static const struct ecard_id serial_cids[] = { @@ -127,7 +129,8 @@ static struct ecard_driver serial_card_driver = { .remove = __devexit_p(serial_card_remove), .id_table = serial_cids, .drv = { - .name = "acornserial", + .devclass = &tty_devclass, + .name = "8250_acorn", }, }; @@ -142,6 +145,7 @@ static void __exit serial_card_exit(void) } MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver"); MODULE_LICENSE("GPL"); module_init(serial_card_init); diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 240b79df5794..1123ebd9fe30 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -20,8 +20,9 @@ #include <linux/string.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/tty.h> #include <linux/serial.h> -#include <linux/serialP.h> +#include <linux/serial_core.h> #include <asm/bitops.h> #include <asm/byteorder.h> @@ -30,174 +31,213 @@ #include "8250.h" +/* + * Definitions for PCI support. + */ +#define FL_BASE_MASK 0x0007 +#define FL_BASE0 0x0000 +#define FL_BASE1 0x0001 +#define FL_BASE2 0x0002 +#define FL_BASE3 0x0003 +#define FL_BASE4 0x0004 +#define FL_GET_BASE(x) (x & FL_BASE_MASK) + +#define FL_IRQ_MASK (0x0007 << 4) +#define FL_IRQBASE0 (0x0000 << 4) +#define FL_IRQBASE1 (0x0001 << 4) +#define FL_IRQBASE2 (0x0002 << 4) +#define FL_IRQBASE3 (0x0003 << 4) +#define FL_IRQBASE4 (0x0004 << 4) +#define FL_GET_IRQBASE(x) ((x & FL_IRQ_MASK) >> 4) + +/* Use successive BARs (PCI base address registers), + else use offset into some specified BAR */ +#define FL_BASE_BARS 0x0008 + +/* Use the irq resource table instead of dev->irq */ +#define FL_IRQRESOURCE 0x0080 + +/* Use the Base address register size to cap number of ports */ +#define FL_REGION_SZ_CAP 0x0100 -#ifndef IS_PCI_REGION_IOPORT -#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ - IORESOURCE_IO) -#endif -#ifndef IS_PCI_REGION_IOMEM -#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \ - IORESOURCE_MEM) -#endif -#ifndef PCI_IRQ_RESOURCE -#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start) -#endif - -#ifndef pci_get_subvendor -#define pci_get_subvendor(dev) ((dev)->subsystem_vendor) -#define pci_get_subdevice(dev) ((dev)->subsystem_device) -#endif - -struct serial_private { - unsigned int nr; - struct pci_board *board; - int line[0]; +struct pci_board { + unsigned int flags; + unsigned int num_ports; + unsigned int base_baud; + unsigned int uart_offset; + unsigned int reg_shift; + unsigned int first_offset; }; /* - * init_fn returns: + * init function returns: * > 0 - number of ports * = 0 - use board->num_ports * < 0 - error */ -struct pci_board { - int flags; - int num_ports; - int base_baud; - int uart_offset; - int reg_shift; - int (*init_fn)(struct pci_dev *dev, int enable); - int first_uart_offset; +struct pci_serial_quirk { + u32 vendor; + u32 device; + u32 subvendor; + u32 subdevice; + int (*init)(struct pci_dev *dev); + int (*setup)(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx); + void (*exit)(struct pci_dev *dev); +}; + +#define PCI_NUM_BAR_RESOURCES 6 + +struct serial_private { + unsigned int nr; + void *remapped_bar[PCI_NUM_BAR_RESOURCES]; + struct pci_serial_quirk *quirk; + int line[0]; }; +static void moan_device(const char *str, struct pci_dev *dev) +{ + printk(KERN_WARNING "%s: %s\n" + KERN_WARNING "Please send the output of lspci -vv, this\n" + KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + KERN_WARNING "manufacturer and name of serial board or\n" + KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n", + dev->slot_name, str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); +} + static int -get_pci_port(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +setup_port(struct pci_dev *dev, struct serial_struct *req, + int bar, int offset, int regshift) { - unsigned long port; - int base_idx; - int max_port; - int offset; + struct serial_private *priv = pci_get_drvdata(dev); + unsigned long port, len; - base_idx = SPCI_FL_GET_BASE(board->flags); - if (board->flags & SPCI_FL_BASE_TABLE) - base_idx += idx; + if (bar >= PCI_NUM_BAR_RESOURCES) + return -EINVAL; - if (board->flags & SPCI_FL_REGION_SZ_CAP) { - max_port = pci_resource_len(dev, base_idx) / 8; - if (idx >= max_port) - return 1; - } - - offset = board->first_uart_offset; + if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { + port = pci_resource_start(dev, bar); + len = pci_resource_len(dev, bar); - /* - * Timedia/SUNIX uses a mixture of BARs and offsets - * Ugh, this is ugly as all hell --- TYT - */ - if (dev->vendor == PCI_VENDOR_ID_TIMEDIA) - switch(idx) { - case 0: - base_idx = 0; - break; - case 1: - base_idx = 0; - offset = 8; - break; - case 2: - base_idx = 1; - break; - case 3: - base_idx = 1; - offset = 8; - break; - case 4: /* BAR 2 */ - case 5: /* BAR 3 */ - case 6: /* BAR 4 */ - case 7: /* BAR 5 */ - base_idx = idx - 2; - } + if (!priv->remapped_bar[bar]) + priv->remapped_bar[bar] = ioremap(port, len); + if (!priv->remapped_bar[bar]) + return -ENOMEM; - /* AFAVLAB uses a different mixture of BARs and offsets */ - /* Not that ugly ;) -- HW */ - if (dev->vendor == PCI_VENDOR_ID_AFAVLAB && idx >= 4) { - base_idx = 4; - offset = (idx - 4) * 8; + req->io_type = UPIO_MEM; + req->iomap_base = port; + req->iomem_base = priv->remapped_bar[bar] + offset; + req->iomem_reg_shift = regshift; + } else { + port = pci_resource_start(dev, bar) + offset; + req->io_type = UPIO_PORT; + req->port = port; + if (HIGH_BITS_OFFSET) + req->port_high = port >> HIGH_BITS_OFFSET; } + return 0; +} - /* Some Titan cards are also a little weird */ - if (dev->vendor == PCI_VENDOR_ID_TITAN && - (dev->device == PCI_DEVICE_ID_TITAN_400L || - dev->device == PCI_DEVICE_ID_TITAN_800L)) { - switch (idx) { - case 0: base_idx = 1; - break; - case 1: base_idx = 2; - break; - default: - base_idx = 4; - offset = 8 * (idx - 2); - } - } +/* + * AFAVLAB uses a different mixture of BARs and offsets + * Not that ugly ;) -- HW + */ +static int +afavlab_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int bar, offset = board->first_offset; + + bar = FL_GET_BASE(board->flags); + if (idx < 4) + bar += idx; + else + offset += (idx - 4) * board->uart_offset; - /* HP's Diva chip puts the 4th/5th serial port further out, and - * some serial ports are supposed to be hidden on certain models. - */ - if (dev->vendor == PCI_VENDOR_ID_HP && - dev->device == PCI_DEVICE_ID_HP_DIVA) { - switch (dev->subsystem_device) { - case PCI_DEVICE_ID_HP_DIVA_MAESTRO: - if (idx == 3) - idx++; - break; - case PCI_DEVICE_ID_HP_DIVA_EVEREST: - if (idx > 0) - idx++; - if (idx > 2) - idx++; - break; - } - if (idx > 2) { - offset = 0x18; - } + return setup_port(dev, req, bar, offset, board->reg_shift); +} + +/* + * HP's Remote Management Console. The Diva chip came in several + * different versions. N-class, L2000 and A500 have two Diva chips, each + * with 3 UARTs (the third UART on the second chip is unused). Superdome + * and Keystone have one Diva chip with 3 UARTs. Some later machines have + * one Diva chip, but it has been expanded to 5 UARTs. + */ +static int __devinit pci_hp_diva_init(struct pci_dev *dev) +{ + int rc = 0; + + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_TOSCA1: + case PCI_DEVICE_ID_HP_DIVA_HALFDOME: + case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + rc = 3; + break; + case PCI_DEVICE_ID_HP_DIVA_TOSCA2: + rc = 2; + break; + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + rc = 4; + break; + case PCI_DEVICE_ID_HP_DIVA_POWERBAR: + rc = 1; + break; } - port = pci_resource_start(dev, base_idx) + offset; + return rc; +} - if ((board->flags & SPCI_FL_BASE_TABLE) == 0) - port += idx * (board->uart_offset ? board->uart_offset : 8); +/* + * HP's Diva chip puts the 4th/5th serial port further out, and + * some serial ports are supposed to be hidden on certain models. + */ +static int +pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int offset = board->first_offset; + unsigned int bar = FL_GET_BASE(board->flags); - if (IS_PCI_REGION_IOPORT(dev, base_idx)) { - req->port = port; - if (HIGH_BITS_OFFSET) - req->port_high = port >> HIGH_BITS_OFFSET; - else - req->port_high = 0; - return 0; + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + if (idx == 3) + idx++; + break; + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + if (idx > 0) + idx++; + if (idx > 2) + idx++; + break; } - req->io_type = SERIAL_IO_MEM; - req->iomap_base = port; - req->iomem_base = ioremap(port, board->uart_offset); - if (req->iomem_base == NULL) - return -ENOMEM; - req->iomem_reg_shift = board->reg_shift; - req->port = 0; - return 0; + if (idx > 2) + offset = 0x18; + + offset += idx * board->uart_offset; + + return setup_port(dev, req, bar, offset, board->reg_shift); } -static _INLINE_ int -get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) +/* + * Added for EKF Intel i960 serial boards + */ +static int __devinit pci_inteli960ni_init(struct pci_dev *dev) { - int base_idx; + unsigned long oldval; - if ((board->flags & SPCI_FL_IRQRESOURCE) == 0) - return dev->irq; + if (!(dev->subsystem_device & 0x1000)) + return -ENODEV; - base_idx = SPCI_FL_GET_IRQBASE(board->flags); - if (board->flags & SPCI_FL_IRQ_TABLE) - base_idx += idx; - - return PCI_IRQ_RESOURCE(dev, base_idx); + /* is firmware started? */ + pci_read_config_dword(dev, 0x44, (void*) &oldval); + if (oldval == 0x00001000L) { /* RESET value */ + printk(KERN_DEBUG "Local i960 firmware missing"); + return -ENODEV; + } + return 0; } /* @@ -206,26 +246,29 @@ get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) * seems to be mainly needed on card using the PLX which also use I/O * mapped memory. */ -static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable) +static int __devinit pci_plx9050_init(struct pci_dev *dev) { - u8 *p, irq_config = 0; - - if (enable) { - irq_config = 0x41; - if (dev->vendor == PCI_VENDOR_ID_PANACOM) - irq_config = 0x43; - if ((dev->vendor == PCI_VENDOR_ID_PLX) && - (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { - /* - * As the megawolf cards have the int pins active - * high, and have 2 UART chips, both ints must be - * enabled on the 9050. Also, the UARTS are set in - * 16450 mode by default, so we have to enable the - * 16C950 'enhanced' mode so that we can use the - * deep FIFOs - */ - irq_config = 0x5b; - } + u8 *p, irq_config; + + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) { + moan_device("no memory in bar 0", dev); + return 0; + } + + irq_config = 0x41; + if (dev->vendor == PCI_VENDOR_ID_PANACOM) + irq_config = 0x43; + if ((dev->vendor == PCI_VENDOR_ID_PLX) && + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { + /* + * As the megawolf cards have the int pins active + * high, and have 2 UART chips, both ints must be + * enabled on the 9050. Also, the UARTS are set in + * 16450 mode by default, so we have to enable the + * 16C950 'enhanced' mode so that we can use the + * deep FIFOs + */ + irq_config = 0x5b; } /* @@ -245,6 +288,27 @@ static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable) return 0; } +static void __devexit pci_plx9050_exit(struct pci_dev *dev) +{ + u8 *p; + + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) + return; + + /* + * disable interrupts + */ + p = ioremap(pci_resource_start(dev, 0), 0x80); + if (p != NULL) { + writel(0, p + 0x4c); + + /* + * Read the register back to ensure that it took effect. + */ + readl(p + 0x4c); + iounmap(p); + } +} /* * SIIG serial cards have an PCI interface chip which also controls @@ -270,23 +334,20 @@ static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable) #define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) #define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) -int pci_siig10x_fn(struct pci_dev *dev, int enable) +static int pci_siig10x_init(struct pci_dev *dev) { u16 data, *p; - if (!enable) - return 0; - switch (dev->device & 0xfff8) { - case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ - data = 0xffdf; - break; - case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ - data = 0xf7ff; - break; - default: /* 1S1P, 4S */ - data = 0xfffb; - break; + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ + data = 0xffdf; + break; + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ + data = 0xf7ff; + break; + default: /* 1S1P, 4S */ + data = 0xfffb; + break; } p = ioremap(pci_resource_start(dev, 0), 0x80); @@ -294,22 +355,18 @@ int pci_siig10x_fn(struct pci_dev *dev, int enable) return -ENOMEM; writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); + readw((unsigned long)p + 0x28); iounmap(p); return 0; } -EXPORT_SYMBOL(pci_siig10x_fn); - #define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) #define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) -int pci_siig20x_fn(struct pci_dev *dev, int enable) +static int pci_siig20x_init(struct pci_dev *dev) { u8 data; - if (!enable) - return 0; - /* Change clock frequency for the first UART. */ pci_read_config_byte(dev, 0x6f, &data); pci_write_config_byte(dev, 0x6f, data & 0xef); @@ -323,28 +380,25 @@ int pci_siig20x_fn(struct pci_dev *dev, int enable) return 0; } -EXPORT_SYMBOL(pci_siig20x_fn); - -/* Added for EKF Intel i960 serial boards */ -static int __devinit pci_inteli960ni_fn(struct pci_dev *dev, int enable) +int pci_siig10x_fn(struct pci_dev *dev, int enable) { - unsigned long oldval; - - if (!(pci_get_subdevice(dev) & 0x1000)) - return -ENODEV; + int ret = 0; + if (enable) + ret = pci_siig10x_init(dev); + return ret; +} - if (!enable) /* is there something to deinit? */ - return 0; - - /* is firmware started? */ - pci_read_config_dword(dev, 0x44, (void*) &oldval); - if (oldval == 0x00001000L) { /* RESET value */ - printk(KERN_DEBUG "Local i960 firmware missing"); - return -ENODEV; - } - return 0; +int pci_siig20x_fn(struct pci_dev *dev, int enable) +{ + int ret = 0; + if (enable) + ret = pci_siig20x_init(dev); + return ret; } +EXPORT_SYMBOL(pci_siig10x_fn); +EXPORT_SYMBOL(pci_siig20x_fn); + /* * Timedia has an explosion of boards, and to avoid the PCI table from * growing *huge*, we use this function to collapse some 70 entries @@ -385,78 +439,453 @@ static struct timedia_struct { { 0, 0 } }; -static int __devinit pci_timedia_fn(struct pci_dev *dev, int enable) +static int __devinit pci_timedia_init(struct pci_dev *dev) { - int i, j; unsigned short *ids; - - if (!enable) - return 0; + int i, j; for (i = 0; timedia_data[i].num; i++) { ids = timedia_data[i].ids; for (j = 0; ids[j]; j++) - if (pci_get_subdevice(dev) == ids[j]) + if (dev->subsystem_device == ids[j]) return timedia_data[i].num; } return 0; } /* - * HP's Remote Management Console. The Diva chip came in several - * different versions. N-class, L2000 and A500 have two Diva chips, each - * with 3 UARTs (the third UART on the second chip is unused). Superdome - * and Keystone have one Diva chip with 3 UARTs. Some later machines have - * one Diva chip, but it has been expanded to 5 UARTs. + * Timedia/SUNIX uses a mixture of BARs and offsets + * Ugh, this is ugly as all hell --- TYT */ -static int __devinit pci_hp_diva(struct pci_dev *dev, int enable) +static int +pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) { - int rc = 0; - - if (!enable) - return 0; + unsigned int bar = 0, offset = board->first_offset; - switch (dev->subsystem_device) { - case PCI_DEVICE_ID_HP_DIVA_TOSCA1: - case PCI_DEVICE_ID_HP_DIVA_HALFDOME: - case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: - case PCI_DEVICE_ID_HP_DIVA_EVEREST: - rc = 3; + switch (idx) { + case 0: + bar = 0; break; - case PCI_DEVICE_ID_HP_DIVA_TOSCA2: - rc = 2; + case 1: + offset = board->uart_offset; + bar = 0; break; - case PCI_DEVICE_ID_HP_DIVA_MAESTRO: - rc = 4; - break; - case PCI_DEVICE_ID_HP_DIVA_POWERBAR: - rc = 1; + case 2: + bar = 1; break; + case 3: + offset = board->uart_offset; + bar = 1; + case 4: /* BAR 2 */ + case 5: /* BAR 3 */ + case 6: /* BAR 4 */ + case 7: /* BAR 5 */ + bar = idx - 2; } - return rc; + return setup_port(dev, req, bar, offset, board->reg_shift); } +/* + * Some Titan cards are also a little weird + */ +static int +titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int bar, offset = board->first_offset; + + switch (idx) { + case 0: + bar = 1; + break; + case 1: + bar = 2; + break; + default: + bar = 4; + offset = (idx - 2) * board->uart_offset; + } + + return setup_port(dev, req, bar, offset, board->reg_shift); +} -static int __devinit pci_xircom_fn(struct pci_dev *dev, int enable) +static int __devinit pci_xircom_init(struct pci_dev *dev) { __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); return 0; } +static int +pci_default_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int bar, offset = board->first_offset, maxnr; + + bar = FL_GET_BASE(board->flags); + if (board->flags & FL_BASE_BARS) + bar += idx; + else + offset += idx * board->uart_offset; + + maxnr = (pci_resource_len(dev, bar) - board->uart_offset) / + (8 << board->reg_shift); + + if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) + return 1; + + return setup_port(dev, req, bar, offset, board->reg_shift); +} + +/* + * Master list of serial port init/setup/exit quirks. + * This does not describe the general nature of the port. + * (ie, baud base, number and location of ports, etc) + * + * This list is ordered alphabetically by vendor then device. + * Specific entries must come before more generic entries. + */ +static struct pci_serial_quirk pci_serial_quirks[] = { + /* + * AFAVLAB cards. + * It is not clear whether this applies to all products. + */ + { + .vendor = PCI_VENDOR_ID_AFAVLAB, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = afavlab_setup, + }, + /* + * HP Diva + */ + { + .vendor = PCI_VENDOR_ID_HP, + .device = PCI_DEVICE_ID_HP_DIVA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_hp_diva_init, + .setup = pci_hp_diva_setup, + }, + /* + * Intel + */ + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_80960_RP, + .subvendor = 0xe4bf, + .subdevice = PCI_ANY_ID, + .init = pci_inteli960ni_init, + .setup = pci_default_setup, + }, + /* + * Panacom + */ + { + .vendor = PCI_VENDOR_ID_PANACOM, + .device = PCI_DEVICE_ID_PANACOM_QUADMODEM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + { + .vendor = PCI_VENDOR_ID_PANACOM, + .device = PCI_DEVICE_ID_PANACOM_DUALMODEM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + /* + * PLX + */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9050, + .subvendor = PCI_SUBVENDOR_ID_KEYSPAN, + .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_ROMULUS, + .subvendor = PCI_VENDOR_ID_PLX, + .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + /* + * SIIG cards. + * It is not clear whether these could be collapsed. + */ + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_10x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_10x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_10x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_10x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_10x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_10x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_10x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_10x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_10x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_20x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_20x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_20x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_20x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_20x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_20x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_20x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_20x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_20x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + /* + * Titan cards + */ + { + .vendor = PCI_VENDOR_ID_TITAN, + .device = PCI_DEVICE_ID_TITAN_400L, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = titan_400l_800l_setup, + }, + { + .vendor = PCI_VENDOR_ID_TITAN, + .device = PCI_DEVICE_ID_TITAN_800L, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = titan_400l_800l_setup, + }, + /* + * Timedia cards + */ + { + .vendor = PCI_VENDOR_ID_TIMEDIA, + .device = PCI_DEVICE_ID_TIMEDIA_1889, + .subvendor = PCI_VENDOR_ID_TIMEDIA, + .subdevice = PCI_ANY_ID, + .init = pci_timedia_init, + .setup = pci_timedia_setup, + }, + { + .vendor = PCI_VENDOR_ID_TIMEDIA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_timedia_setup, + }, + /* + * Xircom cards + */ + { + .vendor = PCI_VENDOR_ID_XIRCOM, + .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_xircom_init, + .setup = pci_default_setup, + }, + /* + * Default "match everything" terminator entry + */ + { + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + } +}; + +static inline int quirk_id_matches(u32 quirk_id, u32 dev_id) +{ + return quirk_id == PCI_ANY_ID || quirk_id == dev_id; +} + +static struct pci_serial_quirk *find_quirk(struct pci_dev *dev) +{ + struct pci_serial_quirk *quirk; + + for (quirk = pci_serial_quirks; ; quirk++) + if (quirk_id_matches(quirk->vendor, dev->vendor) && + quirk_id_matches(quirk->device, dev->device) && + quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) && + quirk_id_matches(quirk->subdevice, dev->subsystem_device)) + break; + return quirk; +} + +static _INLINE_ int +get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) +{ + int base_idx; + + if ((board->flags & FL_IRQRESOURCE) == 0) + return dev->irq; + + base_idx = FL_GET_IRQBASE(board->flags); + + if (base_idx > DEVICE_COUNT_IRQ) + return 0; + + return dev->irq_resource[base_idx].start; +} + /* * This is the configuration table for all of the PCI serial boards * which we support. It is directly indexed by the pci_board_num_t enum * value, which is encoded in the pci_device_id PCI probe table's * driver_data member. + * + * The makeup of these names are: + * pbn_bn{_bt}_n_baud + * + * bn = PCI BAR number + * bt = Index using PCI BARs + * n = number of serial ports + * baud = baud rate + * + * Please note: in theory if n = 1, _bt infix should make no difference. + * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200 */ enum pci_board_num_t { - pbn_b0_1_115200, pbn_default = 0, + pbn_b0_1_115200, pbn_b0_2_115200, pbn_b0_4_115200, + pbn_b0_5_115200, pbn_b0_1_921600, pbn_b0_2_921600, @@ -465,171 +894,465 @@ enum pci_board_num_t { pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, pbn_b0_bt_8_115200, + pbn_b0_bt_1_460800, pbn_b0_bt_2_460800, + pbn_b0_bt_1_921600, + pbn_b0_bt_2_921600, + pbn_b0_bt_4_921600, + pbn_b0_bt_8_921600, + pbn_b1_1_115200, pbn_b1_2_115200, pbn_b1_4_115200, pbn_b1_8_115200, + pbn_b1_1_921600, pbn_b1_2_921600, pbn_b1_4_921600, pbn_b1_8_921600, + pbn_b1_bt_2_921600, + pbn_b1_2_1382400, pbn_b1_4_1382400, pbn_b1_8_1382400, pbn_b2_1_115200, pbn_b2_8_115200, + + pbn_b2_1_460800, pbn_b2_4_460800, pbn_b2_8_460800, pbn_b2_16_460800, + + pbn_b2_1_921600, pbn_b2_4_921600, pbn_b2_8_921600, pbn_b2_bt_1_115200, pbn_b2_bt_2_115200, pbn_b2_bt_4_115200, + pbn_b2_bt_2_921600, + pbn_b2_bt_4_921600, + + pbn_b3_4_115200, + pbn_b3_8_115200, + /* + * Board-specific versions. + */ pbn_panacom, pbn_panacom2, pbn_panacom4, pbn_plx_romulus, pbn_oxsemi, - pbn_timedia, pbn_intel_i960, pbn_sgi_ioc3, - pbn_hp_diva, pbn_nec_nile4, - - pbn_dci_pccom4, - pbn_dci_pccom8, - - pbn_xircom_combo, - - pbn_siig10x_0, - pbn_siig10x_1, - pbn_siig10x_2, - pbn_siig10x_4, - pbn_siig20x_0, - pbn_siig20x_2, - pbn_siig20x_4, - pbn_computone_4, pbn_computone_6, pbn_computone_8, }; static struct pci_board pci_boards[] __devinitdata = { + [pbn_default] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_1_115200] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_2_115200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_4_115200] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_5_115200] = { + .flags = FL_BASE0, + .num_ports = 5, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b0_1_921600] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_2_921600] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_4_921600] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_2_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_8_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b0_bt_2_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 460800, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_2_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_4_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_8_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_1_115200] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_2_115200] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_4_115200] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_8_115200] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b1_1_921600] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_2_921600] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_4_921600] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_8_921600] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_bt_2_921600] = { + .flags = FL_BASE1|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_2_1382400] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_4_1382400] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_8_1382400] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 1382400, + .uart_offset = 8, + }, + + [pbn_b2_1_115200] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_8_115200] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b2_1_460800] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_4_460800] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_8_460800] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_16_460800] = { + .flags = FL_BASE2, + .num_ports = 16, + .base_baud = 460800, + .uart_offset = 8, + }, + + [pbn_b2_1_921600] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_4_921600] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_8_921600] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b2_bt_1_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_bt_2_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_bt_4_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b2_bt_2_921600] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_bt_4_921600] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b3_4_115200] = { + .flags = FL_BASE3, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b3_8_115200] = { + .flags = FL_BASE3, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + /* - * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, - * Offset to get to next UART's registers, - * Register shift to use for memory-mapped I/O, - * Initialization function, first UART offset + * Entries following this are board-specific. */ - /* Generic serial board, pbn_b0_1_115200, pbn_default */ - { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200, - pbn_default */ - - { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */ - { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */ - - { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */ - { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */ - { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */ - - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 8, 115200 }, /* pbn_b0_bt_8_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ - - { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ - { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ - { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */ - { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */ - - { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */ - { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */ - { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */ - - { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */ - { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ - { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ - - { SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */ - { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ - { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ - { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ - { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */ - { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */ - { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */ - - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */ - - { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */ - 0x20, 2, pci_plx9050_fn, 0x03 }, + /* + * Panacom - IOMEM + */ + [pbn_panacom] = { + .flags = FL_BASE2, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + [pbn_panacom2] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + [pbn_panacom4] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + + /* I think this entry is broken - the first_offset looks wrong --rmk */ + [pbn_plx_romulus] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8 << 2, + .reg_shift = 2, + .first_offset = 0x03, + }, /* * This board uses the size of PCI Base region 0 to * signal now many ports are available */ - { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */ - { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */ - 0, 0, pci_timedia_fn }, - /* EKF addition for i960 Boards form EKF with serial port */ - { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */ - 8<<2, 2, pci_inteli960ni_fn, 0x10000}, - { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ - 1, 458333, 0, 0, 0, 0x20178 }, - { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0 },/* pbn_hp_diva */ + [pbn_oxsemi] = { + .flags = FL_BASE0|FL_REGION_SZ_CAP, + .num_ports = 32, + .base_baud = 115200, + .uart_offset = 8, + }, + + /* + * EKF addition for i960 Boards form EKF with serial port. + * Max 256 ports. + */ + [pbn_intel_i960] = { + .flags = FL_BASE0, + .num_ports = 32, + .base_baud = 921600, + .uart_offset = 8 << 2, + .reg_shift = 2, + .first_offset = 0x10000, + }, + [pbn_sgi_ioc3] = { + .flags = FL_BASE0|FL_IRQRESOURCE, + .num_ports = 1, + .base_baud = 458333, + .uart_offset = 8, + .reg_shift = 0, + .first_offset = 0x20178, + }, /* * NEC Vrc-5074 (Nile 4) builtin UART. */ - { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */ - 64, 3, NULL, 0x300 }, - - { SPCI_FL_BASE3, 4, 115200, 8 }, /* pbn_dci_pccom4 */ - { SPCI_FL_BASE3, 8, 115200, 8 }, /* pbn_dci_pccom8 */ - - { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */ - 0, 0, pci_xircom_fn }, - - { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */ - 0, 0, pci_siig20x_fn }, - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */ - 0, 0, pci_siig20x_fn }, - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */ - 0, 0, pci_siig20x_fn }, - - { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */ - 0x40, 2, NULL, 0x200 }, - { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */ - 0x40, 2, NULL, 0x200 }, - { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ - 0x40, 2, NULL, 0x200 }, + [pbn_nec_nile4] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 520833, + .uart_offset = 8 << 3, + .reg_shift = 3, + .first_offset = 0x300, + }, + + /* + * Computone - uses IOMEM. + */ + [pbn_computone_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_computone_6] = { + .flags = FL_BASE0, + .num_ports = 6, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_computone_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, }; /* @@ -640,8 +1363,7 @@ static struct pci_board pci_boards[] __devinitdata = { static int __devinit serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) { - int num_iomem = 0, num_port = 0, first_port = -1; - int i; + int num_iomem, num_port, first_port = -1, i; /* * If it is not a communications device or the programming @@ -655,36 +1377,63 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) (dev->class & 0xff) > 6) return -ENODEV; - for (i = 0; i < 6; i++) { - if (IS_PCI_REGION_IOPORT(dev, i)) { + num_iomem = num_port = 0; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO) { num_port++; if (first_port == -1) first_port = i; } - if (IS_PCI_REGION_IOMEM(dev, i)) + if (pci_resource_flags(dev, i) & IORESOURCE_MEM) num_iomem++; } /* - * If there is 1 or 0 iomem regions, and exactly one port, use - * it. + * If there is 1 or 0 iomem regions, and exactly one port, + * use it. We guess the number of ports based on the IO + * region size. */ if (num_iomem <= 1 && num_port == 1) { board->flags = first_port; + board->num_ports = pci_resource_len(dev, first_port) / 8; return 0; } + + /* + * Now guess if we've got a board which indexes by BARs. + * Each IO BAR should be 8 bytes, and they should follow + * consecutively. + */ + first_port = -1; + num_port = 0; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO && + pci_resource_len(dev, i) == 8 && + (first_port == -1 || (first_port + num_port) == i)) { + num_port++; + if (first_port == -1) + first_port = i; + } + } + + if (num_port > 1) { + board->flags = first_port | FL_BASE_BARS; + board->num_ports = num_port; + return 0; + } + return -ENODEV; } static inline int -serial_pci_matches(struct pci_board *board, int index) +serial_pci_matches(struct pci_board *board, struct pci_board *guessed) { return - board->base_baud == pci_boards[index].base_baud && - board->num_ports == pci_boards[index].num_ports && - board->uart_offset == pci_boards[index].uart_offset && - board->reg_shift == pci_boards[index].reg_shift && - board->first_uart_offset == pci_boards[index].first_uart_offset; + board->num_ports == guessed->num_ports && + board->base_baud == guessed->base_baud && + board->uart_offset == guessed->uart_offset && + board->reg_shift == guessed->reg_shift && + board->first_offset == guessed->first_offset; } /* @@ -692,10 +1441,11 @@ serial_pci_matches(struct pci_board *board, int index) * to the arrangement of serial ports on a PCI card. */ static int __devinit -pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent) +pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) { struct serial_private *priv; struct pci_board *board, tmp; + struct pci_serial_quirk *quirk; struct serial_struct serial_req; int base_baud, rc, nr_ports, i; @@ -732,92 +1482,109 @@ pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent) * detect this boards settings with our heuristic, * then we no longer need this entry. */ + memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board)); rc = serial_pci_guess_board(dev, &tmp); - if (rc == 0 && serial_pci_matches(board, pbn_default)) { - printk(KERN_INFO - "Redundant entry in serial pci_table. Please send the output\n" - "of lspci -vv, this message (0x%04x,0x%04x,0x%04x,0x%04x),\n" - "the manufacturer and name of serial board or modem board to\n" - "rmk@arm.linux.org.uk.\n", - dev->vendor, dev->device, - pci_get_subvendor(dev), pci_get_subdevice(dev)); - } + if (rc == 0 && serial_pci_matches(board, &tmp)) + moan_device("Redundant entry in serial pci_table.", + dev); } nr_ports = board->num_ports; /* - * Run the initialization function, if any. The initialization - * function returns: + * Find an init and setup quirks. + */ + quirk = find_quirk(dev); + + /* + * Run the new-style initialization function. + * The initialization function returns: * <0 - error * 0 - use board->num_ports * >0 - number of ports */ - if (board->init_fn) { - rc = board->init_fn(dev, 1); + if (quirk->init) { + rc = quirk->init(dev); if (rc < 0) goto disable; - if (rc) nr_ports = rc; } priv = kmalloc(sizeof(struct serial_private) + - sizeof(unsigned int) * nr_ports, - GFP_KERNEL); + sizeof(unsigned int) * nr_ports, + GFP_KERNEL); if (!priv) { rc = -ENOMEM; goto deinit; } + memset(priv, 0, sizeof(struct serial_private) + + sizeof(unsigned int) * nr_ports); + + priv->quirk = quirk; + pci_set_drvdata(dev, priv); + base_baud = board->base_baud; - if (!base_baud) + if (!base_baud) { + moan_device("Board entry does not specify baud rate.", dev); base_baud = BASE_BAUD; - memset(&serial_req, 0, sizeof(serial_req)); + } for (i = 0; i < nr_ports; i++) { + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE | + UPF_RESOURCES | UPF_SHARE_IRQ; + serial_req.baud_base = base_baud; serial_req.irq = get_pci_irq(dev, board, i); - if (get_pci_port(dev, board, &serial_req, i)) + if (quirk->setup(dev, board, &serial_req, i)) break; #ifdef SERIAL_DEBUG_PCI printk("Setup PCI port: port %x, irq %d, type %d\n", serial_req.port, serial_req.irq, serial_req.io_type); #endif - serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; - serial_req.baud_base = base_baud; priv->line[i] = register_serial(&serial_req); if (priv->line[i] < 0) break; } - priv->board = board; priv->nr = i; - pci_set_drvdata(dev, priv); - return 0; deinit: - if (board->init_fn) - board->init_fn(dev, 0); + if (quirk->exit) + quirk->exit(dev); disable: pci_disable_device(dev); return rc; } -static void __devexit pci_remove_one(struct pci_dev *dev) +static void __devexit pciserial_remove_one(struct pci_dev *dev) { struct serial_private *priv = pci_get_drvdata(dev); - int i; pci_set_drvdata(dev, NULL); if (priv) { + struct pci_serial_quirk *quirk; + int i; + for (i = 0; i < priv->nr; i++) unregister_serial(priv->line[i]); - if (priv->board->init_fn) - priv->board->init_fn(dev, 0); + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (priv->remapped_bar[i]) + iounmap(priv->remapped_bar[i]); + priv->remapped_bar[i] = NULL; + } + + /* + * Find the exit quirks. + */ + quirk = find_quirk(dev); + if (quirk->exit) + quirk->exit(dev); pci_disable_device(dev); @@ -825,6 +1592,53 @@ static void __devexit pci_remove_one(struct pci_dev *dev) } } +static int pciserial_save_state_one(struct pci_dev *dev, u32 state) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) { + int i; + + for (i = 0; i < priv->nr; i++) + serial8250_suspend_port(priv->line[i], SUSPEND_SAVE_STATE); + } + return 0; +} + +static int pciserial_suspend_one(struct pci_dev *dev, u32 state) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) { + int i; + + for (i = 0; i < priv->nr; i++) + serial8250_suspend_port(priv->line[i], SUSPEND_POWER_DOWN); + } + return 0; +} + +static int pciserial_resume_one(struct pci_dev *dev) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) { + int i; + + /* + * Ensure that the board is correctly configured. + */ + if (priv->quirk->init) + priv->quirk->init(dev); + + for (i = 0; i < priv->nr; i++) { + serial8250_resume_port(priv->line[i], RESUME_POWER_ON); + serial8250_resume_port(priv->line[i], RESUME_RESTORE_STATE); + } + } + return 0; +} + static struct pci_device_id serial_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, PCI_SUBVENDOR_ID_CONNECT_TECH, @@ -908,7 +1722,9 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_bt_2_921600 }, - /* VScom SPCOM800, from sl@s.pl */ + /* + * VScom SPCOM800, from sl@s.pl + */ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_8_921600 }, @@ -949,8 +1765,10 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { PCI_SUBVENDOR_ID_CHASE_PCIRAS, PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, pbn_b2_8_460800 }, - /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ - /* (Exoray@isys.ca) */ + /* + * Megawolf Romulus PCI Serial Card, from Mike Hudson + * (Exoray@isys.ca) + */ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, 0x10b5, 0x106a, 0, 0, pbn_plx_romulus }, @@ -976,16 +1794,24 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_115200 }, - /* Digitan DS560-558, from jimd@esoft.com */ + /* + * Digitan DS560-558, from jimd@esoft.com + */ { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b1_1_115200 }, - /* 3Com US Robotics 56k Voice Internal PCI model 5610 */ + /* + * 3Com US Robotics 56k Voice Internal PCI model 5610 + */ { PCI_VENDOR_ID_USR, 0x1008, - PCI_ANY_ID, PCI_ANY_ID, }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, - /* Titan Electronic cards */ + /* + * Titan Electronic cards + * The 400L and 800L have a custom setup quirk. + */ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_1_921600 }, @@ -999,120 +1825,76 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_4_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE1, 1, 921600 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, - /* The 400L and 800L have a custom hack in get_pci_port */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE_TABLE, 4, 921600 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE_TABLE, 8, 921600 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, + pbn_b2_1_460800 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, + pbn_b2_1_460800 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, + pbn_b2_1_460800 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, + pbn_b2_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, + pbn_b2_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, + pbn_b2_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, + pbn_b2_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, + pbn_b2_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, + pbn_b2_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, + pbn_b0_1_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, + pbn_b0_1_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, + pbn_b0_1_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, + pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, + pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, + pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, + pbn_b0_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, + pbn_b0_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, + pbn_b0_bt_4_921600 }, - /* Computone devices submitted by Doug McNash dmcnash@computone.com */ + /* + * Computone devices submitted by Doug McNash dmcnash@computone.com + */ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, 0, 0, pbn_computone_4 }, @@ -1124,18 +1906,22 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { 0, 0, pbn_computone_6 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi }, { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, - PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia }, + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_921600 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, - /* AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org> */ + /* + * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org> + */ { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_8_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_115200 }, @@ -1158,26 +1944,40 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_1_460800 }, - /* RAStel 2 port modem, gerg@moreton.com.au */ + /* + * RAStel 2 port modem, gerg@moreton.com.au + */ { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_bt_2_115200 }, - /* EKF addition for i960 Boards form EKF with serial port */ - { PCI_VENDOR_ID_INTEL, 0x1960, + /* + * EKF addition for i960 Boards form EKF with serial port + */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP, 0xE4BF, PCI_ANY_ID, 0, 0, pbn_intel_i960 }, - /* Xircom Cardbus/Ethernet combos */ + /* + * Xircom Cardbus/Ethernet combos + */ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_xircom_combo }, + pbn_b0_1_115200 }, + /* + * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry) + */ + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, /* * Untested PCI modems, sent in from various folks... */ - /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */ + /* + * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> + */ { PCI_VENDOR_ID_ROCKWELL, 0x1004, 0x1048, 0x1500, 0, 0, pbn_b1_1_115200 }, @@ -1186,10 +1986,12 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { 0xFF00, 0, 0, 0, pbn_sgi_ioc3 }, - /* HP Diva card */ + /* + * HP Diva card + */ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_hp_diva }, + pbn_b0_5_115200 }, { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_1_115200 }, @@ -1203,15 +2005,14 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_dci_pccom4 }, + pbn_b3_4_115200 }, { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_dci_pccom8 }, + pbn_b3_8_115200 }, /* - * These entries match devices with class - * COMMUNICATION_SERIAL, COMMUNICATION_MODEM - * or COMMUNICATION_MULTISERIAL + * These entries match devices with class COMMUNICATION_SERIAL, + * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -1230,9 +2031,15 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { static struct pci_driver serial_pci_driver = { .name = "serial", - .probe = pci_init_one, - .remove = __devexit_p(pci_remove_one), + .probe = pciserial_init_one, + .remove = __devexit_p(pciserial_remove_one), + .save_state = pciserial_save_state_one, + .suspend = pciserial_suspend_one, + .resume = pciserial_resume_one, .id_table = serial_pci_tbl, + .driver = { + .devclass = &tty_devclass, + }, }; static int __init serial8250_pci_init(void) diff --git a/drivers/serial/core.c b/drivers/serial/core.c index 5b394b10cf2e..cd71c9e65fb0 100644 --- a/drivers/serial/core.c +++ b/drivers/serial/core.c @@ -21,9 +21,6 @@ * 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 - * - * $Id: core.c,v 1.100 2002/07/28 10:03:28 rmk Exp $ - * */ #include <linux/config.h> #include <linux/module.h> @@ -31,9 +28,9 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/console.h> -#include <linux/pm.h> #include <linux/serial_core.h> #include <linux/smp_lock.h> +#include <linux/device.h> #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ #include <asm/irq.h> @@ -46,11 +43,6 @@ #define DPRINTK(x...) do { } while (0) #endif -#ifndef CONFIG_PM -#define pm_access(pm) do { } while (0) -#define pm_unregister(pm) do { } while (0) -#endif - /* * This is used to lock changes in serial line configuration. */ @@ -58,8 +50,17 @@ static DECLARE_MUTEX(port_sem); #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) -static void uart_change_speed(struct uart_info *info, struct termios *old_termios); +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0)) + +#ifdef CONFIG_SERIAL_CORE_CONSOLE +#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) +#else +#define uart_console(port) (0) +#endif + +static void uart_change_speed(struct uart_state *state, struct termios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); +static void uart_change_pm(struct uart_state *state, int pm_state); /* * This routine is used by the interrupt handler to schedule processing in @@ -73,8 +74,8 @@ void uart_write_wakeup(struct uart_port *port) static void uart_stop(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; spin_lock_irqsave(&port->lock, flags); @@ -84,32 +85,31 @@ static void uart_stop(struct tty_struct *tty) static void __uart_start(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; - if (!uart_circ_empty(&info->xmit) && info->xmit.buf && + if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && !tty->stopped && !tty->hw_stopped) port->ops->start_tx(port, 1); } static void uart_start(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; - pm_access(info->state->pm); - - spin_lock_irqsave(&info->port->lock, flags); + spin_lock_irqsave(&port->lock, flags); __uart_start(tty); - spin_unlock_irqrestore(&info->port->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } static void uart_tasklet_action(unsigned long data) { - struct uart_info *info = (struct uart_info *)data; + struct uart_state *state = (struct uart_state *)data; struct tty_struct *tty; - tty = info->tty; + tty = state->info->tty; if (tty) { if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) @@ -137,11 +137,12 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) /* * Startup the port. This will be called once per open. All calls - * will be serialised by the global port semaphore. + * will be serialised by the per-port semaphore. */ -static int uart_startup(struct uart_info *info, int init_hw) +static int uart_startup(struct uart_state *state, int init_hw) { - struct uart_port *port = info->port; + struct uart_info *info = state->info; + struct uart_port *port = state->port; unsigned long page; int retval = 0; @@ -182,7 +183,7 @@ static int uart_startup(struct uart_info *info, int init_hw) /* * Initialise the hardware port settings. */ - uart_change_speed(info, NULL); + uart_change_speed(state, NULL); /* * Setup the RTS and DTR signals once the @@ -194,8 +195,7 @@ static int uart_startup(struct uart_info *info, int init_hw) info->flags |= UIF_INITIALIZED; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + clear_bit(TTY_IO_ERROR, &info->tty->flags); } if (retval && capable(CAP_SYS_ADMIN)) @@ -207,11 +207,12 @@ static int uart_startup(struct uart_info *info, int init_hw) /* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. Calls to - * uart_shutdown are serialised by port_sem. + * uart_shutdown are serialised by the per-port semaphore. */ -static void uart_shutdown(struct uart_info *info) +static void uart_shutdown(struct uart_state *state) { - struct uart_port *port = info->port; + struct uart_info *info = state->info; + struct uart_port *port = state->port; if (!(info->flags & UIF_INITIALIZED)) return; @@ -220,7 +221,7 @@ static void uart_shutdown(struct uart_info *info) * Turn off DTR and RTS early. */ if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - uart_clear_mctrl(info->port, TIOCM_DTR | TIOCM_RTS); + uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); /* * clear delta_msr_wait queue to avoid mem leaks: we may free @@ -412,10 +413,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) EXPORT_SYMBOL(uart_get_divisor); static void -uart_change_speed(struct uart_info *info, struct termios *old_termios) +uart_change_speed(struct uart_state *state, struct termios *old_termios) { - struct tty_struct *tty = info->tty; - struct uart_port *port = info->port; + struct tty_struct *tty = state->info->tty; + struct uart_port *port = state->port; struct termios *termios; /* @@ -431,14 +432,14 @@ uart_change_speed(struct uart_info *info, struct termios *old_termios) * Set flags based on termios cflag */ if (termios->c_cflag & CRTSCTS) - info->flags |= UIF_CTS_FLOW; + state->info->flags |= UIF_CTS_FLOW; else - info->flags &= ~UIF_CTS_FLOW; + state->info->flags &= ~UIF_CTS_FLOW; if (termios->c_cflag & CLOCAL) - info->flags &= ~UIF_CHECK_CD; + state->info->flags &= ~UIF_CHECK_CD; else - info->flags |= UIF_CHECK_CD; + state->info->flags |= UIF_CHECK_CD; port->ops->set_termios(port, termios, old_termios); } @@ -526,10 +527,10 @@ __uart_kern_write(struct uart_port *port, struct circ_buf *circ, static void uart_put_char(struct tty_struct *tty, unsigned char ch) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; if (tty) - __uart_put_char(info->port, &info->xmit, ch); + __uart_put_char(state->port, &state->info->xmit, ch); } static void uart_flush_chars(struct tty_struct *tty) @@ -541,16 +542,16 @@ static int uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, int count) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; int ret; - if (!tty || !info->xmit.buf) + if (!tty || !state->info->xmit.buf) return 0; if (from_user) - ret = __uart_user_write(info->port, &info->xmit, buf, count); + ret = __uart_user_write(state->port, &state->info->xmit, buf, count); else - ret = __uart_kern_write(info->port, &info->xmit, buf, count); + ret = __uart_kern_write(state->port, &state->info->xmit, buf, count); uart_start(tty); return ret; @@ -558,29 +559,30 @@ uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, static int uart_write_room(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; - return uart_circ_chars_free(&info->xmit); + return uart_circ_chars_free(&state->info->xmit); } static int uart_chars_in_buffer(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; - return uart_circ_chars_pending(&info->xmit); + return uart_circ_chars_pending(&state->info->xmit); } static void uart_flush_buffer(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; DPRINTK("uart_flush_buffer(%d) called\n", minor(tty->device) - tty->driver.minor_start); - spin_lock_irqsave(&info->port->lock, flags); - uart_circ_clear(&info->xmit); - spin_unlock_irqrestore(&info->port->lock, flags); + spin_lock_irqsave(&port->lock, flags); + uart_circ_clear(&state->info->xmit); + spin_unlock_irqrestore(&port->lock, flags); wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) @@ -593,8 +595,8 @@ static void uart_flush_buffer(struct tty_struct *tty) */ static void uart_send_xchar(struct tty_struct *tty, char ch) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; if (port->ops->send_xchar) @@ -611,19 +613,19 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) static void uart_throttle(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; if (I_IXOFF(tty)) uart_send_xchar(tty, STOP_CHAR(tty)); if (tty->termios->c_cflag & CRTSCTS) - uart_clear_mctrl(info->port, TIOCM_RTS); + uart_clear_mctrl(state->port, TIOCM_RTS); } static void uart_unthrottle(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; if (I_IXOFF(tty)) { if (port->x_char) @@ -636,10 +638,9 @@ static void uart_unthrottle(struct tty_struct *tty) uart_set_mctrl(port, TIOCM_RTS); } -static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo) +static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo) { - struct uart_state *state = info->state; - struct uart_port *port = info->port; + struct uart_port *port = state->port; struct serial_struct tmp; memset(&tmp, 0, sizeof(tmp)); @@ -649,7 +650,7 @@ static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo) if (HIGH_BITS_OFFSET) tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET; tmp.irq = port->irq; - tmp.flags = port->flags | info->flags; + tmp.flags = port->flags; tmp.xmit_fifo_size = port->fifosize; tmp.baud_base = port->uartclk / 16; tmp.close_delay = state->close_delay; @@ -666,11 +667,10 @@ static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo) } static int -uart_set_info(struct uart_info *info, struct serial_struct *newinfo) +uart_set_info(struct uart_state *state, struct serial_struct *newinfo) { struct serial_struct new_serial; - struct uart_state *state = info->state; - struct uart_port *port = info->port; + struct uart_port *port = state->port; unsigned long new_port; unsigned int change_irq, change_port, old_flags; unsigned int old_custom_divisor; @@ -692,7 +692,7 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) * module insertion/removal doesn't change anything * under us. */ - down(&port_sem); + down(&state->sem); change_irq = new_serial.irq != port->irq; @@ -745,14 +745,14 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) /* * Make sure that we are the sole user of this port. */ - if (state->count > 1 || info->blocked_open != 0) + if (uart_users(state) > 1) goto exit; /* * We need to shutdown the serial port at the old * port/type/irq combination. */ - uart_shutdown(info); + uart_shutdown(state); } if (change_port) { @@ -813,18 +813,21 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) port->irq = new_serial.irq; port->uartclk = new_serial.baud_base * 16; - port->flags = new_serial.flags & UPF_CHANGE_MASK; + port->flags = (port->flags & ~UPF_CHANGE_MASK) | + (new_serial.flags & UPF_CHANGE_MASK); port->custom_divisor = new_serial.custom_divisor; state->close_delay = new_serial.close_delay * HZ / 100; state->closing_wait = new_serial.closing_wait * HZ / 100; port->fifosize = new_serial.xmit_fifo_size; - info->tty->low_latency = (port->flags & UPF_LOW_LATENCY) ? 1 : 0; + if (state->info->tty) + state->info->tty->low_latency = + (port->flags & UPF_LOW_LATENCY) ? 1 : 0; check_and_exit: retval = 0; if (port->type == PORT_UNKNOWN) goto exit; - if (info->flags & UIF_INITIALIZED) { + if (state->info->flags & UIF_INITIALIZED) { if (((old_flags ^ port->flags) & UPF_SPD_MASK) || old_custom_divisor != port->custom_divisor) { /* If they're setting up a custom divisor or speed, @@ -832,25 +835,26 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) * need to rate-limit; it's CAP_SYS_ADMIN only. */ if (port->flags & UPF_SPD_MASK) { printk(KERN_NOTICE "%s sets custom speed on %s%d. This is deprecated.\n", - current->comm, info->tty->driver.name, - info->port->line); + current->comm, state->info->tty->driver.name, + state->port->line); } - uart_change_speed(info, NULL); + uart_change_speed(state, NULL); } } else - retval = uart_startup(info, 1); + retval = uart_startup(state, 1); exit: - up(&port_sem); + up(&state->sem); return retval; } /* - * uart_get_lsr_info - get line status register info + * uart_get_lsr_info - get line status register info. + * Note: uart_ioctl protects us against hangups. */ -static int uart_get_lsr_info(struct uart_info *info, unsigned int *value) +static int uart_get_lsr_info(struct uart_state *state, unsigned int *value) { - struct uart_port *port = info->port; + struct uart_port *port = state->port; unsigned int result; result = port->ops->tx_empty(port); @@ -861,9 +865,9 @@ static int uart_get_lsr_info(struct uart_info *info, unsigned int *value) * avoid a race condition (depending on when the transmit * interrupt happens). */ - if (info->port->x_char || - ((uart_circ_chars_pending(&info->xmit) > 0) && - !info->tty->stopped && !info->tty->hw_stopped)) + if (port->x_char || + ((uart_circ_chars_pending(&state->info->xmit) > 0) && + !state->info->tty->stopped && !state->info->tty->hw_stopped)) result &= ~TIOCSER_TEMT; return put_user(result, value); @@ -888,6 +892,8 @@ uart_set_modem_info(struct uart_port *port, unsigned int cmd, if (get_user(arg, value)) return -EFAULT; + arg &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2; + set = clear = 0; switch (cmd) { case TIOCMBIS: @@ -911,8 +917,8 @@ uart_set_modem_info(struct uart_port *port, unsigned int cmd, static void uart_break_ctl(struct tty_struct *tty, int break_state) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; BUG_ON(!kernel_locked()); @@ -920,25 +926,25 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) port->ops->break_ctl(port, break_state); } -static int uart_do_autoconfig(struct uart_info *info) +static int uart_do_autoconfig(struct uart_state *state) { - struct uart_port *port = info->port; + struct uart_port *port = state->port; int flags, ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; /* - * Take the 'count' lock. This prevents count - * from incrementing, and hence any extra opens - * of the port while we're auto-configging. + * Take the per-port semaphore. This prevents count from + * changing, and hence any extra opens of the port while + * we're auto-configuring. */ - if (down_interruptible(&port_sem)) + if (down_interruptible(&state->sem)) return -ERESTARTSYS; ret = -EBUSY; - if (info->state->count == 1 && info->blocked_open == 0) { - uart_shutdown(info); + if (uart_users(state) == 1) { + uart_shutdown(state); /* * If we already have a port type configured, @@ -957,16 +963,22 @@ static int uart_do_autoconfig(struct uart_info *info) */ port->ops->config_port(port, flags); - ret = uart_startup(info, 1); + ret = uart_startup(state, 1); } - up(&port_sem); + up(&state->sem); return ret; } +/* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ static int -uart_wait_modem_status(struct uart_info *info, unsigned long arg) +uart_wait_modem_status(struct uart_state *state, unsigned long arg) { - struct uart_port *port = info->port; + struct uart_port *port = state->port; DECLARE_WAITQUEUE(wait, current); struct uart_icount cprev, cnow; int ret; @@ -983,7 +995,7 @@ uart_wait_modem_status(struct uart_info *info, unsigned long arg) port->ops->enable_ms(port); spin_unlock_irq(&port->lock); - add_wait_queue(&info->delta_msr_wait, &wait); + add_wait_queue(&state->info->delta_msr_wait, &wait); for (;;) { spin_lock_irq(&port->lock); memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); @@ -1011,117 +1023,144 @@ uart_wait_modem_status(struct uart_info *info, unsigned long arg) } current->state = TASK_RUNNING; - remove_wait_queue(&info->delta_msr_wait, &wait); + remove_wait_queue(&state->info->delta_msr_wait, &wait); return ret; } /* - * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. */ static int -uart_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, - unsigned long arg) +uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt) { - struct uart_info *info = tty->driver_data; struct serial_icounter_struct icount; struct uart_icount cnow; + struct uart_port *port = state->port; + + spin_lock_irq(&port->lock); + memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; +} + +/* + * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. + */ +static int +uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct uart_state *state = tty->driver_data; int ret = -ENOIOCTLCMD; BUG_ON(!kernel_locked()); - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; + /* + * These ioctls don't rely on the hardware to be present. + */ + switch (cmd) { + case TIOCGSERIAL: + ret = uart_get_info(state, (struct serial_struct *)arg); + break; + + case TIOCSSERIAL: + ret = uart_set_info(state, (struct serial_struct *)arg); + break; + + case TIOCSERCONFIG: + ret = uart_do_autoconfig(state); + break; + + case TIOCSERGWILD: /* obsolete */ + case TIOCSERSWILD: /* obsolete */ + ret = 0; + break; } - switch (cmd) { - case TIOCMGET: - ret = uart_get_modem_info(info->port, - (unsigned int *)arg); - break; + if (ret != -ENOIOCTLCMD) + goto out; - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - ret = uart_set_modem_info(info->port, cmd, - (unsigned int *)arg); - break; + if (tty->flags & (1 << TTY_IO_ERROR)) { + ret = -EIO; + goto out; + } - case TIOCGSERIAL: - ret = uart_get_info(info, (struct serial_struct *)arg); - break; + /* + * The following should only be used when hardware is present. + */ + switch (cmd) { + case TIOCMIWAIT: + ret = uart_wait_modem_status(state, arg); + break; - case TIOCSSERIAL: - ret = uart_set_info(info, (struct serial_struct *)arg); - break; + case TIOCGICOUNT: + ret = uart_get_count(state, (struct serial_icounter_struct *)arg); + break; + } - case TIOCSERCONFIG: - ret = uart_do_autoconfig(info); - break; + if (ret != -ENOIOCTLCMD) + goto out; - case TIOCSERGETLSR: /* Get line status register */ - ret = uart_get_lsr_info(info, (unsigned int *)arg); - break; + down(&state->sem); - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - ret = uart_wait_modem_status(info, arg); - break; + if (tty_hung_up_p(filp)) { + ret = -EIO; + goto out_up; + } - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - spin_lock_irq(&info->port->lock); - memcpy(&cnow, &info->port->icount, - sizeof(struct uart_icount)); - spin_unlock_irq(&info->port->lock); - - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - ret = copy_to_user((void *)arg, &icount, sizeof(icount)) - ? -EFAULT : 0; - break; + /* + * All these rely on hardware being present and need to be + * protected against the tty being hung up. + */ + switch (cmd) { + case TIOCMGET: + ret = uart_get_modem_info(state->port, (unsigned int *)arg); + break; - case TIOCSERGWILD: /* obsolete */ - case TIOCSERSWILD: /* obsolete */ - ret = 0; - break; + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + ret = uart_set_modem_info(state->port, cmd, + (unsigned int *)arg); + break; - default: { - struct uart_port *port = info->port; - if (port->ops->ioctl) - ret = port->ops->ioctl(port, cmd, arg); - break; - } + case TIOCSERGETLSR: /* Get line status register */ + ret = uart_get_lsr_info(state, (unsigned int *)arg); + break; + + default: { + struct uart_port *port = state->port; + if (port->ops->ioctl) + ret = port->ops->ioctl(port, cmd, arg); + break; + } } + out_up: + up(&state->sem); + out: return ret; } static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; unsigned long flags; unsigned int cflag = tty->termios->c_cflag; @@ -1137,11 +1176,11 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) return; - uart_change_speed(info, old_termios); + uart_change_speed(state, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) - uart_clear_mctrl(info->port, TIOCM_RTS | TIOCM_DTR); + uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR); /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { @@ -1149,15 +1188,15 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) mask |= TIOCM_RTS; - uart_set_mctrl(info->port, mask); + uart_set_mctrl(state->port, mask); } /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { - spin_lock_irqsave(&info->port->lock, flags); + spin_lock_irqsave(&state->port->lock, flags); tty->hw_stopped = 0; __uart_start(tty); - spin_unlock_irqrestore(&info->port->lock, flags); + spin_unlock_irqrestore(&state->port->lock, flags); } #if 0 @@ -1169,7 +1208,7 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios */ if (!(old_termios->c_cflag & CLOCAL) && (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&state->info->open_wait); #endif } @@ -1180,29 +1219,17 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios */ static void uart_close(struct tty_struct *tty, struct file *filp) { - struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state; - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; - struct uart_state *state; - unsigned long flags; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; BUG_ON(!kernel_locked()); + DPRINTK("uart_close(%d) called\n", port->line); - if (!info) - return; - - state = info->state; + down(&state->sem); - DPRINTK("uart_close() called\n"); - - /* - * This is safe, as long as the BKL exists in - * do_tty_hangup(), and we're protected by the BKL. - */ if (tty_hung_up_p(filp)) goto done; - spin_lock_irqsave(&info->port->lock, flags); if ((tty->count == 1) && (state->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty @@ -1217,34 +1244,28 @@ static void uart_close(struct tty_struct *tty, struct file *filp) } if (--state->count < 0) { printk("rs_close: bad serial port count for %s%d: %d\n", - tty->driver.name, info->port->line, state->count); + tty->driver.name, port->line, state->count); state->count = 0; } - if (state->count) { - spin_unlock_irqrestore(&info->port->lock, flags); + if (state->count) goto done; - } - - /* - * The UIF_CLOSING flag protects us against further opens - * of this port. - */ - info->flags |= UIF_CLOSING; - spin_unlock_irqrestore(&info->port->lock, flags); /* * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. + * the line discipline to only process XON/XOFF characters by + * setting tty->closing. */ tty->closing = 1; - if (info->state->closing_wait != USF_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->state->closing_wait); + + if (state->closing_wait != USF_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, state->closing_wait); /* * At this point, we stop accepting input. To do this, we * disable the receive line status interrupts. */ - if (info->flags & UIF_INITIALIZED) { + if (state->info->flags & UIF_INITIALIZED) { + unsigned long flags; spin_lock_irqsave(&port->lock, flags); port->ops->stop_rx(port); spin_unlock_irqrestore(&port->lock, flags); @@ -1255,46 +1276,38 @@ static void uart_close(struct tty_struct *tty, struct file *filp) */ uart_wait_until_sent(tty, port->timeout); } - down(&port_sem); - uart_shutdown(info); - up(&port_sem); + + uart_shutdown(state); uart_flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); tty->closing = 0; - info->tty = NULL; - if (info->blocked_open) { - if (info->state->close_delay) { + state->info->tty = NULL; + + if (state->info->blocked_open) { + if (state->close_delay) { set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->state->close_delay); + schedule_timeout(state->close_delay); set_current_state(TASK_RUNNING); } - } else { -#ifdef CONFIG_PM - /* - * Put device into D3 state. - */ - pm_send(info->state->pm, PM_SUSPEND, (void *)3); -#else - if (port->ops->pm) - port->ops->pm(port, 3, 0); -#endif + } else if (!uart_console(port)) { + uart_change_pm(state, 3); } /* * Wake up anyone trying to open this port. */ - info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CLOSING); - wake_up_interruptible(&info->open_wait); + state->info->flags &= ~UIF_NORMAL_ACTIVE; + wake_up_interruptible(&state->info->open_wait); done: - module_put(drv->owner); + up(&state->sem); } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long char_time, expire; BUG_ON(!kernel_locked()); @@ -1358,23 +1371,22 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) */ static void uart_hangup(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_state *state = info->state; + struct uart_state *state = tty->driver_data; BUG_ON(!kernel_locked()); + DPRINTK("uart_hangup(%d)\n", state->port->line); - uart_flush_buffer(tty); - down(&port_sem); - if (info->flags & UIF_CLOSING) { - up(&port_sem); - return; + down(&state->sem); + if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { + uart_flush_buffer(tty); + uart_shutdown(state); + state->count = 0; + state->info->flags &= ~UIF_NORMAL_ACTIVE; + state->info->tty = NULL; + wake_up_interruptible(&state->info->open_wait); + wake_up_interruptible(&state->info->delta_msr_wait); } - uart_shutdown(info); - state->count = 0; - info->flags &= ~UIF_NORMAL_ACTIVE; - info->tty = NULL; - up(&port_sem); - wake_up_interruptible(&info->open_wait); + up(&state->sem); } /* @@ -1383,18 +1395,15 @@ static void uart_hangup(struct tty_struct *tty) * kernel settings, and the settings init adopts when it opens the port * for the first time. */ -static void uart_update_termios(struct uart_info *info) +static void uart_update_termios(struct uart_state *state) { - struct tty_struct *tty = info->tty; - -#ifdef CONFIG_SERIAL_CORE_CONSOLE - struct console *c = info->port->cons; + struct tty_struct *tty = state->info->tty; + struct uart_port *port = state->port; - if (c && c->cflag && c->index == info->port->line) { - tty->termios->c_cflag = c->cflag; - c->cflag = 0; + if (uart_console(port) && port->cons->cflag) { + tty->termios->c_cflag = port->cons->cflag; + port->cons->cflag = 0; } -#endif /* * If the device failed to grab its irq resources, @@ -1405,22 +1414,26 @@ static void uart_update_termios(struct uart_info *info) /* * Make termios settings take effect. */ - uart_change_speed(info, NULL); + uart_change_speed(state, NULL); /* * And finally enable the RTS and DTR signals. */ if (tty->termios->c_cflag & CBAUD) - uart_set_mctrl(info->port, TIOCM_DTR | TIOCM_RTS); + uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } } +/* + * Block the open until the port is ready. We must be called with + * the per-port semaphore held. + */ static int -uart_block_til_ready(struct file *filp, struct uart_info *info) +uart_block_til_ready(struct file *filp, struct uart_state *state) { DECLARE_WAITQUEUE(wait, current); - struct uart_state *state = info->state; - struct uart_port *port = info->port; + struct uart_info *info = state->info; + struct uart_port *port = state->port; info->blocked_open++; state->count--; @@ -1432,18 +1445,10 @@ uart_block_til_ready(struct file *filp, struct uart_info *info) /* * If we have been hung up, tell userspace/restart open. */ - if (tty_hung_up_p(filp)) + if (tty_hung_up_p(filp) || info->tty == NULL) break; /* - * If the device is in the middle of being closed, block - * until it's done. We will need to re-initialise the - * port. Hmm, is it legal to block a non-blocking open? - */ - if (info->flags & UIF_CLOSING) - goto wait; - - /* * If the port has been closed, tell userspace/restart open. */ if (!(info->flags & UIF_INITIALIZED)) @@ -1470,7 +1475,7 @@ uart_block_til_ready(struct file *filp, struct uart_info *info) * the data from the modem. */ if (info->tty->termios->c_cflag & CBAUD) - uart_set_mctrl(info->port, TIOCM_DTR); + uart_set_mctrl(port, TIOCM_DTR); /* * and wait for the carrier to indicate that the @@ -1479,8 +1484,9 @@ uart_block_til_ready(struct file *filp, struct uart_info *info) if (port->ops->get_mctrl(port) & TIOCM_CAR) break; - wait: + up(&state->sem); schedule(); + down(&state->sem); if (signal_pending(current)) break; @@ -1494,52 +1500,56 @@ uart_block_til_ready(struct file *filp, struct uart_info *info) if (signal_pending(current)) return -ERESTARTSYS; - if (info->tty->flags & (1 << TTY_IO_ERROR)) - return 0; - - if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED)) + if (!info->tty || tty_hung_up_p(filp)) return (port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; return 0; } -static struct uart_info *uart_get(struct uart_driver *drv, int line) +static struct uart_state *uart_get(struct uart_driver *drv, int line) { - struct uart_state *state = drv->state + line; - struct uart_info *info = NULL; + struct uart_state *state; down(&port_sem); - if (!state->port) + state = drv->state + line; + if (down_interruptible(&state->sem)) { + state = ERR_PTR(-ERESTARTSYS); goto out; + } state->count++; - info = state->info; + if (!state->port) { + state->count--; + up(&state->sem); + state = ERR_PTR(-ENXIO); + goto out; + } - if (!info) { - info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); - if (info) { - memset(info, 0, sizeof(struct uart_info)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->delta_msr_wait); + if (!state->info) { + state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); + if (state->info) { + memset(state->info, 0, sizeof(struct uart_info)); + init_waitqueue_head(&state->info->open_wait); + init_waitqueue_head(&state->info->delta_msr_wait); /* * Link the info into the other structures. */ - info->port = state->port; - info->state = state; - state->port->info = info; - - tasklet_init(&info->tlet, uart_tasklet_action, - (unsigned long)info); - state->info = info; - } else + state->port->info = state->info; + + tasklet_init(&state->info->tlet, uart_tasklet_action, + (unsigned long)state); + } else { state->count--; + up(&state->sem); + state = ERR_PTR(-ENOMEM); + } } out: up(&port_sem); - return info; + return state; } /* @@ -1555,11 +1565,10 @@ static struct uart_info *uart_get(struct uart_driver *drv, int line) static int uart_open(struct tty_struct *tty, struct file *filp) { struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state; - struct uart_info *info; + struct uart_state *state; int retval, line = minor(tty->device) - tty->driver.minor_start; BUG_ON(!kernel_locked()); - DPRINTK("uart_open(%d) called\n", line); /* @@ -1572,92 +1581,66 @@ static int uart_open(struct tty_struct *tty, struct file *filp) goto fail; /* - * If we fail to increment the module use count, we can't have - * any other users of this tty (since this implies that the module - * is about to be unloaded). Therefore, it is safe to set - * tty->driver_data to be NULL, so uart_close() doesn't bite us. + * We take the semaphore inside uart_get to guarantee that we won't + * be re-entered while allocating the info structure, or while we + * request any IRQs that the driver may need. This also has the nice + * side-effect that it delays the action of uart_hangup, so we can + * guarantee that info->tty will always contain something reasonable. */ - if (!try_module_get(drv->owner)) { - tty->driver_data = NULL; + state = uart_get(drv, line); + if (IS_ERR(state)) { + retval = PTR_ERR(state); goto fail; } /* - * FIXME: This one isn't fun. We can't guarantee that the tty isn't - * already in open, nor can we guarantee the state of tty->driver_data - */ - info = uart_get(drv, line); - retval = -ENOMEM; - if (!info) { - if (tty->driver_data) - goto fail; - else - goto out; - } - - /* * Once we set tty->driver_data here, we are guaranteed that * uart_close() will decrement the driver module use count. * Any failures from here onwards should not touch the count. */ - tty->driver_data = info; - tty->low_latency = (info->port->flags & UPF_LOW_LATENCY) ? 1 : 0; + tty->driver_data = state; + tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; tty->alt_speed = 0; - info->tty = tty; + state->info->tty = tty; /* * If the port is in the middle of closing, bail out now. */ - if (tty_hung_up_p(filp) || (info->flags & UIF_CLOSING)) { - wait_event_interruptible(info->open_wait, - !(info->flags & UIF_CLOSING)); - retval = (info->port->flags & UPF_HUP_NOTIFY) ? + if (tty_hung_up_p(filp)) { + retval = (state->port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; + state->count--; + up(&state->sem); goto fail; } /* * Make sure the device is in D0 state. */ - if (info->state->count == 1) { -#ifdef CONFIG_PM - pm_send(info->state->pm, PM_RESUME, (void *)0); -#else - struct uart_port *port = info->port; - if (port->ops->pm) - port->ops->pm(port, 0, 3); -#endif - } + if (state->count == 1) + uart_change_pm(state, 0); /* - * Start up the serial port. We have this semaphore here to - * prevent uart_startup or uart_shutdown being re-entered if - * we sleep while requesting an IRQ. + * Start up the serial port. */ - down(&port_sem); - retval = uart_startup(info, 0); - up(&port_sem); - if (retval) - goto fail; + retval = uart_startup(state, 0); /* - * Wait until the port is ready. + * If we succeeded, wait until the port is ready. */ - retval = uart_block_til_ready(filp, info); + if (retval == 0) + retval = uart_block_til_ready(filp, state); + up(&state->sem); /* * If this is the first open to succeed, adjust things to suit. */ - if (retval == 0 && !(info->flags & UIF_NORMAL_ACTIVE)) { - info->flags |= UIF_NORMAL_ACTIVE; + if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) { + state->info->flags |= UIF_NORMAL_ACTIVE; - uart_update_termios(info); + uart_update_termios(state); } - return retval; - - out: - module_put(drv->owner); fail: return retval; } @@ -1892,115 +1875,98 @@ uart_set_options(struct uart_port *port, struct console *co, } #endif /* CONFIG_SERIAL_CORE_CONSOLE */ -#ifdef CONFIG_PM -/* - * Serial port power management. - * - * This is pretty coarse at the moment - either all on or all off. We - * should probably some day do finer power management here some day. - * - * We don't actually save any state; the serial driver already has the - * state held internally to re-setup the port when we come out of D3. - */ -static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstate) +static void uart_change_pm(struct uart_state *state, int pm_state) { - struct uart_port *port; - struct uart_ops *ops; - int running = state->info && - state->info->flags & UIF_INITIALIZED; + struct uart_port *port = state->port; + if (port->ops->pm) + port->ops->pm(port, pm_state, state->pm_state); + state->pm_state = pm_state; +} - down(&port_sem); +int uart_suspend_port(struct uart_driver *drv, struct uart_port *port, u32 level) +{ + struct uart_state *state = drv->state + port->line; - if (!state->port || state->port->type == PORT_UNKNOWN) { - up(&port_sem); - return 0; - } + down(&state->sem); - port = state->port; - ops = port->ops; + switch (level) { + case SUSPEND_SAVE_STATE: + if (state->info && state->info->flags & UIF_INITIALIZED) { + struct uart_ops *ops = port->ops; - DPRINTK("pm: %08x: %d -> %d, %srunning\n", - port->iobase, dev->state, pm_state, running ? "" : "not "); + spin_lock_irq(&port->lock); + ops->stop_tx(port, 0); + ops->set_mctrl(port, 0); + ops->stop_rx(port); + spin_unlock_irq(&port->lock); - if (pm_state == 0) { - if (ops->pm) - ops->pm(port, pm_state, oldstate); - if (running) { /* - * The port lock isn't taken here - - * the port isn't initialised. + * Wait for the transmitter to empty. */ - ops->set_mctrl(port, 0); - ops->startup(port); - uart_change_speed(state->info, NULL); - spin_lock_irq(&port->lock); - ops->set_mctrl(port, port->mctrl); - ops->start_tx(port, 0); - spin_unlock_irq(&port->lock); + while (!ops->tx_empty(port)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(10*HZ/1000); + } + set_current_state(TASK_RUNNING); + + ops->shutdown(port); } + break; - /* - * Re-enable the console device after suspending. - */ - if (port->cons && port->cons->index == port->line) - port->cons->flags |= CON_ENABLED; - } else if (pm_state == 1) { - if (ops->pm) - ops->pm(port, pm_state, oldstate); - } else { + case SUSPEND_POWER_DOWN: /* * Disable the console device before suspending. */ - if (port->cons && port->cons->index == port->line) + if (uart_console(port)) port->cons->flags &= ~CON_ENABLED; - if (running) { - spin_lock_irq(&port->lock); - ops->stop_tx(port, 0); - ops->set_mctrl(port, 0); - ops->stop_rx(port); - spin_unlock_irq(&port->lock); - ops->shutdown(port); - } - if (ops->pm) - ops->pm(port, pm_state, oldstate); + uart_change_pm(state, 3); + break; } - up(&port_sem); + + up(&state->sem); return 0; } -/* - * Wakeup support. - */ -static int uart_pm_set_wakeup(struct uart_state *state, int data) +int uart_resume_port(struct uart_driver *drv, struct uart_port *port, u32 level) { - int err = 0; - - if (state->port->ops->set_wake) - err = state->port->ops->set_wake(state->port, data); + struct uart_state *state = drv->state + port->line; - return err; -} + down(&state->sem); -static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - struct uart_state *state = dev->data; - int err = 0; + switch (level) { + case RESUME_POWER_ON: + uart_change_pm(state, 0); - switch (rqst) { - case PM_SUSPEND: - case PM_RESUME: - err = uart_pm_set_state(state, (int)(long)data, dev->state); + /* + * Re-enable the console device after suspending. + */ + if (uart_console(port)) { + uart_change_speed(state, NULL); + port->cons->flags |= CON_ENABLED; + } break; - case PM_SET_WAKEUP: - err = uart_pm_set_wakeup(state, (int)(long)data); + case RESUME_RESTORE_STATE: + if (state->info && state->info->flags & UIF_INITIALIZED) { + struct uart_ops *ops = port->ops; + + ops->set_mctrl(port, 0); + ops->startup(port); + uart_change_speed(state, NULL); + spin_lock_irq(&port->lock); + ops->set_mctrl(port, port->mctrl); + ops->start_tx(port, 0); + spin_unlock_irq(&port->lock); + } break; } - return err; + + up(&state->sem); + + return 0; } -#endif static inline void uart_report_port(struct uart_driver *drv, struct uart_port *port) @@ -2022,17 +1988,11 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) } static void -__uart_register_port(struct uart_driver *drv, struct uart_state *state, - struct uart_port *port) +uart_configure_port(struct uart_driver *drv, struct uart_state *state, + struct uart_port *port) { unsigned int flags; - state->port = port; - - spin_lock_init(&port->lock); - port->cons = drv->cons; - port->info = state->info; - /* * If there isn't a port here, don't do anything further. */ @@ -2051,12 +2011,6 @@ __uart_register_port(struct uart_driver *drv, struct uart_state *state, port->ops->config_port(port, flags); } - /* - * Register the port whether it's detected or not. This allows - * setserial to be used to alter this ports parameters. - */ - tty_register_device(drv->tty_driver, drv->minor + port->line); - if (port->type != PORT_UNKNOWN) { unsigned long flags; @@ -2070,51 +2024,33 @@ __uart_register_port(struct uart_driver *drv, struct uart_state *state, port->ops->set_mctrl(port, 0); spin_unlock_irqrestore(&port->lock, flags); -#ifdef CONFIG_PM /* * Power down all ports by default, except the - * console if we have one. We need to drop the - * port semaphore here. + * console if we have one. */ - if (state->pm && (!drv->cons || port->line != drv->cons->index)) { - up(&port_sem); - pm_send(state->pm, PM_SUSPEND, (void *)3); - down(&port_sem); - } -#endif + if (!uart_console(port)) + uart_change_pm(state, 3); } } /* - * Hangup the port. This must be done outside the port_sem - * since uart_hangup() grabs this same semaphore. Grr. + * This reverses the affects of uart_configure_port, hanging up the + * port before removal. */ static void -__uart_hangup_port(struct uart_driver *drv, struct uart_state *state) +uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) { + struct uart_port *port = state->port; struct uart_info *info = state->info; if (info && info->tty) tty_vhangup(info->tty); -} -/* - * This reverses the affects of __uart_register_port. - */ -static void -__uart_unregister_port(struct uart_driver *drv, struct uart_state *state) -{ - struct uart_port *port = state->port; - struct uart_info *info = state->info; + down(&state->sem); state->info = NULL; /* - * Remove the devices from devfs - */ - tty_unregister_device(drv->tty_driver, drv->minor + port->line); - - /* * Free the port IO and memory resources, if any. */ if (port->type != PORT_UNKNOWN) @@ -2132,6 +2068,8 @@ __uart_unregister_port(struct uart_driver *drv, struct uart_state *state) tasklet_kill(&info->tlet); kfree(info); } + + up(&state->sem); } /** @@ -2186,6 +2124,7 @@ int uart_register_driver(struct uart_driver *drv) drv->tty_driver = normal; normal->magic = TTY_DRIVER_MAGIC; + normal->owner = drv->owner; normal->driver_name = drv->driver_name; normal->name = drv->dev_name; normal->major = drv->major; @@ -2232,20 +2171,13 @@ int uart_register_driver(struct uart_driver *drv) state->close_delay = 5 * HZ / 10; state->closing_wait = 30 * HZ; -#ifdef CONFIG_PM - state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm); - if (state->pm) - state->pm->data = state; -#endif + + init_MUTEX(&state->sem); } retval = tty_register_driver(normal); out: if (retval < 0) { -#ifdef CONFIG_PM - for (i = 0; i < drv->nr; i++) - pm_unregister(drv->state[i].pm); -#endif kfree(normal); kfree(drv->state); kfree(termios); @@ -2264,11 +2196,6 @@ int uart_register_driver(struct uart_driver *drv) */ void uart_unregister_driver(struct uart_driver *drv) { - int i; - - for (i = 0; i < drv->nr; i++) - pm_unregister(drv->state[i].pm); - tty_unregister_driver(drv->tty_driver); kfree(drv->state); @@ -2289,6 +2216,7 @@ void uart_unregister_driver(struct uart_driver *drv) int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state; + int ret = 0; BUG_ON(in_interrupt()); @@ -2298,10 +2226,29 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) state = drv->state + port->line; down(&port_sem); - __uart_register_port(drv, state, port); + if (state->port) { + ret = -EINVAL; + goto out; + } + + state->port = port; + + spin_lock_init(&port->lock); + port->cons = drv->cons; + port->info = state->info; + + uart_configure_port(drv, state, port); + + /* + * Register the port whether it's detected or not. This allows + * setserial to be used to alter this ports parameters. + */ + tty_register_device(drv->tty_driver, drv->minor + port->line); + + out: up(&port_sem); - return 0; + return ret; } /** @@ -2323,10 +2270,14 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) printk(KERN_ALERT "Removing wrong port: %p != %p\n", state->port, port); - __uart_hangup_port(drv, state); - down(&port_sem); - __uart_unregister_port(drv, state); + + /* + * Remove the devices from devfs + */ + tty_unregister_device(drv->tty_driver, drv->minor + port->line); + + uart_unconfigure_port(drv, state); state->port = NULL; up(&port_sem); @@ -2426,8 +2377,7 @@ int uart_register_port(struct uart_driver *drv, struct uart_port *port) * alter it underneath itself - the port may be open and * trying to do useful work. */ - if (state->count != 0 || - (state->info && state->info->blocked_open != 0)) { + if (uart_users(state) != 0) { ret = -EBUSY; goto out; } @@ -2447,7 +2397,7 @@ int uart_register_port(struct uart_driver *drv, struct uart_port *port) state->port->line = state - drv->state; state->port->mapbase = port->mapbase; - __uart_register_port(drv, state, state->port); + uart_configure_port(drv, state, state->port); } ret = state->port->line; @@ -2479,16 +2429,16 @@ void uart_unregister_port(struct uart_driver *drv, int line) state = drv->state + line; - __uart_hangup_port(drv, state); - down(&port_sem); - __uart_unregister_port(drv, state); + uart_unconfigure_port(drv, state); up(&port_sem); } EXPORT_SYMBOL(uart_write_wakeup); EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); +EXPORT_SYMBOL(uart_suspend_port); +EXPORT_SYMBOL(uart_resume_port); EXPORT_SYMBOL(uart_register_port); EXPORT_SYMBOL(uart_unregister_port); EXPORT_SYMBOL(uart_add_one_port); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index cf3160b26f57..b32608e75444 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -32,6 +32,7 @@ #include <linux/serial.h> #include <linux/console.h> #include <linux/sysrq.h> +#include <linux/device.h> #include <asm/io.h> #include <asm/irq.h> @@ -857,12 +858,54 @@ static struct uart_driver sa1100_reg = { .cons = SA1100_CONSOLE, }; +static int sa1100_serial_suspend(struct device *dev, u32 state, u32 level) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) + uart_suspend_port(&sa1100_reg, &sa1100_ports[i].port, level); + + return 0; +} + +static int sa1100_serial_resume(struct device *dev, u32 level) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) + uart_resume_port(&sa1100_reg, &sa1100_ports[i].port, level); + + return 0; +} + +static struct device_driver sa11x0_serial_driver = { + .name = "sa11x0_serial", + .bus = &system_bus_type, + .devclass = &tty_devclass, + .suspend = sa1100_serial_suspend, + .resume = sa1100_serial_resume, +}; + +/* + * This "device" covers _all_ ISA 8250-compatible serial devices. + */ +static struct sys_device sa11x0_serial_devs = { + .name = "sa11x0_serial", + .id = 0, + .dev = { + .driver = &sa11x0_serial_driver, + }, +}; + static int __init sa1100_serial_init(void) { int ret; printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n"); + driver_register(&sa11x0_serial_driver); + sys_device_register(&sa11x0_serial_devs); + sa1100_init_ports(); ret = uart_register_driver(&sa1100_reg); if (ret == 0) { diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c index d7cc97c9eff1..b83068f9f13a 100644 --- a/drivers/usb/class/bluetty.c +++ b/drivers/usb/class/bluetty.c @@ -168,7 +168,7 @@ struct usb_bluetooth { int magic; struct usb_device * dev; struct tty_driver * tty_driver; /* the tty_driver for this device */ - struct tty_struct * tty; /* the coresponding tty for this port */ + struct tty_struct * tty; /* the corresponding tty for this port */ unsigned char minor; /* the starting minor number for this device */ int throttle; /* throttled by tty layer */ @@ -1328,7 +1328,7 @@ int usb_bluetooth_init(void) int i; int result; - /* Initalize our global data */ + /* Initialize our global data */ for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) { bluetooth_table[i] = NULL; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5cd38d761590..7a6b3d0204e8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -138,9 +138,9 @@ struct acm_line { */ struct acm { - struct usb_device *dev; /* the coresponding usb device */ + struct usb_device *dev; /* the corresponding usb device */ struct usb_interface *iface; /* the interfaces - +0 control +1 data */ - struct tty_struct *tty; /* the coresponding tty */ + struct tty_struct *tty; /* the corresponding tty */ struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ struct acm_line line; /* line coding (bits, stop, parity) */ struct work_struct work; /* work queue entry for line discipline waking up */ diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c index 4e6d970299da..1361485d7629 100644 --- a/drivers/usb/class/usb-midi.c +++ b/drivers/usb/class/usb-midi.c @@ -1270,7 +1270,7 @@ static void *find_descriptor( void *descStart, unsigned int descLength, void *af return NULL; } -/** Utility to find a class-specfic interface descriptor. +/** Utility to find a class-specific interface descriptor. * dsubtype is a descriptor subtype * Called by parseDescriptor(); **/ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cd039053c127..b8f282d5524a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -516,7 +516,7 @@ descriptor_error: endpoint = &desc->endpoint[0].desc; - /* Output endpoint? Curiousier and curiousier.. */ + /* Output endpoint? Curiouser and curiouser.. */ if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { goto descriptor_error; } @@ -958,7 +958,7 @@ static void usb_hub_events(void) int i, ret; /* - * We restart the list everytime to avoid a deadlock with + * We restart the list every time to avoid a deadlock with * deleting hubs downstream from this one. This should be * safe since we delete the hub from the event list. * Not the most efficient, but avoids deadlocks. diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index a33c33b08082..8b2624844cb1 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -69,7 +69,7 @@ void usb_free_urb(struct urb *urb) * usb_get_urb - increments the reference count of the urb * @urb: pointer to the urb to modify * - * This must be called whenever a urb is transfered from a device driver to a + * This must be called whenever a urb is transferred from a device driver to a * host controller driver. This allows proper reference counting to happen * for urbs. * @@ -383,7 +383,7 @@ int usb_unlink_urb(struct urb *urb) { /* FIXME * We should not care about the state here, but the host controllers - * die a horrible death if we submit a urb for a device that has been + * die a horrible death if we unlink a urb for a device that has been * physically removed. */ if (urb && diff --git a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c index 5d4cf5c02971..f970656f0810 100644 --- a/drivers/usb/host/hc_simple.c +++ b/drivers/usb/host/hc_simple.c @@ -605,7 +605,7 @@ static struct urb *qu_return_urb (hci_t * hci, struct urb * urb, int resub_ok) /*************************************************************************** * Function Name : sh_scan_iso_urb_list * - * This function goes throught the isochronous urb list and schedule the + * This function goes through the isochronous urb list and schedule the * the transfer. * * Note: This function has not tested yet diff --git a/drivers/usb/host/hc_simple.h b/drivers/usb/host/hc_simple.h index dfb67e7d964e..d0289f62f058 100644 --- a/drivers/usb/host/hc_simple.h +++ b/drivers/usb/host/hc_simple.h @@ -44,8 +44,8 @@ struct virt_root_hub { int devnum; /* Address of Root Hub endpoint */ void *urb; /* interrupt URB of root hub */ int send; /* active flag */ - int interval; /* intervall of roothub interrupt transfers */ - struct timer_list rh_int_timer; /* intervall timer for rh interrupt EP */ + int interval; /* interval of roothub interrupt transfers */ + struct timer_list rh_int_timer; /* interval timer for rh interrupt EP */ }; #if 1 diff --git a/drivers/usb/host/hc_sl811.h b/drivers/usb/host/hc_sl811.h index 1618d233f236..8b9eed235088 100644 --- a/drivers/usb/host/hc_sl811.h +++ b/drivers/usb/host/hc_sl811.h @@ -368,7 +368,7 @@ struct hci; #define SL11H_CTL1VAL_RESET 8 -/* Interrut enable (addr 6) and interrupt status register bits (addr 0xD) */ +/* Interrupt enable (addr 6) and interrupt status register bits (addr 0xD) */ #define SL11H_INTMASK_XFERDONE 1 #define SL11H_INTMASK_SOFINTR 0x10 #define SL11H_INTMASK_INSRMV 0x20 diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index a25daa6c899f..f531767a9ecd 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -650,7 +650,7 @@ static void td_submit_urb ( /* calculate transfer length/status and update the urb * PRECONDITION: irqsafe (only for urb->status locking) */ -static void td_done (struct urb *urb, struct td *td) +static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) { u32 tdINFO = le32_to_cpup (&td->hwINFO); int cc = 0; @@ -908,7 +908,7 @@ rescan_this: *prev = td->hwNextTD | savebits; /* HC may have partly processed this TD */ - td_done (urb, td); + td_done (ohci, urb, td); urb_priv->td_cnt++; /* if URB is done, clean up */ @@ -991,7 +991,7 @@ dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs) struct ed *ed = td->ed; /* update URB's length and status from TD */ - td_done (urb, td); + td_done (ohci, urb, td); urb_priv->td_cnt++; /* If all this urb's TDs are done, call complete() */ diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index c3c0a7505765..06541479c29f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -136,7 +136,7 @@ static inline void uhci_add_complete(struct uhci_hcd *uhci, struct urb *urb) unsigned long flags; spin_lock_irqsave(&uhci->complete_list_lock, flags); - list_add(&urbp->complete_list, &uhci->complete_list); + list_add_tail(&urbp->complete_list, &uhci->complete_list); spin_unlock_irqrestore(&uhci->complete_list_lock, flags); } diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c index 9590371e8203..1b74264ee8e5 100644 --- a/drivers/usb/image/hpusbscsi.c +++ b/drivers/usb/image/hpusbscsi.c @@ -303,7 +303,7 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback) } else { usb_callback = simple_payload_callback; } - /* Now we find out which direction data is to be transfered in */ + /* Now we find out which direction data is to be transferred in */ hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ? usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in) : @@ -410,7 +410,7 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); } if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 ) - /* we do a callback to the scsi layer if and only if all data has been transfered */ + /* we do a callback to the scsi layer if and only if all data has been transferred */ hpusbscsi->scallback(hpusbscsi->srb); TRACE_STATE; diff --git a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h index 6e83344dcaa9..b56f091cdd39 100644 --- a/drivers/usb/image/hpusbscsi.h +++ b/drivers/usb/image/hpusbscsi.h @@ -85,7 +85,7 @@ static Scsi_Host_Template hpusbscsi_scsi_host_template = { /* defines for internal driver state */ #define HP_STATE_FREE 0 /*ready for next request */ -#define HP_STATE_BEGINNING 1 /*command being transfered */ +#define HP_STATE_BEGINNING 1 /*command being transferred */ #define HP_STATE_WORKING 2 /* data transfer stage */ #define HP_STATE_ERROR 3 /* error has been reported */ #define HP_STATE_WAIT 4 /* waiting for status transfer */ diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c index c8d1dd5e0835..6fb7c46362d6 100644 --- a/drivers/usb/image/scanner.c +++ b/drivers/usb/image/scanner.c @@ -1,7 +1,7 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.5.64) + * Driver for USB Scanners (linux-2.5) * * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson * Copyright (C) 2002, 2003 Henning Meier-Geinitz @@ -33,8 +33,8 @@ * 0.1 8/31/1999 * * Developed/tested using linux-2.3.15 with minor ohci.c changes to - * support short packes during bulk xfer mode. Some testing was - * done with ohci-hcd but the performace was low. Very limited + * support short packets during bulk xfer mode. Some testing was + * done with ohci-hcd but the performance was low. Very limited * testing was performed with uhci but I was unable to get it to * work. Initial relase to the linux-usb development effort. * @@ -338,7 +338,7 @@ * Till Kamppeter <till.kamppeter@gmx.net> and others for all the ids. * - Cleaned up list of vendor/product ids. * - Print information about user-supplied ids only once at startup instead - * of everytime any USB device is plugged in. + * of every time any USB device is plugged in. * - Removed PV8630 ioctls. Use the standard ioctls instead. * - Made endpoint detection more generic. Basically, only one bulk-in * endpoint is required, everything else is optional. @@ -350,6 +350,9 @@ * - Added vendor/product ids for Artec, Avision, Brother, Medion, Primax, * Prolink, Fujitsu, Plustek, and SYSCAN scanners. * - Fixed generation of devfs names if dynamic minors are disabled. + * - Used kobject reference counting to free the scn struct when the device + * is closed and disconnected. Avoids crashes when writing to a + * disconnected device. (Thanks to Greg KH). * * TODO * - Performance @@ -427,6 +430,7 @@ irq_scanner(struct urb *urb, struct pt_regs *regs) return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + return; } dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data); @@ -461,6 +465,7 @@ open_scanner(struct inode * inode, struct file * file) return -ENODEV; } scn = usb_get_intfdata(intf); + kobject_get(&scn->kobj); dev = scn->scn_dev; @@ -521,6 +526,8 @@ close_scanner(struct inode * inode, struct file * file) up(&scn_mutex); up(&(scn->sem)); + kobject_put(&scn->kobj); + return 0; } @@ -813,6 +820,37 @@ ioctl_scanner(struct inode *inode, struct file *file, return retval; } +static void destroy_scanner (struct kobject *kobj) +{ + struct scn_usb_data *scn; + + dbg ("%s", __FUNCTION__); + + scn = to_scanner(kobj); + + down (&scn_mutex); + down (&(scn->sem)); + + usb_driver_release_interface(&scanner_driver, + &scn->scn_dev->actconfig->interface[scn->ifnum]); + + kfree(scn->ibuf); + kfree(scn->obuf); + + dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor); + devfs_unregister(scn->devfs); + usb_deregister_dev(1, scn->scn_minor); + usb_free_urb(scn->scn_irq); + usb_put_dev(scn->scn_dev); + up (&(scn->sem)); + kfree (scn); + up (&scn_mutex); +} + +static struct kobj_type scanner_kobj_type = { + .release = destroy_scanner, +}; + static struct file_operations usb_scanner_fops = { .owner = THIS_MODULE, @@ -982,6 +1020,8 @@ probe_scanner(struct usb_interface *intf, return -ENOMEM; } memset (scn, 0, sizeof(struct scn_usb_data)); + kobject_init(&scn->kobj); + scn->kobj.ktype = &scanner_kobj_type; scn->scn_irq = usb_alloc_urb(0, GFP_KERNEL); if (!scn->scn_irq) { @@ -1049,6 +1089,7 @@ probe_scanner(struct usb_interface *intf, } + usb_get_dev(dev); scn->bulk_in_ep = have_bulk_in; scn->bulk_out_ep = have_bulk_out; scn->intr_ep = have_intr; @@ -1089,28 +1130,13 @@ disconnect_scanner(struct usb_interface *intf) intf->kdev = NODEV; usb_set_intfdata(intf, NULL); - if (scn) { - down (&scn_mutex); - down (&(scn->sem)); - - if(scn->intr_ep) { - dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor); - usb_unlink_urb(scn->scn_irq); - } - usb_driver_release_interface(&scanner_driver, - &scn->scn_dev->actconfig->interface[scn->ifnum]); - - kfree(scn->ibuf); - kfree(scn->obuf); - - dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor); - devfs_unregister(scn->devfs); - usb_deregister_dev(1, scn->scn_minor); - usb_free_urb(scn->scn_irq); - up (&(scn->sem)); - kfree (scn); - up (&scn_mutex); + if(scn->intr_ep) { + dbg("%s(%d): Unlinking IRQ URB", __FUNCTION__, scn->scn_minor); + usb_unlink_urb(scn->scn_irq); } + + if (scn) + kobject_put(&scn->kobj); } /* we want to look at all devices, as the vendor/product id can change diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h index 93be043c7a62..dc77eb090dec 100644 --- a/drivers/usb/image/scanner.h +++ b/drivers/usb/image/scanner.h @@ -1,5 +1,5 @@ /* - * Driver for USB Scanners (linux-2.5.64) + * Driver for USB Scanners (linux-2.5) * * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson * Previously maintained by Brian Beattie @@ -335,7 +335,9 @@ struct scn_usb_data { wait_queue_head_t rd_wait_q; /* read timeouts */ struct semaphore sem; /* lock to prevent concurrent reads or writes */ unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */ + struct kobject kobj; /* Handles our reference counting */ }; +#define to_scanner(d) container_of(d, struct scn_usb_data, kobj) extern devfs_handle_t usb_devfs_handle; diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 0b222dd524c1..4da30222593a 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -954,7 +954,7 @@ void hid_output_report(struct hid_report *report, __u8 *data) /* * Set a field value. The report this field belongs to has to be - * created and transfered to the device, to set this value in the + * created and transferred to the device, to set this value in the * device. */ diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index c614338be50f..da0267893d06 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -480,7 +480,7 @@ static void hidinput_close(struct input_dev *dev) /* * Register the input device; print a message. * Configure the input layer interface - * Read all reports and initalize the absoulte field values. + * Read all reports and initialize the absolute field values. */ int hidinput_connect(struct hid_device *hid) diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 70cab1643aa7..a6081d795493 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -209,8 +209,8 @@ struct hid_item { #define HID_QUIRK_BADPAD 0x20 /* - * This is the global enviroment of the parser. This information is - * persistent for main-items. The global enviroment can be saved and + * This is the global environment of the parser. This information is + * persistent for main-items. The global environment can be saved and * restored with PUSH/POP statements. */ @@ -228,7 +228,7 @@ struct hid_global { }; /* - * This is the local enviroment. It is resistent up the next main-item. + * This is the local environment. It is persistent up the next main-item. */ #define HID_MAX_DESCRIPTOR_SIZE 4096 diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c index cc099cb8d91d..cabf38496d33 100644 --- a/drivers/usb/media/dsbr100.c +++ b/drivers/usb/media/dsbr100.c @@ -33,6 +33,12 @@ History: + Version 0.30: + Markus: Updates for 2.5.x kernel and more ISO compiant source + + Version 0.25: + PSL and Markus: Cleanup, radio now doesn't stop on device close + Version 0.24: Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally right. Some minor cleanup, improved standalone compilation @@ -69,15 +75,22 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.24" +#define DRIVER_VERSION "v0.25" #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>" -#define DRIVER_DESC "D-Link DSB-R100 USB radio driver" +#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" #define DSB100_VENDOR 0x04b4 #define DSB100_PRODUCT 0x1002 #define TB_LEN 16 +/* Frequency limits in MHz -- these are European values. For Japanese +devices, that would be 76 and 91. */ +#define FREQ_MIN 87.5 +#define FREQ_MAX 108.0 +#define FREQ_MUL 16000 + + static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_interface *intf); @@ -108,7 +121,7 @@ static struct file_operations usb_dsbr100_fops = { static struct video_device usb_dsbr100_radio= { .owner = THIS_MODULE, - .name = "D-Link DSB R-100 USB radio", + .name = "D-Link DSB-R 100", .type = VID_TYPE_TUNER, .hardware = VID_HARDWARE_AZTECH, .fops = &usb_dsbr100_fops, @@ -189,7 +202,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, return -ENOMEM; usb_dsbr100_radio.priv = radio; radio->dev = interface_to_usbdev (intf); - radio->curfreq = 1454000; + radio->curfreq = FREQ_MIN*FREQ_MUL; usb_set_intfdata (intf, radio); return 0; } @@ -225,11 +238,11 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, { case VIDIOCGCAP: { struct video_capability *v = arg; - memset(v,0,sizeof(*v)); - v->type=VID_TYPE_TUNER; - v->channels=1; - v->audios=1; - strcpy(v->name, "D-Link R-100 USB Radio"); + memset(v, 0, sizeof(*v)); + v->type = VID_TYPE_TUNER; + v->channels = 1; + v->audios = 1; + strcpy(v->name, "D-Link R-100 USB FM Radio"); return 0; } case VIDIOCGTUNER: { @@ -237,8 +250,8 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, dsbr100_getstat(radio); if(v->tuner) /* Only 1 tuner */ return -EINVAL; - v->rangelow = 87*16000; - v->rangehigh = 108*16000; + v->rangelow = FREQ_MIN*FREQ_MUL; + v->rangehigh = FREQ_MAX*FREQ_MUL; v->flags = VIDEO_TUNER_LOW; v->mode = VIDEO_MODE_AUTO; v->signal = radio->stereo*0x7000; @@ -268,31 +281,31 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, radio->curfreq = *freq; if (dsbr100_setfreq(radio, radio->curfreq)==-1) - warn("set frequency failed"); + warn("Set frequency failed"); return 0; } case VIDIOCGAUDIO: { struct video_audio *v = arg; - memset(v,0, sizeof(*v)); - v->flags|=VIDEO_AUDIO_MUTABLE; - v->mode=VIDEO_SOUND_STEREO; - v->volume=1; - v->step=1; + memset(v, 0, sizeof(*v)); + v->flags |= VIDEO_AUDIO_MUTABLE; + v->mode = VIDEO_SOUND_STEREO; + v->volume = 1; + v->step = 1; strcpy(v->name, "Radio"); return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if (v->audio) return -EINVAL; - if(v->flags&VIDEO_AUDIO_MUTE) { + if (v->flags&VIDEO_AUDIO_MUTE) { if (dsbr100_stop(radio)==-1) - warn("radio did not respond properly"); + warn("Radio did not respond properly"); } else if (dsbr100_start(radio)==-1) - warn("radio did not respond properly"); + warn("Radio did not respond properly"); return 0; } default: @@ -312,18 +325,18 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) usb_dsbr100 *radio=dev->priv; if (! radio) { - warn("radio not initialised"); + warn("Radio not initialised"); return -EAGAIN; } if(users) { - warn("radio in use"); + warn("Radio in use"); return -EBUSY; } users++; if (dsbr100_start(radio)<0) - warn("radio did not start up properly"); - dsbr100_setfreq(radio,radio->curfreq); + warn("Radio did not start up properly"); + dsbr100_setfreq(radio, radio->curfreq); return 0; } @@ -335,7 +348,6 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file) if (!radio) return -ENODEV; users--; - dsbr100_stop(radio); return 0; } @@ -343,8 +355,9 @@ static int __init dsbr100_init(void) { usb_dsbr100_radio.priv = NULL; usb_register(&usb_dsbr100_driver); - if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO,radio_nr)==-1) { - warn("couldn't register video device"); + if (video_register_device(&usb_dsbr100_radio, VFL_TYPE_RADIO, + radio_nr)==-1) { + warn("Couldn't register video device"); return -EINVAL; } info(DRIVER_VERSION ":" DRIVER_DESC); @@ -367,9 +380,3 @@ module_exit (dsbr100_exit); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); - -/* -vi: ts=8 -Sigh. Of course, I am one of the ts=2 heretics, but Linus' wish is -my command. -*/ diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c index 90049bc8993a..b79f0e816d4d 100644 --- a/drivers/usb/media/konicawc.c +++ b/drivers/usb/media/konicawc.c @@ -65,7 +65,7 @@ static const int debug = 0; #endif -/* Some default values for inital camera settings, +/* Some default values for initial camera settings, can be set by modprobe */ static enum frame_sizes size; diff --git a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c index 92c5c8239913..a1af23e7b589 100644 --- a/drivers/usb/media/pwc-ctrl.c +++ b/drivers/usb/media/pwc-ctrl.c @@ -129,7 +129,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] = 4 compression modi: none, low, medium, high When an uncompressed mode is not available, the next available compressed mode - will be choosen (unless the decompressor is absent). Sometimes there are only + will be chosen (unless the decompressor is absent). Sometimes there are only 1 or 2 compressed modes available; in that case entries are duplicated. */ struct Timon_table_entry diff --git a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c index 6414b56defa4..19fe16084b90 100644 --- a/drivers/usb/media/pwc-if.c +++ b/drivers/usb/media/pwc-if.c @@ -255,7 +255,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) return -ENXIO; } #endif - /* Allocate Isochronuous pipe buffers */ + /* Allocate Isochronous pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) { if (pdev->sbuf[i].data == NULL) { kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL); @@ -811,7 +811,7 @@ static int pwc_isoc_init(struct pwc_device *pdev) if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { Err("Failed to find packet size for video endpoint in current alternate setting.\n"); - return -ENFILE; /* Odd error, that should be noticable */ + return -ENFILE; /* Odd error, that should be noticeable */ } /* Set alternate interface */ @@ -2040,7 +2040,7 @@ static int __init usb_pwc_init(void) if (leds[1] >= 0) led_off = leds[1]; - /* Big device node whoopla. Basicly, it allows you to assign a + /* Big device node whoopla. Basically, it allows you to assign a device node (/dev/videoX) to a camera, based on its type & serial number. The format is [type[.serialnumber]:]node. diff --git a/drivers/usb/media/pwc-uncompress.c b/drivers/usb/media/pwc-uncompress.c index b34074e5d40d..42a65168dd5d 100644 --- a/drivers/usb/media/pwc-uncompress.c +++ b/drivers/usb/media/pwc-uncompress.c @@ -32,7 +32,7 @@ static LIST_HEAD(pwc_decompressor_list); /* Should the pwc_decompress structure ever change, we increase the version number so that we don't get nasty surprises, or can - dynamicly adjust our structure. + dynamically adjust our structure. */ const int pwc_decompressor_version = PWC_MAJOR; diff --git a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h index 3ff42fc9f20e..9745effa4407 100644 --- a/drivers/usb/media/pwc.h +++ b/drivers/usb/media/pwc.h @@ -147,7 +147,7 @@ struct pwc_device 2. data is synchronized and packed into a frame buffer 3a. in case data is compressed, decompress it directly into image buffer 3b. in case data is uncompressed, copy into image buffer with viewport - 4. data is transfered to the user process + 4. data is transferred to the user process Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... We have in effect a back-to-back-double-buffer system. diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c index cde8b307a2a1..f1f3210f3a48 100644 --- a/drivers/usb/media/se401.c +++ b/drivers/usb/media/se401.c @@ -692,7 +692,7 @@ static int se401_set_size(struct usb_se401 *se401, int width, int height) /* This shouldn't really be done in a v4l driver.... But it does make the image look a lot more usable. - Basicly it lifts the dark pixels more than the light pixels. + Basically it lifts the dark pixels more than the light pixels. */ static inline void enhance_picture(unsigned char *frame, int len) { diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 831d932ea9e5..adb87516e8ab 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -531,7 +531,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign return -ENODEV; switch (ioctlnr) { - /* query capabilites */ + /* query capabilities */ case VIDIOCGCAP: { struct video_capability b; diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 28132e35a4a7..74ca6cacd589 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -687,10 +687,10 @@ static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int time This function sends a simple control message to a specified endpoint and waits for the message to complete, or timeout. - If successful, it returns the transfered length, othwise a negative error number. + If successful, it returns the transferred length, otherwise a negative error number. Don't use this function from within an interrupt context, like a - bottom half handler. If you need a asyncronous message, or need to send + bottom half handler. If you need an asynchronous message, or need to send a message from within interrupt context, use auerchain_submit_urb() */ static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, @@ -814,7 +814,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned } return 0; -bl_fail:/* not enought memory. Free allocated elements */ +bl_fail:/* not enough memory. Free allocated elements */ dbg ("auerbuf_setup: no more memory"); auerbuf_free_buffers (bcp); return -ENOMEM; @@ -1083,7 +1083,7 @@ static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs) /* can we do something more? This is a big problem: if this int packet is ignored, the device will wait forever and not signal any more data. - The only real solution is: having enought buffers! + The only real solution is: having enough buffers! Or perhaps temporary disabling the int endpoint? */ goto exit; @@ -1130,7 +1130,7 @@ static void auerswald_int_free (pauerswald_t cp) } /* This function is called to activate the interrupt - endpoint. This function returns 0 if successfull or an error code. + endpoint. This function returns 0 if successful or an error code. NOTE: no mutex please! */ static int auerswald_int_open (pauerswald_t cp) @@ -1181,7 +1181,7 @@ intoend: } /* This function is called to deactivate the interrupt - endpoint. This function returns 0 if successfull or an error code. + endpoint. This function returns 0 if successful or an error code. NOTE: no mutex please! */ static int auerswald_int_release (pauerswald_t cp) @@ -1713,7 +1713,7 @@ doreadlist: return -ERESTARTSYS; } - /* try to read the incomming data again */ + /* try to read the incoming data again */ goto doreadlist; } @@ -2075,7 +2075,7 @@ pfail: auerswald_delete (cp); The argument dev specifies the device context and the driver_context returns a pointer to the previously registered driver_context of the probe function. After returning from the disconnect function the USB - framework completly deallocates all data structures associated with + framework completely deallocates all data structures associated with this device. So especially the usb_device structure must not be used any longer by the usb driver. */ diff --git a/drivers/usb/misc/speedtouch.c b/drivers/usb/misc/speedtouch.c index 0c4ce9d19612..58bb47c64e6a 100644 --- a/drivers/usb/misc/speedtouch.c +++ b/drivers/usb/misc/speedtouch.c @@ -193,7 +193,7 @@ struct udsl_instance_data { static const char udsl_driver_name [] = "speedtch"; /* - * atm driver prototypes and stuctures + * atm driver prototypes and structures */ static void udsl_atm_dev_close (struct atm_dev *dev); @@ -273,39 +273,60 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { ctrl->aal5_trailer [7] = crc; } -static char *udsl_write_cell (struct sk_buff *skb, char *target) { +unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) { struct udsl_control *ctrl = UDSL_SKB (skb); + unsigned char *target = *target_p; + unsigned int nc, ne, i; - ctrl->num_cells--; + dbg ("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding); - memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); - target += ATM_CELL_HEADER; + nc = ctrl->num_cells; + ne = min (howmany, ctrl->num_entire); - if (ctrl->num_entire) { - ctrl->num_entire--; + for (i = 0; i < ne; i++) { + memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); + target += ATM_CELL_HEADER; memcpy (target, skb->data, ATM_CELL_PAYLOAD); target += ATM_CELL_PAYLOAD; __skb_pull (skb, ATM_CELL_PAYLOAD); - return target; } + ctrl->num_entire -= ne; + + if (!(ctrl->num_cells -= ne) || !(howmany -= ne)) + goto out; + + memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); + target += ATM_CELL_HEADER; memcpy (target, skb->data, skb->len); target += skb->len; __skb_pull (skb, skb->len); - memset (target, 0, ctrl->pdu_padding); target += ctrl->pdu_padding; - if (ctrl->num_cells) { - ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; - } else { - memcpy (target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); - target += ATM_AAL5_TRAILER; - /* set pti bit in last cell */ - *(target + 3 - ATM_CELL_SIZE) |= 0x2; + if (--ctrl->num_cells) { + if (!--howmany) { + ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; + goto out; + } + + memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); + target += ATM_CELL_HEADER; + memset (target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); + target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; + + if (--ctrl->num_cells) + BUG(); } - return target; + memcpy (target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); + target += ATM_AAL5_TRAILER; + /* set pti bit in last cell */ + *(target + 3 - ATM_CELL_SIZE) |= 0x2; + +out: + *target_p = target; + return nc - ctrl->num_cells; } @@ -500,14 +521,12 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs) static void udsl_process_send (unsigned long data) { struct udsl_send_buffer *buf; - unsigned int cells_to_write; int err; unsigned long flags; - unsigned int i; struct udsl_instance_data *instance = (struct udsl_instance_data *) data; + unsigned int num_written; struct sk_buff *skb; struct udsl_sender *snd; - unsigned char *target; dbg ("udsl_process_send entered"); @@ -577,16 +596,11 @@ made_progress: instance->current_buffer = buf; } - cells_to_write = min (buf->free_cells, UDSL_SKB (skb)->num_cells); - target = buf->free_start; - - dbg ("writing %u cells from skb 0x%p to buffer 0x%p", cells_to_write, skb, buf); + num_written = udsl_write_cells (buf->free_cells, skb, &buf->free_start); - for (i = 0; i < cells_to_write; i++) - target = udsl_write_cell (skb, target); + dbg ("wrote %u cells from skb 0x%p to buffer 0x%p", num_written, skb, buf); - buf->free_start = target; - if (!(buf->free_cells -= cells_to_write)) { + if (!(buf->free_cells -= num_written)) { list_add_tail (&buf->list, &instance->filled_buffers); instance->current_buffer = NULL; dbg ("queued filled buffer"); diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 398aa567d6ba..fec152c2f241 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -1707,7 +1707,7 @@ static int usbnet_stop (struct net_device *net) /*-------------------------------------------------------------------------*/ -// posts reads, and enables write queing +// posts reads, and enables write queuing // precondition: never called in_interrupt diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 7cf6b5847c1c..0c790ae6a4e8 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -215,7 +215,7 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp) dbg("%s port %d", __FUNCTION__, port->number); /*Start reading from the device*/ - /* TODO: Look at possibility of submitting mulitple URBs to device to + /* TODO: Look at possibility of submitting multiple URBs to device to * enhance buffering. Win trace shows 16 initial read URBs. */ port->read_urb->dev = port->serial->dev; diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 8f6dcd730173..b0161705047e 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -302,7 +302,7 @@ static void cyberjack_read_int_callback( struct urb *urb, struct pt_regs *regs ) short old_rdtodo = priv->rdtodo; int result; - /* This is a announcement of comming bulk_ins. */ + /* This is a announcement of coming bulk_ins. */ unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3; if( (size>259) || (size==0) ) { diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index af4a621ff524..37e266f52650 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1086,7 +1086,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) return -ENODEV; } - /* now wait for the port to be completly opened */ + /* now wait for the port to be completely opened */ timeout = OPEN_TIMEOUT; while (timeout && edge_port->openPending == TRUE) { timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout); diff --git a/drivers/usb/serial/io_ionsp.h b/drivers/usb/serial/io_ionsp.h index e5c344d033ec..944fc04f1946 100644 --- a/drivers/usb/serial/io_ionsp.h +++ b/drivers/usb/serial/io_ionsp.h @@ -19,7 +19,7 @@ The data to and from all ports on the peripheral is multiplexed through a single endpoint pair (EP1 since it supports 64-byte MaxPacketSize). Therefore, the data, commands, and status for -each port must be preceeded by a short header identifying the +each port must be preceded by a short header identifying the destination port. The header also identifies the bytes that follow as data or as command/status info. diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 7ba4d95425d4..b2368748b9de 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -468,7 +468,7 @@ static int TIIsTxActive (struct edgeport_port *port) { int status; struct out_endpoint_desc_block *oedb; - __u8 lsr; + __u8 *lsr; int bytes_left = 0; oedb = kmalloc (sizeof (* oedb), GFP_KERNEL); @@ -477,6 +477,13 @@ static int TIIsTxActive (struct edgeport_port *port) return -ENOMEM; } + lsr = kmalloc (1, GFP_KERNEL); /* Sigh, that's right, just one byte, + as not all platforms can do DMA + from stack */ + if (!lsr) { + kfree(oedb); + return -ENOMEM; + } /* Read the DMA Count Registers */ status = TIReadRam (port->port->serial->dev, port->dma_address, @@ -492,22 +499,25 @@ static int TIIsTxActive (struct edgeport_port *port) status = TIReadRam (port->port->serial->dev, port->uart_base + UMPMEM_OFFS_UART_LSR, 1, - &lsr); + lsr); if (status) goto exit_is_tx_active; - dbg ("%s - LSR = 0x%X", __FUNCTION__, lsr); + dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr); /* If either buffer has data or we are transmitting then return TRUE */ if ((oedb->XByteCount & 0x80 ) != 0 ) bytes_left += 64; - if ((lsr & UMP_UART_LSR_TX_MASK ) == 0 ) + if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 ) bytes_left += 1; /* We return Not Active if we get any kind of error */ exit_is_tx_active: dbg ("%s - return %d", __FUNCTION__, bytes_left ); + + kfree(lsr); + kfree(oedb); return bytes_left; } @@ -1151,8 +1161,12 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status); /* return an error on purpose. */ + kfree (firmware_version); + kfree (rom_desc); + kfree (ti_manuf_desc); return -ENODEV; } + kfree (firmware_version); } // Search for type 0xF2 record (firmware blank record) else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 9381bc4f6023..332a56327123 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -471,7 +471,7 @@ static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) /* * Bypass flip-buffers, and feed the ldisc directly - * due to our potentally large buffer size. Since we + * due to our potentially large buffer size. Since we * used to set low_latency, this is exactly what the * tty layer did anyway :) */ @@ -553,7 +553,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct termios *old_te /* * FIXME, we should compare the baud request against the * capability stated in the IR header that we got in the - * startup funtion. + * startup function. */ switch (cflag & CBAUD) { case B2400: ir_baud = SPEED_2400; break; diff --git a/drivers/usb/serial/keyspan_usa26msg.h b/drivers/usb/serial/keyspan_usa26msg.h index d3c0cb0277b9..cac3d501f523 100644 --- a/drivers/usb/serial/keyspan_usa26msg.h +++ b/drivers/usb/serial/keyspan_usa26msg.h @@ -23,7 +23,7 @@ notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. The name of InnoSys Incorprated may not be used to endorse or promote + 3. The name of InnoSys Incorporated may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/drivers/usb/serial/keyspan_usa28msg.h b/drivers/usb/serial/keyspan_usa28msg.h index 4641abd7d682..d76eb72878e1 100644 --- a/drivers/usb/serial/keyspan_usa28msg.h +++ b/drivers/usb/serial/keyspan_usa28msg.h @@ -23,7 +23,7 @@ notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. The name of InnoSys Incorprated may not be used to endorse or promote + 3. The name of InnoSys Incorporated may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/drivers/usb/serial/keyspan_usa49msg.h b/drivers/usb/serial/keyspan_usa49msg.h index 73444c00023d..320b2cc76874 100644 --- a/drivers/usb/serial/keyspan_usa49msg.h +++ b/drivers/usb/serial/keyspan_usa49msg.h @@ -23,7 +23,7 @@ notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. The name of InnoSys Incorprated may not be used to endorse or promote + 3. The name of InnoSys Incorporated may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 69abd70e79cf..99c634017192 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -253,6 +253,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) port->write_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->write_urb) { dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number); + kfree(transfer_buffer); return -1; } } @@ -260,6 +261,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) // allocate memory for write_urb transfer buffer port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); if (! port->write_urb->transfer_buffer) { + kfree(transfer_buffer); return -1; } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 96f5c051c8e0..b341aad16a6e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -76,6 +76,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, + { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 63051e66e69c..5e2abcc0db20 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -34,3 +34,6 @@ #define RADIOSHACK_VENDOR_ID 0x1453 #define RADIOSHACK_PRODUCT_ID 0x4026 + +#define DCU10_VENDOR_ID 0x0731 +#define DCU10_PRODUCT_ID 0x0528 diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6eda0113534b..c57ce2d5f31f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -229,7 +229,7 @@ * (01/23/2000) gkh * Fixed problem of crash when trying to open a port that didn't have a * device assigned to it. Made the minor node finding a little smarter, - * now it looks to find a continous space for the new device. + * now it looks to find a continuous space for the new device. * * (01/21/2000) gkh * Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) @@ -1293,7 +1293,7 @@ static int __init usb_serial_init(void) int i; int result = 0; - /* Initalize our global data */ + /* Initialize our global data */ for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial_table[i] = NULL; } diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index 5389343ecaf7..ad2d292ddf53 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -71,7 +71,7 @@ * usb_serial_port: structure for the specific ports of a device. * @magic: magic number for internal validity of this pointer. * @serial: pointer back to the struct usb_serial owner of this port. - * @tty: pointer to the coresponding tty for this port. + * @tty: pointer to the corresponding tty for this port. * @number: the number of the port (the minor number). * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index ee5917af0daa..22b4ef591a81 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -12,6 +12,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (03/09/2003) gkh + * Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl + * <brachtl@redgrep.cz> for the information. + * * (03/05/2003) gkh * Think Treo support is now working. * @@ -198,6 +202,8 @@ static struct usb_device_id id_table [] = { .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID), @@ -215,6 +221,8 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { } /* Terminating entry */ }; @@ -230,6 +238,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, @@ -240,6 +249,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h index 86f8f3fb642a..089bcf98da86 100644 --- a/drivers/usb/serial/visor.h +++ b/drivers/usb/serial/visor.h @@ -31,6 +31,7 @@ #define PALM_TUNGSTEN_T_ID 0x0060 #define PALM_TUNGSTEN_Z_ID 0x0031 #define PALM_ZIRE_ID 0x0070 +#define PALM_M100_ID 0x0080 #define SONY_VENDOR_ID 0x054C #define SONY_CLIE_3_5_ID 0x0038 @@ -38,6 +39,7 @@ #define SONY_CLIE_S360_ID 0x0095 #define SONY_CLIE_4_1_ID 0x009A #define SONY_CLIE_NX60_ID 0x00DA +#define SONY_CLIE_NZ90V_ID 0x00E9 /**************************************************************************** * Handspring Visor Vendor specific request codes (bRequest values) diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 9a88b60c9bd5..1f56f63bb8e5 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -650,7 +650,7 @@ static void isd200_log_config( struct isd200_info* info ) /************************************************************************** * isd200_write_config * - * Write the ISD200 Configuraton data + * Write the ISD200 Configuration data * * RETURNS: * ISD status code @@ -693,7 +693,7 @@ int isd200_write_config( struct us_data *us ) /************************************************************************** * isd200_read_config * - * Reads the ISD200 Configuraton data + * Reads the ISD200 Configuration data * * RETURNS: * ISD status code @@ -977,7 +977,7 @@ int isd200_get_inquiry_data( struct us_data *us ) /* check for an ATA device */ if (info->DeviceFlags & DF_ATA_DEVICE) { /* this must be an ATA device */ - /* perform an ATA Commmand Identify */ + /* perform an ATA Command Identify */ transferStatus = isd200_action( us, ACTION_IDENTIFY, &info->drive, sizeof(struct hd_driveid) ); diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 799c4134751e..38c38ee90011 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -118,7 +118,7 @@ struct bulk_cs_wrap { */ #define USB_STOR_XFER_GOOD 0 /* good transfer */ -#define USB_STOR_XFER_SHORT 1 /* transfered less than expected */ +#define USB_STOR_XFER_SHORT 1 /* transferred less than expected */ #define USB_STOR_XFER_STALLED 2 /* endpoint stalled */ #define USB_STOR_XFER_ERROR 3 /* transfer died in the middle */ diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index b5c7e6745b1a..b89ca760a959 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -64,7 +64,7 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" #define DRIVER_DESC "USB Skeleton Driver" -/* Module paramaters */ +/* Module parameters */ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/fs/Kconfig b/fs/Kconfig index 1697ef34c9a5..3326d8daedcc 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -4,89 +4,180 @@ menu "File systems" -config QUOTA - bool "Quota support" +config EXT2_FS + tristate "Second extended fs support" help - If you say Y here, you will be able to set per user limits for disk - usage (also called disk quotas). Currently, it works for the - ext2, ext3, and reiserfs file system. You need additional software - in order to use quota support (you can download sources from - <http://www.sf.net/projects/linuxquota/>). For further details, read - the Quota mini-HOWTO, available from - <http://www.linuxdoc.org/docs.html#howto>. Probably the quota - support is only useful for multi user systems. If unsure, say N. + This is the de facto standard Linux file system (method to organize + files on a storage device) for hard disks. -config QFMT_V1 - tristate "Old quota format support" - depends on QUOTA + You want to say Y here, unless you intend to use Linux exclusively + from inside a DOS partition using the UMSDOS file system. The + advantage of the latter is that you can get away without + repartitioning your hard drive (which often implies backing + everything up and restoring afterwards); the disadvantage is that + Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat + slower than ext2fs. Even if you want to run Linux in this fashion, + it might be a good idea to have ext2fs around: it enables you to + read more floppy disks and facilitates the transition to a *real* + Linux partition later. Another (rare) case which doesn't require + ext2fs is a diskless Linux box which mounts all files over the + network using NFS (in this case it's sufficient to say Y to "NFS + file system support" below). Saying Y here will enlarge your kernel + by about 44 KB. + + The Ext2fs-Undeletion mini-HOWTO, available from + <http://www.linuxdoc.org/docs.html#howto>, gives information about + how to retrieve deleted files on ext2fs file systems. + + To change the behavior of ext2 file systems, you can use the tune2fs + utility ("man tune2fs"). To modify attributes of files and + directories on ext2 file systems, use chattr ("man chattr"). + + Ext2fs partitions can be read from within DOS using the ext2tool + command line tool package (available from + <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from + within Windows NT using the ext2nt command line tool package from + <ftp://ibiblio.org/pub/Linux/utils/dos/>. Explore2fs is a + graphical explorer for ext2fs partitions which runs on Windows 95 + and Windows NT and includes experimental write support; it is + available from + <http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm>. + + If you want to compile this file system as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want), say M here and read <file:Documentation/modules.txt>. The + module will be called ext2. Be aware however that the file system + of your root partition (the one containing the directory /) cannot + be compiled as a module, and so this could be dangerous. Most + everyone wants to say Y here. + +config EXT2_FS_XATTR + bool "Ext2 extended attributes" + depends on EXT2_FS help - This quota format was (is) used by kernels earlier than 2.4.??. If - you have quota working and you don't want to convert to new quota - format say Y here. + Extended attributes are name:value pairs associated with inodes by + the kernel or by users (see the attr(5) manual page, or visit + <http://acl.bestbits.at/> for details). -config QFMT_V2 - tristate "Quota format v2 support" - depends on QUOTA + If unsure, say N. + +config EXT2_FS_POSIX_ACL + bool "Ext2 POSIX Access Control Lists" + depends on EXT2_FS_XATTR help - This quota format allows using quotas with 32-bit UIDs/GIDs. If you - need this functionality say Y here. Note that you will need latest - quota utilities for new quota format with this kernel. + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. -config QUOTACTL - bool - depends on XFS_QUOTA || QUOTA + To learn more about Access Control Lists, visit the Posix ACLs for + Linux website <http://acl.bestbits.at/>. + + If you don't know what Access Control Lists are, say N + +config EXT3_FS + tristate "Ext3 journalling file system support" + help + This is the journaling version of the Second extended file system + (often called ext3), the de facto standard Linux file system + (method to organize files on a storage device) for hard disks. + + The journaling code included in this driver means you do not have + to run e2fsck (file system checker) on your file systems after a + crash. The journal keeps track of any changes that were being made + at the time the system crashed, and can ensure that your file system + is consistent without the need for a lengthy check. + + Other than adding the journal to the file system, the on-disk format + of ext3 is identical to ext2. It is possible to freely switch + between using the ext3 driver and the ext2 driver, as long as the + file system has been cleanly unmounted, or e2fsck is run on the file + system. + + To add a journal on an existing ext2 file system or change the + behavior of ext3 file systems, you can use the tune2fs utility ("man + tune2fs"). To modify attributes of files and directories on ext3 + file systems, use chattr ("man chattr"). You need to be using + e2fsprogs version 1.20 or later in order to create ext3 journals + (available at <http://sourceforge.net/projects/e2fsprogs/>). + + If you want to compile this file system as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want), say M here and read <file:Documentation/modules.txt>. The + module will be called ext3. Be aware however that the file system + of your root partition (the one containing the directory /) cannot + be compiled as a module, and so this may be dangerous. + +config EXT3_FS_XATTR + bool "Ext3 extended attributes" + depends on EXT3_FS default y + help + Extended attributes are name:value pairs associated with inodes by + the kernel or by users (see the attr(5) manual page, or visit + <http://acl.bestbits.at/> for details). -config AUTOFS_FS - tristate "Kernel automounter support" - ---help--- - The automounter is a tool to automatically mount remote file systems - on demand. This implementation is partially kernel-based to reduce - overhead in the already-mounted case; this is unlike the BSD - automounter (amd), which is a pure user space daemon. + If unsure, say N. - To use the automounter you need the user-space tools from the autofs - package; you can find the location in <file:Documentation/Changes>. - You also want to answer Y to "NFS file system support", below. + You need this for POSIX ACL support on ext3. - If you want to use the newer version of the automounter with more - features, say N here and say Y to "Kernel automounter v4 support", - below. +config EXT3_FS_POSIX_ACL + bool "Ext3 POSIX Access Control Lists" + depends on EXT3_FS_XATTR + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called autofs. + To learn more about Access Control Lists, visit the Posix ACLs for + Linux website <http://acl.bestbits.at/>. - If you are not a part of a fairly large, distributed network, you - probably do not need an automounter, and can say N here. + If you don't know what Access Control Lists are, say N -config AUTOFS4_FS - tristate "Kernel automounter version 4 support (also supports v3)" - ---help--- - The automounter is a tool to automatically mount remote file systems - on demand. This implementation is partially kernel-based to reduce - overhead in the already-mounted case; this is unlike the BSD - automounter (amd), which is a pure user space daemon. +config JBD +# CONFIG_JBD could be its own option (even modular), but until there are +# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS +# dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS + bool + default EXT3_FS + help + This is a generic journaling layer for block devices. It is + currently used by the ext3 file system, but it could also be used to + add journal support to other file systems or block devices such as + RAID or LVM. - To use the automounter you need the user-space tools from - <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also - want to answer Y to "NFS file system support", below. + If you are using the ext3 file system, you need to say Y here. If + you are not using ext3 then you will probably want to say N. - If you want to compile this as a module ( = code which can be + If you want to compile this device as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/modules.txt>. The module - will be called autofs4. You will need to add "alias autofs - autofs4" to your modules configuration file. + will be called jbd. If you are compiling ext3 into the kernel, + you cannot compile this code as a module. - If you are not a part of a fairly large, distributed network or - don't have a laptop which needs to dynamically reconfigure to the - local network, you probably do not need an automounter, and can say - N here. +config JBD_DEBUG + bool "JBD (ext3) debugging support" + depends on JBD + help + If you are using the ext3 journaled file system (or potentially any + other file system/device using JBD), this option allows you to + enable debugging output while the system is running, in order to + help track down any problems you are having. By default the + debugging output will be turned off. + + If you select Y here, then you will be able to turn on debugging + with "echo N > /proc/sys/fs/jbd-debug", where N is a number between + 1 and 5, the higher the number, the more debugging output is + generated. To turn debugging off again, do + "echo 0 > /proc/sys/fs/jbd-debug". + +config FS_MBCACHE +# Meta block cache for Extended Attributes (ext2/ext3) + tristate + depends on EXT2_FS_XATTR || EXT3_FS_XATTR + default y if EXT2_FS=y || EXT3_FS=y + default m if EXT2_FS=m || EXT3_FS=m config REISERFS_FS tristate "Reiserfs support" - ---help--- + help Stores not just filenames but the files themselves in a balanced tree. Uses journaling. @@ -135,226 +226,308 @@ config REISERFS_PROC_INFO Almost everyone but ReiserFS developers and people fine-tuning reiserfs or tracing problems should say N. -config ADFS_FS - tristate "ADFS file system support (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - The Acorn Disc Filing System is the standard file system of the - RiscOS operating system which runs on Acorn's ARM-based Risc PC - systems and the Acorn Archimedes range of machines. If you say Y - here, Linux will be able to read from ADFS partitions on hard drives - and from ADFS-formatted floppy discs. If you also want to be able to - write to those devices, say Y to "ADFS write support" below. +config JFS_FS + tristate "JFS filesystem support" + help + This is a port of IBM's Journaled Filesystem . More information is + available in the file Documentation/filesystems/jfs.txt. - The ADFS partition should be the first partition (i.e., - /dev/[hs]d?1) on each of your drives. Please read the file - <file:Documentation/filesystems/adfs.txt> for further details. + If you do not intend to use the JFS filesystem, say N. - This code is also available as a module called adfs ( = code which +config JFS_POSIX_ACL + bool "JFS POSIX Access Control Lists" + depends on JFS_FS + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the Posix ACLs for + Linux website <http://acl.bestbits.at/>. + + If you don't know what Access Control Lists are, say N + +config JFS_DEBUG + bool "JFS debugging" + depends on JFS_FS + help + If you are experiencing any problems with the JFS filesystem, say + Y here. This will result in additional debugging messages to be + written to the system log. Under normal circumstances, this + results in very little overhead. + +config JFS_STATISTICS + bool "JFS statistics" + depends on JFS_FS + help + Enabling this option will cause statistics from the JFS file system + to be made available to the user in the /proc/fs/jfs/ directory. + +config FS_POSIX_ACL +# Posix ACL utility routines (for now, only ext2/ext3/jfs) +# +# NOTE: you can implement Posix ACLs without these helpers (XFS does). +# Never use this symbol for ifdefs. +# + bool + depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL + default y + +config XFS_FS + tristate "XFS filesystem support" + help + XFS is a high performance journaling filesystem which originated + on the SGI IRIX platform. It is completely multi-threaded, can + support large files and large filesystems, extended attributes, + variable block sizes, is extent based, and makes extensive use of + Btrees (directories, extents, free space) to aid both performance + and scalability. + + Refer to the documentation at <http://oss.sgi.com/projects/xfs/> + for complete details. This implementation is on-disk compatible + with the IRIX version of XFS. + + If you want to compile this file system as a module ( = code which can be inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. + want), say M here and read <file:Documentation/modules.txt>. The + module will be called xfs. Be aware, however, that if the file + system of your root partition is compiled as a module, you'll need + to use an initial ramdisk (initrd) to boot. + +config XFS_RT + bool "Realtime support (EXPERIMENTAL)" + depends on XFS_FS && EXPERIMENTAL + help + If you say Y here you will be able to mount and use XFS filesystems + which contain a realtime subvolume. The realtime subvolume is a + separate area of disk space where only file data is stored. The + realtime subvolume is designed to provide very deterministic + data rates suitable for media streaming applications. + + See the xfs man page in section 5 for a bit more information. + + This feature is unsupported at this time, is not yet fully + functional, and may cause serious problems. If unsure, say N. -config ADFS_FS_RW - bool "ADFS write support (DANGEROUS)" - depends on ADFS_FS +config XFS_QUOTA + bool "Quota support" + depends on XFS_FS help - If you say Y here, you will be able to write to ADFS partitions on - hard drives and ADFS-formatted floppy disks. This is experimental - codes, so if you're unsure, say N. + If you say Y here, you will be able to set limits for disk usage on + a per user and/or a per group basis under XFS. XFS considers quota + information as filesystem metadata and uses journaling to provide a + higher level guarantee of consistency. The on-disk data format for + quota is also compatible with the IRIX version of XFS, allowing a + filesystem to be migrated between Linux and IRIX without any need + for conversion. -config AFFS_FS - tristate "Amiga FFS file system support (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - The Fast File System (FFS) is the common file system used on hard - disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y - if you want to be able to read and write files from and to an Amiga - FFS partition on your hard drive. Amiga floppies however cannot be - read with this driver due to an incompatibility of the floppy - controller used in an Amiga and the standard floppy controller in - PCs and workstations. Read <file:Documentation/filesystems/affs.txt> - and <file:fs/affs/Changes>. + If unsure, say N. More comprehensive documentation can be found in + README.quota in the xfsprogs package. XFS quota can be used either + with or without the generic quota support enabled (CONFIG_QUOTA) - + they are completely independent subsystems. - With this driver you can also mount disk files used by Bernd - Schmidt's Un*X Amiga Emulator - (<http://www.freiburg.linux.de/~uae/>). - If you want to do this, you will also need to say Y or M to "Loop - device support", above. +config XFS_POSIX_ACL + bool "ACL support" + depends on XFS_FS + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. - This file system is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called affs. If you want to compile it as a module, - say M here and read <file:Documentation/modules.txt>. If unsure, - say N. + To learn more about Access Control Lists, visit the Posix ACLs for + Linux website <http://acl.bestbits.at/>. -config HFS_FS - tristate "Apple Macintosh file system support (EXPERIMENTAL)" - depends on EXPERIMENTAL + If you don't know what Access Control Lists are, say N + +config MINIX_FS + tristate "Minix fs support" + help + Minix is a simple operating system used in many classes about OS's. + The minix file system (method to organize files on a hard disk + partition or a floppy disk) was the original file system for Linux, + but has been superseded by the second extended file system ext2fs. + You don't want to use the minix file system on your hard disk + because of certain built-in restrictions, but it is sometimes found + on older Linux floppy disks. This option will enlarge your kernel + by about 28 KB. If unsure, say N. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called minix. Note that the file system of your root + partition (the one containing the directory /) cannot be compiled as + a module. + +config ROMFS_FS + tristate "ROM file system support" ---help--- - If you say Y here, you will be able to mount Macintosh-formatted - floppy disks and hard drive partitions with full read-write access. - Please read <file:fs/hfs/HFS.txt> to learn about the available mount - options. + This is a very small read-only file system mainly intended for + initial ram disks of installation disks, but it could be used for + other read-only media as well. Read + <file:Documentation/filesystems/romfs.txt> for details. This file system support is also available as a module ( = code which can be inserted in and removed from the running kernel - whenever you want). The module is called hfs. If you want to + whenever you want). The module is called romfs. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. + <file:Documentation/modules.txt>. Note that the file system of your + root partition (the one containing the directory /) cannot be a + module. -config BEFS_FS - tristate "BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - The BeOS File System (BeFS) is the native file system of Be, Inc's - BeOS. Notable features include support for arbitrary attributes - on files and directories, and database-like indices on selected - attributes. (Also note that this driver doesn't make those features - available at this time). It is a 64 bit filesystem, so it supports - extreemly large volumes and files. + If you don't know whether you need it, then you don't need it: + answer N. - If you use this filesystem, you should also say Y to at least one - of the NLS (native language support) options below. +config QUOTA + bool "Quota support" + help + If you say Y here, you will be able to set per user limits for disk + usage (also called disk quotas). Currently, it works for the + ext2, ext3, and reiserfs file system. You need additional software + in order to use quota support (you can download sources from + <http://www.sf.net/projects/linuxquota/>). For further details, read + the Quota mini-HOWTO, available from + <http://www.linuxdoc.org/docs.html#howto>. Probably the quota + support is only useful for multi user systems. If unsure, say N. - If you don't know what this is about, say N. +config QFMT_V1 + tristate "Old quota format support" + depends on QUOTA + help + This quota format was (is) used by kernels earlier than 2.4.??. If + you have quota working and you don't want to convert to new quota + format say Y here. - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called befs. +config QFMT_V2 + tristate "Quota format v2 support" + depends on QUOTA + help + This quota format allows using quotas with 32-bit UIDs/GIDs. If you + need this functionality say Y here. Note that you will need latest + quota utilities for new quota format with this kernel. -config BEFS_DEBUG - bool "Debug BeFS" - depends on BEFS_FS +config QUOTACTL + bool + depends on XFS_QUOTA || QUOTA + default y + +config AUTOFS_FS + tristate "Kernel automounter support" help - If you say Y here, you can use the 'debug' mount option to enable - debugging output from the driver. + The automounter is a tool to automatically mount remote file systems + on demand. This implementation is partially kernel-based to reduce + overhead in the already-mounted case; this is unlike the BSD + automounter (amd), which is a pure user space daemon. -config BFS_FS - tristate "BFS file system support (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - Boot File System (BFS) is a file system used under SCO UnixWare to - allow the bootloader access to the kernel image and other important - files during the boot process. It is usually mounted under /stand - and corresponds to the slice marked as "STAND" in the UnixWare - partition. You should say Y if you want to read or write the files - on your /stand slice from within Linux. You then also need to say Y - to "UnixWare slices support", below. More information about the BFS - file system is contained in the file - <file:Documentation/filesystems/bfs.txt>. + To use the automounter you need the user-space tools from the autofs + package; you can find the location in <file:Documentation/Changes>. + You also want to answer Y to "NFS file system support", below. - If you don't know what this is about, say N. + If you want to use the newer version of the automounter with more + features, say N here and say Y to "Kernel automounter v4 support", + below. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/modules.txt>. The module - will be called bfs. Note that the file system of your root - partition (the one containing the directory /) cannot be compiled as - a module. + will be called autofs. -config EXT3_FS - tristate "Ext3 journalling file system support" - ---help--- - This is the journaling version of the Second extended file system - (often called ext3), the de facto standard Linux file system - (method to organize files on a storage device) for hard disks. + If you are not a part of a fairly large, distributed network, you + probably do not need an automounter, and can say N here. - The journaling code included in this driver means you do not have - to run e2fsck (file system checker) on your file systems after a - crash. The journal keeps track of any changes that were being made - at the time the system crashed, and can ensure that your file system - is consistent without the need for a lengthy check. +config AUTOFS4_FS + tristate "Kernel automounter version 4 support (also supports v3)" + help + The automounter is a tool to automatically mount remote file systems + on demand. This implementation is partially kernel-based to reduce + overhead in the already-mounted case; this is unlike the BSD + automounter (amd), which is a pure user space daemon. - Other than adding the journal to the file system, the on-disk format - of ext3 is identical to ext2. It is possible to freely switch - between using the ext3 driver and the ext2 driver, as long as the - file system has been cleanly unmounted, or e2fsck is run on the file - system. + To use the automounter you need the user-space tools from + <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also + want to answer Y to "NFS file system support", below. - To add a journal on an existing ext2 file system or change the - behavior of ext3 file systems, you can use the tune2fs utility ("man - tune2fs"). To modify attributes of files and directories on ext3 - file systems, use chattr ("man chattr"). You need to be using - e2fsprogs version 1.20 or later in order to create ext3 journals - (available at <http://sourceforge.net/projects/e2fsprogs/>). + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called autofs4. You will need to add "alias autofs + autofs4" to your modules configuration file. - If you want to compile this file system as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read <file:Documentation/modules.txt>. The - module will be called ext3. Be aware however that the file system - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this may be dangerous. + If you are not a part of a fairly large, distributed network or + don't have a laptop which needs to dynamically reconfigure to the + local network, you probably do not need an automounter, and can say + N here. -config EXT3_FS_XATTR - bool "Ext3 extended attributes" - depends on EXT3_FS - default y - ---help--- - Extended attributes are name:value pairs associated with inodes by - the kernel or by users (see the attr(5) manual page, or visit - <http://acl.bestbits.at/> for details). +menu "CD-ROM/DVD Filesystems" - If unsure, say N. +config ISO9660_FS + tristate "ISO 9660 CDROM file system support" + help + This is the standard file system used on CD-ROMs. It was previously + known as "High Sierra File System" and is called "hsfs" on other + Unix systems. The so-called Rock-Ridge extensions which allow for + long Unix filenames and symbolic links are also supported by this + driver. If you have a CD-ROM drive and want to do more with it than + just listen to audio CDs and watch its LEDs, say Y (and read + <file:Documentation/filesystems/isofs.txt> and the CD-ROM-HOWTO, + available from <http://www.linuxdoc.org/docs.html#howto>), thereby + enlarging your kernel by about 27 KB; otherwise say N. - You need this for POSIX ACL support on ext3. + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called isofs. -config EXT3_FS_POSIX_ACL - bool "Ext3 POSIX Access Control Lists" - depends on EXT3_FS_XATTR - ---help--- - Posix Access Control Lists (ACLs) support permissions for users and - groups beyond the owner/group/world scheme. +config JOLIET + bool "Microsoft Joliet CDROM extensions" + depends on ISO9660_FS + help + Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system + which allows for long filenames in unicode format (unicode is the + new 16 bit character code, successor to ASCII, which encodes the + characters of almost all languages of the world; see + <http://www.unicode.org/> for more information). Say Y here if you + want to be able to read Joliet CD-ROMs under Linux. - To learn more about Access Control Lists, visit the Posix ACLs for - Linux website <http://acl.bestbits.at/>. +config ZISOFS + bool "Transparent decompression extension" + depends on ISO9660_FS + help + This is a Linux-specific extension to RockRidge which lets you store + data in compressed form on a CD-ROM and have it transparently + decompressed when the CD-ROM is accessed. See + <http://www.kernel.org/pub/linux/utils/fs/zisofs/> for the tools + necessary to create such a filesystem. Say Y here if you want to be + able to read such compressed CD-ROMs. - If you don't know what Access Control Lists are, say N +config ZISOFS_FS +# for fs/nls/Config.in + tristate + depends on ZISOFS + default ISO9660_FS -# CONFIG_JBD could be its own option (even modular), but until there are -# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS -# dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS -config JBD - bool - default EXT3_FS - ---help--- - This is a generic journaling layer for block devices. It is - currently used by the ext3 file system, but it could also be used to - add journal support to other file systems or block devices such as - RAID or LVM. +config UDF_FS + tristate "UDF file system support" + help + This is the new file system used on some CD-ROMs and DVDs. Say Y if + you intend to mount DVD discs or CDRW's written in packet mode, or + if written to by other UDF utilities, such as DirectCD. + Please read <file:Documentation/filesystems/udf.txt>. - If you are using the ext3 file system, you need to say Y here. If - you are not using ext3 then you will probably want to say N. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called udf. If you want to + compile it as a module, say M here and read + <file:Documentation/modules.txt>. - If you want to compile this device as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called jbd. If you are compiling ext3 into the kernel, - you cannot compile this code as a module. + If unsure, say N. -config JBD_DEBUG - bool "JBD (ext3) debugging support" - depends on JBD - ---help--- - If you are using the ext3 journaled file system (or potentially any - other file system/device using JBD), this option allows you to - enable debugging output while the system is running, in order to - help track down any problems you are having. By default the - debugging output will be turned off. +endmenu - If you select Y here, then you will be able to turn on debugging - with "echo N > /proc/sys/fs/jbd-debug", where N is a number between - 1 and 5, the higher the number, the more debugging output is - generated. To turn debugging off again, do - "echo 0 > /proc/sys/fs/jbd-debug". +menu "DOS/FAT/NT Filesystems" -# msdos file systems config FAT_FS tristate "DOS FAT fs support" - ---help--- + help If you want to use one of the FAT-based file systems (the MS-DOS, VFAT (Windows 95) and UMSDOS (used to run Linux on top of an ordinary DOS partition) file systems), then you must say Y or M here @@ -398,7 +571,7 @@ config FAT_FS config MSDOS_FS tristate "MSDOS fs support" depends on FAT_FS - ---help--- + help This allows you to mount MSDOS partitions of your hard drive (unless they are compressed; to access compressed MSDOS partitions under Linux, you can either use the DOS emulator DOSEMU, described in the @@ -427,11 +600,35 @@ config MSDOS_FS <file:Documentation/modules.txt>. The module will be called msdos. +config VFAT_FS + tristate "VFAT (Windows-95) fs support" + depends on FAT_FS + help + This option provides support for normal Windows file systems with + long filenames. That includes non-compressed FAT-based file systems + used by Windows 95, Windows 98, Windows NT 4.0, and the Unix + programs from the mtools package. + + You cannot use the VFAT file system for your Linux root partition + (the one containing the directory /); use UMSDOS instead if you + want to run Linux from within a DOS partition (i.e. say Y to + "Unix like fs on top of std MSDOS fs", below). + + The VFAT support enlarges your kernel by about 10 KB and it only + works if you said Y to the "DOS FAT fs support" above. Please read + the file <file:Documentation/filesystems/vfat.txt> for details. If + unsure, say Y. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called vfat. + +config UMSDOS_FS #dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS # UMSDOS is temprory broken -config UMSDOS_FS bool - ---help--- + help Say Y here if you want to run Linux from within an existing DOS partition of your hard drive. The advantage of this is that you can get away without repartitioning your hard drive (which often implies @@ -458,34 +655,317 @@ config UMSDOS_FS root partition (the one containing the directory /) cannot be a module, so saying M could be dangerous. If unsure, say N. -config VFAT_FS - tristate "VFAT (Windows-95) fs support" - depends on FAT_FS +config NTFS_FS + tristate "NTFS file system support (read only)" + help + NTFS is the file system of Microsoft Windows NT/2000/XP. For more + information see <file:Documentation/filesystems/ntfs.txt>. Saying Y + here would allow you to read from NTFS partitions. + + This file system is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ntfs. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + + If you are not using Windows NT/2000/XP in addition to Linux on your + computer it is safe to say N. + +config NTFS_DEBUG + bool "NTFS debugging support" + depends on NTFS_FS + help + If you are experiencing any problems with the NTFS file system, say + Y here. This will result in additional consistency checks to be + performed by the driver as well as additional debugging messages to + be written to the system log. Note that debugging messages are + disabled by default. To enable them, supply the option debug_msgs=1 + at the kernel command line when booting the kernel or as an option + to insmod when loading the ntfs module. Once the driver is active, + you can enable debugging messages by doing (as root): + echo 1 > /proc/sys/fs/ntfs-debug + Replacing the "1" with "0" would disable debug messages. + + If you leave debugging messages disabled, this results in little + overhead, but enabling debug messages results in very significant + slowdown of the system. + + When reporting bugs, please try to have available a full dump of + debugging messages while the misbehaviour was occurring. + +config NTFS_RW + bool "NTFS write support (DANGEROUS)" + depends on NTFS_FS && EXPERIMENTAL + help + This enables the experimental write support in the NTFS driver. + + WARNING: Do not use this option unless you are actively developing + NTFS as it is currently guaranteed to be broken and you + may lose all your data! + + It is strongly recommended and perfectly safe to say N here. + +endmenu + +menu "Pseudo filesystems" + +config PROC_FS + bool "/proc file system support" + help + This is a virtual file system providing information about the status + of the system. "Virtual" means that it doesn't take up any space on + your hard disk: the files are created on the fly by the kernel when + you try to access them. Also, you cannot read the files with older + version of the program less: you need to use more or cat. + + It's totally cool; for example, "cat /proc/interrupts" gives + information about what the different IRQs are used for at the moment + (there is a small number of Interrupt ReQuest lines in your computer + that are used by the attached devices to gain the CPU's attention -- + often a source of trouble if two devices are mistakenly configured + to use the same IRQ). The program procinfo to display some + information about your system gathered from the /proc file system. + + Before you can use the /proc file system, it has to be mounted, + meaning it has to be given a location in the directory hierarchy. + That location should be /proc. A command such as "mount -t proc proc + /proc" or the equivalent line in /etc/fstab does the job. + + The /proc file system is explained in the file + <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage + ("man 5 proc"). + + This option will enlarge your kernel by about 67 KB. Several + programs depend on this, so everyone should say Y here. + +config DEVFS_FS + bool "/dev file system support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This is support for devfs, a virtual file system (like /proc) which + provides the file system interface to device drivers, normally found + in /dev. Devfs does not depend on major and minor number + allocations. Device drivers register entries in /dev which then + appear automatically, which means that the system administrator does + not have to create character and block special device files in the + /dev directory using the mknod command (or MAKEDEV script) anymore. + + This is work in progress. If you want to use this, you *must* read + the material in <file:Documentation/filesystems/devfs/>, especially + the file README there. + + If unsure, say N. + +config DEVFS_MOUNT + bool "Automatically mount at boot" + depends on DEVFS_FS + help + This option appears if you have CONFIG_DEVFS_FS enabled. Setting + this to 'Y' will make the kernel automatically mount devfs onto /dev + when the system is booted, before the init thread is started. + You can override this with the "devfs=nomount" boot option. + + If unsure, say N. + +config DEVFS_DEBUG + bool "Debug devfs" + depends on DEVFS_FS + help + If you say Y here, then the /dev file system code will generate + debugging messages. See the file + <file:Documentation/filesystems/devfs/boot-options> for more + details. + + If unsure, say N. + +config DEVPTS_FS +# It compiles as a module for testing only. It should not be used +# as a module in general. If we make this "tristate", a bunch of people +# who don't know what they are doing turn it on and complain when it +# breaks. + bool "/dev/pts file system for Unix98 PTYs" + depends on UNIX98_PTYS ---help--- - This option provides support for normal Windows file systems with - long filenames. That includes non-compressed FAT-based file systems - used by Windows 95, Windows 98, Windows NT 4.0, and the Unix - programs from the mtools package. + You should say Y here if you said Y to "Unix98 PTY support" above. + You'll then get a virtual file system which can be mounted on + /dev/pts with "mount -t devpts". This, together with the pseudo + terminal master multiplexer /dev/ptmx, is used for pseudo terminal + support as described in The Open Group's Unix98 standard: in order + to acquire a pseudo terminal, a process opens /dev/ptmx; the number + of the pseudo terminal is then made available to the process and the + pseudo terminal slave can be accessed as /dev/pts/<number>. What was + traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - You cannot use the VFAT file system for your Linux root partition - (the one containing the directory /); use UMSDOS instead if you - want to run Linux from within a DOS partition (i.e. say Y to - "Unix like fs on top of std MSDOS fs", below). + The GNU C library glibc 2.1 contains the requisite support for this + mode of operation; you also need client programs that use the Unix98 + API. Please read <file:Documentation/Changes> for more information + about the Unix98 pty devices. - The VFAT support enlarges your kernel by about 10 KB and it only - works if you said Y to the "DOS FAT fs support" above. Please read - the file <file:Documentation/filesystems/vfat.txt> for details. If - unsure, say Y. + Note that the experimental "/dev file system support" + (CONFIG_DEVFS_FS) is a more general facility. + +config TMPFS + bool "Virtual memory file system support (former shm fs)" + help + Tmpfs is a file system which keeps all files in virtual memory. + + Everything in tmpfs is temporary in the sense that no files will be + created on your hard drive. The files live in memory and swap + space. If you unmount a tmpfs instance, everything stored therein is + lost. + + See <file:Documentation/filesystems/tmpfs.txt> for details. + +config HUGETLBFS + bool "HugeTLB file system support" + depends on HUGETLB_PAGE + +config RAMFS + bool + default y + ---help--- + Ramfs is a file system which keeps all files in RAM. It allows + read and write access. + + It is more of an programming example than a useable file system. If + you need a file system which lives in RAM with limit checking use + tmpfs. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/modules.txt>. The module - will be called vfat. + will be called ramfs. + +endmenu + +menu "Miscellaneous filesystems" + +config ADFS_FS + tristate "ADFS file system support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + The Acorn Disc Filing System is the standard file system of the + RiscOS operating system which runs on Acorn's ARM-based Risc PC + systems and the Acorn Archimedes range of machines. If you say Y + here, Linux will be able to read from ADFS partitions on hard drives + and from ADFS-formatted floppy discs. If you also want to be able to + write to those devices, say Y to "ADFS write support" below. + + The ADFS partition should be the first partition (i.e., + /dev/[hs]d?1) on each of your drives. Please read the file + <file:Documentation/filesystems/adfs.txt> for further details. + + This code is also available as a module called adfs ( = code which + can be inserted in and removed from the running kernel whenever you + want). If you want to compile it as a module, say M here and read + <file:Documentation/modules.txt>. + + If unsure, say N. + +config ADFS_FS_RW + bool "ADFS write support (DANGEROUS)" + depends on ADFS_FS + help + If you say Y here, you will be able to write to ADFS partitions on + hard drives and ADFS-formatted floppy disks. This is experimental + codes, so if you're unsure, say N. + +config AFFS_FS + tristate "Amiga FFS file system support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + The Fast File System (FFS) is the common file system used on hard + disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y + if you want to be able to read and write files from and to an Amiga + FFS partition on your hard drive. Amiga floppies however cannot be + read with this driver due to an incompatibility of the floppy + controller used in an Amiga and the standard floppy controller in + PCs and workstations. Read <file:Documentation/filesystems/affs.txt> + and <file:fs/affs/Changes>. + + With this driver you can also mount disk files used by Bernd + Schmidt's Un*X Amiga Emulator + (<http://www.freiburg.linux.de/~uae/>). + If you want to do this, you will also need to say Y or M to "Loop + device support", above. + + This file system is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called affs. If you want to compile it as a module, + say M here and read <file:Documentation/modules.txt>. If unsure, + say N. + +config HFS_FS + tristate "Apple Macintosh file system support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + If you say Y here, you will be able to mount Macintosh-formatted + floppy disks and hard drive partitions with full read-write access. + Please read <file:fs/hfs/HFS.txt> to learn about the available mount + options. + + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called hfs. If you want to + compile it as a module, say M here and read + <file:Documentation/modules.txt>. + +config BEFS_FS + tristate "BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + The BeOS File System (BeFS) is the native file system of Be, Inc's + BeOS. Notable features include support for arbitrary attributes + on files and directories, and database-like indices on selected + attributes. (Also note that this driver doesn't make those features + available at this time). It is a 64 bit filesystem, so it supports + extreemly large volumes and files. + + If you use this filesystem, you should also say Y to at least one + of the NLS (native language support) options below. + + If you don't know what this is about, say N. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called befs. + +config BEFS_DEBUG + bool "Debug BeFS" + depends on BEFS_FS + help + If you say Y here, you can use the 'debug' mount option to enable + debugging output from the driver. + +config BFS_FS + tristate "BFS file system support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Boot File System (BFS) is a file system used under SCO UnixWare to + allow the bootloader access to the kernel image and other important + files during the boot process. It is usually mounted under /stand + and corresponds to the slice marked as "STAND" in the UnixWare + partition. You should say Y if you want to read or write the files + on your /stand slice from within Linux. You then also need to say Y + to "UnixWare slices support", below. More information about the BFS + file system is contained in the file + <file:Documentation/filesystems/bfs.txt>. + + If you don't know what this is about, say N. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called bfs. Note that the file system of your root + partition (the one containing the directory /) cannot be compiled as + a module. + + config EFS_FS tristate "EFS file system support (read only) (EXPERIMENTAL)" depends on EXPERIMENTAL - ---help--- + help EFS is an older file system used for non-ISO9660 CD-ROMs and hard disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer uses the XFS file system for hard disk partitions however). @@ -538,7 +1018,7 @@ config JFFS2_FS_DEBUG int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)" depends on JFFS2_FS default "0" - ---help--- + help This controls the amount of debugging messages produced by the JFFS2 code. Set it to zero for use in production systems. For evaluation, testing and debugging, it's advisable to set it to one. This will @@ -555,7 +1035,7 @@ config JFFS2_FS_NAND bool "JFFS2 support for NAND flash (EXPERIMENTAL)" depends on JFFS2_FS && EXPERIMENTAL default n - ---help--- + help This enables the experimental support for NAND flash in JFFS2. NAND is a newer type of flash chip design than the traditional NOR flash, with higher density but a handful of characteristics which make it @@ -570,7 +1050,7 @@ config JFFS2_FS_NAND config CRAMFS tristate "Compressed ROM file system support" - ---help--- + help Saying Y here includes support for CramFs (Compressed ROM File System). CramFs is designed to be a simple, small, and compressed file system for ROM based embedded systems. CramFs is read-only, @@ -588,136 +1068,9 @@ config CRAMFS If unsure, say N. -config TMPFS - bool "Virtual memory file system support (former shm fs)" - help - Tmpfs is a file system which keeps all files in virtual memory. - - Everything in tmpfs is temporary in the sense that no files will be - created on your hard drive. The files live in memory and swap - space. If you unmount a tmpfs instance, everything stored therein is - lost. - - See <file:Documentation/filesystems/tmpfs.txt> for details. - -config RAMFS - bool - default y - ---help--- - Ramfs is a file system which keeps all files in RAM. It allows - read and write access. - - It is more of an programming example than a useable file system. If - you need a file system which lives in RAM with limit checking use - tmpfs. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called ramfs. - -config HUGETLBFS - bool "HugeTLB file system support" - depends on HUGETLB_PAGE - -config ISO9660_FS - tristate "ISO 9660 CDROM file system support" - ---help--- - This is the standard file system used on CD-ROMs. It was previously - known as "High Sierra File System" and is called "hsfs" on other - Unix systems. The so-called Rock-Ridge extensions which allow for - long Unix filenames and symbolic links are also supported by this - driver. If you have a CD-ROM drive and want to do more with it than - just listen to audio CDs and watch its LEDs, say Y (and read - <file:Documentation/filesystems/isofs.txt> and the CD-ROM-HOWTO, - available from <http://www.linuxdoc.org/docs.html#howto>), thereby - enlarging your kernel by about 27 KB; otherwise say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called isofs. - -config JOLIET - bool "Microsoft Joliet CDROM extensions" - depends on ISO9660_FS - help - Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system - which allows for long filenames in unicode format (unicode is the - new 16 bit character code, successor to ASCII, which encodes the - characters of almost all languages of the world; see - <http://www.unicode.org/> for more information). Say Y here if you - want to be able to read Joliet CD-ROMs under Linux. - -config ZISOFS - bool "Transparent decompression extension" - depends on ISO9660_FS - help - This is a Linux-specific extension to RockRidge which lets you store - data in compressed form on a CD-ROM and have it transparently - decompressed when the CD-ROM is accessed. See - <http://www.kernel.org/pub/linux/utils/fs/zisofs/> for the tools - necessary to create such a filesystem. Say Y here if you want to be - able to read such compressed CD-ROMs. - -config JFS_FS - tristate "JFS filesystem support" - help - This is a port of IBM's Journaled Filesystem . More information is - available in the file Documentation/filesystems/jfs.txt. - - If you do not intend to use the JFS filesystem, say N. - -config JFS_POSIX_ACL - bool "JFS POSIX Access Control Lists" - depends on JFS_FS - ---help--- - Posix Access Control Lists (ACLs) support permissions for users and - groups beyond the owner/group/world scheme. - - To learn more about Access Control Lists, visit the Posix ACLs for - Linux website <http://acl.bestbits.at/>. - - If you don't know what Access Control Lists are, say N - -config JFS_DEBUG - bool "JFS debugging" - depends on JFS_FS - help - If you are experiencing any problems with the JFS filesystem, say - Y here. This will result in additional debugging messages to be - written to the system log. Under normal circumstances, this - results in very little overhead. - -config JFS_STATISTICS - bool "JFS statistics" - depends on JFS_FS - help - Enabling this option will cause statistics from the JFS file system - to be made available to the user in the /proc/fs/jfs/ directory. - -config MINIX_FS - tristate "Minix fs support" - ---help--- - Minix is a simple operating system used in many classes about OS's. - The minix file system (method to organize files on a hard disk - partition or a floppy disk) was the original file system for Linux, - but has been superseded by the second extended file system ext2fs. - You don't want to use the minix file system on your hard disk - because of certain built-in restrictions, but it is sometimes found - on older Linux floppy disks. This option will enlarge your kernel - by about 28 KB. If unsure, say N. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called minix. Note that the file system of your root - partition (the one containing the directory /) cannot be compiled as - a module. - config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" - ---help--- + help FreeVxFS is a file system driver that support the VERITAS VxFS(TM) file system format. VERITAS VxFS(TM) is the standard file system of SCO UnixWare (and possibly others) and optionally available @@ -734,58 +1087,10 @@ config VXFS_FS module, say M here and read <file:Documentation/modules.txt>. If unsure, say N. -config NTFS_FS - tristate "NTFS file system support (read only)" - ---help--- - NTFS is the file system of Microsoft Windows NT/2000/XP. For more - information see <file:Documentation/filesystems/ntfs.txt>. Saying Y - here would allow you to read from NTFS partitions. - - This file system is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called ntfs. If you want to compile it as a - module, say M here and read <file:Documentation/modules.txt>. - - If you are not using Windows NT/2000/XP in addition to Linux on your - computer it is safe to say N. - -config NTFS_DEBUG - bool "NTFS debugging support" - depends on NTFS_FS - ---help--- - If you are experiencing any problems with the NTFS file system, say - Y here. This will result in additional consistency checks to be - performed by the driver as well as additional debugging messages to - be written to the system log. Note that debugging messages are - disabled by default. To enable them, supply the option debug_msgs=1 - at the kernel command line when booting the kernel or as an option - to insmod when loading the ntfs module. Once the driver is active, - you can enable debugging messages by doing (as root): - echo 1 > /proc/sys/fs/ntfs-debug - Replacing the "1" with "0" would disable debug messages. - - If you leave debugging messages disabled, this results in little - overhead, but enabling debug messages results in very significant - slowdown of the system. - - When reporting bugs, please try to have available a full dump of - debugging messages while the misbehaviour was occurring. - -config NTFS_RW - bool "NTFS write support (DANGEROUS)" - depends on NTFS_FS && EXPERIMENTAL - help - This enables the experimental write support in the NTFS driver. - - WARNING: Do not use this option unless you are actively developing - NTFS as it is currently guaranteed to be broken and you - may lose all your data! - - It is strongly recommended and perfectly safe to say N here. config HPFS_FS tristate "OS/2 HPFS file system support" - ---help--- + help OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS is the file system used for organizing files on OS/2 hard disk partitions. Say Y if you want to be able to read files from and @@ -800,104 +1105,11 @@ config HPFS_FS say M here and read <file:Documentation/modules.txt>. If unsure, say N. -config PROC_FS - bool "/proc file system support" - ---help--- - This is a virtual file system providing information about the status - of the system. "Virtual" means that it doesn't take up any space on - your hard disk: the files are created on the fly by the kernel when - you try to access them. Also, you cannot read the files with older - version of the program less: you need to use more or cat. - - It's totally cool; for example, "cat /proc/interrupts" gives - information about what the different IRQs are used for at the moment - (there is a small number of Interrupt ReQuest lines in your computer - that are used by the attached devices to gain the CPU's attention -- - often a source of trouble if two devices are mistakenly configured - to use the same IRQ). The program procinfo to display some - information about your system gathered from the /proc file system. - - Before you can use the /proc file system, it has to be mounted, - meaning it has to be given a location in the directory hierarchy. - That location should be /proc. A command such as "mount -t proc proc - /proc" or the equivalent line in /etc/fstab does the job. - - The /proc file system is explained in the file - <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage - ("man 5 proc"). - - This option will enlarge your kernel by about 67 KB. Several - programs depend on this, so everyone should say Y here. - -config DEVFS_FS - bool "/dev file system support (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - This is support for devfs, a virtual file system (like /proc) which - provides the file system interface to device drivers, normally found - in /dev. Devfs does not depend on major and minor number - allocations. Device drivers register entries in /dev which then - appear automatically, which means that the system administrator does - not have to create character and block special device files in the - /dev directory using the mknod command (or MAKEDEV script) anymore. - - This is work in progress. If you want to use this, you *must* read - the material in <file:Documentation/filesystems/devfs/>, especially - the file README there. - - If unsure, say N. - -config DEVFS_MOUNT - bool "Automatically mount at boot" - depends on DEVFS_FS - help - This option appears if you have CONFIG_DEVFS_FS enabled. Setting - this to 'Y' will make the kernel automatically mount devfs onto /dev - when the system is booted, before the init thread is started. - You can override this with the "devfs=nomount" boot option. - - If unsure, say N. - -config DEVFS_DEBUG - bool "Debug devfs" - depends on DEVFS_FS - help - If you say Y here, then the /dev file system code will generate - debugging messages. See the file - <file:Documentation/filesystems/devfs/boot-options> for more - details. - - If unsure, say N. - -# It compiles as a module for testing only. It should not be used -# as a module in general. If we make this "tristate", a bunch of people -# who don't know what they are doing turn it on and complain when it -# breaks. -config DEVPTS_FS - bool "/dev/pts file system for Unix98 PTYs" - depends on UNIX98_PTYS - ---help--- - You should say Y here if you said Y to "Unix98 PTY support" above. - You'll then get a virtual file system which can be mounted on - /dev/pts with "mount -t devpts". This, together with the pseudo - terminal master multiplexer /dev/ptmx, is used for pseudo terminal - support as described in The Open Group's Unix98 standard: in order - to acquire a pseudo terminal, a process opens /dev/ptmx; the number - of the pseudo terminal is then made available to the process and the - pseudo terminal slave can be accessed as /dev/pts/<number>. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - The GNU C library glibc 2.1 contains the requisite support for this - mode of operation; you also need client programs that use the Unix98 - API. Please read <file:Documentation/Changes> for more information - about the Unix98 pty devices. - Note that the experimental "/dev file system support" - (CONFIG_DEVFS_FS) is a more general facility. config QNX4FS_FS tristate "QNX4 file system support (read only)" - ---help--- + help This is the file system used by the real-time operating systems QNX 4 and QNX 6 (the latter is also called QNX RTP). Further information is available at <http://www.qnx.com/>. @@ -923,97 +1135,11 @@ config QNX4FS_RW It's currently broken, so for now: answer N. -config ROMFS_FS - tristate "ROM file system support" - ---help--- - This is a very small read-only file system mainly intended for - initial ram disks of installation disks, but it could be used for - other read-only media as well. Read - <file:Documentation/filesystems/romfs.txt> for details. - This file system support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called romfs. If you want to - compile it as a module, say M here and read - <file:Documentation/modules.txt>. Note that the file system of your - root partition (the one containing the directory /) cannot be a - module. - - If you don't know whether you need it, then you don't need it: - answer N. - -config EXT2_FS - tristate "Second extended fs support" - ---help--- - This is the de facto standard Linux file system (method to organize - files on a storage device) for hard disks. - - You want to say Y here, unless you intend to use Linux exclusively - from inside a DOS partition using the UMSDOS file system. The - advantage of the latter is that you can get away without - repartitioning your hard drive (which often implies backing - everything up and restoring afterwards); the disadvantage is that - Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat - slower than ext2fs. Even if you want to run Linux in this fashion, - it might be a good idea to have ext2fs around: it enables you to - read more floppy disks and facilitates the transition to a *real* - Linux partition later. Another (rare) case which doesn't require - ext2fs is a diskless Linux box which mounts all files over the - network using NFS (in this case it's sufficient to say Y to "NFS - file system support" below). Saying Y here will enlarge your kernel - by about 44 KB. - - The Ext2fs-Undeletion mini-HOWTO, available from - <http://www.linuxdoc.org/docs.html#howto>, gives information about - how to retrieve deleted files on ext2fs file systems. - - To change the behavior of ext2 file systems, you can use the tune2fs - utility ("man tune2fs"). To modify attributes of files and - directories on ext2 file systems, use chattr ("man chattr"). - - Ext2fs partitions can be read from within DOS using the ext2tool - command line tool package (available from - <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from - within Windows NT using the ext2nt command line tool package from - <ftp://ibiblio.org/pub/Linux/utils/dos/>. Explore2fs is a - graphical explorer for ext2fs partitions which runs on Windows 95 - and Windows NT and includes experimental write support; it is - available from - <http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm>. - - If you want to compile this file system as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read <file:Documentation/modules.txt>. The - module will be called ext2. Be aware however that the file system - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. - -config EXT2_FS_XATTR - bool "Ext2 extended attributes" - depends on EXT2_FS - ---help--- - Extended attributes are name:value pairs associated with inodes by - the kernel or by users (see the attr(5) manual page, or visit - <http://acl.bestbits.at/> for details). - - If unsure, say N. - -config EXT2_FS_POSIX_ACL - bool "Ext2 POSIX Access Control Lists" - depends on EXT2_FS_XATTR - ---help--- - Posix Access Control Lists (ACLs) support permissions for users and - groups beyond the owner/group/world scheme. - - To learn more about Access Control Lists, visit the Posix ACLs for - Linux website <http://acl.bestbits.at/>. - - If you don't know what Access Control Lists are, say N config SYSV_FS tristate "System V/Xenix/V7/Coherent file system support" - ---help--- + help SCO, Xenix and Coherent are commercial Unix systems for Intel machines, and Version 7 was used on the DEC PDP-11. Saying Y here would allow you to read from their floppies and hard disk @@ -1049,25 +1175,11 @@ config SYSV_FS If you haven't heard about all of this before, it's safe to say N. -config UDF_FS - tristate "UDF file system support" - ---help--- - This is the new file system used on some CD-ROMs and DVDs. Say Y if - you intend to mount DVD discs or CDRW's written in packet mode, or - if written to by other UDF utilities, such as DirectCD. - Please read <file:Documentation/filesystems/udf.txt>. - This file system support is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called udf. If you want to - compile it as a module, say M here and read - <file:Documentation/modules.txt>. - - If unsure, say N. config UFS_FS tristate "UFS file system support (read only)" - ---help--- + help BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, OpenBSD and NeXTstep) use a file system called UFS. Some System V Unixes can create and mount hard disk partitions and diskettes using @@ -1103,118 +1215,15 @@ config UFS_FS_WRITE Say Y here if you want to try writing to UFS partitions. This is experimental, so you should back up your UFS partitions beforehand. -config XFS_FS - tristate "XFS filesystem support" - ---help--- - XFS is a high performance journaling filesystem which originated - on the SGI IRIX platform. It is completely multi-threaded, can - support large files and large filesystems, extended attributes, - variable block sizes, is extent based, and makes extensive use of - Btrees (directories, extents, free space) to aid both performance - and scalability. - - Refer to the documentation at <http://oss.sgi.com/projects/xfs/> - for complete details. This implementation is on-disk compatible - with the IRIX version of XFS. - - If you want to compile this file system as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read <file:Documentation/modules.txt>. The - module will be called xfs. Be aware, however, that if the file - system of your root partition is compiled as a module, you'll need - to use an initial ramdisk (initrd) to boot. - -config XFS_RT - bool "Realtime support (EXPERIMENTAL)" - depends on XFS_FS && EXPERIMENTAL - ---help--- - If you say Y here you will be able to mount and use XFS filesystems - which contain a realtime subvolume. The realtime subvolume is a - separate area of disk space where only file data is stored. The - realtime subvolume is designed to provide very deterministic - data rates suitable for media streaming applications. - - See the xfs man page in section 5 for a bit more information. - - This feature is unsupported at this time, is not yet fully - functional, and may cause serious problems. - - If unsure, say N. - -config XFS_QUOTA - bool "Quota support" - depends on XFS_FS - ---help--- - If you say Y here, you will be able to set limits for disk usage on - a per user and/or a per group basis under XFS. XFS considers quota - information as filesystem metadata and uses journaling to provide a - higher level guarantee of consistency. The on-disk data format for - quota is also compatible with the IRIX version of XFS, allowing a - filesystem to be migrated between Linux and IRIX without any need - for conversion. - - If unsure, say N. More comprehensive documentation can be found in - README.quota in the xfsprogs package. XFS quota can be used either - with or without the generic quota support enabled (CONFIG_QUOTA) - - they are completely independent subsystems. - -config XFS_POSIX_ACL - bool "ACL support" - depends on XFS_FS - ---help--- - Posix Access Control Lists (ACLs) support permissions for users and - groups beyond the owner/group/world scheme. - - To learn more about Access Control Lists, visit the Posix ACLs for - Linux website <http://acl.bestbits.at/>. - - If you don't know what Access Control Lists are, say N - +endmenu menu "Network File Systems" depends on NET -config CODA_FS - tristate "Coda file system support (advanced network fs)" - depends on INET - ---help--- - Coda is an advanced network file system, similar to NFS in that it - enables you to mount file systems of a remote server and access them - with regular Unix commands as if they were sitting on your hard - disk. Coda has several advantages over NFS: support for - disconnected operation (e.g. for laptops), read/write server - replication, security model for authentication and encryption, - persistent client caches and write back caching. - - If you say Y here, your Linux box will be able to act as a Coda - *client*. You will need user level code as well, both for the - client and server. Servers are currently user level, i.e. they need - no kernel support. Please read - <file:Documentation/filesystems/coda.txt> and check out the Coda - home page <http://www.coda.cs.cmu.edu/>. - - If you want to compile the coda client support as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want), say M here and read - <file:Documentation/modules.txt>. The module will be called coda. - -config INTERMEZZO_FS - tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)" - depends on INET && EXPERIMENTAL - help - InterMezzo is a networked file system with disconnected operation - and kernel level write back caching. It is most often used for - replicating potentially large trees or keeping laptop/desktop copies - in sync. - - If you say Y or M your kernel or module will provide InterMezzo - support. You will also need a file server daemon, which you can get - from <http://www.inter-mezzo.org/>. - config NFS_FS tristate "NFS file system support" depends on INET - ---help--- + help If you are connected to some other (usually local) Unix computer (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing on that computer (the NFS server) using the Network File Sharing @@ -1268,24 +1277,10 @@ config NFS_V4 If unsure, say N. -config ROOT_NFS - bool "Root file system on NFS" - depends on NFS_FS=y && IP_PNP - help - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS (presumably because your box doesn't have a hard disk), - say Y. Read <file:Documentation/nfsroot.txt> for details. It is - likely that in this case, you also want to say Y to "Kernel level IP - autoconfiguration" so that your box can discover its network address - at boot time. - - Most people say N here. - config NFSD tristate "NFS server support" depends on INET - ---help--- + help If you want your Linux box to act as an NFS *server*, so that other computers on your local network which support NFS can access certain directories on your box transparently, you have two options: you can @@ -1334,34 +1329,19 @@ config NFSD_TCP Enable NFS service over TCP connections. This the officially still experimental, but seems to work well. -config SUNRPC - tristate - default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m) - default y if NFS_FS=y || NFSD=y - -config SUNRPC_GSS - tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)" - depends on SUNRPC && EXPERIMENTAL - default SUNRPC if NFS_V4=y - help - Provides cryptographic authentication for NFS rpc requests. To - make this useful, you must also select at least one rpcsec_gss - mechanism. - Note: You should always select this option if you wish to use - NFSv4. - -config RPCSEC_GSS_KRB5 - tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)" - depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5 - default SUNRPC_GSS if NFS_V4=y +config ROOT_NFS + bool "Root file system on NFS" + depends on NFS_FS=y && IP_PNP help - Provides a gss-api mechanism based on Kerberos V5 (this is - mandatory for RFC3010-compliant NFSv4 implementations). - Requires a userspace daemon; - see http://www.citi.umich.edu/projects/nfsv4/. + If you want your Linux box to mount its whole root file system (the + one containing the directory /) from some other computer over the + net via NFS (presumably because your box doesn't have a hard disk), + say Y. Read <file:Documentation/nfsroot.txt> for details. It is + likely that in this case, you also want to say Y to "Kernel level IP + autoconfiguration" so that your box can discover its network address + at boot time. - Note: If you select this option, please ensure that you also - enable the MD5 and DES crypto ciphers. + Most people say N here. config LOCKD tristate @@ -1377,32 +1357,10 @@ config EXPORTFS tristate default NFSD -config CIFS - tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)" - depends on INET - ---help--- - This is the client VFS module for the Common Internet File System - (CIFS) protocol which is the successor to the Server Message Block - (SMB) protocol, the native file sharing mechanism for most early - PC operating systems. CIFS is fully supported by current network - file servers such as Windows 2000 (including Windows NT version 4 - and Windows XP) as well by Samba (which provides excellent CIFS - server support for Linux and many other operating systems). For - production systems the smbfs module may be used instead of this - cifs module since smbfs is currently more stable and provides - support for older servers. The intent of this module is to provide the - most advanced network file system function for CIFS compliant servers, - including support for dfs (heirarchical name space), secure per-user - session establishment, safe distributed caching (oplock), optional - packet signing, Unicode and other internationalization improvements, and - optional Winbind (nsswitch) integration. This module is in an early - development stage, so unless you are specifically interested in this - filesystem, just say N. - config SMB_FS tristate "SMB file system support (to mount Windows shares etc.)" depends on INET - ---help--- + help SMB (Server Message Block) is the protocol Windows for Workgroups (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share files and printers over local networks. Saying Y here allows you to @@ -1456,10 +1414,32 @@ config SMB_NLS_REMOTE smbmount from samba 2.2.0 or later supports this. +config CIFS + tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)" + depends on INET + help + This is the client VFS module for the Common Internet File System + (CIFS) protocol which is the successor to the Server Message Block + (SMB) protocol, the native file sharing mechanism for most early + PC operating systems. CIFS is fully supported by current network + file servers such as Windows 2000 (including Windows NT version 4 + and Windows XP) as well by Samba (which provides excellent CIFS + server support for Linux and many other operating systems). For + production systems the smbfs module may be used instead of this + cifs module since smbfs is currently more stable and provides + support for older servers. The intent of this module is to provide the + most advanced network file system function for CIFS compliant servers, + including support for dfs (heirarchical name space), secure per-user + session establishment, safe distributed caching (oplock), optional + packet signing, Unicode and other internationalization improvements, and + optional Winbind (nsswitch) integration. This module is in an early + development stage, so unless you are specifically interested in this + filesystem, just say N. + config NCP_FS tristate "NCP file system support (to mount NetWare volumes)" depends on IPX!=n || INET - ---help--- + help NCP (NetWare Core Protocol) is a protocol that runs over IPX and is used by Novell NetWare clients to talk to file servers. It is to IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you @@ -1480,10 +1460,76 @@ config NCP_FS will be called ncpfs. Say N unless you are connected to a Novell network. +config CODA_FS + tristate "Coda file system support (advanced network fs)" + depends on INET + help + Coda is an advanced network file system, similar to NFS in that it + enables you to mount file systems of a remote server and access them + with regular Unix commands as if they were sitting on your hard + disk. Coda has several advantages over NFS: support for + disconnected operation (e.g. for laptops), read/write server + replication, security model for authentication and encryption, + persistent client caches and write back caching. + + If you say Y here, your Linux box will be able to act as a Coda + *client*. You will need user level code as well, both for the + client and server. Servers are currently user level, i.e. they need + no kernel support. Please read + <file:Documentation/filesystems/coda.txt> and check out the Coda + home page <http://www.coda.cs.cmu.edu/>. + + If you want to compile the coda client support as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want), say M here and read + <file:Documentation/modules.txt>. The module will be called coda. + +config INTERMEZZO_FS + tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)" + depends on INET && EXPERIMENTAL + help + InterMezzo is a networked file system with disconnected operation + and kernel level write back caching. It is most often used for + replicating potentially large trees or keeping laptop/desktop copies + in sync. + + If you say Y or M your kernel or module will provide InterMezzo + support. You will also need a file server daemon, which you can get + from <http://www.inter-mezzo.org/>. + +config SUNRPC + tristate + default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m) + default y if NFS_FS=y || NFSD=y + +config SUNRPC_GSS + tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)" + depends on SUNRPC && EXPERIMENTAL + default SUNRPC if NFS_V4=y + help + Provides cryptographic authentication for NFS rpc requests. To + make this useful, you must also select at least one rpcsec_gss + mechanism. + Note: You should always select this option if you wish to use + NFSv4. + +config RPCSEC_GSS_KRB5 + tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)" + depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5 + default SUNRPC_GSS if NFS_V4=y + help + Provides a gss-api mechanism based on Kerberos V5 (this is + mandatory for RFC3010-compliant NFSv4 implementations). + Requires a userspace daemon; + see http://www.citi.umich.edu/projects/nfsv4/. + + Note: If you select this option, please ensure that you also + enable the MD5 and DES crypto ciphers. + source "fs/ncpfs/Kconfig" -# for fs/nls/Config.in config AFS_FS +# for fs/nls/Config.in tristate "Andrew File System support (AFS) (Experimental)" depends on INET && EXPERIMENTAL help @@ -1501,29 +1547,6 @@ config RXRPC endmenu -# for fs/nls/Config.in -config ZISOFS_FS - tristate - depends on ZISOFS - default ISO9660_FS - -# Meta block cache for Extended Attributes (ext2/ext3) -config FS_MBCACHE - tristate - depends on EXT2_FS_XATTR || EXT3_FS_XATTR - default y if EXT2_FS=y || EXT3_FS=y - default m if EXT2_FS=m || EXT3_FS=m - -# Posix ACL utility routines (for now, only ext2/ext3/jfs) -# -# NOTE: you can implement Posix ACLs without these helpers (XFS does). -# Never use this symbol for ifdefs. -# -config FS_POSIX_ACL - bool - depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL - default y - menu "Partition Types" source "fs/partitions/Kconfig" diff --git a/fs/affs/Changes b/fs/affs/Changes index ee6308003167..a29409c1ffe0 100644 --- a/fs/affs/Changes +++ b/fs/affs/Changes @@ -28,6 +28,11 @@ Known bugs: Please direct bug reports to: zippel@linux-m68k.org +Version 3.20 +------------ +- kill kernel lock +- fix for a possible bitmap corruption + Version 3.19 ------------ diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index d1792538c26a..095ef77a407e 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -185,6 +185,8 @@ find_bmap: /* search for the next bmap buffer with free bits */ i = sbi->s_bmap_count; do { + if (--i < 0) + goto err_full; bmap++; bm++; if (bmap < sbi->s_bmap_count) @@ -192,8 +194,6 @@ find_bmap: /* restart search at zero */ bmap = 0; bm = sbi->s_bitmap; - if (--i <= 0) - goto err_full; } while (!bm->bm_free); blk = bmap * sbi->s_bmap_bits; @@ -216,8 +216,8 @@ find_bmap_bit: mask = ~0UL << (bit & 31); blk &= ~31UL; - tmp = be32_to_cpu(*data) & mask; - if (tmp) + tmp = be32_to_cpu(*data); + if (tmp & mask) goto find_bit; /* scan the rest of the buffer */ @@ -230,10 +230,11 @@ find_bmap_bit: goto find_bmap; } while (!(tmp = *data)); tmp = be32_to_cpu(tmp); + mask = ~0; find_bit: /* finally look for a free bit in the word */ - bit = ffs(tmp) - 1; + bit = ffs(tmp & mask) - 1; blk += bit + sbi->s_reserved; mask2 = mask = 1 << (bit & 31); AFFS_I(inode)->i_lastalloc = blk; @@ -266,8 +267,8 @@ err_bh_read: sbi->s_bmap_bh = NULL; sbi->s_last_bmap = ~0; err_full: - pr_debug("failed\n"); up(&sbi->s_bmlock); + pr_debug("failed\n"); return 0; } diff --git a/fs/affs/dir.c b/fs/affs/dir.c index f7fa4f8ddb71..3fc41d17359d 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -65,8 +65,6 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) int stored; int res; - lock_kernel(); - pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos); stored = 0; @@ -162,7 +160,6 @@ readdir_out: affs_brelse(dir_bh); affs_brelse(fh_bh); affs_unlock_dir(inode); - unlock_kernel(); pr_debug("AFFS: readdir()=%d\n", stored); return res; } diff --git a/fs/affs/inode.c b/fs/affs/inode.c index f109be30c624..37aca8f801fd 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -195,11 +195,9 @@ affs_write_inode(struct inode *inode, int unused) if (!inode->i_nlink) // possibly free block return; - lock_kernel(); bh = affs_bread(sb, inode->i_ino); if (!bh) { affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino); - unlock_kernel(); return; } tail = AFFS_TAIL(sb, bh); @@ -227,7 +225,7 @@ affs_write_inode(struct inode *inode, int unused) affs_fix_checksum(sb, bh); mark_buffer_dirty_inode(bh, inode); affs_brelse(bh); - unlock_kernel(); + affs_free_prealloc(inode); } int @@ -236,8 +234,6 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - lock_kernel(); - pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid); error = inode_change_ok(inode,attr); @@ -257,7 +253,6 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) if (!error && (attr->ia_valid & ATTR_MODE)) mode_to_prot(inode); out: - unlock_kernel(); return error; } @@ -265,15 +260,13 @@ void affs_put_inode(struct inode *inode) { pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); - lock_kernel(); affs_free_prealloc(inode); if (atomic_read(&inode->i_count) == 1) { + down(&inode->i_sem); if (inode->i_size != AFFS_I(inode)->mmu_private) affs_truncate(inode); - //if (inode->i_nlink) - // affs_clear_inode(inode); + up(&inode->i_sem); } - unlock_kernel(); } void @@ -284,9 +277,7 @@ affs_delete_inode(struct inode *inode) if (S_ISREG(inode->i_mode)) affs_truncate(inode); clear_inode(inode); - lock_kernel(); affs_free_block(inode->i_sb, inode->i_ino); - unlock_kernel(); } void diff --git a/fs/affs/namei.c b/fs/affs/namei.c index d9bf37b00e05..01defe3d0ff8 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -218,12 +218,10 @@ affs_lookup(struct inode *dir, struct dentry *dentry) pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name); - lock_kernel(); affs_lock_dir(dir); bh = affs_find_entry(dir, dentry); affs_unlock_dir(dir); if (IS_ERR(bh)) { - unlock_kernel(); return ERR_PTR(PTR_ERR(bh)); } if (bh) { @@ -240,12 +238,10 @@ affs_lookup(struct inode *dir, struct dentry *dentry) affs_brelse(bh); inode = iget(sb, ino); if (!inode) { - unlock_kernel(); return ERR_PTR(-EACCES); } } dentry->d_op = AFFS_SB(sb)->s_flags & SF_INTL ? &affs_intl_dentry_operations : &affs_dentry_operations; - unlock_kernel(); d_add(dentry, inode); return NULL; } @@ -253,17 +249,10 @@ affs_lookup(struct inode *dir, struct dentry *dentry) int affs_unlink(struct inode *dir, struct dentry *dentry) { - int res; pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32)dir->i_ino, (int)dentry->d_name.len, dentry->d_name.name); - if (!dentry->d_inode) - return -ENOENT; - - lock_kernel(); - res = affs_remove_header(dentry); - unlock_kernel(); - return res; + return affs_remove_header(dentry); } int @@ -276,12 +265,9 @@ affs_create(struct inode *dir, struct dentry *dentry, int mode) pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,(int)dentry->d_name.len, dentry->d_name.name,mode); - lock_kernel(); inode = affs_new_inode(dir); - if (!inode) { - unlock_kernel(); + if (!inode) return -ENOSPC; - } inode->i_mode = mode; mode_to_prot(inode); @@ -294,10 +280,8 @@ affs_create(struct inode *dir, struct dentry *dentry, int mode) if (error) { inode->i_nlink = 0; iput(inode); - unlock_kernel(); return error; } - unlock_kernel(); return 0; } @@ -310,12 +294,9 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode) pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name,mode); - lock_kernel(); inode = affs_new_inode(dir); - if (!inode) { - unlock_kernel(); + if (!inode) return -ENOSPC; - } inode->i_mode = S_IFDIR | mode; mode_to_prot(inode); @@ -328,10 +309,8 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode) inode->i_nlink = 0; mark_inode_dirty(inode); iput(inode); - unlock_kernel(); return error; } - unlock_kernel(); return 0; } @@ -357,14 +336,10 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name,symname); - lock_kernel(); maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1; - error = -ENOSPC; inode = affs_new_inode(dir); - if (!inode) { - unlock_kernel(); + if (!inode) return -ENOSPC; - } inode->i_op = &affs_symlink_inode_operations; inode->i_data.a_ops = &affs_symlink_aops; @@ -410,7 +385,6 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK); if (error) goto err; - unlock_kernel(); return 0; @@ -418,7 +392,6 @@ err: inode->i_nlink = 0; mark_inode_dirty(inode); iput(inode); - unlock_kernel(); return error; } @@ -426,23 +399,11 @@ int affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; - int error; pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name); - lock_kernel(); - error = affs_add_entry(dir, inode, dentry, ST_LINKFILE); - if (error) { - /* WTF??? */ - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput(inode); - unlock_kernel(); - return error; - } - unlock_kernel(); - return 0; + return affs_add_entry(dir, inode, dentry, ST_LINKFILE); } int @@ -453,21 +414,19 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, struct buffer_head *bh = NULL; int retval; - lock_kernel(); pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); - if ((retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len))) - goto done; + retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len); + if (retval) + return retval; /* Unlink destination if it already exists */ if (new_dentry->d_inode) { retval = affs_remove_header(new_dentry); - if (retval) { - unlock_kernel(); + if (retval) return retval; - } } retval = -EIO; @@ -493,6 +452,5 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, done: mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); affs_brelse(bh); - unlock_kernel(); return retval; } diff --git a/fs/affs/super.c b/fs/affs/super.c index ebc0fb917744..3774983a00fd 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -40,7 +40,6 @@ static void affs_put_super(struct super_block *sb) { struct affs_sb_info *sbi = AFFS_SB(sb); - lock_kernel(); pr_debug("AFFS: put_super()\n"); if (!(sb->s_flags & MS_RDONLY)) { @@ -58,7 +57,6 @@ affs_put_super(struct super_block *sb) affs_brelse(sbi->s_root_bh); kfree(sbi); sb->s_fs_info = NULL; - unlock_kernel(); return; } @@ -67,7 +65,7 @@ affs_write_super(struct super_block *sb) { int clean = 2; struct affs_sb_info *sbi = AFFS_SB(sb); - lock_kernel(); + if (!(sb->s_flags & MS_RDONLY)) { // if (sbi->s_bitmap[i].bm_bh) { // if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) { @@ -81,7 +79,7 @@ affs_write_super(struct super_block *sb) } else sb->s_dirt = 0; - unlock_kernel(); + pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean); } static kmem_cache_t * affs_inode_cachep; @@ -300,7 +298,8 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) if (!sbi) return -ENOMEM; sb->s_fs_info = sbi; - memset(sbi, 0, sizeof(*AFFS_SB)); + memset(sbi, 0, sizeof(struct affs_sb_info)); + init_MUTEX(&sbi->s_bmlock); if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index c7e53656b540..c01cd4c64a61 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -32,9 +32,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page) pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino); err = -EIO; - lock_kernel(); bh = affs_bread(inode->i_sb, inode->i_ino); - unlock_kernel(); if (!bh) goto fail; i = 0; @@ -63,9 +61,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page) j++; } link[i] = '\0'; - lock_kernel(); affs_brelse(bh); - unlock_kernel(); SetPageUptodate(page); kunmap(page); unlock_page(page); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 5a643a493345..409ab7469996 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -452,6 +452,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) unsigned int size; unsigned long elf_entry, interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; + unsigned long reloc_func_desc = 0; struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; @@ -695,6 +696,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) load_bias += error - ELF_PAGESTART(load_bias + vaddr); load_addr += load_bias; + reloc_func_desc = load_addr; } } k = elf_ppnt->p_vaddr; @@ -742,6 +744,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) retval = -ENOEXEC; /* Nobody gets to see this, but.. */ goto out; } + reloc_func_desc = interp_load_addr; } else { elf_entry = elf_ex.e_entry; } @@ -789,10 +792,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* * The ABI may specify that certain registers be set up in special * ways (on i386 %edx is the address of a DT_FINI function, for - * example. This macro performs whatever initialization to - * the regs structure is required. + * example. In addition, it may also specify (eg, PowerPC64 ELF) + * that the e_entry field is the address of the function descriptor + * for the startup routine, rather than the address of the startup + * routine itself. This macro performs whatever initialization to + * the regs structure is required as well as any relocations to the + * function descriptor entries when executing dynamically links apps. */ - ELF_PLAT_INIT(regs); + ELF_PLAT_INIT(regs, reloc_func_desc); #endif start_thread(regs, elf_entry, bprm->p); diff --git a/fs/dcache.c b/fs/dcache.c index 4317d965af1a..719571fa0e47 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -24,7 +24,9 @@ #include <linux/cache.h> #include <linux/module.h> #include <linux/mount.h> +#include <linux/file.h> #include <asm/uaccess.h> +#include <linux/security.h> #define DCACHE_PARANOIA 1 /* #define DCACHE_DEBUG 1 */ @@ -760,6 +762,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) void d_instantiate(struct dentry *entry, struct inode * inode) { if (!list_empty(&entry->d_alias)) BUG(); + security_d_instantiate(entry, inode); spin_lock(&dcache_lock); if (inode) list_add(&entry->d_alias, &inode->i_dentry); @@ -890,6 +893,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) struct dentry *new = NULL; if (inode && S_ISDIR(inode->i_mode)) { + security_d_instantiate(dentry, inode); spin_lock(&dcache_lock); if (!list_empty(&inode->i_dentry)) { new = list_entry(inode->i_dentry.next, struct dentry, d_alias); @@ -1571,7 +1575,7 @@ void __init vfs_caches_init(unsigned long mempages) filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + SLAB_HWCACHE_ALIGN, filp_ctor, filp_dtor); if(!filp_cachep) panic("Cannot create filp SLAB cache"); diff --git a/fs/devfs/base.c b/fs/devfs/base.c index c87c23f3fa01..9cefcfa5b8a7 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -1802,8 +1802,11 @@ int devfs_generate_path (devfs_handle_t de, char *path, int buflen) static struct file_operations *devfs_get_ops (devfs_handle_t de) { struct file_operations *ops = de->u.cdev.ops; - struct module *owner = ops->owner; + struct module *owner; + if (!ops) + return NULL; + owner = ops->owner; read_lock (&de->parent->u.dir.lock); /* Prevent module from unloading */ if ( (de->next == de) || !try_module_get (owner) ) { /* Entry is already unhooked or module is unloading */ diff --git a/fs/exec.c b/fs/exec.c index 061f96130173..f0b70ae3698d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -633,7 +633,7 @@ static inline int de_thread(struct task_struct *tsk) count = 1; while (atomic_read(&oldsig->count) > count) { oldsig->group_exit_task = current; - current->state = TASK_UNINTERRUPTIBLE; + __set_current_state(TASK_UNINTERRUPTIBLE); spin_unlock_irq(lock); schedule(); spin_lock_irq(lock); diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 9a66fe94dc3f..c74c4a628633 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -353,7 +353,7 @@ static int get_name(struct dentry *dentry, char *name, /* * Open the directory ... */ - error = init_private_file(&file, dentry, FMODE_READ); + error = open_private_file(&file, dentry, O_RDONLY); if (error) goto out; error = -EINVAL; @@ -381,8 +381,7 @@ static int get_name(struct dentry *dentry, char *name, } out_close: - if (file.f_op->release) - file.f_op->release(dir, &file); + close_private_file(&file); out: return error; } diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index e5bee153791a..40868d403f0b 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -395,7 +395,7 @@ int ext2_new_block (struct inode * inode, unsigned long goal, goto io_error; group_alloc = group_reserve_blocks(desc, gdp_bh, es_alloc); } - if (bit >= sbi->s_groups_count) { + if (!group_alloc) { *err = -ENOSPC; goto out_release; } diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 7850dcbe7bf1..610695289845 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -112,6 +112,7 @@ extern int ext2_sync_inode (struct inode *); extern void ext2_discard_prealloc (struct inode *); extern void ext2_truncate (struct inode *); extern int ext2_setattr (struct dentry *, struct iattr *); +extern void ext2_set_inode_flags(struct inode *inode); /* ioctl.c */ extern int ext2_ioctl (struct inode *, struct file *, unsigned int, diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 345e7495176d..87b2d99f4a7c 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -545,10 +545,7 @@ repeat: ei->i_prealloc_count = 0; ei->i_dir_start_lookup = 0; ei->i_state = EXT2_STATE_NEW; - if (ei->i_flags & EXT2_SYNC_FL) - inode->i_flags |= S_SYNC; - if (ei->i_flags & EXT2_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; + ext2_set_inode_flags(inode); inode->i_generation = EXT2_SB(sb)->s_next_generation++; insert_inode_hash(inode); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index e47f84e305cd..c2fbefdd3613 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1011,6 +1011,23 @@ Egdp: return ERR_PTR(-EIO); } +void ext2_set_inode_flags(struct inode *inode) +{ + unsigned int flags = EXT2_I(inode)->i_flags; + + inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); + if (flags & EXT2_SYNC_FL) + inode->i_flags |= S_SYNC; + if (flags & EXT2_APPEND_FL) + inode->i_flags |= S_APPEND; + if (flags & EXT2_IMMUTABLE_FL) + inode->i_flags |= S_IMMUTABLE; + if (flags & EXT2_NOATIME_FL) + inode->i_flags |= S_NOATIME; + if (flags & EXT2_DIRSYNC_FL) + inode->i_flags |= S_DIRSYNC; +} + void ext2_read_inode (struct inode * inode) { struct ext2_inode_info *ei = EXT2_I(inode); @@ -1108,14 +1125,7 @@ void ext2_read_inode (struct inode * inode) le32_to_cpu(raw_inode->i_block[0])); } brelse (bh); - if (ei->i_flags & EXT2_SYNC_FL) - inode->i_flags |= S_SYNC; - if (ei->i_flags & EXT2_APPEND_FL) - inode->i_flags |= S_APPEND; - if (ei->i_flags & EXT2_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - if (ei->i_flags & EXT2_NOATIME_FL) - inode->i_flags |= S_NOATIME; + ext2_set_inode_flags(inode); return; bad_inode: diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index afff8566f3b6..101055bbf519 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -58,22 +58,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE; ei->i_flags = flags; - if (flags & EXT2_SYNC_FL) - inode->i_flags |= S_SYNC; - else - inode->i_flags &= ~S_SYNC; - if (flags & EXT2_APPEND_FL) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; - if (flags & EXT2_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; - if (flags & EXT2_NOATIME_FL) - inode->i_flags |= S_NOATIME; - else - inode->i_flags &= ~S_NOATIME; + ext2_set_inode_flags(inode); inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); return 0; diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 228fa402af19..155c19c4ac92 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -568,10 +568,7 @@ repeat: #endif ei->i_block_group = group; - if (ei->i_flags & EXT3_SYNC_FL) - inode->i_flags |= S_SYNC; - if (ei->i_flags & EXT3_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; + ext3_set_inode_flags(inode); if (IS_DIRSYNC(inode)) handle->h_sync = 1; insert_inode_hash(inode); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index b37c23fb3d5a..5012c1719ee4 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2209,6 +2209,24 @@ int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc) return -EIO; } +void ext3_set_inode_flags(struct inode *inode) +{ + unsigned int flags = EXT3_I(inode)->i_flags; + + inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); + if (flags & EXT3_SYNC_FL) + inode->i_flags |= S_SYNC; + if (flags & EXT3_APPEND_FL) + inode->i_flags |= S_APPEND; + if (flags & EXT3_IMMUTABLE_FL) + inode->i_flags |= S_IMMUTABLE; + if (flags & EXT3_NOATIME_FL) + inode->i_flags |= S_NOATIME; + if (flags & EXT3_DIRSYNC_FL) + inode->i_flags |= S_DIRSYNC; +} + + void ext3_read_inode(struct inode * inode) { struct ext3_iloc iloc; @@ -2320,14 +2338,7 @@ void ext3_read_inode(struct inode * inode) init_special_inode(inode, inode->i_mode, le32_to_cpu(iloc.raw_inode->i_block[0])); } - if (ei->i_flags & EXT3_SYNC_FL) - inode->i_flags |= S_SYNC; - if (ei->i_flags & EXT3_APPEND_FL) - inode->i_flags |= S_APPEND; - if (ei->i_flags & EXT3_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - if (ei->i_flags & EXT3_NOATIME_FL) - inode->i_flags |= S_NOATIME; + ext3_set_inode_flags(inode); return; bad_inode: diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 5d74409cef07..cedf91bde8a2 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -85,22 +85,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE; ei->i_flags = flags; - if (flags & EXT3_SYNC_FL) - inode->i_flags |= S_SYNC; - else - inode->i_flags &= ~S_SYNC; - if (flags & EXT3_APPEND_FL) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; - if (flags & EXT3_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; - if (flags & EXT3_NOATIME_FL) - inode->i_flags |= S_NOATIME; - else - inode->i_flags &= ~S_NOATIME; + ext3_set_inode_flags(inode); inode->i_ctime = CURRENT_TIME; err = ext3_mark_iloc_dirty(handle, inode, &iloc); diff --git a/fs/file_table.c b/fs/file_table.c index 4e66a3598de8..8ae8d29c2365 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -22,94 +22,123 @@ struct files_stat_struct files_stat = { .max_files = NR_FILE }; -/* Here the new files go */ -static LIST_HEAD(anon_list); -/* And here the free ones sit */ -static LIST_HEAD(free_list); /* public *and* exported. Not pretty! */ -spinlock_t files_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; +spinlock_t __cacheline_aligned_in_smp files_lock = SPIN_LOCK_UNLOCKED; + +static spinlock_t filp_count_lock = SPIN_LOCK_UNLOCKED; + +/* slab constructors and destructors are called from arbitrary + * context and must be fully threaded - use a local spinlock + * to protect files_stat.nr_files + */ +void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) +{ + if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) { + unsigned long flags; + spin_lock_irqsave(&filp_count_lock, flags); + files_stat.nr_files++; + spin_unlock_irqrestore(&filp_count_lock, flags); + } +} + +void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) +{ + unsigned long flags; + spin_lock_irqsave(&filp_count_lock, flags); + files_stat.nr_files--; + spin_unlock_irqrestore(&filp_count_lock, flags); +} + +static inline void file_free(struct file *f) +{ + kmem_cache_free(filp_cachep, f); +} /* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. - * - * SMP-safe. */ -struct file * get_empty_filp(void) +struct file *get_empty_filp(void) { - static int old_max = 0; +static int old_max = 0; struct file * f; - file_list_lock(); - if (files_stat.nr_free_files > NR_RESERVED_FILES) { - used_one: - f = list_entry(free_list.next, struct file, f_list); - list_del(&f->f_list); - files_stat.nr_free_files--; - new_one: - memset(f, 0, sizeof(*f)); - if (security_file_alloc(f)) { - list_add(&f->f_list, &free_list); - files_stat.nr_free_files++; - file_list_unlock(); - return NULL; - } - eventpoll_init_file(f); - atomic_set(&f->f_count,1); - f->f_version = 0; - f->f_uid = current->fsuid; - f->f_gid = current->fsgid; - f->f_owner.lock = RW_LOCK_UNLOCKED; - list_add(&f->f_list, &anon_list); - file_list_unlock(); - return f; - } - /* - * Use a reserved one if we're the superuser - */ - if (files_stat.nr_free_files && !current->euid) - goto used_one; /* - * Allocate a new one if we're below the limit. + * Privileged users can go above max_files */ - if (files_stat.nr_files < files_stat.max_files) { - file_list_unlock(); - f = kmem_cache_alloc(filp_cachep, SLAB_KERNEL); - file_list_lock(); + if (files_stat.nr_files < files_stat.max_files || + capable(CAP_SYS_ADMIN)) { + f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); if (f) { - files_stat.nr_files++; - goto new_one; + memset(f, 0, sizeof(*f)); + if (security_file_alloc(f)) { + file_free(f); + goto fail; + } + eventpoll_init_file(f); + atomic_set(&f->f_count, 1); + f->f_uid = current->fsuid; + f->f_gid = current->fsgid; + f->f_owner.lock = RW_LOCK_UNLOCKED; + /* f->f_version: 0 */ + INIT_LIST_HEAD(&f->f_list); + return f; } - /* Big problems... */ - printk(KERN_WARNING "VFS: filp allocation failed\n"); + } - } else if (files_stat.max_files > old_max) { - printk(KERN_INFO "VFS: file-max limit %d reached\n", files_stat.max_files); + /* Ran out of filps - report that */ + if (files_stat.max_files >= old_max) { + printk(KERN_INFO "VFS: file-max limit %d reached\n", + files_stat.max_files); old_max = files_stat.max_files; + } else { + /* Big problems... */ + printk(KERN_WARNING "VFS: filp allocation failed\n"); } - file_list_unlock(); +fail: return NULL; } /* * Clear and initialize a (private) struct file for the given dentry, - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. + * allocate the security structure, and call the open function (if any). + * The file should be released using close_private_file. */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int open_private_file(struct file *filp, struct dentry *dentry, int flags) { + int error; memset(filp, 0, sizeof(*filp)); eventpoll_init_file(filp); - filp->f_mode = mode; + filp->f_flags = flags; + filp->f_mode = (flags+1) & O_ACCMODE; atomic_set(&filp->f_count, 1); filp->f_dentry = dentry; filp->f_uid = current->fsuid; filp->f_gid = current->fsgid; filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; + INIT_LIST_HEAD(&filp->f_list); + error = security_file_alloc(filp); + if (!error) + if (filp->f_op && filp->f_op->open) { + error = filp->f_op->open(dentry->d_inode, filp); + if (error) + security_file_free(filp); + } + return error; +} + +/* + * Release a private file by calling the release function (if any) and + * freeing the security structure. + */ +void close_private_file(struct file *file) +{ + struct inode * inode = file->f_dentry->d_inode; + + if (file->f_op && file->f_op->release) + file->f_op->release(inode, file); + security_file_free(file); } void fput(struct file * file) @@ -121,11 +150,11 @@ void fput(struct file * file) /* __fput is called from task context when aio completion releases the last * last use of a struct file *. Do not use otherwise. */ -void __fput(struct file * file) +void __fput(struct file *file) { - struct dentry * dentry = file->f_dentry; - struct vfsmount * mnt = file->f_vfsmnt; - struct inode * inode = dentry->d_inode; + struct dentry *dentry = file->f_dentry; + struct vfsmount *mnt = file->f_vfsmnt; + struct inode *inode = dentry->d_inode; /* * The function eventpoll_release() should be the first called @@ -140,20 +169,17 @@ void __fput(struct file * file) fops_put(file->f_op); if (file->f_mode & FMODE_WRITE) put_write_access(inode); - file_list_lock(); file->f_dentry = NULL; file->f_vfsmnt = NULL; - list_del(&file->f_list); - list_add(&file->f_list, &free_list); - files_stat.nr_free_files++; - file_list_unlock(); + file_kill(file); + file_free(file); dput(dentry); mntput(mnt); } -struct file * fget(unsigned int fd) +struct file *fget(unsigned int fd) { - struct file * file; + struct file *file; struct files_struct *files = current->files; read_lock(&files->file_lock); @@ -164,17 +190,12 @@ struct file * fget(unsigned int fd) return file; } -/* Here. put_filp() is SMP-safe now. */ - void put_filp(struct file *file) { - if(atomic_dec_and_test(&file->f_count)) { + if (atomic_dec_and_test(&file->f_count)) { security_file_free(file); - file_list_lock(); - list_del(&file->f_list); - list_add(&file->f_list, &free_list); - files_stat.nr_free_files++; - file_list_unlock(); + file_kill(file); + file_free(file); } } @@ -183,16 +204,17 @@ void file_move(struct file *file, struct list_head *list) if (!list) return; file_list_lock(); - list_del(&file->f_list); - list_add(&file->f_list, list); + list_move(&file->f_list, list); file_list_unlock(); } void file_kill(struct file *file) { - file_list_lock(); - list_del_init(&file->f_list); - file_list_unlock(); + if (!list_empty(&file->f_list)) { + file_list_lock(); + list_del_init(&file->f_list); + file_list_unlock(); + } } int fs_may_remount_ro(struct super_block *sb) @@ -209,7 +231,7 @@ int fs_may_remount_ro(struct super_block *sb) if (inode->i_nlink == 0) goto too_bad; - /* Writable file? */ + /* Writeable file? */ if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) goto too_bad; } diff --git a/fs/inode.c b/fs/inode.c index 514863d8df82..e54c9ae0169b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -129,6 +129,7 @@ static struct inode *alloc_inode(struct super_block *sb) inode->i_pipe = NULL; inode->i_bdev = NULL; inode->i_cdev = NULL; + inode->i_rdev = to_kdev_t(0); inode->i_security = NULL; if (security_inode_alloc(inode)) { if (inode->i_sb->s_op->destroy_inode) @@ -1213,7 +1214,7 @@ repeat: goto repeat; } remove_wait_queue(wq, &wait); - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); } void wake_up_inode(struct inode *inode) diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 8a827b109c93..dfb16a579c99 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -305,8 +305,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, (long long)lock->fl.fl_end, wait); - /* Lock file against concurrent access */ - down(&file->f_sema); /* Get existing block (in case client is busy-waiting) */ block = nlmsvc_lookup_block(file, lock, 0); @@ -314,6 +312,9 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, lock->fl.fl_flags |= FL_LOCKD; again: + /* Lock file against concurrent access */ + down(&file->f_sema); + if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) { error = posix_lock_file(&file->f_file, &lock->fl); @@ -346,7 +347,10 @@ again: /* If we don't have a block, create and initialize it. Then * retry because we may have slept in kmalloc. */ + /* We have to release f_sema as nlmsvc_create_block may try to + * to claim it while doing host garbage collection */ if (block == NULL) { + up(&file->f_sema); dprintk("lockd: blocking on this lock (allocating).\n"); if (!(block = nlmsvc_create_block(rqstp, file, lock, cookie))) return nlm_lck_denied_nolocks; diff --git a/fs/locks.c b/fs/locks.c index 90f4211bb1d9..1e78fd26a18b 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -565,7 +565,7 @@ static int interruptible_sleep_on_locked(wait_queue_head_t *fl_wait, int timeout int result = 0; DECLARE_WAITQUEUE(wait, current); - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(fl_wait, &wait); if (timeout == 0) schedule(); @@ -574,7 +574,7 @@ static int interruptible_sleep_on_locked(wait_queue_head_t *fl_wait, int timeout if (signal_pending(current)) result = -ERESTARTSYS; remove_wait_queue(fl_wait, &wait); - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); return result; } diff --git a/fs/namei.c b/fs/namei.c index d9c1748ff7aa..953d519cb9aa 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -361,10 +361,8 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i result = dir->i_op->lookup(dir, dentry); if (result) dput(dentry); - else { + else result = dentry; - security_inode_post_lookup(dir, result); - } } up(&dir->i_sem); return result; @@ -894,10 +892,9 @@ struct dentry * lookup_hash(struct qstr *name, struct dentry * base) if (!new) goto out; dentry = inode->i_op->lookup(inode, new); - if (!dentry) { + if (!dentry) dentry = new; - security_inode_post_lookup(inode, dentry); - } else + else dput(new); } out: diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index ea39aa340908..67ed9d1bc1b8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1231,6 +1231,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, if (root->size > sizeof(root->data)) { printk("nfs_get_sb: invalid root filehandle\n"); + kfree(server); return ERR_PTR(-EINVAL); } /* We now require that the mount process passes the remote address */ diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 03c01534a522..4ea38a35403e 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -294,7 +294,9 @@ int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) /* client */ len = qword_get(&mesg, buf, PAGE_SIZE); - if (len <= 0) return -EINVAL; + err = -EINVAL; + if (len <= 0) goto out; + err = -ENOENT; dom = auth_domain_find(buf); if (!dom) @@ -473,8 +475,14 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, exp = svc_export_lookup(&key, 0); if (exp != NULL) - if (cache_check(&svc_export_cache, &exp->h, reqp)) + switch (cache_check(&svc_export_cache, &exp->h, reqp)) { + case 0: break; + case -EAGAIN: + exp = ERR_PTR(-EAGAIN); + break; + default: exp = NULL; + } return exp; } @@ -915,7 +923,8 @@ struct flags { { NFSEXP_UIDMAP, {"uidmap", ""}}, { NFSEXP_KERBEROS, { "kerberos", ""}}, { NFSEXP_SUNSECURE, { "sunsecure", ""}}, - { NFSEXP_CROSSMNT, {"nohide", ""}}, + { NFSEXP_NOHIDE, {"nohide", ""}}, + { NFSEXP_CROSSMNT, {"crossmnt", ""}}, { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, #ifdef MSNFS diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 088ee1438f54..03e8f194fff2 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -79,7 +79,7 @@ static struct raparms * raparm_cache; * N.B. After this call _both_ fhp and resfh need an fh_put * * If the lookup would cross a mountpoint, and the mounted filesystem - * is exported to the client with NFSEXP_CROSSMNT, then the lookup is + * is exported to the client with NFSEXP_NOHIDE, then the lookup is * accepted as it stands and the mounted directory is * returned. Otherwise the covered directory is returned. * NOTE: this mountpoint crossing is not supported properly by all @@ -115,7 +115,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, read_lock(&dparent_lock); dentry = dget(dparent->d_parent); read_unlock(&dparent_lock); - } else if (!EX_CROSSMNT(exp)) + } else if (!EX_NOHIDE(exp)) dentry = dget(dparent); /* .. == . just like at / */ else { /* checking mountpoint crossing is very different when stepping up */ @@ -133,6 +133,12 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, exp2 = exp_parent(exp->ex_client, mnt, dentry, &rqstp->rq_chandle); + if (IS_ERR(exp2)) { + err = PTR_ERR(exp2); + dput(dentry); + mntput(mnt); + goto out; + } if (!exp2) { dput(dentry); dentry = dget(dparent); @@ -157,9 +163,19 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, struct dentry *mounts = dget(dentry); while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)) ; + exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle); - if (exp2 && EX_CROSSMNT(exp2)) { + if (IS_ERR(exp2)) { + err = PTR_ERR(exp2); + dput(mounts); + dput(dentry); + mntput(mnt); + goto out; + } + if (exp2 && + ((exp->ex_flags & NFSEXP_CROSSMNT) + || EX_NOHIDE(exp2))) { /* successfully crossed mount point */ exp_put(exp); exp = exp2; @@ -426,7 +442,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, { struct dentry *dentry; struct inode *inode; - int flags = O_RDONLY|O_LARGEFILE, mode = FMODE_READ, err; + int flags = O_RDONLY|O_LARGEFILE, err; /* * If we get here, then the client has already done an "open", @@ -463,14 +479,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, goto out_nfserr; flags = O_WRONLY|O_LARGEFILE; - mode = FMODE_WRITE; DQUOT_INIT(inode); } - err = init_private_file(filp, dentry, mode); + err = open_private_file(filp, dentry, flags); if (!err) { - filp->f_flags = flags; filp->f_vfsmnt = fhp->fh_export->ex_mnt; } else if (access & MAY_WRITE) put_write_access(inode); @@ -491,8 +505,7 @@ nfsd_close(struct file *filp) struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; - if (filp->f_op->release) - filp->f_op->release(inode, filp); + close_private_file(filp); if (filp->f_mode & FMODE_WRITE) put_write_access(inode); } @@ -1190,7 +1203,9 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, iap->ia_mode = (iap->ia_mode&S_IALLUGO) | S_IFLNK; err = notify_change(dnew, iap); - if (!err && EX_ISSYNC(fhp->fh_export)) + if (err) + err = nfserrno(err); + else if (EX_ISSYNC(fhp->fh_export)) write_inode_now(dentry->d_inode, 1); } } diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index f7c79e8704ee..f7332ea47ea1 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -42,6 +42,7 @@ #include <linux/blkdev.h> #include <linux/hugetlb.h> #include <linux/jiffies.h> +#include <linux/sysrq.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> @@ -521,6 +522,28 @@ static struct file_operations proc_profile_operations = { .write = write_profile, }; +#ifdef CONFIG_MAGIC_SYSRQ +/* + * writing 'C' to /proc/sysrq-trigger is like sysrq-C + */ +static ssize_t write_sysrq_trigger(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + if (count) { + char c; + + if (get_user(c, buf)) + return -EFAULT; + handle_sysrq(c, NULL, NULL); + } + return count; +} + +static struct file_operations proc_sysrq_trigger_operations = { + .write = write_sysrq_trigger, +}; +#endif + struct proc_dir_entry *proc_root_kcore; static void create_seq_entry(char *name, mode_t mode, struct file_operations *f) @@ -592,6 +615,11 @@ void __init proc_misc_init(void) entry->size = (1+prof_len) * sizeof(unsigned int); } } +#ifdef CONFIG_MAGIC_SYSRQ + entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL); + if (entry) + entry->proc_fops = &proc_sysrq_trigger_operations; +#endif #ifdef CONFIG_PPC32 { extern struct file_operations ppc_htab_operations; diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index d90636bfe358..bd15acb84aa9 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1310,6 +1310,10 @@ static void free_journal_ram(struct super_block *p_s_sb) { if (SB_JOURNAL(p_s_sb)->j_header_bh) { brelse(SB_JOURNAL(p_s_sb)->j_header_bh) ; } + /* j_header_bh is on the journal dev, make sure not to release the journal + * dev until we brelse j_header_bh + */ + release_journal_dev(p_s_sb, SB_JOURNAL(p_s_sb)); vfree(SB_JOURNAL(p_s_sb)) ; } @@ -1341,7 +1345,6 @@ static int do_journal_release(struct reiserfs_transaction_handle *th, struct sup commit_wq = NULL; } - release_journal_dev( p_s_sb, SB_JOURNAL( p_s_sb ) ); free_journal_ram(p_s_sb) ; return 0 ; @@ -1867,24 +1870,18 @@ static int release_journal_dev( struct super_block *super, int result; result = 0; - if( journal -> j_dev_file != NULL ) { - /* - * journal block device was taken via filp_open - */ result = filp_close( journal -> j_dev_file, NULL ); journal -> j_dev_file = NULL; journal -> j_dev_bd = NULL; } else if( journal -> j_dev_bd != NULL ) { - /* - * journal block device was taken via bdget and blkdev_get - */ result = blkdev_put( journal -> j_dev_bd, BDEV_FS ); journal -> j_dev_bd = NULL; } + if( result != 0 ) { - reiserfs_warning("sh-457: release_journal_dev: Cannot release journal device: %i", result ); + reiserfs_warning("sh-457: release_journal_dev: Cannot release journal device: %i\n", result ); } return result; } @@ -1895,6 +1892,7 @@ static int journal_init_dev( struct super_block *super, { int result; dev_t jdev; + int blkdev_mode = FMODE_READ | FMODE_WRITE; result = 0; @@ -1902,12 +1900,16 @@ static int journal_init_dev( struct super_block *super, journal -> j_dev_file = NULL; jdev = SB_ONDISK_JOURNAL_DEVICE( super ) ? SB_ONDISK_JOURNAL_DEVICE( super ) : super->s_dev; + + if (bdev_read_only(super->s_bdev)) + blkdev_mode = FMODE_READ; + /* there is no "jdev" option and journal is on separate device */ if( ( !jdev_name || !jdev_name[ 0 ] ) ) { journal -> j_dev_bd = bdget(jdev); if( journal -> j_dev_bd ) result = blkdev_get( journal -> j_dev_bd, - FMODE_READ | FMODE_WRITE, 0, + blkdev_mode, 0, BDEV_FS ); else result = -ENOMEM; @@ -1928,10 +1930,10 @@ static int journal_init_dev( struct super_block *super, jdev_inode = journal -> j_dev_file -> f_dentry -> d_inode; journal -> j_dev_bd = jdev_inode -> i_bdev; if( !S_ISBLK( jdev_inode -> i_mode ) ) { - printk( "journal_init_dev: '%s' is not a block device", jdev_name ); + printk( "journal_init_dev: '%s' is not a block device\n", jdev_name ); result = -ENOTBLK; } else if( jdev_inode -> i_bdev == NULL ) { - printk( "journal_init_dev: bdev uninitialized for '%s'", jdev_name ); + printk( "journal_init_dev: bdev uninitialized for '%s'\n", jdev_name ); result = -ENOMEM; } else { /* ok */ @@ -1941,12 +1943,12 @@ static int journal_init_dev( struct super_block *super, } else { result = PTR_ERR( journal -> j_dev_file ); journal -> j_dev_file = NULL; - printk( "journal_init_dev: Cannot open '%s': %i", jdev_name, result ); + printk( "journal_init_dev: Cannot open '%s': %i\n", jdev_name, result ); } if( result != 0 ) { release_journal_dev( super, journal ); } - printk( "journal_init_dev: journal device: %s", bdevname(journal->j_dev_bd)); + printk( "journal_init_dev: journal device: %s\n", bdevname(journal->j_dev_bd)); return result; } @@ -1960,20 +1962,24 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo struct reiserfs_journal_header *jh; struct reiserfs_journal *journal; - if (sizeof(struct reiserfs_journal_commit) != 4096 || - sizeof(struct reiserfs_journal_desc) != 4096 - ) { - printk("journal-1249: commit or desc struct not 4096 %Zd %Zd\n", sizeof(struct reiserfs_journal_commit), + if (sizeof(struct reiserfs_journal_commit) != 4096 || + sizeof(struct reiserfs_journal_desc) != 4096) { + printk("journal-1249: commit or desc struct not 4096 %Zd %Zd\n", sizeof(struct reiserfs_journal_commit), sizeof(struct reiserfs_journal_desc)) ; - return 1 ; - } + return 1 ; + } journal = SB_JOURNAL(p_s_sb) = vmalloc(sizeof (struct reiserfs_journal)) ; if (!journal) { printk("journal-1256: unable to get memory for journal structure\n") ; - return 1 ; - } + return 1 ; + } memset(journal, 0, sizeof(struct reiserfs_journal)) ; + INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_bitmap_nodes) ; + INIT_LIST_HEAD (&SB_JOURNAL(p_s_sb)->j_prealloc_list); + reiserfs_allocate_list_bitmaps(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_bitmap, + SB_BMAP_NR(p_s_sb)) ; + allocate_bitmap_nodes(p_s_sb) ; /* reserved for journal area support */ SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) = (old_format ? @@ -1983,7 +1989,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo if( journal_init_dev( p_s_sb, journal, j_dev_name ) != 0 ) { printk( "sh-462: unable to initialize jornal device\n"); - return 1; + goto free_and_return; } rs = SB_DISK_SUPER_BLOCK(p_s_sb); @@ -1993,8 +1999,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + SB_ONDISK_JOURNAL_SIZE(p_s_sb)); if (!bhjh) { printk("sh-459: unable to read journal header\n") ; - release_journal_dev(p_s_sb, journal); - return 1 ; + goto free_and_return; } jh = (struct reiserfs_journal_header *)(bhjh->b_data); @@ -2005,8 +2010,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo jh->jh_journal.jp_journal_magic, bdevname( SB_JOURNAL(p_s_sb)->j_dev_bd ), sb_jp_journal_magic(rs), reiserfs_bdevname (p_s_sb)); brelse (bhjh); - release_journal_dev(p_s_sb, journal); - return 1 ; + goto free_and_return; } SB_JOURNAL_TRANS_MAX(p_s_sb) = le32_to_cpu (jh->jh_journal.jp_journal_trans_max); @@ -2064,7 +2068,6 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo brelse (bhjh); - SB_JOURNAL(p_s_sb)->j_list_bitmap_index = 0 ; SB_JOURNAL_LIST_INDEX(p_s_sb) = -10000 ; /* make sure flush_old_commits does not try to flush a list while replay is on */ @@ -2075,12 +2078,8 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo memset(SB_JOURNAL(p_s_sb)->j_list_hash_table, 0, JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *)) ; memset(journal_writers, 0, sizeof(char *) * 512) ; /* debug code */ - INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_bitmap_nodes) ; INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_dirty_buffers) ; spin_lock_init(&SB_JOURNAL(p_s_sb)->j_dirty_buffers_lock) ; - reiserfs_allocate_list_bitmaps(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_bitmap, - SB_BMAP_NR(p_s_sb)) ; - allocate_bitmap_nodes(p_s_sb) ; SB_JOURNAL(p_s_sb)->j_start = 0 ; SB_JOURNAL(p_s_sb)->j_len = 0 ; @@ -2107,20 +2106,15 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap = get_list_bitmap(p_s_sb, SB_JOURNAL_LIST(p_s_sb)) ; if (!(SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap)) { reiserfs_warning("journal-2005, get_list_bitmap failed for journal list 0\n") ; - release_journal_dev(p_s_sb, journal); - return 1 ; + goto free_and_return; } if (journal_read(p_s_sb) < 0) { reiserfs_warning("Replay Failure, unable to mount\n") ; - free_journal_ram(p_s_sb) ; - release_journal_dev(p_s_sb, journal); - return 1 ; + goto free_and_return; } SB_JOURNAL_LIST_INDEX(p_s_sb) = 0 ; /* once the read is done, we can set this where it belongs */ - INIT_LIST_HEAD (&SB_JOURNAL(p_s_sb)->j_prealloc_list); - if (reiserfs_dont_log (p_s_sb)) return 0; @@ -2129,7 +2123,9 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo commit_wq = create_workqueue("reiserfs"); return 0 ; - +free_and_return: + free_journal_ram(p_s_sb); + return 1; } /* diff --git a/fs/select.c b/fs/select.c index 510e1defe964..ce46b5c90eb5 100644 --- a/fs/select.c +++ b/fs/select.c @@ -235,7 +235,7 @@ int do_select(int n, fd_set_bits *fds, long *timeout) } __timeout = schedule_timeout(__timeout); } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); poll_freewait(&table); @@ -425,7 +425,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, break; timeout = schedule_timeout(timeout); } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); return count; } diff --git a/fs/seq_file.c b/fs/seq_file.c index 7d2b18a7bfe4..ba4d28168e01 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -1,7 +1,7 @@ /* * linux/fs/seq_file.c * - * helper functions for making syntetic files from sequences of records. + * helper functions for making synthetic files from sequences of records. * initial implementation -- AV, Oct 2001. */ @@ -215,7 +215,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) while ((retval=traverse(m, offset)) == -EAGAIN) ; if (retval) { - /* with extreme perjudice... */ + /* with extreme prejudice... */ file->f_pos = 0; m->index = 0; m->count = 0; diff --git a/fs/super.c b/fs/super.c index 8ed04f0c4849..2bdc57573671 100644 --- a/fs/super.c +++ b/fs/super.c @@ -611,6 +611,7 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) struct file_system_type *type = get_fs_type(fstype); struct super_block *sb = ERR_PTR(-ENOMEM); struct vfsmount *mnt; + int error; if (!type) return ERR_PTR(-ENODEV); @@ -621,6 +622,9 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) sb = type->get_sb(type, flags, name, data); if (IS_ERR(sb)) goto out_mnt; + error = security_sb_kern_mount(sb); + if (error) + goto out_sb; mnt->mnt_sb = sb; mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = sb->s_root; @@ -628,6 +632,10 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) up_write(&sb->s_umount); put_filesystem(type); return mnt; +out_sb: + up_write(&sb->s_umount); + deactivate_super(sb); + sb = ERR_PTR(error); out_mnt: free_vfsmnt(mnt); out: diff --git a/fs/ufs/util.c b/fs/ufs/util.c index 41b5a8567eda..7656699c165d 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c @@ -48,6 +48,7 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi, failed: for (j = 0; j < i; j++) brelse (ubh->bh[j]); + kfree(ubh); return NULL; } diff --git a/include/asm-alpha/elf.h b/include/asm-alpha/elf.h index 033597e3e0ab..deb49419d65d 100644 --- a/include/asm-alpha/elf.h +++ b/include/asm-alpha/elf.h @@ -50,7 +50,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; we start programs with a value of 0 to indicate that there is no such function. */ -#define ELF_PLAT_INIT(_r) _r->r0 = 0 +#define ELF_PLAT_INIT(_r, load_addr) _r->r0 = 0 /* The registers are layed out in pt_regs for PAL and syscall convenience. Re-order them for the linear elf_gregset_t. */ diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h index 3f88b46f8dfe..1e82bf33cb84 100644 --- a/include/asm-alpha/pci.h +++ b/include/asm-alpha/pci.h @@ -190,6 +190,11 @@ pci_dac_dma_sync_single(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, /* Return the index of the PCI controller for device PDEV. */ extern int pci_controller_num(struct pci_dev *pdev); + +extern void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res); + #endif /* __KERNEL__ */ /* Values for the `which' argument to sys_pciconfig_iobase. */ diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index 7ebef35ec653..00deda790e01 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -48,7 +48,7 @@ typedef struct { void *null; } elf_fpregset_t; /* When the program starts, a1 contains a pointer to a function to be registered with atexit, as per the SVR4 ABI. A value of 0 means we have no such handler. */ -#define ELF_PLAT_INIT(_r) (_r)->ARM_r0 = 0 +#define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 /* This yields a mask that user programs can use to figure out what instruction set this cpu supports. */ diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h index 193c96e1609f..72843a2888b5 100644 --- a/include/asm-arm/pci.h +++ b/include/asm-arm/pci.h @@ -175,6 +175,10 @@ void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr); extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); +extern void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res); + #endif /* __KERNEL__ */ #endif diff --git a/include/asm-cris/elf.h b/include/asm-cris/elf.h index dba80d0609ef..798aeaeaabd1 100644 --- a/include/asm-cris/elf.h +++ b/include/asm-cris/elf.h @@ -39,7 +39,7 @@ typedef unsigned long elf_fpregset_t; A value of 0 tells we have no such handler. */ /* Explicitly set registers to 0 to increase determinism. */ -#define ELF_PLAT_INIT(_r) do { \ +#define ELF_PLAT_INIT(_r, load_addr) do { \ (_r)->r13 = 0; (_r)->r12 = 0; (_r)->r11 = 0; (_r)->r10 = 0; \ (_r)->r9 = 0; (_r)->r8 = 0; (_r)->r7 = 0; (_r)->r6 = 0; \ (_r)->r5 = 0; (_r)->r4 = 0; (_r)->r3 = 0; (_r)->r2 = 0; \ diff --git a/include/asm-generic/pci.h b/include/asm-generic/pci.h new file mode 100644 index 000000000000..df757d240e9a --- /dev/null +++ b/include/asm-generic/pci.h @@ -0,0 +1,25 @@ +/* + * linux/include/asm-generic/pci.h + * + * Copyright (C) 2003 Russell King + */ +#ifndef _ASM_GENERIC_PCI_H +#define _ASM_GENERIC_PCI_H + +/** + * pcibios_resource_to_bus - convert resource to PCI bus address + * @dev: device which owns this resource + * @region: converted bus-centric region (start,end) + * @res: resource to convert + * + * Convert a resource to a PCI device bus address or bus window. + */ +static inline void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) +{ + region->start = res->start; + region->end = res->end; +} + +#endif diff --git a/include/asm-generic/xor.h b/include/asm-generic/xor.h index 5cca395bf3d2..aaab875e1a35 100644 --- a/include/asm-generic/xor.h +++ b/include/asm-generic/xor.h @@ -678,35 +678,35 @@ xor_32regs_p_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, } static struct xor_block_template xor_block_8regs = { - name: "8regs", - do_2: xor_8regs_2, - do_3: xor_8regs_3, - do_4: xor_8regs_4, - do_5: xor_8regs_5, + .name = "8regs", + .do_2 = xor_8regs_2, + .do_3 = xor_8regs_3, + .do_4 = xor_8regs_4, + .do_5 = xor_8regs_5, }; static struct xor_block_template xor_block_32regs = { - name: "32regs", - do_2: xor_32regs_2, - do_3: xor_32regs_3, - do_4: xor_32regs_4, - do_5: xor_32regs_5, + .name = "32regs", + .do_2 = xor_32regs_2, + .do_3 = xor_32regs_3, + .do_4 = xor_32regs_4, + .do_5 = xor_32regs_5, }; static struct xor_block_template xor_block_8regs_p = { - name: "8regs_prefetch", - do_2: xor_8regs_p_2, - do_3: xor_8regs_p_3, - do_4: xor_8regs_p_4, - do_5: xor_8regs_p_5, + .name = "8regs_prefetch", + .do_2 = xor_8regs_p_2, + .do_3 = xor_8regs_p_3, + .do_4 = xor_8regs_p_4, + .do_5 = xor_8regs_p_5, }; static struct xor_block_template xor_block_32regs_p = { - name: "32regs_prefetch", - do_2: xor_32regs_p_2, - do_3: xor_32regs_p_3, - do_4: xor_32regs_p_4, - do_5: xor_32regs_p_5, + .name = "32regs_prefetch", + .do_2 = xor_32regs_p_2, + .do_3 = xor_32regs_p_3, + .do_4 = xor_32regs_p_4, + .do_5 = xor_32regs_p_5, }; #define XOR_TRY_TEMPLATES \ diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h index 5f019713fa4c..46a85b395db8 100644 --- a/include/asm-i386/cpufeature.h +++ b/include/asm-i386/cpufeature.h @@ -9,9 +9,9 @@ #include <linux/bitops.h> -#define NCAPINTS 4 /* Currently we have 4 32-bit words worth of info */ +#define NCAPINTS 6 /* Currently we have 6 32-bit words worth of info */ -/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */ +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ #define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ #define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ #define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ @@ -64,6 +64,11 @@ #define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ #define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ + #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) @@ -87,6 +92,7 @@ #define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR) #define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR) #define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR) +#define cpu_has_xstore boot_cpu_has(X86_FEATURE_XSTORE) #endif /* __ASM_I386_CPUFEATURE_H */ diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h index 73f4067e3995..e893fbf20593 100644 --- a/include/asm-i386/elf.h +++ b/include/asm-i386/elf.h @@ -43,7 +43,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t; We might as well make sure everything else is cleared too (except for %esp), just to make things more deterministic. */ -#define ELF_PLAT_INIT(_r) do { \ +#define ELF_PLAT_INIT(_r, load_addr) do { \ _r->ebx = 0; _r->ecx = 0; _r->edx = 0; \ _r->esi = 0; _r->edi = 0; _r->ebp = 0; \ _r->eax = 0; \ diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h index 520821cb5eaf..65e0461fd8be 100644 --- a/include/asm-i386/hw_irq.h +++ b/include/asm-i386/hw_irq.h @@ -56,6 +56,7 @@ extern void disable_IO_APIC(void); extern void print_IO_APIC(void); extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); extern void send_IPI(int dest, int vector); +extern void setup_ioapic_dest(unsigned long mask); extern unsigned long io_apic_irqs; diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h index a87fcba929f1..7c738dc96ae1 100644 --- a/include/asm-i386/msr.h +++ b/include/asm-i386/msr.h @@ -218,6 +218,7 @@ /* VIA Cyrix defined MSRs*/ #define MSR_VIA_FCR 0x1107 #define MSR_VIA_LONGHAUL 0x110a +#define MSR_VIA_RNG 0x110b #define MSR_VIA_BCR2 0x1147 /* Transmeta defined MSRs */ diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index d41feaba85ef..e0e0442260df 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -105,4 +105,7 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, /* implement the pci_ DMA API in terms of the generic device dma_ one */ #include <asm-generic/pci-dma-compat.h> +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* __i386_PCI_H */ diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index bcdf20186143..8640f483d6ee 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -231,18 +231,41 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pmd_large(pmd) \ ((pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT)) -/* to find an entry in a page-table-directory. */ +/* + * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD] + * + * this macro returns the index of the entry in the pgd page which would + * control the given virtual address + */ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +/* + * pgd_offset() returns a (pgd_t *) + * pgd_index() is used get the offset into the pgd page's array of pgd_t's; + */ #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) -/* to find an entry in a kernel page-table-directory */ +/* + * a shortcut which implies the use of the kernel's pgd, instead + * of a process's + */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) +/* + * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] + * + * this macro returns the index of the entry in the pmd page which would + * control the given virtual address + */ #define pmd_index(address) \ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -/* Find an entry in the third-level page table.. */ +/* + * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] + * + * this macro returns the index of the entry in the pte page which would + * control the given virtual address + */ #define pte_index(address) \ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) \ diff --git a/include/asm-i386/xor.h b/include/asm-i386/xor.h index 0b0dfb0b9431..366d6f15383d 100644 --- a/include/asm-i386/xor.h +++ b/include/asm-i386/xor.h @@ -25,6 +25,7 @@ #define XO3(x,y) " pxor 8*("#x")(%4), %%mm"#y" ;\n" #define XO4(x,y) " pxor 8*("#x")(%5), %%mm"#y" ;\n" +#include <asm/i387.h> static void xor_pII_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h index 8fb191e7712e..4ff7995fae2f 100644 --- a/include/asm-ia64/elf.h +++ b/include/asm-ia64/elf.h @@ -50,7 +50,7 @@ * talk to him... */ extern void ia64_init_addr_space (void); -#define ELF_PLAT_INIT(_r) ia64_init_addr_space() +#define ELF_PLAT_INIT(_r, load_addr) ia64_init_addr_space() /* ELF register definitions. This is needed for core dump support. */ diff --git a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h index 4824df582b8a..35f3b28272c4 100644 --- a/include/asm-ia64/ia32.h +++ b/include/asm-ia64/ia32.h @@ -306,7 +306,7 @@ struct old_linux32_dirent { #define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000) void ia64_elf32_init(struct pt_regs *regs); -#define ELF_PLAT_INIT(_r) ia64_elf32_init(_r) +#define ELF_PLAT_INIT(_r, load_addr) ia64_elf32_init(_r) #define elf_addr_t u32 diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h index 62a7d5a544d5..69a58612d87b 100644 --- a/include/asm-ia64/pci.h +++ b/include/asm-ia64/pci.h @@ -97,4 +97,7 @@ extern int pcibios_prep_mwi (struct pci_dev *); extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* _ASM_IA64_PCI_H */ diff --git a/include/asm-m68k/elf.h b/include/asm-m68k/elf.h index e2743983c3ba..48fa3301dcba 100644 --- a/include/asm-m68k/elf.h +++ b/include/asm-m68k/elf.h @@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t; /* For SVR4/m68k the function pointer to be registered with `atexit' is passed in %a1. Although my copy of the ABI has no such statement, it is actually used on ASV. */ -#define ELF_PLAT_INIT(_r) _r->a1 = 0 +#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0 #define USE_ELF_CORE_DUMP #ifndef CONFIG_SUN3 diff --git a/include/asm-m68knommu/elf.h b/include/asm-m68knommu/elf.h index 566f96120a1f..951a12b26722 100644 --- a/include/asm-m68knommu/elf.h +++ b/include/asm-m68knommu/elf.h @@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t; /* For SVR4/m68k the function pointer to be registered with `atexit' is passed in %a1. Although my copy of the ABI has no such statement, it is actually used on ASV. */ -#define ELF_PLAT_INIT(_r) _r->a1 = 0 +#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0 #define USE_ELF_CORE_DUMP #ifndef CONFIG_SUN3 diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h index f37acc0f8f1f..e6969081689e 100644 --- a/include/asm-mips/elf.h +++ b/include/asm-mips/elf.h @@ -73,7 +73,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; * See comments in asm-alpha/elf.h, this is the same thing * on the MIPS. */ -#define ELF_PLAT_INIT(_r) do { \ +#define ELF_PLAT_INIT(_r, load_addr) do { \ _r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \ _r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \ _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h index 84c9bd2b9bfb..98b248e8cd29 100644 --- a/include/asm-mips/pci.h +++ b/include/asm-mips/pci.h @@ -252,4 +252,7 @@ extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* _ASM_PCI_H */ diff --git a/include/asm-mips64/elf.h b/include/asm-mips64/elf.h index 2fbde92931bd..43a244f9f762 100644 --- a/include/asm-mips64/elf.h +++ b/include/asm-mips64/elf.h @@ -76,7 +76,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; * See comments in asm-alpha/elf.h, this is the same thing * on the MIPS. */ -#define ELF_PLAT_INIT(_r) do { \ +#define ELF_PLAT_INIT(_r, load_addr) do { \ _r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \ _r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \ _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ diff --git a/include/asm-mips64/pci.h b/include/asm-mips64/pci.h index a7cc388c5824..730e04075480 100644 --- a/include/asm-mips64/pci.h +++ b/include/asm-mips64/pci.h @@ -272,4 +272,8 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* _ASM_PCI_H */ + diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h index 226db77c5cb6..b421d4b8d178 100644 --- a/include/asm-parisc/assembly.h +++ b/include/asm-parisc/assembly.h @@ -21,7 +21,25 @@ #ifndef _PARISC_ASSEMBLY_H #define _PARISC_ASSEMBLY_H -#if defined(__LP64__) && defined(__ASSEMBLY__) +#ifdef __LP64__ +#define LDREG ldd +#define STREG std +#define LDREGM ldd,mb +#define STREGM std,ma +#define RP_OFFSET 16 +#define FRAME_SIZE 128 +#else +#define LDREG ldw +#define STREG stw +#define LDREGM ldwm +#define STREGM stwm +#define RP_OFFSET 20 +#define FRAME_SIZE 64 +#endif + +#ifdef __ASSEMBLY__ + +#ifdef __LP64__ /* the 64-bit pa gnu assembler unfortunately defaults to .level 1.1 or 2.0 so * work around that for now... */ .level 2.0w @@ -101,22 +119,6 @@ ldo R%\value(\reg), \reg .endm -#ifdef __LP64__ -#define LDREG ldd -#define STREG std -#define LDREGM ldd,mb -#define STREGM std,ma -#define RP_OFFSET 16 -#define FRAME_SIZE 128 -#else -#define LDREG ldw -#define STREG stw -#define LDREGM ldwm -#define STREGM stwm -#define RP_OFFSET 20 -#define FRAME_SIZE 64 -#endif - .macro loadgp #ifdef __LP64__ ldil L%__gp, %r27 @@ -420,4 +422,5 @@ REST_CR (%cr22, PT_PSW (\regs)) .endm +#endif /* __ASSEMBLY__ */ #endif diff --git a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h index 83b2f926e8e7..51ed91c4b644 100644 --- a/include/asm-parisc/bug.h +++ b/include/asm-parisc/bug.h @@ -5,7 +5,9 @@ * Tell the user there is some problem. */ #define BUG() do { \ + extern void dump_stack(void); \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + dump_stack(); \ } while (0) #define PAGE_BUG(page) do { \ diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h index b7012daae860..cb9e13b3d1bd 100644 --- a/include/asm-parisc/cacheflush.h +++ b/include/asm-parisc/cacheflush.h @@ -25,9 +25,14 @@ flush_page_to_ram(struct page *page) extern void flush_cache_all_local(void); +static inline void cacheflush_h_tmp_function(void *dummy) +{ + flush_cache_all_local(); +} + static inline void flush_cache_all(void) { - on_each_cpu((void (*)(void *))flush_cache_all_local, NULL, 1, 1); + on_each_cpu(cacheflush_h_tmp_function, NULL, 1, 1); } /* The following value needs to be tuned and probably scaled with the @@ -62,13 +67,15 @@ flush_user_icache_range(unsigned long start, unsigned long end) #endif } +extern void __flush_dcache_page(struct page *page); + static inline void flush_dcache_page(struct page *page) { if (page->mapping && list_empty(&page->mapping->i_mmap) && list_empty(&page->mapping->i_mmap_shared)) { set_bit(PG_dcache_dirty, &page->flags); } else { - flush_kernel_dcache_page(page_address(page)); + __flush_dcache_page(page); } } diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h index a95e682ea0bd..13f59a86b0fb 100644 --- a/include/asm-parisc/compat.h +++ b/include/asm-parisc/compat.h @@ -18,6 +18,7 @@ typedef u16 compat_mode_t; typedef u32 compat_ino_t; typedef u32 compat_dev_t; typedef s32 compat_off_t; +typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; typedef s32 compat_daddr_t; @@ -96,7 +97,7 @@ struct compat_statfs { typedef u32 compat_old_sigset_t; /* at least 32 bits */ #define _COMPAT_NSIG 64 -#define _COMPAT_NSIG_BPW BITS_PER_LONG +#define _COMPAT_NSIG_BPW 32 typedef u32 compat_sigset_word; diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h index 9ec23ebda0bc..ea946f11abe6 100644 --- a/include/asm-parisc/elf.h +++ b/include/asm-parisc/elf.h @@ -99,6 +99,9 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); +#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) + struct pt_regs; /* forward declaration... */ @@ -118,7 +121,7 @@ struct pt_regs; /* forward declaration... */ So that we can use the same startup file with static executables, we start programs with a value of 0 to indicate that there is no such function. */ -#define ELF_PLAT_INIT(_r) _r->gr[23] = 0 +#define ELF_PLAT_INIT(_r, load_addr) _r->gr[23] = 0 #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 4096 diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h index d7d96c18480a..d3224c078248 100644 --- a/include/asm-parisc/ide.h +++ b/include/asm-parisc/ide.h @@ -83,6 +83,44 @@ static __inline__ void ide_init_default_hwifs(void) #define ide_check_region(from,extent) check_region((from), (extent)) #define ide_request_region(from,extent,name) request_region((from), (extent), (name)) #define ide_release_region(from,extent) release_region((from), (extent)) +/* Generic I/O and MEMIO string operations. */ + +#define __ide_insw insw +#define __ide_insl insl +#define __ide_outsw outsw +#define __ide_outsl outsl + +static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count) +{ + while (count--) { + *(u16 *)addr = readw(port); + addr += 2; + } +} + +static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count) +{ + while (count--) { + *(u32 *)addr = readl(port); + addr += 4; + } +} + +static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count) +{ + while (count--) { + writew(*(u16 *)addr, port); + addr += 2; + } +} + +static __inline__ void __ide_mm_outsl(unsigned long port, void *addr, u32 count) +{ + while (count--) { + writel(*(u32 *)addr, port); + addr += 4; + } +} #endif /* __KERNEL__ */ diff --git a/include/asm-parisc/kmap_types.h b/include/asm-parisc/kmap_types.h index 5d875871190a..bc8bff06d35b 100644 --- a/include/asm-parisc/kmap_types.h +++ b/include/asm-parisc/kmap_types.h @@ -21,7 +21,9 @@ D(7) KM_PTE0, D(8) KM_PTE1, D(9) KM_IRQ0, D(10) KM_IRQ1, -D(11) KM_TYPE_NR +D(11) KM_SOFTIRQ0, +D(12) KM_SOFTIRQ1, +D(13) KM_TYPE_NR }; #undef D diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h index 2dbd703983e7..d44ad70d0e35 100644 --- a/include/asm-parisc/pci.h +++ b/include/asm-parisc/pci.h @@ -186,4 +186,8 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x) /* export the pci_ DMA API in terms of the dma_ one */ #include <asm-generic/pci-dma-compat.h> +extern void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res); + #endif /* __ASM_PARISC_PCI_H */ diff --git a/include/asm-parisc/posix_types.h b/include/asm-parisc/posix_types.h index 6ec66e81eb85..53c74802f51b 100644 --- a/include/asm-parisc/posix_types.h +++ b/include/asm-parisc/posix_types.h @@ -17,6 +17,8 @@ typedef unsigned int __kernel_uid_t; typedef unsigned int __kernel_gid_t; typedef int __kernel_suseconds_t; typedef int __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; typedef int __kernel_daddr_t; /* Note these change from narrow to wide kernels */ #ifdef __LP64__ diff --git a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h index 939bc47dd038..181fc75a0228 100644 --- a/include/asm-parisc/ptrace.h +++ b/include/asm-parisc/ptrace.h @@ -43,9 +43,6 @@ struct pt_regs { * since we have taken branch traps too) */ #define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ -#define PTRACE_GETSIGINFO 13 /* get child's siginfo structure */ -#define PTRACE_SETSIGINFO 14 /* set child's siginfo structure */ - #ifdef __KERNEL__ /* XXX should we use iaoq[1] or iaoq[0] ? */ diff --git a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h index cc29ceac7744..5ab02aef6dea 100644 --- a/include/asm-parisc/signal.h +++ b/include/asm-parisc/signal.h @@ -156,6 +156,8 @@ struct k_sigaction { struct sigaction sa; }; +#define ptrace_signal_deliver(regs, cookie) do { } while (0) + #include <asm/sigcontext.h> #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h index 92118321f0a5..c178b8e5d4b3 100644 --- a/include/asm-ppc/pci.h +++ b/include/asm-ppc/pci.h @@ -273,4 +273,7 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* __PPC_PCI_H */ diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 18d3995bc586..da0dff483ba7 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -469,8 +469,8 @@ #define ICMP SPRN_ICMP /* Instruction TLB Compare Register */ #define IMISS SPRN_IMISS /* Instruction TLB Miss Register */ #define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */ -#define L2CR SPRN_L2CR /* PPC 750 L2 control register */ -#define L3CR SPRN_L3CR /* PPC 7450 L3 Cache control register */ +#define L2CR SPRN_L2CR /* Classic PPC L2 cache control register */ +#define L3CR SPRN_L3CR /* PPC 745x L3 cache control register */ #define LR SPRN_LR #define PVR SPRN_PVR /* Processor Version */ #define RPA SPRN_RPA /* Required Physical Address Register */ @@ -609,7 +609,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); void release_thread(struct task_struct *); /* Prepare to copy thread state - unlazy all lazy status */ -#define prepare_to_copy(tsk) do { } while (0) +extern void prepare_to_copy(struct task_struct *tsk); /* * Create a new kernel thread. diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h index 4385fb4494c5..75cb531ca3e3 100644 --- a/include/asm-ppc64/compat.h +++ b/include/asm-ppc64/compat.h @@ -61,7 +61,18 @@ struct compat_flock { compat_off_t l_start; compat_off_t l_len; compat_pid_t l_pid; - short __unused; +}; + +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + +struct compat_flock64 { + short l_type; + short l_whence; + compat_loff_t l_start; + compat_loff_t l_len; + compat_pid_t l_pid; }; struct compat_statfs { @@ -84,4 +95,7 @@ typedef u32 compat_old_sigset_t; typedef u32 compat_sigset_word; +#define COMPAT_OFF_T_MAX 0x7fffffff +#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL + #endif /* _ASM_PPC64_COMPAT_H */ diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h index d792a1868af5..6913dc50e904 100644 --- a/include/asm-ppc64/elf.h +++ b/include/asm-ppc64/elf.h @@ -84,9 +84,10 @@ ppc64_elf_core_copy_regs(elf_gregset_t dstRegs, struct pt_regs* srcRegs) #define ELF_PLATFORM (NULL) -#define ELF_PLAT_INIT(_r) do { \ +#define ELF_PLAT_INIT(_r, load_addr) do { \ memset(_r->gpr, 0, sizeof(_r->gpr)); \ _r->ctr = _r->link = _r->xer = _r->ccr = 0; \ + _r->gpr[2] = load_addr; \ } while (0) #ifdef __KERNEL__ diff --git a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h index 19ba4d6dc63c..1ef83570b4e4 100644 --- a/include/asm-ppc64/fcntl.h +++ b/include/asm-ppc64/fcntl.h @@ -42,10 +42,6 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ -#define F_GETLK64 12 /* using 'struct flock64' */ -#define F_SETLK64 13 -#define F_SETLKW64 14 - /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -87,13 +83,6 @@ struct flock { pid_t l_pid; }; -struct flock64 { - short l_type; - short l_whence; - loff_t l_start; - loff_t l_len; - pid_t l_pid; -}; - #define F_LINUX_SPECIFIC_BASE 1024 + #endif /* _PPC64_FCNTL_H */ diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h index c3bdfe012ee3..9061702b8c8e 100644 --- a/include/asm-ppc64/pci-bridge.h +++ b/include/asm-ppc64/pci-bridge.h @@ -20,7 +20,8 @@ enum phb_types { phb_type_unknown = 0x0, phb_type_hypervisor = 0x1, phb_type_python = 0x10, - phb_type_speedwagon = 0x11 + phb_type_speedwagon = 0x11, + phb_type_winnipeg = 0x12 }; /* diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h index 0b715895f043..2cab41c41cca 100644 --- a/include/asm-ppc64/pci.h +++ b/include/asm-ppc64/pci.h @@ -124,4 +124,7 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* __PPC64_PCI_H */ diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h index ecc6cab2895e..0e3f3aece9eb 100644 --- a/include/asm-ppc64/topology.h +++ b/include/asm-ppc64/topology.h @@ -1,6 +1,7 @@ #ifndef _ASM_PPC64_TOPOLOGY_H #define _ASM_PPC64_TOPOLOGY_H +#include <linux/config.h> #include <asm/mmzone.h> #ifdef CONFIG_NUMA diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h index 0be5cfd90ca2..1b2f79a69afa 100644 --- a/include/asm-s390/elf.h +++ b/include/asm-s390/elf.h @@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t; /* For SVR4/S390 the function pointer to be registered with `atexit` is passed in R14. */ -#define ELF_PLAT_INIT(_r) \ +#define ELF_PLAT_INIT(_r, load_addr) \ _r->gprs[14] = 0 #define USE_ELF_CORE_DUMP diff --git a/include/asm-s390x/elf.h b/include/asm-s390x/elf.h index df7559584881..719d0afdc21d 100644 --- a/include/asm-s390x/elf.h +++ b/include/asm-s390x/elf.h @@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t; /* For SVR4/S390 the function pointer to be registered with `atexit` is passed in R14. */ -#define ELF_PLAT_INIT(_r) \ +#define ELF_PLAT_INIT(_r, load_addr) \ do { \ _r->gprs[14] = 0; \ clear_thread_flag(TIF_31BIT); \ diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h index 001cdd8e78ab..a0a579237cb5 100644 --- a/include/asm-sh/elf.h +++ b/include/asm-sh/elf.h @@ -61,7 +61,7 @@ typedef struct user_fpu_struct elf_fpregset_t; #define ELF_PLATFORM (NULL) -#define ELF_PLAT_INIT(_r) \ +#define ELF_PLAT_INIT(_r, load_addr) \ do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \ _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \ _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \ diff --git a/include/asm-sh/pci.h b/include/asm-sh/pci.h index f9690c521d19..60fffd091ad6 100644 --- a/include/asm-sh/pci.h +++ b/include/asm-sh/pci.h @@ -240,6 +240,8 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> #endif /* __ASM_SH_PCI_H */ diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h index 53a010006c41..6b97445a221a 100644 --- a/include/asm-sparc64/pci.h +++ b/include/asm-sparc64/pci.h @@ -207,4 +207,7 @@ extern int pcibios_prep_mwi(struct pci_dev *dev); #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* __SPARC64_PCI_H */ diff --git a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h index bd11a0d536b7..a23261baab5d 100644 --- a/include/asm-um/archparam-i386.h +++ b/include/asm-um/archparam-i386.h @@ -23,7 +23,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; #define ELF_DATA ELFDATA2LSB #define ELF_ARCH EM_386 -#define ELF_PLAT_INIT(regs) do { \ +#define ELF_PLAT_INIT(regs, load_addr) do { \ PT_REGS_EBX(regs) = 0; \ PT_REGS_ECX(regs) = 0; \ PT_REGS_EDX(regs) = 0; \ diff --git a/include/asm-v850/elf.h b/include/asm-v850/elf.h index 0e42ae4ed529..7db8edffb1c6 100644 --- a/include/asm-v850/elf.h +++ b/include/asm-v850/elf.h @@ -81,7 +81,7 @@ typedef struct user_fpu_struct elf_fpregset_t; #define ELF_PLATFORM (NULL) -#define ELF_PLAT_INIT(_r) \ +#define ELF_PLAT_INIT(_r, load_addr) \ do { \ _r->gpr[0] = _r->gpr[1] = _r->gpr[2] = _r->gpr[3] = \ _r->gpr[4] = _r->gpr[5] = _r->gpr[6] = _r->gpr[7] = \ diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h index 7d9d5df88456..cc0690b7073b 100644 --- a/include/asm-x86_64/elf.h +++ b/include/asm-x86_64/elf.h @@ -39,7 +39,7 @@ typedef struct user_i387_struct elf_fpregset_t; We might as well make sure everything else is cleared too (except for %esp), just to make things more deterministic. */ -#define ELF_PLAT_INIT(_r) do { \ +#define ELF_PLAT_INIT(_r, load_addr) do { \ struct task_struct *cur = current; \ (_r)->rbx = 0; (_r)->rcx = 0; (_r)->rdx = 0; \ (_r)->rsi = 0; (_r)->rdi = 0; (_r)->rbp = 0; \ diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index 024a9c045681..74594c63e38c 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -279,4 +279,7 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, #endif /* __KERNEL__ */ +/* generic pci stuff */ +#include <asm-generic/pci.h> + #endif /* __x8664_PCI_H */ diff --git a/include/linux/aio.h b/include/linux/aio.h index c03d92d84e39..6b106ebe99e8 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -37,9 +37,9 @@ struct kioctx; #define kiocbSetKicked(iocb) set_bit(KIF_KICKED, &(iocb)->ki_flags) #define kiocbSetCancelled(iocb) set_bit(KIF_CANCELLED, &(iocb)->ki_flags) -#define kiocbClearLocked(iocb) set_bit(KIF_LOCKED, &(iocb)->ki_flags) -#define kiocbClearKicked(iocb) set_bit(KIF_KICKED, &(iocb)->ki_flags) -#define kiocbClearCancelled(iocb) set_bit(KIF_CANCELLED, &(iocb)->ki_flags) +#define kiocbClearLocked(iocb) clear_bit(KIF_LOCKED, &(iocb)->ki_flags) +#define kiocbClearKicked(iocb) clear_bit(KIF_KICKED, &(iocb)->ki_flags) +#define kiocbClearCancelled(iocb) clear_bit(KIF_CANCELLED, &(iocb)->ki_flags) #define kiocbIsLocked(iocb) test_bit(0, &(iocb)->ki_flags) #define kiocbIsKicked(iocb) test_bit(1, &(iocb)->ki_flags) diff --git a/include/linux/amigaffs.h b/include/linux/amigaffs.h index bde160f417fd..6fb6bb5c6696 100644 --- a/include/linux/amigaffs.h +++ b/include/linux/amigaffs.h @@ -73,7 +73,7 @@ static inline void affs_brelse(struct buffer_head *bh) { if (bh) - pr_debug("affs_brelse: %ld\n", bh->b_blocknr); + pr_debug("affs_brelse: %lld\n", (long long) bh->b_blocknr); brelse(bh); } diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 55218964e7ef..94c93c9c5f66 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -17,8 +17,6 @@ enum bdi_state { BDI_pdflush, /* A pdflush thread is working this device */ BDI_write_congested, /* The write queue is getting full */ BDI_read_congested, /* The read queue is getting full */ - BDI_write_active, /* There are one or more queued writes */ - BDI_read_active, /* There are one or more queued reads */ BDI_unused, /* Available bits start here */ }; @@ -44,14 +42,4 @@ static inline int bdi_write_congested(struct backing_dev_info *bdi) return test_bit(BDI_write_congested, &bdi->state); } -static inline int bdi_read_active(struct backing_dev_info *bdi) -{ - return test_bit(BDI_read_active, &bdi->state); -} - -static inline int bdi_write_active(struct backing_dev_info *bdi) -{ - return test_bit(BDI_write_active, &bdi->state); -} - #endif /* _LINUX_BACKING_DEV_H */ diff --git a/include/linux/bio.h b/include/linux/bio.h index ca324808509f..4eb82c8b33fb 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -239,7 +239,6 @@ extern inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags) * balancing is a lot nicer this way */ local_save_flags(*flags); - local_irq_disable(); addr = (unsigned long) kmap_atomic(bio_page(bio), KM_BIO_SRC_IRQ); if (addr & ~PAGE_MASK) diff --git a/include/linux/device.h b/include/linux/device.h index e27039ec2222..908d6b708fb7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -366,6 +366,7 @@ extern int platform_device_register(struct platform_device *); extern void platform_device_unregister(struct platform_device *); extern struct bus_type platform_bus_type; +extern struct device legacy_bus; /* drivers/base/power.c */ extern int device_suspend(u32 state, u32 level); diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 0612ce8e8274..b3da32479e13 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -730,6 +730,7 @@ extern void ext3_discard_prealloc (struct inode *); extern void ext3_dirty_inode(struct inode *); extern int ext3_change_inode_journal_flag(struct inode *, int); extern void ext3_truncate (struct inode *); +extern void ext3_set_inode_flags(struct inode *); /* ioctl.c */ extern int ext3_ioctl (struct inode *, struct file *, unsigned int, diff --git a/include/linux/file.h b/include/linux/file.h index e5c90a88ba71..0bfe318d873b 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -40,6 +40,9 @@ extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag)); extern void put_filp(struct file *); extern int get_unused_fd(void); extern void FASTCALL(put_unused_fd(unsigned int fd)); +struct kmem_cache_s; +extern void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags); +extern void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags); extern struct file ** alloc_fd_array(int); extern int expand_fd_array(struct files_struct *, int nr); diff --git a/include/linux/fs.h b/include/linux/fs.h index 14bd953f6a64..d6741ac40fb4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -456,7 +456,10 @@ extern spinlock_t files_lock; #define get_file(x) atomic_inc(&(x)->f_count) #define file_count(x) atomic_read(&(x)->f_count) -extern int init_private_file(struct file *, struct dentry *, int); +/* Initialize and open a private file and allocate its security structure. */ +extern int open_private_file(struct file *, struct dentry *, int); +/* Release a private file and free its security structure. */ +extern void close_private_file(struct file *file); #define MAX_NON_LFS ((1UL<<31) - 1) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 0b293a405341..a8f482b94ba4 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -34,6 +34,7 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/i2c-id.h> +#include <linux/device.h> /* for struct device */ #include <asm/semaphore.h> /* --- General options ------------------------------------------------ */ @@ -144,6 +145,8 @@ struct i2c_driver { int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); }; +extern struct bus_type i2c_bus_type; + /* * i2c_client identifies a single device (i.e. chip) that is connected to an * i2c bus. The behaviour is defined by the routines of the driver. This @@ -228,12 +231,14 @@ struct i2c_adapter { int timeout; int retries; + struct device dev; /* the adapter device */ #ifdef CONFIG_PROC_FS /* No need to set this when you initialize the adapter */ int inode; #endif /* def CONFIG_PROC_FS */ }; +#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) /*flags for the driver struct: */ #define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */ diff --git a/include/linux/list.h b/include/linux/list.h index 3cd4d3bd1ebb..f082a59aa3c8 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -5,7 +5,6 @@ #include <linux/stddef.h> #include <linux/prefetch.h> -#include <linux/stddef.h> #include <asm/system.h> /* diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 864e3b801f0f..48860ac34dae 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -35,12 +35,13 @@ #define NFSEXP_UIDMAP 0x0040 #define NFSEXP_KERBEROS 0x0080 /* not available */ #define NFSEXP_SUNSECURE 0x0100 -#define NFSEXP_CROSSMNT 0x0200 +#define NFSEXP_NOHIDE 0x0200 #define NFSEXP_NOSUBTREECHECK 0x0400 #define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */ #define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect */ #define NFSEXP_FSID 0x2000 -#define NFSEXP_ALLFLAGS 0x3FFF +#define NFSEXP_CROSSMNT 0x4000 +#define NFSEXP_ALLFLAGS 0x7FFF #ifdef __KERNEL__ @@ -73,7 +74,7 @@ struct svc_expkey { #define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) #define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY) -#define EX_CROSSMNT(exp) ((exp)->ex_flags & NFSEXP_CROSSMNT) +#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE) #define EX_SUNSECURE(exp) ((exp)->ex_flags & NFSEXP_SUNSECURE) #define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES) diff --git a/include/linux/pci.h b/include/linux/pci.h index 393417af2f89..f87c44ae0689 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -485,11 +485,9 @@ struct pci_ops { int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); }; -struct pbus_set_ranges_data -{ - unsigned long io_start, io_end; - unsigned long mem_start, mem_end; - unsigned long prefetch_start, prefetch_end; +struct pci_bus_region { + unsigned long start; + unsigned long end; }; struct pci_driver { @@ -531,10 +529,7 @@ char *pcibios_setup (char *str); /* Used only when drivers/pci/setup.c is used */ void pcibios_align_resource(void *, struct resource *, unsigned long, unsigned long); -void pcibios_update_resource(struct pci_dev *, struct resource *, - struct resource *, int); void pcibios_update_irq(struct pci_dev *, int irq); -void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *); /* Generic PCI functions used internally */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index e2e9b9f1c2c9..ba94052020f0 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1235,6 +1235,7 @@ #define PCI_VENDOR_ID_XIRCOM 0x115d #define PCI_DEVICE_ID_XIRCOM_X3201_ETH 0x0003 +#define PCI_DEVICE_ID_XIRCOM_RBM56G 0x0101 #define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103 #define PCI_VENDOR_ID_RENDITION 0x1163 diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index d7834b08cc88..3d4faa9f7171 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -27,6 +27,7 @@ #include <linux/module.h> #include <linux/hdreg.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/smp_lock.h> #include <linux/delay.h> #include <net/checksum.h> @@ -68,13 +69,14 @@ extern inline char * bdev_partition_name (struct block_device *bdev) } extern int register_md_personality (int p_num, mdk_personality_t *p); extern int unregister_md_personality (int p_num); -extern mdk_thread_t * md_register_thread (void (*run) (void *data), - void *data, const char *name); +extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev), + mddev_t *mddev, const char *name); extern void md_unregister_thread (mdk_thread_t *thread); extern void md_wakeup_thread(mdk_thread_t *thread); +extern void md_check_recovery(mddev_t *mddev); extern void md_interrupt_thread (mdk_thread_t *thread); extern void md_write_start(mddev_t *mddev); -extern void md_write_end(mddev_t *mddev, mdk_thread_t *thread); +extern void md_write_end(mddev_t *mddev); extern void md_handle_safemode(mddev_t *mddev); extern void md_done_sync(mddev_t *mddev, int blocks, int ok); extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors); diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 6426a2c3fe8f..02bdf9db2ae2 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -155,6 +155,7 @@ struct mdk_rdev_s struct page *sb_page; int sb_loaded; + sector_t data_offset; /* start of data in array */ sector_t sb_offset; int preferred_minor; /* autorun support */ @@ -206,22 +207,31 @@ struct mddev_s char uuid[16]; + struct mdk_thread_s *thread; /* management thread */ struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */ unsigned long curr_resync; /* blocks scheduled */ unsigned long resync_mark; /* a recent timestamp */ unsigned long resync_mark_cnt;/* blocks written at resync_mark */ - /* recovery_running is 0 for no recovery/resync, - * 1 for active recovery - * 2 for active resync - * -error for an error (e.g. -EINTR) - * it can only be set > 0 under reconfig_sem + + /* recovery/resync flags + * NEEDED: we might need to start a resync/recover + * RUNNING: a thread is running, or about to be started + * SYNC: actually doing a resync, not a recovery + * ERR: and IO error was detected - abort the resync/recovery + * INTR: someone requested a (clean) early abort. + * DONE: thread is done and is waiting to be reaped */ - int recovery_running; - int recovery_error; /* error from recovery write */ +#define MD_RECOVERY_RUNNING 0 +#define MD_RECOVERY_SYNC 1 +#define MD_RECOVERY_ERR 2 +#define MD_RECOVERY_INTR 3 +#define MD_RECOVERY_DONE 4 +#define MD_RECOVERY_NEEDED 5 + unsigned long recovery; + int in_sync; /* know to not need resync */ struct semaphore reconfig_sem; atomic_t active; - int spares; int degraded; /* whether md should consider * adding a spare @@ -230,9 +240,11 @@ struct mddev_s atomic_t recovery_active; /* blocks scheduled, but not written */ wait_queue_head_t recovery_wait; sector_t recovery_cp; - int safemode; /* if set, update "clean" superblock + unsigned int safemode; /* if set, update "clean" superblock * when no writes pending. */ + unsigned int safemode_delay; + struct timer_list safemode_timer; atomic_t writes_pending; request_queue_t queue; /* for plugging ... */ @@ -245,7 +257,7 @@ struct mdk_personality_s int (*make_request)(request_queue_t *q, struct bio *bio); int (*run)(mddev_t *mddev); int (*stop)(mddev_t *mddev); - int (*status)(char *page, mddev_t *mddev); + void (*status)(struct seq_file *seq, mddev_t *mddev); /* error_handler must set ->faulty and clear ->in_sync * if appropriate, and should abort recovery if needed */ @@ -292,8 +304,8 @@ extern mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr); ITERATE_RDEV_GENERIC(pending_raid_disks,rdev,tmp) typedef struct mdk_thread_s { - void (*run) (void *data); - void *data; + void (*run) (mddev_t *mddev); + mddev_t *mddev; wait_queue_head_t wqueue; unsigned long flags; struct completion *event; diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index cb002ba3556f..022b607bf9d8 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h @@ -173,5 +173,58 @@ static inline __u64 md_event(mdp_super_t *sb) { return (ev<<32)| sb->events_lo; } +/* + * The version-1 superblock : + * All numeric fields are little-endian. + * + * total size: 256 bytes plus 2 per device. + * 1K allows 384 devices. + */ +struct mdp_superblock_1 { + /* constant array information - 128 bytes */ + __u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ + __u32 major_version; /* 1 */ + __u32 feature_map; /* 0 for now */ + __u32 pad0; /* always set to 0 when writing */ + + __u8 set_uuid[16]; /* user-space generated. */ + char set_name[32]; /* set and interpreted by user-space */ + + __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ + __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ + __u32 layout; /* only for raid5 currently */ + __u64 size; /* used size of component devices, in 512byte sectors */ + + __u32 chunksize; /* in 512byte sectors */ + __u32 raid_disks; + __u8 pad1[128-92]; /* set to 0 when written */ + + /* constant this-device information - 64 bytes */ + __u64 data_offset; /* sector start of data, often 0 */ + __u64 data_size; /* sectors in this device that can be used for data */ + __u64 super_offset; /* sector start of this superblock */ + __u64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */ + __u32 dev_number; /* permanent identifier of this device - not role in raid */ + __u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */ + __u8 device_uuid[16]; /* user-space setable, ignored by kernel */ + __u8 pad2[64-56]; /* set to 0 when writing */ + + /* array state information - 64 bytes */ + __u64 utime; /* 40 bits second, 24 btes microseconds */ + __u64 events; /* incremented when superblock updated */ + __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ + __u32 sb_csum; /* checksum upto devs[max_dev] */ + __u32 max_dev; /* size of devs[] array to consider */ + __u8 pad3[64-40]; /* set to 0 when writing */ + + /* device state information. Indexed by dev_number. + * 2 bytes per device + * Note there are no per-device state flags. State information is rolled + * into the 'roles' value. If a device is spare or faulty, then it doesn't + * have a meaningful role. + */ + __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ +}; + #endif diff --git a/include/linux/raid/multipath.h b/include/linux/raid/multipath.h index 50db7f3c8c57..42d040ea63df 100644 --- a/include/linux/raid/multipath.h +++ b/include/linux/raid/multipath.h @@ -13,7 +13,6 @@ struct multipath_private_data { struct multipath_info multipaths[MD_SB_DISKS]; int raid_disks; int working_disks; - mdk_thread_t *thread; spinlock_t device_lock; mempool_t *pool; diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index 9ed30f4d0748..cc7aa899a613 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h @@ -19,7 +19,6 @@ struct r1_private_data_s { int working_disks; int last_used; sector_t next_seq_sect; - mdk_thread_t *thread; spinlock_t device_lock; /* for use when syncing mirrors: */ @@ -34,7 +33,6 @@ struct r1_private_data_s { mempool_t *r1bio_pool; mempool_t *r1buf_pool; - char thread_name[MD_THREAD_NAME_MAX]; }; typedef struct r1_private_data_s conf_t; diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 636e10b84502..c9eea7c884d0 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -203,7 +203,6 @@ struct disk_info { struct raid5_private_data { struct stripe_head **stripe_hashtbl; mddev_t *mddev; - mdk_thread_t *thread; struct disk_info disks[MD_SB_DISKS]; struct disk_info *spare; int chunk_size, level, algorithm; @@ -226,7 +225,6 @@ struct raid5_private_data { * waiting for 25% to be free */ spinlock_t device_lock; - char thread_name[MD_THREAD_NAME_MAX]; }; typedef struct raid5_private_data raid5_conf_t; diff --git a/include/linux/security.h b/include/linux/security.h index d2873ec35117..6a98cb692bf8 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -48,6 +48,7 @@ extern void cap_bprm_compute_creds (struct linux_binprm *bprm); extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); extern void cap_task_kmod_set_label (void); extern void cap_task_reparent_to_init (struct task_struct *p); +extern int cap_syslog (int type); static inline int cap_netlink_send (struct sk_buff *skb) { @@ -62,7 +63,6 @@ static inline int cap_netlink_recv (struct sk_buff *skb) return 0; } - /* * Values used in the task_security_ops calls */ @@ -351,10 +351,6 @@ struct swap_info_struct; * @mnt is the vfsmount where the dentry was looked up * @dentry contains the dentry structure for the file. * Return 0 if permission is granted. - * @inode_post_lookup: - * Set the security attributes for a file after it has been looked up. - * @inode contains the inode structure for parent directory. - * @d contains the dentry structure for the file. * @inode_delete: * @inode contains the inode structure for deleted inode. * This hook is called when a deleted inode is released (i.e. an inode @@ -926,11 +922,23 @@ struct swap_info_struct; * is NULL. * @file contains the file structure for the accounting file (may be NULL). * Return 0 if permission is granted. + * @sysctl: + * Check permission before accessing the @table sysctl variable in the + * manner specified by @op. + * @table contains the ctl_table structure for the sysctl variable. + * @op contains the operation (001 = search, 002 = write, 004 = read). + * Return 0 if permission is granted. * @capable: * Check whether the @tsk process has the @cap capability. * @tsk contains the task_struct for the process. * @cap contains the capability <include/linux/capability.h>. * Return 0 if the capability is granted for @tsk. + * @syslog: + * Check permission before accessing the kernel message ring or changing + * logging to the console. + * See the syslog(2) manual page for an explanation of the @type values. + * @type contains the type of action. + * Return 0 if permission is granted. * * @register_security: * allow module stacking. @@ -957,9 +965,11 @@ struct security_operations { kernel_cap_t * inheritable, kernel_cap_t * permitted); int (*acct) (struct file * file); + int (*sysctl) (ctl_table * table, int op); int (*capable) (struct task_struct * tsk, int cap); int (*quotactl) (int cmds, int type, int id, struct super_block * sb); int (*quota_on) (struct file * f); + int (*syslog) (int type); int (*bprm_alloc_security) (struct linux_binprm * bprm); void (*bprm_free_security) (struct linux_binprm * bprm); @@ -969,6 +979,7 @@ struct security_operations { int (*sb_alloc_security) (struct super_block * sb); void (*sb_free_security) (struct super_block * sb); + int (*sb_kern_mount) (struct super_block *sb); int (*sb_statfs) (struct super_block * sb); int (*sb_mount) (char *dev_name, struct nameidata * nd, char *type, unsigned long flags, void *data); @@ -1022,7 +1033,6 @@ struct security_operations { int (*inode_permission_lite) (struct inode *inode, int mask); int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); - void (*inode_post_lookup) (struct inode *inode, struct dentry *d); void (*inode_delete) (struct inode *inode); int (*inode_setxattr) (struct dentry *dentry, char *name, void *value, size_t size, int flags); @@ -1111,6 +1121,8 @@ struct security_operations { int (*unregister_security) (const char *name, struct security_operations *ops); + void (*d_instantiate) (struct dentry *dentry, struct inode *inode); + #ifdef CONFIG_SECURITY_NETWORK int (*unix_stream_connect) (struct socket * sock, struct socket * other, struct sock * newsk); @@ -1178,6 +1190,11 @@ static inline int security_acct (struct file *file) return security_ops->acct (file); } +static inline int security_sysctl(ctl_table * table, int op) +{ + return security_ops->sysctl(table, op); +} + static inline int security_quotactl (int cmds, int type, int id, struct super_block *sb) { @@ -1189,6 +1206,11 @@ static inline int security_quota_on (struct file * file) return security_ops->quota_on (file); } +static inline int security_syslog(int type) +{ + return security_ops->syslog(type); +} + static inline int security_bprm_alloc (struct linux_binprm *bprm) { return security_ops->bprm_alloc_security (bprm); @@ -1220,6 +1242,11 @@ static inline void security_sb_free (struct super_block *sb) security_ops->sb_free_security (sb); } +static inline int security_sb_kern_mount (struct super_block *sb) +{ + return security_ops->sb_kern_mount (sb); +} + static inline int security_sb_statfs (struct super_block *sb) { return security_ops->sb_statfs (sb); @@ -1426,12 +1453,6 @@ static inline int security_inode_getattr (struct vfsmount *mnt, return security_ops->inode_getattr (mnt, dentry); } -static inline void security_inode_post_lookup (struct inode *inode, - struct dentry *dentry) -{ - security_ops->inode_post_lookup (inode, dentry); -} - static inline void security_inode_delete (struct inode *inode) { security_ops->inode_delete (inode); @@ -1729,6 +1750,11 @@ static inline int security_sem_semop (struct sem_array * sma, return security_ops->sem_semop(sma, sops, nsops, alter); } +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode) +{ + security_ops->d_instantiate (dentry, inode); +} + static inline int security_netlink_send(struct sk_buff * skb) { return security_ops->netlink_send(skb); @@ -1793,6 +1819,11 @@ static inline int security_acct (struct file *file) return 0; } +static inline int security_sysctl(ctl_table * table, int op) +{ + return 0; +} + static inline int security_quotactl (int cmds, int type, int id, struct super_block * sb) { @@ -1804,6 +1835,11 @@ static inline int security_quota_on (struct file * file) return 0; } +static inline int security_syslog(int type) +{ + return cap_syslog(type); +} + static inline int security_bprm_alloc (struct linux_binprm *bprm) { return 0; @@ -1835,6 +1871,11 @@ static inline int security_sb_alloc (struct super_block *sb) static inline void security_sb_free (struct super_block *sb) { } +static inline int security_sb_kern_mount (struct super_block *sb) +{ + return 0; +} + static inline int security_sb_statfs (struct super_block *sb) { return 0; @@ -2013,10 +2054,6 @@ static inline int security_inode_getattr (struct vfsmount *mnt, return 0; } -static inline void security_inode_post_lookup (struct inode *inode, - struct dentry *dentry) -{ } - static inline void security_inode_delete (struct inode *inode) { } @@ -2300,6 +2337,9 @@ static inline int security_sem_semop (struct sem_array * sma, return 0; } +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode) +{ } + /* * The netlink capability defaults need to be used inline by default * (rather than hooking into the capability module) to reduce overhead diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 3412f8b7f2ce..80ba519dda77 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -208,12 +208,11 @@ struct uart_state { #define USF_CLOSING_WAIT_NONE (65535) int count; + int pm_state; struct uart_info *info; struct uart_port *port; -#ifdef CONFIG_PM - struct pm_dev *pm; -#endif + struct semaphore sem; }; #define UART_XMIT_SIZE 1024 @@ -224,8 +223,6 @@ struct uart_state { * stuff here. */ struct uart_info { - struct uart_port *port; - struct uart_state *state; struct tty_struct *tty; struct circ_buf xmit; unsigned int flags; @@ -237,7 +234,6 @@ struct uart_info { */ #define UIF_CHECK_CD (1 << 25) #define UIF_CTS_FLOW (1 << 26) -#define UIF_CLOSING (1 << 27) #define UIF_NORMAL_ACTIVE (1 << 29) #define UIF_INITIALIZED (1 << 31) @@ -307,6 +303,12 @@ int uart_register_port(struct uart_driver *reg, struct uart_port *port); int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port); +/* + * Power Management + */ +int uart_suspend_port(struct uart_driver *reg, struct uart_port *port, u32 level); +int uart_resume_port(struct uart_driver *reg, struct uart_port *port, u32 level); + #define uart_circ_empty(circ) ((circ)->head == (circ)->tail) #define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index a3cdc080dd85..1d3bccefe959 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -190,6 +190,7 @@ RTN *FNAME ARGS \ else read_unlock(&(DETAIL)->hash_lock); \ if (set) \ cache_fresh(DETAIL, &tmp->MEMBER, item->MEMBER.expiry_time); \ + if (set==1 && new) cache_fresh(DETAIL, &new->MEMBER, 0); \ if (new) (DETAIL)->cache_put(&new->MEMBER, DETAIL); \ return tmp; \ } \ diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 8bacba8ed989..d252f45a0f9b 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -12,7 +12,7 @@ */ struct restart_block { long (*fn)(struct restart_block *); - unsigned long arg0, arg1, arg2; + unsigned long arg0, arg1, arg2, arg3; }; extern long do_no_restart_syscall(struct restart_block *parm); diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 620f18f5ceeb..f316169bb1f7 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -79,6 +79,7 @@ extern int dirty_writeback_centisecs; extern int dirty_expire_centisecs; +void page_writeback_init(void); void balance_dirty_pages(struct address_space *mapping); void balance_dirty_pages_ratelimited(struct address_space *mapping); int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); diff --git a/drivers/media/video/audiochip.h b/include/media/audiochip.h index b161f921d303..e5a5cd2bb172 100644 --- a/drivers/media/video/audiochip.h +++ b/include/media/audiochip.h @@ -3,9 +3,6 @@ /* ---------------------------------------------------------------------- */ -#define MIN(a,b) (((a)>(b))?(b):(a)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - /* v4l device was opened in Radio mode */ #define AUDC_SET_RADIO _IO('m',2) /* select from TV,radio,extern,MUTE */ @@ -21,15 +18,6 @@ #define AUDIO_MUTE 0x80 #define AUDIO_UNMUTE 0x81 -/* all the stuff below is obsolete and just here for reference. I'll - * remove it once the driver is tested and works fine. - * - * Instead creating alot of tiny API's for all kinds of different - * chips, we'll just pass throuth the v4l ioctl structs (v4l2 not - * yet...). It is a bit less flexible, but most/all used i2c chips - * make sense in v4l context only. So I think that's acceptable... - */ - /* misc stuff to pass around config info to i2c chips */ #define AUDC_CONFIG_PINNACLE _IOW('m',32,int) diff --git a/drivers/media/video/id.h b/include/media/id.h index f9360b0665bb..f9360b0665bb 100644 --- a/drivers/media/video/id.h +++ b/include/media/id.h diff --git a/drivers/media/video/tuner.h b/include/media/tuner.h index f716e23dda8e..f716e23dda8e 100644 --- a/drivers/media/video/tuner.h +++ b/include/media/tuner.h diff --git a/drivers/media/video/video-buf.h b/include/media/video-buf.h index fceea3e24f75..fceea3e24f75 100644 --- a/drivers/media/video/video-buf.h +++ b/include/media/video-buf.h diff --git a/init/Makefile b/init/Makefile index 8d501dd326ea..eccdb205754d 100644 --- a/init/Makefile +++ b/init/Makefile @@ -21,5 +21,5 @@ $(obj)/version.o: include/linux/compile.h # actual file if its content has changed. include/linux/compile.h: FORCE - @echo -n ' GEN $@' + @echo ' CHK $@' @sh $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)" diff --git a/init/main.c b/init/main.c index f885a1f785a6..c6367147fe29 100644 --- a/init/main.c +++ b/init/main.c @@ -35,10 +35,21 @@ #include <linux/profile.h> #include <linux/rcupdate.h> #include <linux/moduleparam.h> +#include <linux/writeback.h> #include <asm/io.h> #include <asm/bugs.h> +/* + * This is one of the first .c files built. Error out early + * if we have compiler trouble.. + */ +#if __GNUC__ == 2 && __GNUC_MINOR__ == 96 +#ifdef CONFIG_FRAME_POINTER +#error This compiler cannot compile correctly with frame pointers enabled +#endif +#endif + #ifdef CONFIG_X86_LOCAL_APIC #include <asm/smp.h> #endif @@ -429,6 +440,8 @@ asmlinkage void __init start_kernel(void) vfs_caches_init(num_physpages); radix_tree_init(); signals_init(); + /* rootfs populating might need page-writeback */ + page_writeback_init(); populate_rootfs(); #ifdef CONFIG_PROC_FS proc_root_init(); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 3e9ffd1891ef..fc6ff398cbc4 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -177,7 +177,8 @@ EXPORT_SYMBOL(mark_buffer_dirty); EXPORT_SYMBOL(end_buffer_io_sync); EXPORT_SYMBOL(__mark_inode_dirty); EXPORT_SYMBOL(get_empty_filp); -EXPORT_SYMBOL(init_private_file); +EXPORT_SYMBOL(open_private_file); +EXPORT_SYMBOL(close_private_file); EXPORT_SYMBOL(filp_open); EXPORT_SYMBOL(filp_close); EXPORT_SYMBOL(put_filp); diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 19e2aa5dcb41..3780d17e49b0 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -9,7 +9,6 @@ /* These are all the functions necessary to implement * POSIX clocks & timers */ - #include <linux/mm.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> @@ -23,6 +22,7 @@ #include <linux/compiler.h> #include <linux/idr.h> #include <linux/posix-timers.h> +#include <linux/wait.h> #ifndef div_long_long_rem #include <asm/div64.h> @@ -56,8 +56,8 @@ * Lets keep our timers in a slab cache :-) */ static kmem_cache_t *posix_timers_cache; -struct idr posix_timers_id; -spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; +static struct idr posix_timers_id; +static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; /* * Just because the timer is not in the timer list does NOT mean it is @@ -130,7 +130,7 @@ spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; * which we beg off on and pass to do_sys_settimeofday(). */ -struct k_clock posix_clocks[MAX_CLOCKS]; +static struct k_clock posix_clocks[MAX_CLOCKS]; #define if_clock_do(clock_fun, alt_fun,parms) (! clock_fun)? alt_fun parms :\ clock_fun parms @@ -183,7 +183,7 @@ init_posix_timers(void) __initcall(init_posix_timers); static inline int -tstojiffie(struct timespec *tp, int res, unsigned long *jiff) +tstojiffie(struct timespec *tp, int res, u64 *jiff) { unsigned long sec = tp->tv_sec; long nsec = tp->tv_nsec + res - 1; @@ -203,7 +203,7 @@ tstojiffie(struct timespec *tp, int res, unsigned long *jiff) * below. Here it is enough to just discard the high order * bits. */ - *jiff = HZ * sec; + *jiff = (u64)sec * HZ; /* * Do the res thing. (Don't forget the add in the declaration of nsec) */ @@ -221,9 +221,12 @@ tstojiffie(struct timespec *tp, int res, unsigned long *jiff) static void tstotimer(struct itimerspec *time, struct k_itimer *timer) { + u64 result; int res = posix_clocks[timer->it_clock].res; - tstojiffie(&time->it_value, res, &timer->it_timer.expires); - tstojiffie(&time->it_interval, res, &timer->it_incr); + tstojiffie(&time->it_value, res, &result); + timer->it_timer.expires = (unsigned long)result; + tstojiffie(&time->it_interval, res, &result); + timer->it_incr = (unsigned long)result; } static void @@ -1020,6 +1023,9 @@ do_posix_gettime(struct k_clock *clock, struct timespec *tp) * Note also that the while loop assures that the sub_jiff_offset * will be less than a jiffie, thus no need to normalize the result. * Well, not really, if called with ints off :( + + * HELP, this code should make an attempt at resolution beyond the + * jiffie. Trouble is this is "arch" dependent... */ int @@ -1127,26 +1133,14 @@ nanosleep_wake_up(unsigned long __data) * holds (or has held for it) a write_lock_irq( xtime_lock) and is * called from the timer bh code. Thus we need the irq save locks. */ -spinlock_t nanosleep_abs_list_lock = SPIN_LOCK_UNLOCKED; -struct list_head nanosleep_abs_list = LIST_HEAD_INIT(nanosleep_abs_list); +static DECLARE_WAIT_QUEUE_HEAD(nanosleep_abs_wqueue); -struct abs_struct { - struct list_head list; - struct task_struct *t; -}; void clock_was_set(void) { - struct list_head *pos; - unsigned long flags; - - spin_lock_irqsave(&nanosleep_abs_list_lock, flags); - list_for_each(pos, &nanosleep_abs_list) { - wake_up_process(list_entry(pos, struct abs_struct, list)->t); - } - spin_unlock_irqrestore(&nanosleep_abs_list_lock, flags); + wake_up_all(&nanosleep_abs_wqueue); } long clock_nanosleep_restart(struct restart_block *restart_block); @@ -1201,19 +1195,19 @@ sys_clock_nanosleep(clockid_t which_clock, int flags, return ret; } - long do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) { struct timespec t; struct timer_list new_timer; - struct abs_struct abs_struct = { .list = { .next = 0 } }; + DECLARE_WAITQUEUE(abs_wqueue, current); + u64 rq_time = 0; + s64 left; int abs; - int rtn = 0; - int active; struct restart_block *restart_block = ¤t_thread_info()->restart_block; + abs_wqueue.flags = 0; init_timer(&new_timer); new_timer.expires = 0; new_timer.data = (unsigned long) current; @@ -1226,54 +1220,50 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) * time and continue. */ restart_block->fn = do_no_restart_syscall; - if (!restart_block->arg2) - return -EINTR; - new_timer.expires = restart_block->arg2; - if (time_before(new_timer.expires, jiffies)) + rq_time = restart_block->arg3; + rq_time = (rq_time << 32) + restart_block->arg2; + if (!rq_time) + return -EINTR; + if (rq_time <= get_jiffies_64()) return 0; } if (abs && (posix_clocks[which_clock].clock_get != posix_clocks[CLOCK_MONOTONIC].clock_get)) { - spin_lock_irq(&nanosleep_abs_list_lock); - list_add(&abs_struct.list, &nanosleep_abs_list); - abs_struct.t = current; - spin_unlock_irq(&nanosleep_abs_list_lock); + add_wait_queue(&nanosleep_abs_wqueue, &abs_wqueue); } do { t = *tsave; - if ((abs || !new_timer.expires) && - !(rtn = adjust_abs_time(&posix_clocks[which_clock], - &t, abs))) { - /* - * On error, we don't set up the timer so - * we don't arm the timer so - * del_timer_sync() will return 0, thus - * active is zero... and so it goes. - */ + if (abs || !rq_time){ + adjust_abs_time(&posix_clocks[which_clock], &t, abs); - tstojiffie(&t, - posix_clocks[which_clock].res, - &new_timer.expires); + tstojiffie(&t, posix_clocks[which_clock].res, &rq_time); } - if (new_timer.expires) { - current->state = TASK_INTERRUPTIBLE; - add_timer(&new_timer); - - schedule(); +#if (BITS_PER_LONG < 64) + if ((rq_time - get_jiffies_64()) > MAX_JIFFY_OFFSET){ + new_timer.expires = MAX_JIFFY_OFFSET; + }else +#endif + { + new_timer.expires = (long)rq_time; } - } - while ((active = del_timer_sync(&new_timer)) && - !test_thread_flag(TIF_SIGPENDING)); + current->state = TASK_INTERRUPTIBLE; + add_timer(&new_timer); + + schedule(); - if (abs_struct.list.next) { - spin_lock_irq(&nanosleep_abs_list_lock); - list_del(&abs_struct.list); - spin_unlock_irq(&nanosleep_abs_list_lock); + del_timer_sync(&new_timer); + left = rq_time - get_jiffies_64(); } - if (active) { - long jiffies_left; + while ( (left > 0) && + !test_thread_flag(TIF_SIGPENDING)); + + if( abs_wqueue.task_list.next) + finish_wait(&nanosleep_abs_wqueue, &abs_wqueue); + + if (left > 0) { + unsigned long rmd; /* * Always restart abs calls from scratch to pick up any @@ -1282,29 +1272,19 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) if (abs) return -ERESTARTNOHAND; - jiffies_left = new_timer.expires - jiffies; - - if (jiffies_left < 0) - return 0; - - jiffies_to_timespec(jiffies_left, tsave); + tsave->tv_sec = div_long_long_rem(left, HZ, &rmd); + tsave->tv_nsec = rmd * (NSEC_PER_SEC / HZ); - while (tsave->tv_nsec < 0) { - tsave->tv_nsec += NSEC_PER_SEC; - tsave->tv_sec--; - } - if (tsave->tv_sec < 0) { - tsave->tv_sec = 0; - tsave->tv_nsec = 1; - } restart_block->fn = clock_nanosleep_restart; restart_block->arg0 = which_clock; restart_block->arg1 = (unsigned long)tsave; - restart_block->arg2 = new_timer.expires; + restart_block->arg2 = rq_time & 0xffffffffLL; + restart_block->arg3 = rq_time >> 32; + return -ERESTART_RESTARTBLOCK; } - return rtn; + return 0; } /* * This will restart either clock_nanosleep or clock_nanosleep diff --git a/kernel/printk.c b/kernel/printk.c index 9f2eb4b45669..853ac68708ae 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -28,6 +28,7 @@ #include <linux/config.h> #include <linux/delay.h> #include <linux/smp.h> +#include <linux/security.h> #include <asm/uaccess.h> @@ -161,6 +162,10 @@ int do_syslog(int type, char * buf, int len) char c; int error = 0; + error = security_syslog(type); + if (error) + return error; + switch (type) { case 0: /* Close log */ break; @@ -273,8 +278,6 @@ out: asmlinkage long sys_syslog(int type, char * buf, int len) { - if ((type != 3) && !capable(CAP_SYS_ADMIN)) - return -EPERM; return do_syslog(type, buf, len); } diff --git a/kernel/sched.c b/kernel/sched.c index a399056e6ac2..caeca9ec9c21 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -342,10 +342,10 @@ static inline void __activate_task(task_t *p, runqueue_t *rq) */ static inline int activate_task(task_t *p, runqueue_t *rq) { - unsigned long sleep_time = jiffies - p->last_run; + long sleep_time = jiffies - p->last_run - 1; int requeue_waker = 0; - if (sleep_time) { + if (sleep_time > 0) { int sleep_avg; /* @@ -846,7 +846,7 @@ void sched_balance_exec(void) } /* - * Find the busiest node. All previous node loads contribute with a + * Find the busiest node. All previous node loads contribute with a * geometrically deccaying weight to the load measure: * load_{t} = load_{t-1}/2 + nr_node_running_{t} * This way sudden load peaks are flattened out a bit. @@ -854,7 +854,7 @@ void sched_balance_exec(void) static int find_busiest_node(int this_node) { int i, node = -1, load, this_load, maxload; - + this_load = maxload = (this_rq()->prev_node_load[this_node] >> 1) + atomic_read(&node_nr_running[this_node]); this_rq()->prev_node_load[this_node] = this_load; @@ -1194,8 +1194,8 @@ void scheduler_tick(int user_ticks, int sys_ticks) runqueue_t *rq = this_rq(); task_t *p = current; - if (rcu_pending(cpu)) - rcu_check_callbacks(cpu, user_ticks); + if (rcu_pending(cpu)) + rcu_check_callbacks(cpu, user_ticks); if (p == rq->idle) { /* note: this timer irq context must be accounted for as well */ @@ -1353,7 +1353,7 @@ switch_tasks: if (likely(prev != next)) { rq->nr_switches++; rq->curr = next; - + prepare_arch_switch(rq, next); prev = context_switch(rq, prev, next); barrier(); @@ -1483,7 +1483,7 @@ void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) } #endif - + void complete(struct completion *x) { unsigned long flags; @@ -1567,7 +1567,7 @@ long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) void sleep_on(wait_queue_head_t *q) { SLEEP_ON_VAR - + current->state = TASK_UNINTERRUPTIBLE; SLEEP_ON_HEAD @@ -1578,7 +1578,7 @@ void sleep_on(wait_queue_head_t *q) long sleep_on_timeout(wait_queue_head_t *q, long timeout) { SLEEP_ON_VAR - + current->state = TASK_UNINTERRUPTIBLE; SLEEP_ON_HEAD @@ -2472,12 +2472,12 @@ spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; static void kstat_init_cpu(int cpu) { - /* Add any initialisation to kstat here */ - /* Useful when cpu offlining logic is added.. */ + /* Add any initialisation to kstat here */ + /* Useful when cpu offlining logic is added.. */ } static int __devinit kstat_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) + unsigned long action, void *hcpu) { int cpu = (unsigned long)hcpu; switch(action) { @@ -2489,7 +2489,7 @@ static int __devinit kstat_cpu_notify(struct notifier_block *self, } return NOTIFY_OK; } - + static struct notifier_block __devinitdata kstat_nb = { .notifier_call = kstat_cpu_notify, .next = NULL, @@ -2498,7 +2498,7 @@ static struct notifier_block __devinitdata kstat_nb = { __init static void init_kstat(void) { kstat_cpu_notify(&kstat_nb, (unsigned long)CPU_UP_PREPARE, (void *)(long)smp_processor_id()); - register_cpu_notifier(&kstat_nb); + register_cpu_notifier(&kstat_nb); } void __init sched_init(void) @@ -2538,7 +2538,6 @@ void __init sched_init(void) rq->idle = current; set_task_cpu(current, smp_processor_id()); wake_up_forked_process(current); - current->prio = MAX_PRIO; init_timers(); diff --git a/kernel/signal.c b/kernel/signal.c index 49e483f8451e..7f630c0261e0 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1460,6 +1460,45 @@ do_signal_stop(int signr) #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER +/* + * Do appropriate magic when group_stop_count > 0. + * We return nonzero if we stopped, after releasing the siglock. + * We return zero if we still hold the siglock and should look + * for another signal without checking group_stop_count again. + */ +static inline int handle_group_stop(void) +{ + int stop_count; + + if (current->signal->group_exit_task == current) { + /* + * Group stop is so we can do a core dump, + * We are the initiating thread, so get on with it. + */ + current->signal->group_exit_task = NULL; + return 0; + } + + if (current->signal->group_exit) + /* + * Group stop is so another thread can do a core dump, + * or else we are racing against a death signal. + * Just punt the stop so we can get the next signal. + */ + return 0; + + /* + * There is a group stop in progress. We stop + * without any associated signal being in our queue. + */ + stop_count = --current->signal->group_stop_count; + current->exit_code = current->signal->group_exit_code; + set_current_state(TASK_STOPPED); + spin_unlock_irq(¤t->sighand->siglock); + finish_stop(stop_count); + return 1; +} + int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie) { sigset_t *mask = ¤t->blocked; @@ -1469,28 +1508,9 @@ int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie) struct k_sigaction *ka; spin_lock_irq(¤t->sighand->siglock); - if (unlikely(current->signal->group_stop_count > 0)) { - int stop_count; - if (current->signal->group_exit_task == current) { - /* - * Group stop is so we can do a core dump. - */ - current->signal->group_exit_task = NULL; - goto dequeue; - } - /* - * There is a group stop in progress. We stop - * without any associated signal being in our queue. - */ - stop_count = --current->signal->group_stop_count; - signr = current->signal->group_exit_code; - current->exit_code = signr; - set_current_state(TASK_STOPPED); - spin_unlock_irq(¤t->sighand->siglock); - finish_stop(stop_count); + if (unlikely(current->signal->group_stop_count > 0) && + handle_group_stop()) continue; - } - dequeue: signr = dequeue_signal(current, mask, info); spin_unlock_irq(¤t->sighand->siglock); diff --git a/kernel/sys.c b/kernel/sys.c index 8e3fb524d641..21c75eaf033e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -212,18 +212,25 @@ cond_syscall(sys_delete_module) static int set_one_prio(struct task_struct *p, int niceval, int error) { + int no_nice; + if (p->uid != current->euid && p->uid != current->uid && !capable(CAP_SYS_NICE)) { error = -EPERM; goto out; } - + if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) { + error = -EACCES; + goto out; + } + no_nice = security_task_setnice(p, niceval); + if (no_nice) { + error = no_nice; + goto out; + } if (error == -ESRCH) error = 0; - if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) - error = -EACCES; - else - set_user_nice(p, niceval); + set_user_nice(p, niceval); out: return error; } @@ -941,6 +948,10 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) } ok_pgid: + err = security_task_setpgid(p, pgid); + if (err) + goto out; + if (p->pgrp != pgid) { detach_pid(p, PIDTYPE_PGID); p->pgrp = pgid; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c3c96cd208d4..0364833761c4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -33,6 +33,7 @@ #include <linux/highuid.h> #include <linux/writeback.h> #include <linux/hugetlb.h> +#include <linux/security.h> #include <asm/uaccess.h> #ifdef CONFIG_ROOT_NFS @@ -432,6 +433,10 @@ static int test_perm(int mode, int op) static inline int ctl_perm(ctl_table *table, int op) { + int error; + error = security_sysctl(table, op); + if (error) + return error; return test_perm(table->mode, op); } diff --git a/kernel/timer.c b/kernel/timer.c index 6e7e23cb95ba..d3983cbfa8d7 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -53,11 +53,11 @@ typedef struct tvec_root_s { struct list_head vec[TVR_SIZE]; } tvec_root_t; - struct tvec_t_base_s { spinlock_t lock; unsigned long timer_jiffies; struct timer_list *running_timer; + struct list_head *run_timer_list_running; tvec_root_t tv1; tvec_t tv2; tvec_t tv3; @@ -67,6 +67,14 @@ struct tvec_t_base_s { typedef struct tvec_t_base_s tvec_base_t; +static inline void set_running_timer(tvec_base_t *base, + struct timer_list *timer) +{ +#ifdef CONFIG_SMP + base->running_timer = timer; +#endif +} + /* Fake initialization */ static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED }; @@ -94,13 +102,22 @@ static inline void check_timer(struct timer_list *timer) check_timer_failed(timer); } -static inline void internal_add_timer(tvec_base_t *base, struct timer_list *timer) +/* + * If a timer handler re-adds the timer with expires == jiffies, the timer + * running code can lock up. So here we detect that situation and park the + * timer onto base->run_timer_list_running. It will be added to the main timer + * structures later, by __run_timers(). + */ + +static void internal_add_timer(tvec_base_t *base, struct timer_list *timer) { unsigned long expires = timer->expires; unsigned long idx = expires - base->timer_jiffies; struct list_head *vec; - if (idx < TVR_SIZE) { + if (base->run_timer_list_running) { + vec = base->run_timer_list_running; + } else if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = base->tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { @@ -354,7 +371,7 @@ del_again: static int cascade(tvec_base_t *base, tvec_t *tv) { /* cascade all the timers from tv up one level */ - struct list_head *head, *curr, *next; + struct list_head *head, *curr; head = tv->vec + tv->index; curr = head->next; @@ -366,11 +383,9 @@ static int cascade(tvec_base_t *base, tvec_t *tv) struct timer_list *tmp; tmp = list_entry(curr, struct timer_list, entry); - if (tmp->base != base) - BUG(); - next = curr->next; + BUG_ON(tmp->base != base); + curr = curr->next; internal_add_timer(base, tmp); - curr = next; } INIT_LIST_HEAD(head); @@ -386,9 +401,12 @@ static int cascade(tvec_base_t *base, tvec_t *tv) */ static inline void __run_timers(tvec_base_t *base) { + struct timer_list *timer; + spin_lock_irq(&base->lock); - while ((long)(jiffies - base->timer_jiffies) >= 0) { - struct list_head *head, *curr; + while (time_after_eq(jiffies, base->timer_jiffies)) { + LIST_HEAD(deferred_timers); + struct list_head *head; /* * Cascade timers: @@ -398,37 +416,36 @@ static inline void __run_timers(tvec_base_t *base) (cascade(base, &base->tv3) == 1) && cascade(base, &base->tv4) == 1) cascade(base, &base->tv5); + base->run_timer_list_running = &deferred_timers; repeat: head = base->tv1.vec + base->tv1.index; - curr = head->next; - if (curr != head) { + if (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; - struct timer_list *timer; - timer = list_entry(curr, struct timer_list, entry); + timer = list_entry(head->next,struct timer_list,entry); fn = timer->function; data = timer->data; list_del(&timer->entry); timer->base = NULL; -#if CONFIG_SMP - base->running_timer = timer; -#endif + set_running_timer(base, timer); spin_unlock_irq(&base->lock); - if (!fn) - printk("Bad: timer %p has NULL fn. (data: %08lx)\n", timer, data); - else - fn(data); + fn(data); spin_lock_irq(&base->lock); goto repeat; } + base->run_timer_list_running = NULL; ++base->timer_jiffies; base->tv1.index = (base->tv1.index + 1) & TVR_MASK; + while (!list_empty(&deferred_timers)) { + timer = list_entry(deferred_timers.prev, + struct timer_list, entry); + list_del(&timer->entry); + internal_add_timer(base, timer); + } } -#if CONFIG_SMP - base->running_timer = NULL; -#endif + set_running_timer(base, NULL); spin_unlock_irq(&base->lock); } @@ -775,7 +792,7 @@ static void run_timer_softirq(struct softirq_action *h) { tvec_base_t *base = &per_cpu(tvec_bases, smp_processor_id()); - if ((long)(jiffies - base->timer_jiffies) >= 0) + if (time_after_eq(jiffies, base->timer_jiffies)) __run_timers(base); } diff --git a/mm/highmem.c b/mm/highmem.c index 33adcf242697..10fa9f26a548 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -120,7 +120,7 @@ start: { DECLARE_WAITQUEUE(wait, current); - current->state = TASK_UNINTERRUPTIBLE; + __set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&pkmap_map_wait, &wait); spin_unlock(&kmap_lock); schedule(); diff --git a/mm/memory.c b/mm/memory.c index 4dde60116530..3aafcee5e84d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -484,16 +484,6 @@ void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma, #define ZAP_BLOCK_SIZE (~(0UL)) #endif -/* - * hugepage regions must be unmapped with HPAGE_SIZE granularity - */ -static inline unsigned long zap_block_size(struct vm_area_struct *vma) -{ - if (is_vm_hugetlb_page(vma)) - return HPAGE_SIZE; - return ZAP_BLOCK_SIZE; -} - /** * unmap_vmas - unmap a range of memory covered by a list of vma's * @tlbp: address of the caller's struct mmu_gather @@ -524,7 +514,7 @@ int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long start_addr, unsigned long end_addr, unsigned long *nr_accounted) { - unsigned long zap_bytes = zap_block_size(vma); + unsigned long zap_bytes = ZAP_BLOCK_SIZE; unsigned long tlb_start; /* For tlb_finish_mmu */ int tlb_start_valid = 0; int ret = 0; @@ -554,7 +544,12 @@ int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm, ret++; while (start != end) { - unsigned long block = min(zap_bytes, end - start); + unsigned long block; + + if (is_vm_hugetlb_page(vma)) + block = end - start; + else + block = min(zap_bytes, end - start); if (!tlb_start_valid) { tlb_start = start; @@ -564,7 +559,7 @@ int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm, unmap_page_range(*tlbp, vma, start, start + block); start += block; zap_bytes -= block; - if (zap_bytes != 0) + if ((long)zap_bytes > 0) continue; if (need_resched()) { tlb_finish_mmu(*tlbp, tlb_start, start); @@ -572,7 +567,7 @@ int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm, *tlbp = tlb_gather_mmu(mm, 0); tlb_start_valid = 0; } - zap_bytes = zap_block_size(vma); + zap_bytes = ZAP_BLOCK_SIZE; } if (vma->vm_next && vma->vm_next->vm_start < vma->vm_end) printk("%s: VMA list is not sorted correctly!\n", @@ -1458,7 +1453,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, pgd_t *pgd; pmd_t *pmd; - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); pgd = pgd_offset(mm, address); inc_page_state(pgfault); diff --git a/mm/nommu.c b/mm/nommu.c index 687f37fff425..a40138c746c2 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -130,6 +130,11 @@ void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot) return kmalloc(size, gfp_mask & ~__GFP_HIGHMEM); } +struct page * vmalloc_to_page(void *addr) +{ + return virt_to_page(addr); +} + long vread(char *buf, char *addr, unsigned long count) { memcpy(buf, addr, count); @@ -546,6 +551,17 @@ struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) return NULL; } +struct page * follow_page(struct mm_struct *mm, unsigned long addr, int write) +{ + return NULL; +} + +int remap_page_range(struct vm_area_struct *vma, unsigned long from, + unsigned long to, unsigned long size, pgprot_t prot) +{ + return -EPERM; +} + unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 7348c97a4b25..28a7e425664b 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -369,7 +369,7 @@ static struct notifier_block ratelimit_nb = { * dirty memory thresholds: allowing too much dirty highmem pins an excessive * number of buffer_heads. */ -static int __init page_writeback_init(void) +void __init page_writeback_init(void) { long buffer_pages = nr_free_buffer_pages(); long correction; @@ -392,9 +392,7 @@ static int __init page_writeback_init(void) add_timer(&wb_timer); set_ratelimit(); register_cpu_notifier(&ratelimit_nb); - return 0; } -module_init(page_writeback_init); int do_writepages(struct address_space *mapping, struct writeback_control *wbc) { diff --git a/mm/slab.c b/mm/slab.c index db8c96c49947..1b7bf0a8dfa4 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -344,8 +344,20 @@ struct kmem_cache_s { #endif -/* maximum size of an obj (in 2^order pages) */ +/* + * Maximum size of an obj (in 2^order pages) + * and absolute limit for the gfp order. + */ +#if defined(CONFIG_LARGE_ALLOCS) +#define MAX_OBJ_ORDER 13 /* up to 32Mb */ +#define MAX_GFP_ORDER 13 /* up to 32Mb */ +#elif defined(CONFIG_MMU) #define MAX_OBJ_ORDER 5 /* 32 pages */ +#define MAX_GFP_ORDER 5 /* 32 pages */ +#else +#define MAX_OBJ_ORDER 8 /* up to 1Mb */ +#define MAX_GFP_ORDER 8 /* up to 1Mb */ +#endif /* * Do not go above this order unless 0 objects fit into the slab. @@ -354,12 +366,6 @@ struct kmem_cache_s { #define BREAK_GFP_ORDER_LO 1 static int slab_break_gfp_order = BREAK_GFP_ORDER_LO; -/* - * Absolute limit for the gfp order - */ -#define MAX_GFP_ORDER 5 /* 32 pages */ - - /* Macros for storing/retrieving the cachep and or slab from the * global 'mem_map'. These are used to find the slab an obj belongs to. * With kfree(), these are used to find the cache which an obj belongs to. @@ -399,6 +405,18 @@ static struct cache_sizes malloc_sizes[] = { { 32768, NULL, NULL}, { 65536, NULL, NULL}, {131072, NULL, NULL}, +#ifndef CONFIG_MMU + {262144, NULL, NULL}, + {524288, NULL, NULL}, + {1048576, NULL, NULL}, +#ifdef CONFIG_LARGE_ALLOCS + {2097152, NULL, NULL}, + {4194304, NULL, NULL}, + {8388608, NULL, NULL}, + {16777216, NULL, NULL}, + {33554432, NULL, NULL}, +#endif /* CONFIG_LARGE_ALLOCS */ +#endif /* CONFIG_MMU */ { 0, NULL, NULL} }; /* Must match cache_sizes above. Out of line to keep cache footprint low. */ @@ -427,7 +445,19 @@ static struct { CN("size-16384"), CN("size-32768"), CN("size-65536"), - CN("size-131072") + CN("size-131072"), +#ifndef CONFIG_MMU + CN("size-262144"), + CN("size-524288"), + CN("size-1048576"), +#ifdef CONFIG_LARGE_ALLOCS + CN("size-2097152"), + CN("size-4194304"), + CN("size-8388608"), + CN("size-16777216"), + CN("size-33554432"), +#endif /* CONFIG_LARGE_ALLOCS */ +#endif /* CONFIG_MMU */ }; #undef CN diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4c3caba9f157..3397f58011e7 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -441,9 +441,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp) return SVC_DENIED; } - /* Put NULL verifier */ - svc_putu32(resv, RPC_AUTH_NULL); - svc_putu32(resv, 0); key.m_class = rqstp->rq_server->sv_program->pg_class; key.m_addr = rqstp->rq_addr.sin_addr; @@ -470,8 +467,13 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp) } else rv = SVC_DROP; - if (rqstp->rq_client == NULL && rqstp->rq_proc != 0) + if (rv == SVC_OK && rqstp->rq_client == NULL && rqstp->rq_proc != 0) goto badcred; + + /* Put NULL verifier */ + svc_putu32(resv, RPC_AUTH_NULL); + svc_putu32(resv, 0); + return rv; badcred: diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index c727f2598039..31eace23cab3 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -577,12 +577,15 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) if (skb_is_nonlinear(skb)) { /* we have to copy */ + local_bh_disable(); if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { + local_bh_enable(); /* checksum error */ skb_free_datagram(svsk->sk_sk, skb); svc_sock_received(svsk); return 0; } + local_bh_enable(); skb_free_datagram(svsk->sk_sk, skb); } else { /* we can use it in-place */ @@ -1435,7 +1438,7 @@ static struct cache_deferred_req * svc_defer(struct cache_req *req) { struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle); - int size = sizeof(struct svc_deferred_req) + (rqstp->rq_arg.head[0].iov_len); + int size = sizeof(struct svc_deferred_req) + (rqstp->rq_arg.len); struct svc_deferred_req *dr; if (rqstp->rq_arg.page_len) @@ -1444,6 +1447,7 @@ svc_defer(struct cache_req *req) dr = rqstp->rq_deferred; rqstp->rq_deferred = NULL; } else { + int skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len; /* FIXME maybe discard if size too large */ dr = kmalloc(size, GFP_KERNEL); if (dr == NULL) @@ -1452,8 +1456,8 @@ svc_defer(struct cache_req *req) dr->serv = rqstp->rq_server; dr->prot = rqstp->rq_prot; dr->addr = rqstp->rq_addr; - dr->argslen = rqstp->rq_arg.head[0].iov_len >> 2; - memcpy(dr->args, rqstp->rq_arg.head[0].iov_base, dr->argslen<<2); + dr->argslen = rqstp->rq_arg.len >> 2; + memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2); } spin_lock(&rqstp->rq_server->sv_lock); rqstp->rq_sock->sk_inuse++; diff --git a/scripts/Makefile b/scripts/Makefile index 3b00318d0bc6..658b93f061ac 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -8,11 +8,11 @@ # docproc: Preprocess .tmpl file in order to generate .sgml docs # conmakehash: Create arrays for initializing the kernel console tables -host-progs := fixdep split-include conmakehash docproc kallsyms modpost \ - mk_elfconfig -build-targets := $(host-progs) empty.o +host-progs := fixdep split-include conmakehash docproc kallsyms modpost \ + mk_elfconfig +always := $(host-progs) empty.o -modpost-objs := modpost.o file2alias.o +modpost-objs := modpost.o file2alias.o subdir-$(CONFIG_MODVERSIONS) += genksyms @@ -20,7 +20,7 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms subdir- += lxdialog kconfig # fixdep is needed to compile other host programs -$(addprefix $(obj)/,$(filter-out fixdep,$(build-targets)) $(subdir-y)): $(obj)/fixdep +$(addprefix $(obj)/,$(filter-out fixdep,$(always)) $(subdir-y)): $(obj)/fixdep # dependencies on generated files need to be listed explicitly @@ -32,4 +32,4 @@ quiet_cmd_elfconfig = MKELF $@ $(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE $(call if_changed,elfconfig) -targets += $(obj)/elfconfig.h +targets += elfconfig.h diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 7f5fbbd1111c..4f3f9e3346a9 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -15,6 +15,14 @@ include $(obj)/Makefile include scripts/Makefile.lib +ifdef EXTRA_TARGETS +$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.5. Please fix!) +endif + +ifdef build-targets +$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.5. Please fix!) +endif + ifdef export-objs $(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.5. Please fix!) endif @@ -53,9 +61,9 @@ endif touch-module = @echo $(@:.o=.ko) > $(MODVERDIR)/$(@F:.o=.mod) -__build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \ +__build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(extra-y)) \ $(if $(KBUILD_MODULES),$(obj-m)) \ - $(subdir-ym) $(build-targets) + $(subdir-ym) $(always) @: # Module versioning @@ -198,8 +206,7 @@ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< %.o: %.S FORCE $(call if_changed_dep,as_o_S) -targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) \ - $(build-targets) +targets += $(real-objs-y) $(real-objs-m) $(extra-y) $(MAKECMDGOALS) $(always) # Build the compiled-in targets # --------------------------------------------------------------------------- diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index b88e5e494a49..dc734426699f 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -28,15 +28,13 @@ subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-)) # Add subdir path -EXTRA_TARGETS := $(addprefix $(obj)/,$(EXTRA_TARGETS)) -clean-files := $(addprefix $(obj)/,$(clean-files)) -host-progs := $(addprefix $(obj)/,$(host-progs)) subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) +__clean-files := $(wildcard $(addprefix $(obj)/, \ + $(extra-y) $(EXTRA_TARGETS) $(always) $(host-progs) \ + $(targets) $(clean-files))) # ========================================================================== -__clean-files := $(wildcard $(EXTRA_TARGETS) $(host-progs) $(clean-files) $(targets)) - quiet_cmd_clean = CLEAN $(obj) cmd_clean = rm -f $(__clean-files); $(clean-rule) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 6877b8bd9c85..5d4b44b7150a 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -8,6 +8,8 @@ comma := , empty := space := $(empty) $(empty) +# Backward compatibility - to be removed... +extra-y += $(EXTRA_TARGETS) # Figure out what we need to build from the various variables # =========================================================================== @@ -51,7 +53,7 @@ multi-objs := $(multi-objs-y) $(multi-objs-m) subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o))) # Replace multi-part objects by their individual parts, look at local dir only -real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(EXTRA_TARGETS) +real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) # C code @@ -84,8 +86,9 @@ host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) # Add subdir path -EXTRA_TARGETS := $(addprefix $(obj)/,$(EXTRA_TARGETS)) -build-targets := $(addprefix $(obj)/,$(build-targets)) +extra-y := $(addprefix $(obj)/,$(extra-y)) +always := $(addprefix $(obj)/,$(always)) +targets := $(addprefix $(obj)/,$(targets)) obj-y := $(addprefix $(obj)/,$(obj-y)) obj-m := $(addprefix $(obj)/,$(obj-m)) subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y)) diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile index 771d2dc303cf..6d9e57472fc1 100644 --- a/scripts/genksyms/Makefile +++ b/scripts/genksyms/Makefile @@ -1,6 +1,6 @@ host-progs := genksyms -build-targets := $(host-progs) +always := $(host-progs) genksyms-objs := genksyms.o parse.o lex.o diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 927d00fe7814..bae5e29352da 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -6,20 +6,29 @@ # Utilizes the lxdialog package # qconf: Used for the xconfig target # Based on QT which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK which needs to be installed to compile it # +################# # object files used by all lkc flavours libkconfig-objs := zconf.tab.o -host-progs := conf mconf qconf +host-progs := conf mconf qconf gconf conf-objs := conf.o libkconfig.so mconf-objs := mconf.o libkconfig.so -qconf-objs := kconfig_load.o +ifeq ($(MAKECMDGOALS),$(obj)/qconf) qconf-cxxobjs := qconf.o +qconf-objs := kconfig_load.o +endif + +ifeq ($(MAKECMDGOALS),$(obj)/gconf) +gconf-objs := gconf.o kconfig_load.o +endif clean-files := libkconfig.so lkc_defs.h qconf.moc .tmp_qtcheck \ - zconf.tab.c zconf.tab.h lex.zconf.c + .tmp_gtkcheck zconf.tab.c zconf.tab.h lex.zconf.c # generated files seem to need this to find local include files HOSTCFLAGS_lex.zconf.o := -I$(src) @@ -28,7 +37,10 @@ HOSTCFLAGS_zconf.tab.o := -I$(src) HOSTLOADLIBES_qconf = -L$(QTDIR)/lib -Wl,-rpath,$(QTDIR)/lib -l$(QTLIB) -ldl HOSTCXXFLAGS_qconf.o = -I$(QTDIR)/include -$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o: $(obj)/zconf.tab.h +HOSTLOADLIBES_gconf = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs` +HOSTCFLAGS_gconf.o = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` + +$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o: $(obj)/zconf.tab.h $(obj)/qconf.o: $(obj)/.tmp_qtcheck @@ -38,7 +50,7 @@ MOC = $(QTDIR)/bin/moc # QT needs some extra effort... $(obj)/.tmp_qtcheck: - @set -e; for d in $$QTDIR /usr/share/qt /usr/lib/qt*3*; do \ + @set -e; for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ if [ -f $$d/include/qconfig.h ]; then DIR=$$d; break; fi; \ done; \ if [ -z "$$DIR" ]; then \ @@ -60,12 +72,40 @@ $(obj)/.tmp_qtcheck: fi endif +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(MAKECMDGOALS),$(obj)/gconf) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: + @if `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --exists`; then \ + if `pkg-config gtk+-2.0 --atleast-version=2.0.0`; then \ + touch $@; \ + else \ + echo "*"; \ + echo "* GTK+ is present but version >= 2.0.0 is required."; \ + echo "*"; \ + false; \ + fi \ + else \ + echo "*"; \ + echo "* Unable to find the GTK+ installation. Please make sure that"; \ + echo "* the GTK+ 2.0 development package is correctly installed..."; \ + echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo "*"; \ + false; \ + fi +endif + $(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/kconfig_load.o: $(obj)/lkc_defs.h $(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h +$(obj)/gconf.o: $(obj)/lkc_defs.h + $(obj)/%.moc: $(src)/%.h $(MOC) -i $< -o $@ diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 896a296d17c5..373e8346d5b3 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -155,9 +155,11 @@ struct property { #define for_all_properties(sym, st, tok) \ for (st = sym->prop; st; st = st->next) \ if (st->type == (tok)) -#define for_all_prompts(sym, st) for_all_properties(sym, st, P_PROMPT) #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) struct menu { struct menu *next; diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c new file mode 100644 index 000000000000..8baeb63dfaf7 --- /dev/null +++ b/scripts/kconfig/gconf.c @@ -0,0 +1,1580 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin <roms@lpg.ticalc.org> + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lkc.h" +#include "images.c" + +#include <glade/glade.h> +#include <gtk/gtk.h> +#include <glib.h> +#include <gdk/gdkkeysyms.h> + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <stdlib.h> + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +static gint view_mode = SPLIT_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean show_all = FALSE; +static gboolean show_debug = FALSE; +static gboolean resizeable = FALSE; + +static gboolean config_changed = FALSE; + +static char nohelp_text[] = + "Sorry, no help available for this option yet.\n"; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256] = { 0 }; +static gint indent; + +static struct menu *current; + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node2(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); + + +/* Helping/Debugging Functions */ + + +const char *dbg_print_stype(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val == S_UNKNOWN) + strcpy(buf, "unknown"); + if (val == S_BOOLEAN) + strcpy(buf, "boolean"); + if (val == S_TRISTATE) + strcpy(buf, "tristate"); + if (val == S_INT) + strcpy(buf, "int"); + if (val == S_HEX) + strcpy(buf, "hex"); + if (val == S_STRING) + strcpy(buf, "string"); + if (val == S_OTHER) + strcpy(buf, "other"); + +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + +const char *dbg_print_flags(int val) +{ + static char buf[256] = { 0 }; + + bzero(buf, 256); + + if (val & SYMBOL_YES) + strcat(buf, "yes/"); + if (val & SYMBOL_MOD) + strcat(buf, "mod/"); + if (val & SYMBOL_NO) + strcat(buf, "no/"); + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_PRINTED) + strcat(buf, "printed/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_NEW) + strcat(buf, "new/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + +const char *dbg_print_ptype(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val == P_UNKNOWN) + strcpy(buf, "unknown"); + if (val == P_PROMPT) + strcpy(buf, "prompt"); + if (val == P_COMMENT) + strcpy(buf, "comment"); + if (val == P_MENU) + strcpy(buf, "menu"); + if (val == P_ROOTMENU) + strcpy(buf, "rootmenu"); + if (val == P_DEFAULT) + strcpy(buf, "default"); + if (val == P_CHOICE) + strcpy(buf, "choice"); + +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + + +/* Main Window Initialization */ + + +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + char title[256]; + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error("GUI loading failed !\n"); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + + pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **) xpm_single_view); + gtk_image_set_from_pixmap(GTK_IMAGE + (((GtkToolbarChild + *) (g_list_nth(GTK_TOOLBAR(widget)-> + children, + 5)->data))->icon), + pixmap, mask); + pixmap = + gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **) xpm_split_view); + gtk_image_set_from_pixmap(GTK_IMAGE + (((GtkToolbarChild + *) (g_list_nth(GTK_TOOLBAR(widget)-> + children, + 6)->data))->icon), + pixmap, mask); + pixmap = + gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **) xpm_tree_view); + gtk_image_set_from_pixmap(GTK_IMAGE + (((GtkToolbarChild + *) (g_list_nth(GTK_TOOLBAR(widget)-> + children, + 7)->data))->icon), + pixmap, mask); + + switch (view_mode) { + case SINGLE_VIEW: + widget = glade_xml_get_widget(xml, "button4"); + gtk_button_clicked(GTK_BUTTON(widget)); + break; + case SPLIT_VIEW: + widget = glade_xml_get_widget(xml, "button5"); + gtk_button_clicked(GTK_BUTTON(widget)); + break; + case FULL_VIEW: + widget = glade_xml_get_widget(xml, "button6"); + gtk_button_clicked(GTK_BUTTON(widget)); + break; + } + + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + sprintf(title, "Linux Kernel v%s.%s.%s%s Configuration", + getenv("VERSION"), getenv("PATCHLEVEL"), + getenv("SUBLEVEL"), getenv("EXTRAVERSION")); + gtk_window_set_title(GTK_WINDOW(main_wnd), title); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, FALSE); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Options", renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); +static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, + gchar * arg1, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, FALSE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, "Options"); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, NULL); + g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(renderer_toggled), NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Name", renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Value", renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = menu_get_prompt(menu); + gchar *name; + const char *help = nohelp_text; + + if (!menu->sym) + help = ""; + else if (menu->sym->help) + help = menu->sym->help; + + if (menu->sym && menu->sym->name) + name = g_strdup_printf(menu->sym->name); + else + name = g_strdup(""); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, " ", 1); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2, + NULL); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (config_changed == FALSE) + return FALSE; + + dialog = gtk_dialog_new_with_buttons("Warning !", + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new("\nSave configuration ?\n"); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save1_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h = 0; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg("Error", "Unable to load configuration !"); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new("Load file..."); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg("Error", "Unable to save configuration !"); + + config_changed = FALSE; +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg("Error", "Unable to save configuration !"); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new("Save file as..."); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; + + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); // instead of update_tree for speed reasons +} + + +void +on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; + update_tree(&rootmenu, NULL); +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = + "Welcome to gkc, the GTK+ graphical kernel configuration tool\n" + "for Linux.\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."; + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" + "Based on the source code from Roman Zippel.\n"; + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + "gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"; + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_pressed(GtkButton * button, gpointer user_data) +{ + enum prop_type type; + + current = current->parent; + type = current->prompt ? current->prompt->type : P_UNKNOWN; + if ((type != P_ROOTMENU) && (type != P_MENU)) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_pressed(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_save_pressed(GtkButton * button, gpointer user_data) +{ + on_save1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_paned_set_position(GTK_PANED(hpaned), 0); + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_paned_set_position(GTK_PANED(hpaned), 0); + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_pressed(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_pressed(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + config_changed = TRUE; + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + int stype; + tristate oldval, newval; + + newval = no; + switch (col) { + case COL_OPTION: + return; + case COL_NAME: + return; + case COL_NO: + newval = no; + break; + case COL_MOD: + newval = mod; + break; + case COL_YES: + newval = yes; + break; + default: + break; + } + + if (!sym) + return; + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + case S_TRISTATE: + if (col == COL_VALUE) + return; + else { + oldval = sym_get_tristate_value(sym); + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + config_changed = TRUE; + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else + //display_tree_part(); //fixme: keep exp/coll + update_tree(current, NULL); + } + break; + case S_INT: + case S_HEX: + case S_STRING: + break; + } +} + +static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, + gchar * path_string, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + gint col; + struct menu *menu; + const int next_col[3] = { COL_NO, COL_MOD, COL_YES }; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + gtk_tree_model_get(model2, &iter, COL_BTNINC, &col, -1); + if (col) + col = COL_MOD; + else { + gtk_tree_model_get(model2, &iter, COL_BTNACT, &col, -1); + col = col ? COL_YES : COL_NO; + } + + change_sym_value(menu, next_col[((col - COL_NO) + 1) % 3]); + + gtk_tree_path_free(path); +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +//#define GTK_BUG_FIXED // GTK+ 2.1.4 mini + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#ifdef GTK_BUG_FIXED + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if ((col == COL_OPTION) && (event->type == GDK_2BUTTON_PRESS) && + (view_mode != FULL_VIEW) && menu->list) { + enum prop_type type; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if ((type != P_MENU) && (type != P_ROOTMENU)) + return FALSE; + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else + change_sym_value(menu, col); + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) { + //g_warning("key_press_event: path is NULL !\n"); + return FALSE; + } + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return FALSE; + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else if (!strcasecmp(event->string, "e")) + col = COL_VALUE; + else + col = 0; + + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + current = menu; + display_tree_part(); + + return FALSE; +} + + +/* Conf management */ + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar **row; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type type; + + //g_strfreev(row); //to fix... + row = (gchar **) g_malloc0(COL_NUMBER * sizeof(gchar *)); + row[COL_OPTION] = + g_strdup_printf("%s %s", menu_get_prompt(menu), + sym ? (sym-> + flags & SYMBOL_NEW ? "(NEW)" : "") : + ""); + + if (show_all && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (type) { + case P_MENU: + case P_ROOTMENU: + row[COL_PIXBUF] = + (gchar *) (view_mode != + FULL_VIEW ? xpm_menu : xpm_void); + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(menu_get_prompt(def_menu)); + } + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (sym_is_choice(sym)) + break; + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node2(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + -1); + + g_object_unref(pix); + g_strfreev(row); +} + + +/* Add a node to the tree */ +static void place_node2(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node2(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct property *prop; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + prop = child1->prompt; + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if (!menu_is_visible(child1) && !show_all) { // remove node + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node2(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node2(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) && (ptype != P_ROOTMENU) && + (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (ptype == P_ROOTMENU) && + (tree == tree2)) + continue; + + if (menu_is_visible(child) || show_all) + place_node2(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + dbg_print_ptype(ptype); + printf(" | "); + if (sym) { + dbg_print_stype(sym->type); + printf(" | "); + dbg_print_flags(sym->flags); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; + + if (((menu != &rootmenu) && (ptype != P_ROOTMENU)) || + (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(current); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +static void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + + if (!menu->prompt || menu->prompt->type != P_MENU) + return; + menu->prompt->type = P_ROOTMENU; + for (child = menu->list; child; child = child->next) + fixup_rootmenu(child); +} + + +/* Main */ + + +int main(int ac, char *av[]) +{ + const char *name; + gchar *cur_dir, *exe_path; + gchar *glade_file; + +#ifndef LKC_DIRECT_LINK + kconfig_load(); +#endif + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + cur_dir = g_get_current_dir(); + exe_path = g_strdup(av[0]); + exe_path[0] = '/'; + glade_file = g_strconcat(cur_dir, exe_path, ".glade", NULL); + g_free(cur_dir); + g_free(exe_path); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 'h': + case '?': + printf("%s <config>\n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade new file mode 100644 index 000000000000..1e1736d81ee9 --- /dev/null +++ b/scripts/kconfig/gconf.glade @@ -0,0 +1,543 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="window1"> + <property name="visible">True</property> + <property name="title" translatable="yes">Gtk Kernel Configurator</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">640</property> + <property name="default_height">480</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <signal name="destroy" handler="on_window1_destroy" object="window1"/> + <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/> + <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkMenuBar" id="menubar1"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="file1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="file1_menu"> + + <child> + <widget class="GtkImageMenuItem" id="load1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Load a config file</property> + <property name="label" translatable="yes">_Load</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_load1_activate"/> + <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image27"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="save1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Save the config in .config</property> + <property name="label" translatable="yes">_Save</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_save1_activate"/> + <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image28"> + <property name="visible">True</property> + <property name="stock">gtk-save</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="save_as1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Save the config in a file</property> + <property name="label" translatable="yes">Save _as</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_save_as1_activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image29"> + <property name="visible">True</property> + <property name="stock">gtk-save-as</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="separator1"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="quit1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Quit</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_quit1_activate"/> + <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image30"> + <property name="visible">True</property> + <property name="stock">gtk-quit</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="options1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Options</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="options1_menu"> + + <child> + <widget class="GtkCheckMenuItem" id="show_name1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show name</property> + <property name="label" translatable="yes">Show _name</property> + <property name="use_underline">True</property> + <property name="active">False</property> + <signal name="activate" handler="on_show_name1_activate"/> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="show_range1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show range (Y/M/N)</property> + <property name="label" translatable="yes">Show _range</property> + <property name="use_underline">True</property> + <property name="active">False</property> + <signal name="activate" handler="on_show_range1_activate"/> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="show_data1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show value of the option</property> + <property name="label" translatable="yes">Show _data</property> + <property name="use_underline">True</property> + <property name="active">False</property> + <signal name="activate" handler="on_show_data1_activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="separator2"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="show_all_options1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show all options</property> + <property name="label" translatable="yes">Show all _options</property> + <property name="use_underline">True</property> + <property name="active">False</property> + <signal name="activate" handler="on_show_all_options1_activate"/> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="show_debug_info1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show masked options</property> + <property name="label" translatable="yes">Show _debug info</property> + <property name="use_underline">True</property> + <property name="active">False</property> + <signal name="activate" handler="on_show_debug_info1_activate"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="help1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="help1_menu"> + + <child> + <widget class="GtkImageMenuItem" id="introduction1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Introduction</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> + <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image31"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-question</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="about1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_About</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> + <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image32"> + <property name="visible">True</property> + <property name="stock">gtk-properties</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="license1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_License</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image33"> + <property name="visible">True</property> + <property name="stock">gtk-justify-fill</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHandleBox" id="handlebox1"> + <property name="visible">True</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <property name="handle_position">GTK_POS_LEFT</property> + <property name="snap_edge">GTK_POS_TOP</property> + + <child> + <widget class="GtkToolbar" id="toolbar1"> + <property name="visible">True</property> + <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> + <property name="toolbar_style">GTK_TOOLBAR_BOTH</property> + <property name="tooltips">True</property> + + <child> + <widget class="button" id="button1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Goes up of one level (single view)</property> + <property name="label" translatable="yes">Back</property> + <property name="use_underline">True</property> + <property name="stock_pixmap">gtk-undo</property> + <signal name="pressed" handler="on_back_pressed"/> + </widget> + </child> + + <child> + <widget class="GtkVSeparator" id="vseparator1"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="button" id="button2"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Load a config file</property> + <property name="label" translatable="yes">Load</property> + <property name="use_underline">True</property> + <property name="stock_pixmap">gtk-open</property> + <signal name="pressed" handler="on_load_pressed"/> + </widget> + </child> + + <child> + <widget class="button" id="button3"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Save a config file</property> + <property name="label" translatable="yes">Save</property> + <property name="use_underline">True</property> + <property name="stock_pixmap">gtk-save</property> + <signal name="pressed" handler="on_save_pressed"/> + </widget> + </child> + + <child> + <widget class="GtkVSeparator" id="vseparator2"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="button" id="button4"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Single view</property> + <property name="label" translatable="yes">Single</property> + <property name="use_underline">True</property> + <property name="stock_pixmap">gtk-missing-image</property> + <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/> + </widget> + </child> + + <child> + <widget class="button" id="button5"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Split view</property> + <property name="label" translatable="yes">Split</property> + <property name="use_underline">True</property> + <property name="stock_pixmap">gtk-missing-image</property> + <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/> + </widget> + </child> + + <child> + <widget class="button" id="button6"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Full view</property> + <property name="label" translatable="yes">Full</property> + <property name="use_underline">True</property> + <property name="stock_pixmap">gtk-missing-image</property> + <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkVSeparator" id="vseparator3"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="button" id="button7"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property> + <property name="label" translatable="yes">Collapse</property> + <property name="use_underline">True</property> + <signal name="pressed" handler="on_collapse_pressed"/> + </widget> + </child> + + <child> + <widget class="button" id="button8"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property> + <property name="label" translatable="yes">Expand</property> + <property name="use_underline">True</property> + <signal name="pressed" handler="on_expand_pressed"/> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHPaned" id="hpaned1"> + <property name="width_request">1</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">0</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeview1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/> + <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/> + <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">False</property> + </packing> + </child> + + <child> + <widget class="GtkVPaned" id="vpaned1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">0</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeview2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/> + <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/> + <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">False</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow3"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTextView" id="textview3"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_WORD</property> + <property name="cursor_visible">True</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">0</property> + <property name="right_margin">0</property> + <property name="indent">0</property> + <property name="text" translatable="yes">Sorry, no help available for this option yet.</property> + </widget> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c index 65a5d67f8488..d4f84bd4a96b 100644 --- a/scripts/kconfig/images.c +++ b/scripts/kconfig/images.c @@ -290,3 +290,37 @@ static const char *xpm_menu_inv[] = { " .......... ", " .......... ", " "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped index 290d48114aab..b0300b6ca490 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/lex.zconf.c_shipped @@ -357,18 +357,18 @@ static yyconst short yy_nxt[][37] = }, { - 11, 38, 38, 39, 40, 41, 38, 42, 41, 43, - 44, 45, 46, 46, 47, 48, 46, 46, 46, 46, - 46, 46, 46, 46, 49, 46, 46, 46, 50, 46, - 46, 46, 46, 46, 46, 46, 51 + 11, 38, 38, 39, 40, 41, 42, 43, 41, 44, + 45, 46, 47, 47, 48, 49, 47, 47, 47, 47, + 47, 47, 47, 47, 50, 47, 47, 47, 51, 47, + 47, 47, 47, 47, 47, 47, 52 }, { - 11, 38, 38, 39, 40, 41, 38, 42, 41, 43, - 44, 45, 46, 46, 47, 48, 46, 46, 46, 46, - 46, 46, 46, 46, 49, 46, 46, 46, 50, 46, - 46, 46, 46, 46, 46, 46, 51 + 11, 38, 38, 39, 40, 41, 42, 43, 41, 44, + 45, 46, 47, 47, 48, 49, 47, 47, 47, 47, + 47, 47, 47, 47, 50, 47, 47, 47, 51, 47, + 47, 47, 47, 47, 47, 47, 52 }, { @@ -387,7 +387,7 @@ static yyconst short yy_nxt[][37] = }, { - 11, -13, 52, 53, -13, -13, 54, -13, -13, -13, + 11, -13, 53, 54, -13, -13, 55, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13 @@ -402,10 +402,10 @@ static yyconst short yy_nxt[][37] = }, { - 11, 55, 55, 56, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55 + 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56 }, { @@ -425,109 +425,109 @@ static yyconst short yy_nxt[][37] = { 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, - -18, -18, -18, 57, -18, -18, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -18 + -18, -18, -18, 58, -18, -18, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -18 }, { 11, -19, -19, -19, -19, -19, -19, -19, -19, -19, - -19, -19, -19, 57, -19, -19, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 58, 57, - 57, 57, 57, 57, 57, 57, -19 + -19, -19, -19, 58, -19, -19, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 59, 58, + 58, 58, 58, 58, 58, 58, -19 }, { 11, -20, -20, -20, -20, -20, -20, -20, -20, -20, - -20, -20, -20, 57, -20, -20, 57, 57, 57, 57, - 57, 57, 57, 59, 57, 57, 57, 57, 60, 57, - 57, 57, 57, 57, 57, 57, -20 + -20, -20, -20, 58, -20, -20, 58, 58, 58, 58, + 58, 58, 58, 60, 58, 58, 58, 58, 61, 58, + 58, 58, 58, 58, 58, 58, -20 }, { 11, -21, -21, -21, -21, -21, -21, -21, -21, -21, - -21, -21, -21, 57, -21, -21, 57, 57, 57, 57, - 61, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -21 + -21, -21, -21, 58, -21, -21, 58, 58, 58, 58, + 62, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -21 }, { 11, -22, -22, -22, -22, -22, -22, -22, -22, -22, - -22, -22, -22, 57, -22, -22, 57, 57, 57, 57, + -22, -22, -22, 58, -22, -22, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 62, 57, 57, - 57, 57, 57, 57, 57, 57, -22 + 58, 58, 58, 58, 58, 58, 58, 63, 58, 58, + 58, 58, 58, 58, 58, 58, -22 }, { 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, - -23, -23, -23, 57, -23, -23, 57, 57, 57, 57, - 63, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -23 + -23, -23, -23, 58, -23, -23, 58, 58, 58, 58, + 64, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -23 }, { 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, - -24, -24, -24, 57, -24, -24, 57, 57, 57, 57, - 57, 64, 57, 57, 57, 57, 57, 65, 57, 57, - 57, 57, 57, 57, 57, 57, -24 + -24, -24, -24, 58, -24, -24, 58, 58, 58, 58, + 58, 65, 58, 58, 58, 58, 58, 66, 58, 58, + 58, 58, 58, 58, 58, 58, -24 }, { 11, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, 57, -25, -25, 66, 57, 57, 57, - 67, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -25 + -25, -25, -25, 58, -25, -25, 67, 58, 58, 58, + 68, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -25 }, { 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, - -26, -26, -26, 57, -26, -26, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 68, - 57, 57, 57, 57, 57, 57, -26 + -26, -26, -26, 58, -26, -26, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 69, + 58, 58, 58, 58, 58, 58, -26 }, { 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, - -27, -27, -27, 57, -27, -27, 57, 57, 57, 57, + -27, -27, -27, 58, -27, -27, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 69, 57, 57, 57, 57, -27 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 70, 58, 58, 58, 58, -27 }, { 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, - -28, -28, -28, 57, -28, -28, 57, 57, 57, 57, - 70, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -28 + -28, -28, -28, 58, -28, -28, 58, 58, 58, 58, + 71, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -28 }, { 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, 57, -29, -29, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 71, 57, - 57, 57, 57, 72, 57, 57, -29 + -29, -29, -29, 58, -29, -29, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 72, 58, + 58, 58, 58, 73, 58, 58, -29 }, { 11, -30, -30, -30, -30, -30, -30, -30, -30, -30, - -30, -30, -30, 57, -30, -30, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 73, 57, 57, 57, 57, -30 + -30, -30, -30, 58, -30, -30, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 74, 58, 58, 58, 58, -30 }, { - 11, 74, 74, -31, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74 + 11, 75, 75, -31, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75 }, { - 11, -32, 75, 76, -32, -32, -32, -32, -32, -32, + 11, -32, 76, 77, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, @@ -535,17 +535,17 @@ static yyconst short yy_nxt[][37] = }, { - 11, 77, -33, -33, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77 + 11, 78, -33, -33, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78 }, { - 11, 78, 78, 79, 78, -34, 78, 78, -34, 78, - 78, 78, 78, 78, 78, -34, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78 + 11, 79, 79, 80, 79, -34, 79, 79, -34, 79, + 79, 79, 79, 79, 79, -34, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79 }, @@ -564,11 +564,11 @@ static yyconst short yy_nxt[][37] = }, { - 11, 80, 80, 81, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 11, 81, 81, 82, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80 + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81 }, { @@ -588,7 +588,7 @@ static yyconst short yy_nxt[][37] = { 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, - -40, -40, -40, -40, 82, -40, -40, -40, -40, -40, + -40, -40, -40, -40, 83, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40 }, @@ -601,15 +601,15 @@ static yyconst short yy_nxt[][37] = }, { - 11, -42, -42, -42, -42, -42, -42, 83, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, + 11, 84, 84, -42, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42 + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84 }, { - 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + 11, -43, -43, -43, -43, -43, -43, 85, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43 @@ -625,272 +625,272 @@ static yyconst short yy_nxt[][37] = { 11, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, 84, 85, 85, -45, -45, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -45 + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45 }, { 11, -46, -46, -46, -46, -46, -46, -46, -46, -46, - -46, 85, 85, 85, -46, -46, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -46 + -46, 86, 87, 87, -46, -46, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -46 }, { 11, -47, -47, -47, -47, -47, -47, -47, -47, -47, - -47, -47, -47, -47, -47, -47, -47, -47, -47, -47, + -47, 87, 87, 87, -47, -47, 87, 87, 87, 87, - -47, -47, -47, -47, -47, -47, -47, -47, -47, -47, - -47, -47, -47, -47, -47, -47, -47 + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -47 }, { - 11, -48, -48, 86, -48, -48, -48, -48, -48, -48, + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48 }, { - 11, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, 85, 85, 85, -49, -49, 85, 85, 85, 85, - 85, 87, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -49 + 11, -49, -49, 88, -49, -49, -49, -49, -49, -49, + -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, + -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, + -49, -49, -49, -49, -49, -49, -49 }, { 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, - -50, 85, 85, 85, -50, -50, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 88, 85, 85, - 85, 85, 85, 85, 85, 85, -50 + -50, 87, 87, 87, -50, -50, 87, 87, 87, 87, + 87, 89, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -50 }, { 11, -51, -51, -51, -51, -51, -51, -51, -51, -51, - -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, - -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, - -51, -51, -51, -51, -51, -51, 89 + -51, 87, 87, 87, -51, -51, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 90, 87, 87, + 87, 87, 87, 87, 87, 87, -51 }, { - 11, -52, 52, 53, -52, -52, 54, -52, -52, -52, + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, - -52, -52, -52, -52, -52, -52, -52 + -52, -52, -52, -52, -52, -52, 91 }, { - 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + 11, -53, 53, 54, -53, -53, 55, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53 }, { - 11, 55, 55, 56, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55 + 11, -54, -54, -54, -54, -54, -54, -54, -54, -54, + -54, -54, -54, -54, -54, -54, -54, -54, -54, -54, + -54, -54, -54, -54, -54, -54, -54, -54, -54, -54, + -54, -54, -54, -54, -54, -54, -54 }, { - 11, 55, 55, 56, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55 + 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56 }, { - 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, - -56, -56, -56, -56, -56, -56, -56, -56, -56, -56, - -56, -56, -56, -56, -56, -56, -56, -56, -56, -56, - -56, -56, -56, -56, -56, -56, -56 + 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56 }, { 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, - -57, -57, -57, 57, -57, -57, 57, 57, 57, 57, + -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -57 + -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, -57, -57, -57, -57, -57, -57 }, { 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, - -58, -58, -58, 57, -58, -58, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 90, 57, - 57, 57, 57, 57, 57, 57, -58 + -58, -58, -58, 58, -58, -58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -58 }, { 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, - -59, -59, -59, 57, -59, -59, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 91, 57, - 57, 57, 57, 57, 57, 57, -59 + -59, -59, -59, 58, -59, -59, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 92, 58, + 58, 58, 58, 58, 58, 58, -59 }, { 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, - -60, -60, -60, 57, -60, -60, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 92, 93, 57, 57, - 57, 57, 57, 57, 57, 57, -60 + -60, -60, -60, 58, -60, -60, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 93, 58, + 58, 58, 58, 58, 58, 58, -60 }, { 11, -61, -61, -61, -61, -61, -61, -61, -61, -61, - -61, -61, -61, 57, -61, -61, 57, 57, 57, 57, - 57, 94, 57, 57, 57, 57, 57, 57, 57, 95, - 57, 57, 57, 57, 57, 57, -61 + -61, -61, -61, 58, -61, -61, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 94, 95, 58, 58, + 58, 58, 58, 58, 58, 58, -61 }, { 11, -62, -62, -62, -62, -62, -62, -62, -62, -62, - -62, -62, -62, 57, -62, -62, 57, 57, 57, 96, + -62, -62, -62, 58, -62, -62, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -62 + 58, 96, 58, 58, 58, 58, 58, 58, 58, 97, + 58, 58, 58, 58, 58, 58, -62 }, { 11, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -63, -63, 57, -63, -63, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 97, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 98, -63 + -63, -63, -63, 58, -63, -63, 58, 58, 58, 98, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -63 }, { 11, -64, -64, -64, -64, -64, -64, -64, -64, -64, - -64, -64, -64, 57, -64, -64, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -64 + -64, -64, -64, 58, -64, -64, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 99, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 100, -64 }, { 11, -65, -65, -65, -65, -65, -65, -65, -65, -65, - -65, -65, -65, 57, -65, -65, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 99, 57, 57, -65 + -65, -65, -65, 58, -65, -65, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -65 }, { 11, -66, -66, -66, -66, -66, -66, -66, -66, -66, - -66, -66, -66, 57, -66, -66, 57, 57, 57, 57, - 57, 57, 57, 57, 100, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -66 + -66, -66, -66, 58, -66, -66, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 101, 58, 58, -66 }, { 11, -67, -67, -67, -67, -67, -67, -67, -67, -67, - -67, -67, -67, 57, -67, -67, 57, 57, 57, 57, + -67, -67, -67, 58, -67, -67, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 101, 57, 57, - 57, 57, 57, 57, 57, 57, -67 + 58, 58, 58, 58, 102, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -67 }, { 11, -68, -68, -68, -68, -68, -68, -68, -68, -68, - -68, -68, -68, 57, -68, -68, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 102, 57, 57, -68 + -68, -68, -68, 58, -68, -68, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 103, 58, 58, + 58, 58, 58, 58, 58, 58, -68 }, { 11, -69, -69, -69, -69, -69, -69, -69, -69, -69, - -69, -69, -69, 57, -69, -69, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 103, 57, - 57, 57, 57, 57, 57, 57, -69 + -69, -69, -69, 58, -69, -69, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 104, 58, 58, -69 }, { 11, -70, -70, -70, -70, -70, -70, -70, -70, -70, - -70, -70, -70, 57, -70, -70, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 104, 57, 57, 57, 57, 57, -70 + -70, -70, -70, 58, -70, -70, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 105, 58, + 58, 58, 58, 58, 58, 58, -70 }, { 11, -71, -71, -71, -71, -71, -71, -71, -71, -71, - -71, -71, -71, 57, -71, -71, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 105, 57, -71 + -71, -71, -71, 58, -71, -71, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 106, 58, 58, 58, 58, 58, -71 }, { 11, -72, -72, -72, -72, -72, -72, -72, -72, -72, - -72, -72, -72, 57, -72, -72, 57, 57, 57, 57, + -72, -72, -72, 58, -72, -72, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 106, 57, 57, 57, 57, -72 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 107, 58, -72 }, { 11, -73, -73, -73, -73, -73, -73, -73, -73, -73, - -73, -73, -73, 57, -73, -73, 57, 57, 57, 57, - 57, 57, 57, 57, 107, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -73 + -73, -73, -73, 58, -73, -73, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 108, 58, 58, 58, 58, -73 }, { - 11, 74, 74, -74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74 + 11, -74, -74, -74, -74, -74, -74, -74, -74, -74, + -74, -74, -74, 58, -74, -74, 58, 58, 58, 58, + 58, 58, 58, 58, 109, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -74 }, { - 11, -75, 75, 76, -75, -75, -75, -75, -75, -75, - -75, -75, -75, -75, -75, -75, -75, -75, -75, -75, - -75, -75, -75, -75, -75, -75, -75, -75, -75, -75, - -75, -75, -75, -75, -75, -75, -75 + 11, 75, 75, -75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75 }, { - 11, -76, -76, -76, -76, -76, -76, -76, -76, -76, + 11, -76, 76, 77, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76 }, { - 11, -77, -77, -77, -77, -77, -77, -77, -77, -77, - -77, -77, -77, -77, -77, -77, -77, -77, -77, -77, + 11, 78, -77, -77, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - -77, -77, -77, -77, -77, -77, -77, -77, -77, -77, - -77, -77, -77, -77, -77, -77, -77 + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78 }, { - 11, 78, 78, 79, 78, -78, 78, 78, -78, 78, - 78, 78, 78, 78, 78, -78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78 + 11, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78 }, { - 11, -79, -79, -79, -79, -79, -79, -79, -79, -79, - -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, - -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, - -79, -79, -79, -79, -79, -79, -79 + 11, 79, 79, 80, 79, -79, 79, 79, -79, 79, + 79, 79, 79, 79, 79, -79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79 }, { - 11, -80, -80, 81, -80, -80, -80, -80, -80, -80, + 11, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80 }, { - 11, -81, -81, -81, -81, -81, -81, -81, -81, -81, + 11, -81, -81, 82, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81, -81 @@ -912,669 +912,728 @@ static yyconst short yy_nxt[][37] = }, { - 11, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, 108, 85, 85, -84, -84, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -84 + 11, 84, 84, -84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84 }, { 11, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, 85, 85, 85, -85, -85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -85 + -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, + -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, + -85, -85, -85, -85, -85, -85, -85 }, { 11, -86, -86, -86, -86, -86, -86, -86, -86, -86, - -86, -86, -86, -86, -86, -86, -86, -86, -86, -86, - -86, -86, -86, -86, -86, -86, -86, -86, -86, -86, - -86, -86, -86, -86, -86, -86, -86 + -86, 110, 87, 87, -86, -86, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -86 }, { 11, -87, -87, -87, -87, -87, -87, -87, -87, -87, - -87, 85, 85, 85, -87, -87, 85, 85, 85, 85, + -87, 87, 87, 87, -87, -87, 87, 87, 87, 87, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -87 + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -87 }, { 11, -88, -88, -88, -88, -88, -88, -88, -88, -88, - -88, 85, 85, 85, -88, -88, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -88 + -88, -88, -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88 }, { 11, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, -89, -89, -89, -89, -89, -89 + -89, 87, 87, 87, -89, -89, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -89 }, { 11, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, 57, -90, -90, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 109, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -90 + -90, 87, 87, 87, -90, -90, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -90 }, { 11, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, 57, -91, -91, 57, 57, 57, 57, - 57, 57, 57, 57, 110, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -91 + -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91, -91 }, { 11, -92, -92, -92, -92, -92, -92, -92, -92, -92, - -92, -92, -92, 57, -92, -92, 57, 57, 57, 57, + -92, -92, -92, 58, -92, -92, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 111, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -92 + 58, 58, 58, 58, 58, 111, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -92 }, { 11, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, 57, -93, -93, 57, 57, 57, 57, - 57, 112, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -93 + -93, -93, -93, 58, -93, -93, 58, 58, 58, 58, + 58, 58, 58, 58, 112, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -93 }, { 11, -94, -94, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, 57, -94, -94, 113, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -94 + -94, -94, -94, 58, -94, -94, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 113, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -94 }, { 11, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, 57, -95, -95, 57, 57, 57, 57, - 114, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -95 + -95, -95, -95, 58, -95, -95, 58, 58, 58, 58, + 58, 114, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -95 }, { 11, -96, -96, -96, -96, -96, -96, -96, -96, -96, - -96, -96, -96, 57, -96, -96, 57, 57, 115, 57, - 57, 57, 57, 57, 116, 57, 117, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -96 + -96, -96, -96, 58, -96, -96, 115, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -96 }, { 11, -97, -97, -97, -97, -97, -97, -97, -97, -97, - -97, -97, -97, 57, -97, -97, 57, 57, 57, 57, + -97, -97, -97, 58, -97, -97, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 118, - 57, 57, 57, 57, 57, 57, -97 + 116, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -97 }, { 11, -98, -98, -98, -98, -98, -98, -98, -98, -98, - -98, -98, -98, 57, -98, -98, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -98 + -98, -98, -98, 58, -98, -98, 58, 58, 117, 58, + 58, 58, 58, 58, 118, 58, 119, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -98 }, { 11, -99, -99, -99, -99, -99, -99, -99, -99, -99, - -99, -99, -99, 57, -99, -99, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -99 + -99, -99, -99, 58, -99, -99, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 120, + 58, 58, 58, 58, 58, 58, -99 }, { 11, -100, -100, -100, -100, -100, -100, -100, -100, -100, - -100, -100, -100, 57, -100, -100, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 119, 57, 57, - 57, 57, 57, 57, 57, 57, -100 + -100, -100, -100, 58, -100, -100, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -100 }, { 11, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, 57, -101, -101, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 120, 57, -101 + -101, -101, -101, 58, -101, -101, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -101 }, { 11, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, 57, -102, -102, 57, 57, 57, 57, + -102, -102, -102, 58, -102, -102, 58, 58, 58, 58, - 57, 57, 57, 57, 121, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -102 + 58, 58, 58, 58, 58, 58, 58, 121, 58, 58, + 58, 58, 58, 58, 58, 58, -102 }, { 11, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, 57, -103, -103, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 122, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -103 + -103, -103, -103, 58, -103, -103, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 122, 58, -103 }, { 11, -104, -104, -104, -104, -104, -104, -104, -104, -104, - -104, -104, -104, 57, -104, -104, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 123, 57, -104 + -104, -104, -104, 58, -104, -104, 58, 58, 58, 58, + 58, 58, 58, 58, 123, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -104 }, { 11, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, 57, -105, -105, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 124, 57, 57, 57, 57, -105 + -105, -105, -105, 58, -105, -105, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 124, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -105 }, { 11, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, 57, -106, -106, 57, 57, 57, 57, - 57, 57, 57, 57, 125, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -106 + -106, -106, -106, 58, -106, -106, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 125, 58, -106 }, { 11, -107, -107, -107, -107, -107, -107, -107, -107, -107, - -107, -107, -107, 57, -107, -107, 57, 57, 57, 57, + -107, -107, -107, 58, -107, -107, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 126, 57, 57, 57, -107 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 126, 58, 58, 58, 58, -107 }, { 11, -108, -108, -108, -108, -108, -108, -108, -108, -108, - -108, 85, 85, 85, -108, -108, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, -108 + -108, -108, -108, 58, -108, -108, 58, 58, 58, 58, + 58, 58, 58, 58, 127, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -108 }, { 11, -109, -109, -109, -109, -109, -109, -109, -109, -109, - -109, -109, -109, 57, -109, -109, 57, 57, 57, 57, - 127, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -109 + -109, -109, -109, 58, -109, -109, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 128, 58, 58, 58, -109 }, { 11, -110, -110, -110, -110, -110, -110, -110, -110, -110, - -110, -110, -110, 57, -110, -110, 57, 57, 128, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -110 + -110, 87, 87, 87, -110, -110, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, -110 }, { 11, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 57, -111, -111, 57, 57, 57, 57, - 129, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -111 + -111, -111, -111, 58, -111, -111, 58, 58, 58, 58, + 129, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -111 }, { 11, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, 57, -112, -112, 57, 57, 57, 57, + -112, -112, -112, 58, -112, -112, 58, 58, 130, 58, - 57, 57, 57, 57, 130, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -112 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -112 }, { 11, -113, -113, -113, -113, -113, -113, -113, -113, -113, - -113, -113, -113, 57, -113, -113, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 131, 57, -113 + -113, -113, -113, 58, -113, -113, 58, 58, 58, 58, + 131, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -113 }, { 11, -114, -114, -114, -114, -114, -114, -114, -114, -114, - -114, -114, -114, 57, -114, -114, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 132, 57, 57, - 57, 57, 57, 57, 57, 57, -114 + -114, -114, -114, 58, -114, -114, 58, 58, 58, 58, + 58, 58, 58, 58, 132, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -114 }, { 11, -115, -115, -115, -115, -115, -115, -115, -115, -115, - -115, -115, -115, 57, -115, -115, 57, 57, 57, 57, - 57, 57, 57, 133, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -115 + -115, -115, -115, 58, -115, -115, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 133, 58, -115 }, { 11, -116, -116, -116, -116, -116, -116, -116, -116, -116, - -116, -116, -116, 57, -116, -116, 57, 57, 57, 57, - 57, 134, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -116 + -116, -116, -116, 58, -116, -116, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 134, 58, 58, + 58, 58, 58, 58, 58, 58, -116 }, { 11, -117, -117, -117, -117, -117, -117, -117, -117, -117, - -117, -117, -117, 57, -117, -117, 57, 57, 57, 57, + -117, -117, -117, 58, -117, -117, 58, 58, 58, 58, - 135, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -117 + 58, 58, 58, 135, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -117 }, { 11, -118, -118, -118, -118, -118, -118, -118, -118, -118, - -118, -118, -118, 57, -118, -118, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -118 + -118, -118, -118, 58, -118, -118, 58, 58, 58, 58, + 58, 136, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -118 }, { 11, -119, -119, -119, -119, -119, -119, -119, -119, -119, - -119, -119, -119, 57, -119, -119, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 136, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -119 + -119, -119, -119, 58, -119, -119, 58, 58, 58, 58, + 137, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -119 }, { 11, -120, -120, -120, -120, -120, -120, -120, -120, -120, - -120, -120, -120, 57, -120, -120, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -120 + -120, -120, -120, 58, -120, -120, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -120 }, { 11, -121, -121, -121, -121, -121, -121, -121, -121, -121, - -121, -121, -121, 57, -121, -121, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 137, 57, - 57, 57, 57, 57, 57, 57, -121 + -121, -121, -121, 58, -121, -121, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 138, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -121 }, { 11, -122, -122, -122, -122, -122, -122, -122, -122, -122, - -122, -122, -122, 57, -122, -122, 57, 57, 57, 57, + -122, -122, -122, 58, -122, -122, 58, 58, 139, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 138, - 57, 57, 57, 57, 57, 57, -122 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -122 }, { 11, -123, -123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, 57, -123, -123, 57, 57, 57, 57, - 57, 57, 57, 57, 139, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -123 + -123, -123, -123, 58, -123, -123, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 140, 58, + 58, 58, 58, 58, 58, 58, -123 }, { 11, -124, -124, -124, -124, -124, -124, -124, -124, -124, - -124, -124, -124, 57, -124, -124, 57, 57, 140, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -124 + -124, -124, -124, 58, -124, -124, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 141, + 58, 58, 58, 58, 58, 58, -124 }, { 11, -125, -125, -125, -125, -125, -125, -125, -125, -125, - -125, -125, -125, 57, -125, -125, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 141, 57, 57, - 57, 57, 57, 57, 57, 57, -125 + -125, -125, -125, 58, -125, -125, 58, 58, 58, 58, + 58, 58, 58, 58, 142, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -125 }, { 11, -126, -126, -126, -126, -126, -126, -126, -126, -126, - -126, -126, -126, 57, -126, -126, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 142, 57, 57, -126 + -126, -126, -126, 58, -126, -126, 58, 58, 143, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -126 }, { 11, -127, -127, -127, -127, -127, -127, -127, -127, -127, - -127, -127, -127, 57, -127, -127, 143, 57, 57, 57, + -127, -127, -127, 58, -127, -127, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -127 + 58, 58, 58, 58, 58, 58, 58, 144, 58, 58, + 58, 58, 58, 58, 58, 58, -127 }, { 11, -128, -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, 57, -128, -128, 57, 57, 57, 57, - 144, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -128 + -128, -128, -128, 58, -128, -128, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 145, 58, 58, -128 }, { 11, -129, -129, -129, -129, -129, -129, -129, -129, -129, - -129, -129, -129, 57, -129, -129, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 145, 57, 57, - 57, 57, 57, 57, 57, 57, -129 + -129, -129, -129, 58, -129, -129, 146, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -129 }, { 11, -130, -130, -130, -130, -130, -130, -130, -130, -130, - -130, -130, -130, 57, -130, -130, 57, 57, 57, 57, - 57, 57, 146, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -130 + -130, -130, -130, 58, -130, -130, 58, 58, 58, 58, + 147, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -130 }, { 11, -131, -131, -131, -131, -131, -131, -131, -131, -131, - -131, -131, -131, 57, -131, -131, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 147, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -131 + -131, -131, -131, 58, -131, -131, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 148, 58, 58, + 58, 58, 58, 58, 58, 58, -131 }, { 11, -132, -132, -132, -132, -132, -132, -132, -132, -132, - -132, -132, -132, 57, -132, -132, 57, 57, 57, 148, + -132, -132, -132, 58, -132, -132, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -132 + 58, 58, 149, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -132 }, { 11, -133, -133, -133, -133, -133, -133, -133, -133, -133, - -133, -133, -133, 57, -133, -133, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 149, 57, - 57, 57, 57, 57, 57, 57, -133 + -133, -133, -133, 58, -133, -133, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 150, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -133 }, { 11, -134, -134, -134, -134, -134, -134, -134, -134, -134, - -134, -134, -134, 57, -134, -134, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -134 + -134, -134, -134, 58, -134, -134, 58, 58, 58, 151, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -134 }, { 11, -135, -135, -135, -135, -135, -135, -135, -135, -135, - -135, -135, -135, 57, -135, -135, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 150, 57, 57, - 57, 57, 57, 57, 57, 57, -135 + -135, -135, -135, 58, -135, -135, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 152, 58, + 58, 58, 58, 58, 58, 58, -135 }, { 11, -136, -136, -136, -136, -136, -136, -136, -136, -136, - -136, -136, -136, 57, -136, -136, 57, 57, 57, 57, - 151, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -136 + -136, -136, -136, 58, -136, -136, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -136 }, { 11, -137, -137, -137, -137, -137, -137, -137, -137, -137, - -137, -137, -137, 57, -137, -137, 57, 57, 57, 57, + -137, -137, -137, 58, -137, -137, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 152, 57, 57, - 57, 57, 57, 57, 57, 57, -137 + 58, 58, 58, 58, 58, 58, 58, 153, 58, 58, + 58, 58, 58, 58, 58, 58, -137 }, { 11, -138, -138, -138, -138, -138, -138, -138, -138, -138, - -138, -138, -138, 57, -138, -138, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 153, 57, 57, -138 + -138, -138, -138, 58, -138, -138, 58, 58, 58, 58, + 154, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -138 }, { 11, -139, -139, -139, -139, -139, -139, -139, -139, -139, - -139, -139, -139, 57, -139, -139, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 154, 57, 57, 57, 57, -139 + -139, -139, -139, 58, -139, -139, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 155, 58, + 58, 58, 58, 58, 58, 58, -139 }, { 11, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, 57, -140, -140, 57, 57, 57, 57, - 155, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -140 + -140, -140, -140, 58, -140, -140, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 156, 58, 58, + 58, 58, 58, 58, 58, 58, -140 }, { 11, -141, -141, -141, -141, -141, -141, -141, -141, -141, - -141, -141, -141, 57, -141, -141, 57, 57, 57, 57, - 57, 57, 156, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -141 + -141, -141, -141, 58, -141, -141, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 157, 58, 58, -141 }, { 11, -142, -142, -142, -142, -142, -142, -142, -142, -142, - -142, -142, -142, 57, -142, -142, 157, 57, 57, 57, + -142, -142, -142, 58, -142, -142, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -142 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 158, 58, 58, 58, 58, -142 }, { 11, -143, -143, -143, -143, -143, -143, -143, -143, -143, - -143, -143, -143, 57, -143, -143, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 158, 57, 57, - 57, 57, 57, 57, 57, 57, -143 + -143, -143, -143, 58, -143, -143, 58, 58, 58, 58, + 159, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -143 }, { 11, -144, -144, -144, -144, -144, -144, -144, -144, -144, - -144, -144, -144, 57, -144, -144, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -144 + -144, -144, -144, 58, -144, -144, 58, 58, 58, 58, + 58, 58, 160, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -144 }, { 11, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -145, -145, 57, -145, -145, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 159, 57, 57, -145 + -145, -145, -145, 58, -145, -145, 161, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -145 }, { 11, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, -146, 57, -146, -146, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -146 + -146, -146, -146, 58, -146, -146, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 162, 58, 58, + 58, 58, 58, 58, 58, 58, -146 }, { 11, -147, -147, -147, -147, -147, -147, -147, -147, -147, - -147, -147, -147, 57, -147, -147, 57, 57, 57, 57, + -147, -147, -147, 58, -147, -147, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 160, 57, 57, -147 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -147 }, { 11, -148, -148, -148, -148, -148, -148, -148, -148, -148, - -148, -148, -148, 57, -148, -148, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 161, 57, 57, 57, -148 + -148, -148, -148, 58, -148, -148, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 163, 58, 58, -148 }, { 11, -149, -149, -149, -149, -149, -149, -149, -149, -149, - -149, -149, -149, 57, -149, -149, 57, 57, 57, 57, - 57, 57, 57, 57, 162, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -149 + -149, -149, -149, 58, -149, -149, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -149 }, { 11, -150, -150, -150, -150, -150, -150, -150, -150, -150, - -150, -150, -150, 57, -150, -150, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 163, 57, -150 + -150, -150, -150, 58, -150, -150, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 164, 58, 58, -150 }, { 11, -151, -151, -151, -151, -151, -151, -151, -151, -151, - -151, -151, -151, 57, -151, -151, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 164, 57, 57, - 57, 57, 57, 57, 57, 57, -151 + -151, -151, -151, 58, -151, -151, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 165, 58, 58, 58, -151 }, { 11, -152, -152, -152, -152, -152, -152, -152, -152, -152, - -152, -152, -152, 57, -152, -152, 165, 57, 57, 57, + -152, -152, -152, 58, -152, -152, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -152 + 58, 58, 58, 58, 166, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -152 }, { 11, -153, -153, -153, -153, -153, -153, -153, -153, -153, - -153, -153, -153, 57, -153, -153, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -153 + -153, -153, -153, 58, -153, -153, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 167, 58, -153 }, { 11, -154, -154, -154, -154, -154, -154, -154, -154, -154, - -154, -154, -154, 57, -154, -154, 57, 57, 57, 57, - 166, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -154 + -154, -154, -154, 58, -154, -154, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 168, 58, 58, + 58, 58, 58, 58, 58, 58, -154 }, { 11, -155, -155, -155, -155, -155, -155, -155, -155, -155, - -155, -155, -155, 57, -155, -155, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -155 + -155, -155, -155, 58, -155, -155, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 169, 58, 58, + 58, 58, 58, 58, 58, 58, -155 }, { 11, -156, -156, -156, -156, -156, -156, -156, -156, -156, - -156, -156, -156, 57, -156, -156, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -156 + -156, -156, -156, 58, -156, -156, 170, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -156 }, { 11, -157, -157, -157, -157, -157, -157, -157, -157, -157, - -157, -157, -157, 57, -157, -157, 57, 57, 57, 57, + -157, -157, -157, 58, -157, -157, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 167, 57, 57, -157 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -157 }, { 11, -158, -158, -158, -158, -158, -158, -158, -158, -158, - -158, -158, -158, 57, -158, -158, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -158 + -158, -158, -158, 58, -158, -158, 58, 58, 58, 58, + 171, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -158 }, { 11, -159, -159, -159, -159, -159, -159, -159, -159, -159, - -159, -159, -159, 57, -159, -159, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -159 + -159, -159, -159, 58, -159, -159, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -159 }, { 11, -160, -160, -160, -160, -160, -160, -160, -160, -160, - -160, -160, -160, 57, -160, -160, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -160 + -160, -160, -160, 58, -160, -160, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -160 }, { 11, -161, -161, -161, -161, -161, -161, -161, -161, -161, - -161, -161, -161, 57, -161, -161, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -161 + -161, -161, -161, 58, -161, -161, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 172, 58, 58, -161 }, { 11, -162, -162, -162, -162, -162, -162, -162, -162, -162, - -162, -162, -162, 57, -162, -162, 57, 57, 168, 57, + -162, -162, -162, 58, -162, -162, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -162 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -162 }, { 11, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, 57, -163, -163, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -163 + -163, -163, -163, 58, -163, -163, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -163 }, { 11, -164, -164, -164, -164, -164, -164, -164, -164, -164, - -164, -164, -164, 57, -164, -164, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 169, 57, -164 + -164, -164, -164, 58, -164, -164, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -164 }, { 11, -165, -165, -165, -165, -165, -165, -165, -165, -165, - -165, -165, -165, 57, -165, -165, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 170, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -165 + -165, -165, -165, 58, -165, -165, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -165 }, { 11, -166, -166, -166, -166, -166, -166, -166, -166, -166, - -166, -166, -166, 57, -166, -166, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 171, 57, 57, 57, -166 + -166, -166, -166, 58, -166, -166, 58, 58, 173, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -166 }, { 11, -167, -167, -167, -167, -167, -167, -167, -167, -167, - -167, -167, -167, 57, -167, -167, 57, 57, 57, 57, + -167, -167, -167, 58, -167, -167, 58, 58, 58, 58, - 172, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -167 + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -167 }, { 11, -168, -168, -168, -168, -168, -168, -168, -168, -168, - -168, -168, -168, 57, -168, -168, 57, 57, 57, 57, - 173, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -168 + -168, -168, -168, 58, -168, -168, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 174, 58, -168 }, { 11, -169, -169, -169, -169, -169, -169, -169, -169, -169, - -169, -169, -169, 57, -169, -169, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -169 + -169, -169, -169, 58, -169, -169, 58, 58, 58, 58, + 58, 175, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -169 }, { 11, -170, -170, -170, -170, -170, -170, -170, -170, -170, - -170, -170, -170, 57, -170, -170, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -170 + -170, -170, -170, 58, -170, -170, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 176, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -170 }, { 11, -171, -171, -171, -171, -171, -171, -171, -171, -171, - -171, -171, -171, 57, -171, -171, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -171 + -171, -171, -171, 58, -171, -171, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 177, 58, 58, 58, -171 }, { 11, -172, -172, -172, -172, -172, -172, -172, -172, -172, - -172, -172, -172, 57, -172, -172, 57, 57, 57, 57, + -172, -172, -172, 58, -172, -172, 58, 58, 58, 58, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -172 + 178, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -172 }, { 11, -173, -173, -173, -173, -173, -173, -173, -173, -173, - -173, -173, -173, 57, -173, -173, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, -173 + -173, -173, -173, 58, -173, -173, 58, 58, 58, 58, + 179, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -173 + }, + + { + 11, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, 58, -174, -174, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -174 + + }, + + { + 11, -175, -175, -175, -175, -175, -175, -175, -175, -175, + -175, -175, -175, 58, -175, -175, 58, 58, 58, 58, + 58, 58, 58, 58, 180, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -175 + }, + + { + 11, -176, -176, -176, -176, -176, -176, -176, -176, -176, + -176, -176, -176, 58, -176, -176, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -176 + }, + + { + 11, -177, -177, -177, -177, -177, -177, -177, -177, -177, + -177, -177, -177, 58, -177, -177, 58, 58, 58, 58, + + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -177 + }, + + { + 11, -178, -178, -178, -178, -178, -178, -178, -178, -178, + -178, -178, -178, 58, -178, -178, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -178 + }, + + { + 11, -179, -179, -179, -179, -179, -179, -179, -179, -179, + -179, -179, -179, 58, -179, -179, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -179 + + }, + + { + 11, -180, -180, -180, -180, -180, -180, -180, -180, -180, + -180, -180, -180, 58, -180, -180, 58, 58, 58, 58, + 58, 58, 181, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -180 + }, + + { + 11, -181, -181, -181, -181, -181, -181, -181, -181, -181, + -181, -181, -181, 58, -181, -181, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, -181 }, } ; @@ -1595,29 +1654,30 @@ static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 56 -#define YY_END_OF_BUFFER 57 -static yyconst short int yy_accept[174] = +#define YY_NUM_RULES 58 +#define YY_END_OF_BUFFER 59 +static yyconst short int yy_accept[182] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 57, 5, 4, 3, 2, 29, 30, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 55, 52, 54, 47, 51, 50, 49, 45, 41, 35, - 40, 45, 33, 34, 43, 43, 36, 45, 43, 43, - 45, 4, 3, 2, 2, 1, 28, 28, 28, 28, - 28, 28, 28, 15, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 55, 52, 54, 53, 47, 46, 49, - 48, 37, 31, 43, 43, 44, 38, 39, 32, 28, - 28, 28, 28, 28, 28, 28, 28, 26, 25, 28, - - 28, 28, 28, 28, 28, 28, 28, 42, 23, 28, - 28, 28, 28, 28, 28, 28, 28, 14, 28, 7, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 16, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 10, 28, 13, 28, 28, 28, 28, - 28, 28, 21, 28, 9, 27, 28, 24, 12, 20, - 17, 28, 8, 28, 28, 28, 28, 28, 6, 19, - 18, 22, 11 + 59, 5, 4, 3, 2, 30, 31, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 57, 54, 56, 49, 53, 52, 51, 47, 42, 36, + 41, 45, 47, 34, 35, 44, 44, 37, 47, 44, + 44, 47, 4, 3, 2, 2, 1, 29, 29, 29, + 29, 29, 29, 29, 16, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 57, 54, 56, 55, 49, 48, + 51, 50, 38, 45, 32, 44, 44, 46, 39, 40, + 33, 29, 29, 29, 29, 29, 29, 29, 29, 27, + + 26, 29, 29, 29, 29, 29, 29, 29, 29, 43, + 24, 29, 29, 29, 29, 29, 29, 29, 29, 15, + 29, 7, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 17, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 10, 29, 13, 29, + 29, 29, 29, 29, 29, 29, 22, 29, 9, 28, + 29, 25, 12, 21, 18, 29, 8, 29, 29, 29, + 29, 29, 29, 6, 29, 20, 19, 23, 11, 29, + 14 } ; static yyconst int yy_ec[256] = @@ -1993,43 +2053,43 @@ BEGIN(PARAM); return T_CONFIG; YY_BREAK case 14: YY_RULE_SETUP -BEGIN(PARAM); return T_HELP; +BEGIN(PARAM); return T_MENUCONFIG; YY_BREAK case 15: YY_RULE_SETUP -BEGIN(PARAM); return T_IF; +BEGIN(PARAM); return T_HELP; YY_BREAK case 16: YY_RULE_SETUP -BEGIN(PARAM); return T_ENDIF; +BEGIN(PARAM); return T_IF; YY_BREAK case 17: YY_RULE_SETUP -BEGIN(PARAM); return T_DEPENDS; +BEGIN(PARAM); return T_ENDIF; YY_BREAK case 18: YY_RULE_SETUP -BEGIN(PARAM); return T_REQUIRES; +BEGIN(PARAM); return T_DEPENDS; YY_BREAK case 19: YY_RULE_SETUP -BEGIN(PARAM); return T_OPTIONAL; +BEGIN(PARAM); return T_REQUIRES; YY_BREAK case 20: YY_RULE_SETUP -BEGIN(PARAM); return T_DEFAULT; +BEGIN(PARAM); return T_OPTIONAL; YY_BREAK case 21: YY_RULE_SETUP -BEGIN(PARAM); return T_PROMPT; +BEGIN(PARAM); return T_DEFAULT; YY_BREAK case 22: YY_RULE_SETUP -BEGIN(PARAM); return T_TRISTATE; +BEGIN(PARAM); return T_PROMPT; YY_BREAK case 23: YY_RULE_SETUP -BEGIN(PARAM); return T_BOOLEAN; +BEGIN(PARAM); return T_TRISTATE; YY_BREAK case 24: YY_RULE_SETUP @@ -2037,71 +2097,75 @@ BEGIN(PARAM); return T_BOOLEAN; YY_BREAK case 25: YY_RULE_SETUP -BEGIN(PARAM); return T_INT; +BEGIN(PARAM); return T_BOOLEAN; YY_BREAK case 26: YY_RULE_SETUP -BEGIN(PARAM); return T_HEX; +BEGIN(PARAM); return T_INT; YY_BREAK case 27: YY_RULE_SETUP -BEGIN(PARAM); return T_STRING; +BEGIN(PARAM); return T_HEX; YY_BREAK case 28: YY_RULE_SETUP +BEGIN(PARAM); return T_STRING; + YY_BREAK +case 29: +YY_RULE_SETUP { alloc_string(yytext, yyleng); zconflval.string = text; return T_WORD; } YY_BREAK -case 29: +case 30: YY_RULE_SETUP YY_BREAK -case 30: +case 31: YY_RULE_SETUP current_file->lineno++; BEGIN(INITIAL); YY_BREAK -case 31: +case 32: YY_RULE_SETUP return T_AND; YY_BREAK -case 32: +case 33: YY_RULE_SETUP return T_OR; YY_BREAK -case 33: +case 34: YY_RULE_SETUP return T_OPEN_PAREN; YY_BREAK -case 34: +case 35: YY_RULE_SETUP return T_CLOSE_PAREN; YY_BREAK -case 35: +case 36: YY_RULE_SETUP return T_NOT; YY_BREAK -case 36: +case 37: YY_RULE_SETUP return T_EQUAL; YY_BREAK -case 37: +case 38: YY_RULE_SETUP return T_UNEQUAL; YY_BREAK -case 38: +case 39: YY_RULE_SETUP return T_IF; YY_BREAK -case 39: +case 40: YY_RULE_SETUP return T_ON; YY_BREAK -case 40: +case 41: YY_RULE_SETUP { str = yytext[0]; @@ -2109,15 +2173,15 @@ YY_RULE_SETUP BEGIN(STRING); } YY_BREAK -case 41: +case 42: YY_RULE_SETUP BEGIN(INITIAL); current_file->lineno++; return T_EOL; YY_BREAK -case 42: +case 43: YY_RULE_SETUP /* ignore */ YY_BREAK -case 43: +case 44: YY_RULE_SETUP { alloc_string(yytext, yyleng); @@ -2125,11 +2189,15 @@ YY_RULE_SETUP return T_WORD; } YY_BREAK -case 44: +case 45: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 46: YY_RULE_SETUP current_file->lineno++; YY_BREAK -case 45: +case 47: YY_RULE_SETUP YY_BREAK @@ -2140,7 +2208,7 @@ case YY_STATE_EOF(PARAM): YY_BREAK -case 46: +case 48: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ @@ -2151,13 +2219,13 @@ YY_RULE_SETUP return T_WORD_QUOTE; } YY_BREAK -case 47: +case 49: YY_RULE_SETUP { append_string(yytext, yyleng); } YY_BREAK -case 48: +case 50: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ @@ -2168,13 +2236,13 @@ YY_RULE_SETUP return T_WORD_QUOTE; } YY_BREAK -case 49: +case 51: YY_RULE_SETUP { append_string(yytext + 1, yyleng - 1); } YY_BREAK -case 50: +case 52: YY_RULE_SETUP { if (str == yytext[0]) { @@ -2185,7 +2253,7 @@ YY_RULE_SETUP append_string(yytext, 1); } YY_BREAK -case 51: +case 53: YY_RULE_SETUP { printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); @@ -2201,7 +2269,7 @@ case YY_STATE_EOF(STRING): YY_BREAK -case 52: +case 54: YY_RULE_SETUP { ts = 0; @@ -2227,9 +2295,9 @@ YY_RULE_SETUP } YY_BREAK -case 53: +case 55: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ -yy_c_buf_p = yy_cp = yy_bp + 1; +yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP { @@ -2238,14 +2306,14 @@ YY_RULE_SETUP return T_HELPTEXT; } YY_BREAK -case 54: +case 56: YY_RULE_SETUP { current_file->lineno++; append_string("\n", 1); } YY_BREAK -case 55: +case 57: YY_RULE_SETUP { append_string(yytext, yyleng); @@ -2271,7 +2339,7 @@ case YY_STATE_EOF(COMMAND): yyterminate(); } YY_BREAK -case 56: +case 58: YY_RULE_SETUP YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 48a2c02334b0..4cca5835fb13 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -302,11 +302,8 @@ static void build_conf(struct menu *menu) cprint1("%s%*c%s", menu->data ? "-->" : "++>", indent + 1, ' ', prompt); - } else { - if (menu->parent != &rootmenu) - cprint1(" %*c", indent + 1, ' '); - cprint1("%s --->", prompt); - } + } else + cprint1(" %*c%s --->", indent + 1, ' ', prompt); cprint_done(); if (single_menu_mode && menu->data) @@ -373,6 +370,11 @@ static void build_conf(struct menu *menu) } cprint_done(); } else { + if (menu == current_menu) { + cprint(":%p", menu); + cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); + goto conf_childs; + } child_count++; val = sym_get_tristate_value(sym); if (sym_is_choice_value(sym) && val == yes) { @@ -407,6 +409,11 @@ static void build_conf(struct menu *menu) } cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), sym_has_value(sym) ? "" : " (NEW)"); + if (menu->prompt->type == P_MENU) { + cprint1(" --->"); + cprint_done(); + return; + } cprint_done(); } @@ -445,9 +452,9 @@ static void conf(struct menu *menu) cprint(":"); cprint("--- "); cprint("L"); - cprint("Load an Alternate Configuration File"); + cprint(" Load an Alternate Configuration File"); cprint("S"); - cprint("Save Configuration to an Alternate File"); + cprint(" Save Configuration to an Alternate File"); } stat = exec_conf(); if (stat < 0) @@ -484,6 +491,8 @@ static void conf(struct menu *menu) case 't': if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu); break; case 's': conf_string(submenu); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 24be0ec65f3b..81d764e7230d 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -54,9 +54,34 @@ void menu_end_menu(void) current_menu = current_menu->parent; } +struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + void menu_add_dep(struct expr *dep) { - current_entry->dep = expr_alloc_and(current_entry->dep, dep); + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); } void menu_set_type(int type) @@ -96,7 +121,7 @@ struct property *menu_add_prop(int token, char *prompt, struct symbol *def, stru prop->menu = current_entry; prop->text = prompt; prop->def = def; - E_EXPR(prop->visible) = dep; + E_EXPR(prop->visible) = menu_check_dep(dep); if (prompt) current_entry->prompt = prop; @@ -169,8 +194,8 @@ void menu_finalize(struct menu *parent) } for (menu = parent->list; menu; menu = menu->next) menu_finalize(menu); - } else if (sym && parent->prompt) { - basedep = E_EXPR(parent->prompt->visible); + } else if (sym) { + basedep = parent->prompt ? E_EXPR(parent->prompt->visible) : NULL; basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); basedep = expr_eliminate_dups(expr_transform(basedep)); last_menu = NULL; diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index bed541dc6b1f..df1577f4b6d7 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -42,15 +42,12 @@ static QSettings *configSettings; * menu: entry to be updated */ template <class P> -static void updateMenuList(P* parent, struct menu* menu) +void ConfigList::updateMenuList(P* parent, struct menu* menu) { struct menu* child; - ConfigList* list = parent->listView(); ConfigItem* item; ConfigItem* last; bool visible; - bool showAll = list->showAll; - enum listMode mode = list->mode; enum prop_type type; if (!menu) { @@ -59,7 +56,9 @@ static void updateMenuList(P* parent, struct menu* menu) return; } - last = 0; + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; for (child = menu->list; child; child = child->next) { item = last ? last->nextSibling() : parent->firstChild(); type = child->prompt ? child->prompt->type : P_UNKNOWN; @@ -81,16 +80,8 @@ static void updateMenuList(P* parent, struct menu* menu) if (showAll || visible) { if (!item || item->menu != child) item = new ConfigItem(parent, last, child, visible); - else { - item->visible = visible; - if (item->updateNeeded()) { - ConfigItem* i = (ConfigItem*)child->data; - for (; i; i = i->nextItem) { - i->updateMenu(); - } - } else if (list->updateAll) - item->updateMenu(); - } + else + item->testUpdateMenu(visible); if (mode == fullMode || mode == menuMode || (type != P_MENU && type != P_ROOTMENU)) @@ -100,7 +91,7 @@ static void updateMenuList(P* parent, struct menu* menu) last = item; continue; } - hide: + hide: if (item && item->menu == child) { last = parent->firstChild(); if (last == item) @@ -131,24 +122,46 @@ void ConfigItem::updateMenu(void) { ConfigList* list; struct symbol* sym; + struct property *prop; QString prompt; int type; - enum prop_type ptype; tristate expr; list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } sym = menu->sym; - if (!sym) { - setText(promptColIdx, menu_get_prompt(menu)); - ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; - if ((ptype == P_ROOTMENU || ptype == P_MENU) && - (list->mode == singleMode || list->mode == symbolMode)) + prop = menu->prompt; + prompt = menu_get_prompt(menu); + + if (prop) switch (prop->type) { + case P_MENU: + case P_ROOTMENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; setPixmap(promptColIdx, list->menuPix); - else + } else { + if (sym) + break; setPixmap(promptColIdx, 0); - return; + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, 0); + goto set_prompt; + default: + ; } + if (!sym) + goto set_prompt; setText(nameColIdx, sym->name); @@ -158,7 +171,6 @@ void ConfigItem::updateMenu(void) case S_TRISTATE: char ch; - prompt = menu_get_prompt(menu); if (!sym_is_changable(sym) && !list->showAll) { setText(noColIdx, 0); setText(modColIdx, 0); @@ -211,26 +223,33 @@ void ConfigItem::updateMenu(void) #endif setText(dataColIdx, data); if (type == S_STRING) - prompt.sprintf("%s: %s", menu_get_prompt(menu), data); + prompt.sprintf("%s: %s", prompt.latin1(), data); else - prompt.sprintf("(%s) %s", data, menu_get_prompt(menu)); + prompt.sprintf("(%s) %s", data, prompt.latin1()); break; } if (!sym_has_value(sym) && visible) prompt += " (NEW)"; +set_prompt: setText(promptColIdx, prompt); } -bool ConfigItem::updateNeeded(void) +void ConfigItem::testUpdateMenu(bool v) { - struct symbol* sym = menu->sym; - if (sym) - sym_calc_value(sym); + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ menu->flags &= ~MENU_CHANGED; - return true; - } - return false; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); } void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) @@ -251,14 +270,15 @@ void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int w */ void ConfigItem::init(void) { - ConfigList* list = listView(); - nextItem = (ConfigItem*)menu->data; - menu->data = this; + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; - if (list->mode != fullMode) - setOpen(TRUE); - if (menu->sym) + if (list->mode != fullMode) + setOpen(TRUE); sym_calc_value(menu->sym); + } updateMenu(); } @@ -267,11 +287,13 @@ void ConfigItem::init(void) */ ConfigItem::~ConfigItem(void) { - ConfigItem** ip = &(ConfigItem*)menu->data; - for (; *ip; ip = &(*ip)->nextItem) { - if (*ip == this) { - *ip = nextItem; - break; + if (menu) { + ConfigItem** ip = &(ConfigItem*)menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } } } } @@ -310,7 +332,8 @@ ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv) : Parent(p), cview(cv), updateAll(false), symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), - choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), menuPix(xpm_menu), menuInvPix(xpm_menu_inv), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), showAll(false), showName(false), showRange(false), showData(false), rootEntry(0) { @@ -366,6 +389,8 @@ void ConfigList::updateSelection(void) cview->setHelp(item); menu = item->menu; + if (!menu) + return; type = menu->prompt ? menu->prompt->type : P_UNKNOWN; if (mode == menuMode && (type == P_MENU || type == P_ROOTMENU)) emit menuSelected(menu); @@ -373,7 +398,27 @@ void ConfigList::updateSelection(void) void ConfigList::updateList(ConfigItem* item) { - (void)item; // unused so far + ConfigItem* last = 0; + + if (!rootEntry) + goto update; + + if ((mode == singleMode || mode == symbolMode) && rootEntry != &rootmenu) { + item = firstChild(); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if (mode == singleMode && rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + + updateMenuList(item, rootEntry); + triggerUpdate(); + return; + } +update: updateMenuList(this, rootEntry); triggerUpdate(); } @@ -392,7 +437,7 @@ void ConfigList::setValue(ConfigItem* item, tristate val) int type; tristate oldval; - sym = item->menu->sym; + sym = item->menu ? item->menu->sym : 0; if (!sym) return; @@ -418,6 +463,8 @@ void ConfigList::changeValue(ConfigItem* item) int type, oldexpr, newexpr; menu = item->menu; + if (!menu) + return; sym = menu->sym; if (!sym) { if (item->menu->list) @@ -511,7 +558,13 @@ void ConfigList::keyPressEvent(QKeyEvent* ev) switch (ev->key()) { case Key_Return: case Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } menu = item->menu; + if (!menu) + break; type = menu->prompt ? menu->prompt->type : P_UNKNOWN; if ((type == P_MENU || type == P_ROOTMENU) && mode != fullMode) { emit menuSelected(menu); @@ -564,7 +617,11 @@ void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) int off = header()->sectionPos(0) + itemMargin() + treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); if (x >= off && x < off + pm->width()) { - if (menu->sym) + if (item->goParent) + emit parentSelected(); + else if (!menu) + break; + else if (menu->sym) changeValue(item); else emit menuSelected(menu); @@ -606,7 +663,13 @@ void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) if (!item) goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } menu = item->menu; + if (!menu) + goto skip; ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; if ((ptype == P_ROOTMENU || ptype == P_MENU) && (mode == singleMode || mode == symbolMode)) @@ -677,7 +740,6 @@ void ConfigView::updateListAll(void) */ ConfigMainWindow::ConfigMainWindow(void) { - ConfigView* view; QMenuBar* menu; QSplitter* split1; QSplitter* split2; @@ -707,15 +769,15 @@ ConfigMainWindow::ConfigMainWindow(void) split1->setOrientation(QSplitter::Horizontal); setCentralWidget(split1); - view = new ConfigView(split1, this); - menuList = view->list; + menuView = new ConfigView(split1, this); + menuList = menuView->list; split2 = new QSplitter(split1); split2->setOrientation(QSplitter::Vertical); // create config tree - view = new ConfigView(split2, this); - configList = view->list; + configView = new ConfigView(split2, this); + configList = configView->list; helpText = new QTextView(split2); helpText->setTextFormat(Qt::RichText); @@ -864,89 +926,87 @@ static void expr_print_help(void *data, const char *str) void ConfigMainWindow::setHelp(QListViewItem* item) { struct symbol* sym; - struct menu* menu; + struct menu* menu = 0; configList->parent()->lineEdit->hide(); - if (item) { - QString head, debug, help; + if (item) menu = ((ConfigItem*)item)->menu; - sym = menu->sym; - if (sym) { - if (menu->prompt) { - head += "<big><b>"; - head += print_filter(menu->prompt->text); - head += "</b></big>"; - if (sym->name) { - head += " ("; - head += print_filter(sym->name); - head += ")"; - } - } else if (sym->name) { - head += "<big><b>"; + if (!menu) { + helpText->setText(NULL); + return; + } + + QString head, debug, help; + menu = ((ConfigItem*)item)->menu; + sym = menu->sym; + if (sym) { + if (menu->prompt) { + head += "<big><b>"; + head += print_filter(menu->prompt->text); + head += "</b></big>"; + if (sym->name) { + head += " ("; head += print_filter(sym->name); - head += "</b></big>"; + head += ")"; } - head += "<br><br>"; - - if (showDebug) { - debug += "type: "; - debug += print_filter(sym_type_name(sym->type)); - debug += "<br>"; - for (struct property *prop = sym->prop; prop; prop = prop->next) { - switch (prop->type) { - case P_PROMPT: - debug += "prompt: "; - debug += print_filter(prop->text); - debug += "<br>"; - if (prop->visible.expr) { - debug += " dep: "; - expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); - debug += "<br>"; - } - break; - case P_DEFAULT: - debug += "default: "; - if (sym_is_choice(sym)) - debug += print_filter(prop->def->name); - else { - sym_calc_value(prop->def); - debug += print_filter(sym_get_string_value(prop->def)); - } + } else if (sym->name) { + head += "<big><b>"; + head += print_filter(sym->name); + head += "</b></big>"; + } + head += "<br><br>"; + + if (showDebug) { + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + debug += "<br>"; + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + debug += "prompt: "; + debug += print_filter(prop->text); + debug += "<br>"; + if (prop->visible.expr) { + debug += " dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); debug += "<br>"; - if (prop->visible.expr) { - debug += " dep: "; - expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); - debug += "<br>"; - } - break; - case P_CHOICE: - break; - default: - debug += "unknown property: "; - debug += prop_get_type_name(prop->type); + } + break; + case P_DEFAULT: + debug += "default: "; + debug += print_filter(prop->def->name); + debug += "<br>"; + if (prop->visible.expr) { + debug += " dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); debug += "<br>"; } + break; + case P_CHOICE: + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "<br>"; } - debug += "<br>"; } + debug += "<br>"; + } - help = print_filter(sym->help); - } else if (menu->prompt) { - head += "<big><b>"; - head += print_filter(menu->prompt->text); - head += "</b></big><br><br>"; - if (showDebug) { - if (menu->prompt->visible.expr) { - debug += " dep: "; - expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); - debug += "<br>"; - } + help = print_filter(sym->help); + } else if (menu->prompt) { + head += "<big><b>"; + head += print_filter(menu->prompt->text); + head += "</b></big><br><br>"; + if (showDebug) { + if (menu->prompt->visible.expr) { + debug += " dep: "; + expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "<br>"; } } - helpText->setText(head + debug + help); - return; } - helpText->setText(NULL); + helpText->setText(head + debug + help); } void ConfigMainWindow::loadConfig(void) @@ -1010,7 +1070,7 @@ void ConfigMainWindow::goBack(void) void ConfigMainWindow::showSingleView(void) { - menuList->hide(); + menuView->hide(); menuList->setRootMenu(0); configList->mode = singleMode; if (configList->rootEntry == &rootmenu) @@ -1032,14 +1092,14 @@ void ConfigMainWindow::showSplitView(void) configApp->processEvents(); menuList->mode = menuMode; menuList->setRootMenu(&rootmenu); - menuList->show(); menuList->setAllOpen(TRUE); + menuView->show(); menuList->setFocus(); } void ConfigMainWindow::showFullView(void) { - menuList->hide(); + menuView->hide(); menuList->setRootMenu(0); configList->mode = fullMode; if (configList->rootEntry == &rootmenu) diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 6f096b4e8d40..6ed5a0ceb90f 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -101,10 +101,14 @@ public: void setAllOpen(bool open); void setParentMenu(void); + template <class P> + void ConfigList::updateMenuList(P*, struct menu*); + bool updateAll; QPixmap symbolYesPix, symbolModPix, symbolNoPix; - QPixmap choiceYesPix, choiceNoPix, menuPix, menuInvPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix; bool showAll, showName, showRange, showData; enum listMode mode; @@ -121,12 +125,17 @@ class ConfigItem : public QListViewItem { typedef class QListViewItem Parent; public: ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v) - : Parent(parent, after), menu(m), visible(v) + : Parent(parent, after), menu(m), visible(v), goParent(false) { init(); } ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) - : Parent(parent, after), menu(m), visible(v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(QListView *parent, ConfigItem *after, bool v) + : Parent(parent, after), menu(0), visible(v), goParent(true) { init(); } @@ -136,7 +145,7 @@ public: void okRename(int col); #endif void updateMenu(void); - bool updateNeeded(void); + void testUpdateMenu(bool v); ConfigList* listView() const { return (ConfigList*)Parent::listView(); @@ -170,6 +179,7 @@ public: ConfigItem* nextItem; struct menu *menu; bool visible; + bool goParent; }; class ConfigLineEdit : public QLineEdit { @@ -216,7 +226,9 @@ public slots: protected: void closeEvent(QCloseEvent *e); + ConfigView *menuView; ConfigList *menuList; + ConfigView *configView; ConfigList *configList; QTextView *helpText; QToolBar *toolBar; diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 845d8a37827b..7fa7825f3759 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -160,6 +160,9 @@ void sym_calc_value(struct symbol *sym) struct symbol *def_sym; struct expr *e; + if (!sym) + return; + if (sym->flags & SYMBOL_VALID) return; diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index fbacd970f2a2..2e6b7c95ecfc 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l @@ -96,6 +96,7 @@ n [A-Za-z0-9_] "endchoice" BEGIN(PARAM); return T_ENDCHOICE; "comment" BEGIN(PARAM); return T_COMMENT; "config" BEGIN(PARAM); return T_CONFIG; + "menuconfig" BEGIN(PARAM); return T_MENUCONFIG; "help" BEGIN(PARAM); return T_HELP; "if" BEGIN(PARAM); return T_IF; "endif" BEGIN(PARAM); return T_ENDIF; @@ -141,6 +142,7 @@ n [A-Za-z0-9_] zconflval.string = text; return T_WORD; } + #.* /* comment */ \\\n current_file->lineno++; . <<EOF>> { @@ -208,7 +210,7 @@ n [A-Za-z0-9_] } } - \n/[^ \t\n] { + [ \t]*\n/[^ \t\n] { current_file->lineno++; zconf_endhelp(); return T_HELPTEXT; diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index d312cc10dc88..e8904d9bf813 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -1,7 +1,7 @@ -/* A Bison parser, made from zconf.y, by GNU bison 1.75. */ +/* A Bison parser, made by GNU Bison 1.875a. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, 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 @@ -34,10 +34,13 @@ USER NAME SPACE" below. */ /* Identify Bison output. */ -#define YYBISON 1 +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ -#define YYPURE 0 +#define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 @@ -67,32 +70,33 @@ T_ENDCHOICE = 263, T_COMMENT = 264, T_CONFIG = 265, - T_HELP = 266, - T_HELPTEXT = 267, - T_IF = 268, - T_ENDIF = 269, - T_DEPENDS = 270, - T_REQUIRES = 271, - T_OPTIONAL = 272, - T_PROMPT = 273, - T_DEFAULT = 274, - T_TRISTATE = 275, - T_BOOLEAN = 276, - T_STRING = 277, - T_INT = 278, - T_HEX = 279, - T_WORD = 280, - T_WORD_QUOTE = 281, - T_UNEQUAL = 282, - T_EOF = 283, - T_EOL = 284, - T_CLOSE_PAREN = 285, - T_OPEN_PAREN = 286, - T_ON = 287, - T_OR = 288, - T_AND = 289, - T_EQUAL = 290, - T_NOT = 291 + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_REQUIRES = 272, + T_OPTIONAL = 273, + T_PROMPT = 274, + T_DEFAULT = 275, + T_TRISTATE = 276, + T_BOOLEAN = 277, + T_STRING = 278, + T_INT = 279, + T_HEX = 280, + T_WORD = 281, + T_WORD_QUOTE = 282, + T_UNEQUAL = 283, + T_EOF = 284, + T_EOL = 285, + T_CLOSE_PAREN = 286, + T_OPEN_PAREN = 287, + T_ON = 288, + T_OR = 289, + T_AND = 290, + T_EQUAL = 291, + T_NOT = 292 }; #endif #define T_MAINMENU 258 @@ -103,38 +107,40 @@ #define T_ENDCHOICE 263 #define T_COMMENT 264 #define T_CONFIG 265 -#define T_HELP 266 -#define T_HELPTEXT 267 -#define T_IF 268 -#define T_ENDIF 269 -#define T_DEPENDS 270 -#define T_REQUIRES 271 -#define T_OPTIONAL 272 -#define T_PROMPT 273 -#define T_DEFAULT 274 -#define T_TRISTATE 275 -#define T_BOOLEAN 276 -#define T_STRING 277 -#define T_INT 278 -#define T_HEX 279 -#define T_WORD 280 -#define T_WORD_QUOTE 281 -#define T_UNEQUAL 282 -#define T_EOF 283 -#define T_EOL 284 -#define T_CLOSE_PAREN 285 -#define T_OPEN_PAREN 286 -#define T_ON 287 -#define T_OR 288 -#define T_AND 289 -#define T_EQUAL 290 -#define T_NOT 291 +#define T_MENUCONFIG 266 +#define T_HELP 267 +#define T_HELPTEXT 268 +#define T_IF 269 +#define T_ENDIF 270 +#define T_DEPENDS 271 +#define T_REQUIRES 272 +#define T_OPTIONAL 273 +#define T_PROMPT 274 +#define T_DEFAULT 275 +#define T_TRISTATE 276 +#define T_BOOLEAN 277 +#define T_STRING 278 +#define T_INT 279 +#define T_HEX 280 +#define T_WORD 281 +#define T_WORD_QUOTE 282 +#define T_UNEQUAL 283 +#define T_EOF 284 +#define T_EOL 285 +#define T_CLOSE_PAREN 286 +#define T_OPEN_PAREN 287 +#define T_ON 288 +#define T_OR 289 +#define T_AND 290 +#define T_EQUAL 291 +#define T_NOT 292 /* Copy the first part of user declarations. */ + /* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Released under the terms of the GNU GPL v2.0. @@ -166,7 +172,7 @@ struct symbol *symbol_hash[257]; /* Enabling traces. */ #ifndef YYDEBUG -# define YYDEBUG 0 +# define YYDEBUG 1 #endif /* Enabling verbose error messages. */ @@ -177,41 +183,33 @@ struct symbol *symbol_hash[257]; # define YYERROR_VERBOSE 0 #endif -#ifndef YYSTYPE -#line 33 "zconf.y" -typedef union { +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) + +typedef union YYSTYPE { int token; char *string; struct symbol *symbol; struct expr *expr; struct menu *menu; -} yystype; -/* Line 193 of /usr/share/bison/yacc.c. */ -#line 191 "zconf.tab.c" -# define YYSTYPE yystype +} YYSTYPE; +/* Line 191 of yacc.c. */ + +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif -#ifndef YYLTYPE -typedef struct yyltype -{ - int first_line; - int first_column; - int last_line; - int last_column; -} yyltype; -# define YYLTYPE yyltype -# define YYLTYPE_IS_TRIVIAL 1 -#endif + /* Copy the second part of user declarations. */ + #define LKC_DIRECT_LINK #include "lkc.h" -/* Line 213 of /usr/share/bison/yacc.c. */ -#line 215 "zconf.tab.c" +/* Line 214 of yacc.c. */ + #if ! defined (yyoverflow) || YYERROR_VERBOSE @@ -247,7 +245,7 @@ typedef struct yyltype #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ - || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + || (YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc @@ -257,13 +255,13 @@ union yyalloc }; /* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAX) + + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ @@ -277,7 +275,7 @@ union yyalloc { \ register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ + (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif @@ -294,7 +292,7 @@ union yyalloc YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) @@ -309,23 +307,24 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 -#define YYLAST 154 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 160 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 37 +#define YYNTOKENS 38 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 39 +#define YYNNTS 41 /* YYNRULES -- Number of rules. */ -#define YYNRULES 96 +#define YYNRULES 99 /* YYNRULES -- Number of states. */ -#define YYNSTATES 146 +#define YYNSTATES 152 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 291 +#define YYMAXUTOK 292 -#define YYTRANSLATE(X) \ - ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK) +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const unsigned char yytranslate[] = @@ -359,7 +358,7 @@ static const unsigned char yytranslate[] = 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36 + 35, 36, 37 }; #if YYDEBUG @@ -368,63 +367,64 @@ static const unsigned char yytranslate[] = static const unsigned short yyprhs[] = { 0, 0, 3, 4, 7, 9, 11, 13, 17, 19, - 21, 23, 26, 28, 30, 32, 34, 36, 39, 43, - 44, 48, 52, 55, 58, 61, 64, 67, 70, 73, - 77, 81, 83, 87, 89, 94, 97, 98, 102, 106, - 109, 112, 116, 118, 122, 123, 126, 129, 131, 137, - 141, 142, 145, 148, 151, 154, 158, 160, 165, 168, - 169, 172, 175, 178, 182, 185, 188, 191, 195, 198, - 201, 202, 206, 209, 213, 216, 219, 220, 222, 226, - 228, 230, 232, 234, 236, 238, 240, 241, 244, 246, - 250, 254, 258, 261, 265, 269, 271 + 21, 23, 26, 28, 30, 32, 34, 36, 38, 41, + 45, 48, 52, 53, 57, 61, 64, 67, 70, 73, + 76, 79, 82, 86, 90, 92, 96, 98, 103, 106, + 107, 111, 115, 118, 121, 125, 127, 131, 132, 135, + 138, 140, 146, 150, 151, 154, 157, 160, 163, 167, + 169, 174, 177, 178, 181, 184, 187, 191, 194, 197, + 200, 204, 207, 210, 211, 215, 218, 222, 225, 228, + 229, 231, 235, 237, 239, 241, 243, 245, 247, 249, + 250, 253, 255, 259, 263, 267, 270, 274, 278, 280 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { - 38, 0, -1, -1, 38, 39, -1, 40, -1, 48, - -1, 59, -1, 3, 70, 72, -1, 5, -1, 14, - -1, 8, -1, 1, 72, -1, 54, -1, 64, -1, - 42, -1, 62, -1, 72, -1, 10, 25, -1, 41, - 29, 43, -1, -1, 43, 44, 29, -1, 43, 68, - 29, -1, 43, 66, -1, 43, 29, -1, 20, 69, - -1, 21, 69, -1, 23, 69, -1, 24, 69, -1, - 22, 69, -1, 18, 70, 73, -1, 19, 75, 73, - -1, 7, -1, 45, 29, 49, -1, 71, -1, 46, - 51, 47, 29, -1, 46, 51, -1, -1, 49, 50, - 29, -1, 49, 68, 29, -1, 49, 66, -1, 49, - 29, -1, 18, 70, 73, -1, 17, -1, 19, 75, - 73, -1, -1, 51, 40, -1, 13, 74, -1, 71, - -1, 52, 29, 55, 53, 29, -1, 52, 29, 55, - -1, -1, 55, 40, -1, 55, 59, -1, 55, 48, - -1, 4, 70, -1, 56, 29, 67, -1, 71, -1, - 57, 60, 58, 29, -1, 57, 60, -1, -1, 60, - 40, -1, 60, 59, -1, 60, 48, -1, 60, 1, - 29, -1, 6, 70, -1, 61, 29, -1, 9, 70, - -1, 63, 29, 67, -1, 11, 29, -1, 65, 12, - -1, -1, 67, 68, 29, -1, 67, 29, -1, 15, - 32, 74, -1, 15, 74, -1, 16, 74, -1, -1, - 70, -1, 70, 13, 74, -1, 25, -1, 26, -1, - 5, -1, 8, -1, 14, -1, 29, -1, 28, -1, - -1, 13, 74, -1, 75, -1, 75, 35, 75, -1, - 75, 27, 75, -1, 31, 74, 30, -1, 36, 74, - -1, 74, 33, 74, -1, 74, 34, 74, -1, 25, - -1, 26, -1 + 39, 0, -1, -1, 39, 40, -1, 41, -1, 51, + -1, 62, -1, 3, 73, 75, -1, 5, -1, 15, + -1, 8, -1, 1, 75, -1, 57, -1, 67, -1, + 43, -1, 45, -1, 65, -1, 75, -1, 10, 26, + -1, 42, 30, 46, -1, 11, 26, -1, 44, 30, + 46, -1, -1, 46, 47, 30, -1, 46, 71, 30, + -1, 46, 69, -1, 46, 30, -1, 21, 72, -1, + 22, 72, -1, 24, 72, -1, 25, 72, -1, 23, + 72, -1, 19, 73, 76, -1, 20, 78, 76, -1, + 7, -1, 48, 30, 52, -1, 74, -1, 49, 54, + 50, 30, -1, 49, 54, -1, -1, 52, 53, 30, + -1, 52, 71, 30, -1, 52, 69, -1, 52, 30, + -1, 19, 73, 76, -1, 18, -1, 20, 78, 76, + -1, -1, 54, 41, -1, 14, 77, -1, 74, -1, + 55, 30, 58, 56, 30, -1, 55, 30, 58, -1, + -1, 58, 41, -1, 58, 62, -1, 58, 51, -1, + 4, 73, -1, 59, 30, 70, -1, 74, -1, 60, + 63, 61, 30, -1, 60, 63, -1, -1, 63, 41, + -1, 63, 62, -1, 63, 51, -1, 63, 1, 30, + -1, 6, 73, -1, 64, 30, -1, 9, 73, -1, + 66, 30, 70, -1, 12, 30, -1, 68, 13, -1, + -1, 70, 71, 30, -1, 70, 30, -1, 16, 33, + 77, -1, 16, 77, -1, 17, 77, -1, -1, 73, + -1, 73, 14, 77, -1, 26, -1, 27, -1, 5, + -1, 8, -1, 15, -1, 30, -1, 29, -1, -1, + 14, 77, -1, 78, -1, 78, 36, 78, -1, 78, + 28, 78, -1, 32, 77, 31, -1, 37, 77, -1, + 77, 34, 77, -1, 77, 35, 77, -1, 26, -1, + 27, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short yyrline[] = { - 0, 89, 89, 90, 93, 94, 95, 96, 97, 98, - 99, 100, 103, 105, 106, 107, 108, 114, 122, 128, - 130, 131, 132, 133, 136, 142, 148, 154, 160, 166, - 172, 180, 189, 195, 203, 205, 211, 213, 214, 215, - 216, 219, 225, 231, 237, 239, 244, 253, 261, 263, - 269, 271, 272, 273, 278, 285, 291, 299, 301, 307, - 309, 310, 311, 312, 315, 321, 328, 335, 342, 348, - 355, 356, 357, 360, 365, 370, 378, 380, 384, 389, - 390, 393, 394, 395, 398, 399, 401, 402, 405, 406, - 407, 408, 409, 410, 411, 414, 415 + 0, 90, 90, 91, 94, 95, 96, 97, 98, 99, + 100, 101, 105, 106, 107, 108, 109, 110, 116, 124, + 130, 138, 148, 150, 151, 152, 153, 156, 162, 168, + 174, 180, 186, 192, 200, 209, 215, 224, 225, 231, + 233, 234, 235, 236, 239, 245, 251, 257, 259, 264, + 273, 282, 283, 289, 291, 292, 293, 298, 305, 311, + 320, 321, 327, 329, 330, 331, 332, 335, 341, 348, + 355, 362, 368, 375, 376, 377, 380, 385, 390, 398, + 400, 404, 409, 410, 413, 414, 415, 419, 419, 421, + 422, 425, 426, 427, 428, 429, 430, 431, 434, 435 }; #endif @@ -435,19 +435,19 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", - "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", "T_REQUIRES", - "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", "T_BOOLEAN", - "T_STRING", "T_INT", "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", - "T_EOF", "T_EOL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_OR", - "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", + "T_BOOLEAN", "T_STRING", "T_INT", "T_HEX", "T_WORD", "T_WORD_QUOTE", + "T_UNEQUAL", "T_EOF", "T_EOL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", + "T_OR", "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", "common_block", "config_entry_start", "config_stmt", - "config_option_list", "config_option", "choice", "choice_entry", - "choice_end", "choice_stmt", "choice_option_list", "choice_option", - "choice_block", "if", "if_end", "if_stmt", "if_block", "menu", - "menu_entry", "menu_end", "menu_stmt", "menu_block", "source", - "source_stmt", "comment", "comment_stmt", "help_start", "help", - "depends_list", "depends", "prompt_stmt_opt", "prompt", "end", - "nl_or_eof", "if_expr", "expr", "symbol", 0 + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", + "choice_option_list", "choice_option", "choice_block", "if", "if_end", + "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", + "menu_block", "source", "source_stmt", "comment", "comment_stmt", + "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", + "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0 }; #endif @@ -459,38 +459,38 @@ static const unsigned short yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291 + 285, 286, 287, 288, 289, 290, 291, 292 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { - 0, 37, 38, 38, 39, 39, 39, 39, 39, 39, - 39, 39, 40, 40, 40, 40, 40, 41, 42, 43, - 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, - 44, 45, 46, 47, 48, 48, 49, 49, 49, 49, - 49, 50, 50, 50, 51, 51, 52, 53, 54, 54, - 55, 55, 55, 55, 56, 57, 58, 59, 59, 60, - 60, 60, 60, 60, 61, 62, 63, 64, 65, 66, - 67, 67, 67, 68, 68, 68, 69, 69, 69, 70, - 70, 71, 71, 71, 72, 72, 73, 73, 74, 74, - 74, 74, 74, 74, 74, 75, 75 + 0, 38, 39, 39, 40, 40, 40, 40, 40, 40, + 40, 40, 41, 41, 41, 41, 41, 41, 42, 43, + 44, 45, 46, 46, 46, 46, 46, 47, 47, 47, + 47, 47, 47, 47, 48, 49, 50, 51, 51, 52, + 52, 52, 52, 52, 53, 53, 53, 54, 54, 55, + 56, 57, 57, 58, 58, 58, 58, 59, 60, 61, + 62, 62, 63, 63, 63, 63, 63, 64, 65, 66, + 67, 68, 69, 70, 70, 70, 71, 71, 71, 72, + 72, 72, 73, 73, 74, 74, 74, 75, 75, 76, + 76, 77, 77, 77, 77, 77, 77, 77, 78, 78 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { 0, 2, 0, 2, 1, 1, 1, 3, 1, 1, - 1, 2, 1, 1, 1, 1, 1, 2, 3, 0, - 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, - 3, 1, 3, 1, 4, 2, 0, 3, 3, 2, - 2, 3, 1, 3, 0, 2, 2, 1, 5, 3, - 0, 2, 2, 2, 2, 3, 1, 4, 2, 0, - 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, - 0, 3, 2, 3, 2, 2, 0, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 0, 2, 1, 3, - 3, 3, 2, 3, 3, 1, 1 + 1, 2, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 3, 0, 3, 3, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 1, 3, 1, 4, 2, 0, + 3, 3, 2, 2, 3, 1, 3, 0, 2, 2, + 1, 5, 3, 0, 2, 2, 2, 2, 3, 1, + 4, 2, 0, 2, 2, 2, 3, 2, 2, 2, + 3, 2, 2, 0, 3, 2, 3, 2, 2, 0, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 1, 3, 3, 3, 2, 3, 3, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -498,127 +498,134 @@ static const unsigned char yyr2[] = means the default is an error. */ static const unsigned char yydefact[] = { - 2, 0, 1, 0, 0, 0, 8, 0, 31, 10, - 0, 0, 0, 9, 85, 84, 3, 4, 0, 14, - 0, 44, 5, 0, 12, 0, 59, 6, 0, 15, - 0, 13, 16, 11, 79, 80, 0, 54, 64, 66, - 17, 95, 96, 0, 0, 46, 88, 19, 36, 35, - 50, 70, 0, 65, 70, 7, 0, 92, 0, 0, - 0, 0, 18, 32, 81, 82, 83, 45, 0, 33, - 49, 55, 0, 60, 62, 0, 61, 56, 67, 91, - 93, 94, 90, 89, 0, 0, 0, 0, 0, 76, - 76, 76, 76, 76, 23, 0, 0, 22, 0, 42, - 0, 0, 40, 0, 39, 0, 34, 51, 53, 0, - 52, 47, 72, 0, 63, 57, 68, 0, 74, 75, - 86, 86, 24, 77, 25, 28, 26, 27, 20, 69, - 21, 86, 86, 37, 38, 48, 71, 73, 0, 29, - 30, 0, 41, 43, 87, 78 + 2, 0, 1, 0, 0, 0, 8, 0, 34, 10, + 0, 0, 0, 0, 9, 88, 87, 3, 4, 0, + 14, 0, 15, 0, 47, 5, 0, 12, 0, 62, + 6, 0, 16, 0, 13, 17, 11, 82, 83, 0, + 57, 67, 69, 18, 20, 98, 99, 0, 0, 49, + 91, 22, 22, 39, 38, 53, 73, 0, 68, 73, + 7, 0, 95, 0, 0, 0, 0, 19, 21, 35, + 84, 85, 86, 48, 0, 36, 52, 58, 0, 63, + 65, 0, 64, 59, 70, 94, 96, 97, 93, 92, + 0, 0, 0, 0, 0, 79, 79, 79, 79, 79, + 26, 0, 0, 25, 0, 45, 0, 0, 43, 0, + 42, 0, 37, 54, 56, 0, 55, 50, 75, 0, + 66, 60, 71, 0, 77, 78, 89, 89, 27, 80, + 28, 31, 29, 30, 23, 72, 24, 89, 89, 40, + 41, 51, 74, 76, 0, 32, 33, 0, 44, 46, + 90, 81 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short yydefgoto[] = { - -1, 1, 16, 17, 18, 19, 62, 95, 20, 21, - 68, 22, 63, 103, 49, 23, 109, 24, 70, 25, - 26, 75, 27, 52, 28, 29, 30, 31, 96, 97, - 71, 113, 122, 123, 69, 32, 139, 45, 46 + -1, 1, 17, 18, 19, 20, 21, 22, 67, 101, + 23, 24, 74, 25, 69, 109, 54, 26, 115, 27, + 76, 28, 29, 81, 30, 57, 31, 32, 33, 34, + 102, 103, 77, 104, 128, 129, 75, 35, 145, 49, + 50 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -120 +#define YYPACT_NINF -121 static const short yypact[] = { - -120, 17, -120, 32, 71, 71, -120, 71, -120, -120, - 71, 11, 99, -120, -120, -120, -120, -120, 12, -120, - 22, -120, -120, 35, -120, 52, -120, -120, 56, -120, - 60, -120, -120, -120, -120, -120, 32, -120, -120, -120, - -120, -120, -120, 99, 99, 83, 38, -120, -120, 74, - -120, -120, 49, -120, -120, -120, 98, -120, 99, 99, - 101, 101, 89, 104, -120, -120, -120, -120, 65, -120, - 62, 77, 72, -120, -120, 85, -120, -120, 77, -120, - 95, -120, -120, -120, 105, 8, 99, 71, 101, 71, - 71, 71, 71, 71, -120, 113, 131, -120, 115, -120, - 71, 101, -120, 116, -120, 117, -120, -120, -120, 118, - -120, -120, -120, 119, -120, -120, -120, 99, 83, 83, - 136, 136, -120, 137, -120, -120, -120, -120, -120, -120, - -120, 136, 136, -120, -120, -120, -120, 83, 99, -120, - -120, 99, -120, -120, 83, 83 + -121, 25, -121, -18, -11, -11, -121, -11, -121, -121, + -11, 21, 27, 112, -121, -121, -121, -121, -121, 51, + -121, 54, -121, 57, -121, -121, 58, -121, 62, -121, + -121, 80, -121, 96, -121, -121, -121, -121, -121, -18, + -121, -121, -121, -121, -121, -121, -121, 112, 112, 17, + 77, -121, -121, -121, 85, -121, -121, 56, -121, -121, + -121, -21, -121, 112, 112, 42, 42, 100, 100, 115, + -121, -121, -121, -121, 98, -121, 68, 28, 99, -121, + -121, 111, -121, -121, 28, -121, 105, -121, -121, -121, + 116, 110, 112, -11, 42, -11, -11, -11, -11, -11, + -121, 118, 137, -121, 121, -121, -11, 42, -121, 122, + -121, 123, -121, -121, -121, 124, -121, -121, -121, 125, + -121, -121, -121, 112, 17, 17, 142, 142, -121, 143, + -121, -121, -121, -121, -121, -121, -121, 142, 142, -121, + -121, -121, -121, 17, 112, -121, -121, 112, -121, -121, + 17, 17 }; /* YYPGOTO[NTERM-NUM]. */ static const yysigned_char yypgoto[] = { - -120, -120, -120, -38, -120, -120, -120, -120, -120, -120, - -120, -42, -120, -120, -120, -120, -120, -120, -120, -120, - -120, -120, -33, -120, -120, -120, -120, -120, -120, 88, - 100, 78, 46, -1, -23, 2, -119, -43, -53 + -121, -121, -121, -35, -121, -121, -121, -121, 106, -121, + -121, -121, -121, -34, -121, -121, -121, -121, -121, -121, + -121, -121, -121, -121, -33, -121, -121, -121, -121, -121, + -121, 90, 101, 34, 10, -4, -30, -1, -120, -43, + -57 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, parse error. */ -#define YYTABLE_NINF -59 + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -62 static const short yytable[] = { - 56, 57, 140, 36, 37, 33, 38, 82, 83, 39, - 74, 67, 142, 143, 73, 80, 81, 2, 3, 76, - 4, 5, 6, 7, 8, 9, 10, 11, 108, 77, - 12, 13, 107, 41, 42, 121, 40, 110, 55, 43, - 117, 47, 118, 119, 44, 14, 15, 111, 132, -58, - 72, 48, -58, 5, 64, 7, 8, 65, 10, 11, - 14, 15, 12, 66, 50, 60, 5, 64, 7, 8, - 65, 10, 11, 61, 137, 12, 66, 14, 15, 64, - 7, 51, 65, 10, 11, 53, 120, 12, 66, 54, - 14, 15, 85, 86, 106, 144, 34, 35, 145, 131, - 84, 114, 14, 15, 85, 86, 112, 87, 88, 89, - 90, 91, 92, 93, 115, 84, 58, 59, 94, 85, - 86, 99, 100, 101, 41, 42, 41, 42, 79, 59, - 43, 58, 59, 102, 116, 44, 124, 125, 126, 127, - 98, 105, 128, 129, 130, 133, 134, 135, 136, 138, - 141, 104, 0, 0, 78 + 39, 40, 36, 41, 61, 62, 42, 146, 88, 89, + 85, 15, 16, 63, 64, 37, 38, 148, 149, 73, + 86, 87, 79, 80, 82, 2, 3, 83, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 127, 60, 13, + 14, 113, 114, 116, 91, 92, 117, 43, 124, 125, + 138, 63, 64, 44, 15, 16, -61, 78, 118, -61, + 5, 70, 7, 8, 71, 10, 11, 12, 45, 46, + 13, 72, 5, 70, 7, 8, 71, 10, 11, 12, + 143, 51, 13, 72, 52, 15, 16, 53, 55, 126, + 70, 7, 56, 71, 10, 11, 12, 15, 16, 13, + 72, 150, 137, 111, 151, 65, 130, 131, 132, 133, + 58, 119, 90, 66, 15, 16, 91, 92, 119, 93, + 94, 95, 96, 97, 98, 99, 59, 90, 112, 120, + 100, 91, 92, 105, 106, 107, 45, 46, 45, 46, + 64, 121, 47, 123, 47, 108, 122, 48, 134, 48, + 135, 136, 139, 140, 141, 142, 144, 147, 68, 110, + 84 }; -static const short yycheck[] = +static const unsigned char yycheck[] = { - 43, 44, 121, 4, 5, 3, 7, 60, 61, 10, - 52, 49, 131, 132, 52, 58, 59, 0, 1, 52, - 3, 4, 5, 6, 7, 8, 9, 10, 70, 52, - 13, 14, 70, 25, 26, 88, 25, 70, 36, 31, - 32, 29, 85, 86, 36, 28, 29, 70, 101, 0, - 1, 29, 3, 4, 5, 6, 7, 8, 9, 10, - 28, 29, 13, 14, 29, 27, 4, 5, 6, 7, - 8, 9, 10, 35, 117, 13, 14, 28, 29, 5, - 6, 29, 8, 9, 10, 29, 87, 13, 14, 29, - 28, 29, 15, 16, 29, 138, 25, 26, 141, 100, - 11, 29, 28, 29, 15, 16, 29, 18, 19, 20, - 21, 22, 23, 24, 29, 11, 33, 34, 29, 15, - 16, 17, 18, 19, 25, 26, 25, 26, 30, 34, - 31, 33, 34, 29, 29, 36, 90, 91, 92, 93, - 62, 63, 29, 12, 29, 29, 29, 29, 29, 13, - 13, 63, -1, -1, 54 + 4, 5, 3, 7, 47, 48, 10, 127, 65, 66, + 31, 29, 30, 34, 35, 26, 27, 137, 138, 54, + 63, 64, 57, 57, 57, 0, 1, 57, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 94, 39, 14, + 15, 76, 76, 76, 16, 17, 76, 26, 91, 92, + 107, 34, 35, 26, 29, 30, 0, 1, 30, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 26, 27, + 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, + 123, 30, 14, 15, 30, 29, 30, 30, 30, 93, + 5, 6, 30, 8, 9, 10, 11, 29, 30, 14, + 15, 144, 106, 69, 147, 28, 96, 97, 98, 99, + 30, 77, 12, 36, 29, 30, 16, 17, 84, 19, + 20, 21, 22, 23, 24, 25, 30, 12, 30, 30, + 30, 16, 17, 18, 19, 20, 26, 27, 26, 27, + 35, 30, 32, 33, 32, 30, 30, 37, 30, 37, + 13, 30, 30, 30, 30, 30, 14, 14, 52, 69, + 59 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { - 0, 38, 0, 1, 3, 4, 5, 6, 7, 8, - 9, 10, 13, 14, 28, 29, 39, 40, 41, 42, - 45, 46, 48, 52, 54, 56, 57, 59, 61, 62, - 63, 64, 72, 72, 25, 26, 70, 70, 70, 70, - 25, 25, 26, 31, 36, 74, 75, 29, 29, 51, - 29, 29, 60, 29, 29, 72, 74, 74, 33, 34, - 27, 35, 43, 49, 5, 8, 14, 40, 47, 71, - 55, 67, 1, 40, 48, 58, 59, 71, 67, 30, - 74, 74, 75, 75, 11, 15, 16, 18, 19, 20, - 21, 22, 23, 24, 29, 44, 65, 66, 68, 17, - 18, 19, 29, 50, 66, 68, 29, 40, 48, 53, - 59, 71, 29, 68, 29, 29, 29, 32, 74, 74, - 70, 75, 69, 70, 69, 69, 69, 69, 29, 12, - 29, 70, 75, 29, 29, 29, 29, 74, 13, 73, - 73, 13, 73, 73, 74, 74 + 0, 39, 0, 1, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 14, 15, 29, 30, 40, 41, 42, + 43, 44, 45, 48, 49, 51, 55, 57, 59, 60, + 62, 64, 65, 66, 67, 75, 75, 26, 27, 73, + 73, 73, 73, 26, 26, 26, 27, 32, 37, 77, + 78, 30, 30, 30, 54, 30, 30, 63, 30, 30, + 75, 77, 77, 34, 35, 28, 36, 46, 46, 52, + 5, 8, 15, 41, 50, 74, 58, 70, 1, 41, + 51, 61, 62, 74, 70, 31, 77, 77, 78, 78, + 12, 16, 17, 19, 20, 21, 22, 23, 24, 25, + 30, 47, 68, 69, 71, 18, 19, 20, 30, 53, + 69, 71, 30, 41, 51, 56, 62, 74, 30, 71, + 30, 30, 30, 33, 77, 77, 73, 78, 72, 73, + 72, 72, 72, 72, 30, 13, 30, 73, 78, 30, + 30, 30, 30, 77, 14, 76, 76, 14, 76, 76, + 77, 77 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) @@ -639,13 +646,14 @@ static const unsigned char yystos[] = #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 +#define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 + /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ @@ -660,13 +668,13 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yychar1 = YYTRANSLATE (yychar); \ + yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ - yyerror ("syntax error: cannot back up"); \ + yyerror ("syntax error: cannot back up");\ YYERROR; \ } \ while (0) @@ -678,7 +686,7 @@ while (0) are run). */ #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ +# define YYLLOC_DEFAULT(Current, Rhs, N) \ Current.first_line = Rhs[1].first_line; \ Current.first_column = Rhs[1].first_column; \ Current.last_line = Rhs[N].last_line; \ @@ -687,7 +695,11 @@ while (0) /* YYLEX -- calling `yylex' with the right arguments. */ -#define YYLEX yylex () +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -702,19 +714,93 @@ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) + # define YYDSYMPRINT(Args) \ do { \ if (yydebug) \ yysymprint Args; \ } while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylineno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylineno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ + /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 @@ -793,95 +879,85 @@ yystpcpy (yydest, yysrc) #if YYDEBUG -/*-----------------------------. -| Print this symbol on YYOUT. | -`-----------------------------*/ +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ -static void #if defined (__STDC__) || defined (__cplusplus) -yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) #else -yysymprint (yyout, yytype, yyvalue) - FILE* yyout; +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; int yytype; - YYSTYPE yyvalue; + YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ - (void) yyvalue; + (void) yyvaluep; if (yytype < YYNTOKENS) { - YYFPRINTF (yyout, "token %s (", yytname[yytype]); + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); # ifdef YYPRINT - YYPRINT (yyout, yytoknum[yytype], yyvalue); + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif } else - YYFPRINTF (yyout, "nterm %s (", yytname[yytype]); + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); switch (yytype) { default: break; } - YYFPRINTF (yyout, ")"); + YYFPRINTF (yyoutput, ")"); } -#endif /* YYDEBUG. */ - +#endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -static void #if defined (__STDC__) || defined (__cplusplus) -yydestruct (int yytype, YYSTYPE yyvalue) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) #else -yydestruct (yytype, yyvalue) +static void +yydestruct (yytype, yyvaluep) int yytype; - YYSTYPE yyvalue; + YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ - (void) yyvalue; + (void) yyvaluep; switch (yytype) { + default: break; } } - -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ +/* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) -# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -# define YYPARSE_PARAM_DECL +int yyparse (void *YYPARSE_PARAM); # else -# define YYPARSE_PARAM_ARG YYPARSE_PARAM -# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +int yyparse (); # endif -#else /* !YYPARSE_PARAM */ -# define YYPARSE_PARAM_ARG -# define YYPARSE_PARAM_DECL -#endif /* !YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -# ifdef YYPARSE_PARAM -int yyparse (void *); -# else +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) int yyparse (void); -# endif +#else +int yyparse (); #endif +#endif /* ! YYPARSE_PARAM */ + /* The lookahead symbol. */ @@ -890,13 +966,32 @@ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; -/* Number of parse errors so far. */ +/* Number of syntax errors so far. */ int yynerrs; + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else int -yyparse (YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL +yyparse () + +#endif +#endif { register int yystate; @@ -905,7 +1000,7 @@ yyparse (YYPARSE_PARAM_ARG) /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Lookahead token as an internal (translated) token number. */ - int yychar1 = 0; + int yytoken = 0; /* Three stacks and their tools: `yyss': related to states, @@ -969,7 +1064,7 @@ yyparse (YYPARSE_PARAM_ARG) yysetstate: *yyssp = yystate; - if (yyssp >= yyss + yystacksize - 1) + if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; @@ -1001,10 +1096,10 @@ yyparse (YYPARSE_PARAM_ARG) goto yyoverflowlab; # else /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) + if (YYMAXDEPTH <= yystacksize) goto yyoverflowlab; yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) + if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { @@ -1030,7 +1125,7 @@ yyparse (YYPARSE_PARAM_ARG) YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); - if (yyssp >= yyss + yystacksize - 1) + if (yyss + yystacksize - 1 <= yyssp) YYABORT; } @@ -1055,39 +1150,28 @@ yybackup: /* Not known => get a lookahead token if don't already have one. */ - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } - /* Convert token to internal form (in yychar1) for indexing tables with. */ - - if (yychar <= 0) /* This means end of input. */ + if (yychar <= YYEOF) { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more. */ - + yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { - yychar1 = YYTRANSLATE (yychar); - - /* We have to keep this `#if YYDEBUG', since we use variables - which are defined only if `YYDEBUG' is set. */ - YYDPRINTF ((stderr, "Next token is ")); - YYDSYMPRINT ((stderr, yychar1, yylval)); - YYDPRINTF ((stderr, "\n")); + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } - /* If the proper action on seeing token YYCHAR1 is to reduce or to + /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ - yyn += yychar1; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1) + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) @@ -1102,8 +1186,7 @@ yybackup: YYACCEPT; /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %d (%s), ", - yychar, yytname[yychar1])); + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) @@ -1149,378 +1232,430 @@ yyreduce: yyval = yyvsp[1-yylen]; - -#if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables which - are defined only if `YYDEBUG' is set. */ - if (yydebug) - { - int yyi; - - YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", - yyn - 1, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++) - YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); - YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif + YY_REDUCE_PRINT (yyn); switch (yyn) { case 8: - { zconfprint("unexpected 'endmenu' statement"); } + + { zconfprint("unexpected 'endmenu' statement"); ;} break; case 9: - { zconfprint("unexpected 'endif' statement"); } + + { zconfprint("unexpected 'endif' statement"); ;} break; case 10: - { zconfprint("unexpected 'endchoice' statement"); } + + { zconfprint("unexpected 'endchoice' statement"); ;} break; case 11: - { zconfprint("syntax error"); yyerrok; } + + { zconfprint("syntax error"); yyerrok; ;} break; - case 17: + case 18: + { struct symbol *sym = sym_lookup(yyvsp[0].string, 0); sym->flags |= SYMBOL_OPTIONAL; menu_add_entry(sym); printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[0].string); -} +;} break; - case 18: + case 19: + { menu_end_entry(); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -} +;} + break; + + case 20: + + { + struct symbol *sym = sym_lookup(yyvsp[0].string, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[0].string); +;} + break; + + case 21: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} break; - case 23: - { } + case 26: + + { ;} break; - case 24: + case 27: + { menu_set_type(S_TRISTATE); printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 25: + case 28: + { menu_set_type(S_BOOLEAN); printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 26: + case 29: + { menu_set_type(S_INT); printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 27: + case 30: + { menu_set_type(S_HEX); printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 28: + case 31: + { menu_set_type(S_STRING); printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 29: + case 32: + { menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 30: + case 33: + { menu_add_prop(P_DEFAULT, NULL, yyvsp[-1].symbol, yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 31: + case 34: + { struct symbol *sym = sym_lookup(NULL, 0); sym->flags |= SYMBOL_CHOICE; menu_add_entry(sym); menu_add_prop(P_CHOICE, NULL, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 32: + case 35: + { menu_end_entry(); menu_add_menu(); -} +;} break; - case 33: + case 36: + { if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); } -} +;} break; - case 35: + case 38: + { printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); zconfnerrs++; -} +;} break; - case 41: + case 44: + { menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 42: + case 45: + { current_entry->sym->flags |= SYMBOL_OPTIONAL; printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 43: + case 46: + { menu_add_prop(P_DEFAULT, NULL, yyvsp[-1].symbol, yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 46: + case 49: + { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); menu_add_dep(yyvsp[0].expr); menu_end_entry(); menu_add_menu(); -} +;} break; - case 47: + case 50: + { if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); } -} +;} break; - case 49: + case 52: + { printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); zconfnerrs++; -} +;} break; - case 54: + case 57: + { menu_add_entry(NULL); menu_add_prop(P_MENU, yyvsp[0].string, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 55: + case 58: + { menu_end_entry(); menu_add_menu(); -} +;} break; - case 56: + case 59: + { if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); } -} +;} break; - case 58: + case 61: + { printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); zconfnerrs++; -} +;} break; - case 63: - { zconfprint("invalid menu option"); yyerrok; } + case 66: + + { zconfprint("invalid menu option"); yyerrok; ;} break; - case 64: + case 67: + { yyval.string = yyvsp[0].string; printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[0].string); -} +;} break; - case 65: + case 68: + { zconf_nextfile(yyvsp[-1].string); -} +;} break; - case 66: + case 69: + { menu_add_entry(NULL); menu_add_prop(P_COMMENT, yyvsp[0].string, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 67: + case 70: + { menu_end_entry(); -} +;} break; - case 68: + case 71: + { printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); zconf_starthelp(); -} +;} break; - case 69: + case 72: + { current_entry->sym->help = yyvsp[0].string; -} +;} break; - case 72: - { } + case 75: + + { ;} break; - case 73: + case 76: + { menu_add_dep(yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 74: + case 77: + { menu_add_dep(yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 75: + case 78: + { menu_add_dep(yyvsp[0].expr); printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); -} +;} break; - case 77: + case 80: + { menu_add_prop(P_PROMPT, yyvsp[0].string, NULL, NULL); -} +;} break; - case 78: + case 81: + { menu_add_prop(P_PROMPT, yyvsp[-2].string, NULL, yyvsp[0].expr); -} +;} break; - case 81: - { yyval.token = T_ENDMENU; } - break; + case 84: - case 82: - { yyval.token = T_ENDCHOICE; } + { yyval.token = T_ENDMENU; ;} break; - case 83: - { yyval.token = T_ENDIF; } - break; + case 85: - case 86: - { yyval.expr = NULL; } + { yyval.token = T_ENDCHOICE; ;} break; - case 87: - { yyval.expr = yyvsp[0].expr; } - break; + case 86: - case 88: - { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); } + { yyval.token = T_ENDIF; ;} break; case 89: - { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); } + + { yyval.expr = NULL; ;} break; case 90: - { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); } + + { yyval.expr = yyvsp[0].expr; ;} break; case 91: - { yyval.expr = yyvsp[-1].expr; } + + { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;} break; case 92: - { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); } + + { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} break; case 93: - { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); } + + { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} break; case 94: - { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); } + + { yyval.expr = yyvsp[-1].expr; ;} break; case 95: - { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); } + + { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;} break; case 96: - { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); } + + { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;} + break; + + case 97: + + { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;} + break; + + case 98: + + { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;} + break; + + case 99: + + { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;} break; } -/* Line 1016 of /usr/share/bison/yacc.c. */ -#line 1509 "zconf.tab.c" +/* Line 999 of yacc.c. */ + yyvsp -= yylen; yyssp -= yylen; -#if YYDEBUG - if (yydebug) - { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); - } -#endif + YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; @@ -1565,12 +1700,12 @@ yyerrlab: yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen ("syntax error, unexpected ") + 1; yysize += yystrlen (yytname[yytype]); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { - char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); yyp = yystpcpy (yyp, yytname[yytype]); if (yycount < 5) @@ -1591,19 +1726,15 @@ yyerrlab: YYSTACK_FREE (yymsg); } else - yyerror ("parse error; also virtual memory exhausted"); + yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ - yyerror ("parse error"); + yyerror ("syntax error"); } - goto yyerrlab1; -/*----------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action. | -`----------------------------------------------------*/ -yyerrlab1: + if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an @@ -1615,28 +1746,30 @@ yyerrlab1: /* Pop the error token. */ YYPOPSTACK; /* Pop the rest of the stack. */ - while (yyssp > yyss) + while (yyss < yyssp) { - YYDPRINTF ((stderr, "Error: popping ")); - YYDSYMPRINT ((stderr, - yystos[*yyssp], - *yyvsp)); - YYDPRINTF ((stderr, "\n")); - yydestruct (yystos[*yyssp], *yyvsp); + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); YYPOPSTACK; } YYABORT; } - YYDPRINTF ((stderr, "Discarding token %d (%s).\n", - yychar, yytname[yychar1])); - yydestruct (yychar1, yylval); + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); yychar = YYEMPTY; + } /* Else will try to reuse lookahead token after shifting the error token. */ + goto yyerrlab1; + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) @@ -1657,26 +1790,12 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - YYDPRINTF ((stderr, "Error: popping ")); - YYDSYMPRINT ((stderr, - yystos[*yyssp], *yyvsp)); - YYDPRINTF ((stderr, "\n")); - - yydestruct (yystos[yystate], *yyvsp); + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); yyvsp--; yystate = *--yyssp; - -#if YYDEBUG - if (yydebug) - { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "Error: state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); - } -#endif + YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) @@ -1726,12 +1845,14 @@ yyreturn: + void conf_parse(const char *name) { zconf_initscan(name); sym_init(); menu_init(); + modules_sym = sym_lookup("MODULES", 0); rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL); //zconfdebug = 1; @@ -1740,8 +1861,6 @@ void conf_parse(const char *name) exit(1); menu_finalize(&rootmenu); - modules_sym = sym_lookup("MODULES", 0); - sym_change_count = 1; } diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 8d4abc5c1610..04e949903894 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -27,7 +27,7 @@ struct symbol *symbol_hash[257]; #define YYERROR_VERBOSE %} -%expect 36 +%expect 40 %union { @@ -46,6 +46,7 @@ struct symbol *symbol_hash[257]; %token T_ENDCHOICE %token T_COMMENT %token T_CONFIG +%token T_MENUCONFIG %token T_HELP %token <string> T_HELPTEXT %token T_IF @@ -104,12 +105,13 @@ common_block: if_stmt | comment_stmt | config_stmt + | menuconfig_stmt | source_stmt | nl_or_eof ; -/* config entry */ +/* config/menuconfig entry */ config_entry_start: T_CONFIG T_WORD { @@ -125,6 +127,24 @@ config_stmt: config_entry_start T_EOL config_option_list printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); }; +menuconfig_entry_start: T_MENUCONFIG T_WORD +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start T_EOL config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + config_option_list: /* empty */ | config_option_list config_option T_EOL @@ -423,6 +443,7 @@ void conf_parse(const char *name) sym_init(); menu_init(); + modules_sym = sym_lookup("MODULES", 0); rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL); //zconfdebug = 1; @@ -431,8 +452,6 @@ void conf_parse(const char *name) exit(1); menu_finalize(&rootmenu); - modules_sym = sym_lookup("MODULES", 0); - sym_change_count = 1; } diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile index f4b40f078ee8..fe959bd22a6a 100644 --- a/scripts/lxdialog/Makefile +++ b/scripts/lxdialog/Makefile @@ -15,8 +15,8 @@ endif endif endif -host-progs := lxdialog -build-targets := $(host-progs) +host-progs := lxdialog +always := $(host-progs) lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \ util.o lxdialog.o msgbox.o diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h index e3247cb98d3b..85f6a6f94aa9 100755 --- a/scripts/mkcompile_h +++ b/scripts/mkcompile_h @@ -10,7 +10,7 @@ CC=$4 # do "compiled by root" if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then - echo ' (not modified)' + echo " SKIPPED $TARGET" exit 0 fi @@ -70,10 +70,9 @@ if [ -r $TARGET ] && \ grep -v 'UTS_VERSION\|LINUX_COMPILE_TIME' $TARGET > .tmpver.1 && \ grep -v 'UTS_VERSION\|LINUX_COMPILE_TIME' .tmpcompile > .tmpver.2 && \ cmp -s .tmpver.1 .tmpver.2; then - echo ' (unchanged)' rm -f .tmpcompile else - echo ' (updated)' + echo " UPD $TARGET" mv -f .tmpcompile $TARGET fi -#rm -f .tmpver.1 .tmpver.2 +rm -f .tmpver.1 .tmpver.2 diff --git a/security/capability.c b/security/capability.c index 09882ecc997d..02cb4112fce0 100644 --- a/security/capability.c +++ b/security/capability.c @@ -263,6 +263,13 @@ void cap_task_reparent_to_init (struct task_struct *p) return; } +int cap_syslog (int type) +{ + if ((type != 3) && !capable(CAP_SYS_ADMIN)) + return -EPERM; + return 0; +} + EXPORT_SYMBOL(cap_capable); EXPORT_SYMBOL(cap_ptrace); EXPORT_SYMBOL(cap_capget); @@ -273,6 +280,7 @@ EXPORT_SYMBOL(cap_bprm_compute_creds); EXPORT_SYMBOL(cap_task_post_setuid); EXPORT_SYMBOL(cap_task_kmod_set_label); EXPORT_SYMBOL(cap_task_reparent_to_init); +EXPORT_SYMBOL(cap_syslog); #ifdef CONFIG_SECURITY @@ -292,6 +300,8 @@ static struct security_operations capability_ops = { .task_post_setuid = cap_task_post_setuid, .task_kmod_set_label = cap_task_kmod_set_label, .task_reparent_to_init = cap_task_reparent_to_init, + + .syslog = cap_syslog, }; #if defined(CONFIG_SECURITY_CAPABILITIES_MODULE) diff --git a/security/dummy.c b/security/dummy.c index 9b450c740bfa..062ae9a7fa2b 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -75,6 +75,11 @@ static int dummy_capable (struct task_struct *tsk, int cap) return -EPERM; } +static int dummy_sysctl (ctl_table * table, int op) +{ + return 0; +} + static int dummy_quotactl (int cmds, int type, int id, struct super_block *sb) { return 0; @@ -85,6 +90,13 @@ static int dummy_quota_on (struct file *f) return 0; } +static int dummy_syslog (int type) +{ + if ((type != 3) && current->euid) + return -EPERM; + return 0; +} + static int dummy_bprm_alloc_security (struct linux_binprm *bprm) { return 0; @@ -120,6 +132,11 @@ static void dummy_sb_free_security (struct super_block *sb) return; } +static int dummy_sb_kern_mount (struct super_block *sb) +{ + return 0; +} + static int dummy_sb_statfs (struct super_block *sb) { return 0; @@ -306,11 +323,6 @@ static int dummy_inode_getattr (struct vfsmount *mnt, struct dentry *dentry) return 0; } -static void dummy_inode_post_lookup (struct inode *ino, struct dentry *d) -{ - return; -} - static void dummy_inode_delete (struct inode *ino) { return; @@ -719,6 +731,12 @@ static int dummy_unregister_security (const char *name, struct security_operatio return -EINVAL; } +static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode) +{ + return; +} + + struct security_operations dummy_security_ops; #define set_to_dummy_if_null(ops, function) \ @@ -740,6 +758,8 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, capable); set_to_dummy_if_null(ops, quotactl); set_to_dummy_if_null(ops, quota_on); + set_to_dummy_if_null(ops, sysctl); + set_to_dummy_if_null(ops, syslog); set_to_dummy_if_null(ops, bprm_alloc_security); set_to_dummy_if_null(ops, bprm_free_security); set_to_dummy_if_null(ops, bprm_compute_creds); @@ -747,6 +767,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, bprm_check_security); set_to_dummy_if_null(ops, sb_alloc_security); set_to_dummy_if_null(ops, sb_free_security); + set_to_dummy_if_null(ops, sb_kern_mount); set_to_dummy_if_null(ops, sb_statfs); set_to_dummy_if_null(ops, sb_mount); set_to_dummy_if_null(ops, sb_check_sb); @@ -780,7 +801,6 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, inode_permission_lite); set_to_dummy_if_null(ops, inode_setattr); set_to_dummy_if_null(ops, inode_getattr); - set_to_dummy_if_null(ops, inode_post_lookup); set_to_dummy_if_null(ops, inode_delete); set_to_dummy_if_null(ops, inode_setxattr); set_to_dummy_if_null(ops, inode_getxattr); @@ -839,6 +859,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, netlink_recv); set_to_dummy_if_null(ops, register_security); set_to_dummy_if_null(ops, unregister_security); + set_to_dummy_if_null(ops, d_instantiate); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); set_to_dummy_if_null(ops, unix_may_send); diff --git a/usr/Makefile b/usr/Makefile index f50927e58c27..58a915ee7fe5 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -25,10 +25,10 @@ quiet_cmd_cpio = CPIO $@ $(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio $(initramfs-y) FORCE $(call if_changed,cpio) -targets += $(obj)/initramfs_data.cpio +targets += initramfs_data.cpio $(obj)/initramfs_data.cpio.gz: $(obj)/initramfs_data.cpio FORCE $(call if_changed,gzip) -targets += $(obj)/initramfs_data.cpio.gz +targets += initramfs_data.cpio.gz |
