diff options
585 files changed, 7868 insertions, 4613 deletions
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt new file mode 100644 index 00000000000..e4c38152f7f --- /dev/null +++ b/Documentation/RCU/torture.txt @@ -0,0 +1,122 @@ +RCU Torture Test Operation + + +CONFIG_RCU_TORTURE_TEST + +The CONFIG_RCU_TORTURE_TEST config option is available for all RCU +implementations. It creates an rcutorture kernel module that can +be loaded to run a torture test. The test periodically outputs +status messages via printk(), which can be examined via the dmesg +command (perhaps grepping for "rcutorture"). The test is started +when the module is loaded, and stops when the module is unloaded. + +However, actually setting this config option to "y" results in the system +running the test immediately upon boot, and ending only when the system +is taken down. Normally, one will instead want to build the system +with CONFIG_RCU_TORTURE_TEST=m and to use modprobe and rmmod to control +the test, perhaps using a script similar to the one shown at the end of +this document. Note that you will need CONFIG_MODULE_UNLOAD in order +to be able to end the test. + + +MODULE PARAMETERS + +This module has the following parameters: + +nreaders This is the number of RCU reading threads supported. + The default is twice the number of CPUs. Why twice? + To properly exercise RCU implementations with preemptible + read-side critical sections. + +stat_interval The number of seconds between output of torture + statistics (via printk()). Regardless of the interval, + statistics are printed when the module is unloaded. + Setting the interval to zero causes the statistics to + be printed -only- when the module is unloaded, and this + is the default. + +verbose Enable debug printk()s. Default is disabled. + + +OUTPUT + +The statistics output is as follows: + + rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0 + rcutorture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915 + rcutorture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0 + rcutorture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0 + rcutorture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0 + rcutorture: --- End of test + +The command "dmesg | grep rcutorture:" will extract this information on +most systems. On more esoteric configurations, it may be necessary to +use other commands to access the output of the printk()s used by +the RCU torture test. The printk()s use KERN_ALERT, so they should +be evident. ;-) + +The entries are as follows: + +o "ggp": The number of counter flips (or batches) since boot. + +o "rtc": The hexadecimal address of the structure currently visible + to readers. + +o "ver": The number of times since boot that the rcutw writer task + has changed the structure visible to readers. + +o "tfle": If non-zero, indicates that the "torture freelist" + containing structure to be placed into the "rtc" area is empty. + This condition is important, since it can fool you into thinking + that RCU is working when it is not. :-/ + +o "rta": Number of structures allocated from the torture freelist. + +o "rtaf": Number of allocations from the torture freelist that have + failed due to the list being empty. + +o "rtf": Number of frees into the torture freelist. + +o "Reader Pipe": Histogram of "ages" of structures seen by readers. + If any entries past the first two are non-zero, RCU is broken. + And rcutorture prints the error flag string "!!!" to make sure + you notice. The age of a newly allocated structure is zero, + it becomes one when removed from reader visibility, and is + incremented once per grace period subsequently -- and is freed + after passing through (RCU_TORTURE_PIPE_LEN-2) grace periods. + + The output displayed above was taken from a correctly working + RCU. If you want to see what it looks like when broken, break + it yourself. ;-) + +o "Reader Batch": Another histogram of "ages" of structures seen + by readers, but in terms of counter flips (or batches) rather + than in terms of grace periods. The legal number of non-zero + entries is again two. The reason for this separate view is + that it is easier to get the third entry to show up in the + "Reader Batch" list than in the "Reader Pipe" list. + +o "Free-Block Circulation": Shows the number of torture structures + that have reached a given point in the pipeline. The first element + should closely correspond to the number of structures allocated, + the second to the number that have been removed from reader view, + and all but the last remaining to the corresponding number of + passes through a grace period. The last entry should be zero, + as it is only incremented if a torture structure's counter + somehow gets incremented farther than it should. + + +USAGE + +The following script may be used to torture RCU: + + #!/bin/sh + + modprobe rcutorture + sleep 100 + rmmod rcutorture + dmesg | grep rcutorture: + +The output can be manually inspected for the error flag of "!!!". +One could of course create a more elaborate script that automatically +checked for such errors. diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt index d17b7d2dd77..a09a8eb8066 100644 --- a/Documentation/cpusets.txt +++ b/Documentation/cpusets.txt @@ -94,7 +94,7 @@ the available CPU and Memory resources amongst the requesting tasks. But larger systems, which benefit more from careful processor and memory placement to reduce memory access times and contention, and which typically represent a larger investment for the customer, -can benefit from explictly placing jobs on properly sized subsets of +can benefit from explicitly placing jobs on properly sized subsets of the system. This can be especially valuable on: diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c index 4bef8c25172..d3ad2c24490 100644 --- a/Documentation/firmware_class/firmware_sample_driver.c +++ b/Documentation/firmware_class/firmware_sample_driver.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/string.h> #include "linux/firmware.h" diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c index 09eab2f1b37..57b956aecbc 100644 --- a/Documentation/firmware_class/firmware_sample_firmware_class.c +++ b/Documentation/firmware_class/firmware_sample_firmware_class.c @@ -14,6 +14,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/timer.h> +#include <linux/slab.h> +#include <linux/string.h> #include <linux/firmware.h> diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index e94d9c6cc52..cff7b652588 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -273,6 +273,7 @@ For now, you can ignore the `flags' parameter. It is there for future use. if (is_isa) { /* Discard immediately if this ISA range is already used */ + /* FIXME: never use check_region(), only request_region() */ if (check_region(address,FOO_EXTENT)) goto ERROR0; diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 4afe03a58c5..31154882000 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -196,7 +196,7 @@ KEY ACCESS PERMISSIONS Keys have an owner user ID, a group access ID, and a permissions mask. The mask has up to eight bits each for possessor, user, group and other access. Only -five of each set of eight bits are defined. These permissions granted are: +six of each set of eight bits are defined. These permissions granted are: (*) View @@ -224,6 +224,10 @@ five of each set of eight bits are defined. These permissions granted are: keyring to a key, a process must have Write permission on the keyring and Link permission on the key. + (*) Set Attribute + + This permits a key's UID, GID and permissions mask to be changed. + For changing the ownership, group ID or permissions mask, being the owner of the key or having the sysadmin capability is sufficient. @@ -242,15 +246,15 @@ about the status of the key service: this way: SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY - 00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4 - 00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty - 00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty - 0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty - 000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4 - 000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty + 00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4 + 00000002 I----- 2 perm 1f3f0000 0 0 keyring _uid.0: empty + 00000007 I----- 1 perm 1f3f0000 0 0 keyring _pid.1: empty + 0000018d I----- 1 perm 1f3f0000 0 0 keyring _pid.412: empty + 000004d2 I--Q-- 1 perm 1f3f0000 32 -1 keyring _uid.32: 1/4 + 000004d3 I--Q-- 3 perm 1f3f0000 32 -1 keyring _uid_ses.32: empty 00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0 - 00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0 - 00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0 + 00000893 I--Q-N 1 35s 1f3f0000 0 0 user metal:silver: 0 + 00000894 I--Q-- 1 10h 003f0000 0 0 user metal:gold: 0 The flags are: diff --git a/MAINTAINERS b/MAINTAINERS index e88d193d42f..983f9e9aed6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2286,6 +2286,11 @@ W: http://tpmdd.sourceforge.net L: tpmdd-devel@lists.sourceforge.net S: Maintained +Telecom Clock Driver for MCPL0010 +P: Mark Gross +M: mark.gross@intel.com +S: Supported + TENSILICA XTENSA PORT (xtensa): P: Chris Zankel M: chris@zankel.net @@ -54,6 +54,10 @@ INSTALLING the kernel: gzip -cd linux-2.6.XX.tar.gz | tar xvf - + or + bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf - + + Replace "XX" with the version number of the latest kernel. Do NOT use the /usr/src/linux area! This area has a (usually diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 67be50b7d80..6b2921be190 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -55,10 +55,6 @@ #include "proto.h" #include "irq_impl.h" -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - extern unsigned long wall_jiffies; /* kernel/timer.c */ static int set_rtc_mmss(unsigned long); diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c index c6beb751f2a..e1013112c35 100644 --- a/arch/arm/common/amba.c +++ b/arch/arm/common/amba.c @@ -10,6 +10,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/irq.h> diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index cbf2165476b..ad6c89a555b 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -33,8 +33,8 @@ #include <asm/cacheflush.h> #undef DEBUG - #undef STATS + #ifdef STATS #define DO_STATS(X) do { X ; } while (0) #else @@ -52,26 +52,31 @@ struct safe_buffer { int direction; /* safe buffer info */ - struct dma_pool *pool; + struct dmabounce_pool *pool; void *safe; dma_addr_t safe_dma_addr; }; +struct dmabounce_pool { + unsigned long size; + struct dma_pool *pool; +#ifdef STATS + unsigned long allocs; +#endif +}; + struct dmabounce_device_info { struct list_head node; struct device *dev; - struct dma_pool *small_buffer_pool; - struct dma_pool *large_buffer_pool; struct list_head safe_buffers; - unsigned long small_buffer_size, large_buffer_size; #ifdef STATS - unsigned long sbp_allocs; - unsigned long lbp_allocs; unsigned long total_allocs; unsigned long map_op_count; unsigned long bounce_count; #endif + struct dmabounce_pool small; + struct dmabounce_pool large; }; static LIST_HEAD(dmabounce_devs); @@ -82,9 +87,9 @@ static void print_alloc_stats(struct dmabounce_device_info *device_info) printk(KERN_INFO "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n", device_info->dev->bus_id, - device_info->sbp_allocs, device_info->lbp_allocs, - device_info->total_allocs - device_info->sbp_allocs - - device_info->lbp_allocs, + device_info->small.allocs, device_info->large.allocs, + device_info->total_allocs - device_info->small.allocs - + device_info->large.allocs, device_info->total_allocs); } #endif @@ -106,18 +111,22 @@ find_dmabounce_dev(struct device *dev) /* allocate a 'safe' buffer and keep track of it */ static inline struct safe_buffer * alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, - size_t size, enum dma_data_direction dir) + size_t size, enum dma_data_direction dir) { struct safe_buffer *buf; - struct dma_pool *pool; + struct dmabounce_pool *pool; struct device *dev = device_info->dev; - void *safe; - dma_addr_t safe_dma_addr; dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n", __func__, ptr, size, dir); - DO_STATS ( device_info->total_allocs++ ); + if (size <= device_info->small.size) { + pool = &device_info->small; + } else if (size <= device_info->large.size) { + pool = &device_info->large; + } else { + pool = NULL; + } buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC); if (buf == NULL) { @@ -125,41 +134,35 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, return NULL; } - if (size <= device_info->small_buffer_size) { - pool = device_info->small_buffer_pool; - safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); - - DO_STATS ( device_info->sbp_allocs++ ); - } else if (size <= device_info->large_buffer_size) { - pool = device_info->large_buffer_pool; - safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + buf->ptr = ptr; + buf->size = size; + buf->direction = dir; + buf->pool = pool; - DO_STATS ( device_info->lbp_allocs++ ); + if (pool) { + buf->safe = dma_pool_alloc(pool->pool, GFP_ATOMIC, + &buf->safe_dma_addr); } else { - pool = NULL; - safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC); + buf->safe = dma_alloc_coherent(dev, size, &buf->safe_dma_addr, + GFP_ATOMIC); } - if (safe == NULL) { - dev_warn(device_info->dev, - "%s: could not alloc dma memory (size=%d)\n", - __func__, size); + if (buf->safe == NULL) { + dev_warn(dev, + "%s: could not alloc dma memory (size=%d)\n", + __func__, size); kfree(buf); return NULL; } #ifdef STATS + if (pool) + pool->allocs++; + device_info->total_allocs++; if (device_info->total_allocs % 1000 == 0) print_alloc_stats(device_info); #endif - buf->ptr = ptr; - buf->size = size; - buf->direction = dir; - buf->pool = pool; - buf->safe = safe; - buf->safe_dma_addr = safe_dma_addr; - list_add(&buf->node, &device_info->safe_buffers); return buf; @@ -186,7 +189,7 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer * list_del(&buf->node); if (buf->pool) - dma_pool_free(buf->pool, buf->safe, buf->safe_dma_addr); + dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr); else dma_free_coherent(device_info->dev, buf->size, buf->safe, buf->safe_dma_addr); @@ -197,12 +200,10 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer * /* ************************************************** */ #ifdef STATS - static void print_map_stats(struct dmabounce_device_info *device_info) { - printk(KERN_INFO - "%s: dmabounce: map_op_count=%lu, bounce_count=%lu\n", - device_info->dev->bus_id, + dev_info(device_info->dev, + "dmabounce: map_op_count=%lu, bounce_count=%lu\n", device_info->map_op_count, device_info->bounce_count); } #endif @@ -258,13 +259,13 @@ map_single(struct device *dev, void *ptr, size_t size, __func__, ptr, buf->safe, size); memcpy(buf->safe, ptr, size); } - consistent_sync(buf->safe, size, dir); + ptr = buf->safe; dma_addr = buf->safe_dma_addr; - } else { - consistent_sync(ptr, size, dir); } + consistent_sync(ptr, size, dir); + return dma_addr; } @@ -278,7 +279,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, /* * Trying to unmap an invalid mapping */ - if (dma_addr == ~0) { + if (dma_mapping_error(dma_addr)) { dev_err(dev, "Trying to unmap invalid mapping\n"); return; } @@ -570,11 +571,25 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, local_irq_restore(flags); } +static int +dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev, const char *name, + unsigned long size) +{ + pool->size = size; + DO_STATS(pool->allocs = 0); + pool->pool = dma_pool_create(name, dev, size, + 0 /* byte alignment */, + 0 /* no page-crossing issues */); + + return pool->pool ? 0 : -ENOMEM; +} + int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, unsigned long large_buffer_size) { struct dmabounce_device_info *device_info; + int ret; device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC); if (!device_info) { @@ -584,45 +599,31 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, return -ENOMEM; } - device_info->small_buffer_pool = - dma_pool_create("small_dmabounce_pool", - dev, - small_buffer_size, - 0 /* byte alignment */, - 0 /* no page-crossing issues */); - if (!device_info->small_buffer_pool) { - printk(KERN_ERR - "dmabounce: could not allocate small DMA pool for %s\n", - dev->bus_id); - kfree(device_info); - return -ENOMEM; + ret = dmabounce_init_pool(&device_info->small, dev, + "small_dmabounce_pool", small_buffer_size); + if (ret) { + dev_err(dev, + "dmabounce: could not allocate DMA pool for %ld byte objects\n", + small_buffer_size); + goto err_free; } if (large_buffer_size) { - device_info->large_buffer_pool = - dma_pool_create("large_dmabounce_pool", - dev, - large_buffer_size, - 0 /* byte alignment */, - 0 /* no page-crossing issues */); - if (!device_info->large_buffer_pool) { - printk(KERN_ERR - "dmabounce: could not allocate large DMA pool for %s\n", - dev->bus_id); - dma_pool_destroy(device_info->small_buffer_pool); - - return -ENOMEM; + ret = dmabounce_init_pool(&device_info->large, dev, + "large_dmabounce_pool", + large_buffer_size); + if (ret) { + dev_err(dev, + "dmabounce: could not allocate DMA pool for %ld byte objects\n", + large_buffer_size); + goto err_destroy; } } device_info->dev = dev; - device_info->small_buffer_size = small_buffer_size; - device_info->large_buffer_size = large_buffer_size; INIT_LIST_HEAD(&device_info->safe_buffers); #ifdef STATS - device_info->sbp_allocs = 0; - device_info->lbp_allocs = 0; device_info->total_allocs = 0; device_info->map_op_count = 0; device_info->bounce_count = 0; @@ -634,6 +635,12 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, dev->bus_id, dev->bus->name); return 0; + + err_destroy: + dma_pool_destroy(device_info->small.pool); + err_free: + kfree(device_info); + return ret; } void @@ -655,10 +662,10 @@ dmabounce_unregister_dev(struct device *dev) BUG(); } - if (device_info->small_buffer_pool) - dma_pool_destroy(device_info->small_buffer_pool); - if (device_info->large_buffer_pool) - dma_pool_destroy(device_info->large_buffer_pool); + if (device_info->small.pool) + dma_pool_destroy(device_info->small.pool); + if (device_info->large.pool) + dma_pool_destroy(device_info->large.pool); #ifdef STATS print_alloc_stats(device_info); diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index e8356b76d7c..4af0cf5f3bf 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -12,6 +12,9 @@ */ #include <linux/device.h> +#include <linux/string.h> +#include <linux/slab.h> + #include <asm/io.h> #include <asm/hardware/scoop.h> diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index 678720fa2e2..ddeb9f99d66 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig @@ -559,7 +559,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_NR_UARTS=1 # CONFIG_SERIAL_8250_EXTENDED is not set # diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index 261e2343903..81d3a0606f9 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig @@ -559,7 +559,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_NR_UARTS=1 # CONFIG_SERIAL_8250_EXTENDED is not set # diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c index a418dad6692..0ee2e981963 100644 --- a/arch/arm/kernel/arthur.c +++ b/arch/arm/kernel/arthur.c @@ -18,6 +18,7 @@ #include <linux/stddef.h> #include <linux/signal.h> #include <linux/init.h> +#include <linux/sched.h> #include <asm/ptrace.h> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index cd99b83f14c..9bd8609a292 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -782,7 +782,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 69449a818dc..fc4729106a3 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -36,10 +36,6 @@ #include <asm/thread_info.h> #include <asm/mach/time.h> -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - /* * Our system timer. */ diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 66e5a0516f2..45e9ea6cd2a 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -198,25 +198,16 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) barrier(); } -DEFINE_SPINLOCK(die_lock); - -/* - * This function is protected against re-entrancy. - */ -NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) +static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) { - struct task_struct *tsk = current; + struct task_struct *tsk = thread->task; static int die_counter; - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); - printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); print_modules(); __show_regs(regs); printk("Process %s (pid: %d, stack limit = 0x%p)\n", - tsk->comm, tsk->pid, tsk->thread_info + 1); + tsk->comm, tsk->pid, thread + 1); if (!user_mode(regs) || in_interrupt()) { dump_mem("Stack: ", regs->ARM_sp, @@ -224,7 +215,21 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) dump_backtrace(regs, tsk); dump_instr(regs); } +} +DEFINE_SPINLOCK(die_lock); + +/* + * This function is protected against re-entrancy. + */ +NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) +{ + struct thread_info *thread = current_thread_info(); + + console_verbose(); + spin_lock_irq(&die_lock); + bust_spinlocks(1); + __die(str, err, thread, regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S new file mode 100644 index 00000000000..561e20717b3 --- /dev/null +++ b/arch/arm/lib/ashldi3.S @@ -0,0 +1,48 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file 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, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#include <linux/linkage.h> + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +ENTRY(__ashldi3) + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi ah, ah, lsl r2 + movpl ah, al, lsl r3 + orrmi ah, ah, al, lsr ip + mov al, al, lsl r2 + mov pc, lr + diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c deleted file mode 100644 index b62875cfd8f..00000000000 --- a/arch/arm/lib/ashldi3.c +++ /dev/null @@ -1,56 +0,0 @@ -/* More subroutines needed by GCC output code on some machines. */ -/* Compile this one with gcc. */ -/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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, or (at your option) -any later version. - -GNU CC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. - */ -/* support functions required by the kernel. based on code from gcc-2.95.3 */ -/* I Molton 29/07/01 */ - -#include "gcclib.h" - -s64 __ashldi3(s64 u, int b) -{ - DIunion w; - int bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof(s32) * BITS_PER_UNIT) - b; - if (bm <= 0) { - w.s.low = 0; - w.s.high = (u32) uu.s.low << -bm; - } else { - u32 carries = (u32) uu.s.low >> bm; - w.s.low = (u32) uu.s.low << b; - w.s.high = ((u32) uu.s.high << b) | carries; - } - - return w.ll; -} diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S new file mode 100644 index 00000000000..86fb2a90c30 --- /dev/null +++ b/arch/arm/lib/ashrdi3.S @@ -0,0 +1,48 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file 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, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#include <linux/linkage.h> + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +ENTRY(__ashrdi3) + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, asr r3 + orrmi al, al, ah, lsl ip + mov ah, ah, asr r2 + mov pc, lr + diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c deleted file mode 100644 index 9a8600a7543..00000000000 --- a/arch/arm/lib/ashrdi3.c +++ /dev/null @@ -1,57 +0,0 @@ -/* More subroutines needed by GCC output code on some machines. */ -/* Compile this one with gcc. */ -/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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, or (at your option) -any later version. - -GNU CC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. - */ -/* support functions required by the kernel. based on code from gcc-2.95.3 */ -/* I Molton 29/07/01 */ - -#include "gcclib.h" - -s64 __ashrdi3(s64 u, int b) -{ - DIunion w; - int bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof(s32) * BITS_PER_UNIT) - b; - if (bm <= 0) { - /* w.s.high = 1..1 or 0..0 */ - w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1); - w.s.low = uu.s.high >> -bm; - } else { - u32 carries = (u32) uu.s.high << bm; - w.s.high = uu.s.high >> b; - w.s.low = ((u32) uu.s.low >> b) | carries; - } - - return w.ll; -} diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h deleted file mode 100644 index 8b6dcc656de..00000000000 --- a/arch/arm/lib/gcclib.h +++ /dev/null @@ -1,22 +0,0 @@ -/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */ -/* I Molton 29/07/01 */ - -#include <linux/types.h> - -#define BITS_PER_UNIT 8 -#define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT) - -#ifdef __ARMEB__ -struct DIstruct { - s32 high, low; -}; -#else -struct DIstruct { - s32 low, high; -}; -#endif - -typedef union { - struct DIstruct s; - s64 ll; -} DIunion; diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S new file mode 100644 index 00000000000..46c2ed19ec9 --- /dev/null +++ b/arch/arm/lib/lshrdi3.S @@ -0,0 +1,48 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file 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, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#include <linux/linkage.h> + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +ENTRY(__lshrdi3) + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, lsr r3 + orrmi al, al, ah, lsl ip + mov ah, ah, lsr r2 + mov pc, lr + diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c deleted file mode 100644 index 3681f49d2b6..00000000000 --- a/arch/arm/lib/lshrdi3.c +++ /dev/null @@ -1,56 +0,0 @@ -/* More subroutines needed by GCC output code on some machines. */ -/* Compile this one with gcc. */ -/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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, or (at your option) -any later version. - -GNU CC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. - */ -/* support functions required by the kernel. based on code from gcc-2.95.3 */ -/* I Molton 29/07/01 */ - -#include "gcclib.h" - -s64 __lshrdi3(s64 u, int b) -{ - DIunion w; - int bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof(s32) * BITS_PER_UNIT) - b; - if (bm <= 0) { - w.s.high = 0; - w.s.low = (u32) uu.s.high >> -bm; - } else { - u32 carries = (u32) uu.s.high << bm; - w.s.high = (u32) uu.s.high >> b; - w.s.low = ((u32) uu.s.low >> b) | carries; - } - - return w.ll; -} diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S new file mode 100644 index 00000000000..c7fbdf00531 --- /dev/null +++ b/arch/arm/lib/muldi3.S @@ -0,0 +1,44 @@ +/* + * linux/arch/arm/lib/muldi3.S + * + * Author: Nicolas Pitre + * Created: Oct 19, 2005 + * Copyright: Monta Vista Software, Inc. + * + * 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 + * published by the Free Software Foundation. + */ + +#include <linux/linkage.h> + +#ifdef __ARMEB__ +#define xh r0 +#define xl r1 +#define yh r2 +#define yl r3 +#else +#define xl r0 +#define xh r1 +#define yl r2 +#define yh r3 +#endif + +ENTRY(__muldi3) + + mul xh, yl, xh + mla xh, xl, yh, xh + mov ip, xl, asr #16 + mov yh, yl, asr #16 + bic xl, xl, ip, lsl #16 + bic yl, yl, yh, lsl #16 + mla xh, yh, ip, xh + mul yh, xl, yh + mul xl, yl, xl + mul ip, yl, ip + adds xl, xl, yh, lsl #16 + adc xh, xh, yh, lsr #16 + adds xl, xl, ip, lsl #16 + adc xh, xh, ip, lsr #16 + mov pc, lr + diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c deleted file mode 100644 index 0a3b93313f1..00000000000 --- a/arch/arm/lib/muldi3.c +++ /dev/null @@ -1,72 +0,0 @@ -/* More subroutines needed by GCC output code on some machines. */ -/* Compile this one with gcc. */ -/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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, or (at your option) -any later version. - -GNU CC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. - */ -/* support functions required by the kernel. based on code from gcc-2.95.3 */ -/* I Molton 29/07/01 */ - -#include "gcclib.h" - -#define umul_ppmm(xh, xl, a, b) \ -{register u32 __t0, __t1, __t2; \ - __asm__ ("%@ Inlined umul_ppmm \n\ - mov %2, %5, lsr #16 \n\ - mov %0, %6, lsr #16 \n\ - bic %3, %5, %2, lsl #16 \n\ - bic %4, %6, %0, lsl #16 \n\ - mul %1, %3, %4 \n\ - mul %4, %2, %4 \n\ - mul %3, %0, %3 \n\ - mul %0, %2, %0 \n\ - adds %3, %4, %3 \n\ - addcs %0, %0, #65536 \n\ - adds %1, %1, %3, lsl #16 \n\ - adc %0, %0, %3, lsr #16" \ - : "=&r" ((u32) (xh)), \ - "=r" ((u32) (xl)), \ - "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ - : "r" ((u32) (a)), \ - "r" ((u32) (b)));} - -#define __umulsidi3(u, v) \ - ({DIunion __w; \ - umul_ppmm (__w.s.high, __w.s.low, u, v); \ - __w.ll; }) - -s64 __muldi3(s64 u, s64 v) -{ - DIunion w; - DIunion uu, vv; - - uu.ll = u, vv.ll = v; - - w.ll = __umulsidi3(uu.s.low, vv.s.low); - w.s.high += ((u32) uu.s.low * (u32) vv.s.high - + (u32) uu.s.high * (u32) vv.s.low); - - return w.ll; -} diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S new file mode 100644 index 00000000000..112630f93e5 --- /dev/null +++ b/arch/arm/lib/ucmpdi2.S @@ -0,0 +1,35 @@ +/* + * linux/arch/arm/lib/ucmpdi2.S + * + * Author: Nicolas Pitre + * Created: Oct 19, 2005 + * Copyright: Monta Vista Software, Inc. + * + * 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 + * published by the Free Software Foundation. + */ + +#include <linux/linkage.h> + +#ifdef __ARMEB__ +#define xh r0 +#define xl r1 +#define yh r2 +#define yl r3 +#else +#define xl r0 +#define xh r1 +#define yl r2 +#define yh r3 +#endif + +ENTRY(__ucmpdi2) + + cmp xh, yh + cmpeq xl, yl + movlo r0, #0 + moveq r0, #1 + movhi r0, #2 + mov pc, lr + diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c deleted file mode 100644 index 57f3f2df385..00000000000 --- a/arch/arm/lib/ucmpdi2.c +++ /dev/null @@ -1,49 +0,0 @@ -/* More subroutines needed by GCC output code on some machines. */ -/* Compile this one with gcc. */ -/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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, or (at your option) -any later version. - -GNU CC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. - */ -/* support functions required by the kernel. based on code from gcc-2.95.3 */ -/* I Molton 29/07/01 */ - -#include "gcclib.h" - -int __ucmpdi2(s64 a, s64 b) -{ - DIunion au, bu; - - au.ll = a, bu.ll = b; - - if ((u32) au.s.high < (u32) bu.s.high) - return 0; - else if ((u32) au.s.high > (u32) bu.s.high) - return 2; - if ((u32) au.s.low < (u32) bu.s.low) - return 0; - else if ((u32) au.s.low > (u32) bu.s.low) - return 2; - return 1; -} diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c index cb14b0682ce..837d7f0bda4 100644 --- a/arch/arm/mach-imx/generic.c +++ b/arch/arm/mach-imx/generic.c @@ -26,6 +26,8 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/string.h> + #include <asm/arch/imxfb.h> #include <asm/hardware.h> #include <asm/arch/imx-regs.h> diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index 56200594db3..73c360685ca 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c @@ -13,6 +13,7 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> +#include <linux/string.h> #include <asm/semaphore.h> #include <asm/hardware/clock.h> diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index f368b85f044..764ceb49470 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -30,6 +30,7 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/setup.h> +#include <asm/param.h> /* HZ */ #include <asm/mach-types.h> #include <asm/hardware/amba.h> #include <asm/hardware/amba_kmi.h> diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c index c5f19d16059..5b41e3a724e 100644 --- a/arch/arm/mach-integrator/lm.c +++ b/arch/arm/mach-integrator/lm.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/slab.h> #include <asm/arch/lm.h> diff --git a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c index f997daa800b..c6a973ba8fc 100644 --- a/arch/arm/mach-iop3xx/iq31244-pci.c +++ b/arch/arm/mach-iop3xx/iq31244-pci.c @@ -14,6 +14,8 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/hardware.h> #include <asm/irq.h> diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c index 79fea3d20b6..802f6d091b7 100644 --- a/arch/arm/mach-iop3xx/iq80321-pci.c +++ b/arch/arm/mach-iop3xx/iq80321-pci.c @@ -14,6 +14,8 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/hardware.h> #include <asm/irq.h> diff --git a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c index f37a0e26b46..654e450a131 100644 --- a/arch/arm/mach-iop3xx/iq80331-pci.c +++ b/arch/arm/mach-iop3xx/iq80331-pci.c @@ -13,6 +13,8 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/hardware.h> #include <asm/irq.h> diff --git a/arch/arm/mach-iop3xx/iq80332-pci.c b/arch/arm/mach-iop3xx/iq80332-pci.c index b9807aa2aad..65951ffe463 100644 --- a/arch/arm/mach-iop3xx/iq80332-pci.c +++ b/arch/arm/mach-iop3xx/iq80332-pci.c @@ -13,6 +13,8 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/hardware.h> #include <asm/irq.h> diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 60c8b9d8bb9..656f73bbcb5 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -33,6 +33,7 @@ #include <asm/arch/pxa-regs.h> #include <asm/arch/irq.h> +#include <asm/arch/irda.h> #include <asm/arch/mmc.h> #include <asm/arch/udc.h> #include <asm/arch/corgi.h> @@ -224,6 +225,22 @@ static struct pxamci_platform_data corgi_mci_platform_data = { }; +/* + * Irda + */ +static void corgi_irda_transceiver_mode(struct device *dev, int mode) +{ + if (mode & IR_OFF) + GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON); + else + GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON); +} + +static struct pxaficp_platform_data corgi_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = corgi_irda_transceiver_mode, +}; + /* * USB Device Controller @@ -269,10 +286,13 @@ static void __init corgi_init(void) corgi_ssp_set_machinfo(&corgi_ssp_machinfo); + pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT); pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT); pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); + pxa_set_udc_info(&udc_info); pxa_set_mci_info(&corgi_mci_platform_data); + pxa_set_ficp_info(&corgi_ficp_platform_data); scoop_num = 1; scoop_devs = &corgi_pcmcia_scoop[0]; diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 3248bc9b949..9c028933330 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -23,6 +23,7 @@ #include <linux/device.h> #include <linux/ioport.h> #include <linux/pm.h> +#include <linux/string.h> #include <asm/hardware.h> #include <asm/irq.h> diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index f2563881001..6d413f6701a 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -32,6 +32,7 @@ #include <asm/arch/irq.h> #include <asm/arch/mmc.h> #include <asm/arch/udc.h> +#include <asm/arch/irda.h> #include <asm/arch/poodle.h> #include <asm/arch/pxafb.h> @@ -152,6 +153,24 @@ static struct pxamci_platform_data poodle_mci_platform_data = { /* + * Irda + */ +static void poodle_irda_transceiver_mode(struct device *dev, int mode) +{ + if (mode & IR_OFF) { + GPSR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON); + } else { + GPCR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON); + } +} + +static struct pxaficp_platform_data poodle_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = poodle_irda_transceiver_mode, +}; + + +/* * USB Device Controller */ static void poodle_udc_command(int cmd) @@ -244,8 +263,10 @@ static void __init poodle_init(void) set_pxa_fb_info(&poodle_fb_info); pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT); + pxa_gpio_mode(POODLE_GPIO_IR_ON | GPIO_OUT); pxa_set_udc_info(&udc_info); pxa_set_mci_info(&poodle_mci_platform_data); + pxa_set_ficp_info(&poodle_ficp_platform_data); scoop_num = 1; scoop_devs = &poodle_pcmcia_scoop[0]; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index d0ab428c2d7..b838842b6a2 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -34,6 +34,7 @@ #include <asm/arch/pxa-regs.h> #include <asm/arch/irq.h> +#include <asm/arch/irda.h> #include <asm/arch/mmc.h> #include <asm/arch/udc.h> #include <asm/arch/pxafb.h> @@ -277,6 +278,23 @@ static struct pxamci_platform_data spitz_mci_platform_data = { /* + * Irda + */ +static void spitz_irda_transceiver_mode(struct device *dev, int mode) +{ + if (mode & IR_OFF) + set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); + else + reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); +} + +static struct pxaficp_platform_data spitz_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = spitz_irda_transceiver_mode, +}; + + +/* * Spitz PXA Framebuffer */ static struct pxafb_mach_info spitz_pxafb_info __initdata = { @@ -326,6 +344,7 @@ static void __init common_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_mci_info(&spitz_mci_platform_data); + pxa_set_ficp_info(&spitz_ficp_platform_data); set_pxa_fb_parent(&spitzssp_device.dev); set_pxa_fb_info(&spitz_pxafb_info); } diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index f94b0fbcdcc..83eba8b5481 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -17,6 +17,7 @@ #include <linux/pm.h> #include <linux/cpufreq.h> #include <linux/ioport.h> +#include <linux/sched.h> /* just for sched_clock() - funny that */ #include <asm/div64.h> #include <asm/hardware.h> diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index 48025c2b998..b96a2ea15d4 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c @@ -13,6 +13,7 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> +#include <linux/string.h> #include <asm/semaphore.h> #include <asm/hardware/clock.h> diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index 27d041574ea..269ce6913ee 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -22,9 +22,7 @@ #endif #define from_address (0xffff8000) -#define from_pgprot PAGE_KERNEL #define to_address (0xffffc000) -#define to_pgprot PAGE_KERNEL #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) @@ -34,7 +32,7 @@ static DEFINE_SPINLOCK(v6_lock); * Copy the user page. No aliasing to deal with so we can just * attack the kernel's existing mapping of these pages. */ -void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr) +static void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr) { copy_page(kto, kfrom); } @@ -43,7 +41,7 @@ void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long v * Clear the user page. No aliasing to deal with so we can just * attack the kernel's existing mapping of this page. */ -void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr) +static void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr) { clear_page(kaddr); } @@ -51,7 +49,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr) /* * Copy the page, taking account of the cache colour. */ -void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr) +static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr) { unsigned int offset = CACHE_COLOUR(vaddr); unsigned long from, to; @@ -72,8 +70,8 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd */ spin_lock(&v6_lock); - set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot)); - set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot)); + set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, PAGE_KERNEL)); + set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, PAGE_KERNEL)); from = from_address + (offset << PAGE_SHIFT); to = to_address + (offset << PAGE_SHIFT); @@ -91,7 +89,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd * so remap the kernel page into the same cache colour as the user * page. */ -void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) +static void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) { unsigned int offset = CACHE_COLOUR(vaddr); unsigned long to = to_address + (offset << PAGE_SHIFT); @@ -112,7 +110,7 @@ void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) */ spin_lock(&v6_lock); - set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot)); + set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, PAGE_KERNEL)); flush_tlb_kernel_page(to); clear_page((void *)to); diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 52a58b2da28..a020fe16428 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -13,6 +13,7 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> +#include <linux/string.h> #include <asm/io.h> #include <asm/semaphore.h> diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 8a52124de0e..cf7e977d18c 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -665,7 +665,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c index e66aedd02fa..335525339ad 100644 --- a/arch/arm26/kernel/time.c +++ b/arch/arm26/kernel/time.c @@ -34,10 +34,6 @@ #include <asm/irq.h> #include <asm/ioc.h> -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - extern unsigned long wall_jiffies; /* this needs a better home */ diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c index 11ab3836aac..56b038c8d48 100644 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/arch/cris/arch-v10/drivers/axisflashmap.c @@ -140,6 +140,7 @@ #include <linux/kernel.h> #include <linux/config.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/mtd/concat.h> #include <linux/mtd/map.h> diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c index 78ed52b1cda..b679f983b90 100644 --- a/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/arch/cris/arch-v32/drivers/axisflashmap.c @@ -20,6 +20,7 @@ #include <linux/kernel.h> #include <linux/config.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/mtd/concat.h> #include <linux/mtd/map.h> diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c index a2d99b4aedc..66ba8898db0 100644 --- a/arch/cris/kernel/time.c +++ b/arch/cris/kernel/time.c @@ -31,10 +31,7 @@ #include <linux/timex.h> #include <linux/init.h> #include <linux/profile.h> - -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); +#include <linux/sched.h> /* just for sched_clock() - funny that */ int have_rtc; /* used to remember if we have an RTC or not */; diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index cbe03cba9f0..cb335a14a31 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -106,7 +106,7 @@ void ptrace_enable(struct task_struct *child) child->thread.frame0->__status |= REG__STATUS_STEP; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; unsigned long tmp; diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c index f43b734482e..2e9741227b7 100644 --- a/arch/frv/kernel/time.c +++ b/arch/frv/kernel/time.c @@ -34,9 +34,6 @@ extern unsigned long wall_jiffies; -u64 jiffies_64 = INITIAL_JIFFIES; -EXPORT_SYMBOL(jiffies_64); - unsigned long __nongprelbss __clkin_clock_speed_HZ; unsigned long __nongprelbss __ext_bus_clock_speed_HZ; unsigned long __nongprelbss __res_bus_clock_speed_HZ; diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index 05c15e86977..a569fe4aa28 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -57,7 +57,7 @@ void ptrace_disable(struct task_struct *child) h8300_disable_trace(child); } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c index af8c5d2057d..688a5100604 100644 --- a/arch/h8300/kernel/time.c +++ b/arch/h8300/kernel/time.c @@ -32,10 +32,6 @@ #define TICK_SIZE (tick_nsec / 1000) -u64 jiffies_64; - -EXPORT_SYMBOL(jiffies_64); - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index d2703cda61e..5383e5e2d9b 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -5,7 +5,7 @@ mainmenu "Linux Kernel Configuration" -config X86 +config X86_32 bool default y help @@ -18,6 +18,10 @@ config SEMAPHORE_SLEEPERS bool default y +config X86 + bool + default y + config MMU bool default y @@ -151,304 +155,7 @@ config ES7000_CLUSTERED_APIC default y depends on SMP && X86_ES7000 && MPENTIUMIII -if !X86_ELAN - -choice - prompt "Processor family" - default M686 - -config M386 - bool "386" - ---help--- - This is the processor type of your CPU. This information is used for - optimizing purposes. In order to compile a kernel that can run on - all x86 CPU types (albeit not optimally fast), you can specify - "386" here. - - The kernel will not necessarily run on earlier architectures than - the one you have chosen, e.g. a Pentium optimized kernel will run on - a PPro, but not necessarily on a i486. - - Here are the settings recommended for greatest speed: - - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI - 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels - will run on a 386 class machine. - - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or - SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. - - "586" for generic Pentium CPUs lacking the TSC - (time stamp counter) register. - - "Pentium-Classic" for the Intel Pentium. - - "Pentium-MMX" for the Intel Pentium MMX. - - "Pentium-Pro" for the Intel Pentium Pro. - - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron. - - "Pentium-III" for the Intel Pentium III or Coppermine Celeron. - - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron. - - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). - - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). - - "Crusoe" for the Transmeta Crusoe series. - - "Efficeon" for the Transmeta Efficeon series. - - "Winchip-C6" for original IDT Winchip. - - "Winchip-2" for IDT Winchip 2. - - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. - - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). - - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. - - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). - - If you don't know what to do, choose "386". - -config M486 - bool "486" - help - Select this for a 486 series processor, either Intel or one of the - compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, - DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or - U5S. - -config M586 - bool "586/K5/5x86/6x86/6x86MX" - help - Select this for an 586 or 686 series processor such as the AMD K5, - the Cyrix 5x86, 6x86 and 6x86MX. This choice does not - assume the RDTSC (Read Time Stamp Counter) instruction. - -config M586TSC - bool "Pentium-Classic" - help - Select this for a Pentium Classic processor with the RDTSC (Read - Time Stamp Counter) instruction for benchmarking. - -config M586MMX - bool "Pentium-MMX" - help - Select this for a Pentium with the MMX graphics/multimedia - extended instructions. - -config M686 - bool "Pentium-Pro" - help - Select this for Intel Pentium Pro chips. This enables the use of - Pentium Pro extended instructions, and disables the init-time guard - against the f00f bug found in earlier Pentiums. - -config MPENTIUMII - bool "Pentium-II/Celeron(pre-Coppermine)" - help - Select this for Intel chips based on the Pentium-II and - pre-Coppermine Celeron core. This option enables an unaligned - copy optimization, compiles the kernel with optimization flags - tailored for the chip, and applies any applicable Pentium Pro - optimizations. - -config MPENTIUMIII - bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" - help - Select this for Intel chips based on the Pentium-III and - Celeron-Coppermine core. This option enables use of some - extended prefetch instructions in addition to the Pentium II - extensions. - -config MPENTIUMM - bool "Pentium M" - help - Select this for Intel Pentium M (not Pentium-4 M) - notebook chips. - -config MPENTIUM4 - bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon" - help - Select this for Intel Pentium 4 chips. This includes the - Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M - (not Pentium M) chips. This option enables compile flags - optimized for the chip, uses the correct cache shift, and - applies any applicable Pentium III optimizations. - -config MK6 - bool "K6/K6-II/K6-III" - help - Select this for an AMD K6-family processor. Enables use of - some extended instructions, and passes appropriate optimization - flags to GCC. - -config MK7 - bool "Athlon/Duron/K7" - help - Select this for an AMD Athlon K7-family processor. Enables use of - some extended instructions, and passes appropriate optimization - flags to GCC. - -config MK8 - bool "Opteron/Athlon64/Hammer/K8" - help - Select this for an AMD Opteron or Athlon64 Hammer-family processor. Enables - use of some extended instructions, and passes appropriate optimization - flags to GCC. - -config MCRUSOE - bool "Crusoe" - help - Select this for a Transmeta Crusoe processor. Treats the processor - like a 586 with TSC, and sets some GCC optimization flags (like a - Pentium Pro with no alignment requirements). - -config MEFFICEON - bool "Efficeon" - help - Select this for a Transmeta Efficeon processor. - -config MWINCHIPC6 - bool "Winchip-C6" - help - Select this for an IDT Winchip C6 chip. Linux and GCC - treat this chip as a 586TSC with some extended instructions - and alignment requirements. - -config MWINCHIP2 - bool "Winchip-2" - help - Select this for an IDT Winchip-2. Linux and GCC - treat this chip as a 586TSC with some extended instructions - and alignment requirements. - -config MWINCHIP3D - bool "Winchip-2A/Winchip-3" - help - Select this for an IDT Winchip-2A or 3. Linux and GCC - treat this chip as a 586TSC with some extended instructions - and alignment reqirements. Also enable out of order memory - stores for this CPU, which can increase performance of some - operations. - -config MGEODEGX1 - bool "GeodeGX1" - help - Select this for a Geode GX1 (Cyrix MediaGX) chip. - -config MCYRIXIII - bool "CyrixIII/VIA-C3" - help - Select this for a Cyrix III or C3 chip. Presently Linux and GCC - treat this chip as a generic 586. Whilst the CPU is 686 class, - it lacks the cmov extension which gcc assumes is present when - generating 686 code. - Note that Nehemiah (Model 9) and above will not boot with this - kernel due to them lacking the 3DNow! instructions used in earlier - incarnations of the CPU. - -config MVIAC3_2 - bool "VIA C3-2 (Nehemiah)" - help - Select this for a VIA C3 "Nehemiah". Selecting this enables usage - of SSE and tells gcc to treat the CPU as a 686. - Note, this kernel will not boot on older (pre model 9) C3s. - -endchoice - -config X86_GENERIC - bool "Generic x86 support" - help - Instead of just including optimizations for the selected - x86 variant (e.g. PII, Crusoe or Athlon), include some more - generic optimizations as well. This will make the kernel - perform better on x86 CPUs other than that selected. - - This is really intended for distributors who need more - generic optimizations. - -endif - -# -# Define implied options from the CPU selection here -# -config X86_CMPXCHG - bool - depends on !M386 - default y - -config X86_XADD - bool - depends on !M386 - default y - -config X86_L1_CACHE_SHIFT - int - default "7" if MPENTIUM4 || X86_GENERIC - default "4" if X86_ELAN || M486 || M386 - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1 - default "6" if MK7 || MK8 || MPENTIUMM - -config RWSEM_GENERIC_SPINLOCK - bool - depends on M386 - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - depends on !M386 - default y - -config GENERIC_CALIBRATE_DELAY - bool - default y - -config X86_PPRO_FENCE - bool - depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1 - default y - -config X86_F00F_BUG - bool - depends on M586MMX || M586TSC || M586 || M486 || M386 - default y - -config X86_WP_WORKS_OK - bool - depends on !M386 - default y - -config X86_INVLPG - bool - depends on !M386 - default y - -config X86_BSWAP - bool - depends on !M386 - default y - -config X86_POPAD_OK - bool - depends on !M386 - default y - -config X86_ALIGNMENT_16 - bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 - default y - -config X86_GOOD_APIC - bool - depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON - default y - -config X86_INTEL_USERCOPY - bool - depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON - default y - -config X86_USE_PPRO_CHECKSUM - bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON - default y - -config X86_USE_3DNOW - bool - depends on MCYRIXIII || MK7 - default y - -config X86_OOSTORE - bool - depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR - default y +source "arch/i386/Kconfig.cpu" config HPET_TIMER bool "HPET Timer Support" @@ -561,11 +268,6 @@ config X86_VISWS_APIC depends on X86_VISWS default y -config X86_TSC - bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ - default y - config X86_MCE bool "Machine Check Exception" depends on !X86_VOYAGER diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu new file mode 100644 index 00000000000..53bbb3c008e --- /dev/null +++ b/arch/i386/Kconfig.cpu @@ -0,0 +1,309 @@ +# Put here option for CPU selection and depending optimization +if !X86_ELAN + +choice + prompt "Processor family" + default M686 + +config M386 + bool "386" + ---help--- + This is the processor type of your CPU. This information is used for + optimizing purposes. In order to compile a kernel that can run on + all x86 CPU types (albeit not optimally fast), you can specify + "386" here. + + The kernel will not necessarily run on earlier architectures than + the one you have chosen, e.g. a Pentium optimized kernel will run on + a PPro, but not necessarily on a i486. + + Here are the settings recommended for greatest speed: + - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI + 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels + will run on a 386 class machine. + - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or + SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. + - "586" for generic Pentium CPUs lacking the TSC + (time stamp counter) register. + - "Pentium-Classic" for the Intel Pentium. + - "Pentium-MMX" for the Intel Pentium MMX. + - "Pentium-Pro" for the Intel Pentium Pro. + - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron. + - "Pentium-III" for the Intel Pentium III or Coppermine Celeron. + - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron. + - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). + - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). + - "Crusoe" for the Transmeta Crusoe series. + - "Efficeon" for the Transmeta Efficeon series. + - "Winchip-C6" for original IDT Winchip. + - "Winchip-2" for IDT Winchip 2. + - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. + - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). + - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. + - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). + + If you don't know what to do, choose "386". + +config M486 + bool "486" + help + Select this for a 486 series processor, either Intel or one of the + compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, + DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or + U5S. + +config M586 + bool "586/K5/5x86/6x86/6x86MX" + help + Select this for an 586 or 686 series processor such as the AMD K5, + the Cyrix 5x86, 6x86 and 6x86MX. This choice does not + assume the RDTSC (Read Time Stamp Counter) instruction. + +config M586TSC + bool "Pentium-Classic" + help + Select this for a Pentium Classic processor with the RDTSC (Read + Time Stamp Counter) instruction for benchmarking. + +config M586MMX + bool "Pentium-MMX" + help + Select this for a Pentium with the MMX graphics/multimedia + extended instructions. + +config M686 + bool "Pentium-Pro" + help + Select this for Intel Pentium Pro chips. This enables the use of + Pentium Pro extended instructions, and disables the init-time guard + against the f00f bug found in earlier Pentiums. + +config MPENTIUMII + bool "Pentium-II/Celeron(pre-Coppermine)" + help + Select this for Intel chips based on the Pentium-II and + pre-Coppermine Celeron core. This option enables an unaligned + copy optimization, compiles the kernel with optimization flags + tailored for the chip, and applies any applicable Pentium Pro + optimizations. + +config MPENTIUMIII + bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" + help + Select this for Intel chips based on the Pentium-III and + Celeron-Coppermine core. This option enables use of some + extended prefetch instructions in addition to the Pentium II + extensions. + +config MPENTIUMM + bool "Pentium M" + help + Select this for Intel Pentium M (not Pentium-4 M) + notebook chips. + +config MPENTIUM4 + bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon" + help + Select this for Intel Pentium 4 chips. This includes the + Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M + (not Pentium M) chips. This option enables compile flags + optimized for the chip, uses the correct cache shift, and + applies any applicable Pentium III optimizations. + +config MK6 + bool "K6/K6-II/K6-III" + help + Select this for an AMD K6-family processor. Enables use of + some extended instructions, and passes appropriate optimization + flags to GCC. + +config MK7 + bool "Athlon/Duron/K7" + help + Select this for an AMD Athlon K7-family processor. Enables use of + some extended instructions, and passes appropriate optimization + flags to GCC. + +config MK8 + bool "Opteron/Athlon64/Hammer/K8" + help + Select this for an AMD Opteron or Athlon64 Hammer-family processor. Enables + use of some extended instructions, and passes appropriate optimization + flags to GCC. + +config MCRUSOE + bool "Crusoe" + help + Select this for a Transmeta Crusoe processor. Treats the processor + like a 586 with TSC, and sets some GCC optimization flags (like a + Pentium Pro with no alignment requirements). + +config MEFFICEON + bool "Efficeon" + help + Select this for a Transmeta Efficeon processor. + +config MWINCHIPC6 + bool "Winchip-C6" + help + Select this for an IDT Winchip C6 chip. Linux and GCC + treat this chip as a 586TSC with some extended instructions + and alignment requirements. + +config MWINCHIP2 + bool "Winchip-2" + help + Select this for an IDT Winchip-2. Linux and GCC + treat this chip as a 586TSC with some extended instructions + and alignment requirements. + +config MWINCHIP3D + bool "Winchip-2A/Winchip-3" + help + Select this for an IDT Winchip-2A or 3. Linux and GCC + treat this chip as a 586TSC with some extended instructions + and alignment reqirements. Also enable out of order memory + stores for this CPU, which can increase performance of some + operations. + +config MGEODEGX1 + bool "GeodeGX1" + help + Select this for a Geode GX1 (Cyrix MediaGX) chip. + +config MCYRIXIII + bool "CyrixIII/VIA-C3" + help + Select this for a Cyrix III or C3 chip. Presently Linux and GCC + treat this chip as a generic 586. Whilst the CPU is 686 class, + it lacks the cmov extension which gcc assumes is present when + generating 686 code. + Note that Nehemiah (Model 9) and above will not boot with this + kernel due to them lacking the 3DNow! instructions used in earlier + incarnations of the CPU. + +config MVIAC3_2 + bool "VIA C3-2 (Nehemiah)" + help + Select this for a VIA C3 "Nehemiah". Selecting this enables usage + of SSE and tells gcc to treat the CPU as a 686. + Note, this kernel will not boot on older (pre model 9) C3s. + +endchoice + +config X86_GENERIC + bool "Generic x86 support" + help + Instead of just including optimizations for the selected + x86 variant (e.g. PII, Crusoe or Athlon), include some more + generic optimizations as well. This will make the kernel + perform better on x86 CPUs other than that selected. + + This is really intended for distributors who need more + generic optimizations. + +endif + +# +# Define implied options from the CPU selection here +# +config X86_CMPXCHG + bool + depends on !M386 + default y + +config X86_XADD + bool + depends on !M386 + default y + +config X86_L1_CACHE_SHIFT + int + default "7" if MPENTIUM4 || X86_GENERIC + default "4" if X86_ELAN || M486 || M386 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1 + default "6" if MK7 || MK8 || MPENTIUMM + +config RWSEM_GENERIC_SPINLOCK + bool + depends on M386 + default y + +config RWSEM_XCHGADD_ALGORITHM + bool + depends on !M386 + default y + +config GENERIC_CALIBRATE_DELAY + bool + default y + +config X86_PPRO_FENCE + bool + depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1 + default y + +config X86_F00F_BUG + bool + depends on M586MMX || M586TSC || M586 || M486 || M386 + default y + +config X86_WP_WORKS_OK + bool + depends on !M386 + default y + +config X86_INVLPG + bool + depends on !M386 + default y + +config X86_BSWAP + bool + depends on !M386 + default y + +config X86_POPAD_OK + bool + depends on !M386 + default y + +config X86_CMPXCHG64 + bool + depends on !M386 && !M486 + default y + +config X86_ALIGNMENT_16 + bool + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 + default y + +config X86_GOOD_APIC + bool + depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON + default y + +config X86_INTEL_USERCOPY + bool + depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON + default y + +config X86_USE_PPRO_CHECKSUM + bool + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON + default y + +config X86_USE_3DNOW + bool + depends on MCYRIXIII || MK7 + default y + +config X86_OOSTORE + bool + depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR + default y + +config X86_TSC + bool + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ + default y diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 09951990a62..d121ea18460 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -34,35 +34,8 @@ CFLAGS += -pipe -msoft-float # prevent gcc from keeping the stack 16 byte aligned CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) -align := $(cc-option-align) -cflags-$(CONFIG_M386) += -march=i386 -cflags-$(CONFIG_M486) += -march=i486 -cflags-$(CONFIG_M586) += -march=i586 -cflags-$(CONFIG_M586TSC) += -march=i586 -cflags-$(CONFIG_M586MMX) += $(call cc-option,-march=pentium-mmx,-march=i586) -cflags-$(CONFIG_M686) += -march=i686 -cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call cc-option,-mtune=pentium2) -cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call cc-option,-mtune=pentium3) -cflags-$(CONFIG_MPENTIUMM) += -march=i686 $(call cc-option,-mtune=pentium3) -cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call cc-option,-mtune=pentium4) -cflags-$(CONFIG_MK6) += -march=k6 -# Please note, that patches that add -march=athlon-xp and friends are pointless. -# They make zero difference whatsosever to performance at this time. -cflags-$(CONFIG_MK7) += $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4) -cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)) -cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 -cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call cc-option,-mtune=pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 -cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) -cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586) -cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) -cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 -cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) - -# AMD Elan support -cflags-$(CONFIG_X86_ELAN) += -march=i486 - -# Geode GX1 support -cflags-$(CONFIG_MGEODEGX1) += $(call cc-option,-march=pentium-mmx,-march=i486) +# CPU-specific tuning. Anything which can be shared with UML should go here. +include $(srctree)/arch/i386/Makefile.cpu # -mregparm=3 works ok on gcc-3.0 and later # diff --git a/arch/i386/Makefile.cpu b/arch/i386/Makefile.cpu new file mode 100644 index 00000000000..8e51456df23 --- /dev/null +++ b/arch/i386/Makefile.cpu @@ -0,0 +1,41 @@ +# CPU tuning section - shared with UML. +# Must change only cflags-y (or [yn]), not CFLAGS! That makes a difference for UML. + +#-mtune exists since gcc 3.4, and some -mcpu flavors didn't exist in gcc 2.95. +HAS_MTUNE := $(call cc-option-yn, -mtune=i386) +ifeq ($(HAS_MTUNE),y) +tune = $(call cc-option,-mtune=$(1),) +else +tune = $(call cc-option,-mcpu=$(1),) +endif + +align := $(cc-option-align) +cflags-$(CONFIG_M386) += -march=i386 +cflags-$(CONFIG_M486) += -march=i486 +cflags-$(CONFIG_M586) += -march=i586 +cflags-$(CONFIG_M586TSC) += -march=i586 +cflags-$(CONFIG_M586MMX) += $(call cc-option,-march=pentium-mmx,-march=i586) +cflags-$(CONFIG_M686) += -march=i686 +cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call tune,pentium2) +cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call tune,pentium3) +cflags-$(CONFIG_MPENTIUMM) += -march=i686 $(call tune,pentium3) +cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call tune,pentium4) +cflags-$(CONFIG_MK6) += -march=k6 +# Please note, that patches that add -march=athlon-xp and friends are pointless. +# They make zero difference whatsosever to performance at this time. +cflags-$(CONFIG_MK7) += $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4) +cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)) +cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 +cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 +cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) +cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586) +cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) +cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 +cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) + +# AMD Elan support +cflags-$(CONFIG_X86_ELAN) += -march=i486 + +# Geode GX1 support +cflags-$(CONFIG_MGEODEGX1) += $(call cc-option,-march=pentium-mmx,-march=i486) + diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 5546ddebec3..9204be6eedb 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -803,6 +803,7 @@ no_apic: void __init init_apic_mappings(void) { + unsigned int orig_apicid; unsigned long apic_phys; /* @@ -824,8 +825,11 @@ void __init init_apic_mappings(void) * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - if (boot_cpu_physical_apicid == -1U) - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); + orig_apicid = boot_cpu_physical_apicid; + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); + if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid)) + printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)", + orig_apicid, boot_cpu_physical_apicid); #ifdef CONFIG_X86_IO_APIC { @@ -1046,10 +1050,11 @@ static unsigned int calibration_result; void __init setup_boot_APIC_clock(void) { + unsigned long flags; apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"); using_apic_timer = 1; - local_irq_disable(); + local_irq_save(flags); calibration_result = calibrate_APIC_clock(); /* @@ -1057,7 +1062,7 @@ void __init setup_boot_APIC_clock(void) */ setup_APIC_timer(calibration_result); - local_irq_enable(); + local_irq_restore(flags); } void __devinit setup_secondary_APIC_clock(void) @@ -1254,40 +1259,81 @@ fastcall void smp_error_interrupt(struct pt_regs *regs) } /* - * This initializes the IO-APIC and APIC hardware if this is - * a UP kernel. + * This initializes the IO-APIC and APIC hardware. */ -int __init APIC_init_uniprocessor (void) +int __init APIC_init(void) { - if (enable_local_apic < 0) - clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); + if (enable_local_apic < 0) { + printk(KERN_INFO "APIC disabled\n"); + return -1; + } - if (!smp_found_config && !cpu_has_apic) + /* See if we have a SMP configuration or have forced enabled + * the local apic. + */ + if (!smp_found_config && !acpi_lapic && !cpu_has_apic) { + enable_local_apic = -1; return -1; + } /* - * Complain if the BIOS pretends there is one. + * Complain if the BIOS pretends there is an apic. + * Then get out because we don't have an a local apic. */ if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); + printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); + enable_local_apic = -1; return -1; } verify_local_APIC(); + /* + * Should not be necessary because the MP table should list the boot + * CPU too, but we do it for the sake of robustness anyway. + * Makes no sense to do this check in clustered apic mode, so skip it + */ + if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { + printk("weird, boot CPU (#%d) not listed by the BIOS.\n", + boot_cpu_physical_apicid); + physid_set(boot_cpu_physical_apicid, phys_cpu_present_map); + } + + /* + * Switch from PIC to APIC mode. + */ connect_bsp_APIC(); + setup_local_APIC(); - phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); +#ifdef CONFIG_X86_IO_APIC + /* + * Now start the IO-APICs + */ + if (smp_found_config && !skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); +#endif + return 0; +} - setup_local_APIC(); +void __init APIC_late_time_init(void) +{ + /* Improve our loops per jiffy estimate */ + loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz; + boot_cpu_data.loops_per_jiffy = loops_per_jiffy; + cpu_data[0].loops_per_jiffy = loops_per_jiffy; + + /* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is + * initialized. So redo it here to ensure the boot cpu is setup + * properly. + */ + if (nmi_watchdog == NMI_LOCAL_APIC) + setup_apic_nmi_watchdog(); #ifdef CONFIG_X86_IO_APIC - if (smp_found_config) - if (!skip_ioapic_setup && nr_ioapics) - setup_IO_APIC(); + if (smp_found_config && !skip_ioapic_setup && nr_ioapics) + IO_APIC_late_time_init(); #endif setup_boot_APIC_clock(); - - return 0; } diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index d7811c4e8b5..d2ef0c2aa93 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -597,12 +597,14 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, cpumask_t cpus; int cpu; struct desc_struct save_desc_40; + struct desc_struct *gdt; cpus = apm_save_cpus(); cpu = get_cpu(); - save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8]; - per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc; + gdt = get_cpu_gdt_table(cpu); + save_desc_40 = gdt[0x40 / 8]; + gdt[0x40 / 8] = bad_bios_desc; local_save_flags(flags); APM_DO_CLI; @@ -610,7 +612,7 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); APM_DO_RESTORE_SEGS; local_irq_restore(flags); - per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = save_desc_40; + gdt[0x40 / 8] = save_desc_40; put_cpu(); apm_restore_cpus(cpus); @@ -639,13 +641,14 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) cpumask_t cpus; int cpu; struct desc_struct save_desc_40; - + struct desc_struct *gdt; cpus = apm_save_cpus(); cpu = get_cpu(); - save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8]; - per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc; + gdt = get_cpu_gdt_table(cpu); + save_desc_40 = gdt[0x40 / 8]; + gdt[0x40 / 8] = bad_bios_desc; local_save_flags(flags); APM_DO_CLI; @@ -653,7 +656,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); APM_DO_RESTORE_SEGS; local_irq_restore(flags); - __get_cpu_var(cpu_gdt_table)[0x40 / 8] = save_desc_40; + gdt[0x40 / 8] = save_desc_40; put_cpu(); apm_restore_cpus(cpus); return error; @@ -2295,35 +2298,36 @@ static int __init apm_init(void) apm_bios_entry.segment = APM_CS; for (i = 0; i < NR_CPUS; i++) { - set_base(per_cpu(cpu_gdt_table, i)[APM_CS >> 3], + struct desc_struct *gdt = get_cpu_gdt_table(i); + set_base(gdt[APM_CS >> 3], __va((unsigned long)apm_info.bios.cseg << 4)); - set_base(per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], + set_base(gdt[APM_CS_16 >> 3], __va((unsigned long)apm_info.bios.cseg_16 << 4)); - set_base(per_cpu(cpu_gdt_table, i)[APM_DS >> 3], + set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); #ifndef APM_RELAX_SEGMENTS if (apm_info.bios.version == 0x100) { #endif /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 - 1); + _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); /* For some unknown machine. */ - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], 64 * 1024 - 1); + _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], 64 * 1024 - 1); + _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); #ifndef APM_RELAX_SEGMENTS } else { - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], + _set_limit((char *)&gdt[APM_CS >> 3], (apm_info.bios.cseg_len - 1) & 0xffff); - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], + _set_limit((char *)&gdt[APM_CS_16 >> 3], (apm_info.bios.cseg_16_len - 1) & 0xffff); - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], + _set_limit((char *)&gdt[APM_DS >> 3], (apm_info.bios.dseg_len - 1) & 0xffff); /* workaround for broken BIOSes */ if (apm_info.bios.cseg_len <= apm_info.bios.offset) - _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 -1); + _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1); if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */ /* for the BIOS that assumes granularity = 1 */ - per_cpu(cpu_gdt_table, i)[APM_DS >> 3].b |= 0x800000; + gdt[APM_DS >> 3].b |= 0x800000; printk(KERN_NOTICE "apm: we set the granularity of dseg.\n"); } } diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 9ad43be9a01..74145a33cb0 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -573,6 +573,7 @@ void __devinit cpu_init(void) int cpu = smp_processor_id(); struct tss_struct * t = &per_cpu(init_tss, cpu); struct thread_struct *thread = ¤t->thread; + struct desc_struct *gdt = get_cpu_gdt_table(cpu); __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu); if (cpu_test_and_set(cpu, cpu_initialized)) { @@ -594,24 +595,16 @@ void __devinit cpu_init(void) * Initialize the per-CPU GDT with the boot GDT, * and set up the GDT descriptor: */ - memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table, - GDT_SIZE); + memcpy(gdt, cpu_gdt_table, GDT_SIZE); /* Set up GDT entry for 16bit stack */ - *(__u64 *)&(per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_ESPFIX_SS]) |= + *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |= ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) | ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | (CPU_16BIT_STACK_SIZE - 1); cpu_gdt_descr[cpu].size = GDT_SIZE - 1; - cpu_gdt_descr[cpu].address = - (unsigned long)&per_cpu(cpu_gdt_table, cpu); - - /* - * Set up the per-thread TLS descriptor cache: - */ - memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu), - GDT_ENTRY_TLS_ENTRIES * 8); + cpu_gdt_descr[cpu].address = (unsigned long)gdt; load_gdt(&cpu_gdt_descr[cpu]); load_idt(&idt_descr); diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 822c8ce9d1f..caa9f771134 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -32,6 +32,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/compiler.h> +#include <linux/sched.h> /* current */ #include <asm/io.h> #include <asm/delay.h> #include <asm/uaccess.h> diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index aa622d52c6e..270f2188d68 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -28,6 +28,7 @@ #include <linux/cpufreq.h> #include <linux/slab.h> #include <linux/cpumask.h> +#include <linux/sched.h> /* current / set_cpus_allowed() */ #include <asm/processor.h> #include <asm/msr.h> diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 58ca98fdc2c..2d5c9adba0c 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -32,6 +32,7 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/cpumask.h> +#include <linux/sched.h> /* for current / set_cpus_allowed() */ #include <asm/msr.h> #include <asm/io.h> diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index c397b622043..1465974256c 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/cpufreq.h> #include <linux/config.h> +#include <linux/sched.h> /* current */ #include <linux/delay.h> #include <linux/compiler.h> diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index 9e0d5f83cb9..4dc42a189ae 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -3,6 +3,7 @@ * * Changes: * Venkatesh Pallipadi : Adding cache identification through cpuid(4) + * Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure. */ #include <linux/init.h> @@ -10,6 +11,7 @@ #include <linux/device.h> #include <linux/compiler.h> #include <linux/cpu.h> +#include <linux/sched.h> #include <asm/processor.h> #include <asm/smp.h> @@ -28,7 +30,7 @@ struct _cache_table }; /* all the cache descriptor types we care about (no TLB or trace cache entries) */ -static struct _cache_table cache_table[] __devinitdata = +static struct _cache_table cache_table[] __cpuinitdata = { { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ @@ -117,10 +119,9 @@ struct _cpuid4_info { cpumask_t shared_cpu_map; }; -#define MAX_CACHE_LEAVES 4 static unsigned short num_cache_leaves; -static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) +static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { unsigned int eax, ebx, ecx, edx; union _cpuid4_leaf_eax cache_eax; @@ -144,23 +145,18 @@ static int __init find_num_cache_leaves(void) { unsigned int eax, ebx, ecx, edx; union _cpuid4_leaf_eax cache_eax; - int i; - int retval; + int i = -1; - retval = MAX_CACHE_LEAVES; - /* Do cpuid(4) loop to find out num_cache_leaves */ - for (i = 0; i < MAX_CACHE_LEAVES; i++) { + do { + ++i; + /* Do cpuid(4) loop to find out num_cache_leaves */ cpuid_count(4, i, &eax, &ebx, &ecx, &edx); cache_eax.full = eax; - if (cache_eax.split.type == CACHE_TYPE_NULL) { - retval = i; - break; - } - } - return retval; + } while (cache_eax.split.type != CACHE_TYPE_NULL); + return i; } -unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c) +unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) { unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ @@ -284,13 +280,7 @@ unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c) if ( l3 ) printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); - /* - * This assumes the L3 cache is shared; it typically lives in - * the northbridge. The L1 caches are included by the L2 - * cache, and so should not be included for the purpose of - * SMP switching weights. - */ - c->x86_cache_size = l2 ? l2 : (l1i+l1d); + c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d)); } return l2; @@ -301,7 +291,7 @@ static struct _cpuid4_info *cpuid4_info[NR_CPUS]; #define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y])) #ifdef CONFIG_SMP -static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index) +static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf; unsigned long num_threads_sharing; @@ -334,7 +324,7 @@ static void free_cache_attributes(unsigned int cpu) cpuid4_info[cpu] = NULL; } -static int __devinit detect_cache_attributes(unsigned int cpu) +static int __cpuinit detect_cache_attributes(unsigned int cpu) { struct _cpuid4_info *this_leaf; unsigned long j; @@ -511,7 +501,7 @@ static void cpuid4_cache_sysfs_exit(unsigned int cpu) free_cache_attributes(cpu); } -static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu) +static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) { if (num_cache_leaves == 0) @@ -542,7 +532,7 @@ err_out: } /* Add/Remove cache interface for CPU device */ -static int __devinit cache_add_dev(struct sys_device * sys_dev) +static int __cpuinit cache_add_dev(struct sys_device * sys_dev) { unsigned int cpu = sys_dev->id; unsigned long i, j; @@ -579,7 +569,7 @@ static int __devinit cache_add_dev(struct sys_device * sys_dev) return retval; } -static int __devexit cache_remove_dev(struct sys_device * sys_dev) +static void __cpuexit cache_remove_dev(struct sys_device * sys_dev) { unsigned int cpu = sys_dev->id; unsigned long i; @@ -588,24 +578,49 @@ static int __devexit cache_remove_dev(struct sys_device * sys_dev) kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); kobject_unregister(cache_kobject[cpu]); cpuid4_cache_sysfs_exit(cpu); - return 0; + return; +} + +static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_ONLINE: + cache_add_dev(sys_dev); + break; + case CPU_DEAD: + cache_remove_dev(sys_dev); + break; + } + return NOTIFY_OK; } -static struct sysdev_driver cache_sysdev_driver = { - .add = cache_add_dev, - .remove = __devexit_p(cache_remove_dev), +static struct notifier_block cacheinfo_cpu_notifier = +{ + .notifier_call = cacheinfo_cpu_callback, }; -/* Register/Unregister the cpu_cache driver */ -static int __devinit cache_register_driver(void) +static int __cpuinit cache_sysfs_init(void) { + int i; + if (num_cache_leaves == 0) return 0; - return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver); + register_cpu_notifier(&cacheinfo_cpu_notifier); + + for_each_online_cpu(i) { + cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE, + (void *)(long)i); + } + + return 0; } -device_initcall(cache_register_driver); +device_initcall(cache_sysfs_init); #endif - diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c index 3c035b8fa3d..979b18bc95c 100644 --- a/arch/i386/kernel/cpu/mcheck/p6.c +++ b/arch/i386/kernel/cpu/mcheck/p6.c @@ -102,11 +102,16 @@ void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c) wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); nr_mce_banks = l & 0xff; - /* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */ - for (i=1; i<nr_mce_banks; i++) { + /* + * Following the example in IA-32 SDM Vol 3: + * - MC0_CTL should not be written + * - Status registers on all banks should be cleared on reset + */ + for (i=1; i<nr_mce_banks; i++) wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); + + for (i=0; i<nr_mce_banks; i++) wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); - } set_in_cr4 (X86_CR4_MCE); printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c index 1923e0aed26..cf39e205d33 100644 --- a/arch/i386/kernel/cpu/mtrr/if.c +++ b/arch/i386/kernel/cpu/mtrr/if.c @@ -149,60 +149,89 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos) return -EINVAL; } -static int -mtrr_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long __arg) +static long +mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) { - int err; + int err = 0; mtrr_type type; struct mtrr_sentry sentry; struct mtrr_gentry gentry; void __user *arg = (void __user *) __arg; switch (cmd) { + case MTRRIOC_ADD_ENTRY: + case MTRRIOC_SET_ENTRY: + case MTRRIOC_DEL_ENTRY: + case MTRRIOC_KILL_ENTRY: + case MTRRIOC_ADD_PAGE_ENTRY: + case MTRRIOC_SET_PAGE_ENTRY: + case MTRRIOC_DEL_PAGE_ENTRY: + case MTRRIOC_KILL_PAGE_ENTRY: + if (copy_from_user(&sentry, arg, sizeof sentry)) + return -EFAULT; + break; + case MTRRIOC_GET_ENTRY: + case MTRRIOC_GET_PAGE_ENTRY: + if (copy_from_user(&gentry, arg, sizeof gentry)) + return -EFAULT; + break; +#ifdef CONFIG_COMPAT + case MTRRIOC32_ADD_ENTRY: + case MTRRIOC32_SET_ENTRY: + case MTRRIOC32_DEL_ENTRY: + case MTRRIOC32_KILL_ENTRY: + case MTRRIOC32_ADD_PAGE_ENTRY: + case MTRRIOC32_SET_PAGE_ENTRY: + case MTRRIOC32_DEL_PAGE_ENTRY: + case MTRRIOC32_KILL_PAGE_ENTRY: { + struct mtrr_sentry32 __user *s32 = (struct mtrr_sentry32 __user *)__arg; + err = get_user(sentry.base, &s32->base); + err |= get_user(sentry.size, &s32->size); + err |= get_user(sentry.type, &s32->type); + if (err) + return err; + break; + } + case MTRRIOC32_GET_ENTRY: + case MTRRIOC32_GET_PAGE_ENTRY: { + struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)__arg; + err = get_user(gentry.regnum, &g32->regnum); + err |= get_user(gentry.base, &g32->base); + err |= get_user(gentry.size, &g32->size); + err |= get_user(gentry.type, &g32->type); + if (err) + return err; + break; + } +#endif + } + + switch (cmd) { default: return -ENOTTY; case MTRRIOC_ADD_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, file, 0); - if (err < 0) - return err; break; case MTRRIOC_SET_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_add(sentry.base, sentry.size, sentry.type, 0); - if (err < 0) - return err; break; case MTRRIOC_DEL_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_file_del(sentry.base, sentry.size, file, 0); - if (err < 0) - return err; break; case MTRRIOC_KILL_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_del(-1, sentry.base, sentry.size); - if (err < 0) - return err; break; case MTRRIOC_GET_ENTRY: - if (copy_from_user(&gentry, arg, sizeof gentry)) - return -EFAULT; if (gentry.regnum >= num_var_ranges) return -EINVAL; mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); @@ -217,60 +246,59 @@ mtrr_ioctl(struct inode *inode, struct file *file, gentry.type = type; } - if (copy_to_user(arg, &gentry, sizeof gentry)) - return -EFAULT; break; case MTRRIOC_ADD_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, file, 1); - if (err < 0) - return err; break; case MTRRIOC_SET_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0); - if (err < 0) - return err; break; case MTRRIOC_DEL_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_file_del(sentry.base, sentry.size, file, 1); - if (err < 0) - return err; break; case MTRRIOC_KILL_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, arg, sizeof sentry)) - return -EFAULT; err = mtrr_del_page(-1, sentry.base, sentry.size); - if (err < 0) - return err; break; case MTRRIOC_GET_PAGE_ENTRY: - if (copy_from_user(&gentry, arg, sizeof gentry)) - return -EFAULT; if (gentry.regnum >= num_var_ranges) return -EINVAL; mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); gentry.type = type; + break; + } + + if (err) + return err; + switch(cmd) { + case MTRRIOC_GET_ENTRY: + case MTRRIOC_GET_PAGE_ENTRY: if (copy_to_user(arg, &gentry, sizeof gentry)) - return -EFAULT; + err = -EFAULT; + break; +#ifdef CONFIG_COMPAT + case MTRRIOC32_GET_ENTRY: + case MTRRIOC32_GET_PAGE_ENTRY: { + struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)__arg; + err = put_user(gentry.base, &g32->base); + err |= put_user(gentry.size, &g32->size); + err |= put_user(gentry.regnum, &g32->regnum); + err |= put_user(gentry.type, &g32->type); break; } - return 0; +#endif + } + return err; } static int @@ -310,7 +338,8 @@ static struct file_operations mtrr_fops = { .read = seq_read, .llseek = seq_lseek, .write = mtrr_write, - .ioctl = mtrr_ioctl, + .unlocked_ioctl = mtrr_ioctl, + .compat_ioctl = mtrr_ioctl, .release = mtrr_close, }; diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 8bd77d948a8..41b871ecf4b 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -44,7 +44,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", + "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", NULL, "est", "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index 0248e084017..af809ccf5fb 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c @@ -21,7 +21,6 @@ #include <asm/hardirq.h> #include <asm/nmi.h> #include <asm/hw_irq.h> -#include <asm/apic.h> #include <mach_ipi.h> @@ -148,7 +147,6 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu) regs = &fixed_regs; } crash_save_this_cpu(regs, cpu); - disable_local_APIC(); atomic_dec(&waiting_for_crash_ipi); /* Assume hlt works */ halt(); @@ -188,7 +186,6 @@ static void nmi_shootdown_cpus(void) } /* Leave the nmi callback set */ - disable_local_APIC(); } #else static void nmi_shootdown_cpus(void) @@ -213,9 +210,5 @@ void machine_crash_shutdown(struct pt_regs *regs) /* Make a note of crashing cpu. Will be used in NMI callback.*/ crashing_cpu = smp_processor_id(); nmi_shootdown_cpus(); - lapic_shutdown(); -#if defined(CONFIG_X86_IO_APIC) - disable_IO_APIC(); -#endif crash_save_self(regs); } diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 323ef8ab324..d86f2490928 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -435,4 +435,8 @@ void __init init_IRQ(void) setup_irq(FPU_IRQ, &fpu_irq); irq_ctx_init(smp_processor_id()); + +#ifdef CONFIG_X86_LOCAL_APIC + APIC_init(); +#endif } diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index fb3991e8229..5a77c52b20a 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -46,6 +46,9 @@ int (*ioapic_renumber_irq)(int ioapic, int irq); atomic_t irq_mis_count; +/* Where if anywhere is the i8259 connect in external int mode */ +static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; + static DEFINE_SPINLOCK(ioapic_lock); /* @@ -738,7 +741,7 @@ static int find_irq_entry(int apic, int pin, int type) /* * Find the pin to which IRQ[irq] (ISA) is connected */ -static int find_isa_irq_pin(int irq, int type) +static int __init find_isa_irq_pin(int irq, int type) { int i; @@ -758,6 +761,33 @@ static int find_isa_irq_pin(int irq, int type) return -1; } +static int __init find_isa_irq_apic(int irq, int type) +{ + int i; + + for (i = 0; i < mp_irq_entries; i++) { + int lbus = mp_irqs[i].mpc_srcbus; + + if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || + mp_bus_id_to_type[lbus] == MP_BUS_EISA || + mp_bus_id_to_type[lbus] == MP_BUS_MCA || + mp_bus_id_to_type[lbus] == MP_BUS_NEC98 + ) && + (mp_irqs[i].mpc_irqtype == type) && + (mp_irqs[i].mpc_srcbusirq == irq)) + break; + } + if (i < mp_irq_entries) { + int apic; + for(apic = 0; apic < nr_ioapics; apic++) { + if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic) + return apic; + } + } + + return -1; +} + /* * Find a specific PCI IRQ entry. * Not an __init, possibly needed by modules @@ -1253,7 +1283,7 @@ static void __init setup_IO_APIC_irqs(void) /* * Set up the 8259A-master output pin: */ -static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) +static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) { struct IO_APIC_route_entry entry; unsigned long flags; @@ -1287,8 +1317,8 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) * Add it to the IO-APIC irq-routing table: */ spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); - io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); + io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); spin_unlock_irqrestore(&ioapic_lock, flags); enable_8259A_irq(0); @@ -1595,7 +1625,8 @@ void /*__init*/ print_PIC(void) static void __init enable_IO_APIC(void) { union IO_APIC_reg_01 reg_01; - int i; + int i8259_apic, i8259_pin; + int i, apic; unsigned long flags; for (i = 0; i < PIN_MAP_SIZE; i++) { @@ -1609,11 +1640,52 @@ static void __init enable_IO_APIC(void) /* * The number of IO-APIC IRQ registers (== #pins): */ - for (i = 0; i < nr_ioapics; i++) { + for (apic = 0; apic < nr_ioapics; apic++) { spin_lock_irqsave(&ioapic_lock, flags); - reg_01.raw = io_apic_read(i, 1); + reg_01.raw = io_apic_read(apic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[i] = reg_01.bits.entries+1; + nr_ioapic_registers[apic] = reg_01.bits.entries+1; + } + for(apic = 0; apic < nr_ioapics; apic++) { + int pin; + /* See if any of the pins is in ExtINT mode */ + for(pin = 0; pin < nr_ioapic_registers[i]; pin++) { + struct IO_APIC_route_entry entry; + spin_lock_irqsave(&ioapic_lock, flags); + *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); + *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + spin_unlock_irqrestore(&ioapic_lock, flags); + + + /* If the interrupt line is enabled and in ExtInt mode + * I have found the pin where the i8259 is connected. + */ + if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) { + ioapic_i8259.apic = apic; + ioapic_i8259.pin = pin; + goto found_i8259; + } + } + } + found_i8259: + /* Look to see what if the MP table has reported the ExtINT */ + /* If we could not find the appropriate pin by looking at the ioapic + * the i8259 probably is not connected the ioapic but give the + * mptable a chance anyway. + */ + i8259_pin = find_isa_irq_pin(0, mp_ExtINT); + i8259_apic = find_isa_irq_apic(0, mp_ExtINT); + /* Trust the MP table if nothing is setup in the hardware */ + if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) { + printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n"); + ioapic_i8259.pin = i8259_pin; + ioapic_i8259.apic = i8259_apic; + } + /* Complain if the MP table and the hardware disagree */ + if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) && + (i8259_pin >= 0) && (ioapic_i8259.pin >= 0)) + { + printk(KERN_WARNING "ExtINT in hardware and MP table differ\n"); } /* @@ -1627,7 +1699,6 @@ static void __init enable_IO_APIC(void) */ void disable_IO_APIC(void) { - int pin; /* * Clear the IO-APIC before rebooting: */ @@ -1638,8 +1709,7 @@ void disable_IO_APIC(void) * Put that IOAPIC in virtual wire mode * so legacy interrupts can be delivered. */ - pin = find_isa_irq_pin(0, mp_ExtINT); - if (pin != -1) { + if (ioapic_i8259.pin != -1) { struct IO_APIC_route_entry entry; unsigned long flags; @@ -1650,7 +1720,7 @@ void disable_IO_APIC(void) entry.polarity = 0; /* High */ entry.delivery_status = 0; entry.dest_mode = 0; /* Physical */ - entry.delivery_mode = 7; /* ExtInt */ + entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; entry.dest.physical.physical_dest = 0; @@ -1659,11 +1729,13 @@ void disable_IO_APIC(void) * Add it to the IO-APIC irq-routing table: */ spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); - io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); + io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin, + *(((int *)&entry)+1)); + io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin, + *(((int *)&entry)+0)); spin_unlock_irqrestore(&ioapic_lock, flags); } - disconnect_bsp_APIC(pin != -1); + disconnect_bsp_APIC(ioapic_i8259.pin != -1); } /* @@ -2113,20 +2185,21 @@ static void setup_nmi (void) */ static inline void unlock_ExtINT_logic(void) { - int pin, i; + int apic, pin, i; struct IO_APIC_route_entry entry0, entry1; unsigned char save_control, save_freq_select; unsigned long flags; - pin = find_isa_irq_pin(8, mp_INT); + pin = find_isa_irq_pin(8, mp_INT); + apic = find_isa_irq_apic(8, mp_INT); if (pin == -1) return; spin_lock_irqsave(&ioapic_lock, flags); - *(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin); - *(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin); + *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin); spin_unlock_irqrestore(&ioapic_lock, flags); - clear_IO_APIC_pin(0, pin); + clear_IO_APIC_pin(apic, pin); memset(&entry1, 0, sizeof(entry1)); @@ -2139,8 +2212,8 @@ static inline void unlock_ExtINT_logic(void) entry1.vector = 0; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); - io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); spin_unlock_irqrestore(&ioapic_lock, flags); save_control = CMOS_READ(RTC_CONTROL); @@ -2158,11 +2231,11 @@ static inline void unlock_ExtINT_logic(void) CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - clear_IO_APIC_pin(0, pin); + clear_IO_APIC_pin(apic, pin); spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); - io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -2174,7 +2247,7 @@ static inline void unlock_ExtINT_logic(void) */ static inline void check_timer(void) { - int pin1, pin2; + int apic1, pin1, apic2, pin2; int vector; /* @@ -2196,10 +2269,13 @@ static inline void check_timer(void) timer_ack = 1; enable_8259A_irq(0); - pin1 = find_isa_irq_pin(0, mp_INT); - pin2 = find_isa_irq_pin(0, mp_ExtINT); + pin1 = find_isa_irq_pin(0, mp_INT); + apic1 = find_isa_irq_apic(0, mp_INT); + pin2 = ioapic_i8259.pin; + apic2 = ioapic_i8259.apic; - printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2); + printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", + vector, apic1, pin1, apic2, pin2); if (pin1 != -1) { /* @@ -2216,8 +2292,9 @@ static inline void check_timer(void) clear_IO_APIC_pin(0, pin1); return; } - clear_IO_APIC_pin(0, pin1); - printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); + clear_IO_APIC_pin(apic1, pin1); + printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to " + "IO-APIC\n"); } printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); @@ -2226,13 +2303,13 @@ static inline void check_timer(void) /* * legacy devices should be connected to IO APIC #0 */ - setup_ExtINT_IRQ0_pin(pin2, vector); + setup_ExtINT_IRQ0_pin(apic2, pin2, vector); if (timer_irq_works()) { printk("works.\n"); if (pin1 != -1) - replace_pin_at_irq(0, 0, pin1, 0, pin2); + replace_pin_at_irq(0, apic1, pin1, apic2, pin2); else - add_pin_to_irq(0, 0, pin2); + add_pin_to_irq(0, apic2, pin2); if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); } @@ -2241,7 +2318,7 @@ static inline void check_timer(void) /* * Cleanup, just in case ... */ - clear_IO_APIC_pin(0, pin2); + clear_IO_APIC_pin(apic2, pin2); } printk(" failed.\n"); @@ -2310,11 +2387,15 @@ void __init setup_IO_APIC(void) sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); - check_timer(); if (!acpi_ioapic) print_IO_APIC(); } +void __init IO_APIC_late_time_init(void) +{ + check_timer(); +} + /* * Called after all the initialization is done. If we didnt find any * APIC bugs then we can allow the modify fast path diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index ce66dcc26d9..1a201a93286 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -218,7 +218,7 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for_each_cpu(j) + for_each_online_cpu(j) seq_printf(p, "CPU%d ",j); seq_putc(p, '\n'); } @@ -232,7 +232,7 @@ int show_interrupts(struct seq_file *p, void *v) #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for_each_cpu(j) + for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif seq_printf(p, " %14s", irq_desc[i].handler->typename); @@ -246,12 +246,12 @@ skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); - for_each_cpu(j) + for_each_online_cpu(j) seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); #ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); - for_each_cpu(j) + for_each_online_cpu(j) seq_printf(p, "%10u ", per_cpu(irq_stat,j).apic_timer_irqs); seq_putc(p, '\n'); diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 27aabfceb67..8f767d9aa45 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -69,7 +69,7 @@ unsigned int def_to_bigsmp = 0; /* Processor that is doing the boot up */ unsigned int boot_cpu_physical_apicid = -1U; /* Internal processor count */ -static unsigned int __initdata num_processors; +static unsigned int __devinitdata num_processors; /* Bitmask of physically existing CPUs */ physid_mask_t phys_cpu_present_map; @@ -119,7 +119,7 @@ static int MP_valid_apicid(int apicid, int version) } #endif -static void __init MP_processor_info (struct mpc_config_processor *m) +static void __devinit MP_processor_info (struct mpc_config_processor *m) { int ver, apicid; physid_mask_t phys_cpu; @@ -182,17 +182,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m) boot_cpu_physical_apicid = m->mpc_apicid; } - if (num_processors >= NR_CPUS) { - printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." - " Processor ignored.\n", NR_CPUS); - return; - } - - if (num_processors >= maxcpus) { - printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." - " Processor ignored.\n", maxcpus); - return; - } ver = m->mpc_apicver; if (!MP_valid_apicid(apicid, ver)) { @@ -201,11 +190,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m) return; } - cpu_set(num_processors, cpu_possible_map); - num_processors++; - phys_cpu = apicid_to_cpu_present(apicid); - physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu); - /* * Validate version */ @@ -216,6 +200,25 @@ static void __init MP_processor_info (struct mpc_config_processor *m) ver = 0x10; } apic_version[m->mpc_apicid] = ver; + + phys_cpu = apicid_to_cpu_present(apicid); + physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu); + + if (num_processors >= NR_CPUS) { + printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." + " Processor ignored.\n", NR_CPUS); + return; + } + + if (num_processors >= maxcpus) { + printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." + " Processor ignored.\n", maxcpus); + return; + } + + cpu_set(num_processors, cpu_possible_map); + num_processors++; + if ((num_processors > 8) && APIC_XAPIC(ver) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) @@ -834,7 +837,7 @@ void __init mp_register_lapic_address ( } -void __init mp_register_lapic ( +void __devinit mp_register_lapic ( u8 id, u8 enabled) { diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 72515b8a1b1..d661703ac1c 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -100,16 +100,44 @@ int nmi_active; (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) +#ifdef CONFIG_SMP +/* The performance counters used by NMI_LOCAL_APIC don't trigger when + * the CPU is idle. To make sure the NMI watchdog really ticks on all + * CPUs during the test make them busy. + */ +static __init void nmi_cpu_busy(void *data) +{ + volatile int *endflag = data; + local_irq_enable(); + /* Intentionally don't use cpu_relax here. This is + to make sure that the performance counter really ticks, + even if there is a simulator or similar that catches the + pause instruction. On a real HT machine this is fine because + all other CPUs are busy with "useless" delay loops and don't + care if they get somewhat less cycles. */ + while (*endflag == 0) + barrier(); +} +#endif + static int __init check_nmi_watchdog(void) { - unsigned int prev_nmi_count[NR_CPUS]; + volatile int endflag = 0; + unsigned int *prev_nmi_count; int cpu; if (nmi_watchdog == NMI_NONE) return 0; + prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); + if (!prev_nmi_count) + return -1; + printk(KERN_INFO "Testing NMI watchdog ... "); + if (nmi_watchdog == NMI_LOCAL_APIC) + smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); + for (cpu = 0; cpu < NR_CPUS; cpu++) prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; local_irq_enable(); @@ -123,12 +151,18 @@ static int __init check_nmi_watchdog(void) continue; #endif if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) { - printk("CPU#%d: NMI appears to be stuck!\n", cpu); + endflag = 1; + printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", + cpu, + prev_nmi_count[cpu], + nmi_count(cpu)); nmi_active = 0; lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG; + kfree(prev_nmi_count); return -1; } } + endflag = 1; printk("OK.\n"); /* now that we know it works we can reduce NMI frequency to @@ -136,6 +170,7 @@ static int __init check_nmi_watchdog(void) if (nmi_watchdog == NMI_LOCAL_APIC) nmi_hz = 1; + kfree(prev_nmi_count); return 0; } /* This needs to happen later in boot so counters are working */ diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 7b6368bf897..efd11f09c99 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -354,7 +354,7 @@ ptrace_set_thread_area(struct task_struct *child, return 0; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; struct user * dummy = NULL; diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c index 1b183b378c2..c9b87330aee 100644 --- a/arch/i386/kernel/reboot_fixups.c +++ b/arch/i386/kernel/reboot_fixups.c @@ -44,7 +44,7 @@ void mach_reboot_fixups(void) for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) { cur = &(fixups_table[i]); - dev = pci_get_device(cur->vendor, cur->device, 0); + dev = pci_get_device(cur->vendor, cur->device, NULL); if (!dev) continue; diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 9b8c8a19824..b48ac635f3c 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -389,14 +389,24 @@ static void __init limit_regions(unsigned long long size) } } for (i = 0; i < e820.nr_map; i++) { - if (e820.map[i].type == E820_RAM) { - current_addr = e820.map[i].addr + e820.map[i].size; - if (current_addr >= size) { - e820.map[i].size -= current_addr-size; - e820.nr_map = i + 1; - return; - } + current_addr = e820.map[i].addr + e820.map[i].size; + if (current_addr < size) + continue; + + if (e820.map[i].type != E820_RAM) + continue; + + if (e820.map[i].addr >= size) { + /* + * This region starts past the end of the + * requested size, skip it completely. + */ + e820.nr_map = i; + } else { + e820.nr_map = i + 1; + e820.map[i].size -= current_addr - size; } + return; } } diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 1fb26d0e30b..5a2bbe0c4ff 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -87,7 +87,11 @@ EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_callin_map; cpumask_t cpu_callout_map; EXPORT_SYMBOL(cpu_callout_map); +#ifdef CONFIG_HOTPLUG_CPU +cpumask_t cpu_possible_map = CPU_MASK_ALL; +#else cpumask_t cpu_possible_map; +#endif EXPORT_SYMBOL(cpu_possible_map); static cpumask_t smp_commenced_mask; @@ -1074,6 +1078,16 @@ void *xquad_portio; EXPORT_SYMBOL(xquad_portio); #endif +/* + * Fall back to non SMP mode after errors. + * + */ +static __init void disable_smp(void) +{ + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); +} + static void __init smp_boot_cpus(unsigned int max_cpus) { int apicid, cpu, bit, kicked; @@ -1086,7 +1100,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk("CPU%d: ", 0); print_cpu_info(&cpu_data[0]); - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; @@ -1098,68 +1111,27 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpus_clear(cpu_core_map[0]); cpu_set(0, cpu_core_map[0]); + map_cpu_to_logical_apicid(); + /* * If we couldn't find an SMP configuration at boot time, * get out of here now! */ if (!smp_found_config && !acpi_lapic) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); - smpboot_clear_io_apic_irqs(); - phys_cpu_present_map = physid_mask_of_physid(0); - if (APIC_init_uniprocessor()) - printk(KERN_NOTICE "Local APIC not detected." - " Using dummy APIC emulation.\n"); - map_cpu_to_logical_apicid(); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + disable_smp(); return; } /* - * Should not be necessary because the MP table should list the boot - * CPU too, but we do it for the sake of robustness anyway. - * Makes no sense to do this check in clustered apic mode, so skip it - */ - if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { - printk("weird, boot CPU (#%d) not listed by the BIOS.\n", - boot_cpu_physical_apicid); - physid_set(hard_smp_processor_id(), phys_cpu_present_map); - } - - /* - * If we couldn't find a local APIC, then get out of here now! - */ - if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) { - printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", - boot_cpu_physical_apicid); - printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); - smpboot_clear_io_apic_irqs(); - phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); - return; - } - - verify_local_APIC(); - - /* * If SMP should be disabled, then really disable it! */ - if (!max_cpus) { - smp_found_config = 0; - printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); - smpboot_clear_io_apic_irqs(); - phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + if (!max_cpus || (enable_local_apic < 0)) { + printk(KERN_INFO "SMP mode deactivated.\n"); + disable_smp(); return; } - connect_bsp_APIC(); - setup_local_APIC(); - map_cpu_to_logical_apicid(); - - setup_portio_remap(); /* @@ -1240,10 +1212,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpu_set(0, cpu_sibling_map[0]); cpu_set(0, cpu_core_map[0]); - smpboot_setup_io_apic(); - - setup_boot_APIC_clock(); - /* * Synchronize the TSC with the AP */ diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index 516bf5653b0..8de658db814 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c @@ -327,7 +327,12 @@ int __init get_memcfg_from_srat(void) int tables = 0; int i = 0; - acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING, rsdp_address); + if (ACPI_FAILURE(acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING, + rsdp_address))) { + printk("%s: System description tables not found\n", + __FUNCTION__); + goto out_err; + } if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) { printk("%s: assigning address to rsdp\n", __FUNCTION__); diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 2883a4d4f01..07471bba2dc 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -74,10 +74,6 @@ int pit_latch_buggy; /* extern */ #include "do_timer.h" -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - unsigned int cpu_khz; /* Detected as we calibrate the TSC */ EXPORT_SYMBOL(cpu_khz); @@ -444,8 +440,8 @@ static int time_init_device(void) device_initcall(time_init_device); -#ifdef CONFIG_HPET_TIMER extern void (*late_time_init)(void); +#ifdef CONFIG_HPET_TIMER /* Duplicate of time_init() below, with hpet_enable part added */ static void __init hpet_time_init(void) { @@ -462,6 +458,11 @@ static void __init hpet_time_init(void) printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); time_init_hook(); + +#ifdef CONFIG_X86_LOCAL_APIC + if (enable_local_apic >= 0) + APIC_late_time_init(); +#endif } #endif @@ -486,4 +487,9 @@ void __init time_init(void) printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); time_init_hook(); + +#ifdef CONFIG_X86_LOCAL_APIC + if (enable_local_apic >= 0) + late_time_init = APIC_late_time_init; +#endif } diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c index 658c0629ba6..9caeaa315cd 100644 --- a/arch/i386/kernel/time_hpet.c +++ b/arch/i386/kernel/time_hpet.c @@ -275,6 +275,7 @@ static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ; static unsigned long PIE_count; static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */ +static unsigned int hpet_t1_cmp; /* cached comparator register */ /* * Timer 1 for RTC, we do not use periodic interrupt feature, @@ -306,10 +307,12 @@ int hpet_rtc_timer_init(void) cnt = hpet_readl(HPET_COUNTER); cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); hpet_writel(cnt, HPET_T1_CMP); + hpet_t1_cmp = cnt; local_irq_restore(flags); cfg = hpet_readl(HPET_T1_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT; + cfg &= ~HPET_TN_PERIODIC; + cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; hpet_writel(cfg, HPET_T1_CFG); return 1; @@ -319,8 +322,12 @@ static void hpet_rtc_timer_reinit(void) { unsigned int cfg, cnt; - if (!(PIE_on | AIE_on | UIE_on)) + if (unlikely(!(PIE_on | AIE_on | UIE_on))) { + cfg = hpet_readl(HPET_T1_CFG); + cfg &= ~HPET_TN_ENABLE; + hpet_writel(cfg, HPET_T1_CFG); return; + } if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) hpet_rtc_int_freq = PIE_freq; @@ -328,15 +335,10 @@ static void hpet_rtc_timer_reinit(void) hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; /* It is more accurate to use the comparator value than current count.*/ - cnt = hpet_readl(HPET_T1_CMP); + cnt = hpet_t1_cmp; cnt += hpet_tick*HZ/hpet_rtc_int_freq; hpet_writel(cnt, HPET_T1_CMP); - - cfg = hpet_readl(HPET_T1_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT; - hpet_writel(cfg, HPET_T1_CFG); - - return; + hpet_t1_cmp = cnt; } /* diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c index d973a8b681f..be242723c33 100644 --- a/arch/i386/kernel/timers/timer_hpet.c +++ b/arch/i386/kernel/timers/timer_hpet.c @@ -30,23 +30,28 @@ static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; * basic equation: * ns = cycles / (freq / ns_per_sec) * ns = cycles * (ns_per_sec / freq) - * ns = cycles * (10^9 / (cpu_mhz * 10^6)) - * ns = cycles * (10^3 / cpu_mhz) + * ns = cycles * (10^9 / (cpu_khz * 10^3)) + * ns = cycles * (10^6 / cpu_khz) * * Then we use scaling math (suggested by george@mvista.com) to get: - * ns = cycles * (10^3 * SC / cpu_mhz) / SC + * ns = cycles * (10^6 * SC / cpu_khz) / SC * ns = cycles * cyc2ns_scale / SC * * And since SC is a constant power of two, we can convert the div * into a shift. + * + * We can use khz divisor instead of mhz to keep a better percision, since + * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. + * (mathieu.desnoyers@polymtl.ca) + * * -johnstul@us.ibm.com "math is hard, lets go shopping!" */ static unsigned long cyc2ns_scale; #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ -static inline void set_cyc2ns_scale(unsigned long cpu_mhz) +static inline void set_cyc2ns_scale(unsigned long cpu_khz) { - cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; + cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; } static inline unsigned long long cycles_2_ns(unsigned long long cyc) @@ -163,7 +168,7 @@ static int __init init_hpet(char* override) printk("Detected %u.%03u MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); } - set_cyc2ns_scale(cpu_khz/1000); + set_cyc2ns_scale(cpu_khz); } /* set this only when cpu_has_tsc */ timer_hpet.read_timer = read_timer_tsc; diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 6dd470cc9f7..d395e3b4248 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -49,23 +49,28 @@ static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; * basic equation: * ns = cycles / (freq / ns_per_sec) * ns = cycles * (ns_per_sec / freq) - * ns = cycles * (10^9 / (cpu_mhz * 10^6)) - * ns = cycles * (10^3 / cpu_mhz) + * ns = cycles * (10^9 / (cpu_khz * 10^3)) + * ns = cycles * (10^6 / cpu_khz) * * Then we use scaling math (suggested by george@mvista.com) to get: - * ns = cycles * (10^3 * SC / cpu_mhz) / SC + * ns = cycles * (10^6 * SC / cpu_khz) / SC * ns = cycles * cyc2ns_scale / SC * * And since SC is a constant power of two, we can convert the div - * into a shift. + * into a shift. + * + * We can use khz divisor instead of mhz to keep a better percision, since + * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. + * (mathieu.desnoyers@polymtl.ca) + * * -johnstul@us.ibm.com "math is hard, lets go shopping!" */ static unsigned long cyc2ns_scale; #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ -static inline void set_cyc2ns_scale(unsigned long cpu_mhz) +static inline void set_cyc2ns_scale(unsigned long cpu_khz) { - cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; + cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; } static inline unsigned long long cycles_2_ns(unsigned long long cyc) @@ -286,7 +291,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, if (use_tsc) { if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); - set_cyc2ns_scale(cpu_khz/1000); + set_cyc2ns_scale(cpu_khz); } } #endif @@ -536,7 +541,7 @@ static int __init init_tsc(char* override) printk("Detected %u.%03u MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); } - set_cyc2ns_scale(cpu_khz/1000); + set_cyc2ns_scale(cpu_khz); return 0; } } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 19e90bdd84e..c34d1bfc516 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -488,6 +488,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs, tss->io_bitmap_max - thread->io_bitmap_max); tss->io_bitmap_max = thread->io_bitmap_max; tss->io_bitmap_base = IO_BITMAP_OFFSET; + tss->io_bitmap_owner = thread; put_cpu(); return; } diff --git a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h index 898ed905e11..f1e3204f5de 100644 --- a/arch/i386/mach-es7000/es7000.h +++ b/arch/i386/mach-es7000/es7000.h @@ -24,6 +24,15 @@ * http://www.unisys.com */ +/* + * ES7000 chipsets + */ + +#define NON_UNISYS 0 +#define ES7000_CLASSIC 1 +#define ES7000_ZORRO 2 + + #define MIP_REG 1 #define MIP_PSAI_REG 4 @@ -106,6 +115,6 @@ struct mip_reg { extern int parse_unisys_oem (char *oemptr); extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); -extern void setup_unisys (); +extern void setup_unisys(void); extern int es7000_start_cpu(int cpu, unsigned long eip); extern void es7000_sw_apic(void); diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c index dc6660511b0..a9ab0644f40 100644 --- a/arch/i386/mach-es7000/es7000plat.c +++ b/arch/i386/mach-es7000/es7000plat.c @@ -62,6 +62,9 @@ static unsigned int base; static int es7000_rename_gsi(int ioapic, int gsi) { + if (es7000_plat == ES7000_ZORRO) + return gsi; + if (!base) { int i; for (i = 0; i < nr_ioapics; i++) @@ -76,7 +79,7 @@ es7000_rename_gsi(int ioapic, int gsi) #endif /* (CONFIG_X86_IO_APIC) && (CONFIG_ACPI) */ void __init -setup_unisys () +setup_unisys(void) { /* * Determine the generation of the ES7000 currently running. @@ -86,9 +89,9 @@ setup_unisys () * */ if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2)) - es7000_plat = 2; + es7000_plat = ES7000_ZORRO; else - es7000_plat = 1; + es7000_plat = ES7000_CLASSIC; ioapic_renumber_irq = es7000_rename_gsi; } @@ -151,7 +154,7 @@ parse_unisys_oem (char *oemptr) } if (success < 2) { - es7000_plat = 0; + es7000_plat = NON_UNISYS; } else setup_unisys(); return es7000_plat; diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 9edd4485b91..cf572d9a3b6 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -108,7 +108,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs, desc = (void *)desc + (seg & ~7); } else { /* Must disable preemption while reading the GDT. */ - desc = (u32 *)&per_cpu(cpu_gdt_table, get_cpu()); + desc = (u32 *)get_cpu_gdt_table(get_cpu()); desc = (void *)desc + (seg & ~7); } diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index cddafe33ff7..19e6f4871d1 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -547,31 +547,48 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route return 0; } -static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int via_router_probe(struct irq_router *r, + struct pci_dev *router, u16 device) { /* FIXME: We should move some of the quirk fixup stuff here */ - if (router->device == PCI_DEVICE_ID_VIA_82C686 && - device == PCI_DEVICE_ID_VIA_82C586_0) { - /* Asus k7m bios wrongly reports 82C686A as 586-compatible */ - device = PCI_DEVICE_ID_VIA_82C686; + /* + * work arounds for some buggy BIOSes + */ + if (device == PCI_DEVICE_ID_VIA_82C586_0) { + switch(router->device) { + case PCI_DEVICE_ID_VIA_82C686: + /* + * Asus k7m bios wrongly reports 82C686A + * as 586-compatible + */ + device = PCI_DEVICE_ID_VIA_82C686; + break; + case PCI_DEVICE_ID_VIA_8235: + /** + * Asus a7v-x bios wrongly reports 8235 + * as 586-compatible + */ + device = PCI_DEVICE_ID_VIA_8235; + break; + } } - switch(device) - { - case PCI_DEVICE_ID_VIA_82C586_0: - r->name = "VIA"; - r->get = pirq_via586_get; - r->set = pirq_via586_set; - return 1; - case PCI_DEVICE_ID_VIA_82C596: - case PCI_DEVICE_ID_VIA_82C686: - case PCI_DEVICE_ID_VIA_8231: + switch(device) { + case PCI_DEVICE_ID_VIA_82C586_0: + r->name = "VIA"; + r->get = pirq_via586_get; + r->set = pirq_via586_set; + return 1; + case PCI_DEVICE_ID_VIA_82C596: + case PCI_DEVICE_ID_VIA_82C686: + case PCI_DEVICE_ID_VIA_8231: + case PCI_DEVICE_ID_VIA_8235: /* FIXME: add new ones for 8233/5 */ - r->name = "VIA"; - r->get = pirq_via_get; - r->set = pirq_via_set; - return 1; + r->name = "VIA"; + r->get = pirq_via_get; + r->set = pirq_via_set; + return 1; } return 0; } diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index b27c5acc79d..1f1572692e0 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -51,16 +51,14 @@ void save_processor_state(void) __save_processor_state(&saved_context); } -static void -do_fpu_end(void) +static void do_fpu_end(void) { - /* restore FPU regs if necessary */ - /* Do it out of line so that gcc does not move cr0 load to some stupid place */ - kernel_fpu_end(); - mxcsr_feature_mask_init(); + /* + * Restore FPU regs if necessary. + */ + kernel_fpu_end(); } - static void fix_processor_context(void) { int cpu = smp_processor_id(); diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 3fa67ecebc8..dc282710421 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -36,6 +36,7 @@ #include <linux/uio.h> #include <linux/nfs_fs.h> #include <linux/quota.h> +#include <linux/syscalls.h> #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsd.h> #include <linux/nfsd/cache.h> diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c index 768c7e46957..6ade3790ce0 100644 --- a/arch/ia64/kernel/cyclone.c +++ b/arch/ia64/kernel/cyclone.c @@ -2,6 +2,7 @@ #include <linux/smp.h> #include <linux/time.h> #include <linux/errno.h> +#include <linux/timex.h> #include <asm/io.h> /* IBM Summit (EXA) Cyclone counter code*/ diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 8b8a5a45b62..5b7e736f3b4 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -32,10 +32,6 @@ extern unsigned long wall_jiffies; -u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - #define TIME_KEEPER_ID 0 /* smp_processor_id() of time-keeper */ #ifdef CONFIG_IA64_DEBUG_IRQ diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 85920fb8d08..396c94218cc 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -653,8 +653,6 @@ ENTRY(rie_handler) SAVE_ALL mvfc r0, bpc ld r1, @r0 - seth r0, #0xa0f0 - st r1, @r0 ldi r1, #0x20 ; error_code mv r0, sp ; pt_regs bl do_rie_handler diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c index e545b065f7e..eda9f963c1e 100644 --- a/arch/m32r/kernel/io_m32700ut.c +++ b/arch/m32r/kernel/io_m32700ut.c @@ -64,11 +64,11 @@ static inline void *__port2addr_ata(unsigned long port) * from 0x10000000 to 0x13ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART 0x300 -#define LAN_IOEND 0x320 +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 static inline void *_port2addr_ne(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET + 0x10000000); + return (void *)(port + 0x10000000); } static inline void *_port2addr_usb(unsigned long port) { diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c index 78033165fb5..3c3da042fbd 100644 --- a/arch/m32r/kernel/io_mappi.c +++ b/arch/m32r/kernel/io_mappi.c @@ -31,7 +31,7 @@ extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } static inline void *_port2addr_ne(unsigned long port) diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c index 5c03504bf65..df3c729cb3e 100644 --- a/arch/m32r/kernel/io_mappi2.c +++ b/arch/m32r/kernel/io_mappi2.c @@ -33,12 +33,9 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } -#define LAN_IOSTART 0x300 -#define LAN_IOEND 0x320 - #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) static inline void *__port2addr_ata(unsigned long port) { @@ -59,15 +56,17 @@ static inline void *__port2addr_ata(unsigned long port) } #endif +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 #ifdef CONFIG_CHIP_OPSP static inline void *_port2addr_ne(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET + 0x10000000); + return (void *)(port + 0x10000000); } #else static inline void *_port2addr_ne(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET + 0x04000000); + return (void *)(port + 0x04000000); } #endif static inline void *_port2addr_usb(unsigned long port) diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c index c80bde65785..6716ffea769 100644 --- a/arch/m32r/kernel/io_mappi3.c +++ b/arch/m32r/kernel/io_mappi3.c @@ -36,9 +36,6 @@ static inline void *_port2addr(unsigned long port) return (void *)(port + NONCACHE_OFFSET); } -#define LAN_IOSTART 0x300 -#define LAN_IOEND 0x320 - #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) static inline void *__port2addr_ata(unsigned long port) { @@ -59,9 +56,11 @@ static inline void *__port2addr_ata(unsigned long port) } #endif +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 static inline void *_port2addr_ne(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET + 0x10000000); + return (void *)(port + 0x10000000); } static inline void *_port2addr_usb(unsigned long port) diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c index 9997dddd24d..8be323931e4 100644 --- a/arch/m32r/kernel/io_oaks32r.c +++ b/arch/m32r/kernel/io_oaks32r.c @@ -16,7 +16,7 @@ static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } static inline void *_port2addr_ne(unsigned long port) diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c index e34951e8156..4793bd18e11 100644 --- a/arch/m32r/kernel/io_opsput.c +++ b/arch/m32r/kernel/io_opsput.c @@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } /* @@ -44,11 +44,11 @@ static inline void *_port2addr(unsigned long port) * from 0x10000000 to 0x13ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART 0x300 -#define LAN_IOEND 0x320 +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 static inline void *_port2addr_ne(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET + 0x10000000); + return (void *)(port + 0x10000000); } static inline void *_port2addr_usb(unsigned long port) { diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c index 9eb161dcc10..39a379af40b 100644 --- a/arch/m32r/kernel/io_usrv.c +++ b/arch/m32r/kernel/io_usrv.c @@ -47,7 +47,7 @@ static inline void *_port2addr(unsigned long port) else if (port >= UART1_IOSTART && port <= UART1_IOEND) port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART; #endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */ - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } static inline void delay(void) diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 124f7c1b775..078d2a0e71c 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -756,7 +756,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) return ret; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index ec5674727e7..f722ec8eb02 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c @@ -305,19 +305,19 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "processor\t: %ld\n", cpu); -#ifdef CONFIG_CHIP_VDEC2 +#if defined(CONFIG_CHIP_VDEC2) seq_printf(m, "cpu family\t: VDEC2\n" "cache size\t: Unknown\n"); -#elif CONFIG_CHIP_M32700 +#elif defined(CONFIG_CHIP_M32700) seq_printf(m,"cpu family\t: M32700\n" "cache size\t: I-8KB/D-8KB\n"); -#elif CONFIG_CHIP_M32102 +#elif defined(CONFIG_CHIP_M32102) seq_printf(m,"cpu family\t: M32102\n" "cache size\t: I-8KB\n"); -#elif CONFIG_CHIP_OPSP +#elif defined(CONFIG_CHIP_OPSP) seq_printf(m,"cpu family\t: OPSP\n" "cache size\t: I-8KB/D-8KB\n"); -#elif CONFIG_CHIP_MP +#elif defined(CONFIG_CHIP_MP) seq_printf(m, "cpu family\t: M32R-MP\n" "cache size\t: I-xxKB/D-xxKB\n"); #else @@ -326,19 +326,19 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "bogomips\t: %lu.%02lu\n", c->loops_per_jiffy/(500000/HZ), (c->loops_per_jiffy/(5000/HZ)) % 100); -#ifdef CONFIG_PLAT_MAPPI +#if defined(CONFIG_PLAT_MAPPI) seq_printf(m, "Machine\t\t: Mappi Evaluation board\n"); -#elif CONFIG_PLAT_MAPPI2 +#elif defined(CONFIG_PLAT_MAPPI2) seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n"); -#elif CONFIG_PLAT_MAPPI3 +#elif defined(CONFIG_PLAT_MAPPI3) seq_printf(m, "Machine\t\t: Mappi-III Evaluation board\n"); -#elif CONFIG_PLAT_M32700UT +#elif defined(CONFIG_PLAT_M32700UT) seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n"); -#elif CONFIG_PLAT_OPSPUT +#elif defined(CONFIG_PLAT_OPSPUT) seq_printf(m, "Machine\t\t: OPSPUT Evaluation board\n"); -#elif CONFIG_PLAT_USRV +#elif defined(CONFIG_PLAT_USRV) seq_printf(m, "Machine\t\t: uServer\n"); -#elif CONFIG_PLAT_OAKS32R +#elif defined(CONFIG_PLAT_OAKS32R) seq_printf(m, "Machine\t\t: OAKS32R\n"); #else seq_printf(m, "Machine\t\t: Unknown\n"); diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 539c562cd54..2ebce2063fe 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -39,10 +39,6 @@ extern void send_IPI_allbutself(int, int); extern void smp_local_timer_interrupt(struct pt_regs *); #endif -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - extern unsigned long wall_jiffies; #define TICK_SIZE (tick_nsec / 1000) diff --git a/arch/m32r/lib/csum_partial_copy.c b/arch/m32r/lib/csum_partial_copy.c index ddb16a83a8c..3d5f0614585 100644 --- a/arch/m32r/lib/csum_partial_copy.c +++ b/arch/m32r/lib/csum_partial_copy.c @@ -18,10 +18,10 @@ #include <linux/module.h> #include <linux/types.h> +#include <linux/string.h> #include <net/checksum.h> #include <asm/byteorder.h> -#include <asm/string.h> #include <asm/uaccess.h> /* diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 8ed1b01a6a8..f7f1d2e5b90 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -121,7 +121,7 @@ void ptrace_disable(struct task_struct *child) child->thread.work.syscall_trace = 0; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; unsigned long tmp; diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 4ec95e3cb87..98e4b1adfa2 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -27,10 +27,6 @@ #include <linux/timex.h> #include <linux/profile.h> -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - static inline int set_rtc_mmss(unsigned long nowtime) { if (mach_set_clock_mmss) diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 9724e1cd82e..621d7b91ccf 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -101,7 +101,7 @@ void ptrace_disable(struct task_struct *child) put_reg(child, PT_SR, tmp); } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c index b17c1ecba96..b9d8abb4543 100644 --- a/arch/m68knommu/kernel/time.c +++ b/arch/m68knommu/kernel/time.c @@ -27,10 +27,6 @@ #define TICK_SIZE (tick_nsec / 1000) -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - extern unsigned long wall_jiffies; diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 7ce34d4aa22..10d3644e360 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -1077,8 +1077,8 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) struct elfhdr elf; off_t offset = 0, dataoff; int limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; - int numnote = 4; - struct memelfnote notes[4]; + int numnote = 3; + struct memelfnote notes[3]; struct elf_prstatus prstatus; /* NT_PRSTATUS */ elf_fpregset_t fpu; /* NT_PRFPREG */ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ @@ -1211,20 +1211,15 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) } strlcpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname)); - notes[2].name = "CORE"; - notes[2].type = NT_TASKSTRUCT; - notes[2].datasz = sizeof(*current); - notes[2].data = current; - /* Try to dump the FPU. */ prstatus.pr_fpvalid = dump_fpu (regs, &fpu); if (!prstatus.pr_fpvalid) { numnote--; } else { - notes[3].name = "CORE"; - notes[3].type = NT_PRFPREG; - notes[3].datasz = sizeof(fpu); - notes[3].data = &fpu; + notes[2].name = "CORE"; + notes[2].type = NT_PRFPREG; + notes[2].datasz = sizeof(fpu); + notes[2].data = &fpu; } /* Write notes phdr entry. */ diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index fcceab8f2e0..f1b0f3e1f95 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -174,7 +174,7 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) return 0; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index a24651dfaab..787ed541d44 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -45,10 +45,6 @@ #define TICK_SIZE (tick_nsec / 1000) -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - /* * forward reference */ diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c index e1829a5d3b1..07631a97670 100644 --- a/arch/mips/sgi-ip27/ip27-berr.c +++ b/arch/mips/sgi-ip27/ip27-berr.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/signal.h> /* for SIGBUS */ #include <asm/module.h> #include <asm/sn/addrs.h> diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c index 8cad8f004f0..0a331104ad5 100644 --- a/arch/parisc/kernel/ioctl32.c +++ b/arch/parisc/kernel/ioctl32.c @@ -561,11 +561,6 @@ IOCTL_TABLE_START #define DECLARES #include "compat_ioctl.c" -/* Might be moved to compat_ioctl.h with some ifdefs... */ -COMPATIBLE_IOCTL(TIOCSTART) -COMPATIBLE_IOCTL(TIOCSTOP) -COMPATIBLE_IOCTL(TIOCSLTC) - /* PA-specific ioctls */ COMPATIBLE_IOCTL(PA_PERF_ON) COMPATIBLE_IOCTL(PA_PERF_OFF) diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index f3428e5e86f..18130c3748f 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -78,7 +78,7 @@ void ptrace_disable(struct task_struct *child) pa_psw(child)->l = 0; } -long sys_ptrace(long request, pid_t pid, long addr, long data) +long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; long ret; diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index bc979e1abde..cded2568078 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -33,10 +33,6 @@ #include <linux/timex.h> -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - /* xtime and wall_jiffies keep wall-clock time */ extern unsigned long wall_jiffies; diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index e7aee4108de..e2744b6879d 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -240,7 +240,7 @@ void ptrace_disable(struct task_struct *child) clear_single_step(child); } -int sys_ptrace(long request, long pid, long addr, long data) +long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret = -EPERM; diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index 22d7fd1e0ae..67797184f4e 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -66,11 +66,6 @@ #include <asm/time.h> -/* XXX false sharing with below? */ -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - unsigned long disarm_decr[NR_CPUS]; extern struct timezone sys_tz; diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index ff379686012..eed4ff6903f 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -609,11 +609,6 @@ static void parse_bootinfo(unsigned long r3, } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - static void hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) { diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c index 93c7231ea70..85b82125163 100644 --- a/arch/ppc/syslib/of_device.c +++ b/arch/ppc/syslib/of_device.c @@ -4,6 +4,8 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> +#include <linux/slab.h> + #include <asm/errno.h> #include <asm/of_device.h> diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/ppc64/kernel/hvcserver.c index bde8f42da85..4d584172055 100644 --- a/arch/ppc64/kernel/hvcserver.c +++ b/arch/ppc64/kernel/hvcserver.c @@ -22,6 +22,8 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/slab.h> + #include <asm/hvcall.h> #include <asm/hvcserver.h> #include <asm/io.h> diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c index a8005db23ec..ba4a899045c 100644 --- a/arch/ppc64/kernel/ioctl32.c +++ b/arch/ppc64/kernel/ioctl32.c @@ -39,9 +39,7 @@ IOCTL_TABLE_START #include <linux/compat_ioctl.h> #define DECLARES #include "compat_ioctl.c" -COMPATIBLE_IOCTL(TIOCSTART) -COMPATIBLE_IOCTL(TIOCSTOP) -COMPATIBLE_IOCTL(TIOCSLTC) + /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c index 9f200f0f2ad..3aabfd0d3dd 100644 --- a/arch/ppc64/kernel/of_device.c +++ b/arch/ppc64/kernel/of_device.c @@ -4,6 +4,8 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> +#include <linux/slab.h> + #include <asm/errno.h> #include <asm/of_device.h> diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index b1c044ca575..b33073c3172 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -53,7 +53,7 @@ void ptrace_disable(struct task_struct *child) clear_single_step(child); } -int sys_ptrace(long request, long pid, long addr, long data) +long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret = -EPERM; diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index b56c6a324e1..ab565468578 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -68,10 +68,6 @@ #include <asm/systemcfg.h> #include <asm/firmware.h> -u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - /* keep track of when we need to update the rtc */ time_t last_rtc_update; extern int piranha_simulator; diff --git a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c index 033643ab69e..d622c1d58e4 100644 --- a/arch/ppc64/lib/locks.c +++ b/arch/ppc64/lib/locks.c @@ -17,6 +17,8 @@ #include <linux/spinlock.h> #include <linux/module.h> #include <linux/stringify.h> +#include <linux/smp.h> + #include <asm/hvcall.h> #include <asm/iSeries/HvCall.h> diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c index 24a1e9f069a..6504c4e6998 100644 --- a/arch/s390/kernel/compat_ioctl.c +++ b/arch/s390/kernel/compat_ioctl.c @@ -18,6 +18,8 @@ #include <asm/dasd.h> #include <asm/cmb.h> #include <asm/tape390.h> +#include <asm/ccwdev.h> +#include "../../../drivers/s390/char/raw3270.h" static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *f) @@ -62,6 +64,13 @@ COMPATIBLE_IOCTL(BIODASDCMFENABLE) COMPATIBLE_IOCTL(BIODASDCMFDISABLE) COMPATIBLE_IOCTL(BIODASDREADALLCMB) +COMPATIBLE_IOCTL(TUBICMD) +COMPATIBLE_IOCTL(TUBOCMD) +COMPATIBLE_IOCTL(TUBGETI) +COMPATIBLE_IOCTL(TUBGETO) +COMPATIBLE_IOCTL(TUBSETMOD) +COMPATIBLE_IOCTL(TUBGETMOD) + COMPATIBLE_IOCTL(TAPE390_DISPLAY) /* s390 doesn't need handlers here */ diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 55654b6e16d..039354d7234 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -485,7 +485,9 @@ start: # .org 0x10000 startup:basr %r13,0 # get base -.LPG1: lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers +.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) + basr %r14, %r1 + lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers la %r12,_pstart-.LPG1(%r13) # pointer to parameter area # move IPL device to lowcore mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) @@ -560,6 +562,9 @@ startup:basr %r13,0 # get base mr %r2,%r1 # mem size in bytes in %r3 b .Lfchunk-.LPG1(%r13) + .align 4 +.Lget_ipl_device_addr: + .long .Lget_ipl_device .Lpmask: .byte 0 .align 8 @@ -755,6 +760,63 @@ _pstart: .global _pend _pend: +.Lget_ipl_device: + basr %r12,0 +.LPG2: l %r1,0xb8 # get sid + sll %r1,15 # test if subchannel is enabled + srl %r1,31 + ltr %r1,%r1 + bz 0(%r14) # subchannel disabled + l %r1,0xb8 + la %r5,.Lipl_schib-.LPG2(%r12) + stsch 0(%r5) # get schib of subchannel + bnz 0(%r14) # schib not available + tm 5(%r5),0x01 # devno valid? + bno 0(%r14) + la %r6,ipl_parameter_flags-.LPG2(%r12) + oi 3(%r6),0x01 # set flag + la %r2,ipl_devno-.LPG2(%r12) + mvc 0(2,%r2),6(%r5) # store devno + tm 4(%r5),0x80 # qdio capable device? + bno 0(%r14) + oi 3(%r6),0x02 # set flag + + # copy ipl parameters + + lhi %r0,4096 + l %r2,20(%r0) # get address of parameter list + lhi %r3,IPL_PARMBLOCK_ORIGIN + st %r3,20(%r0) + lhi %r4,1 + cr %r2,%r3 # start parameters < destination ? + jl 0f + lhi %r1,1 # copy direction is upwards + j 1f +0: lhi %r1,-1 # copy direction is downwards + ar %r2,%r0 + ar %r3,%r0 + ar %r2,%r1 + ar %r3,%r1 +1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters + ar %r3,%r1 + ar %r2,%r1 + sr %r0,%r4 + jne 1b + b 0(%r14) + + .align 4 +.Lipl_schib: + .rept 13 + .long 0 + .endr + + .globl ipl_parameter_flags +ipl_parameter_flags: + .long 0 + .globl ipl_devno +ipl_devno: + .word 0 + #ifdef CONFIG_SHARED_KERNEL .org 0x100000 #endif @@ -764,11 +826,11 @@ _pend: # .globl _stext _stext: basr %r13,0 # get base -.LPG2: +.LPG3: # # Setup stack # - l %r15,.Linittu-.LPG2(%r13) + l %r15,.Linittu-.LPG3(%r13) mvc __LC_CURRENT(4),__TI_task(%r15) ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE st %r15,__LC_KERNEL_STACK # set end of kernel stack @@ -782,8 +844,8 @@ _stext: basr %r13,0 # get base lctl %c0,%c15,0(%r15) # - lam 0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess - l %r14,.Lstart-.LPG2(%r13) + lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess + l %r14,.Lstart-.LPG3(%r13) basr %r14,%r14 # call start_kernel # # We returned from start_kernel ?!? PANIK diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index c9ff0404c87..193aafa72f5 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -484,6 +484,8 @@ start: startup:basr %r13,0 # get base .LPG1: sll %r13,1 # remove high order bit srl %r13,1 + l %r1,.Lget_ipl_device_addr-.LPG1(%r13) + basr %r14,%r1 lhi %r1,1 # mode 1 = esame slr %r0,%r0 # set cpuid to zero sigp %r1,%r0,0x12 # switch to esame mode @@ -556,6 +558,9 @@ startup:basr %r13,0 # get base mlgr %r2,%r1 # mem size in bytes in %r3 b .Lfchunk-.LPG1(%r13) + .align 4 +.Lget_ipl_device_addr: + .long .Lget_ipl_device .Lpmask: .byte 0 .align 8 @@ -746,6 +751,63 @@ _pstart: .global _pend _pend: +.Lget_ipl_device: + basr %r12,0 +.LPG2: l %r1,0xb8 # get sid + sll %r1,15 # test if subchannel is enabled + srl %r1,31 + ltr %r1,%r1 + bz 0(%r14) # subchannel disabled + l %r1,0xb8 + la %r5,.Lipl_schib-.LPG2(%r12) + stsch 0(%r5) # get schib of subchannel + bnz 0(%r14) # schib not available + tm 5(%r5),0x01 # devno valid? + bno 0(%r14) + la %r6,ipl_parameter_flags-.LPG2(%r12) + oi 3(%r6),0x01 # set flag + la %r2,ipl_devno-.LPG2(%r12) + mvc 0(2,%r2),6(%r5) # store devno + tm 4(%r5),0x80 # qdio capable device? + bno 0(%r14) + oi 3(%r6),0x02 # set flag + + # copy ipl parameters + + lhi %r0,4096 + l %r2,20(%r0) # get address of parameter list + lhi %r3,IPL_PARMBLOCK_ORIGIN + st %r3,20(%r0) + lhi %r4,1 + cr %r2,%r3 # start parameters < destination ? + jl 0f + lhi %r1,1 # copy direction is upwards + j 1f +0: lhi %r1,-1 # copy direction is downwards + ar %r2,%r0 + ar %r3,%r0 + ar %r2,%r1 + ar %r3,%r1 +1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters + ar %r3,%r1 + ar %r2,%r1 + sr %r0,%r4 + jne 1b + b 0(%r14) + + .align 4 +.Lipl_schib: + .rept 13 + .long 0 + .endr + + .globl ipl_parameter_flags +ipl_parameter_flags: + .long 0 + .globl ipl_devno +ipl_devno: + .word 0 + #ifdef CONFIG_SHARED_KERNEL .org 0x100000 #endif @@ -755,7 +817,7 @@ _pend: # .globl _stext _stext: basr %r13,0 # get base -.LPG2: +.LPG3: # # Setup stack # @@ -774,7 +836,7 @@ _stext: basr %r13,0 # get base lctlg %c0,%c15,0(%r15) # - lam 0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess + lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess brasl %r14,start_kernel # go to C code # # We returned from start_kernel ?!? PANIK diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 5204778b8e5..31e7b19348b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -36,6 +36,7 @@ #include <linux/console.h> #include <linux/seq_file.h> #include <linux/kernel_stat.h> +#include <linux/device.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -685,3 +686,188 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; +#define DEFINE_IPL_ATTR(_name, _format, _value) \ +static ssize_t ipl_##_name##_show(struct subsystem *subsys, \ + char *page) \ +{ \ + return sprintf(page, _format, _value); \ +} \ +static struct subsys_attribute ipl_##_name##_attr = \ + __ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL); + +DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.wwpn); +DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.lun); +DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.bootprog); +DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.br_lba); + +enum ipl_type_type { + ipl_type_unknown, + ipl_type_ccw, + ipl_type_fcp, +}; + +static enum ipl_type_type +get_ipl_type(void) +{ + struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; + + if (!IPL_DEVNO_VALID) + return ipl_type_unknown; + if (!IPL_PARMBLOCK_VALID) + return ipl_type_ccw; + if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION) + return ipl_type_unknown; + if (ipl->fcp.pbt != IPL_TYPE_FCP) + return ipl_type_unknown; + return ipl_type_fcp; +} + +static ssize_t +ipl_type_show(struct subsystem *subsys, char *page) +{ + switch (get_ipl_type()) { + case ipl_type_ccw: + return sprintf(page, "ccw\n"); + case ipl_type_fcp: + return sprintf(page, "fcp\n"); + default: + return sprintf(page, "unknown\n"); + } +} + +static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type); + +static ssize_t +ipl_device_show(struct subsystem *subsys, char *page) +{ + struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; + + switch (get_ipl_type()) { + case ipl_type_ccw: + return sprintf(page, "0.0.%04x\n", ipl_devno); + case ipl_type_fcp: + return sprintf(page, "0.0.%04x\n", ipl->fcp.devno); + default: + return 0; + } +} + +static struct subsys_attribute ipl_device_attr = + __ATTR(device, S_IRUGO, ipl_device_show, NULL); + +static struct attribute *ipl_fcp_attrs[] = { + &ipl_type_attr.attr, + &ipl_device_attr.attr, + &ipl_wwpn_attr.attr, + &ipl_lun_attr.attr, + &ipl_bootprog_attr.attr, + &ipl_br_lba_attr.attr, + NULL, +}; + +static struct attribute_group ipl_fcp_attr_group = { + .attrs = ipl_fcp_attrs, +}; + +static struct attribute *ipl_ccw_attrs[] = { + &ipl_type_attr.attr, + &ipl_device_attr.attr, + NULL, +}; + +static struct attribute_group ipl_ccw_attr_group = { + .attrs = ipl_ccw_attrs, +}; + +static struct attribute *ipl_unknown_attrs[] = { + &ipl_type_attr.attr, + NULL, +}; + +static struct attribute_group ipl_unknown_attr_group = { + .attrs = ipl_unknown_attrs, +}; + +static ssize_t +ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + unsigned int size = IPL_PARMBLOCK_SIZE; + + if (off > size) + return 0; + if (off + count > size) + count = size - off; + + memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count); + return count; +} + +static struct bin_attribute ipl_parameter_attr = { + .attr = { + .name = "binary_parameter", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = PAGE_SIZE, + .read = &ipl_parameter_read, +}; + +static ssize_t +ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len; + void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data; + + if (off > size) + return 0; + if (off + count > size) + count = size - off; + + memcpy(buf, scp_data + off, count); + return count; +} + +static struct bin_attribute ipl_scp_data_attr = { + .attr = { + .name = "scp_data", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = PAGE_SIZE, + .read = &ipl_scp_data_read, +}; + +static decl_subsys(ipl, NULL, NULL); + +static int __init +ipl_device_sysfs_register(void) { + int rc; + + rc = firmware_register(&ipl_subsys); + if (rc) + return rc; + + switch (get_ipl_type()) { + case ipl_type_ccw: + sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group); + break; + case ipl_type_fcp: + sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); + sysfs_create_bin_file(&ipl_subsys.kset.kobj, + &ipl_parameter_attr); + sysfs_create_bin_file(&ipl_subsys.kset.kobj, + &ipl_scp_data_attr); + break; + default: + sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_unknown_attr_group); + break; + } + return 0; +} + +__initcall(ipl_device_sysfs_register); diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 2fd75da1549..9a1d95894f3 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -49,10 +49,6 @@ #define TICK_SIZE tick -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - static ext_int_info_t ext_int_info_cc; static u64 init_timer_cc; static u64 jiffies_timer_cc; diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index fa0726507b3..22a895ecb7a 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -24,7 +24,6 @@ #include <asm/s390_ext.h> #include <asm/timer.h> -#define VTIMER_MAGIC (TIMER_MAGIC + 1) static ext_int_info_t ext_int_info_timer; DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); @@ -277,20 +276,12 @@ static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code) void init_virt_timer(struct vtimer_list *timer) { - timer->magic = VTIMER_MAGIC; timer->function = NULL; INIT_LIST_HEAD(&timer->entry); spin_lock_init(&timer->lock); } EXPORT_SYMBOL(init_virt_timer); -static inline int check_vtimer(struct vtimer_list *timer) -{ - if (timer->magic != VTIMER_MAGIC) - return -EINVAL; - return 0; -} - static inline int vtimer_pending(struct vtimer_list *timer) { return (!list_empty(&timer->entry)); @@ -346,7 +337,7 @@ static void internal_add_vtimer(struct vtimer_list *timer) static inline int prepare_vtimer(struct vtimer_list *timer) { - if (check_vtimer(timer) || !timer->function) { + if (!timer->function) { printk("add_virt_timer: uninitialized timer\n"); return -EINVAL; } @@ -414,7 +405,7 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires) unsigned long flags; int cpu; - if (check_vtimer(timer) || !timer->function) { + if (!timer->function) { printk("mod_virt_timer: uninitialized timer\n"); return -EINVAL; } @@ -481,11 +472,6 @@ int del_virt_timer(struct vtimer_list *timer) unsigned long flags; struct vtimer_queue *vt_list; - if (check_vtimer(timer)) { - printk("del_virt_timer: timer not initialized\n"); - return -EINVAL; - } - /* check if timer is pending */ if (!vtimer_pending(timer)) return 0; diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 71a6d4e7809..6e3b58bd879 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/sysdev.h> #include <linux/module.h> +#include <linux/string.h> #include <asm/dma.h> static struct sysdev_class dma_sysclass = { diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index e0b384bef55..47abf6e49df 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c @@ -20,6 +20,7 @@ #include <linux/delay.h> #include <linux/cpumask.h> #include <linux/smp.h> +#include <linux/sched.h> /* set_cpus_allowed() */ #include <asm/processor.h> #include <asm/watchdog.h> diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index b28919b6568..1fbe5a428e3 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -80,7 +80,7 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; struct user * dummy = NULL; diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 02ca69918d7..671b876416b 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -56,10 +56,6 @@ extern unsigned long wall_jiffies; #define TICK_SIZE (tick_nsec / 1000) DEFINE_SPINLOCK(tmu0_lock); -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - /* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want * these routines anywhere... */ #ifdef CONFIG_SH_RTC diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index fd2000956da..71f2eec00b9 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -121,7 +121,7 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) return 0; } -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; extern void poke_real_address_q(unsigned long long addr, unsigned long long data); diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c index 43e395a14f4..870fe5327e0 100644 --- a/arch/sh64/kernel/time.c +++ b/arch/sh64/kernel/time.c @@ -116,8 +116,6 @@ extern unsigned long wall_jiffies; -u64 jiffies_64 = INITIAL_JIFFIES; - static unsigned long tmu_base, rtc_base; unsigned long cprc_base; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 36a40697b8d..25e31d5ec99 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -497,8 +497,8 @@ static void pcic_map_pci_device(struct linux_pcic *pcic, * CheerIO makes a similar conversion. * See ebus.c for details. * - * Note that check_region()/request_region() - * work for these devices. + * Note that request_region() + * works for these devices. * * XXX Neat trick, but it's a *bad* idea * to shit into regions like that. diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 279a62627c1..24814d58f9e 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -45,10 +45,6 @@ extern unsigned long wall_jiffies; -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - DEFINE_SPINLOCK(rtc_lock); enum sparc_clock_type sp_clock_typ; DEFINE_SPINLOCK(mostek_lock); diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 43fc3173d48..e6a00325075 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -475,9 +475,6 @@ IOCTL_TABLE_START #include <linux/compat_ioctl.h> #define DECLARES #include "compat_ioctl.c" -COMPATIBLE_IOCTL(TIOCSTART) -COMPATIBLE_IOCTL(TIOCSTOP) -COMPATIBLE_IOCTL(TIOCSLTC) COMPATIBLE_IOCTL(FBIOGTYPE) COMPATIBLE_IOCTL(FBIOSATTR) COMPATIBLE_IOCTL(FBIOGATTR) diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 3f08a32f51a..38c5525087a 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -55,10 +55,6 @@ unsigned long ds1287_regs = 0UL; extern unsigned long wall_jiffies; -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - static void __iomem *mstk48t08_regs; static void __iomem *mstk48t59_regs; diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 684e1f8b275..cd06ed7d842 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -27,10 +27,6 @@ config UID16 bool default y -config RWSEM_GENERIC_SPINLOCK - bool - default y - config GENERIC_CALIBRATE_DELAY bool default y @@ -40,6 +36,12 @@ config IRQ_RELEASE_METHOD bool default y +menu "Host processor type and features" + +source "arch/i386/Kconfig.cpu" + +endmenu + menu "UML-specific options" config MODE_TT diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64 index bd35e59419c..aae19bc4b06 100644 --- a/arch/um/Kconfig.x86_64 +++ b/arch/um/Kconfig.x86_64 @@ -6,6 +6,11 @@ config 64BIT bool default y +#XXX: this is so in the underlying arch, but it's wrong!!! +config RWSEM_GENERIC_SPINLOCK + bool + default y + config SEMAPHORE_SLEEPERS bool default y diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 2ee8a285811..aef7c50f8e1 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -29,6 +29,12 @@ endif CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) -ifneq ($(CONFIG_GPROF),y) -ARCH_CFLAGS += -DUM_FASTCALL -endif +# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. +include $(srctree)/arch/i386/Makefile.cpu + +# prevent gcc from keeping the stack 16 byte aligned. Taken from i386. +cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) + +CFLAGS += $(cflags-y) +USER_CFLAGS += $(cflags-y) + diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h index a0d5b74d373..57bd79efbee 100644 --- a/arch/um/include/sysdep-i386/syscalls.h +++ b/arch/um/include/sysdep-i386/syscalls.h @@ -11,7 +11,6 @@ typedef long syscall_handler_t(struct pt_regs); /* Not declared on x86, incompatible declarations on x86_64, so these have * to go here rather than in sys_call_table.c */ -extern syscall_handler_t sys_ptrace; extern syscall_handler_t sys_rt_sigaction; extern syscall_handler_t old_mmap_i386; diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 4e08f7545d6..020ca79b8d3 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -22,10 +22,6 @@ #include "mode.h" #include "os.h" -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - int hz(void) { return(HZ); diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index 4726b87f5e5..d6077ff47d2 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -113,7 +113,7 @@ static int set_single_step (struct task_struct *t, int val) return 1; } -int sys_ptrace(long request, long pid, long addr, long data) +long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int rval; diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c index ea3fd8844ff..c1e85c2aef6 100644 --- a/arch/v850/kernel/time.c +++ b/arch/v850/kernel/time.c @@ -26,10 +26,6 @@ #include "mach.h" -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - #define TICK_SIZE (tick_nsec / 1000) /* diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 419758f19ca..4ba0e293d5e 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -12,40 +12,11 @@ #define INCLUDES #include <linux/syscalls.h> #include "compat_ioctl.c" -#include <asm/mtrr.h> #include <asm/ia32.h> #define CODE #include "compat_ioctl.c" -#ifndef TIOCGDEV -#define TIOCGDEV _IOR('T',0x32, unsigned int) -#endif -static int tiocgdev(unsigned fd, unsigned cmd, unsigned int __user *ptr) -{ - - struct file *file; - struct tty_struct *real_tty; - int fput_needed, ret; - - file = fget_light(fd, &fput_needed); - if (!file) - return -EBADF; - - ret = -EINVAL; - if (file->f_op->ioctl != tty_ioctl) - goto out; - real_tty = (struct tty_struct *)file->private_data; - if (!real_tty) - goto out; - - ret = put_user(new_encode_dev(tty_devnum(real_tty)), ptr); - -out: - fput_light(file, fput_needed); - return ret; -} - #define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */ #define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */ #define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */ @@ -85,90 +56,6 @@ static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg) return sys_ioctl(fd,cmd,arg); } -/* /proc/mtrr ioctls */ - - -struct mtrr_sentry32 -{ - compat_ulong_t base; /* Base address */ - compat_uint_t size; /* Size of region */ - compat_uint_t type; /* Type of region */ -}; - -struct mtrr_gentry32 -{ - compat_ulong_t regnum; /* Register number */ - compat_uint_t base; /* Base address */ - compat_uint_t size; /* Size of region */ - compat_uint_t type; /* Type of region */ -}; - -#define MTRR_IOCTL_BASE 'M' - -#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32) -#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32) -#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32) -#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32) -#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32) -#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32) -#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32) -#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32) -#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32) -#define MTRRIOC32_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) - - -static int mtrr_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct mtrr_gentry g; - struct mtrr_sentry s; - int get = 0, err = 0; - struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)arg; - mm_segment_t oldfs = get_fs(); - - switch (cmd) { -#define SET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; break -#define GET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; get=1; break - SET(ADD); - SET(SET); - SET(DEL); - GET(GET); - SET(KILL); - SET(ADD_PAGE); - SET(SET_PAGE); - SET(DEL_PAGE); - GET(GET_PAGE); - SET(KILL_PAGE); - } - - if (get) { - err = get_user(g.regnum, &g32->regnum); - err |= get_user(g.base, &g32->base); - err |= get_user(g.size, &g32->size); - err |= get_user(g.type, &g32->type); - - arg = (unsigned long)&g; - } else { - struct mtrr_sentry32 __user *s32 = (struct mtrr_sentry32 __user *)arg; - err = get_user(s.base, &s32->base); - err |= get_user(s.size, &s32->size); - err |= get_user(s.type, &s32->type); - - arg = (unsigned long)&s; - } - if (err) return err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, arg); - set_fs(oldfs); - - if (!err && get) { - err = put_user(g.base, &g32->base); - err |= put_user(g.size, &g32->size); - err |= put_user(g.regnum, &g32->regnum); - err |= put_user(g.type, &g32->type); - } - return err; -} #define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) }, #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) @@ -185,7 +72,6 @@ COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain * COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ -HANDLE_IOCTL(TIOCGDEV, tiocgdev) /* realtime device */ HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl) HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) @@ -193,17 +79,6 @@ HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl) HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl) HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl) /* take care of sizeof(sizeof()) breakage */ -/* mtrr */ -HANDLE_IOCTL(MTRRIOC32_ADD_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_SET_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_DEL_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_GET_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_KILL_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_ADD_PAGE_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_SET_PAGE_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_DEL_PAGE_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_GET_PAGE_ENTRY, mtrr_ioctl32) -HANDLE_IOCTL(MTRRIOC32_KILL_PAGE_ENTRY, mtrr_ioctl32) }; int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index b2a238b5a17..c6c9791d77c 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -494,7 +494,7 @@ void invalidate_interrupt7(void); void thermal_interrupt(void); void i8254_timer_resume(void); -static void setup_timer(void) +static void setup_timer_hardware(void) { outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ udelay(10); @@ -505,13 +505,13 @@ static void setup_timer(void) static int timer_resume(struct sys_device *dev) { - setup_timer(); + setup_timer_hardware(); return 0; } void i8254_timer_resume(void) { - setup_timer(); + setup_timer_hardware(); } static struct sysdev_class timer_sysclass = { @@ -594,7 +594,7 @@ void __init init_IRQ(void) * Set the clock to HZ Hz, we already have a valid * vector now: */ - setup_timer(); + setup_timer_hardware(); if (!acpi_ioapic) setup_irq(2, &irq2); diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index cb28df14ff6..da0bc3e7bdf 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -1213,7 +1213,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", + "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", NULL, "est", "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c index f066c6ab361..fd2bef78088 100644 --- a/arch/x86_64/kernel/suspend.c +++ b/arch/x86_64/kernel/suspend.c @@ -63,13 +63,12 @@ void save_processor_state(void) __save_processor_state(&saved_context); } -static void -do_fpu_end(void) +static void do_fpu_end(void) { - /* restore FPU regs if necessary */ - /* Do it out of line so that gcc does not move cr0 load to some stupid place */ - kernel_fpu_end(); - mxcsr_feature_mask_init(); + /* + * Restore FPU regs if necessary + */ + kernel_fpu_end(); } void __restore_processor_state(struct saved_context *ctxt) @@ -148,57 +147,7 @@ extern int restore_image(void); pgd_t *temp_level4_pgt; -static void **pages; - -static inline void *__add_page(void) -{ - void **c; - - c = (void **)get_usable_page(GFP_ATOMIC); - if (c) { - *c = pages; - pages = c; - } - return c; -} - -static inline void *__next_page(void) -{ - void **c; - - c = pages; - if (c) { - pages = *c; - *c = NULL; - } - return c; -} - -/* - * Try to allocate as many usable pages as needed and daisy chain them. - * If one allocation fails, free the pages allocated so far - */ -static int alloc_usable_pages(unsigned long n) -{ - void *p; - - pages = NULL; - do - if (!__add_page()) - break; - while (--n); - if (n) { - p = __next_page(); - while (p) { - free_page((unsigned long)p); - p = __next_page(); - } - return -ENOMEM; - } - return 0; -} - -static void res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) +static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) { long i, j; @@ -212,7 +161,9 @@ static void res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long e if (paddr >= end) break; - pmd = (pmd_t *)__next_page(); + pmd = (pmd_t *)get_safe_page(GFP_ATOMIC); + if (!pmd) + return -ENOMEM; set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { unsigned long pe; @@ -224,13 +175,17 @@ static void res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long e set_pmd(pmd, __pmd(pe)); } } + return 0; } -static void set_up_temporary_mappings(void) +static int set_up_temporary_mappings(void) { unsigned long start, end, next; + int error; - temp_level4_pgt = (pgd_t *)__next_page(); + temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC); + if (!temp_level4_pgt) + return -ENOMEM; /* It is safe to reuse the original kernel mapping */ set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map), @@ -241,29 +196,27 @@ static void set_up_temporary_mappings(void) end = (unsigned long)pfn_to_kaddr(end_pfn); for (; start < end; start = next) { - pud_t *pud = (pud_t *)__next_page(); + pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC); + if (!pud) + return -ENOMEM; next = start + PGDIR_SIZE; if (next > end) next = end; - res_phys_pud_init(pud, __pa(start), __pa(next)); + if ((error = res_phys_pud_init(pud, __pa(start), __pa(next)))) + return error; set_pgd(temp_level4_pgt + pgd_index(start), mk_kernel_pgd(__pa(pud))); } + return 0; } int swsusp_arch_resume(void) { - unsigned long n; + int error; - n = ((end_pfn << PAGE_SHIFT) + PUD_SIZE - 1) >> PUD_SHIFT; - n += (n + PTRS_PER_PUD - 1) / PTRS_PER_PUD + 1; - pr_debug("swsusp_arch_resume(): pages needed = %lu\n", n); - if (alloc_usable_pages(n)) { - free_eaten_memory(); - return -ENOMEM; - } /* We have got enough memory and from now on we cannot recover */ - set_up_temporary_mappings(); + if ((error = set_up_temporary_mappings())) + return error; restore_image(); return 0; } diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 703acde2a1a..fdaddc4e528 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -42,10 +42,6 @@ #include <asm/apic.h> #endif -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - #ifdef CONFIG_CPU_FREQ static void cpufreq_delayed_get(void); #endif @@ -481,9 +477,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static unsigned int cyc2ns_scale; #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ -static inline void set_cyc2ns_scale(unsigned long cpu_mhz) +static inline void set_cyc2ns_scale(unsigned long cpu_khz) { - cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; + cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; } static inline unsigned long long cycles_2_ns(unsigned long long cyc) @@ -655,7 +651,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, vxtime.tsc_quot = (1000L << 32) / cpu_khz; } - set_cyc2ns_scale(cpu_khz_ref / 1000); + set_cyc2ns_scale(cpu_khz_ref); return 0; } @@ -939,7 +935,7 @@ void __init time_init(void) rdtscll_sync(&vxtime.last_tsc); setup_irq(0, &irq0); - set_cyc2ns_scale(cpu_khz / 1000); + set_cyc2ns_scale(cpu_khz); #ifndef CONFIG_SMP time_init_gtod(); @@ -1093,6 +1089,7 @@ static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ; static unsigned long PIE_count; static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */ +static unsigned int hpet_t1_cmp; /* cached comparator register */ int is_hpet_enabled(void) { @@ -1129,10 +1126,12 @@ int hpet_rtc_timer_init(void) cnt = hpet_readl(HPET_COUNTER); cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); hpet_writel(cnt, HPET_T1_CMP); + hpet_t1_cmp = cnt; local_irq_restore(flags); cfg = hpet_readl(HPET_T1_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT; + cfg &= ~HPET_TN_PERIODIC; + cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; hpet_writel(cfg, HPET_T1_CFG); return 1; @@ -1142,8 +1141,12 @@ static void hpet_rtc_timer_reinit(void) { unsigned int cfg, cnt; - if (!(PIE_on | AIE_on | UIE_on)) + if (unlikely(!(PIE_on | AIE_on | UIE_on))) { + cfg = hpet_readl(HPET_T1_CFG); + cfg &= ~HPET_TN_ENABLE; + hpet_writel(cfg, HPET_T1_CFG); return; + } if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) hpet_rtc_int_freq = PIE_freq; @@ -1151,15 +1154,10 @@ static void hpet_rtc_timer_reinit(void) hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; /* It is more accurate to use the comparator value than current count.*/ - cnt = hpet_readl(HPET_T1_CMP); + cnt = hpet_t1_cmp; cnt += hpet_tick*HZ/hpet_rtc_int_freq; hpet_writel(cnt, HPET_T1_CMP); - - cfg = hpet_readl(HPET_T1_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT; - hpet_writel(cfg, HPET_T1_CFG); - - return; + hpet_t1_cmp = cnt; } /* diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 03674daabc6..a17930747f2 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -18,6 +18,7 @@ #include <linux/time.h> #include <asm/platform.h> #include <asm/timex.h> +#include <asm/param.h> /* HZ */ #define _F(r,f,a,b) \ r __platform_##f a b; \ diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 2659efdd4e9..14460743de0 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -45,7 +45,7 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } -int sys_ptrace(long request, long pid, long addr, long data) +long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret = -EPERM; diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 8e423d1335c..cb6e38ed2b1 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -29,9 +29,6 @@ extern volatile unsigned long wall_jiffies; -u64 jiffies_64 = INITIAL_JIFFIES; -EXPORT_SYMBOL(jiffies_64); - spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; EXPORT_SYMBOL(rtc_lock); diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c index 2b850e5860a..e26f007a141 100644 --- a/drivers/acorn/char/pcf8583.c +++ b/drivers/acorn/char/pcf8583.c @@ -9,6 +9,7 @@ * * Driver for PCF8583 RTC & RAM chip */ +#include <linux/module.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/string.h> @@ -32,7 +33,8 @@ static struct i2c_client_address_data addr_data = { .forces = forces, }; -#define DAT(x) ((unsigned int)(x->dev.driver_data)) +#define set_ctrl(x, v) i2c_set_clientdata(x, (void *)(unsigned int)(v)) +#define get_ctrl(x) ((unsigned int)i2c_get_clientdata(x)) static int pcf8583_attach(struct i2c_adapter *adap, int addr, int kind) @@ -40,8 +42,17 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, int kind) struct i2c_client *c; unsigned char buf[1], ad[1] = { 0 }; struct i2c_msg msgs[2] = { - { addr, 0, 1, ad }, - { addr, I2C_M_RD, 1, buf } + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = ad, + }, { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } }; c = kmalloc(sizeof(*c), GFP_KERNEL); @@ -54,7 +65,7 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, int kind) c->driver = &pcf8583_driver; if (i2c_transfer(c->adapter, msgs, 2) == 2) - DAT(c) = buf[0]; + set_ctrl(c, buf[0]); return i2c_attach_client(c); } @@ -78,8 +89,17 @@ pcf8583_get_datetime(struct i2c_client *client, struct rtc_tm *dt) { unsigned char buf[8], addr[1] = { 1 }; struct i2c_msg msgs[2] = { - { client->addr, 0, 1, addr }, - { client->addr, I2C_M_RD, 6, buf } + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 6, + .buf = buf, + } }; int ret = -EIO; @@ -113,7 +133,7 @@ pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) int ret, len = 6; buf[0] = 0; - buf[1] = DAT(client) | 0x80; + buf[1] = get_ctrl(client) | 0x80; buf[2] = BIN_TO_BCD(dt->cs); buf[3] = BIN_TO_BCD(dt->secs); buf[4] = BIN_TO_BCD(dt->mins); @@ -129,7 +149,7 @@ pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) if (ret == len) ret = 0; - buf[1] = DAT(client); + buf[1] = get_ctrl(client); i2c_master_send(client, (char *)buf, 2); return ret; @@ -138,7 +158,7 @@ pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl) { - *ctrl = DAT(client); + *ctrl = get_ctrl(client); return 0; } @@ -149,7 +169,7 @@ pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl) buf[0] = 0; buf[1] = *ctrl; - DAT(client) = *ctrl; + set_ctrl(client, *ctrl); return i2c_master_send(client, (char *)buf, 2); } @@ -159,15 +179,23 @@ pcf8583_read_mem(struct i2c_client *client, struct mem *mem) { unsigned char addr[1]; struct i2c_msg msgs[2] = { - { client->addr, 0, 1, addr }, - { client->addr, I2C_M_RD, 0, mem->data } + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = mem->nr, + .buf = mem->data, + } }; if (mem->loc < 8) return -EINVAL; addr[0] = mem->loc; - msgs[1].len = mem->nr; return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; } @@ -177,15 +205,23 @@ pcf8583_write_mem(struct i2c_client *client, struct mem *mem) { unsigned char addr[1]; struct i2c_msg msgs[2] = { - { client->addr, 0, 1, addr }, - { client->addr, 0, 0, mem->data } + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_NOSTART, + .len = mem->nr, + .buf = mem->data, + } }; if (mem->loc < 8) return -EINVAL; addr[0] = mem->loc; - msgs[1].len = mem->nr; return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; } @@ -234,4 +270,14 @@ static __init int pcf8583_init(void) return i2c_add_driver(&pcf8583_driver); } -__initcall(pcf8583_init); +static __exit void pcf8583_exit(void) +{ + i2c_del_driver(&pcf8583_driver); +} + +module_init(pcf8583_init); +module_exit(pcf8583_exit); + +MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("PCF8583 I2C RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 26a3a401611..161db4acfb9 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -37,6 +37,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/moduleparam.h> +#include <linux/sched.h> /* need_resched() */ #include <asm/io.h> #include <asm/uaccess.h> diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index aee50b45326..930427fc0c4 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -158,7 +158,15 @@ int acpi_suspend(u32 acpi_state) return -EINVAL; } +static int acpi_pm_state_valid(suspend_state_t pm_state) +{ + u32 acpi_state = acpi_suspend_states[pm_state]; + + return sleep_states[acpi_state]; +} + static struct pm_ops acpi_pm_ops = { + .valid = acpi_pm_state_valid, .prepare = acpi_pm_prepare, .enter = acpi_pm_enter, .finish = acpi_pm_finish, diff --git a/drivers/base/class.c b/drivers/base/class.c index c3e569730af..db65fd0babe 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -17,6 +17,7 @@ #include <linux/string.h> #include <linux/kdev_t.h> #include <linux/err.h> +#include <linux/slab.h> #include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 081c927b1ed..a95844790f7 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -16,6 +16,8 @@ struct sysdev_class cpu_sysdev_class = { }; EXPORT_SYMBOL(cpu_sysdev_class); +static struct sys_device *cpu_sys_devices[NR_CPUS]; + #ifdef CONFIG_HOTPLUG_CPU int __attribute__((weak)) smp_prepare_cpu (int cpu) { @@ -64,6 +66,7 @@ static void __devinit register_cpu_control(struct cpu *cpu) } void unregister_cpu(struct cpu *cpu, struct node *root) { + int logical_cpu = cpu->sysdev.id; if (root) sysfs_remove_link(&root->sysdev.kobj, @@ -71,7 +74,7 @@ void unregister_cpu(struct cpu *cpu, struct node *root) sysdev_remove_file(&cpu->sysdev, &attr_online); sysdev_unregister(&cpu->sysdev); - + cpu_sys_devices[logical_cpu] = NULL; return; } #else /* ... !CONFIG_HOTPLUG_CPU */ @@ -103,10 +106,19 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) kobject_name(&cpu->sysdev.kobj)); if (!error && !cpu->no_control) register_cpu_control(cpu); + if (!error) + cpu_sys_devices[num] = &cpu->sysdev; return error; } - +struct sys_device *get_cpu_sysdev(int cpu) +{ + if (cpu < NR_CPUS) + return cpu_sys_devices[cpu]; + else + return NULL; +} +EXPORT_SYMBOL_GPL(get_cpu_sysdev); int __init cpu_dev_init(void) { diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 4acb2c5733c..98f6c02d679 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -62,14 +62,16 @@ firmware_timeout_show(struct class *class, char *buf) } /** - * firmware_timeout_store: - * Description: + * firmware_timeout_store - set number of seconds to wait for firmware + * @class: device class pointer + * @buf: buffer to scan for timeout value + * @count: number of bytes in @buf + * * Sets the number of seconds to wait for the firmware. Once - * this expires an error will be return to the driver and no + * this expires an error will be returned to the driver and no * firmware will be provided. * - * Note: zero means 'wait for ever' - * + * Note: zero means 'wait forever'. **/ static ssize_t firmware_timeout_store(struct class *class, const char *buf, size_t count) @@ -123,12 +125,15 @@ firmware_loading_show(struct class_device *class_dev, char *buf) } /** - * firmware_loading_store: - loading control file - * Description: + * firmware_loading_store - set value in the 'loading' control file + * @class_dev: class_device pointer + * @buf: buffer to scan for loading control value + * @count: number of bytes in @buf + * * The relevant values are: * * 1: Start a load, discarding any previous partial load. - * 0: Conclude the load and handle the data to the driver code. + * 0: Conclude the load and hand the data to the driver code. * -1: Conclude the load with an error and discard any written data. **/ static ssize_t @@ -201,6 +206,7 @@ out: up(&fw_lock); return ret_count; } + static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) { @@ -227,11 +233,13 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) } /** - * firmware_data_write: + * firmware_data_write - write method for firmware + * @kobj: kobject for the class_device + * @buffer: buffer being written + * @offset: buffer offset for write in total data store area + * @count: buffer size * - * Description: - * - * Data written to the 'data' attribute will be later handled to + * Data written to the 'data' attribute will be later handed to * the driver as a firmware image. **/ static ssize_t @@ -264,6 +272,7 @@ out: up(&fw_lock); return retval; } + static struct bin_attribute firmware_attr_data_tmpl = { .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, .size = 0, @@ -448,13 +457,16 @@ out: /** * request_firmware: - request firmware to hotplug and wait for it - * Description: - * @firmware will be used to return a firmware image by the name + * @firmware_p: pointer to firmware image + * @name: name of firmware file + * @device: device for which firmware is being loaded + * + * @firmware_p will be used to return a firmware image by the name * of @name for device @device. * * Should be called from user context where sleeping is allowed. * - * @name will be use as $FIRMWARE in the hotplug environment and + * @name will be used as $FIRMWARE in the hotplug environment and * should be distinctive enough not to be confused with any other * firmware image for this or any other device. **/ @@ -468,6 +480,7 @@ request_firmware(const struct firmware **firmware_p, const char *name, /** * release_firmware: - release the resource associated with a firmware image + * @fw: firmware resource to release **/ void release_firmware(const struct firmware *fw) @@ -480,8 +493,10 @@ release_firmware(const struct firmware *fw) /** * register_firmware: - provide a firmware image for later usage + * @name: name of firmware image file + * @data: buffer pointer for the firmware image + * @size: size of the data buffer area * - * Description: * Make sure that @data will be available by requesting firmware @name. * * Note: This will not be possible until some kind of persistence @@ -526,21 +541,19 @@ request_firmware_work_func(void *arg) } /** - * request_firmware_nowait: + * request_firmware_nowait: asynchronous version of request_firmware + * @module: module requesting the firmware + * @hotplug: invokes hotplug event to copy the firmware image if this flag + * is non-zero else the firmware copy must be done manually. + * @name: name of firmware file + * @device: device for which firmware is being loaded + * @context: will be passed over to @cont, and + * @fw may be %NULL if firmware request fails. + * @cont: function will be called asynchronously when the firmware + * request is over. * - * Description: * Asynchronous variant of request_firmware() for contexts where * it is not possible to sleep. - * - * @hotplug invokes hotplug event to copy the firmware image if this flag - * is non-zero else the firmware copy must be done manually. - * - * @cont will be called asynchronously when the firmware request is over. - * - * @context will be passed over to @cont. - * - * @fw may be %NULL if firmware request fails. - * **/ int request_firmware_nowait( diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 75ce8711bca..08d9cc99c7d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -16,6 +16,7 @@ #include <linux/dma-mapping.h> #include <linux/bootmem.h> #include <linux/err.h> +#include <linux/slab.h> #include "base.h" diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 3431eb6004c..66ed8f2fece 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/pm.h> +#include <asm/semaphore.h> extern struct subsystem devices_subsys; diff --git a/drivers/block/Kconfig.iosched b/drivers/block/Kconfig.iosched index 6070a480600..5b90d2fa63b 100644 --- a/drivers/block/Kconfig.iosched +++ b/drivers/block/Kconfig.iosched @@ -38,4 +38,32 @@ config IOSCHED_CFQ among all processes in the system. It should provide a fair working environment, suitable for desktop systems. +choice + prompt "Default I/O scheduler" + default DEFAULT_AS + help + Select the I/O scheduler which will be used by default for all + block devices. + + config DEFAULT_AS + bool "Anticipatory" if IOSCHED_AS + + config DEFAULT_DEADLINE + bool "Deadline" if IOSCHED_DEADLINE + + config DEFAULT_CFQ + bool "CFQ" if IOSCHED_CFQ + + config DEFAULT_NOOP + bool "No-op" + +endchoice + +config DEFAULT_IOSCHED + string + default "anticipatory" if DEFAULT_AS + default "deadline" if DEFAULT_DEADLINE + default "cfq" if DEFAULT_CFQ + default "noop" if DEFAULT_NOOP + endmenu diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 56417223481..c6744ff3829 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -1973,8 +1973,8 @@ static int __init as_init(void) static void __exit as_exit(void) { - kmem_cache_destroy(arq_pool); elv_unregister(&iosched_as); + kmem_cache_destroy(arq_pool); } module_init(as_init); diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index e183a3ef783..ec27976a57d 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -28,13 +28,17 @@ through the array controller. Note in particular, neither physical nor logical disks are presented through the scsi layer. */ +#include <linux/timer.h> +#include <linux/completion.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include <asm/atomic.h> + #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> -#include <asm/atomic.h> -#include <linux/timer.h> -#include <linux/completion.h> #include "cciss_scsi.h" diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index 94690e4d41e..5281f8e7051 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c @@ -2418,28 +2418,8 @@ static int __init cfq_init(void) static void __exit cfq_exit(void) { - struct task_struct *g, *p; - unsigned long flags; - - read_lock_irqsave(&tasklist_lock, flags); - - /* - * iterate each process in the system, removing our io_context - */ - do_each_thread(g, p) { - struct io_context *ioc = p->io_context; - - if (ioc && ioc->cic) { - ioc->cic->exit(ioc->cic); - cfq_free_io_context(ioc->cic); - ioc->cic = NULL; - } - } while_each_thread(g, p); - - read_unlock_irqrestore(&tasklist_lock, flags); - - cfq_slab_kill(); elv_unregister(&iosched_cfq); + cfq_slab_kill(); } module_init(cfq_init); diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 55621d5c577..36f1057084b 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c @@ -147,24 +147,17 @@ static void elevator_setup_default(void) struct elevator_type *e; /* - * check if default is set and exists + * If default has not been set, use the compiled-in selection. */ - if (chosen_elevator[0] && (e = elevator_get(chosen_elevator))) { - elevator_put(e); - return; - } + if (!chosen_elevator[0]) + strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); -#if defined(CONFIG_IOSCHED_AS) - strcpy(chosen_elevator, "anticipatory"); -#elif defined(CONFIG_IOSCHED_DEADLINE) - strcpy(chosen_elevator, "deadline"); -#elif defined(CONFIG_IOSCHED_CFQ) - strcpy(chosen_elevator, "cfq"); -#elif defined(CONFIG_IOSCHED_NOOP) - strcpy(chosen_elevator, "noop"); -#else -#error "You must build at least 1 IO scheduler into the kernel" -#endif + /* + * If the given scheduler is not available, fall back to no-op. + */ + if (!(e = elevator_find(chosen_elevator))) + strcpy(chosen_elevator, "noop"); + elevator_put(e); } static int __init elevator_setup(char *str) @@ -642,6 +635,27 @@ EXPORT_SYMBOL_GPL(elv_register); void elv_unregister(struct elevator_type *e) { + struct task_struct *g, *p; + + /* + * Iterate every thread in the process to remove the io contexts. + */ + read_lock(&tasklist_lock); + do_each_thread(g, p) { + struct io_context *ioc = p->io_context; + if (ioc && ioc->cic) { + ioc->cic->exit(ioc->cic); + ioc->cic->dtor(ioc->cic); + ioc->cic = NULL; + } + if (ioc && ioc->aic) { + ioc->aic->exit(ioc->aic); + ioc->aic->dtor(ioc->aic); + ioc->aic = NULL; + } + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + spin_lock_irq(&elv_list_lock); list_del_init(&e->list); spin_unlock_irq(&elv_list_lock); @@ -739,8 +753,10 @@ ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) return -EINVAL; } - if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) + if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { + elevator_put(e); return count; + } elevator_switch(q, e); return count; diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c index 1fef136c0e4..ce94aa11f6a 100644 --- a/drivers/block/paride/paride.c +++ b/drivers/block/paride/paride.c @@ -29,6 +29,7 @@ #include <linux/string.h> #include <linux/spinlock.h> #include <linux/wait.h> +#include <linux/sched.h> /* TASK_* */ #ifdef CONFIG_PARPORT_MODULE #define CONFIG_PARPORT diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 94af920465b..e9746af29b9 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -807,10 +807,6 @@ static int pf_next_buf(void) return 1; spin_lock_irqsave(&pf_spin_lock, saved_flags); pf_end_request(1); - if (pf_req) { - pf_count = pf_req->current_nr_sectors; - pf_buf = pf_req->buffer; - } spin_unlock_irqrestore(&pf_spin_lock, saved_flags); return 1; } diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 82f2d6d2eee..6f5df0fad70 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -162,6 +162,8 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; #include <linux/mtio.h> #include <linux/pg.h> #include <linux/device.h> +#include <linux/sched.h> /* current, TASK_* */ +#include <linux/jiffies.h> #include <asm/uaccess.h> diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 686c9557345..715ae5dc88f 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -146,6 +146,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; #include <linux/slab.h> #include <linux/mtio.h> #include <linux/device.h> +#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */ #include <asm/uaccess.h> diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index c29365d5b52..fdf4370db99 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -661,7 +661,7 @@ config HW_RANDOM config NVRAM tristate "/dev/nvram support" - depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM + depends on ATARI || X86 || ARM || GENERIC_NVRAM ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), @@ -985,7 +985,7 @@ config MAX_RAW_DEVS config HANGCHECK_TIMER tristate "Hangcheck timer" - depends on X86_64 || X86 || IA64 || PPC64 || ARCH_S390 + depends on X86 || IA64 || PPC64 || ARCH_S390 help The hangcheck-timer module detects when the system has gone out to lunch past a certain margin. It can reboot the system @@ -1001,5 +1001,17 @@ config MMTIMER source "drivers/char/tpm/Kconfig" +config TELCLOCK + tristate "Telecom clock driver for MPBL0010 ATCA SBC" + depends on EXPERIMENTAL + default n + help + The telecom clock device is specific to the MPBL0010 ATCA computer and + allows direct userspace access to the configuration of the telecom clock + configuration settings. This device is used for hardware synchronization + across the ATCA backplane fabric. Upon loading, the driver exports a + sysfs directory, /sys/devices/platform/telco_clock, with a number of + files for controlling the behavior of this hardware. + endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 08f69287ea3..4aeae687e88 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o obj-$(CONFIG_TANBAC_TB0219) += tb0219.o +obj-$(CONFIG_TELCLOCK) += tlclk.o obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_MWAVE) += mwave/ diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 7f8c1b53b75..486ed8a11b5 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -27,7 +27,7 @@ config AGP config AGP_ALI tristate "ALI chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 ---help--- This option gives you AGP support for the GLX component of XFree86 4.x on the following ALi chipsets. The supported chipsets @@ -45,7 +45,7 @@ config AGP_ALI config AGP_ATI tristate "ATI chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 ---help--- This option gives you AGP support for the GLX component of XFree86 4.x on the ATI RadeonIGP family of chipsets. @@ -55,7 +55,7 @@ config AGP_ATI config AGP_AMD tristate "AMD Irongate, 761, and 762 chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 help This option gives you AGP support for the GLX component of XFree86 4.x on AMD Irongate, 761, and 762 chipsets. @@ -91,7 +91,7 @@ config AGP_INTEL config AGP_NVIDIA tristate "NVIDIA nForce/nForce2 chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 help This option gives you AGP support for the GLX component of XFree86 4.x on the following NVIDIA chipsets. The supported chipsets @@ -99,7 +99,7 @@ config AGP_NVIDIA config AGP_SIS tristate "SiS chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 help This option gives you AGP support for the GLX component of XFree86 4.x on Silicon Integrated Systems [SiS] chipsets. @@ -111,14 +111,14 @@ config AGP_SIS config AGP_SWORKS tristate "Serverworks LE/HE chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 help Say Y here to support the Serverworks AGP card. See <http://www.serverworks.com/> for product descriptions and images. config AGP_VIA tristate "VIA chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 help This option gives you AGP support for the GLX component of XFree86 4.x on VIA MVP3/Apollo Pro chipsets. @@ -154,7 +154,7 @@ config AGP_UNINORTH config AGP_EFFICEON tristate "Transmeta Efficeon support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86_32 help This option gives you AGP support for the Transmeta Efficeon series processors with integrated northbridges. diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 9c9c9c2247c..b02fc226715 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -7,6 +7,7 @@ #include <linux/pci.h> #include <linux/init.h> #include <linux/agp_backend.h> +#include <asm/page.h> /* PAGE_SIZE */ #include "agp.h" #define ALI_AGPCTRL 0xb8 diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 0a7624a9b1c..0e6c3a31d34 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -13,6 +13,7 @@ #include <linux/pci.h> #include <linux/init.h> #include <linux/agp_backend.h> +#include <asm/page.h> /* PAGE_SIZE */ #include "agp.h" /* Will need to be increased if AMD64 ever goes >8-way. */ diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index e572ced9100..0b6e72642d6 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -6,6 +6,8 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <linux/agp_backend.h> #include <asm/agp.h> #include "agp.h" diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 94943298c03..a2d9e5e48bb 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -10,6 +10,8 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <linux/agp_backend.h> #include "agp.h" diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c index c9ac731504f..40083241804 100644 --- a/drivers/char/agp/isoch.c +++ b/drivers/char/agp/isoch.c @@ -6,6 +6,7 @@ #include <linux/pci.h> #include <linux/agp_backend.h> #include <linux/module.h> +#include <linux/slab.h> #include "agp.h" diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index a9fb12c20eb..71ea59a1dbe 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -5,6 +5,8 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <linux/agp_backend.h> #include "agp.h" diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index cf4c3648463..c7f818cd7b0 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -281,7 +281,7 @@ static char rcsid[] = * make sure "cyc" appears in all kernel messages; all soft interrupts * handled by same routine; recognize out-of-band reception; comment * out some diagnostic messages; leave RTS/CTS flow control to hardware; - * fix race condition in -Z buffer management; only -Y needs to explictly + * fix race condition in -Z buffer management; only -Y needs to explicitly * flush chars; tidy up some startup messages; * * Revision 1.36.4.18 1996/07/25 18:57:31 bentson diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 475cc5e555e..6d344976191 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -15,6 +15,8 @@ #include <linux/device.h> #include <linux/kdev_t.h> #include <linux/err.h> +#include <linux/slab.h> +#include <linux/string.h> #include "drm_core.h" #include "drmP.h" diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 407708a001e..b7a0e4d6b93 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -3113,6 +3113,7 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl); int __init init_PCI (void) { /* Begin init_PCI */ memset (&epca_driver, 0, sizeof (epca_driver)); + epca_driver.owner = THIS_MODULE; epca_driver.name = "epca"; epca_driver.id_table = epca_pci_tbl; epca_driver.probe = epca_init_one; diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index a54bc93353a..66e53dd450f 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c @@ -117,7 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse_reboot); __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks); #endif /* not MODULE */ -#if defined(CONFIG_X86) || defined(CONFIG_X86_64) +#if defined(CONFIG_X86) # define HAVE_MONOTONIC # define TIMER_FREQ 1000000000ULL #elif defined(CONFIG_ARCH_S390) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index c055bb630ff..3808d957261 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -49,7 +49,9 @@ #define HPET_USER_FREQ (64) #define HPET_DRIFT (500) -static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; +#define HPET_RANGE_SIZE 1024 /* from HPET spec */ + +static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; /* A lock for concurrent access by app and isr hpet activity. */ static DEFINE_SPINLOCK(hpet_lock); @@ -78,7 +80,7 @@ struct hpets { struct hpet __iomem *hp_hpet; unsigned long hp_hpet_phys; struct time_interpolator *hp_interpolator; - unsigned long hp_period; + unsigned long long hp_tick_freq; unsigned long hp_delta; unsigned int hp_ntimer; unsigned int hp_which; @@ -90,6 +92,7 @@ static struct hpets *hpets; #define HPET_OPEN 0x0001 #define HPET_IE 0x0002 /* interrupt enabled */ #define HPET_PERIODIC 0x0004 +#define HPET_SHARED_IRQ 0x0008 #if BITS_PER_LONG == 64 #define write_counter(V, MC) writeq(V, MC) @@ -120,6 +123,11 @@ static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs) unsigned long isr; devp = data; + isr = 1 << (devp - devp->hd_hpets->hp_dev); + + if ((devp->hd_flags & HPET_SHARED_IRQ) && + !(isr & readl(&devp->hd_hpet->hpet_isr))) + return IRQ_NONE; spin_lock(&hpet_lock); devp->hd_irqdata++; @@ -137,8 +145,8 @@ static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs) &devp->hd_timer->hpet_compare); } - isr = (1 << (devp - devp->hd_hpets->hp_dev)); - writeq(isr, &devp->hd_hpet->hpet_isr); + if (devp->hd_flags & HPET_SHARED_IRQ) + writel(isr, &devp->hd_hpet->hpet_isr); spin_unlock(&hpet_lock); spin_lock(&hpet_task_lock); @@ -276,7 +284,8 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma) if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot)) { - printk(KERN_ERR "remap_pfn_range failed in hpet.c\n"); + printk(KERN_ERR "%s: io_remap_pfn_range failed\n", + __FUNCTION__); return -EAGAIN; } @@ -364,7 +373,9 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) hpet = devp->hd_hpet; hpetp = devp->hd_hpets; - v = readq(&timer->hpet_config); + if (!devp->hd_ireqfreq) + return -EIO; + spin_lock_irq(&hpet_lock); if (devp->hd_flags & HPET_IE) { @@ -373,16 +384,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) } devp->hd_flags |= HPET_IE; + + if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK) + devp->hd_flags |= HPET_SHARED_IRQ; spin_unlock_irq(&hpet_lock); - t = readq(&timer->hpet_config); irq = devp->hd_hdwirq; if (irq) { - sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); + unsigned long irq_flags; - if (request_irq - (irq, hpet_interrupt, SA_INTERRUPT, devp->hd_name, (void *)devp)) { + sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); + irq_flags = devp->hd_flags & HPET_SHARED_IRQ + ? SA_SHIRQ : SA_INTERRUPT; + if (request_irq(irq, hpet_interrupt, irq_flags, + devp->hd_name, (void *)devp)) { printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); irq = 0; } @@ -416,20 +432,24 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); } - isr = (1 << (devp - hpets->hp_dev)); - writeq(isr, &hpet->hpet_isr); + if (devp->hd_flags & HPET_SHARED_IRQ) { + isr = 1 << (devp - devp->hd_hpets->hp_dev); + writel(isr, &hpet->hpet_isr); + } writeq(g, &timer->hpet_config); local_irq_restore(flags); return 0; } -static inline unsigned long hpet_time_div(unsigned long dis) +/* converts Hz to number of timer ticks */ +static inline unsigned long hpet_time_div(struct hpets *hpets, + unsigned long dis) { - unsigned long long m = 1000000000000000ULL; + unsigned long long m; + m = hpets->hp_tick_freq + (dis >> 1); do_div(m, dis); - return (unsigned long)m; } @@ -477,14 +497,21 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) { struct hpet_info info; - info.hi_ireqfreq = hpet_time_div(hpetp->hp_period * - devp->hd_ireqfreq); + if (devp->hd_ireqfreq) + info.hi_ireqfreq = + hpet_time_div(hpetp, devp->hd_ireqfreq); + else + info.hi_ireqfreq = 0; info.hi_flags = readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; - info.hi_hpet = devp->hd_hpets->hp_which; - info.hi_timer = devp - devp->hd_hpets->hp_dev; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - err = -EFAULT; + info.hi_hpet = hpetp->hp_which; + info.hi_timer = devp - hpetp->hp_dev; + if (kernel) + memcpy((void *)arg, &info, sizeof(info)); + else + if (copy_to_user((void __user *)arg, &info, + sizeof(info))) + err = -EFAULT; break; } case HPET_EPI: @@ -516,12 +543,12 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) break; } - if (arg & (arg - 1)) { + if (!arg) { err = -EINVAL; break; } - devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg); + devp->hd_ireqfreq = hpet_time_div(hpetp, arg); } return err; @@ -539,6 +566,17 @@ static struct file_operations hpet_fops = { .mmap = hpet_mmap, }; +static int hpet_is_known(struct hpet_data *hdp) +{ + struct hpets *hpetp; + + for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) + if (hpetp->hp_hpet_phys == hdp->hd_phys_address) + return 1; + + return 0; +} + EXPORT_SYMBOL(hpet_alloc); EXPORT_SYMBOL(hpet_register); EXPORT_SYMBOL(hpet_unregister); @@ -563,6 +601,8 @@ int hpet_register(struct hpet_task *tp, int periodic) return -EINVAL; } + tp->ht_opaque = NULL; + spin_lock_irq(&hpet_task_lock); spin_lock(&hpet_lock); @@ -702,15 +742,14 @@ static void hpet_register_interpolator(struct hpets *hpetp) #ifdef CONFIG_TIME_INTERPOLATION struct time_interpolator *ti; - ti = kmalloc(sizeof(*ti), GFP_KERNEL); + ti = kzalloc(sizeof(*ti), GFP_KERNEL); if (!ti) return; - memset(ti, 0, sizeof(*ti)); ti->source = TIME_SOURCE_MMIO64; ti->shift = 10; ti->addr = &hpetp->hp_hpet->hpet_mc; - ti->frequency = hpet_time_div(hpets->hp_period); + ti->frequency = hpetp->hp_tick_freq; ti->drift = HPET_DRIFT; ti->mask = -1; @@ -743,11 +782,11 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) if (!timer) return 0; - hpet = hpets->hp_hpet; + hpet = hpetp->hp_hpet; t = read_counter(&timer->hpet_compare); i = 0; - count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE); + count = hpet_time_div(hpetp, TICK_CALIBRATE); local_irq_save(flags); @@ -771,28 +810,29 @@ int hpet_alloc(struct hpet_data *hdp) struct hpets *hpetp; size_t siz; struct hpet __iomem *hpet; - static struct hpets *last = (struct hpets *)0; - unsigned long ns; + static struct hpets *last = NULL; + unsigned long period; + unsigned long long temp; /* * hpet_alloc can be called by platform dependent code. - * if platform dependent code has allocated the hpet - * ACPI also reports hpet, then we catch it here. + * If platform dependent code has allocated the hpet that + * ACPI has also reported, then we catch it here. */ - for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - if (hpetp->hp_hpet == hdp->hd_address) - return 0; + if (hpet_is_known(hdp)) { + printk(KERN_DEBUG "%s: duplicate HPET ignored\n", + __FUNCTION__); + return 0; + } siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * sizeof(struct hpet_dev)); - hpetp = kmalloc(siz, GFP_KERNEL); + hpetp = kzalloc(siz, GFP_KERNEL); if (!hpetp) return -ENOMEM; - memset(hpetp, 0, siz); - hpetp->hp_which = hpet_nhpet++; hpetp->hp_hpet = hdp->hd_address; hpetp->hp_hpet_phys = hdp->hd_phys_address; @@ -822,21 +862,23 @@ int hpet_alloc(struct hpet_data *hdp) last = hpetp; - hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> - HPET_COUNTER_CLK_PERIOD_SHIFT; + period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> + HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */ + temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */ + temp += period >> 1; /* round */ + do_div(temp, period); + hpetp->hp_tick_freq = temp; /* ticks per second */ - printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", - hpetp->hp_which, hdp->hd_phys_address, + printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s", + hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address, hpetp->hp_ntimer > 1 ? "s" : ""); for (i = 0; i < hpetp->hp_ntimer; i++) printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); printk("\n"); - ns = hpetp->hp_period; /* femptoseconds, 10^-15 */ - ns /= 1000000; /* convert to nanoseconds, 10^-9 */ - printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", - hpetp->hp_which, ns, hpetp->hp_ntimer, - cap & HPET_COUNTER_SIZE_MASK ? 64 : 32); + printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", + hpetp->hp_which, hpetp->hp_ntimer, + cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); mcfg = readq(&hpet->hpet_config); if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { @@ -845,13 +887,10 @@ int hpet_alloc(struct hpet_data *hdp) writeq(mcfg, &hpet->hpet_config); } - for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; - i++, hpet_ntimer++, devp++) { - unsigned long v; + for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) { struct hpet_timer __iomem *timer; timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; - v = readq(&timer->hpet_config); devp->hd_hpets = hpetp; devp->hd_hpet = hpet; @@ -880,7 +919,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) struct hpet_data *hdp; acpi_status status; struct acpi_resource_address64 addr; - struct hpets *hpetp; hdp = data; @@ -893,9 +931,29 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) hdp->hd_phys_address = addr.min_address_range; hdp->hd_address = ioremap(addr.min_address_range, size); - for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - if (hpetp->hp_hpet == hdp->hd_address) - return -EBUSY; + if (hpet_is_known(hdp)) { + printk(KERN_DEBUG "%s: 0x%lx is busy\n", + __FUNCTION__, hdp->hd_phys_address); + iounmap(hdp->hd_address); + return -EBUSY; + } + } else if (res->id == ACPI_RSTYPE_FIXED_MEM32) { + struct acpi_resource_fixed_mem32 *fixmem32; + + fixmem32 = &res->data.fixed_memory32; + if (!fixmem32) + return -EINVAL; + + hdp->hd_phys_address = fixmem32->range_base_address; + hdp->hd_address = ioremap(fixmem32->range_base_address, + HPET_RANGE_SIZE); + + if (hpet_is_known(hdp)) { + printk(KERN_DEBUG "%s: 0x%lx is busy\n", + __FUNCTION__, hdp->hd_phys_address); + iounmap(hdp->hd_address); + return -EBUSY; + } } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { struct acpi_resource_ext_irq *irqp; int i; diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c index 613aed9e184..d1fe05e8388 100644 --- a/drivers/char/mwave/3780i.c +++ b/drivers/char/mwave/3780i.c @@ -53,6 +53,8 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/bitops.h> +#include <linux/sched.h> /* cond_resched() */ + #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 5b1d3680c8a..928b850cc67 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -256,7 +256,6 @@ static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, static int sReadAiopID(ByteIO_t io); static int sReadAiopNumChan(WordIO_t io); -#ifdef MODULE MODULE_AUTHOR("Theodore Ts'o"); MODULE_DESCRIPTION("Comtrol RocketPort driver"); module_param(board1, ulong, 0); @@ -288,17 +287,14 @@ MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc1 module_param_array(pc104_4, ulong, NULL, 0); MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,..."); -int rp_init(void); +static int rp_init(void); static void rp_cleanup_module(void); module_init(rp_init); module_exit(rp_cleanup_module); -#endif -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); -#endif /*************************************************************************/ /* Module code starts here */ @@ -2378,7 +2374,7 @@ static struct tty_operations rocket_ops = { /* * The module "startup" routine; it's run when the module is loaded. */ -int __init rp_init(void) +static int __init rp_init(void) { int retval, pci_boards_found, isa_boards_found, i; @@ -2502,7 +2498,6 @@ int __init rp_init(void) return 0; } -#ifdef MODULE static void rp_cleanup_module(void) { @@ -2530,7 +2525,6 @@ static void rp_cleanup_module(void) if (controller) release_region(controller, 4); } -#endif /*************************************************************************** Function: sInitController diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 6b4e9d155f5..dda30e42ec7 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -790,7 +790,7 @@ static int __init a2232board_init(void) } - printk("Total: %d A2232 boards initialized.\n.", nr_a2232); /* Some status report if no card was found */ + printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */ a2232_init_portstructs(); diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 50e0b612a8a..352547eabf7 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -38,19 +38,19 @@ * * Revision 1.0: April 1st 1997. * Initial release for alpha testing. - * Revision 1.1: April 14th 1997. - * Incorporated Richard Hudsons suggestions, + * Revision 1.1: April 14th 1997. + * Incorporated Richard Hudsons suggestions, * removed some debugging printk's. * Revision 1.2: April 15th 1997. * Ported to 2.1.x kernels. - * Revision 1.3: April 17th 1997 - * Backported to 2.0. (Compatibility macros). + * Revision 1.3: April 17th 1997 + * Backported to 2.0. (Compatibility macros). * Revision 1.4: April 18th 1997 - * Fixed DTR/RTS bug that caused the card to indicate - * "don't send data" to a modem after the password prompt. + * Fixed DTR/RTS bug that caused the card to indicate + * "don't send data" to a modem after the password prompt. * Fixed bug for premature (fake) interrupts. * Revision 1.5: April 19th 1997 - * fixed a minor typo in the header file, cleanup a little. + * fixed a minor typo in the header file, cleanup a little. * performance warnings are now MAXed at once per minute. * Revision 1.6: May 23 1997 * Changed the specialix=... format to include interrupt. @@ -60,10 +60,10 @@ * port to linux-2.1.43 kernel. * Revision 1.9: Oct 9 1998 * Added stuff for the IO8+/PCI version. - * Revision 1.10: Oct 22 1999 / Jan 21 2000. - * Added stuff for setserial. + * Revision 1.10: Oct 22 1999 / Jan 21 2000. + * Added stuff for setserial. * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr) - * + * */ #define VERSION "1.11" @@ -154,7 +154,7 @@ static int sx_poll = HZ; -/* +/* * The following defines are mostly for testing purposes. But if you need * some nice reporting in your syslog, you can define them also. */ @@ -188,7 +188,7 @@ static DECLARE_MUTEX(tmp_buf_sem); static unsigned long baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 0, + 9600, 19200, 38400, 57600, 115200, 0, }; static struct specialix_board sx_board[SX_NBOARD] = { @@ -216,7 +216,7 @@ static inline int sx_paranoia_check(struct specialix_port const * port, KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; static const char *badinfo = KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; - + if (!port) { printk(badinfo, name, routine); return 1; @@ -231,9 +231,9 @@ static inline int sx_paranoia_check(struct specialix_port const * port, /* - * + * * Service functions for specialix IO8+ driver. - * + * */ /* Get board number from pointer */ @@ -246,7 +246,7 @@ static inline int board_No (struct specialix_board * bp) /* Get port number from pointer */ static inline int port_No (struct specialix_port const * port) { - return SX_PORT(port - sx_port); + return SX_PORT(port - sx_port); } @@ -309,7 +309,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) return; udelay (1); } - + printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); } @@ -329,7 +329,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) return; udelay (1); } - + printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); } @@ -338,34 +338,28 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) * specialix IO8+ IO range functions. */ -static inline int sx_check_io_range(struct specialix_board * bp) +static inline int sx_request_io_range(struct specialix_board * bp) { - return check_region (bp->base, SX_IO_SPACE); -} - - -static inline void sx_request_io_range(struct specialix_board * bp) -{ - request_region(bp->base, - bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE, - "specialix IO8+" ); + return request_region(bp->base, + bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, + "specialix IO8+") == NULL; } static inline void sx_release_io_range(struct specialix_board * bp) { - release_region(bp->base, + release_region(bp->base, bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); } - + /* Must be called with enabled interrupts */ -/* Ugly. Very ugly. Don't use this for anything else than initialization +/* Ugly. Very ugly. Don't use this for anything else than initialization code */ static inline void sx_long_delay(unsigned long delay) { unsigned long i; - + for (i = jiffies + delay; time_after(i, jiffies); ) ; } @@ -378,7 +372,7 @@ static int sx_set_irq ( struct specialix_board *bp) int i; unsigned long flags; - if (bp->flags & SX_BOARD_IS_PCI) + if (bp->flags & SX_BOARD_IS_PCI) return 1; switch (bp->irq) { /* In the same order as in the docs... */ @@ -420,7 +414,7 @@ static int sx_init_CD186x(struct specialix_board * bp) sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ /* Set RegAckEn */ sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); - + /* Setting up prescaler. We need 4 ticks per 1 ms */ scaler = SX_OSCFREQ/SPECIALIX_TPS; @@ -448,7 +442,7 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit) spin_lock_irqsave(&bp->lock, flags); for (i=0, t=0;i<8;i++) { sx_out_off (bp, CD186x_CAR, i); - if (sx_in_off (bp, reg) & bit) + if (sx_in_off (bp, reg) & bit) t |= 1 << i; } spin_unlock_irqrestore(&bp->lock, flags); @@ -472,7 +466,7 @@ void missed_irq (unsigned long data) spin_unlock_irqrestore(&bp->lock, flags); if (irq) { printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); - sx_interrupt (((struct specialix_board *)data)->irq, + sx_interrupt (((struct specialix_board *)data)->irq, (void*)data, NULL); } missed_irq_timer.expires = jiffies + sx_poll; @@ -495,7 +489,7 @@ static int sx_probe(struct specialix_board *bp) func_enter(); - if (sx_check_io_range(bp)) { + if (sx_request_io_range(bp)) { func_exit(); return 1; } @@ -509,15 +503,16 @@ static int sx_probe(struct specialix_board *bp) short_pause (); val2 = sx_in_off(bp, CD186x_PPRL); - + if ((val1 != 0x5a) || (val2 != 0xa5)) { printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", board_No(bp), bp->base); + sx_release_io_range(bp); func_exit(); return 1; } - /* Check the DSR lines that Specialix uses as board + /* Check the DSR lines that Specialix uses as board identification */ val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); @@ -532,6 +527,7 @@ static int sx_probe(struct specialix_board *bp) if (val1 != val2) { printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", board_No(bp), val2, bp->base, val1); + sx_release_io_range(bp); func_exit(); return 1; } @@ -546,7 +542,7 @@ static int sx_probe(struct specialix_board *bp) sx_wait_CCR(bp); sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ - sx_long_delay(HZ/20); + sx_long_delay(HZ/20); irqs = probe_irq_off(irqs); dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); @@ -561,14 +557,15 @@ static int sx_probe(struct specialix_board *bp) } dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", - val1, val2, val3); - + val1, val2, val3); + } - + #if 0 if (irqs <= 0) { printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", board_No(bp), bp->base); + sx_release_io_range(bp); func_exit(); return 1; } @@ -579,19 +576,20 @@ static int sx_probe(struct specialix_board *bp) #endif /* Reset CD186x again */ if (!sx_init_CD186x(bp)) { + sx_release_io_range(bp); func_exit(); - return -EIO; + return 1; } sx_request_io_range(bp); bp->flags |= SX_BOARD_PRESENT; - + /* Chip revcode pkgtype GFRCR SRCR bit 7 CD180 rev B 0x81 0 CD180 rev C 0x82 0 CD1864 rev A 0x82 1 - CD1865 rev A 0x83 1 -- Do not use!!! Does not work. + CD1865 rev A 0x83 1 -- Do not use!!! Does not work. CD1865 rev B 0x84 1 -- Thanks to Gwen Wang, Cirrus Logic. */ @@ -623,8 +621,8 @@ static int sx_probe(struct specialix_board *bp) return 0; } -/* - * +/* + * * Interrupt processing routines. * */ @@ -657,7 +655,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp, return port; } } - printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", + printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", board_No(bp), what, channel); return NULL; } @@ -681,7 +679,7 @@ static inline void sx_receive_exc(struct specialix_board * bp) tty = port->tty; dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n", port, tty->flip.count, TTY_FLIPBUF_SIZE); - + status = sx_in(bp, CD186x_RCSR); dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); @@ -707,30 +705,30 @@ static inline void sx_receive_exc(struct specialix_board * bp) return; } if (status & RCSR_TOUT) { - printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", + printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", board_No(bp), port_No(port)); func_exit(); return; - + } else if (status & RCSR_BREAK) { dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", board_No(bp), port_No(port)); *tty->flip.flag_buf_ptr++ = TTY_BREAK; if (port->flags & ASYNC_SAK) do_SAK(tty); - - } else if (status & RCSR_PE) + + } else if (status & RCSR_PE) *tty->flip.flag_buf_ptr++ = TTY_PARITY; - - else if (status & RCSR_FE) + + else if (status & RCSR_FE) *tty->flip.flag_buf_ptr++ = TTY_FRAME; - + else if (status & RCSR_OE) *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - + else *tty->flip.flag_buf_ptr++ = 0; - + *tty->flip.char_buf_ptr++ = ch; tty->flip.count++; schedule_delayed_work(&tty->flip.work, 1); @@ -746,18 +744,18 @@ static inline void sx_receive(struct specialix_board * bp) unsigned char count; func_enter(); - + if (!(port = sx_get_port(bp, "Receive"))) { dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); func_exit(); return; } tty = port->tty; - + count = sx_in(bp, CD186x_RDCR); dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); port->hits[count > 8 ? 9 : count]++; - + while (count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n", @@ -787,7 +785,7 @@ static inline void sx_transmit(struct specialix_board * bp) } dprintk (SX_DEBUG_TX, "port: %p\n", port); tty = port->tty; - + if (port->IER & IER_TXEMPTY) { /* FIFO drained */ sx_out(bp, CD186x_CAR, port_No(port)); @@ -796,7 +794,7 @@ static inline void sx_transmit(struct specialix_board * bp) func_exit(); return; } - + if ((port->xmit_cnt <= 0 && !port->break_length) || tty->stopped || tty->hw_stopped) { sx_out(bp, CD186x_CAR, port_No(port)); @@ -805,7 +803,7 @@ static inline void sx_transmit(struct specialix_board * bp) func_exit(); return; } - + if (port->break_length) { if (port->break_length > 0) { if (port->COR2 & COR2_ETC) { @@ -831,7 +829,7 @@ static inline void sx_transmit(struct specialix_board * bp) func_exit(); return; } - + count = CD186x_NFIFO; do { sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]); @@ -839,7 +837,7 @@ static inline void sx_transmit(struct specialix_board * bp) if (--port->xmit_cnt <= 0) break; } while (--count > 0); - + if (port->xmit_cnt <= 0) { sx_out(bp, CD186x_CAR, port_No(port)); port->IER &= ~IER_TXRDY; @@ -862,9 +860,9 @@ static inline void sx_check_modem(struct specialix_board * bp) dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); if (!(port = sx_get_port(bp, "Modem"))) return; - + tty = port->tty; - + mcr = sx_in(bp, CD186x_MCR); printk ("mcr = %02x.\n", mcr); @@ -879,7 +877,7 @@ static inline void sx_check_modem(struct specialix_board * bp) schedule_work(&port->tqueue_hangup); } } - + #ifdef SPECIALIX_BRAIN_DAMAGED_CTS if (mcr & MCR_CTSCHG) { if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) { @@ -906,7 +904,7 @@ static inline void sx_check_modem(struct specialix_board * bp) sx_out(bp, CD186x_IER, port->IER); } #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */ - + /* Clear change bits */ sx_out(bp, CD186x_MCR, 0); } @@ -940,7 +938,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & (SRSR_RREQint | SRSR_TREQint | - SRSR_MREQint)))) { + SRSR_MREQint)))) { if (status & SRSR_RREQint) { ack = sx_in(bp, CD186x_RRAR); @@ -951,7 +949,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) else printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", board_No(bp), status, ack); - + } else if (status & SRSR_TREQint) { ack = sx_in(bp, CD186x_TRAR); @@ -963,13 +961,13 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) } else if (status & SRSR_MREQint) { ack = sx_in(bp, CD186x_MRAR); - if (ack == (SX_ID | GIVR_IT_MODEM)) + if (ack == (SX_ID | GIVR_IT_MODEM)) sx_check_modem(bp); else printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", board_No(bp), status, ack); - - } + + } sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ } @@ -1026,7 +1024,7 @@ static inline int sx_setup_board(struct specialix_board * bp) { int error; - if (bp->flags & SX_BOARD_ACTIVE) + if (bp->flags & SX_BOARD_ACTIVE) return 0; if (bp->flags & SX_BOARD_IS_PCI) @@ -1034,7 +1032,7 @@ static inline int sx_setup_board(struct specialix_board * bp) else error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp); - if (error) + if (error) return error; turn_ints_on (bp); @@ -1055,7 +1053,7 @@ static inline void sx_shutdown_board(struct specialix_board *bp) } bp->flags &= ~SX_BOARD_ACTIVE; - + dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", bp->irq, board_No (bp)); free_irq(bp->irq, bp); @@ -1068,7 +1066,7 @@ static inline void sx_shutdown_board(struct specialix_board *bp) /* - * Setting up port characteristics. + * Setting up port characteristics. * Must be called with disabled interrupts */ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) @@ -1103,10 +1101,10 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p spin_unlock_irqrestore(&bp->lock, flags); dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); baud = C_BAUD(tty); - + if (baud & CBAUDEX) { baud &= ~CBAUDEX; - if (baud < 1 || baud > 2) + if (baud < 1 || baud > 2) port->tty->termios->c_cflag &= ~CBAUDEX; else baud += 15; @@ -1117,8 +1115,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) baud += 2; } - - + + if (!baud_table[baud]) { /* Drop DTR & exit */ dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); @@ -1127,7 +1125,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_MSVR, port->MSVR ); spin_unlock_irqrestore(&bp->lock, flags); - } + } else dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); return; @@ -1137,9 +1135,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p port ->MSVR |= MSVR_DTR; } } - + /* - * Now we must calculate some speed depended things + * Now we must calculate some speed depended things */ /* Set baud rate for port */ @@ -1152,7 +1150,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + CD186x_TPC/2) / CD186x_TPC); - if ((tmp < 0x10) && time_before(again, jiffies)) { + if ((tmp < 0x10) && time_before(again, jiffies)) { again = jiffies + HZ * 60; /* Page 48 of version 2.0 of the CL-CD1865 databook */ if (tmp >= 12) { @@ -1164,27 +1162,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" "Warning: overstressing Cirrus chip. " "This might not work.\n" - "Read specialix.txt for more info.\n", + "Read specialix.txt for more info.\n", port_No (port), tmp); } } spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); - sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); - sx_out(bp, CD186x_RBPRL, tmp & 0xff); + sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); + sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); + sx_out(bp, CD186x_RBPRL, tmp & 0xff); sx_out(bp, CD186x_TBPRL, tmp & 0xff); spin_unlock_irqrestore(&bp->lock, flags); if (port->custom_divisor) { baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; baud = ( baud + 5 ) / 10; - } else + } else baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ /* Two timer ticks seems enough to wakeup something like SLIP driver */ - tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; + tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? SERIAL_XMIT_SIZE - 1 : tmp); - + /* Receiver timeout will be transmission time for 1.5 chars */ tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud; tmp = (tmp > 0xff) ? 0xff : tmp; @@ -1205,29 +1203,29 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p cor1 |= COR1_8BITS; break; } - - if (C_CSTOPB(tty)) + + if (C_CSTOPB(tty)) cor1 |= COR1_2SB; - + cor1 |= COR1_IGNORE; if (C_PARENB(tty)) { cor1 |= COR1_NORMPAR; - if (C_PARODD(tty)) + if (C_PARODD(tty)) cor1 |= COR1_ODDP; - if (I_INPCK(tty)) + if (I_INPCK(tty)) cor1 &= ~COR1_IGNORE; } /* Set marking of some errors */ port->mark_mask = RCSR_OE | RCSR_TOUT; - if (I_INPCK(tty)) + if (I_INPCK(tty)) port->mark_mask |= RCSR_FE | RCSR_PE; - if (I_BRKINT(tty) || I_PARMRK(tty)) + if (I_BRKINT(tty) || I_PARMRK(tty)) port->mark_mask |= RCSR_BREAK; - if (I_IGNPAR(tty)) + if (I_IGNPAR(tty)) port->mark_mask &= ~(RCSR_FE | RCSR_PE); if (I_IGNBRK(tty)) { port->mark_mask &= ~RCSR_BREAK; - if (I_IGNPAR(tty)) + if (I_IGNPAR(tty)) /* Real raw mode. Ignore all */ port->mark_mask &= ~RCSR_OE; } @@ -1241,7 +1239,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); spin_unlock_irqrestore(&bp->lock, flags); #else - port->COR2 |= COR2_CTSAE; + port->COR2 |= COR2_CTSAE; #endif } /* Enable Software Flow Control. FIXME: I'm not sure about this */ @@ -1264,11 +1262,11 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p mcor1 |= MCOR1_CDZD; mcor2 |= MCOR2_CDOD; } - - if (C_CREAD(tty)) + + if (C_CREAD(tty)) /* Enable receiver */ port->IER |= IER_RXD; - + /* Set input FIFO size (1-8 bytes) */ cor3 |= sx_rxfifo; /* Setting up CD186x channel registers */ @@ -1311,11 +1309,11 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port func_exit(); return 0; } - + if (!port->xmit_buf) { /* We may sleep in get_zeroed_page() */ unsigned long tmp; - + if (!(tmp = get_zeroed_page(GFP_KERNEL))) { func_exit(); return -ENOMEM; @@ -1328,10 +1326,10 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port } port->xmit_buf = (unsigned char *) tmp; } - + spin_lock_irqsave(&port->lock, flags); - if (port->tty) + if (port->tty) clear_bit(TTY_IO_ERROR, &port->tty->flags); port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; @@ -1340,7 +1338,7 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port spin_unlock_irqrestore(&port->lock, flags); - + func_exit(); return 0; } @@ -1352,14 +1350,14 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * struct tty_struct *tty; int i; unsigned long flags; - + func_enter(); if (!(port->flags & ASYNC_INITIALIZED)) { func_exit(); return; } - + if (sx_debug & SX_DEBUG_FIFO) { dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", board_No(bp), port_No(port), port->overrun); @@ -1394,13 +1392,13 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * if (tty) set_bit(TTY_IO_ERROR, &tty->flags); port->flags &= ~ASYNC_INITIALIZED; - - if (!bp->count) + + if (!bp->count) sx_shutdown_board(bp); func_exit(); } - + static int block_til_ready(struct tty_struct *tty, struct file * filp, struct specialix_port *port) { @@ -1427,7 +1425,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, return -ERESTARTSYS; } } - + /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. @@ -1477,7 +1475,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, if (port->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else - retval = -ERESTARTSYS; + retval = -ERESTARTSYS; break; } if (!(port->flags & ASYNC_CLOSING) && @@ -1506,7 +1504,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, port->flags |= ASYNC_NORMAL_ACTIVE; func_exit(); return 0; -} +} static int sx_open(struct tty_struct * tty, struct file * filp) @@ -1526,7 +1524,7 @@ static int sx_open(struct tty_struct * tty, struct file * filp) func_exit(); return -ENODEV; } - + bp = &sx_board[board]; port = sx_port + board * SX_NPORT + SX_PORT(tty->index); port->overrun = 0; @@ -1557,7 +1555,7 @@ static int sx_open(struct tty_struct * tty, struct file * filp) func_enter(); return error; } - + if ((error = block_til_ready(tty, filp, port))) { func_enter(); return error; @@ -1574,7 +1572,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) struct specialix_board *bp; unsigned long flags; unsigned long timeout; - + func_enter(); if (!port || sx_paranoia_check(port, tty->name, "close")) { func_exit(); @@ -1587,7 +1585,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) func_exit(); return; } - + bp = port_Board(port); if ((tty->count == 1) && (port->count != 1)) { printk(KERN_ERR "sx%d: sx_close: bad port count;" @@ -1607,7 +1605,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } port->flags |= ASYNC_CLOSING; /* - * Now we wait for the transmit buffer to clear; and we notify + * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; @@ -1681,7 +1679,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } -static int sx_write(struct tty_struct * tty, +static int sx_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; @@ -1694,7 +1692,7 @@ static int sx_write(struct tty_struct * tty, func_exit(); return 0; } - + bp = port_Board(port); if (!tty || !port->xmit_buf || !tmp_buf) { @@ -1824,7 +1822,7 @@ static int sx_chars_in_buffer(struct tty_struct *tty) struct specialix_port *port = (struct specialix_port *)tty->driver_data; func_enter(); - + if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) { func_exit(); return 0; @@ -1881,13 +1879,13 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) port_No(port), status, sx_in (bp, CD186x_CAR)); dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); if (SX_CRTSCTS(port->tty)) { - result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ + result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ | ((status & MSVR_DTR) ? TIOCM_RTS : 0) | ((status & MSVR_CD) ? TIOCM_CAR : 0) |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | ((status & MSVR_CTS) ? TIOCM_CTS : 0); } else { - result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ + result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | ((status & MSVR_CD) ? TIOCM_CAR : 0) |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ @@ -1955,7 +1953,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len { struct specialix_board *bp = port_Board(port); unsigned long flags; - + func_enter(); spin_lock_irqsave (&port->lock, flags); @@ -1996,8 +1994,8 @@ static inline int sx_set_serial_info(struct specialix_port * port, func_enter(); return -EFAULT; } - -#if 0 + +#if 0 if ((tmp.irq != bp->irq) || (tmp.port != bp->base) || (tmp.type != PORT_CIRRUS) || @@ -2008,12 +2006,12 @@ static inline int sx_set_serial_info(struct specialix_port * port, func_exit(); return -EINVAL; } -#endif +#endif change_speed = ((port->flags & ASYNC_SPD_MASK) != (tmp.flags & ASYNC_SPD_MASK)); change_speed |= (tmp.custom_divisor != port->custom_divisor); - + if (!capable(CAP_SYS_ADMIN)) { if ((tmp.close_delay != port->close_delay) || (tmp.closing_wait != port->closing_wait) || @@ -2045,7 +2043,7 @@ static inline int sx_get_serial_info(struct specialix_port * port, { struct serial_struct tmp; struct specialix_board *bp = port_Board(port); - + func_enter(); /* @@ -2074,7 +2072,7 @@ static inline int sx_get_serial_info(struct specialix_port * port, } -static int sx_ioctl(struct tty_struct * tty, struct file * filp, +static int sx_ioctl(struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; @@ -2087,7 +2085,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, func_exit(); return -ENODEV; } - + switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); @@ -2129,7 +2127,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, case TIOCGSERIAL: func_exit(); return sx_get_serial_info(port, argp); - case TIOCSSERIAL: + case TIOCSSERIAL: func_exit(); return sx_set_serial_info(port, argp); default: @@ -2153,16 +2151,16 @@ static void sx_throttle(struct tty_struct * tty) func_exit(); return; } - + bp = port_Board(port); - + /* Use DTR instead of RTS ! */ - if (SX_CRTSCTS (tty)) + if (SX_CRTSCTS (tty)) port->MSVR &= ~MSVR_DTR; else { /* Auch!!! I think the system shouldn't call this then. */ /* Or maybe we're supposed (allowed?) to do our side of hw - handshake anyway, even when hardware handshake is off. + handshake anyway, even when hardware handshake is off. When you see this in your logs, please report.... */ printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", port_No (port)); @@ -2193,14 +2191,14 @@ static void sx_unthrottle(struct tty_struct * tty) unsigned long flags; func_enter(); - + if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) { func_exit(); return; } - + bp = port_Board(port); - + spin_lock_irqsave(&port->lock, flags); /* XXXX Use DTR INSTEAD???? */ if (SX_CRTSCTS(tty)) { @@ -2234,14 +2232,14 @@ static void sx_stop(struct tty_struct * tty) unsigned long flags; func_enter(); - + if (sx_paranoia_check(port, tty->name, "sx_stop")) { func_exit(); return; } bp = port_Board(port); - + spin_lock_irqsave(&port->lock, flags); port->IER &= ~IER_TXRDY; spin_lock_irqsave(&bp->lock, flags); @@ -2261,14 +2259,14 @@ static void sx_start(struct tty_struct * tty) unsigned long flags; func_enter(); - + if (sx_paranoia_check(port, tty->name, "sx_start")) { func_exit(); return; } - + bp = port_Board(port); - + spin_lock_irqsave(&port->lock, flags); if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { port->IER |= IER_TXRDY; @@ -2290,13 +2288,13 @@ static void sx_start(struct tty_struct * tty) * * serial interrupt routine -> (workqueue) -> * do_sx_hangup() -> tty->hangup() -> sx_hangup() - * + * */ static void do_sx_hangup(void *private_) { struct specialix_port *port = (struct specialix_port *) private_; struct tty_struct *tty; - + func_enter(); tty = port->tty; @@ -2319,9 +2317,9 @@ static void sx_hangup(struct tty_struct * tty) func_exit(); return; } - + bp = port_Board(port); - + sx_shutdown_port(bp, port); spin_lock_irqsave(&port->lock, flags); port->event = 0; @@ -2346,10 +2344,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; struct specialix_board * bp; - + if (sx_paranoia_check(port, tty->name, "sx_set_termios")) return; - + if (tty->termios->c_cflag == old_termios->c_cflag && tty->termios->c_iflag == old_termios->c_iflag) return; @@ -2420,7 +2418,7 @@ static int sx_init_drivers(void) func_exit(); return 1; } - + if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) { printk(KERN_ERR "sx: Couldn't get free page.\n"); put_tty_driver(specialix_driver); @@ -2457,7 +2455,7 @@ static int sx_init_drivers(void) init_waitqueue_head(&sx_port[i].close_wait); spin_lock_init(&sx_port[i].lock); } - + func_exit(); return 0; } @@ -2472,8 +2470,8 @@ static void sx_release_drivers(void) func_exit(); } -/* - * This routine must be called by kernel at boot time +/* + * This routine must be called by kernel at boot time */ static int __init specialix_init(void) { @@ -2489,7 +2487,7 @@ static int __init specialix_init(void) #else printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); #endif - + for (i = 0; i < SX_NBOARD; i++) sx_board[i].lock = SPIN_LOCK_UNLOCKED; @@ -2498,7 +2496,7 @@ static int __init specialix_init(void) return -EIO; } - for (i = 0; i < SX_NBOARD; i++) + for (i = 0; i < SX_NBOARD; i++) if (sx_board[i].base && !sx_probe(&sx_board[i])) found++; @@ -2512,8 +2510,8 @@ static int __init specialix_init(void) i++; continue; } - pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_IO8, + pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, + PCI_DEVICE_ID_SPECIALIX_IO8, pdev); if (!pdev) break; @@ -2557,10 +2555,10 @@ module_param(sx_poll, int, 0); /* * You can setup up to 4 boards. * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter. - * You should specify the IRQs too in that case "irq=....,...". - * + * You should specify the IRQs too in that case "irq=....,...". + * * More than 4 boards in one computer is not possible, as the card can - * only use 4 different interrupts. + * only use 4 different interrupts. * */ static int __init specialix_init_module(void) @@ -2583,16 +2581,16 @@ static int __init specialix_init_module(void) return specialix_init(); } - + static void __exit specialix_exit_module(void) { int i; - + func_enter(); sx_release_drivers(); for (i = 0; i < SX_NBOARD; i++) - if (sx_board[i].flags & SX_BOARD_PRESENT) + if (sx_board[i].flags & SX_BOARD_PRESENT) sx_release_io_range(&sx_board[i]); #ifdef SPECIALIX_TIMER del_timer (&missed_irq_timer); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ea2d54be484..0133dc0e25d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -912,6 +912,7 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); MODULE_LICENSE("GPL"); static struct pci_driver synclink_pci_driver = { + .owner = THIS_MODULE, .name = "synclink", .id_table = synclink_pci_tbl, .probe = synclink_init_one, diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 6fb165cf8a6..f185724448b 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -500,6 +500,7 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl); MODULE_LICENSE("GPL"); static struct pci_driver synclinkmp_pci_driver = { + .owner = THIS_MODULE, .name = "synclinkmp", .id_table = synclinkmp_pci_tbl, .probe = synclinkmp_init_one, diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c new file mode 100644 index 00000000000..18cdd4361dc --- /dev/null +++ b/drivers/char/tlclk.c @@ -0,0 +1,896 @@ +/* + * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010 + * + * Copyright (C) 2005 Kontron Canada + * + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to <sebastien.bouchard@ca.kontron.com> and the current + * Maintainer <mark.gross@intel.com> + * + * Description : This is the TELECOM CLOCK module driver for the ATCA + * MPCBL0010 ATCA computer. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/kernel.h> /* printk() */ +#include <linux/fs.h> /* everything... */ +#include <linux/errno.h> /* error codes */ +#include <linux/delay.h> /* udelay */ +#include <linux/slab.h> +#include <linux/ioport.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/timer.h> +#include <linux/sysfs.h> +#include <linux/device.h> +#include <linux/miscdevice.h> +#include <asm/io.h> /* inb/outb */ +#include <asm/uaccess.h> + +MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>"); +MODULE_LICENSE("GPL"); + +/*Hardware Reset of the PLL */ +#define RESET_ON 0x00 +#define RESET_OFF 0x01 + +/* MODE SELECT */ +#define NORMAL_MODE 0x00 +#define HOLDOVER_MODE 0x10 +#define FREERUN_MODE 0x20 + +/* FILTER SELECT */ +#define FILTER_6HZ 0x04 +#define FILTER_12HZ 0x00 + +/* SELECT REFERENCE FREQUENCY */ +#define REF_CLK1_8kHz 0x00 +#define REF_CLK2_19_44MHz 0x02 + +/* Select primary or secondary redundant clock */ +#define PRIMARY_CLOCK 0x00 +#define SECONDARY_CLOCK 0x01 + +/* CLOCK TRANSMISSION DEFINE */ +#define CLK_8kHz 0xff +#define CLK_16_384MHz 0xfb + +#define CLK_1_544MHz 0x00 +#define CLK_2_048MHz 0x01 +#define CLK_4_096MHz 0x02 +#define CLK_6_312MHz 0x03 +#define CLK_8_192MHz 0x04 +#define CLK_19_440MHz 0x06 + +#define CLK_8_592MHz 0x08 +#define CLK_11_184MHz 0x09 +#define CLK_34_368MHz 0x0b +#define CLK_44_736MHz 0x0a + +/* RECEIVED REFERENCE */ +#define AMC_B1 0 +#define AMC_B2 1 + +/* HARDWARE SWITCHING DEFINE */ +#define HW_ENABLE 0x80 +#define HW_DISABLE 0x00 + +/* HARDWARE SWITCHING MODE DEFINE */ +#define PLL_HOLDOVER 0x40 +#define LOST_CLOCK 0x00 + +/* ALARMS DEFINE */ +#define UNLOCK_MASK 0x10 +#define HOLDOVER_MASK 0x20 +#define SEC_LOST_MASK 0x40 +#define PRI_LOST_MASK 0x80 + +/* INTERRUPT CAUSE DEFINE */ + +#define PRI_LOS_01_MASK 0x01 +#define PRI_LOS_10_MASK 0x02 + +#define SEC_LOS_01_MASK 0x04 +#define SEC_LOS_10_MASK 0x08 + +#define HOLDOVER_01_MASK 0x10 +#define HOLDOVER_10_MASK 0x20 + +#define UNLOCK_01_MASK 0x40 +#define UNLOCK_10_MASK 0x80 + +struct tlclk_alarms { + __u32 lost_clocks; + __u32 lost_primary_clock; + __u32 lost_secondary_clock; + __u32 primary_clock_back; + __u32 secondary_clock_back; + __u32 switchover_primary; + __u32 switchover_secondary; + __u32 pll_holdover; + __u32 pll_end_holdover; + __u32 pll_lost_sync; + __u32 pll_sync; +}; +/* Telecom clock I/O register definition */ +#define TLCLK_BASE 0xa08 +#define TLCLK_REG0 TLCLK_BASE +#define TLCLK_REG1 (TLCLK_BASE+1) +#define TLCLK_REG2 (TLCLK_BASE+2) +#define TLCLK_REG3 (TLCLK_BASE+3) +#define TLCLK_REG4 (TLCLK_BASE+4) +#define TLCLK_REG5 (TLCLK_BASE+5) +#define TLCLK_REG6 (TLCLK_BASE+6) +#define TLCLK_REG7 (TLCLK_BASE+7) + +#define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port) + +/* 0 = Dynamic allocation of the major device number */ +#define TLCLK_MAJOR 0 + +/* sysfs interface definition: +Upon loading the driver will create a sysfs directory under +/sys/devices/platform/telco_clock. + +This directory exports the following interfaces. There operation is +documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4. +alarms : +current_ref : +enable_clk3a_output : +enable_clk3b_output : +enable_clka0_output : +enable_clka1_output : +enable_clkb0_output : +enable_clkb1_output : +filter_select : +hardware_switching : +hardware_switching_mode : +interrupt_switch : +mode_select : +refalign : +reset : +select_amcb1_transmit_clock : +select_amcb2_transmit_clock : +select_redundant_clock : +select_ref_frequency : +test_mode : + +All sysfs interfaces are integers in hex format, i.e echo 99 > refalign +has the same effect as echo 0x99 > refalign. +*/ + +static unsigned int telclk_interrupt; + +static int int_events; /* Event that generate a interrupt */ +static int got_event; /* if events processing have been done */ + +static void switchover_timeout(unsigned long data); +static struct timer_list switchover_timer = + TIMER_INITIALIZER(switchover_timeout , 0, 0); + +static struct tlclk_alarms *alarm_events; + +static DEFINE_SPINLOCK(event_lock); + +static int tlclk_major = TLCLK_MAJOR; + +static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs); + +static DECLARE_WAIT_QUEUE_HEAD(wq); + +static int tlclk_open(struct inode *inode, struct file *filp) +{ + int result; + + /* Make sure there is no interrupt pending while + * initialising interrupt handler */ + inb(TLCLK_REG6); + + /* This device is wired through the FPGA IO space of the ATCA blade + * we can't share this IRQ */ + result = request_irq(telclk_interrupt, &tlclk_interrupt, + SA_INTERRUPT, "telco_clock", tlclk_interrupt); + if (result == -EBUSY) { + printk(KERN_ERR "telco_clock: Interrupt can't be reserved!\n"); + return -EBUSY; + } + inb(TLCLK_REG6); /* Clear interrupt events */ + + return 0; +} + +static int tlclk_release(struct inode *inode, struct file *filp) +{ + free_irq(telclk_interrupt, tlclk_interrupt); + + return 0; +} + +ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + if (count < sizeof(struct tlclk_alarms)) + return -EIO; + + wait_event_interruptible(wq, got_event); + if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) + return -EFAULT; + + memset(alarm_events, 0, sizeof(struct tlclk_alarms)); + got_event = 0; + + return sizeof(struct tlclk_alarms); +} + +ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + return 0; +} + +static struct file_operations tlclk_fops = { + .read = tlclk_read, + .write = tlclk_write, + .open = tlclk_open, + .release = tlclk_release, + +}; + +static struct miscdevice tlclk_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "telco_clock", + .fops = &tlclk_fops, +}; + +static ssize_t show_current_ref(struct device *d, + struct device_attribute *attr, char *buf) +{ + unsigned long ret_val; + unsigned long flags; + + spin_lock_irqsave(&event_lock, flags); + ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3); + spin_unlock_irqrestore(&event_lock, flags); + + return sprintf(buf, "0x%lX\n", ret_val); +} + +static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL); + + +static ssize_t show_interrupt_switch(struct device *d, + struct device_attribute *attr, char *buf) +{ + unsigned long ret_val; + unsigned long flags; + + spin_lock_irqsave(&event_lock, flags); + ret_val = inb(TLCLK_REG6); + spin_unlock_irqrestore(&event_lock, flags); + + return sprintf(buf, "0x%lX\n", ret_val); +} + +static DEVICE_ATTR(interrupt_switch, S_IRUGO, + show_interrupt_switch, NULL); + +static ssize_t show_alarms(struct device *d, + struct device_attribute *attr, char *buf) +{ + unsigned long ret_val; + unsigned long flags; + + spin_lock_irqsave(&event_lock, flags); + ret_val = (inb(TLCLK_REG2) & 0xf0); + spin_unlock_irqrestore(&event_lock, flags); + + return sprintf(buf, "0x%lX\n", ret_val); +} + +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + +static ssize_t store_enable_clk3b_output(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, ": tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL, + store_enable_clk3b_output); + +static ssize_t store_enable_clk3a_output(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL, + store_enable_clk3a_output); + +static ssize_t store_enable_clkb1_output(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL, + store_enable_clkb1_output); + + +static ssize_t store_enable_clka1_output(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL, + store_enable_clka1_output); + +static ssize_t store_enable_clkb0_output(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL, + store_enable_clkb0_output); + +static ssize_t store_enable_clka0_output(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG2, 0xfe, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL, + store_enable_clka0_output); + +static ssize_t store_test_mode(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG4, 0xfd, 2); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode); + +static ssize_t store_select_amcb2_transmit_clock(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long flags; + unsigned long tmp; + unsigned char val; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { + SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28); + SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); + } else if (val >= CLK_8_592MHz) { + SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38); + switch (val) { + case CLK_8_592MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); + break; + case CLK_11_184MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); + break; + case CLK_34_368MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); + break; + case CLK_44_736MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); + break; + } + } else + SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3); + + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL, + store_select_amcb2_transmit_clock); + +static ssize_t store_select_amcb1_transmit_clock(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { + SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5); + SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); + } else if (val >= CLK_8_592MHz) { + SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); + switch (val) { + case CLK_8_592MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); + break; + case CLK_11_184MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); + break; + case CLK_34_368MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); + break; + case CLK_44_736MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); + break; + } + } else + SET_PORT_BITS(TLCLK_REG3, 0xf8, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL, + store_select_amcb1_transmit_clock); + +static ssize_t store_select_redundant_clock(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG1, 0xfe, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL, + store_select_redundant_clock); + +static ssize_t store_select_ref_frequency(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG1, 0xfd, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL, + store_select_ref_frequency); + +static ssize_t store_filter_select(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG0, 0xfb, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select); + +static ssize_t store_hardware_switching_mode(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG0, 0xbf, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL, + store_hardware_switching_mode); + +static ssize_t store_hardware_switching(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG0, 0x7f, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL, + store_hardware_switching); + +static ssize_t store_refalign (struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG0, 0xf7, 0); + udelay(2); + SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08); + udelay(2); + SET_PORT_BITS(TLCLK_REG0, 0xf7, 0); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign); + +static ssize_t store_mode_select (struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG0, 0xcf, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select); + +static ssize_t store_reset (struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, "tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG4, 0xfd, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset); + +static struct attribute *tlclk_sysfs_entries[] = { + &dev_attr_current_ref.attr, + &dev_attr_interrupt_switch.attr, + &dev_attr_alarms.attr, + &dev_attr_enable_clk3a_output.attr, + &dev_attr_enable_clk3b_output.attr, + &dev_attr_enable_clkb1_output.attr, + &dev_attr_enable_clka1_output.attr, + &dev_attr_enable_clkb0_output.attr, + &dev_attr_enable_clka0_output.attr, + &dev_attr_test_mode.attr, + &dev_attr_select_amcb1_transmit_clock.attr, + &dev_attr_select_amcb2_transmit_clock.attr, + &dev_attr_select_redundant_clock.attr, + &dev_attr_select_ref_frequency.attr, + &dev_attr_filter_select.attr, + &dev_attr_hardware_switching_mode.attr, + &dev_attr_hardware_switching.attr, + &dev_attr_refalign.attr, + &dev_attr_mode_select.attr, + &dev_attr_reset.attr, + NULL +}; + +static struct attribute_group tlclk_attribute_group = { + .name = NULL, /* put in device directory */ + .attrs = tlclk_sysfs_entries, +}; + +static struct platform_device *tlclk_device; + +static int __init tlclk_init(void) +{ + int ret; + + ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops); + if (ret < 0) { + printk(KERN_ERR "telco_clock: can't get major! %d\n", tlclk_major); + return ret; + } + alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); + if (!alarm_events) + goto out1; + + /* Read telecom clock IRQ number (Set by BIOS) */ + if (!request_region(TLCLK_BASE, 8, "telco_clock")) { + printk(KERN_ERR "tlclk: request_region failed! 0x%X\n", + TLCLK_BASE); + ret = -EBUSY; + goto out2; + } + telclk_interrupt = (inb(TLCLK_REG7) & 0x0f); + + if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */ + printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw\n", + telclk_interrupt); + ret = -ENXIO; + goto out3; + } + + init_timer(&switchover_timer); + + ret = misc_register(&tlclk_miscdev); + if (ret < 0) { + printk(KERN_ERR " misc_register retruns %d\n", ret); + ret = -EBUSY; + goto out3; + } + + tlclk_device = platform_device_register_simple("telco_clock", + -1, NULL, 0); + if (!tlclk_device) { + printk(KERN_ERR " platform_device_register retruns 0x%X\n", + (unsigned int) tlclk_device); + ret = -EBUSY; + goto out4; + } + + ret = sysfs_create_group(&tlclk_device->dev.kobj, + &tlclk_attribute_group); + if (ret) { + printk(KERN_ERR "failed to create sysfs device attributes\n"); + sysfs_remove_group(&tlclk_device->dev.kobj, + &tlclk_attribute_group); + goto out5; + } + + return 0; +out5: + platform_device_unregister(tlclk_device); +out4: + misc_deregister(&tlclk_miscdev); +out3: + release_region(TLCLK_BASE, 8); +out2: + kfree(alarm_events); +out1: + unregister_chrdev(tlclk_major, "telco_clock"); + return ret; +} + +static void __exit tlclk_cleanup(void) +{ + sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group); + platform_device_unregister(tlclk_device); + misc_deregister(&tlclk_miscdev); + unregister_chrdev(tlclk_major, "telco_clock"); + + release_region(TLCLK_BASE, 8); + del_timer_sync(&switchover_timer); + kfree(alarm_events); + +} + +static void switchover_timeout(unsigned long data) +{ + if ((data & 1)) { + if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08)) + alarm_events->switchover_primary++; + } else { + if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08)) + alarm_events->switchover_secondary++; + } + + /* Alarm processing is done, wake up read task */ + del_timer(&switchover_timer); + got_event = 1; + wake_up(&wq); +} + +static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + + spin_lock_irqsave(&event_lock, flags); + /* Read and clear interrupt events */ + int_events = inb(TLCLK_REG6); + + /* Primary_Los changed from 0 to 1 ? */ + if (int_events & PRI_LOS_01_MASK) { + if (inb(TLCLK_REG2) & SEC_LOST_MASK) + alarm_events->lost_clocks++; + else + alarm_events->lost_primary_clock++; + } + + /* Primary_Los changed from 1 to 0 ? */ + if (int_events & PRI_LOS_10_MASK) { + alarm_events->primary_clock_back++; + SET_PORT_BITS(TLCLK_REG1, 0xFE, 1); + } + /* Secondary_Los changed from 0 to 1 ? */ + if (int_events & SEC_LOS_01_MASK) { + if (inb(TLCLK_REG2) & PRI_LOST_MASK) + alarm_events->lost_clocks++; + else + alarm_events->lost_secondary_clock++; + } + /* Secondary_Los changed from 1 to 0 ? */ + if (int_events & SEC_LOS_10_MASK) { + alarm_events->secondary_clock_back++; + SET_PORT_BITS(TLCLK_REG1, 0xFE, 0); + } + if (int_events & HOLDOVER_10_MASK) + alarm_events->pll_end_holdover++; + + if (int_events & UNLOCK_01_MASK) + alarm_events->pll_lost_sync++; + + if (int_events & UNLOCK_10_MASK) + alarm_events->pll_sync++; + + /* Holdover changed from 0 to 1 ? */ + if (int_events & HOLDOVER_01_MASK) { + alarm_events->pll_holdover++; + + /* TIMEOUT in ~10ms */ + switchover_timer.expires = jiffies + msecs_to_jiffies(10); + switchover_timer.data = inb(TLCLK_REG1); + add_timer(&switchover_timer); + } else { + got_event = 1; + wake_up(&wq); + } + spin_unlock_irqrestore(&event_lock, flags); + + return IRQ_HANDLED; +} + +module_init(tlclk_init); +module_exit(tlclk_cleanup); diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 049d128ae7f..303f1588046 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -64,7 +64,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, if (count == 0) return -ENODATA; if (count > bufsiz) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "invalid count value %x %zx \n", count, bufsiz); return -E2BIG; } @@ -72,21 +72,21 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, down(&chip->tpm_mutex); if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc); goto out; } stop = jiffies + 2 * 60 * HZ; do { - u8 status = inb(chip->vendor->base + 1); + u8 status = chip->vendor->status(chip); if ((status & chip->vendor->req_complete_mask) == chip->vendor->req_complete_val) { goto out_recv; } if ((status == chip->vendor->req_canceled)) { - dev_err(&chip->pci_dev->dev, "Operation Canceled\n"); + dev_err(chip->dev, "Operation Canceled\n"); rc = -ECANCELED; goto out; } @@ -97,14 +97,14 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, chip->vendor->cancel(chip); - dev_err(&chip->pci_dev->dev, "Operation Timed out\n"); + dev_err(chip->dev, "Operation Timed out\n"); rc = -ETIME; goto out; out_recv: rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz); if (rc < 0) - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); out: up(&chip->tpm_mutex); @@ -139,15 +139,14 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, __be32 index; char *str = buf; - struct tpm_chip *chip = - pci_get_drvdata(to_pci_dev(dev)); + struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; memcpy(data, cap_pcr, sizeof(cap_pcr)); if ((len = tpm_transmit(chip, data, sizeof(data))) < CAP_PCR_RESULT_SIZE) { - dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred " + dev_dbg(chip->dev, "A TPM error (%d) occurred " "attempting to determine the number of PCRS\n", be32_to_cpu(*((__be32 *) (data + 6)))); return 0; @@ -161,9 +160,10 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, memcpy(data + 10, &index, 4); if ((len = tpm_transmit(chip, data, sizeof(data))) < READ_PCR_RESULT_SIZE){ - dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred" + dev_dbg(chip->dev, "A TPM error (%d) occurred" " attempting to read PCR %d of %d\n", - be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs); + be32_to_cpu(*((__be32 *) (data + 6))), + i, num_pcrs); goto out; } str += sprintf(str, "PCR-%02d: ", i); @@ -191,21 +191,19 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, int i, rc; char *str = buf; - struct tpm_chip *chip = - pci_get_drvdata(to_pci_dev(dev)); + struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; - data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); + data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); if (!data) return -ENOMEM; memcpy(data, readpubek, sizeof(readpubek)); - memset(data + sizeof(readpubek), 0, 20); /* zero nonce */ if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < READ_PUBEK_RESULT_SIZE) { - dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred " + dev_dbg(chip->dev, "A TPM error (%d) occurred " "attempting to read the PUBEK\n", be32_to_cpu(*((__be32 *) (data + 6)))); rc = 0; @@ -245,7 +243,6 @@ out: kfree(data); return rc; } - EXPORT_SYMBOL_GPL(tpm_show_pubek); #define CAP_VER_RESULT_SIZE 18 @@ -274,8 +271,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, ssize_t len; char *str = buf; - struct tpm_chip *chip = - pci_get_drvdata(to_pci_dev(dev)); + struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; @@ -315,7 +311,6 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, } EXPORT_SYMBOL_GPL(tpm_store_cancel); - /* * Device file system interface to the TPM */ @@ -339,21 +334,20 @@ int tpm_open(struct inode *inode, struct file *file) } if (chip->num_opens) { - dev_dbg(&chip->pci_dev->dev, - "Another process owns this TPM\n"); + dev_dbg(chip->dev, "Another process owns this TPM\n"); rc = -EBUSY; goto err_out; } chip->num_opens++; - pci_dev_get(chip->pci_dev); + get_device(chip->dev); spin_unlock(&driver_lock); chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); if (chip->data_buffer == NULL) { chip->num_opens--; - pci_dev_put(chip->pci_dev); + put_device(chip->dev); return -ENOMEM; } @@ -366,7 +360,6 @@ err_out: spin_unlock(&driver_lock); return rc; } - EXPORT_SYMBOL_GPL(tpm_open); int tpm_release(struct inode *inode, struct file *file) @@ -378,15 +371,14 @@ int tpm_release(struct inode *inode, struct file *file) chip->num_opens--; del_singleshot_timer_sync(&chip->user_read_timer); atomic_set(&chip->data_pending, 0); - pci_dev_put(chip->pci_dev); + put_device(chip->dev); kfree(chip->data_buffer); spin_unlock(&driver_lock); return 0; } - EXPORT_SYMBOL_GPL(tpm_release); -ssize_t tpm_write(struct file * file, const char __user * buf, +ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t * off) { struct tpm_chip *chip = file->private_data; @@ -422,7 +414,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf, EXPORT_SYMBOL_GPL(tpm_write); -ssize_t tpm_read(struct file * file, char __user * buf, +ssize_t tpm_read(struct file * file, char __user *buf, size_t size, loff_t * off) { struct tpm_chip *chip = file->private_data; @@ -444,15 +436,14 @@ ssize_t tpm_read(struct file * file, char __user * buf, return ret_size; } - EXPORT_SYMBOL_GPL(tpm_read); -void __devexit tpm_remove(struct pci_dev *pci_dev) +void tpm_remove_hardware(struct device *dev) { - struct tpm_chip *chip = pci_get_drvdata(pci_dev); + struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) { - dev_err(&pci_dev->dev, "No device data found\n"); + dev_err(dev, "No device data found\n"); return; } @@ -462,22 +453,20 @@ void __devexit tpm_remove(struct pci_dev *pci_dev) spin_unlock(&driver_lock); - pci_set_drvdata(pci_dev, NULL); + dev_set_drvdata(dev, NULL); misc_deregister(&chip->vendor->miscdev); kfree(chip->vendor->miscdev.name); - sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group); + sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); - pci_disable_device(pci_dev); - - dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); + dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= + !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); kfree(chip); - pci_dev_put(pci_dev); + put_device(dev); } - -EXPORT_SYMBOL_GPL(tpm_remove); +EXPORT_SYMBOL_GPL(tpm_remove_hardware); static u8 savestate[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ @@ -489,32 +478,30 @@ static u8 savestate[] = { * We are about to suspend. Save the TPM state * so that it can be restored. */ -int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state) +int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) { - struct tpm_chip *chip = pci_get_drvdata(pci_dev); + struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; tpm_transmit(chip, savestate, sizeof(savestate)); return 0; } - EXPORT_SYMBOL_GPL(tpm_pm_suspend); /* * Resume from a power safe. The BIOS already restored * the TPM state. */ -int tpm_pm_resume(struct pci_dev *pci_dev) +int tpm_pm_resume(struct device *dev) { - struct tpm_chip *chip = pci_get_drvdata(pci_dev); + struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; return 0; } - EXPORT_SYMBOL_GPL(tpm_pm_resume); /* @@ -524,8 +511,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); * upon errant exit from this function specific probe function should call * pci_disable_device */ -int tpm_register_hardware(struct pci_dev *pci_dev, - struct tpm_vendor_specific *entry) +int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) { #define DEVNAME_SIZE 7 @@ -534,12 +520,10 @@ int tpm_register_hardware(struct pci_dev *pci_dev, int i, j; /* Driver specific per-device data */ - chip = kmalloc(sizeof(*chip), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; - memset(chip, 0, sizeof(struct tpm_chip)); - init_MUTEX(&chip->buffer_mutex); init_MUTEX(&chip->tpm_mutex); INIT_LIST_HEAD(&chip->list); @@ -563,8 +547,7 @@ int tpm_register_hardware(struct pci_dev *pci_dev, dev_num_search_complete: if (chip->dev_num < 0) { - dev_err(&pci_dev->dev, - "No available tpm device numbers\n"); + dev_err(dev, "No available tpm device numbers\n"); kfree(chip); return -ENODEV; } else if (chip->dev_num == 0) @@ -576,15 +559,15 @@ dev_num_search_complete: scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); chip->vendor->miscdev.name = devname; - chip->vendor->miscdev.dev = &(pci_dev->dev); - chip->pci_dev = pci_dev_get(pci_dev); + chip->vendor->miscdev.dev = dev; + chip->dev = get_device(dev); if (misc_register(&chip->vendor->miscdev)) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "unable to misc_register %s, minor %d\n", chip->vendor->miscdev.name, chip->vendor->miscdev.minor); - pci_dev_put(pci_dev); + put_device(dev); kfree(chip); dev_mask[i] &= !(1 << j); return -ENODEV; @@ -592,17 +575,16 @@ dev_num_search_complete: spin_lock(&driver_lock); - pci_set_drvdata(pci_dev, chip); + dev_set_drvdata(dev, chip); list_add(&chip->list, &tpm_chip_list); spin_unlock(&driver_lock); - sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group); + sysfs_create_group(&dev->kobj, chip->vendor->attr_group); return 0; } - EXPORT_SYMBOL_GPL(tpm_register_hardware); MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 373b41f6b46..024814b50c3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -55,12 +55,13 @@ struct tpm_vendor_specific { int (*recv) (struct tpm_chip *, u8 *, size_t); int (*send) (struct tpm_chip *, u8 *, size_t); void (*cancel) (struct tpm_chip *); + u8 (*status) (struct tpm_chip *); struct miscdevice miscdev; struct attribute_group *attr_group; }; struct tpm_chip { - struct pci_dev *pci_dev; /* PCI device stuff */ + struct device *dev; /* Device stuff */ int dev_num; /* /dev/tpm# */ int num_opens; /* only one allowed */ @@ -91,13 +92,13 @@ static inline void tpm_write_index(int base, int index, int value) outb(value & 0xFF, base+1); } -extern int tpm_register_hardware(struct pci_dev *, +extern int tpm_register_hardware(struct device *, struct tpm_vendor_specific *); extern int tpm_open(struct inode *, struct file *); extern int tpm_release(struct inode *, struct file *); extern ssize_t tpm_write(struct file *, const char __user *, size_t, loff_t *); extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); -extern void __devexit tpm_remove(struct pci_dev *); -extern int tpm_pm_suspend(struct pci_dev *, pm_message_t); -extern int tpm_pm_resume(struct pci_dev *); +extern void tpm_remove_hardware(struct device *); +extern int tpm_pm_suspend(struct device *, pm_message_t); +extern int tpm_pm_resume(struct device *); diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index c0d64914595..8cb42e84723 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -40,7 +40,7 @@ enum tpm_atmel_read_status { ATML_STATUS_READY = 0x08 }; -static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) +static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) { u8 status, *hdr = buf; u32 size; @@ -54,7 +54,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) for (i = 0; i < 6; i++) { status = inb(chip->vendor->base + 1); if ((status & ATML_STATUS_DATA_AVAIL) == 0) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "error reading header\n"); return -EIO; } @@ -66,12 +66,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) size = be32_to_cpu(*native_size); if (count < size) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "Recv size(%d) less than available space\n", size); for (; i < size; i++) { /* clear the waiting data anyway */ status = inb(chip->vendor->base + 1); if ((status & ATML_STATUS_DATA_AVAIL) == 0) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "error reading data\n"); return -EIO; } @@ -83,7 +83,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) for (; i < size; i++) { status = inb(chip->vendor->base + 1); if ((status & ATML_STATUS_DATA_AVAIL) == 0) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "error reading data\n"); return -EIO; } @@ -93,20 +93,20 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) /* make sure data available is gone */ status = inb(chip->vendor->base + 1); if (status & ATML_STATUS_DATA_AVAIL) { - dev_err(&chip->pci_dev->dev, "data available is stuck\n"); + dev_err(chip->dev, "data available is stuck\n"); return -EIO; } return size; } -static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count) +static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) { int i; - dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: "); + dev_dbg(chip->dev, "tpm_atml_send:\n"); for (i = 0; i < count; i++) { - dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]); + dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); outb(buf[i], chip->vendor->base); } @@ -118,6 +118,11 @@ static void tpm_atml_cancel(struct tpm_chip *chip) outb(ATML_STATUS_ABORT, chip->vendor->base + 1); } +static u8 tpm_atml_status(struct tpm_chip *chip) +{ + return inb(chip->vendor->base + 1); +} + static struct file_operations atmel_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -137,7 +142,7 @@ static struct attribute* atmel_attrs[] = { &dev_attr_pcrs.attr, &dev_attr_caps.attr, &dev_attr_cancel.attr, - 0, + NULL, }; static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; @@ -146,6 +151,7 @@ static struct tpm_vendor_specific tpm_atmel = { .recv = tpm_atml_recv, .send = tpm_atml_send, .cancel = tpm_atml_cancel, + .status = tpm_atml_status, .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, .req_complete_val = ATML_STATUS_DATA_AVAIL, .req_canceled = ATML_STATUS_READY, @@ -153,86 +159,94 @@ static struct tpm_vendor_specific tpm_atmel = { .miscdev = { .fops = &atmel_ops, }, }; -static int __devinit tpm_atml_init(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) +static struct platform_device *pdev; + +static void __devexit tpm_atml_remove(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip) { + release_region(chip->vendor->base, 2); + tpm_remove_hardware(chip->dev); + } +} + +static struct device_driver atml_drv = { + .name = "tpm_atmel", + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .suspend = tpm_pm_suspend, + .resume = tpm_pm_resume, +}; + +static int __init init_atmel(void) { - u8 version[4]; int rc = 0; int lo, hi; - if (pci_enable_device(pci_dev)) - return -EIO; + driver_register(&atml_drv); lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); tpm_atmel.base = (hi<<8)|lo; - dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base); /* verify that it is an Atmel part */ if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T' || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') { - rc = -ENODEV; - goto out_err; + return -ENODEV; } - /* query chip for its version number */ - if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) { - version[1] = tpm_read_index(TPM_ADDR, 0x01); - version[2] = tpm_read_index(TPM_ADDR, 0x02); - version[3] = tpm_read_index(TPM_ADDR, 0x03); - } else { - dev_info(&pci_dev->dev, "version query failed\n"); - rc = -ENODEV; - goto out_err; + /* verify chip version number is 1.1 */ + if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) || + (tpm_read_index(TPM_ADDR, 0x01) != 0x01 )) + return -ENODEV; + + pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); + if ( !pdev ) + return -ENOMEM; + + pdev->name = "tpm_atmel0"; + pdev->id = -1; + pdev->num_resources = 0; + pdev->dev.release = tpm_atml_remove; + pdev->dev.driver = &atml_drv; + + if ((rc = platform_device_register(pdev)) < 0) { + kfree(pdev); + pdev = NULL; + return rc; } - if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0) - goto out_err; + if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) { + platform_device_unregister(pdev); + kfree(pdev); + pdev = NULL; + return -EBUSY; + } - dev_info(&pci_dev->dev, - "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1], - version[2], version[3]); + if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) { + release_region(tpm_atmel.base, 2); + platform_device_unregister(pdev); + kfree(pdev); + pdev = NULL; + return rc; + } + dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n", + tpm_atmel.base); return 0; -out_err: - pci_disable_device(pci_dev); - return rc; -} - -static struct pci_device_id tpm_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, - {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, tpm_pci_tbl); - -static struct pci_driver atmel_pci_driver = { - .name = "tpm_atmel", - .id_table = tpm_pci_tbl, - .probe = tpm_atml_init, - .remove = __devexit_p(tpm_remove), - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, -}; - -static int __init init_atmel(void) -{ - return pci_register_driver(&atmel_pci_driver); } static void __exit cleanup_atmel(void) { - pci_unregister_driver(&atmel_pci_driver); + if (pdev) { + tpm_atml_remove(&pdev->dev); + platform_device_unregister(pdev); + kfree(pdev); + pdev = NULL; + } + + driver_unregister(&atml_drv); } module_init(init_atmel); diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 939e51e119e..8198dbb7370 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -5,6 +5,7 @@ * Specifications at www.trustedcomputinggroup.org * * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de> + * Sirrix AG - security technologies, http://www.sirrix.com and * Applied Data Security Group, Ruhr-University Bochum, Germany * Project-Homepage: http://www.prosec.rub.de/tpm * @@ -29,9 +30,10 @@ #define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 /* These values will be filled after PnP-call */ -static int TPM_INF_DATA = 0; -static int TPM_INF_ADDR = 0; -static int pnp_registered = 0; +static int TPM_INF_DATA; +static int TPM_INF_ADDR; +static int TPM_INF_BASE; +static int TPM_INF_PORT_LEN; /* TPM header definitions */ enum infineon_tpm_header { @@ -143,11 +145,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) } if (i == TPM_MAX_TRIES) { /* timeout occurs */ if (wait_for_bit == STAT_XFE) - dev_err(&chip->pci_dev->dev, - "Timeout in wait(STAT_XFE)\n"); + dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n"); if (wait_for_bit == STAT_RDA) - dev_err(&chip->pci_dev->dev, - "Timeout in wait(STAT_RDA)\n"); + dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n"); return -EIO; } return 0; @@ -170,7 +170,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) static void tpm_wtx(struct tpm_chip *chip) { number_of_wtx++; - dev_info(&chip->pci_dev->dev, "Granting WTX (%02d / %02d)\n", + dev_info(chip->dev, "Granting WTX (%02d / %02d)\n", number_of_wtx, TPM_MAX_WTX_PACKAGES); wait_and_send(chip, TPM_VL_VER); wait_and_send(chip, TPM_CTRL_WTX); @@ -181,7 +181,7 @@ static void tpm_wtx(struct tpm_chip *chip) static void tpm_wtx_abort(struct tpm_chip *chip) { - dev_info(&chip->pci_dev->dev, "Aborting WTX\n"); + dev_info(chip->dev, "Aborting WTX\n"); wait_and_send(chip, TPM_VL_VER); wait_and_send(chip, TPM_CTRL_WTX_ABORT); wait_and_send(chip, 0x00); @@ -206,7 +206,7 @@ recv_begin: } if (buf[0] != TPM_VL_VER) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "Wrong transport protocol implementation!\n"); return -EIO; } @@ -221,8 +221,7 @@ recv_begin: } if ((size == 0x6D00) && (buf[1] == 0x80)) { - dev_err(&chip->pci_dev->dev, - "Error handling on vendor layer!\n"); + dev_err(chip->dev, "Error handling on vendor layer!\n"); return -EIO; } @@ -234,7 +233,7 @@ recv_begin: } if (buf[1] == TPM_CTRL_WTX) { - dev_info(&chip->pci_dev->dev, "WTX-package received\n"); + dev_info(chip->dev, "WTX-package received\n"); if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { tpm_wtx(chip); goto recv_begin; @@ -245,14 +244,14 @@ recv_begin: } if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { - dev_info(&chip->pci_dev->dev, "WTX-abort acknowledged\n"); + dev_info(chip->dev, "WTX-abort acknowledged\n"); return size; } if (buf[1] == TPM_CTRL_ERROR) { - dev_err(&chip->pci_dev->dev, "ERROR-package received:\n"); + dev_err(chip->dev, "ERROR-package received:\n"); if (buf[4] == TPM_INF_NAK) - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "-> Negative acknowledgement" " - retransmit command!\n"); return -EIO; @@ -271,7 +270,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) ret = empty_fifo(chip, 1); if (ret) { - dev_err(&chip->pci_dev->dev, "Timeout while clearing FIFO\n"); + dev_err(chip->dev, "Timeout while clearing FIFO\n"); return -EIO; } @@ -316,6 +315,11 @@ static void tpm_inf_cancel(struct tpm_chip *chip) */ } +static u8 tpm_inf_status(struct tpm_chip *chip) +{ + return inb(chip->vendor->base + STAT); +} + static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); @@ -344,6 +348,7 @@ static struct tpm_vendor_specific tpm_inf = { .recv = tpm_inf_recv, .send = tpm_inf_send, .cancel = tpm_inf_cancel, + .status = tpm_inf_status, .req_complete_mask = 0, .req_complete_val = 0, .attr_group = &inf_attr_grp, @@ -356,30 +361,11 @@ static const struct pnp_device_id tpm_pnp_tbl[] = { {"IFX0102", 0}, {"", 0} }; + MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, - const struct pnp_device_id *dev_id) -{ - if (pnp_port_valid(dev, 0)) { - TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); - TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); - tpm_inf.base = pnp_port_start(dev, 1); - dev_info(&dev->dev, "Found %s with ID %s\n", - dev->name, dev_id->id); - return 0; - } - return -ENODEV; -} - -static struct pnp_driver tpm_inf_pnp = { - .name = "tpm_inf_pnp", - .id_table = tpm_pnp_tbl, - .probe = tpm_inf_pnp_probe, -}; - -static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) + const struct pnp_device_id *dev_id) { int rc = 0; u8 iol, ioh; @@ -388,30 +374,28 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, int productid[2]; char chipname[20]; - rc = pci_enable_device(pci_dev); - if (rc) - return rc; - - dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); - - /* read IO-ports from PnP */ - rc = pnp_register_driver(&tpm_inf_pnp); - if (rc < 0) { - dev_err(&pci_dev->dev, - "Error %x from pnp_register_driver!\n",rc); - goto error2; - } - if (!rc) { - dev_info(&pci_dev->dev, "No Infineon TPM found!\n"); - goto error; + /* read IO-ports through PnP */ + if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && + !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { + TPM_INF_ADDR = pnp_port_start(dev, 0); + TPM_INF_DATA = (TPM_INF_ADDR + 1); + TPM_INF_BASE = pnp_port_start(dev, 1); + TPM_INF_PORT_LEN = pnp_port_len(dev, 1); + if (!TPM_INF_PORT_LEN) + return -EINVAL; + dev_info(&dev->dev, "Found %s with ID %s\n", + dev->name, dev_id->id); + if (!((TPM_INF_BASE >> 8) & 0xff)) + return -EINVAL; + /* publish my base address and request region */ + tpm_inf.base = TPM_INF_BASE; + if (request_region + (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { + release_region(tpm_inf.base, TPM_INF_PORT_LEN); + return -EINVAL; + } } else { - pnp_registered = 1; - } - - /* Make sure, we have received valid config ports */ - if (!TPM_INF_ADDR) { - dev_err(&pci_dev->dev, "No valid IO-ports received!\n"); - goto error; + return -EINVAL; } /* query chip for its vendor, its version number a.s.o. */ @@ -443,10 +427,6 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { - if (tpm_inf.base == 0) { - dev_err(&pci_dev->dev, "No IO-ports found!\n"); - goto error; - } /* configure TPM with IO-ports */ outb(IOLIMH, TPM_INF_ADDR); outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); @@ -460,10 +440,11 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, iol = inb(TPM_INF_DATA); if ((ioh << 8 | iol) != tpm_inf.base) { - dev_err(&pci_dev->dev, + dev_err(&dev->dev, "Could not set IO-ports to %04x\n", tpm_inf.base); - goto error; + release_region(tpm_inf.base, TPM_INF_PORT_LEN); + return -EIO; } /* activate register */ @@ -475,7 +456,7 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); /* Finally, we're done, print some infos */ - dev_info(&pci_dev->dev, "TPM found: " + dev_info(&dev->dev, "TPM found: " "config base 0x%x, " "io base 0x%x, " "chip version %02x%02x, " @@ -483,59 +464,53 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, "product id %02x%02x" "%s\n", TPM_INF_ADDR, - tpm_inf.base, + TPM_INF_BASE, version[0], version[1], vendorid[0], vendorid[1], productid[0], productid[1], chipname); - rc = tpm_register_hardware(pci_dev, &tpm_inf); - if (rc < 0) - goto error; + rc = tpm_register_hardware(&dev->dev, &tpm_inf); + if (rc < 0) { + release_region(tpm_inf.base, TPM_INF_PORT_LEN); + return -ENODEV; + } return 0; } else { - dev_info(&pci_dev->dev, "No Infineon TPM found!\n"); -error: - pnp_unregister_driver(&tpm_inf_pnp); -error2: - pci_disable_device(pci_dev); - pnp_registered = 0; + dev_info(&dev->dev, "No Infineon TPM found!\n"); return -ENODEV; } } -static struct pci_device_id tpm_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)}, - {0,} -}; +static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) +{ + struct tpm_chip *chip = pnp_get_drvdata(dev); -MODULE_DEVICE_TABLE(pci, tpm_pci_tbl); + if (chip) { + release_region(chip->vendor->base, TPM_INF_PORT_LEN); + tpm_remove_hardware(chip->dev); + } +} -static struct pci_driver inf_pci_driver = { - .name = "tpm_inf", - .id_table = tpm_pci_tbl, - .probe = tpm_inf_probe, - .remove = __devexit_p(tpm_remove), - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, +static struct pnp_driver tpm_inf_pnp = { + .name = "tpm_inf_pnp", + .driver = { + .owner = THIS_MODULE, + .suspend = tpm_pm_suspend, + .resume = tpm_pm_resume, + }, + .id_table = tpm_pnp_tbl, + .probe = tpm_inf_pnp_probe, + .remove = tpm_inf_pnp_remove, }; static int __init init_inf(void) { - return pci_register_driver(&inf_pci_driver); + return pnp_register_driver(&tpm_inf_pnp); } static void __exit cleanup_inf(void) { - if (pnp_registered) - pnp_unregister_driver(&tpm_inf_pnp); - pci_unregister_driver(&inf_pci_driver); + pnp_unregister_driver(&tpm_inf_pnp); } module_init(init_inf); @@ -543,5 +518,5 @@ module_exit(cleanup_inf); MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); -MODULE_VERSION("1.5"); +MODULE_VERSION("1.6"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index b4127348c06..253871b5b1e 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c @@ -111,7 +111,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) } while (time_before(jiffies, stop)); - dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); + dev_info(chip->dev, "wait for ready failed\n"); return -EBUSY; } @@ -127,12 +127,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) return -EIO; if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { - dev_err(&chip->pci_dev->dev, "F0 timeout\n"); + dev_err(chip->dev, "F0 timeout\n"); return -EIO; } if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) { - dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n", + dev_err(chip->dev, "not in normal mode (0x%x)\n", data); return -EIO; } @@ -141,7 +141,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) for (p = buffer; p < &buffer[count]; p++) { if (wait_for_stat (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "OBF timeout (while reading data)\n"); return -EIO; } @@ -152,11 +152,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) if ((data & NSC_STATUS_F0) == 0 && (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { - dev_err(&chip->pci_dev->dev, "F0 not set\n"); + dev_err(chip->dev, "F0 not set\n"); return -EIO; } if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "expected end of command(0x%x)\n", data); return -EIO; } @@ -187,19 +187,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) return -EIO; if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(&chip->pci_dev->dev, "IBF timeout\n"); + dev_err(chip->dev, "IBF timeout\n"); return -EIO; } outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND); if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { - dev_err(&chip->pci_dev->dev, "IBR timeout\n"); + dev_err(chip->dev, "IBR timeout\n"); return -EIO; } for (i = 0; i < count; i++) { if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(&chip->pci_dev->dev, + dev_err(chip->dev, "IBF timeout (while writing data)\n"); return -EIO; } @@ -207,7 +207,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) } if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(&chip->pci_dev->dev, "IBF timeout\n"); + dev_err(chip->dev, "IBF timeout\n"); return -EIO; } outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND); @@ -220,6 +220,11 @@ static void tpm_nsc_cancel(struct tpm_chip *chip) outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); } +static u8 tpm_nsc_status(struct tpm_chip *chip) +{ + return inb(chip->vendor->base + NSC_STATUS); +} + static struct file_operations nsc_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -239,7 +244,7 @@ static struct attribute * nsc_attrs[] = { &dev_attr_pcrs.attr, &dev_attr_caps.attr, &dev_attr_cancel.attr, - 0, + NULL, }; static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; @@ -248,6 +253,7 @@ static struct tpm_vendor_specific tpm_nsc = { .recv = tpm_nsc_recv, .send = tpm_nsc_send, .cancel = tpm_nsc_cancel, + .status = tpm_nsc_status, .req_complete_mask = NSC_STATUS_OBF, .req_complete_val = NSC_STATUS_OBF, .req_canceled = NSC_STATUS_RDY, @@ -255,16 +261,32 @@ static struct tpm_vendor_specific tpm_nsc = { .miscdev = { .fops = &nsc_ops, }, }; -static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) +static struct platform_device *pdev = NULL; + +static void __devexit tpm_nsc_remove(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + if ( chip ) { + release_region(chip->vendor->base, 2); + tpm_remove_hardware(chip->dev); + } +} + +static struct device_driver nsc_drv = { + .name = "tpm_nsc", + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .suspend = tpm_pm_suspend, + .resume = tpm_pm_resume, +}; + +static int __init init_nsc(void) { int rc = 0; int lo, hi; int nscAddrBase = TPM_ADDR; - - if (pci_enable_device(pci_dev)) - return -EIO; + driver_register(&nsc_drv); /* select PM channel 1 */ tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12); @@ -273,37 +295,71 @@ static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)| (tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE); - if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) { - rc = -ENODEV; - goto out_err; - } + if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) + return -ENODEV; } hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); tpm_nsc.base = (hi<<8) | lo; - dev_dbg(&pci_dev->dev, "NSC TPM detected\n"); - dev_dbg(&pci_dev->dev, + /* enable the DPM module */ + tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); + + pdev = kmalloc(sizeof(struct platform_device), GFP_KERNEL); + if ( !pdev ) + return -ENOMEM; + + memset(pdev, 0, sizeof(struct platform_device)); + + pdev->name = "tpm_nscl0"; + pdev->id = -1; + pdev->num_resources = 0; + pdev->dev.release = tpm_nsc_remove; + pdev->dev.driver = &nsc_drv; + + if ((rc=platform_device_register(pdev)) < 0) { + kfree(pdev); + pdev = NULL; + return rc; + } + + if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { + platform_device_unregister(pdev); + kfree(pdev); + pdev = NULL; + return -EBUSY; + } + + if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) { + release_region(tpm_nsc.base, 2); + platform_device_unregister(pdev); + kfree(pdev); + pdev = NULL; + return rc; + } + + dev_dbg(&pdev->dev, "NSC TPM detected\n"); + dev_dbg(&pdev->dev, "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20), tpm_read_index(nscAddrBase,0x27)); - dev_dbg(&pci_dev->dev, + dev_dbg(&pdev->dev, "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n", tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25), tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28)); - dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n", + dev_dbg(&pdev->dev, "NSC IO Base0 0x%x\n", (tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61)); - dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n", + dev_dbg(&pdev->dev, "NSC IO Base1 0x%x\n", (tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63)); - dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n", + dev_dbg(&pdev->dev, "NSC Interrupt number and wakeup 0x%x\n", tpm_read_index(nscAddrBase,0x70)); - dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n", + dev_dbg(&pdev->dev, "NSC IRQ type select 0x%x\n", tpm_read_index(nscAddrBase,0x71)); - dev_dbg(&pci_dev->dev, + dev_dbg(&pdev->dev, "NSC DMA channel select0 0x%x, select1 0x%x\n", tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75)); - dev_dbg(&pci_dev->dev, + dev_dbg(&pdev->dev, "NSC Config " "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1), @@ -312,55 +368,23 @@ static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7), tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9)); - dev_info(&pci_dev->dev, + dev_info(&pdev->dev, "NSC TPM revision %d\n", tpm_read_index(nscAddrBase, 0x27) & 0x1F); - /* enable the DPM module */ - tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); - - if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0) - goto out_err; - return 0; - -out_err: - pci_disable_device(pci_dev); - return rc; -} - -static struct pci_device_id tpm_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, tpm_pci_tbl); - -static struct pci_driver nsc_pci_driver = { - .name = "tpm_nsc", - .id_table = tpm_pci_tbl, - .probe = tpm_nsc_init, - .remove = __devexit_p(tpm_remove), - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, -}; - -static int __init init_nsc(void) -{ - return pci_register_driver(&nsc_pci_driver); } static void __exit cleanup_nsc(void) { - pci_unregister_driver(&nsc_pci_driver); + if (pdev) { + tpm_nsc_remove(&pdev->dev); + platform_device_unregister(pdev); + kfree(pdev); + pdev = NULL; + } + + driver_unregister(&nsc_drv); } module_init(init_nsc); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f5649a33774..c586bfa852e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -809,7 +809,7 @@ static void do_tty_hangup(void *data) check_tty_count(tty, "do_tty_hangup"); file_list_lock(); /* This breaks for file handles being sent over AF_UNIX sockets ? */ - list_for_each_entry(filp, &tty->tty_files, f_list) { + list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { if (filp->f_op->write == redirected_tty_write) cons_filp = filp; if (filp->f_op->write != tty_write) diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 1d44f69e1fd..003dda147cd 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -192,6 +192,9 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) int i, j, k; int ret; + if (!capable(CAP_SYS_TTY_CONFIG)) + return -EPERM; + kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); if (!kbs) { ret = -ENOMEM; diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c index 2865dac0a81..e75045fe264 100644 --- a/drivers/char/watchdog/cpu5wdt.c +++ b/drivers/char/watchdog/cpu5wdt.c @@ -28,6 +28,7 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/timer.h> +#include <linux/jiffies.h> #include <asm/io.h> #include <asm/uaccess.h> diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index 7fc2188386d..d8dede57540 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -45,6 +45,8 @@ #include <linux/fs.h> #include <linux/reboot.h> #include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/timer.h> #include <asm/uaccess.h> #include <asm/io.h> diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 427ad51b7a3..37c9e13ad3a 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -66,7 +66,7 @@ #include <linux/init.h> #include <linux/spinlock.h> #include <linux/reboot.h> - +#include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */ #include <asm/uaccess.h> #include <asm/io.h> diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index 0b8e493be04..5308e5c8f29 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c @@ -753,6 +753,7 @@ static struct pci_device_id pcipcwd_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl); static struct pci_driver pcipcwd_driver = { + .owner = THIS_MODULE, .name = WATCHDOG_NAME, .id_table = pcipcwd_pci_tbl, .probe = pcipcwd_card_init, diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 72501be79b0..4ee9974ad8c 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -63,6 +63,7 @@ #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <linux/jiffies.h> #include <asm/io.h> #include <asm/uaccess.h> diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c index 20e5eb8667f..a91edaf3a35 100644 --- a/drivers/char/watchdog/softdog.c +++ b/drivers/char/watchdog/softdog.c @@ -47,6 +47,8 @@ #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <linux/jiffies.h> + #include <asm/uaccess.h> #define PFX "SoftDog: " diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c index 4b3311993d4..dc9370f6c34 100644 --- a/drivers/char/watchdog/wdt_pci.c +++ b/drivers/char/watchdog/wdt_pci.c @@ -711,6 +711,7 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); static struct pci_driver wdtpci_driver = { + .owner = THIS_MODULE, .name = "wdt_pci", .id_table = wdtpci_pci_tbl, .probe = wdtpci_init_one, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 109d62ccf65..6c6121b85a5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -4,6 +4,9 @@ * Copyright (C) 2001 Russell King * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de> * + * Oct 2005 - Ashok Raj <ashok.raj@intel.com> + * Added handling for CPU hotplug + * * 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 * published by the Free Software Foundation. @@ -36,13 +39,6 @@ static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static DEFINE_SPINLOCK(cpufreq_driver_lock); -/* we keep a copy of all ->add'ed CPU's struct sys_device here; - * as it is only accessed in ->add and ->remove, no lock or reference - * count is necessary. - */ -static struct sys_device *cpu_sys_devices[NR_CPUS]; - - /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); @@ -574,6 +570,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) unsigned long flags; unsigned int j; + if (cpu_is_offline(cpu)) + return 0; + cpufreq_debug_disable_ratelimit(); dprintk("adding CPU %u\n", cpu); @@ -582,7 +581,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) * CPU because it is in the same boat. */ policy = cpufreq_cpu_get(cpu); if (unlikely(policy)) { - cpu_sys_devices[cpu] = sys_dev; dprintk("CPU already managed, adding link\n"); sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq"); cpufreq_debug_enable_ratelimit(); @@ -657,7 +655,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) } module_put(cpufreq_driver->owner); - cpu_sys_devices[cpu] = sys_dev; dprintk("initialization complete\n"); cpufreq_debug_enable_ratelimit(); @@ -682,7 +679,7 @@ err_out: nomem_out: module_put(cpufreq_driver->owner); - module_out: +module_out: cpufreq_debug_enable_ratelimit(); return ret; } @@ -698,6 +695,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) unsigned int cpu = sys_dev->id; unsigned long flags; struct cpufreq_policy *data; + struct sys_device *cpu_sys_dev; #ifdef CONFIG_SMP unsigned int j; #endif @@ -710,7 +708,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) if (!data) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - cpu_sys_devices[cpu] = NULL; cpufreq_debug_enable_ratelimit(); return -EINVAL; } @@ -725,14 +722,12 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) dprintk("removing link\n"); spin_unlock_irqrestore(&cpufreq_driver_lock, flags); sysfs_remove_link(&sys_dev->kobj, "cpufreq"); - cpu_sys_devices[cpu] = NULL; cpufreq_cpu_put(data); cpufreq_debug_enable_ratelimit(); return 0; } #endif - cpu_sys_devices[cpu] = NULL; if (!kobject_get(&data->kobj)) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); @@ -761,7 +756,8 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) if (j == cpu) continue; dprintk("removing link for cpu %u\n", j); - sysfs_remove_link(&cpu_sys_devices[j]->kobj, "cpufreq"); + cpu_sys_dev = get_cpu_sysdev(j); + sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); cpufreq_cpu_put(data); } } @@ -772,7 +768,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) down(&data->lock); if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); - cpufreq_driver->target = NULL; up(&data->lock); kobject_unregister(&data->kobj); @@ -1119,17 +1114,30 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int relation) { int retval = -EINVAL; - lock_cpu_hotplug(); + + /* + * Converted the lock_cpu_hotplug to preempt_disable() + * and preempt_enable(). This is a bit kludgy and relies on how cpu + * hotplug works. All we need is a guarantee that cpu hotplug won't make + * progress on any cpu. Once we do preempt_disable(), this would ensure + * that hotplug threads don't get onto this cpu, thereby delaying + * the cpu remove process. + * + * We removed the lock_cpu_hotplug since we need to call this function + * via cpu hotplug callbacks, which result in locking the cpu hotplug + * thread itself. Agree this is not very clean, cpufreq community + * could improve this if required. - Ashok Raj <ashok.raj@intel.com> + */ + preempt_disable(); dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu, target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); - unlock_cpu_hotplug(); + preempt_enable(); return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); - int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -1416,6 +1424,45 @@ int cpufreq_update_policy(unsigned int cpu) } EXPORT_SYMBOL(cpufreq_update_policy); +static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct cpufreq_policy *policy; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + + if (sys_dev) { + switch (action) { + case CPU_ONLINE: + cpufreq_add_dev(sys_dev); + break; + case CPU_DOWN_PREPARE: + /* + * We attempt to put this cpu in lowest frequency + * possible before going down. This will permit + * hardware-managed P-State to switch other related + * threads to min or higher speeds if possible. + */ + policy = cpufreq_cpu_data[cpu]; + if (policy) { + cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_H); + } + break; + case CPU_DEAD: + cpufreq_remove_dev(sys_dev); + break; + } + } + return NOTIFY_OK; +} + +static struct notifier_block cpufreq_cpu_notifier = +{ + .notifier_call = cpufreq_cpu_callback, +}; /********************************************************************* * REGISTER / UNREGISTER CPUFREQ DRIVER * @@ -1476,6 +1523,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) } if (!ret) { + register_cpu_notifier(&cpufreq_cpu_notifier); dprintk("driver %s up and running\n", driver_data->name); cpufreq_debug_enable_ratelimit(); } @@ -1507,6 +1555,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) dprintk("unregistering driver %s\n", driver->name); sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); + unregister_cpu_notifier(&cpufreq_cpu_notifier); spin_lock_irqsave(&cpufreq_driver_lock, flags); cpufreq_driver = NULL; diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 741b6b191e6..3597f25d5ef 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -19,6 +19,7 @@ #include <linux/percpu.h> #include <linux/kobject.h> #include <linux/spinlock.h> +#include <linux/notifier.h> #include <asm/cputime.h> static spinlock_t cpufreq_stats_lock; @@ -298,6 +299,27 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, return 0; } +static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_ONLINE: + cpufreq_update_policy(cpu); + break; + case CPU_DEAD: + cpufreq_stats_free_table(cpu); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block cpufreq_stat_cpu_notifier = +{ + .notifier_call = cpufreq_stat_cpu_callback, +}; + static struct notifier_block notifier_policy_block = { .notifier_call = cpufreq_stat_notifier_policy }; @@ -311,6 +333,7 @@ __init cpufreq_stats_init(void) { int ret; unsigned int cpu; + spin_lock_init(&cpufreq_stats_lock); if ((ret = cpufreq_register_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER))) @@ -323,20 +346,31 @@ __init cpufreq_stats_init(void) return ret; } - for_each_cpu(cpu) - cpufreq_update_policy(cpu); + register_cpu_notifier(&cpufreq_stat_cpu_notifier); + lock_cpu_hotplug(); + for_each_online_cpu(cpu) { + cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, + (void *)(long)cpu); + } + unlock_cpu_hotplug(); return 0; } static void __exit cpufreq_stats_exit(void) { unsigned int cpu; + cpufreq_unregister_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); cpufreq_unregister_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); - for_each_cpu(cpu) - cpufreq_stats_free_table(cpu); + unregister_cpu_notifier(&cpufreq_stat_cpu_notifier); + lock_cpu_hotplug(); + for_each_online_cpu(cpu) { + cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD, + (void *)(long)cpu); + } + unlock_cpu_hotplug(); } MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>"); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 094835cce32..4263935443c 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -2,7 +2,7 @@ menu "Hardware crypto devices" config CRYPTO_DEV_PADLOCK tristate "Support for VIA PadLock ACE" - depends on CRYPTO && X86 && !X86_64 + depends on CRYPTO && X86_32 help Some VIA processors come with an integrated crypto engine (so called VIA PadLock ACE, Advanced Cryptography Engine) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 327b58e6487..b6815c6c29a 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -70,8 +70,7 @@ config DELL_RBU config DCDBAS tristate "Dell Systems Management Base Driver" - depends on X86 || X86_64 - default m + depends on X86 help The Dell Systems Management Base Driver provides a sysfs interface for systems management software to perform System Management diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 74af7e07486..8b9d8552659 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2211,13 +2211,12 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) if (toc == NULL) { /* Try to allocate space. */ - toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc), - GFP_KERNEL); - info->toc = toc; + toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL); if (toc == NULL) { printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name); return -ENOMEM; } + info->toc = toc; } /* Check to see if the existing data is still valid. @@ -2240,7 +2239,8 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) /* First read just the header, so we know how long the TOC is. */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, sizeof(struct atapi_toc_header), sense); - if (stat) return stat; + if (stat) + return stat; #if ! STANDARD_ATAPI if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { @@ -2324,7 +2324,8 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) /* Read the multisession information. */ stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); - if (stat) return stat; + if (stat) + return stat; toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba); } else { @@ -2460,7 +2461,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) { struct request req; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; if (cgc->timeout <= 0) cgc->timeout = ATAPI_WAIT_PC; @@ -2537,7 +2538,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, unsigned int cmd, void *arg) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; struct cdrom_info *info = drive->driver_data; int stat; @@ -2548,7 +2549,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, */ case CDROMPLAYTRKIND: { unsigned long lba_start, lba_end; - struct cdrom_ti *ti = (struct cdrom_ti *)arg; + struct cdrom_ti *ti = arg; struct atapi_toc_entry *first_toc, *last_toc; stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc); @@ -2571,12 +2572,13 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, } case CDROMREADTOCHDR: { - struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; + struct cdrom_tochdr *tochdr = arg; struct atapi_toc *toc; /* Make sure our saved TOC is valid. */ stat = cdrom_read_toc(drive, NULL); - if (stat) return stat; + if (stat) + return stat; toc = info->toc; tochdr->cdth_trk0 = toc->hdr.first_track; @@ -2586,11 +2588,12 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, } case CDROMREADTOCENTRY: { - struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg; + struct cdrom_tocentry *tocentry = arg; struct atapi_toc_entry *toce; stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce); - if (stat) return stat; + if (stat) + return stat; tocentry->cdte_ctrl = toce->control; tocentry->cdte_adr = toce->adr; @@ -2613,7 +2616,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, static int ide_cdrom_reset (struct cdrom_device_info *cdi) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; struct request_sense sense; struct request req; int ret; @@ -2636,12 +2639,13 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi) static int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; struct request_sense sense; if (position) { int stat = cdrom_lockdoor(drive, 0, &sense); - if (stat) return stat; + if (stat) + return stat; } return cdrom_eject(drive, !position, &sense); @@ -2650,7 +2654,7 @@ int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) static int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; return cdrom_lockdoor(drive, lock, NULL); } @@ -2700,7 +2704,7 @@ void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page static int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; struct request_sense sense; struct atapi_capabilities_page cap; int stat; @@ -2723,7 +2727,7 @@ int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) static int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; struct media_event_desc med; struct request_sense sense; int stat; @@ -2769,7 +2773,7 @@ int ide_cdrom_get_last_session (struct cdrom_device_info *cdi, struct cdrom_multisession *ms_info) { struct atapi_toc *toc; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; struct cdrom_info *info = drive->driver_data; struct request_sense sense; int ret; @@ -2791,7 +2795,7 @@ int ide_cdrom_get_mcn (struct cdrom_device_info *cdi, { int stat; char mcnbuf[24]; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; /* get MCN */ if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL))) @@ -2815,7 +2819,7 @@ static int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, int slot_nr) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; + ide_drive_t *drive = cdi->handle; int retval; if (slot_nr == CDSL_CURRENT) { @@ -2886,7 +2890,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) devinfo->mask = 0; devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed; devinfo->capacity = nslots; - devinfo->handle = (void *) drive; + devinfo->handle = drive; strcpy(devinfo->name, drive->name); /* set capability mask to match the probe. */ @@ -2942,7 +2946,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) * registered with the Uniform layer yet, it can't do this. * Same goes for cdi->ops. */ - cdi->handle = (ide_drive_t *) drive; + cdi->handle = drive; cdi->ops = &ide_cdrom_dops; if (ide_cdrom_get_capabilities(drive, &cap)) @@ -3254,6 +3258,7 @@ int ide_cdrom_setup (ide_drive_t *drive) return 0; } +#ifdef CONFIG_PROC_FS static sector_t ide_cdrom_capacity (ide_drive_t *drive) { @@ -3264,6 +3269,7 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) return capacity * sectors_per_frame; } +#endif static int ide_cd_remove(struct device *dev) { @@ -3309,7 +3315,7 @@ static int ide_cd_probe(struct device *); static int proc_idecd_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { - ide_drive_t*drive = (ide_drive_t *)data; + ide_drive_t *drive = data; int len; len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive)); @@ -3449,7 +3455,7 @@ static int ide_cd_probe(struct device *dev) printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); goto failed; } - info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); + info = kmalloc(sizeof(struct cdrom_info), GFP_KERNEL); if (info == NULL) { printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); goto failed; diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index f014e639088..c57a3871184 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -38,6 +38,7 @@ #include <linux/module.h> #include <linux/errno.h> #include <linux/slab.h> +#include <linux/sched.h> /* INIT_WORK, schedule_work(), flush_scheduled_work() */ #include <rdma/ib_cache.h> diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 89ce9dc210d..acda7d63d6f 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -43,6 +43,7 @@ #include <linux/dma-mapping.h> #include <linux/kref.h> #include <linux/idr.h> +#include <linux/workqueue.h> #include <rdma/ib_pack.h> #include <rdma/ib_sa.h> diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 889e8509673..22fdc446f25 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -34,6 +34,8 @@ */ #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <rdma/ib_verbs.h> #include <rdma/ib_cache.h> diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 8561b297a19..1229c604c6e 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -34,6 +34,9 @@ * $Id: mthca_mad.c 1349 2004-12-16 21:09:43Z roland $ */ +#include <linux/string.h> +#include <linux/slab.h> + #include <rdma/ib_verbs.h> #include <rdma/ib_mad.h> #include <rdma/ib_smi.h> diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index b47ea7daf08..2fc449da418 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -33,6 +33,8 @@ */ #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include "mthca_dev.h" #include "mthca_cmd.h" diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c index 0576056b34f..bd133868207 100644 --- a/drivers/infiniband/hw/mthca/mthca_profile.c +++ b/drivers/infiniband/hw/mthca/mthca_profile.c @@ -35,6 +35,8 @@ #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/string.h> +#include <linux/slab.h> #include "mthca_profile.h" diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 62ff091505d..7c9afde5ace 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -36,6 +36,8 @@ */ #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include <rdma/ib_verbs.h> #include <rdma/ib_cache.h> diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c index 4f995391dd1..df5e494a9d3 100644 --- a/drivers/infiniband/hw/mthca/mthca_reset.c +++ b/drivers/infiniband/hw/mthca/mthca_reset.c @@ -37,6 +37,7 @@ #include <linux/errno.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/slab.h> #include "mthca_dev.h" #include "mthca_cmd.h" diff --git a/drivers/infiniband/hw/mthca/mthca_uar.c b/drivers/infiniband/hw/mthca/mthca_uar.c index 1c8791ded6f..8e9219842be 100644 --- a/drivers/infiniband/hw/mthca/mthca_uar.c +++ b/drivers/infiniband/hw/mthca/mthca_uar.c @@ -32,6 +32,8 @@ * $Id$ */ +#include <asm/page.h> /* PAGE_SHIFT */ + #include "mthca_dev.h" #include "mthca_memfree.h" diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index ab09cf4093e..0506934244f 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/kthread.h> +#include <linux/sched.h> /* HZ */ /*#include <asm/io.h>*/ diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index bf65430181f..4571ea3a4b9 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -34,6 +34,7 @@ #include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> +#include <linux/jiffies.h> #define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver" diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 9d95459f4bc..704bf70f1db 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -34,6 +34,7 @@ #include <linux/input.h> #include <linux/gameport.h> #include <linux/init.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Logitech ADI joystick family driver" diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index c75ac6eb1ff..3121961e3e7 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -38,6 +38,7 @@ #include <linux/init.h> #include <linux/input.h> #include <linux/gameport.h> +#include <linux/jiffies.h> #include <asm/timex.h> #define DRIVER_DESC "Analog joystick and gamepad driver" diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 9a3dfc724a4..1909f7ef340 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -34,6 +34,7 @@ #include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Creative Labs Blaster GamePad Cobra driver" diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index e151f8c5bcb..8a3ad455eb3 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -35,6 +35,7 @@ #include <linux/init.h> #include <linux/input.h> #include <linux/gameport.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Genius Flight 2000 joystick driver" diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index e206bb56e53..a936e7aedb1 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -34,6 +34,7 @@ #include <linux/slab.h> #include <linux/gameport.h> #include <linux/input.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Gravis GrIP protocol joystick driver" diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index a0ba93ccac7..51a912222e8 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -19,6 +19,7 @@ #include <linux/input.h> #include <linux/delay.h> #include <linux/proc_fs.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Gravis Grip Multiport driver" diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index c528473c09d..6e2c721c26b 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -35,6 +35,7 @@ #include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Guillemot Digital joystick driver" diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 8511ee7bb26..c4ed0175822 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -38,6 +38,7 @@ #include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> +#include <linux/jiffies.h> #define DRIVER_DESC "InterAct digital joystick driver" diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index 4234ccaf914..88ec5a918f2 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c @@ -34,6 +34,7 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/slab.h> #define DRIVER_DESC "Gameport data dumper module" diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index eaaad45cc75..78dd163cd70 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -33,6 +33,7 @@ #include <linux/init.h> #include <linux/input.h> #include <linux/gameport.h> +#include <linux/jiffies.h> #define DRIVER_DESC "Microsoft SideWinder joystick family driver" diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 3a7d1bb4647..60e2aac7d06 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -38,6 +38,7 @@ #include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> +#include <linux/jiffies.h> #define DRIVER_DESC "ThrustMaster DirectConnect joystick driver" diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index bb934e6d963..b3eaac1b35b 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -14,7 +14,7 @@ if INPUT_MISC config INPUT_PCSPKR tristate "PC Speaker support" - depends on ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES + depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES help Say Y here if you want the standard PC Speaker to be used for bells and whistles. diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index e3c44ffae67..1c9426fd520 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c @@ -40,6 +40,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/string.h> +#include <asm/semaphore.h> #define PREFIX "HP SDC MLC: " diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 3abd7fc6e5e..7b564c0dd99 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/ctype.h> +#include <linux/sched.h> /* current */ MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem"); MODULE_AUTHOR("Carsten Paeth"); diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c index 7333377ab31..e3866b0a97f 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/drivers/isdn/hisax/hfc4s8s_l1.c @@ -1063,7 +1063,7 @@ tx_b_frame(struct hfc4s8s_btype *bch) Write_hfc8(l1->hw, A_INC_RES_FIFO, 1); } ack_len += skb->truesize; - bch->tx_skb = 0; + bch->tx_skb = NULL; bch->tx_cnt = 0; dev_kfree_skb(skb); } else @@ -1659,10 +1659,10 @@ hfc4s8s_remove(struct pci_dev *pdev) } static struct pci_driver hfc4s8s_driver = { - name:"hfc4s8s_l1", - probe:hfc4s8s_probe, - remove:__devexit_p(hfc4s8s_remove), - id_table:hfc4s8s_ids, + .name = "hfc4s8s_l1", + .probe = hfc4s8s_probe, + .remove = __devexit_p(hfc4s8s_remove), + .id_table = hfc4s8s_ids, }; /**********************/ diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 1ee00334692..c34c96d1890 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -17,6 +17,8 @@ #include <linux/pci_ids.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> + #include <asm/machdep.h> #include <asm/macio.h> #include <asm/pmac_feature.h> diff --git a/drivers/mca/mca-device.c b/drivers/mca/mca-device.c index 76d430aa243..e7adf89fae4 100644 --- a/drivers/mca/mca-device.c +++ b/drivers/mca/mca-device.c @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/mca.h> +#include <linux/string.h> /** * mca_device_read_stored_pos - read POS register from stored data diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 06f4d4686a6..31fccb4f05d 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c @@ -22,6 +22,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/string.h> #include <media/ir-common.h> /* -------------------------------------------------------------------------- */ diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 88757e2634e..2aa767f9bd7 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -36,6 +36,7 @@ #include <linux/vmalloc.h> #include <linux/delay.h> #include <linux/rwsem.h> +#include <linux/sched.h> #include "dvb_ca_en50221.h" #include "dvb_ringbuffer.h" diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index 5aa12ebab34..b595476332c 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = { .cold_ids = { &dtt200u_usb_table[0], NULL }, .warm_ids = { &dtt200u_usb_table[1], NULL }, }, - { 0 }, + { NULL }, } }; @@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = { .cold_ids = { &dtt200u_usb_table[2], NULL }, .warm_ids = { &dtt200u_usb_table[3], NULL }, }, - { 0 }, + { NULL }, } }; diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 0f57abeb6d6..75765e3a569 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = { .cold_ids = { &vp7045_usb_table[2], NULL }, .warm_ids = { &vp7045_usb_table[3], NULL }, }, - { 0 }, + { NULL }, } }; diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index f5fdc5c3e60..f6d4ee78bdd 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -36,6 +36,9 @@ #include <linux/moduleparam.h> #include <linux/device.h> #include <linux/firmware.h> +#include <linux/jiffies.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "bcm3510.h" diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c index 21433e1831e..6b055360861 100644 --- a/drivers/media/dvb/frontends/dib3000mb.c +++ b/drivers/media/dvb/frontends/dib3000mb.c @@ -27,6 +27,8 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dib3000-common.h" #include "dib3000mb_priv.h" diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 441de665fec..c024fad1733 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c @@ -26,6 +26,8 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dib3000-common.h" #include "dib3000mc_priv.h" diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index cff93b9d8ab..794be520d59 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -22,6 +22,8 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "dvb_dummy_fe.h" diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 7142b9c51dd..8dde72bd104 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -37,6 +37,8 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/byteorder.h> #include "dvb_frontend.h" diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index e455aecd76b..e38454901dd 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -29,6 +29,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "mt312_priv.h" diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c index cc1bc0edd65..f0c610f2c2d 100644 --- a/drivers/media/dvb/frontends/mt352.c +++ b/drivers/media/dvb/frontends/mt352.c @@ -35,6 +35,8 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "mt352_priv.h" diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c index 35a1d60f192..30786b1911b 100644 --- a/drivers/media/dvb/frontends/nxt2002.c +++ b/drivers/media/dvb/frontends/nxt2002.c @@ -32,6 +32,8 @@ #include <linux/moduleparam.h> #include <linux/device.h> #include <linux/firmware.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "nxt2002.h" diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index b6d0eecc59e..817b044c7fd 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -36,6 +36,8 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/byteorder.h> #include "dvb_frontend.h" diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index ad56a995840..8a9db23dd1b 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -34,6 +34,8 @@ #include <linux/moduleparam.h> #include <linux/device.h> #include <linux/firmware.h> +#include <linux/string.h> +#include <linux/slab.h> #include <asm/byteorder.h> #include "dvb_frontend.h" diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index c7fe27fd530..f265418e326 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include <linux/string.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/jiffies.h> +#include <asm/div64.h> #include "dvb_frontend.h" #include "s5h1420.h" diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index 764a95a2e21..1c6b2e9264b 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -32,6 +32,8 @@ #include <linux/device.h> #include <linux/firmware.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "sp8870.h" diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index d868a6927a1..73384e75625 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c @@ -14,6 +14,8 @@ #include <linux/moduleparam.h> #include <linux/device.h> #include <linux/firmware.h> +#include <linux/string.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "sp887x.h" diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 8d09afd7545..6122ba754bc 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -24,6 +24,8 @@ #include <linux/module.h> #include <linux/string.h> #include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/slab.h> #include "dvb_frontend.h" #include "stv0297.h" diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 2d62931f20b..889d9257215 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -48,6 +48,7 @@ #include <linux/moduleparam.h> #include <linux/string.h> #include <linux/slab.h> +#include <linux/jiffies.h> #include <asm/div64.h> #include "dvb_frontend.h" diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 74cea9f8d72..3529c618f82 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -32,6 +32,10 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/device.h> +#include <linux/jiffies.h> +#include <linux/string.h> +#include <linux/slab.h> + #include "dvb_frontend.h" #include "tda1004x.h" diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 168e013d23b..c05cf186105 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c @@ -30,6 +30,7 @@ #include <linux/moduleparam.h> #include <linux/string.h> #include <linux/slab.h> +#include <linux/jiffies.h> #include "dvb_frontend.h" #include "tda8083.h" diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index df79d5e0aae..e09214082e0 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -14,6 +14,7 @@ #include <linux/slab.h> #include <linux/fs.h> #include <linux/miscdevice.h> +#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */ #include <linux/delay.h> #include <asm/uaccess.h> #include "miropcm20-rds-core.h" diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 018ca887ca8..40d4ea898db 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -90,7 +90,7 @@ static void i2o_report_fail_status(u8 req_status, u32 * msg) }; if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE) - printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", + printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n", req_status); else printk(KERN_DEBUG "TRANSPORT_%s.\n", diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index d9879965eb5..8eb50cdb8ae 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -16,6 +16,8 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> #include "core.h" /** diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 0079a4be0af..0fb9c4e2ad4 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -17,6 +17,9 @@ #include <linux/module.h> #include <linux/rwsem.h> #include <linux/i2o.h> +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/slab.h> #include "core.h" #define OSM_NAME "i2o" diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index bda2c62648b..b675b4ebbeb 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -30,6 +30,10 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <asm/param.h> /* HZ */ #include "core.h" #define OSM_NAME "exec-osm" diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 361da8d1d5e..61b837de4b6 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -28,6 +28,7 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include <linux/sched.h> #include "core.h" #define OSM_NAME "i2o" diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 585cded3d36..a984c0efabf 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -32,9 +32,12 @@ #include <linux/suspend.h> #include <linux/slab.h> #include <linux/kthread.h> +#include <linux/delay.h> #include <asm/dma.h> #include <asm/semaphore.h> +#include <asm/arch/collie.h> +#include <asm/mach-types.h> #include "ucb1x00.h" @@ -85,12 +88,23 @@ static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts) */ static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) { - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + if (machine_is_collie()) { + ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); - return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); + udelay(55); + + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync); + } else { + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); + } } /* @@ -101,12 +115,16 @@ static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) */ static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) { - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + if (machine_is_collie()) + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); + else { + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + } ucb1x00_reg_write(ts->ucb, UCB_TS_CR, UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); @@ -124,12 +142,17 @@ static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) */ static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) { - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + if (machine_is_collie()) + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); + else { + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + } + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); @@ -163,6 +186,15 @@ static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts) return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); } +static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts) +{ + unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); + if (machine_is_collie()) + return (!(val & (UCB_TS_CR_TSPX_LOW))); + else + return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)); +} + /* * This is a RT kernel thread that handles the ADC accesses * (mainly so we can use semaphores in the UCB1200 core code @@ -186,7 +218,7 @@ static int ucb1x00_thread(void *_ts) add_wait_queue(&ts->irq_wait, &wait); while (!kthread_should_stop()) { - unsigned int x, y, p, val; + unsigned int x, y, p; signed long timeout; ts->restart = 0; @@ -206,12 +238,12 @@ static int ucb1x00_thread(void *_ts) msleep(10); ucb1x00_enable(ts->ucb); - val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); - if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) { + + if (ucb1x00_ts_pen_down(ts)) { set_task_state(tsk, TASK_INTERRUPTIBLE); - ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); ucb1x00_disable(ts->ucb); /* diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index fa83f15fdf1..9b629856c73 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -85,6 +85,12 @@ static void mmc_blk_put(struct mmc_blk_data *md) up(&open_lock); } +static inline int mmc_blk_readonly(struct mmc_card *card) +{ + return mmc_card_readonly(card) || + !(card->csd.cmdclass & CCC_BLOCK_WRITE); +} + static int mmc_blk_open(struct inode *inode, struct file *filp) { struct mmc_blk_data *md; @@ -97,7 +103,7 @@ static int mmc_blk_open(struct inode *inode, struct file *filp) ret = 0; if ((filp->f_mode & FMODE_WRITE) && - mmc_card_readonly(md->queue.card)) + mmc_blk_readonly(md->queue.card)) ret = -EROFS; } @@ -410,7 +416,7 @@ static int mmc_blk_probe(struct mmc_card *card) printk(KERN_INFO "%s: %s %s %dKiB %s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), (card->csd.capacity << card->csd.read_blkbits) / 1024, - mmc_card_readonly(card)?"(ro)":""); + mmc_blk_readonly(card)?"(ro)":""); mmc_set_drvdata(card, md); add_disk(md->disk); diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 8eba373d42d..d575e3a018b 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -29,7 +29,6 @@ #include <asm/dma.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/scatterlist.h> #include <asm/sizes.h> diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c index 62d235a9a4e..4f6778f3ee3 100644 --- a/drivers/mtd/chips/jedec.c +++ b/drivers/mtd/chips/jedec.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/mtd/jedec.h> #include <linux/mtd/map.h> #include <linux/mtd/mtd.h> diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index dfd335e4a2a..df987a53ed9 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c @@ -44,6 +44,7 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/errno.h> +#include <linux/string.h> #include <linux/mtd/mtd.h> #ifdef HAVE_PARTITIONS #include <linux/mtd/partitions.h> diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index a423a382095..765c0179c8d 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -22,6 +22,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args) diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c index 0ba0ff7d43b..63104c73ca3 100644 --- a/drivers/mtd/maps/bast-flash.c +++ b/drivers/mtd/maps/bast-flash.c @@ -33,6 +33,7 @@ #include <linux/string.h> #include <linux/ioport.h> #include <linux/device.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index da8584a662f..c68b31dc7e6 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c @@ -20,6 +20,7 @@ #include <linux/ioport.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index 938c41f2f05..e5b74169fde 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index 0bc79c93a58..f99519692cb 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c @@ -30,12 +30,15 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/string.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> #include <linux/mtd/concat.h> +#include <asm/io.h> + /* ** The DIL/NetPC keeps its BIOS in two distinct flash blocks. ** Destroying any of these blocks transforms the DNPC into diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c index ab6dbe2b8cc..1df6188926b 100644 --- a/drivers/mtd/maps/epxa10db-flash.c +++ b/drivers/mtd/maps/epxa10db-flash.c @@ -27,12 +27,15 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/slab.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> +#include <asm/io.h> #include <asm/hardware.h> + #ifdef CONFIG_EPXA10DB #define BOARD_NAME "EPXA10DB" #else diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c index 068bb6a5452..00f7bbe5479 100644 --- a/drivers/mtd/maps/fortunet.c +++ b/drivers/mtd/maps/fortunet.c @@ -7,11 +7,14 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/string.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> +#include <asm/io.h> + #define MAX_NUM_REGIONS 4 #define MAX_NUM_PARTITIONS 8 diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index a9f86c7fbd5..1e5d6e1d05f 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -22,11 +22,13 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> +#include <linux/slab.h> +#include <linux/ioport.h> +#include <linux/device.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> -#include <linux/ioport.h> -#include <linux/device.h> #include <asm/io.h> #include <asm/hardware.h> diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 3fcc3288407..da316e54323 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -20,11 +20,14 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> +#include <linux/slab.h> +#include <linux/ioport.h> +#include <linux/device.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> -#include <linux/ioport.h> -#include <linux/device.h> + #include <asm/io.h> #include <asm/mach/flash.h> diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c index 1298de475c9..2337e0c4675 100644 --- a/drivers/mtd/maps/lubbock-flash.c +++ b/drivers/mtd/maps/lubbock-flash.c @@ -15,10 +15,13 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/slab.h> + #include <linux/dma-mapping.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> + #include <asm/io.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> diff --git a/drivers/mtd/maps/mainstone-flash.c b/drivers/mtd/maps/mainstone-flash.c index 87e93fa6058..da0f8a69262 100644 --- a/drivers/mtd/maps/mainstone-flash.c +++ b/drivers/mtd/maps/mainstone-flash.c @@ -16,9 +16,12 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/dma-mapping.h> +#include <linux/slab.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> + #include <asm/io.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c index 496109071cb..da36e8dddd1 100644 --- a/drivers/mtd/maps/omap-toto-flash.c +++ b/drivers/mtd/maps/omap-toto-flash.c @@ -12,9 +12,9 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> - #include <linux/errno.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index b17bca657da..fa84566245a 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c @@ -36,6 +36,8 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/ioport.h> +#include <linux/slab.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 18dbd3af1ea..d9c64e99ee3 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 118b04544ca..a0577ea00c3 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -30,6 +30,7 @@ #include <linux/string.h> #include <linux/ioport.h> #include <linux/device.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index 995e9991cb8..4e28b977f22 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c @@ -27,12 +27,14 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> +#include <asm/io.h> + #define FLASH_ADDR 0x40000000 #define FLASH_SIZE 0x00800000 #define FLASH_BANK_MAX 4 diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index b7c32c242bc..400dd9c8988 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/sched.h> /* TASK_* */ #include <linux/mtd/mtd.h> #include <linux/mtd/blktrans.h> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index c534fd5d95c..16df1e4fb0e 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -13,6 +13,7 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/fs.h> +#include <linux/sched.h> /* TASK_* */ #include <asm/uaccess.h> #include <linux/device.h> diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 8f66d093c80..f3e65af33a9 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -14,7 +14,7 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/slab.h> - +#include <linux/sched.h> /* TASK_* */ #include <linux/mtd/mtd.h> #include <linux/mtd/concat.h> diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index b47ebcb31e0..b58ba236a9e 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -51,6 +51,7 @@ #include <linux/device.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 1ce2c675b8a..a806dfe54d2 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -552,8 +552,7 @@ static int __init do_eepro_probe(struct net_device *dev) { unsigned short int WS[32]=WakeupSeq; - if (check_region(WakeupPort, 2)==0) { - + if (request_region(WakeupPort, 2, "eepro wakeup")) { if (net_debug>5) printk(KERN_DEBUG "Waking UP\n"); @@ -563,7 +562,10 @@ static int __init do_eepro_probe(struct net_device *dev) outb_p(WS[i],WakeupPort); if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]); } - } else printk(KERN_WARNING "Checkregion Failed!\n"); + + release_region(WakeupPort, 2); + } else + printk(KERN_WARNING "PnP wakeup region busy!\n"); } #endif @@ -705,7 +707,7 @@ static void __init eepro_print_info (struct net_device *dev) dev->name, (unsigned)dev->base_addr); break; case LAN595FX: - printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", + printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595TX: @@ -713,7 +715,7 @@ static void __init eepro_print_info (struct net_device *dev) dev->name, (unsigned)dev->base_addr); break; case LAN595: - printk("%s: Intel 82595-based lan card at %#x,", + printk("%s: Intel 82595-based lan card at %#x,", dev->name, (unsigned)dev->base_addr); } @@ -726,7 +728,7 @@ static void __init eepro_print_info (struct net_device *dev) if (dev->irq > 2) printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); - else + else printk(", %s.\n", ifmap[dev->if_port]); if (net_debug > 3) { @@ -756,7 +758,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) int err; /* Grab the region so we can find another board if autoIRQ fails. */ - if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { + if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { if (!autoprobe) printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n", ioaddr); @@ -838,15 +840,15 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) /* Mask off INT number */ int count = lp->word[1] & 7; unsigned irqMask = lp->word[7]; - + while (count--) irqMask &= irqMask - 1; - + count = ffs(irqMask); - + if (count) dev->irq = count - 1; - + if (dev->irq < 2) { printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n"); goto exit; @@ -854,7 +856,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) dev->irq = 9; } } - + dev->open = eepro_open; dev->stop = eepro_close; dev->hard_start_xmit = eepro_send_packet; @@ -863,7 +865,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) dev->tx_timeout = eepro_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->ethtool_ops = &eepro_ethtool_ops; - + /* print boot time info */ eepro_print_info(dev); @@ -1047,8 +1049,8 @@ static int eepro_open(struct net_device *dev) /* Initialize the RCV and XMT upper and lower limits */ - outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); - outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); + outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); + outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg); outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg); @@ -1065,12 +1067,12 @@ static int eepro_open(struct net_device *dev) eepro_clear_int(ioaddr); /* Initialize RCV */ - outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); + outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); lp->rx_start = lp->rcv_lower_limit; - outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP); + outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP); /* Initialize XMT */ - outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); + outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); lp->tx_start = lp->tx_end = lp->xmt_lower_limit; lp->tx_last = 0; @@ -1411,7 +1413,7 @@ set_multicast_list(struct net_device *dev) outb(0x08, ioaddr + STATUS_REG); if (i & 0x20) { /* command ABORTed */ - printk(KERN_NOTICE "%s: multicast setup failed.\n", + printk(KERN_NOTICE "%s: multicast setup failed.\n", dev->name); break; } else if ((i & 0x0f) == 0x03) { /* MC-Done */ @@ -1512,7 +1514,7 @@ hardware_send_packet(struct net_device *dev, void *buf, short length) end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */ - if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) { + if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) { /* Arrrr!!!, must keep the xmt header together, several days were lost to chase this one down. */ last = lp->xmt_lower_limit; @@ -1643,7 +1645,7 @@ eepro_rx(struct net_device *dev) else if (rcv_status & 0x0800) lp->stats.rx_crc_errors++; - printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", + printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); } @@ -1674,10 +1676,10 @@ eepro_transmit_interrupt(struct net_device *dev) { struct eepro_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; - short boguscount = 25; + short boguscount = 25; short xmt_status; - while ((lp->tx_start != lp->tx_end) && boguscount--) { + while ((lp->tx_start != lp->tx_end) && boguscount--) { outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); xmt_status = inw(ioaddr+IO_PORT); @@ -1723,7 +1725,7 @@ static int eepro_ethtool_get_settings(struct net_device *dev, { struct eepro_local *lp = (struct eepro_local *)dev->priv; - cmd->supported = SUPPORTED_10baseT_Half | + cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_Autoneg; cmd->advertising = ADVERTISED_10baseT_Half | diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index aef80f5e7c9..b886b07412a 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -704,15 +704,12 @@ static int pxa_irda_stop(struct net_device *dev) return 0; } -static int pxa_irda_suspend(struct device *_dev, pm_message_t state, u32 level) +static int pxa_irda_suspend(struct device *_dev, pm_message_t state) { struct net_device *dev = dev_get_drvdata(_dev); struct pxa_irda *si; - if (!dev || level != SUSPEND_DISABLE) - return 0; - - if (netif_running(dev)) { + if (dev && netif_running(dev)) { si = netdev_priv(dev); netif_device_detach(dev); pxa_irda_shutdown(si); @@ -721,15 +718,12 @@ static int pxa_irda_suspend(struct device *_dev, pm_message_t state, u32 level) return 0; } -static int pxa_irda_resume(struct device *_dev, u32 level) +static int pxa_irda_resume(struct device *_dev) { struct net_device *dev = dev_get_drvdata(_dev); struct pxa_irda *si; - if (!dev || level != RESUME_ENABLE) - return 0; - - if (netif_running(dev)) { + if (dev && netif_running(dev)) { si = netdev_priv(dev); pxa_irda_startup(si); netif_device_attach(dev); diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index bbac720cca6..140b7cdb1f7 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -638,21 +638,14 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self) */ static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) { - int iobase, ir_mode, ctrl, fast; - - IRDA_ASSERT(self != NULL, return;); - - iobase = self->io.fir_base; - ir_mode = IRCC_CFGA_IRDA_SIR_A; - ctrl = 0; - fast = 0; + int iobase = self->io.fir_base; register_bank(iobase, 0); outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); outb(0x00, iobase + IRCC_MASTER); register_bank(iobase, 1); - outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode), + outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | IRCC_CFGA_IRDA_SIR_A), iobase + IRCC_SCE_CFGA); #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */ @@ -666,10 +659,10 @@ static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD); register_bank(iobase, 4); - outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL); + outb((inb(iobase + IRCC_CONTROL) & 0x30), iobase + IRCC_CONTROL); register_bank(iobase, 0); - outb(fast, iobase + IRCC_LCR_A); + outb(0, iobase + IRCC_LCR_A); smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); @@ -1556,6 +1549,46 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self) } #endif /* unused */ +static int smsc_ircc_request_irq(struct smsc_ircc_cb *self) +{ + int error; + + error = request_irq(self->io.irq, smsc_ircc_interrupt, 0, + self->netdev->name, self->netdev); + if (error) + IRDA_DEBUG(0, "%s(), unable to allocate irq=%d, err=%d\n", + __FUNCTION__, self->io.irq, error); + + return error; +} + +static void smsc_ircc_start_interrupts(struct smsc_ircc_cb *self) +{ + unsigned long flags; + + spin_lock_irqsave(&self->lock, flags); + + self->io.speed = 0; + smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); + + spin_unlock_irqrestore(&self->lock, flags); +} + +static void smsc_ircc_stop_interrupts(struct smsc_ircc_cb *self) +{ + int iobase = self->io.fir_base; + unsigned long flags; + + spin_lock_irqsave(&self->lock, flags); + + register_bank(iobase, 0); + outb(0, iobase + IRCC_IER); + outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); + outb(0x00, iobase + IRCC_MASTER); + + spin_unlock_irqrestore(&self->lock, flags); +} + /* * Function smsc_ircc_net_open (dev) @@ -1567,7 +1600,6 @@ static int smsc_ircc_net_open(struct net_device *dev) { struct smsc_ircc_cb *self; char hwname[16]; - unsigned long flags; IRDA_DEBUG(1, "%s\n", __FUNCTION__); @@ -1575,6 +1607,11 @@ static int smsc_ircc_net_open(struct net_device *dev) self = netdev_priv(dev); IRDA_ASSERT(self != NULL, return 0;); + if (self->io.suspended) { + IRDA_DEBUG(0, "%s(), device is suspended\n", __FUNCTION__); + return -EAGAIN; + } + if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, (void *) dev)) { IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n", @@ -1582,11 +1619,7 @@ static int smsc_ircc_net_open(struct net_device *dev) return -EAGAIN; } - spin_lock_irqsave(&self->lock, flags); - /*smsc_ircc_sir_start(self);*/ - self->io.speed = 0; - smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); - spin_unlock_irqrestore(&self->lock, flags); + smsc_ircc_start_interrupts(self); /* Give self a hardware name */ /* It would be cool to offer the chip revision here - Jean II */ @@ -1639,7 +1672,12 @@ static int smsc_ircc_net_close(struct net_device *dev) irlap_close(self->irlap); self->irlap = NULL; - free_irq(self->io.irq, dev); + smsc_ircc_stop_interrupts(self); + + /* if we are called from smsc_ircc_resume we don't have IRQ reserved */ + if (!self->io.suspended) + free_irq(self->io.irq, dev); + disable_dma(self->io.dma); free_dma(self->io.dma); @@ -1650,11 +1688,18 @@ static int smsc_ircc_suspend(struct device *dev, pm_message_t state) { struct smsc_ircc_cb *self = dev_get_drvdata(dev); - IRDA_MESSAGE("%s, Suspending\n", driver_name); - if (!self->io.suspended) { - smsc_ircc_net_close(self->netdev); + IRDA_DEBUG(1, "%s, Suspending\n", driver_name); + + rtnl_lock(); + if (netif_running(self->netdev)) { + netif_device_detach(self->netdev); + smsc_ircc_stop_interrupts(self); + free_irq(self->io.irq, self->netdev); + disable_dma(self->io.dma); + } self->io.suspended = 1; + rtnl_unlock(); } return 0; @@ -1665,11 +1710,25 @@ static int smsc_ircc_resume(struct device *dev) struct smsc_ircc_cb *self = dev_get_drvdata(dev); if (self->io.suspended) { - - smsc_ircc_net_open(self->netdev); + IRDA_DEBUG(1, "%s, Waking up\n", driver_name); + + rtnl_lock(); + smsc_ircc_init_chip(self); + if (netif_running(self->netdev)) { + if (smsc_ircc_request_irq(self)) { + /* + * Don't fail resume process, just kill this + * network interface + */ + unregister_netdevice(self->netdev); + } else { + enable_dma(self->io.dma); + smsc_ircc_start_interrupts(self); + netif_device_attach(self->netdev); + } + } self->io.suspended = 0; - - IRDA_MESSAGE("%s, Waking up\n", driver_name); + rtnl_unlock(); } return 0; } @@ -1682,9 +1741,6 @@ static int smsc_ircc_resume(struct device *dev) */ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) { - int iobase; - unsigned long flags; - IRDA_DEBUG(1, "%s\n", __FUNCTION__); IRDA_ASSERT(self != NULL, return -1;); @@ -1694,22 +1750,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) /* Remove netdevice */ unregister_netdev(self->netdev); - /* Make sure the irq handler is not exectuting */ - spin_lock_irqsave(&self->lock, flags); - - /* Stop interrupts */ - iobase = self->io.fir_base; - register_bank(iobase, 0); - outb(0, iobase + IRCC_IER); - outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); - outb(0x00, iobase + IRCC_MASTER); -#if 0 - /* Reset to SIR mode */ - register_bank(iobase, 1); - outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase + IRCC_SCE_CFGA); - outb(IRCC_CFGB_IR, iobase + IRCC_SCE_CFGB); -#endif - spin_unlock_irqrestore(&self->lock, flags); + smsc_ircc_stop_interrupts(self); /* Release the PORTS that this driver is using */ IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c index f17c05cbe44..99a776a51fb 100644 --- a/drivers/net/skfp/smt.c +++ b/drivers/net/skfp/smt.c @@ -1896,7 +1896,7 @@ void smt_swap_para(struct smt_header *sm, int len, int direction) static void smt_string_swap(char *data, const char *format, int len) { - const char *open_paren = 0 ; + const char *open_paren = NULL ; int x ; while (len > 0 && *format) { diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index ac9ce6509ee..817f200742c 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -230,12 +230,12 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_CAN_USE_16BIT 1 #define SMC_CAN_USE_32BIT 0 -#define SMC_inb(a, r) inb((a) + (r) - 0xa0000000) -#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000) -#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000) -#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000) -#define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) -#define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) +#define SMC_inb(a, r) inb((u32)a) + (r)) +#define SMC_inw(a, r) inw(((u32)a) + (r)) +#define SMC_outb(v, a, r) outb(v, ((u32)a) + (r)) +#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r)) +#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) #define set_irq_type(irq, type) do {} while(0) diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 4937a5ad4b2..6a60c5970cb 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -137,7 +137,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev) PCI_DMA_FROMDEVICE); if (!buf->pci_addr) { printk(KERN_WARNING - "Failed to make memory DMA'able\n."); + "Failed to make memory DMA'able.\n"); return -ENOMEM; } } diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index a62a4345b46..2d4639d6841 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c @@ -39,6 +39,7 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/pci.h> +#include <linux/string.h> #include "cpci_hotplug.h" #define DRIVER_VERSION "0.1" diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index 790abadd816..f7cb00da38d 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -36,6 +36,7 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/pci.h> +#include <linux/signal.h> /* SA_SHIRQ */ #include "cpci_hotplug.h" #include "cpcihp_zt5550.h" diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 8e47fa66e25..060d74775d7 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -37,6 +37,8 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> #include "pci_hotplug.h" #include "../pci.h" diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 0392e004258..aabf1e70b52 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1077,7 +1077,7 @@ static int enable_slot(struct hotplug_slot *hs) if (rc) { err("Adding this card exceeds the limitations of this bus.\n"); err("(i.e., >1 133MHz cards running on same bus, or " - ">2 66 PCI cards running on same bus\n."); + ">2 66 PCI cards running on same bus.\n"); err("Try hot-adding into another bus\n"); rc = -EINVAL; goto error_nopower; diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 33b539b34f7..ff17d8e07e9 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -113,7 +113,7 @@ int pciehp_unconfigure_device(struct pci_func* func) */ int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) { -#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64) +#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC) int rc; u16 temp_word; struct pci_dev fakedev; diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 3622965f896..33b2c69a082 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -33,10 +33,13 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/slab.h> + #include <asm/uaccess.h> #ifdef CONFIG_IA64 #include <asm/iosapic.h> #endif + #include "pciehp.h" #include "pciehprm.h" #include "pciehprm_nonacpi.h" diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index ad1017da865..fcb66b9a0e2 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -16,10 +16,13 @@ */ #include <linux/init.h> #include <linux/pci.h> +#include <linux/string.h> + #include <asm/pci-bridge.h> #include <asm/semaphore.h> #include <asm/rtas.h> #include <asm/vio.h> + #include "../pci.h" #include "rpaphp.h" #include "rpadlpar.h" diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 46c157d26a2..f7c12d7dfcf 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -23,11 +23,13 @@ * */ #include <linux/pci.h> +#include <linux/string.h> + #include <asm/pci-bridge.h> #include <asm/rtas.h> #include <asm/machdep.h> -#include "../pci.h" /* for pci_add_new_bus */ +#include "../pci.h" /* for pci_add_new_bus */ #include "rpaphp.h" static struct pci_bus *find_bus_among_children(struct pci_bus *bus, diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 0e881549508..daa89ae5712 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -27,6 +27,9 @@ #include <linux/kobject.h> #include <linux/sysfs.h> #include <linux/pci.h> +#include <linux/string.h> +#include <linux/slab.h> + #include <asm/rtas.h> #include "rpaphp.h" diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index abe2cf411e6..08ad26a0cae 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -32,6 +32,8 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/sched.h> /* signal_pending(), struct timer_list */ + #include "pci_hotplug.h" #if !defined(MODULE) diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c index d70fe540841..c6b40998eeb 100644 --- a/drivers/pci/hotplug/shpchprm_nonacpi.c +++ b/drivers/pci/hotplug/shpchprm_nonacpi.c @@ -32,6 +32,8 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> +#include <linux/slab.h> + #include "shpchp.h" int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 8972e6a3aac..ae986e590b4 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -8,6 +8,8 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/mempolicy.h> +#include <linux/string.h> +#include <linux/slab.h> #include "pci.h" /* diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 61b855c99e3..e74d7584304 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -15,6 +15,7 @@ #include <linux/pci.h> #include <linux/module.h> #include <linux/spinlock.h> +#include <linux/string.h> #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 14f05d22bb7..467a4ceccf1 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -11,6 +11,8 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/pm.h> +#include <linux/string.h> +#include <linux/slab.h> #include <linux/pcieport_if.h> #include "portdrv.h" diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3c565ce7f77..02260141dc8 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -12,6 +12,7 @@ #include <linux/errno.h> #include <linux/pm.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/pcieport_if.h> #include "portdrv.h" diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bbd9c2323d8..5627ce1d2b3 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -356,7 +356,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int /* * PIIX4 ACPI: Two IO regions pointed to by longwords at * 0x40 (64 bytes of ACPI registers) - * 0x90 (32 bytes of SMB registers) + * 0x90 (16 bytes of SMB registers) * and a few strange programmable PIIX4 device resources. */ static void __devinit quirk_piix4_acpi(struct pci_dev *dev) @@ -366,7 +366,7 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev) pci_read_config_dword(dev, 0x40, ®ion); quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); pci_read_config_dword(dev, 0x90, ®ion); - quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); + quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); /* Device resource A has enables for some of the other ones */ pci_read_config_dword(dev, 0x5c, &res_a); diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 49bd2170231..598a115cd00 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -9,6 +9,7 @@ #include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/slab.h> #include "pci.h" diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 77ecee7f987..da7a8f2dab2 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -59,6 +59,7 @@ sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o sa1100_cs-y += sa1100_generic.o sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o +sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index a1178a600e3..bd924336a49 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -18,10 +18,15 @@ #include <linux/interrupt.h> #include <linux/device.h> +#include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/irq.h> #include <asm/hardware/scoop.h> -#include <asm/arch/pxa-regs.h> +#ifdef CONFIG_SA1100_COLLIE +#include <asm/arch-sa1100/collie.h> +#else +#include <asm/arch-pxa/pxa-regs.h> +#endif #include "soc_common.h" @@ -38,6 +43,7 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; +#ifndef CONFIG_SA1100_COLLIE /* * Setup default state of GPIO outputs * before we enable them as outputs. @@ -60,6 +66,7 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) pxa_gpio_mode(GPIO55_nPREG_MD); pxa_gpio_mode(GPIO56_nPWAIT_MD); pxa_gpio_mode(GPIO57_nIOIS16_MD); +#endif /* Register interrupts */ if (scoop_devs[skt->nr].cd_irq >= 0) { @@ -213,12 +220,20 @@ static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0); write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101); scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; + + if (machine_is_collie()) + /* We need to disable SS_OUTPUT_ENA here. */ + write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); } static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { /* CF_BUS_OFF */ sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); + + if (machine_is_collie()) + /* We need to disable SS_OUTPUT_ENA here. */ + write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); } static struct pcmcia_low_level sharpsl_pcmcia_ops = { @@ -235,6 +250,19 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = { static struct platform_device *sharpsl_pcmcia_device; +#ifdef CONFIG_SA1100_COLLIE +int __init pcmcia_collie_init(struct device *dev) +{ + int ret = -ENODEV; + + if (machine_is_collie()) + ret = sa11xx_drv_pcmcia_probe(dev, &sharpsl_pcmcia_ops, 0, 1); + + return ret; +} + +#else + static int __init sharpsl_pcmcia_init(void) { int ret; @@ -269,6 +297,7 @@ static void __exit sharpsl_pcmcia_exit(void) fs_initcall(sharpsl_pcmcia_init); module_exit(sharpsl_pcmcia_exit); +#endif MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index fc87e7e2b6b..00960a379b9 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -779,7 +779,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) if (!s->cb_dev || !s->cb_dev->bus) return -ENODEV; -#if defined(CONFIG_X86) || defined(CONFIG_X86_64) +#if defined(CONFIG_X86) /* If this is the root bus, the risk of hitting * some strange system devices which aren't protected * by either ACPI resource tables or properly requested diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index b768fa81f04..acf60ffc8a1 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -38,8 +38,12 @@ #include <pcmcia/cs.h> #include <pcmcia/ss.h> +#include <asm/hardware/scoop.h> + #include "sa1100_generic.h" +int __init pcmcia_collie_init(struct device *dev); + static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = { #ifdef CONFIG_SA1100_ASSABET pcmcia_assabet_init, @@ -56,6 +60,9 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = { #ifdef CONFIG_SA1100_SIMPAD pcmcia_simpad_init, #endif +#ifdef CONFIG_SA1100_COLLIE + pcmcia_collie_init, +#endif }; static int sa11x0_drv_pcmcia_probe(struct device *dev) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 94442ffd4ae..cbb2749db17 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -12,6 +12,8 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/pnp.h> +#include <linux/slab.h> +#include <linux/bitmap.h> #include "base.h" DECLARE_MUTEX(pnp_res_mutex); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index b0ca65b6864..5e38cd7335f 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -7,6 +7,8 @@ #include <linux/ctype.h> #include <linux/pnp.h> #include <linux/pnpbios.h> +#include <linux/string.h> +#include <linux/slab.h> #ifdef CONFIG_PCI #include <linux/pci.h> diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index fc7a213e591..c570a9f6ce9 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -213,6 +213,9 @@ con3270_update(struct con3270 *cp) struct string *s, *n; int rc; + if (cp->view.dev) + raw3270_activate_view(&cp->view); + wrq = xchg(&cp->write, 0); if (!wrq) { con3270_set_timer(cp, 1); @@ -489,8 +492,6 @@ con3270_write(struct console *co, const char *str, unsigned int count) unsigned char c; cp = condev; - if (cp->view.dev) - raw3270_activate_view(&cp->view); spin_lock_irqsave(&cp->view.lock, flags); while (count-- > 0) { c = *str++; @@ -620,7 +621,7 @@ con3270_init(void) (void (*)(unsigned long)) con3270_read_tasklet, (unsigned long) condev->read); - raw3270_add_view(&condev->view, &con3270_fn, 0); + raw3270_add_view(&condev->view, &con3270_fn, 1); INIT_LIST_HEAD(&condev->freemem); for (i = 0; i < CON3270_STRING_PAGES; i++) { diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 60afcdcf91c..735a7fcdeff 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -33,8 +33,11 @@ struct fs3270 { int read_command; /* ccw command to use for reads. */ int write_command; /* ccw command to use for writes. */ int attention; /* Got attention. */ - struct raw3270_request *clear; /* single clear request. */ - wait_queue_head_t attn_wait; /* Attention wait queue. */ + int active; /* Fullscreen view is active. */ + struct raw3270_request *init; /* single init request. */ + wait_queue_head_t wait; /* Init & attention wait queue. */ + struct idal_buffer *rdbuf; /* full-screen-deactivate buffer */ + size_t rdbuf_size; /* size of data returned by RDBUF */ }; static void @@ -43,58 +46,172 @@ fs3270_wake_up(struct raw3270_request *rq, void *data) wake_up((wait_queue_head_t *) data); } +static inline int +fs3270_working(struct fs3270 *fp) +{ + /* + * The fullscreen view is in working order if the view + * has been activated AND the initial request is finished. + */ + return fp->active && raw3270_request_final(fp->init); +} + static int fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq) { - wait_queue_head_t wq; + struct fs3270 *fp; int rc; - init_waitqueue_head(&wq); + fp = (struct fs3270 *) view; rq->callback = fs3270_wake_up; - rq->callback_data = &wq; - rc = raw3270_start(view, rq); - if (rc) - return rc; - /* Started sucessfully. Now wait for completion. */ - wait_event(wq, raw3270_request_final(rq)); - return rq->rc; + rq->callback_data = &fp->wait; + + do { + if (!fs3270_working(fp)) { + /* Fullscreen view isn't ready yet. */ + rc = wait_event_interruptible(fp->wait, + fs3270_working(fp)); + if (rc != 0) + break; + } + rc = raw3270_start(view, rq); + if (rc == 0) { + /* Started sucessfully. Now wait for completion. */ + wait_event(fp->wait, raw3270_request_final(rq)); + } + } while (rc == -EACCES); + return rc; } +/* + * Switch to the fullscreen view. + */ static void fs3270_reset_callback(struct raw3270_request *rq, void *data) { + struct fs3270 *fp; + + fp = (struct fs3270 *) rq->view; raw3270_request_reset(rq); + wake_up(&fp->wait); +} + +static void +fs3270_restore_callback(struct raw3270_request *rq, void *data) +{ + struct fs3270 *fp; + + fp = (struct fs3270 *) rq->view; + if (rq->rc != 0 || rq->rescnt != 0) { + if (fp->fs_pid) + kill_proc(fp->fs_pid, SIGHUP, 1); + } + fp->rdbuf_size = 0; + raw3270_request_reset(rq); + wake_up(&fp->wait); } -/* - * Switch to the fullscreen view. - */ static int fs3270_activate(struct raw3270_view *view) { struct fs3270 *fp; + char *cp; + int rc; fp = (struct fs3270 *) view; - raw3270_request_set_cmd(fp->clear, TC_EWRITEA); - fp->clear->callback = fs3270_reset_callback; - return raw3270_start(view, fp->clear); + + /* If an old init command is still running just return. */ + if (!raw3270_request_final(fp->init)) + return 0; + + if (fp->rdbuf_size == 0) { + /* No saved buffer. Just clear the screen. */ + raw3270_request_set_cmd(fp->init, TC_EWRITEA); + fp->init->callback = fs3270_reset_callback; + } else { + /* Restore fullscreen buffer saved by fs3270_deactivate. */ + raw3270_request_set_cmd(fp->init, TC_EWRITEA); + raw3270_request_set_idal(fp->init, fp->rdbuf); + fp->init->ccw.count = fp->rdbuf_size; + cp = fp->rdbuf->data[0]; + cp[0] = TW_KR; + cp[1] = TO_SBA; + cp[2] = cp[6]; + cp[3] = cp[7]; + cp[4] = TO_IC; + cp[5] = TO_SBA; + cp[6] = 0x40; + cp[7] = 0x40; + fp->init->rescnt = 0; + fp->init->callback = fs3270_restore_callback; + } + rc = fp->init->rc = raw3270_start_locked(view, fp->init); + if (rc) + fp->init->callback(fp->init, NULL); + else + fp->active = 1; + return rc; } /* * Shutdown fullscreen view. */ static void +fs3270_save_callback(struct raw3270_request *rq, void *data) +{ + struct fs3270 *fp; + + fp = (struct fs3270 *) rq->view; + + /* Correct idal buffer element 0 address. */ + fp->rdbuf->data[0] -= 5; + fp->rdbuf->size += 5; + + /* + * If the rdbuf command failed or the idal buffer is + * to small for the amount of data returned by the + * rdbuf command, then we have no choice but to send + * a SIGHUP to the application. + */ + if (rq->rc != 0 || rq->rescnt == 0) { + if (fp->fs_pid) + kill_proc(fp->fs_pid, SIGHUP, 1); + fp->rdbuf_size = 0; + } else + fp->rdbuf_size = fp->rdbuf->size - rq->rescnt; + raw3270_request_reset(rq); + wake_up(&fp->wait); +} + +static void fs3270_deactivate(struct raw3270_view *view) { - // FIXME: is this a good idea? The user program using fullscreen 3270 - // will die just because a console message appeared. On the other - // hand the fullscreen device is unoperational now. struct fs3270 *fp; fp = (struct fs3270 *) view; - if (fp->fs_pid != 0) - kill_proc(fp->fs_pid, SIGHUP, 1); - fp->fs_pid = 0; + fp->active = 0; + + /* If an old init command is still running just return. */ + if (!raw3270_request_final(fp->init)) + return; + + /* Prepare read-buffer request. */ + raw3270_request_set_cmd(fp->init, TC_RDBUF); + /* + * Hackish: skip first 5 bytes of the idal buffer to make + * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence + * in the activation command. + */ + fp->rdbuf->data[0] += 5; + fp->rdbuf->size -= 5; + raw3270_request_set_idal(fp->init, fp->rdbuf); + fp->init->rescnt = 0; + fp->init->callback = fs3270_save_callback; + + /* Start I/O to read in the 3270 buffer. */ + fp->init->rc = raw3270_start_locked(view, fp->init); + if (fp->init->rc) + fp->init->callback(fp->init, NULL); } static int @@ -103,7 +220,7 @@ fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb) /* Handle ATTN. Set indication and wake waiters for attention. */ if (irb->scsw.dstat & DEV_STAT_ATTENTION) { fp->attention = 1; - wake_up(&fp->attn_wait); + wake_up(&fp->wait); } if (rq) { @@ -125,7 +242,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off) struct fs3270 *fp; struct raw3270_request *rq; struct idal_buffer *ib; - int rc; + ssize_t rc; if (count == 0 || count > 65535) return -EINVAL; @@ -133,7 +250,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off) if (!fp) return -ENODEV; ib = idal_buffer_alloc(count, 0); - if (!ib) + if (IS_ERR(ib)) return -ENOMEM; rq = raw3270_request_alloc(0); if (!IS_ERR(rq)) { @@ -141,10 +258,19 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off) fp->read_command = 6; raw3270_request_set_cmd(rq, fp->read_command ? : 2); raw3270_request_set_idal(rq, ib); - wait_event(fp->attn_wait, fp->attention); - rc = fs3270_do_io(&fp->view, rq); - if (rc == 0 && idal_buffer_to_user(ib, data, count)) - rc = -EFAULT; + rc = wait_event_interruptible(fp->wait, fp->attention); + fp->attention = 0; + if (rc == 0) { + rc = fs3270_do_io(&fp->view, rq); + if (rc == 0) { + count -= rq->rescnt; + if (idal_buffer_to_user(ib, data, count) != 0) + rc = -EFAULT; + else + rc = count; + + } + } raw3270_request_free(rq); } else rc = PTR_ERR(rq); @@ -162,13 +288,13 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off) struct raw3270_request *rq; struct idal_buffer *ib; int write_command; - int rc; + ssize_t rc; fp = filp->private_data; if (!fp) return -ENODEV; ib = idal_buffer_alloc(count, 0); - if (!ib) + if (IS_ERR(ib)) return -ENOMEM; rq = raw3270_request_alloc(0); if (!IS_ERR(rq)) { @@ -179,6 +305,8 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off) raw3270_request_set_cmd(rq, write_command); raw3270_request_set_idal(rq, ib); rc = fs3270_do_io(&fp->view, rq); + if (rc == 0) + rc = count - rq->rescnt; } else rc = -EFAULT; raw3270_request_free(rq); @@ -232,7 +360,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp, } /* - * Allocate tty3270 structure. + * Allocate fs3270 structure. */ static struct fs3270 * fs3270_alloc_view(void) @@ -243,8 +371,8 @@ fs3270_alloc_view(void) if (!fp) return ERR_PTR(-ENOMEM); memset(fp, 0, sizeof(struct fs3270)); - fp->clear = raw3270_request_alloc(0); - if (!IS_ERR(fp->clear)) { + fp->init = raw3270_request_alloc(0); + if (IS_ERR(fp->init)) { kfree(fp); return ERR_PTR(-ENOMEM); } @@ -252,12 +380,17 @@ fs3270_alloc_view(void) } /* - * Free tty3270 structure. + * Free fs3270 structure. */ static void fs3270_free_view(struct raw3270_view *view) { - raw3270_request_free(((struct fs3270 *) view)->clear); + struct fs3270 *fp; + + fp = (struct fs3270 *) view; + if (fp->rdbuf) + idal_buffer_free(fp->rdbuf); + raw3270_request_free(((struct fs3270 *) view)->init); kfree(view); } @@ -285,11 +418,20 @@ static int fs3270_open(struct inode *inode, struct file *filp) { struct fs3270 *fp; + struct idal_buffer *ib; int minor, rc; if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR) return -ENODEV; minor = iminor(filp->f_dentry->d_inode); + /* Check for minor 0 multiplexer. */ + if (minor == 0) { + if (!current->signal->tty) + return -ENODEV; + if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR) + return -ENODEV; + minor = current->signal->tty->index + RAW3270_FIRSTMINOR; + } /* Check if some other program is already using fullscreen mode. */ fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); if (!IS_ERR(fp)) { @@ -301,7 +443,7 @@ fs3270_open(struct inode *inode, struct file *filp) if (IS_ERR(fp)) return PTR_ERR(fp); - init_waitqueue_head(&fp->attn_wait); + init_waitqueue_head(&fp->wait); fp->fs_pid = current->pid; rc = raw3270_add_view(&fp->view, &fs3270_fn, minor); if (rc) { @@ -309,8 +451,18 @@ fs3270_open(struct inode *inode, struct file *filp) return rc; } + /* Allocate idal-buffer. */ + ib = idal_buffer_alloc(2*fp->view.rows*fp->view.cols + 5, 0); + if (IS_ERR(ib)) { + raw3270_put_view(&fp->view); + raw3270_del_view(&fp->view); + return PTR_ERR(fp); + } + fp->rdbuf = ib; + rc = raw3270_activate_view(&fp->view); if (rc) { + raw3270_put_view(&fp->view); raw3270_del_view(&fp->view); return rc; } @@ -329,8 +481,12 @@ fs3270_close(struct inode *inode, struct file *filp) fp = filp->private_data; filp->private_data = 0; - if (fp) + if (fp) { + fp->fs_pid = 0; + raw3270_reset(&fp->view); + raw3270_put_view(&fp->view); raw3270_del_view(&fp->view); + } return 0; } diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 328d9cbc56a..d66946443df 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -25,6 +25,12 @@ #include "raw3270.h" +#include <linux/major.h> +#include <linux/kdev_t.h> +#include <linux/device.h> + +struct class *class3270; + /* The main 3270 data structure. */ struct raw3270 { struct list_head list; @@ -41,6 +47,8 @@ struct raw3270 { struct timer_list timer; /* Device timer. */ unsigned char *ascebc; /* ascii -> ebcdic table */ + struct class_device *clttydev; /* 3270-class tty device ptr */ + struct class_device *cltubdev; /* 3270-class tub device ptr */ }; /* raw3270->flags */ @@ -317,6 +325,22 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq) } int +raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq) +{ + struct raw3270 *rp; + int rc; + + rp = view->dev; + if (!rp || rp->view != view) + rc = -EACCES; + else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) + rc = -ENODEV; + else + rc = __raw3270_start(rp, view, rq); + return rc; +} + +int raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq) { struct raw3270 *rp; @@ -744,6 +768,22 @@ raw3270_reset_device(struct raw3270 *rp) return rc; } +int +raw3270_reset(struct raw3270_view *view) +{ + struct raw3270 *rp; + int rc; + + rp = view->dev; + if (!rp || rp->view != view) + rc = -EACCES; + else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) + rc = -ENODEV; + else + rc = raw3270_reset_device(view->dev); + return rc; +} + /* * Setup new 3270 device. */ @@ -774,11 +814,12 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc) /* * Add device to list and find the smallest unused minor - * number for it. + * number for it. Note: there is no device with minor 0, + * see special case for fs3270.c:fs3270_open(). */ down(&raw3270_sem); /* Keep the list sorted. */ - minor = 0; + minor = RAW3270_FIRSTMINOR; rp->minor = -1; list_for_each(l, &raw3270_devices) { tmp = list_entry(l, struct raw3270, list); @@ -789,7 +830,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc) } minor++; } - if (rp->minor == -1 && minor < RAW3270_MAXDEVS) { + if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) { rp->minor = minor; list_add_tail(&rp->list, &raw3270_devices); } @@ -941,11 +982,12 @@ raw3270_deactivate_view(struct raw3270_view *view) list_add_tail(&view->list, &rp->view_list); /* Try to activate another view. */ if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) { - list_for_each_entry(view, &rp->view_list, list) - if (view->fn->activate(view) == 0) { - rp->view = view; + list_for_each_entry(view, &rp->view_list, list) { + rp->view = view; + if (view->fn->activate(view) == 0) break; - } + rp->view = 0; + } } } spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); @@ -961,6 +1003,8 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor) struct raw3270 *rp; int rc; + if (minor <= 0) + return -ENODEV; down(&raw3270_sem); rc = -ENODEV; list_for_each_entry(rp, &raw3270_devices, list) { @@ -976,7 +1020,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor) view->cols = rp->cols; view->ascebc = rp->ascebc; spin_lock_init(&view->lock); - list_add_tail(&view->list, &rp->view_list); + list_add(&view->list, &rp->view_list); rc = 0; } spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); @@ -1039,7 +1083,7 @@ raw3270_del_view(struct raw3270_view *view) if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) { /* Try to activate another view. */ list_for_each_entry(nv, &rp->view_list, list) { - if (nv->fn->activate(view) == 0) { + if (nv->fn->activate(nv) == 0) { rp->view = nv; break; } @@ -1063,6 +1107,12 @@ raw3270_delete_device(struct raw3270 *rp) /* Remove from device chain. */ down(&raw3270_sem); + if (rp->clttydev) + class_device_destroy(class3270, + MKDEV(IBM_TTY3270_MAJOR, rp->minor)); + if (rp->cltubdev) + class_device_destroy(class3270, + MKDEV(IBM_FS3270_MAJOR, rp->minor)); list_del_init(&rp->list); up(&raw3270_sem); @@ -1129,6 +1179,16 @@ raw3270_create_attributes(struct raw3270 *rp) { //FIXME: check return code sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); + rp->clttydev = + class_device_create(class3270, + MKDEV(IBM_TTY3270_MAJOR, rp->minor), + &rp->cdev->dev, "tty%s", + rp->cdev->dev.bus_id); + rp->cltubdev = + class_device_create(class3270, + MKDEV(IBM_FS3270_MAJOR, rp->minor), + &rp->cdev->dev, "tub%s", + rp->cdev->dev.bus_id); } /* @@ -1189,13 +1249,13 @@ raw3270_set_online (struct ccw_device *cdev) return PTR_ERR(rp); rc = raw3270_reset_device(rp); if (rc) - return rc; + goto failure; rc = raw3270_size_device(rp); if (rc) - return rc; + goto failure; rc = raw3270_reset_device(rp); if (rc) - return rc; + goto failure; raw3270_create_attributes(rp); set_bit(RAW3270_FLAGS_READY, &rp->flags); down(&raw3270_sem); @@ -1203,6 +1263,10 @@ raw3270_set_online (struct ccw_device *cdev) np->notifier(rp->minor, 1); up(&raw3270_sem); return 0; + +failure: + raw3270_delete_device(rp); + return rc; } /* @@ -1217,6 +1281,14 @@ raw3270_remove (struct ccw_device *cdev) struct raw3270_notifier *np; rp = cdev->dev.driver_data; + /* + * _remove is the opposite of _probe; it's probe that + * should set up rp. raw3270_remove gets entered for + * devices even if they haven't been varied online. + * Thus, rp may validly be NULL here. + */ + if (rp == NULL) + return; clear_bit(RAW3270_FLAGS_READY, &rp->flags); sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group); @@ -1301,6 +1373,7 @@ raw3270_init(void) if (rc == 0) { /* Create attributes for early (= console) device. */ down(&raw3270_sem); + class3270 = class_create(THIS_MODULE, "3270"); list_for_each_entry(rp, &raw3270_devices, list) { get_device(&rp->cdev->dev); raw3270_create_attributes(rp); @@ -1314,6 +1387,7 @@ static void raw3270_exit(void) { ccw_driver_unregister(&raw3270_ccw_driver); + class_destroy(class3270); } MODULE_LICENSE("GPL"); @@ -1335,7 +1409,9 @@ EXPORT_SYMBOL(raw3270_find_view); EXPORT_SYMBOL(raw3270_activate_view); EXPORT_SYMBOL(raw3270_deactivate_view); EXPORT_SYMBOL(raw3270_start); +EXPORT_SYMBOL(raw3270_start_locked); EXPORT_SYMBOL(raw3270_start_irq); +EXPORT_SYMBOL(raw3270_reset); EXPORT_SYMBOL(raw3270_register_notifier); EXPORT_SYMBOL(raw3270_unregister_notifier); EXPORT_SYMBOL(raw3270_wait_queue); diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h index ed5d4eb9f62..b635bf8e777 100644 --- a/drivers/s390/char/raw3270.h +++ b/drivers/s390/char/raw3270.h @@ -21,6 +21,7 @@ /* Local Channel Commands */ #define TC_WRITE 0x01 /* Write */ +#define TC_RDBUF 0x02 /* Read Buffer */ #define TC_EWRITE 0x05 /* Erase write */ #define TC_READMOD 0x06 /* Read modified */ #define TC_EWRITEA 0x0d /* Erase write alternate */ @@ -76,7 +77,8 @@ #define TW_KR 0xc2 /* Keyboard restore */ #define TW_PLUSALARM 0x04 /* Add this bit for alarm */ -#define RAW3270_MAXDEVS 256 +#define RAW3270_FIRSTMINOR 1 /* First minor number */ +#define RAW3270_MAXDEVS 255 /* Max number of 3270 devices */ /* For TUBGETMOD and TUBSETMOD. Should include. */ struct raw3270_iocb { @@ -166,7 +168,10 @@ void raw3270_del_view(struct raw3270_view *); void raw3270_deactivate_view(struct raw3270_view *); struct raw3270_view *raw3270_find_view(struct raw3270_fn *, int); int raw3270_start(struct raw3270_view *, struct raw3270_request *); +int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *); int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *); +int raw3270_reset(struct raw3270_view *); +struct raw3270_view *raw3270_view(struct raw3270_view *); /* Reference count inliner for view structures. */ static inline void diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 7db5ebce7f0..4b906937038 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -653,18 +653,12 @@ tty3270_activate(struct raw3270_view *view) tp->update_flags = TTY_UPDATE_ALL; tty3270_set_timer(tp, 1); spin_unlock_irqrestore(&tp->view.lock, flags); - start_tty(tp->tty); return 0; } static void tty3270_deactivate(struct raw3270_view *view) { - struct tty3270 *tp; - - tp = (struct tty3270 *) view; - if (tp && tp->tty) - stop_tty(tp->tty); } static int @@ -716,13 +710,13 @@ tty3270_alloc_view(void) tp->freemem_pages[pages], PAGE_SIZE); } tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE); - if (!tp->write) + if (IS_ERR(tp->write)) goto out_pages; tp->read = raw3270_request_alloc(0); - if (!tp->read) + if (IS_ERR(tp->read)) goto out_write; tp->kreset = raw3270_request_alloc(1); - if (!tp->kreset) + if (IS_ERR(tp->kreset)) goto out_read; tp->kbd = kbd_alloc(); if (!tp->kbd) @@ -845,7 +839,8 @@ tty3270_del_views(void) int i; for (i = 0; i < tty3270_max_index; i++) { - tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, i); + tp = (struct tty3270 *) + raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR); if (!IS_ERR(tp)) raw3270_del_view(&tp->view); } @@ -871,7 +866,9 @@ tty3270_open(struct tty_struct *tty, struct file * filp) if (tty->count > 1) return 0; /* Check if the tty3270 is already there. */ - tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, tty->index); + tp = (struct tty3270 *) + raw3270_find_view(&tty3270_fn, + tty->index + RAW3270_FIRSTMINOR); if (!IS_ERR(tp)) { tty->driver_data = tp; tty->winsize.ws_row = tp->view.rows - 2; @@ -903,7 +900,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp) (void (*)(unsigned long)) tty3270_read_tasklet, (unsigned long) tp->read); - rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index); + rc = raw3270_add_view(&tp->view, &tty3270_fn, + tty->index + RAW3270_FIRSTMINOR); if (rc) { tty3270_free_view(tp); return rc; @@ -911,8 +909,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp) rc = tty3270_alloc_screen(tp); if (rc) { - raw3270_del_view(&tp->view); raw3270_put_view(&tp->view); + raw3270_del_view(&tp->view); return rc; } @@ -1780,7 +1778,7 @@ tty3270_init(void) struct tty_driver *driver; int ret; - driver = alloc_tty_driver(256); + driver = alloc_tty_driver(RAW3270_MAXDEVS); if (!driver) return -ENOMEM; @@ -1794,6 +1792,7 @@ tty3270_init(void) driver->driver_name = "ttyTUB"; driver->name = "ttyTUB"; driver->major = IBM_TTY3270_MAJOR; + driver->minor_start = RAW3270_FIRSTMINOR; driver->type = TTY_DRIVER_TYPE_SYSTEM; driver->subtype = SYSTEM_TYPE_TTY; driver->init_termios = tty_std_termios; diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 8cc4f1a940d..c05b069c299 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -30,10 +30,13 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/slab.h> +#include <linux/timex.h> /* get_clock() */ #include <asm/ccwdev.h> #include <asm/cio.h> #include <asm/cmb.h> +#include <asm/div64.h> #include "cio.h" #include "css.h" diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 9adc11e8b8b..811c9d15063 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -22,6 +22,7 @@ #include <asm/ccwdev.h> #include <asm/cio.h> +#include <asm/param.h> /* HZ */ #include "cio.h" #include "css.h" @@ -252,6 +253,23 @@ cutype_show (struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t +modalias_show (struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ccw_device *cdev = to_ccwdev(dev); + struct ccw_device_id *id = &(cdev->id); + int ret; + + ret = sprintf(buf, "ccw:t%04Xm%02x", + id->cu_type, id->cu_model); + if (id->dev_type != 0) + ret += sprintf(buf + ret, "dt%04Xdm%02X\n", + id->dev_type, id->dev_model); + else + ret += sprintf(buf + ret, "dtdm\n"); + return ret; +} + +static ssize_t online_show (struct device *dev, struct device_attribute *attr, char *buf) { struct ccw_device *cdev = to_ccwdev(dev); @@ -448,6 +466,7 @@ static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); +static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); static DEVICE_ATTR(online, 0644, online_show, online_store); extern struct device_attribute dev_attr_cmb_enable; static DEVICE_ATTR(availability, 0444, available_show, NULL); @@ -471,6 +490,7 @@ subchannel_add_files (struct device *dev) static struct attribute * ccwdev_attrs[] = { &dev_attr_devtype.attr, &dev_attr_cutype.attr, + &dev_attr_modalias.attr, &dev_attr_online.attr, &dev_attr_cmb_enable.attr, &dev_attr_availability.attr, diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index fbe4202a3f6..c1c89f4fd4e 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -11,6 +11,8 @@ #include <linux/module.h> #include <linux/config.h> #include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/string.h> #include <asm/ccwdev.h> #include <asm/cio.h> diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index fe8187d6f58..e2a5657d5fd 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -41,6 +41,7 @@ #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/dma-mapping.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -192,7 +193,6 @@ static void ahci_port_stop(struct ata_port *ap); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); -static u8 ahci_check_err(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); @@ -221,7 +221,6 @@ static const struct ata_port_operations ahci_ops = { .check_status = ahci_check_status, .check_altstatus = ahci_check_status, - .check_err = ahci_check_err, .dev_select = ata_noop_dev_select, .tf_read = ahci_tf_read, @@ -458,13 +457,6 @@ static u8 ahci_check_status(struct ata_port *ap) return readl(mmio + PORT_TFDATA) & 0xFF; } -static u8 ahci_check_err(struct ata_port *ap) -{ - void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; - - return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF; -} - static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ahci_port_priv *pp = ap->private_data; @@ -609,7 +601,7 @@ static void ahci_eng_timeout(struct ata_port *ap) * not being called from the SCSI EH. */ qc->scsidone = scsi_finish_command; - ata_qc_complete(qc, ATA_ERR); + ata_qc_complete(qc, AC_ERR_OTHER); } spin_unlock_irqrestore(&host_set->lock, flags); @@ -638,7 +630,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) if (status & PORT_IRQ_FATAL) { ahci_intr_error(ap, status); if (qc) - ata_qc_complete(qc, ATA_ERR); + ata_qc_complete(qc, AC_ERR_OTHER); } return 1; @@ -683,10 +675,10 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * if (!ahci_host_intr(ap, qc)) if (ata_ratelimit()) { struct pci_dev *pdev = - to_pci_dev(ap->host_set->dev); - printk(KERN_WARNING - "ahci(%s): unhandled interrupt on port %u\n", - pci_name(pdev), i); + to_pci_dev(ap->host_set->dev); + dev_printk(KERN_WARNING, &pdev->dev, + "unhandled interrupt on port %u\n", + i); } VPRINTK("port %u\n", i); @@ -694,10 +686,9 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * VPRINTK("port %u (no irq)\n", i); if (ata_ratelimit()) { struct pci_dev *pdev = - to_pci_dev(ap->host_set->dev); - printk(KERN_WARNING - "ahci(%s): interrupt on disabled port %u\n", - pci_name(pdev), i); + to_pci_dev(ap->host_set->dev); + dev_printk(KERN_WARNING, &pdev->dev, + "interrupt on disabled port %u\n", i); } } @@ -769,8 +760,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) tmp = readl(mmio + HOST_CTL); if (tmp & HOST_RESET) { - printk(KERN_ERR DRV_NAME "(%s): controller reset failed (0x%x)\n", - pci_name(pdev), tmp); + dev_printk(KERN_ERR, &pdev->dev, + "controller reset failed (0x%x)\n", tmp); return -EIO; } @@ -798,22 +789,22 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) if (rc) { rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME "(%s): 64-bit DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "64-bit DMA enable failed\n"); return rc; } } } else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); return rc; } rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); return rc; } } @@ -916,10 +907,10 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent) else scc_s = "unknown"; - printk(KERN_INFO DRV_NAME "(%s) AHCI %02x%02x.%02x%02x " + dev_printk(KERN_INFO, &pdev->dev, + "AHCI %02x%02x.%02x%02x " "%u slots %u ports %s Gbps 0x%x impl %s mode\n" , - pci_name(pdev), (vers >> 24) & 0xff, (vers >> 16) & 0xff, @@ -932,11 +923,11 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent) impl, scc_s); - printk(KERN_INFO DRV_NAME "(%s) flags: " + dev_printk(KERN_INFO, &pdev->dev, + "flags: " "%s%s%s%s%s%s" "%s%s%s%s%s%s%s\n" , - pci_name(pdev), cap & (1 << 31) ? "64bit " : "", cap & (1 << 30) ? "ncq " : "", @@ -969,7 +960,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) VPRINTK("ENTER\n"); if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index be021478f41..7f8aa1b552c 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -45,6 +45,7 @@ #include <linux/init.h> #include <linux/blkdev.h> #include <linux/delay.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -621,18 +622,19 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; struct ata_port_info *port_info[2]; - unsigned int combined = 0, n_ports = 1; + unsigned int combined = 0; unsigned int pata_chan = 0, sata_chan = 0; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, + "version " DRV_VERSION "\n"); /* no hotplugging support (FIXME) */ if (!in_module_init) return -ENODEV; port_info[0] = &piix_port_info[ent->driver_data]; - port_info[1] = NULL; + port_info[1] = &piix_port_info[ent->driver_data]; if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { u8 tmp; @@ -670,12 +672,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) port_info[sata_chan] = &piix_port_info[ent->driver_data]; port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS; port_info[pata_chan] = &piix_port_info[ich5_pata]; - n_ports++; - printk(KERN_WARNING DRV_NAME ": combined mode detected\n"); + dev_printk(KERN_WARNING, &pdev->dev, + "combined mode detected (p=%u, s=%u)\n", + pata_chan, sata_chan); } - return ata_pci_init_one(pdev, port_info, n_ports); + return ata_pci_init_one(pdev, port_info, 2); } static int __init piix_init(void) diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 3d62c9bcbff..00d6a6657eb 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -180,19 +180,12 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne return; } count = min(pc->sg->length - pc->b_count, bcount); - if (PageHighMem(pc->sg->page)) { - unsigned long flags; - - local_irq_save(flags); - buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset; - drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); - kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); - local_irq_restore(flags); - } else { - buf = page_address(pc->sg->page) + pc->sg->offset; - drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); - } - bcount -= count; pc->b_count += count; + buf = kmap_atomic(pc->sg->page, KM_IRQ0); + drive->hwif->atapi_input_bytes(drive, + buf + pc->b_count + pc->sg->offset, count); + kunmap_atomic(buf, KM_IRQ0); + bcount -= count; + pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; pc->b_count = 0; @@ -212,19 +205,12 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign return; } count = min(pc->sg->length - pc->b_count, bcount); - if (PageHighMem(pc->sg->page)) { - unsigned long flags; - - local_irq_save(flags); - buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset; - drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); - kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); - local_irq_restore(flags); - } else { - buf = page_address(pc->sg->page) + pc->sg->offset; - drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); - } - bcount -= count; pc->b_count += count; + buf = kmap_atomic(pc->sg->page, KM_IRQ0); + drive->hwif->atapi_output_bytes(drive, + buf + pc->b_count + pc->sg->offset, count); + kunmap_atomic(buf, KM_IRQ0); + bcount -= count; + pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; pc->b_count = 0; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5ca97605ff3..8be7dc0b47b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -372,7 +372,7 @@ static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) struct ata_ioports *ioaddr = &ap->ioaddr; tf->command = ata_check_status(ap); - tf->feature = ata_chk_err(ap); + tf->feature = inb(ioaddr->error_addr); tf->nsect = inb(ioaddr->nsect_addr); tf->lbal = inb(ioaddr->lbal_addr); tf->lbam = inb(ioaddr->lbam_addr); @@ -406,7 +406,7 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) struct ata_ioports *ioaddr = &ap->ioaddr; tf->command = ata_check_status(ap); - tf->feature = ata_chk_err(ap); + tf->feature = readb((void __iomem *)ioaddr->error_addr); tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); @@ -527,30 +527,6 @@ u8 ata_altstatus(struct ata_port *ap) /** - * ata_chk_err - Read device error reg - * @ap: port where the device is - * - * Reads ATA taskfile error register for - * currently-selected device and return its value. - * - * Note: may NOT be used as the check_err() entry in - * ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ -u8 ata_chk_err(struct ata_port *ap) -{ - if (ap->ops->check_err) - return ap->ops->check_err(ap); - - if (ap->flags & ATA_FLAG_MMIO) { - return readb((void __iomem *) ap->ioaddr.error_addr); - } - return inb(ap->ioaddr.error_addr); -} - -/** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert * @fis: Buffer into which data will output @@ -902,8 +878,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) memset(&tf, 0, sizeof(tf)); - err = ata_chk_err(ap); ap->ops->tf_read(ap, &tf); + err = tf.feature; dev->class = ATA_DEV_NONE; @@ -1140,7 +1116,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) unsigned int major_version; u16 tmp; unsigned long xfer_modes; - u8 status; unsigned int using_edd; DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; @@ -1194,8 +1169,11 @@ retry: else wait_for_completion(&wait); - status = ata_chk_status(ap); - if (status & ATA_ERR) { + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->ops->tf_read(ap, &qc->tf); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + if (qc->tf.command & ATA_ERR) { /* * arg! EDD works for all test cases, but seems to return * the ATA signature for some ATAPI devices. Until the @@ -1208,7 +1186,7 @@ retry: * to have this problem. */ if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) { - u8 err = ata_chk_err(ap); + u8 err = qc->tf.feature; if (err & ATA_ABORTED) { dev->class = ATA_DEV_ATAPI; qc->cursg = 0; @@ -2685,7 +2663,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) * None. (grabs host lock) */ -void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask) { struct ata_port *ap = qc->ap; unsigned long flags; @@ -2693,7 +2671,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) spin_lock_irqsave(&ap->host_set->lock, flags); ap->flags &= ~ATA_FLAG_NOINTR; ata_irq_on(ap); - ata_qc_complete(qc, drv_stat); + ata_qc_complete(qc, err_mask); spin_unlock_irqrestore(&ap->host_set->lock, flags); } @@ -2790,7 +2768,7 @@ static int ata_pio_complete (struct ata_port *ap) ap->hsm_task_state = HSM_ST_IDLE; - ata_poll_qc_complete(qc, drv_stat); + ata_poll_qc_complete(qc, 0); /* another command may start at this point */ @@ -3158,18 +3136,15 @@ static void ata_pio_block(struct ata_port *ap) static void ata_pio_error(struct ata_port *ap) { struct ata_queued_cmd *qc; - u8 drv_stat; + + printk(KERN_WARNING "ata%u: PIO error\n", ap->id); qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); - drv_stat = ata_chk_status(ap); - printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n", - ap->id, drv_stat); - ap->hsm_task_state = HSM_ST_IDLE; - ata_poll_qc_complete(qc, drv_stat | ATA_ERR); + ata_poll_qc_complete(qc, AC_ERR_ATA_BUS); } static void ata_pio_task(void *_data) @@ -3292,7 +3267,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ap->id, qc->tf.command, drv_stat, host_stat); /* complete taskfile transaction */ - ata_qc_complete(qc, drv_stat); + ata_qc_complete(qc, ac_err_mask(drv_stat)); break; } @@ -3397,7 +3372,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, return qc; } -int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat) +int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask) { return 0; } @@ -3456,7 +3431,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) */ -void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask) { int rc; @@ -3473,7 +3448,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) qc->flags &= ~ATA_QCFLAG_ACTIVE; /* call completion callback */ - rc = qc->complete_fn(qc, drv_stat); + rc = qc->complete_fn(qc, err_mask); /* if callback indicates not to complete command (non-zero), * return immediately @@ -3911,7 +3886,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ap->ops->irq_clear(ap); /* complete taskfile transaction */ - ata_qc_complete(qc, status); + ata_qc_complete(qc, ac_err_mask(status)); break; default: @@ -4006,7 +3981,7 @@ static void atapi_packet_task(void *_data) /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) - goto err_out; + goto err_out_status; /* make sure DRQ is set */ status = ata_chk_status(ap); @@ -4043,8 +4018,10 @@ static void atapi_packet_task(void *_data) return; +err_out_status: + status = ata_chk_status(ap); err_out: - ata_poll_qc_complete(qc, ATA_ERR); + ata_poll_qc_complete(qc, __ac_err_mask(status)); } @@ -4550,11 +4527,11 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int return probe_ent; } -static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num) +static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num) { struct ata_probe_ent *probe_ent; - probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); + probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); if (!probe_ent) return NULL; @@ -4701,9 +4678,9 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, if (legacy_mode) { if (legacy_mode & (1 << 0)) - probe_ent = ata_pci_init_legacy_port(pdev, port, 0); + probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0); if (legacy_mode & (1 << 1)) - probe_ent2 = ata_pci_init_legacy_port(pdev, port, 1); + probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1); } else { if (n_ports == 2) probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); @@ -4867,7 +4844,6 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_check_status); EXPORT_SYMBOL_GPL(ata_altstatus); -EXPORT_SYMBOL_GPL(ata_chk_err); EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 89a04b1a5a0..1e3792f86fc 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -560,7 +560,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) { + if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, &sb[1], &sb[2], &sb[3]); sb[1] &= 0x0f; @@ -635,7 +635,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) { + if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, &sb[2], &sb[12], &sb[13]); sb[2] &= 0x0f; @@ -644,7 +644,11 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) sb[0] = 0x70; sb[7] = 0x0a; - if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) { + if (tf->flags & ATA_TFLAG_LBA48) { + /* TODO: find solution for LBA48 descriptors */ + } + + else if (tf->flags & ATA_TFLAG_LBA) { /* A small (28b) LBA will fit in the 32b info field */ sb[0] |= 0x80; /* set valid bit */ sb[3] = tf->device & 0x0f; @@ -652,6 +656,10 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) sb[5] = tf->lbam; sb[6] = tf->lbal; } + + else { + /* TODO: C/H/S */ + } } /** @@ -1199,10 +1207,12 @@ nothing_to_do: return 1; } -static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, + unsigned int err_mask) { struct scsi_cmnd *cmd = qc->scsicmd; - int need_sense = drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ); + u8 *cdb = cmd->cmnd; + int need_sense = (err_mask != 0); /* For ATA pass thru (SAT) commands, generate a sense block if * user mandated it or if there's an error. Note that if we @@ -1211,8 +1221,8 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) * whether the command completed successfully or not. If there * was no error, SK, ASC and ASCQ will all be zero. */ - if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) && - ((cmd->cmnd[2] & 0x20) || need_sense)) { + if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && + ((cdb[2] & 0x20) || need_sense)) { ata_gen_ata_desc_sense(qc); } else { if (!need_sense) { @@ -1995,21 +2005,13 @@ void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, DPRINTK("EXIT\n"); } -static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask) { struct scsi_cmnd *cmd = qc->scsicmd; - VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat); - - if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ))) - /* FIXME: not quite right; we don't want the - * translation of taskfile registers into - * a sense descriptors, since that's only - * correct for ATA, not ATAPI - */ - ata_gen_ata_desc_sense(qc); + VPRINTK("ENTER, err_mask 0x%X\n", err_mask); - else if (unlikely(drv_stat & ATA_ERR)) { + if (unlikely(err_mask & AC_ERR_DEV)) { DPRINTK("request check condition\n"); /* FIXME: command completion with check condition @@ -2026,6 +2028,14 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) return 1; } + else if (unlikely(err_mask)) + /* FIXME: not quite right; we don't want the + * translation of taskfile registers into + * a sense descriptors, since that's only + * correct for ATA, not ATAPI + */ + ata_gen_ata_desc_sense(qc); + else { u8 *scsicmd = cmd->cmnd; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 65c264b9113..10ecd9e15e4 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -39,7 +39,7 @@ struct ata_scsi_args { /* libata-core.c */ extern int atapi_enabled; -extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); +extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask); extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc); diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index b235556b7b6..bdccf73cf9f 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -730,7 +730,7 @@ static void start_phase(struct mesh_state *ms) * issue a SEQ_MSGOUT to get the mesh to drop ACK. */ if ((in_8(&mr->bus_status0) & BS0_ATN) == 0) { - dlog(ms, "bus0 was %.2x explictly asserting ATN", mr->bus_status0); + dlog(ms, "bus0 was %.2x explicitly asserting ATN", mr->bus_status0); out_8(&mr->bus_status0, BS0_ATN); /* explicit ATN */ mesh_flush_io(mr); udelay(1); diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index af99feb9d23..665017eda8a 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -40,6 +40,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <asm/io.h> @@ -451,7 +452,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) struct adma_port_priv *pp; struct ata_queued_cmd *qc; void __iomem *chan = ADMA_REGS(mmio_base, port_no); - u8 drv_stat = 0, status = readb(chan + ADMA_STATUS); + u8 status = readb(chan + ADMA_STATUS); if (status == 0) continue; @@ -464,11 +465,14 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) continue; qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + unsigned int err_mask = 0; + if ((status & (aPERR | aPSD | aUIRQ))) - drv_stat = ATA_ERR; + err_mask = AC_ERR_OTHER; else if (pp->pkt[0] != cDONE) - drv_stat = ATA_ERR; - ata_qc_complete(qc, drv_stat); + err_mask = AC_ERR_OTHER; + + ata_qc_complete(qc, err_mask); } } return handled; @@ -498,7 +502,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set) /* complete taskfile transaction */ pp->state = adma_state_idle; - ata_qc_complete(qc, status); + ata_qc_complete(qc, ac_err_mask(status)); handled = 1; } } @@ -623,16 +627,14 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME - "(%s): 32-bit DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); return rc; } rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME - "(%s): 32-bit consistent DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); return rc; } return 0; @@ -648,7 +650,7 @@ static int adma_ata_init_one(struct pci_dev *pdev, int rc, port_no; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 422e0b6f603..46dbdee79f7 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -29,6 +29,7 @@ #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/dma-mapping.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -258,7 +259,6 @@ struct mv_host_priv { static void mv_irq_clear(struct ata_port *ap); static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); -static u8 mv_check_err(struct ata_port *ap); static void mv_phy_reset(struct ata_port *ap); static void mv_host_stop(struct ata_host_set *host_set); static int mv_port_start(struct ata_port *ap); @@ -296,7 +296,6 @@ static const struct ata_port_operations mv_ops = { .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, - .check_err = mv_check_err, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, @@ -1067,6 +1066,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, struct ata_queued_cmd *qc; u32 hc_irq_cause; int shift, port, port0, hard_port, handled; + unsigned int err_mask; u8 ata_status = 0; if (hc == 0) { @@ -1102,15 +1102,15 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, handled++; } + err_mask = ac_err_mask(ata_status); + shift = port << 1; /* (port * 2) */ if (port >= MV_PORTS_PER_HC) { shift++; /* skip bit 8 in the HC Main IRQ reg */ } if ((PORT0_ERR << shift) & relevant) { mv_err_intr(ap); - /* OR in ATA_ERR to ensure libata knows we took one */ - ata_status = readb((void __iomem *) - ap->ioaddr.status_addr) | ATA_ERR; + err_mask |= AC_ERR_OTHER; handled++; } @@ -1120,7 +1120,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, VPRINTK("port %u IRQ found for qc, " "ata_status 0x%x\n", port,ata_status); /* mark qc status appropriately */ - ata_qc_complete(qc, ata_status); + ata_qc_complete(qc, err_mask); } } } @@ -1185,22 +1185,6 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, } /** - * mv_check_err - Return the error shadow register to caller. - * @ap: ATA channel to manipulate - * - * Marvell requires DMA to be stopped before accessing shadow - * registers. So we do that, then return the needed register. - * - * LOCKING: - * Inherited from caller. FIXME: protect mv_stop_dma with lock? - */ -static u8 mv_check_err(struct ata_port *ap) -{ - mv_stop_dma(ap); /* can't read shadow regs if DMA on */ - return readb((void __iomem *) ap->ioaddr.error_addr); -} - -/** * mv_phy_reset - Perform eDMA reset followed by COMRESET * @ap: ATA channel to manipulate * @@ -1312,7 +1296,7 @@ static void mv_eng_timeout(struct ata_port *ap) */ spin_lock_irqsave(&ap->host_set->lock, flags); qc->scsidone = scsi_finish_command; - ata_qc_complete(qc, ATA_ERR); + ata_qc_complete(qc, AC_ERR_OTHER); spin_unlock_irqrestore(&ap->host_set->lock, flags); } } @@ -1454,9 +1438,9 @@ static void mv_print_info(struct ata_probe_ent *probe_ent) else scc_s = "unknown"; - printk(KERN_INFO DRV_NAME - "(%s) %u slots %u ports %s mode IRQ via %s\n", - pci_name(pdev), (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports, + dev_printk(KERN_INFO, &pdev->dev, + "%u slots %u ports %s mode IRQ via %s\n", + (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports, scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); } @@ -1477,9 +1461,8 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *mmio_base; int pci_dev_busy = 0, rc; - if (!printed_version++) { - printk(KERN_INFO DRV_NAME " version " DRV_VERSION "\n"); - } + if (!printed_version++) + dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) { diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 1a56d6c79dd..d573888eda7 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -61,6 +61,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -383,7 +384,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 63911f16b6e..b41c977d6fa 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -399,7 +400,8 @@ static void pdc_eng_timeout(struct ata_port *ap) case ATA_PROT_DMA: case ATA_PROT_NODATA: printk(KERN_ERR "ata%u: command timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); + drv_stat = ata_wait_idle(ap); + ata_qc_complete(qc, __ac_err_mask(drv_stat)); break; default: @@ -408,7 +410,7 @@ static void pdc_eng_timeout(struct ata_port *ap) printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", ap->id, qc->tf.command, drv_stat); - ata_qc_complete(qc, drv_stat); + ata_qc_complete(qc, ac_err_mask(drv_stat)); break; } @@ -420,24 +422,21 @@ out: static inline unsigned int pdc_host_intr( struct ata_port *ap, struct ata_queued_cmd *qc) { - u8 status; - unsigned int handled = 0, have_err = 0; + unsigned int handled = 0, err_mask = 0; u32 tmp; void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL; tmp = readl(mmio); if (tmp & PDC_ERR_MASK) { - have_err = 1; + err_mask = AC_ERR_DEV; pdc_reset_port(ap); } switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - status = ata_wait_idle(ap); - if (have_err) - status |= ATA_ERR; - ata_qc_complete(qc, status); + err_mask |= ac_err_mask(ata_wait_idle(ap)); + ata_qc_complete(qc, err_mask); handled = 1; break; @@ -635,7 +634,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e int rc; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); /* * If this driver happens to only be useful on Apple's K2, then diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 1aaf3304d39..9938dae782b 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -35,6 +35,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <asm/io.h> @@ -400,11 +401,12 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) { switch (sHST) { - case 0: /* sucessful CPB */ + case 0: /* successful CPB */ case 3: /* device error */ pp->state = qs_state_idle; qs_enter_reg_mode(qc->ap); - ata_qc_complete(qc, sDST); + ata_qc_complete(qc, + ac_err_mask(sDST)); break; default: break; @@ -441,7 +443,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) /* complete taskfile transaction */ pp->state = qs_state_idle; - ata_qc_complete(qc, status); + ata_qc_complete(qc, ac_err_mask(status)); handled = 1; } } @@ -599,25 +601,22 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) if (rc) { rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME - "(%s): 64-bit DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "64-bit DMA enable failed\n"); return rc; } } } else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME - "(%s): 32-bit DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); return rc; } rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME - "(%s): 32-bit consistent DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); return rc; } } @@ -634,7 +633,7 @@ static int qs_ata_init_one(struct pci_dev *pdev, int rc, port_no; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 3a056173fb9..435f7e0085e 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -41,6 +41,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -386,7 +387,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) u8 cls; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); /* * If this driver happens to only be useful on Apple's K2, then @@ -463,8 +464,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) writeb(cls, mmio_base + SIL_FIFO_W3); } } else - printk(KERN_WARNING DRV_NAME "(%s): cache line size not set. Driver may not function\n", - pci_name(pdev)); + dev_printk(KERN_WARNING, &pdev->dev, + "cache line size not set. Driver may not function\n"); if (ent->driver_data == sil_3114) { irq_mask = SIL_MASK_4PORT; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 51855d3bac6..c6654802565 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -35,6 +35,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> +#include <linux/device.h> #include <scsi/scsi_host.h> #include "scsi.h" #include <linux/libata.h> @@ -225,7 +226,6 @@ struct sil24_host_priv { }; static u8 sil24_check_status(struct ata_port *ap); -static u8 sil24_check_err(struct ata_port *ap); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); @@ -280,7 +280,6 @@ static const struct ata_port_operations sil24_ops = { .check_status = sil24_check_status, .check_altstatus = sil24_check_status, - .check_err = sil24_check_err, .dev_select = ata_noop_dev_select, .tf_read = sil24_tf_read, @@ -363,12 +362,6 @@ static u8 sil24_check_status(struct ata_port *ap) return pp->tf.command; } -static u8 sil24_check_err(struct ata_port *ap) -{ - struct sil24_port_priv *pp = ap->private_data; - return pp->tf.feature; -} - static int sil24_scr_map[] = { [SCR_CONTROL] = 0, [SCR_STATUS] = 1, @@ -506,7 +499,7 @@ static void sil24_eng_timeout(struct ata_port *ap) qc = ata_qc_from_tag(ap, ap->active_tag); if (!qc) { - printk(KERN_ERR "ata%u: BUG: tiemout without command\n", + printk(KERN_ERR "ata%u: BUG: timeout without command\n", ap->id); return; } @@ -520,7 +513,7 @@ static void sil24_eng_timeout(struct ata_port *ap) */ printk(KERN_ERR "ata%u: command timeout\n", ap->id); qc->scsidone = scsi_finish_command; - ata_qc_complete(qc, ATA_ERR); + ata_qc_complete(qc, AC_ERR_OTHER); sil24_reset_controller(ap); } @@ -531,6 +524,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) struct sil24_port_priv *pp = ap->private_data; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; u32 irq_stat, cmd_err, sstatus, serror; + unsigned int err_mask; irq_stat = readl(port + PORT_IRQ_STAT); writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ @@ -558,17 +552,18 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) * Device is reporting error, tf registers are valid. */ sil24_update_tf(ap); + err_mask = ac_err_mask(pp->tf.command); } else { /* * Other errors. libata currently doesn't have any * mechanism to report these errors. Just turn on * ATA_ERR. */ - pp->tf.command = ATA_ERR; + err_mask = AC_ERR_OTHER; } if (qc) - ata_qc_complete(qc, pp->tf.command); + ata_qc_complete(qc, err_mask); sil24_reset_controller(ap); } @@ -593,7 +588,7 @@ static inline void sil24_host_intr(struct ata_port *ap) sil24_update_tf(ap); if (qc) - ata_qc_complete(qc, pp->tf.command); + ata_qc_complete(qc, ac_err_mask(pp->tf.command)); } else sil24_error_intr(ap, slot_stat); } @@ -696,7 +691,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int i, rc; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) @@ -756,14 +751,14 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) */ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); goto out_free; } rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { - printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); goto out_free; } @@ -799,9 +794,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) break; } if (tmp & PORT_CS_PORT_RST) - printk(KERN_ERR DRV_NAME - "(%s): failed to clear port RST\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "failed to clear port RST\n"); } /* Zero error counters. */ @@ -830,9 +824,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Reset itself */ if (__sil24_reset_controller(port)) - printk(KERN_ERR DRV_NAME - "(%s): failed to reset controller\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, + "failed to reset controller\n"); } /* Turn on interrupts */ diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 057f7b98b6c..42288be0e56 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -38,6 +38,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -237,6 +238,7 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { + static int printed_version; struct ata_probe_ent *probe_ent = NULL; int rc; u32 genctl; @@ -245,6 +247,9 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) u8 pmr; u8 port2_start; + if (!printed_version++) + dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); + rc = pci_enable_device(pdev); if (rc) return rc; @@ -288,16 +293,18 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) pci_read_config_byte(pdev, SIS_PMR, &pmr); if (ent->device != 0x182) { if ((pmr & SIS_PMR_COMBINED) == 0) { - printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 180/181 chipset in SATA mode\n"); port2_start = 64; } else { - printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 180/181 chipset in combined mode\n"); port2_start=0; } } else { - printk(KERN_INFO "sata_sis: Detected SiS 182 chipset\n"); + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n"); port2_start = 0x20; } diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 46208f52d0e..db615ff794d 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -44,6 +44,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -362,7 +363,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e int i; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); /* * If this driver happens to only be useful on Apple's K2, then diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index af08f4f650c..0ec21e09f5d 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -718,7 +719,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap)); + ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap))); pdc20621_pop_hdma(qc); } @@ -756,7 +757,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap)); + ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap))); pdc20621_pop_hdma(qc); } handled = 1; @@ -766,7 +767,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); - ata_qc_complete(qc, status); + ata_qc_complete(qc, ac_err_mask(status)); handled = 1; } else { @@ -881,7 +882,7 @@ static void pdc_eng_timeout(struct ata_port *ap) case ATA_PROT_DMA: case ATA_PROT_NODATA: printk(KERN_ERR "ata%u: command timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); + ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap))); break; default: @@ -890,7 +891,7 @@ static void pdc_eng_timeout(struct ata_port *ap) printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", ap->id, qc->tf.command, drv_stat); - ata_qc_complete(qc, drv_stat); + ata_qc_complete(qc, ac_err_mask(drv_stat)); break; } @@ -1385,7 +1386,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * int rc; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); /* * If this driver happens to only be useful on Apple's K2, then diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index d68dc7d3422..a5e245c098e 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -32,6 +32,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -178,12 +179,16 @@ static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { + static int printed_version; struct ata_probe_ent *probe_ent; struct ata_port_info *ppi; int rc; unsigned int board_idx = (unsigned int) ent->driver_data; int pci_dev_busy = 0; + if (!printed_version++) + dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); + rc = pci_enable_device(pdev); if (rc) return rc; diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 80e291a909a..b3ecdbe400e 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -41,6 +41,7 @@ #include <linux/init.h> #include <linux/blkdev.h> #include <linux/delay.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -259,15 +260,15 @@ static void svia_configure(struct pci_dev *pdev) u8 tmp8; pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8); - printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n", - pci_name(pdev), + dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n", (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f); /* make sure SATA channels are enabled */ pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8); if ((tmp8 & ALL_PORTS) != ALL_PORTS) { - printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n", - pci_name(pdev), (int) tmp8); + dev_printk(KERN_DEBUG, &pdev->dev, + "enabling SATA channels (0x%x)\n", + (int) tmp8); tmp8 |= ALL_PORTS; pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); } @@ -275,8 +276,9 @@ static void svia_configure(struct pci_dev *pdev) /* make sure interrupts for each channel sent to us */ pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8); if ((tmp8 & ALL_PORTS) != ALL_PORTS) { - printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n", - pci_name(pdev), (int) tmp8); + dev_printk(KERN_DEBUG, &pdev->dev, + "enabling SATA channel interrupts (0x%x)\n", + (int) tmp8); tmp8 |= ALL_PORTS; pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); } @@ -284,8 +286,9 @@ static void svia_configure(struct pci_dev *pdev) /* make sure native mode is enabled */ pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8); if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { - printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n", - pci_name(pdev), (int) tmp8); + dev_printk(KERN_DEBUG, &pdev->dev, + "enabling SATA channel native mode (0x%x)\n", + (int) tmp8); tmp8 |= NATIVE_MODE_ALL; pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); } @@ -303,7 +306,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) u8 tmp8; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) @@ -318,8 +321,9 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (board_id == vt6420) { pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); if (tmp8 & SATA_2DEV) { - printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n", - pci_name(pdev), (int) tmp8); + dev_printk(KERN_ERR, &pdev->dev, + "SATA master/slave not supported (0x%x)\n", + (int) tmp8); rc = -EIO; goto err_out_regions; } @@ -332,10 +336,11 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) if ((pci_resource_start(pdev, i) == 0) || (pci_resource_len(pdev, i) < bar_sizes[i])) { - printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n", - pci_name(pdev), i, - pci_resource_start(pdev, i), - pci_resource_len(pdev, i)); + dev_printk(KERN_ERR, &pdev->dev, + "invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n", + i, + pci_resource_start(pdev, i), + pci_resource_len(pdev, i)); rc = -ENODEV; goto err_out_regions; } @@ -353,8 +358,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent = vt6421_init_probe_ent(pdev); if (!probe_ent) { - printk(KERN_ERR DRV_NAME "(%s): out of memory\n", - pci_name(pdev)); + dev_printk(KERN_ERR, &pdev->dev, "out of memory\n"); rc = -ENOMEM; goto err_out_regions; } diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 54273e0063c..bb84ba0c7e8 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -42,6 +42,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> +#include <linux/device.h> #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -295,7 +296,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d int rc; if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); if (rc) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 771e97ef136..b856e140e65 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -26,6 +26,7 @@ */ #include <linux/module.h> #include <linux/init.h> +#include <linux/sched.h> /* workqueue stuff, HZ */ #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_transport.h> diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 8bb8222ea58..d2caa35059d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -19,6 +19,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/module.h> +#include <linux/string.h> +#include <linux/slab.h> + #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index e753ba27dc5..a1a58e1d5ad 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -37,6 +37,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <linux/slab.h> + #include "sym_glue.h" #include "sym_nvram.h" diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 3131a6bf7ab..3a264a40821 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -37,6 +37,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/gfp.h> + #ifndef SYM_HIPD_H #define SYM_HIPD_H diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index f88fdd48068..771676abee6 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -308,6 +308,8 @@ struct ioc4_serial { typedef void ioc4_intr_func_f(void *, uint32_t); typedef ioc4_intr_func_f *ioc4_intr_func_t; +static unsigned int Num_of_ioc4_cards; + /* defining this will get you LOTS of great debug info */ //#define DEBUG_INTERRUPTS #define DPRINT_CONFIG(_x...) ; @@ -317,7 +319,8 @@ typedef ioc4_intr_func_f *ioc4_intr_func_t; #define WAKEUP_CHARS 256 /* number of characters we want to transmit to the lower level at a time */ -#define IOC4_MAX_CHARS 128 +#define IOC4_MAX_CHARS 256 +#define IOC4_FIFO_CHARS 255 /* Device name we're using */ #define DEVICE_NAME "ttyIOC" @@ -1038,6 +1041,7 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd) return -ENOMEM; } memset(port, 0, sizeof(struct ioc4_port)); + spin_lock_init(&port->ip_lock); /* we need to remember the previous ones, to point back to * them farther down - setting up the ring buffers. @@ -1691,12 +1695,14 @@ ioc4_change_speed(struct uart_port *the_port, baud = 9600; if (!the_port->fifosize) - the_port->fifosize = IOC4_MAX_CHARS; + the_port->fifosize = IOC4_FIFO_CHARS; the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10)); the_port->timeout += HZ / 50; /* Add .02 seconds of slop */ the_port->ignore_status_mask = N_ALL_INPUT; + info->tty->low_latency = 1; + if (I_IGNPAR(info->tty)) the_port->ignore_status_mask &= ~(N_PARITY_ERROR | N_FRAMING_ERROR); @@ -1742,7 +1748,6 @@ ioc4_change_speed(struct uart_port *the_port, */ static inline int ic4_startup_local(struct uart_port *the_port) { - int retval = 0; struct ioc4_port *port; struct uart_info *info; @@ -1754,9 +1759,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) return -1; info = the_port->info; - if (info->flags & UIF_INITIALIZED) { - return retval; - } if (info->tty) { set_bit(TTY_IO_ERROR, &info->tty->flags); @@ -1775,7 +1777,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) /* set the speed of the serial port */ ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); - info->flags |= UIF_INITIALIZED; return 0; } @@ -1785,9 +1786,13 @@ static inline int ic4_startup_local(struct uart_port *the_port) */ static void ioc4_cb_output_lowat(struct ioc4_port *port) { + unsigned long pflags; + /* ip_lock is set on the call here */ if (port->ip_port) { + spin_lock_irqsave(&port->ip_port->lock, pflags); transmit_chars(port->ip_port); + spin_unlock_irqrestore(&port->ip_port->lock, pflags); } } @@ -2064,8 +2069,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, * available data as long as it returns some. */ /* Re-arm the timer */ - writel(port->ip_rx_cons | IOC4_SRCIR_ARM, - &port->ip_serial_regs->srcir); + writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir); prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; cons_ptr = port->ip_rx_cons; @@ -2299,6 +2303,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, } return total; } + /** * receive_chars - upper level read. Called with ip_lock. * @the_port: port to read from @@ -2307,9 +2312,11 @@ static void receive_chars(struct uart_port *the_port) { struct tty_struct *tty; unsigned char ch[IOC4_MAX_CHARS]; - int read_count, request_count; + int read_count, request_count = IOC4_MAX_CHARS; struct uart_icount *icount; struct uart_info *info = the_port->info; + int flip = 0; + unsigned long pflags; /* Make sure all the pointers are "good" ones */ if (!info) @@ -2317,16 +2324,17 @@ static void receive_chars(struct uart_port *the_port) if (!info->tty) return; + spin_lock_irqsave(&the_port->lock, pflags); tty = info->tty; - request_count = TTY_FLIPBUF_SIZE - tty->flip.count - 1; + if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count) + request_count = TTY_FLIPBUF_SIZE - tty->flip.count; if (request_count > 0) { - if (request_count > IOC4_MAX_CHARS - 2) - request_count = IOC4_MAX_CHARS - 2; icount = &the_port->icount; read_count = do_read(the_port, ch, request_count); if (read_count > 0) { + flip = 1; memcpy(tty->flip.char_buf_ptr, ch, read_count); memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count); tty->flip.char_buf_ptr += read_count; @@ -2335,7 +2343,11 @@ static void receive_chars(struct uart_port *the_port) icount->rx += read_count; } } - tty_flip_buffer_push(tty); + + spin_unlock_irqrestore(&the_port->lock, pflags); + + if (flip) + tty_flip_buffer_push(tty); } /** @@ -2393,18 +2405,14 @@ static void ic4_shutdown(struct uart_port *the_port) info = the_port->info; - if (!(info->flags & UIF_INITIALIZED)) - return; - wake_up_interruptible(&info->delta_msr_wait); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - spin_lock_irqsave(&port->ip_lock, port_flags); + spin_lock_irqsave(&the_port->lock, port_flags); set_notification(port, N_ALL, 0); - info->flags &= ~UIF_INITIALIZED; - spin_unlock_irqrestore(&port->ip_lock, port_flags); + spin_unlock_irqrestore(&the_port->lock, port_flags); } /** @@ -2463,12 +2471,10 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) static void ic4_start_tx(struct uart_port *the_port) { struct ioc4_port *port = get_ioc4_port(the_port); - unsigned long flags; if (port) { - spin_lock_irqsave(&port->ip_lock, flags); - transmit_chars(the_port); - spin_unlock_irqrestore(&port->ip_lock, flags); + set_notification(port, N_OUTPUT_LOWAT, 1); + enable_intrs(port, port->ip_hooks->intr_tx_mt); } } @@ -2510,9 +2516,9 @@ static int ic4_startup(struct uart_port *the_port) } /* Start up the serial port */ - spin_lock_irqsave(&port->ip_lock, port_flags); + spin_lock_irqsave(&the_port->lock, port_flags); retval = ic4_startup_local(the_port); - spin_unlock_irqrestore(&port->ip_lock, port_flags); + spin_unlock_irqrestore(&the_port->lock, port_flags); return retval; } @@ -2527,12 +2533,11 @@ static void ic4_set_termios(struct uart_port *the_port, struct termios *termios, struct termios *old_termios) { - struct ioc4_port *port = get_ioc4_port(the_port); unsigned long port_flags; - spin_lock_irqsave(&port->ip_lock, port_flags); + spin_lock_irqsave(&the_port->lock, port_flags); ioc4_change_speed(the_port, termios, old_termios); - spin_unlock_irqrestore(&port->ip_lock, port_flags); + spin_unlock_irqrestore(&the_port->lock, port_flags); } /** @@ -2607,24 +2612,25 @@ ioc4_serial_core_attach(struct pci_dev *pdev) __FUNCTION__, (void *)the_port, (void *)port)); - spin_lock_init(&the_port->lock); /* membase, iobase and mapbase just need to be non-0 */ the_port->membase = (unsigned char __iomem *)1; - the_port->line = the_port->iobase = ii; + the_port->iobase = (pdev->bus->number << 16) | ii; + the_port->line = (Num_of_ioc4_cards << 2) | ii; the_port->mapbase = 1; the_port->type = PORT_16550A; - the_port->fifosize = IOC4_MAX_CHARS; + the_port->fifosize = IOC4_FIFO_CHARS; the_port->ops = &ioc4_ops; the_port->irq = control->ic_irq; the_port->dev = &pdev->dev; + spin_lock_init(&the_port->lock); if (uart_add_one_port(&ioc4_uart, the_port) < 0) { printk(KERN_WARNING - "%s: unable to add port %d\n", - __FUNCTION__, the_port->line); + "%s: unable to add port %d bus %d\n", + __FUNCTION__, the_port->line, pdev->bus->number); } else { DPRINT_CONFIG( - ("IOC4 serial driver port %d irq = %d\n", - the_port->line, the_port->irq)); + ("IOC4 serial port %d irq = %d, bus %d\n", + the_port->line, the_port->irq, pdev->bus->number)); } /* all ports are rs232 for now */ ioc4_set_proto(port, PROTO_RS232); @@ -2734,6 +2740,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) goto out4; + Num_of_ioc4_cards++; + return ret; /* error exits that give back resources */ diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index efe79b1fd43..aec83f577ce 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1100,6 +1100,8 @@ mpsc_start_rx(struct mpsc_port_info *pi) { pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line); + /* Issue a Receive Abort to clear any receive errors */ + writel(MPSC_CHR_2_RA, pi->mpsc_base + MPSC_CHR_2); if (pi->rcv_data) { mpsc_enter_hunt(pi); mpsc_sdma_cmd(pi, SDMA_SDCM_ERD); diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index f056276b08a..28757cb9d24 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -16,6 +16,8 @@ #include <linux/types.h> #include <linux/list.h> #include <linux/superhyway.h> +#include <linux/string.h> +#include <linux/slab.h> static int superhyway_devices; diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 45efeed1fcc..49815ec4b84 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -14,6 +14,9 @@ * This file is licenced under the GPL. */ +#include <linux/signal.h> /* SA_INTERRUPT */ +#include <linux/jiffies.h> + #include <asm/hardware.h> #include <asm/io.h> #include <asm/mach-types.h> diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index bf1d5ab4aa3..7ce1d9ef028 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -14,6 +14,8 @@ * This file is licenced under the GPL. */ +#include <linux/jiffies.h> + #ifdef CONFIG_PPC_PMAC #include <asm/machdep.h> #include <asm/pmac_feature.h> diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index d287dcccd41..f4a4aeda40b 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -20,6 +20,7 @@ */ #include <linux/device.h> +#include <linux/signal.h> #include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index a00672c9664..dca5ee93a4e 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c @@ -198,7 +198,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, } effect->id = id; - dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id); + dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d.\n", id); pid_private->effects[id].owner = current->pid; pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED); spin_unlock_irqrestore(&pid_private->lock, flags); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7e297947a2b..7192b770bfb 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -494,7 +494,7 @@ config FB_TGA config FB_VESA bool "VESA VGA graphics support" - depends on (FB = y) && (X86 || X86_64) + depends on (FB = y) && X86 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -712,7 +712,7 @@ config FB_RIVA_DEBUG config FB_I810 tristate "Intel 810/815 support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64 + depends on FB && EXPERIMENTAL && PCI && X86_32 select AGP select AGP_INTEL select FB_MODE_HELPERS @@ -761,7 +761,7 @@ config FB_I810_I2C config FB_INTEL tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64 + depends on FB && EXPERIMENTAL && PCI && X86_32 select AGP select AGP_INTEL select FB_MODE_HELPERS diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 7e731691e2a..6a9ae2b3d1a 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -28,7 +28,7 @@ config VGA_CONSOLE config VIDEO_SELECT bool "Video mode selection support" - depends on (X86 || X86_64) && VGA_CONSOLE + depends on X86 && VGA_CONSOLE ---help--- This enables support for text mode selection on kernel startup. If you want to take advantage of some high-resolution text mode your diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 809fee2140a..56cd199605f 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -579,6 +579,7 @@ static void vga_set_palette(struct vc_data *vc, unsigned char *table) { int i, j; + vga_w(state.vgabase, VGA_PEL_MSK, 0xff); for (i = j = 0; i < 16; i++) { vga_w(state.vgabase, VGA_PEL_IW, table[i]); vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); @@ -721,6 +722,7 @@ static void vga_pal_blank(struct vgastate *state) { int i; + vga_w(state->vgabase, VGA_PEL_MSK, 0xff); for (i = 0; i < 16; i++) { vga_w(state->vgabase, VGA_PEL_IW, i); vga_w(state->vgabase, VGA_PEL_D, 0); diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c index 88c517a4c17..9e293e139a0 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c @@ -21,6 +21,7 @@ #include <linux/spinlock.h> #include <linux/list.h> +#include <linux/sched.h> /* schedule_timeout() */ #include <linux/delay.h> #include "w1_family.h" diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 04ca8840acf..87c29d7b6c1 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/zorro.h> #include <linux/stat.h> +#include <linux/string.h> #include "zorro.h" diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index d3c05dfe20d..0f2b40605b0 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -16,6 +16,8 @@ #include <linux/init.h> #include <linux/zorro.h> #include <linux/bitops.h> +#include <linux/string.h> + #include <asm/setup.h> #include <asm/amigahw.h> diff --git a/fs/Kconfig b/fs/Kconfig index 48f5422cb19..01a295232f7 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -810,7 +810,7 @@ config TMPFS config HUGETLBFS bool "HugeTLB file system support" - depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN + depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN config HUGETLB_PAGE def_bool HUGETLBFS diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 434c19d076a..175b2e8177c 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -57,7 +57,7 @@ config BINFMT_SHARED_FLAT config BINFMT_AOUT tristate "Kernel support for a.out and ECOFF binaries" - depends on (X86 && !X86_64) || ALPHA || ARM || M68K || SPARC32 + depends on X86_32 || ALPHA || ARM || M68K || SPARC32 ---help--- A.out (Assembler.OUTput) is a set of formats for libraries and executables used in the earliest versions of UNIX. Linux used diff --git a/fs/attr.c b/fs/attr.c index b1796fb9e52..67bcd9b14ea 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -117,9 +117,6 @@ int notify_change(struct dentry * dentry, struct iattr * attr) struct timespec now; unsigned int ia_valid = attr->ia_valid; - if (!inode) - BUG(); - mode = inode->i_mode; now = current_fs_time(inode->i_sb); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 918ccc267e4..6fa6adc4097 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1502,9 +1502,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) fill_psinfo(psinfo, current->group_leader, current->mm); fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); - fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current); - - numnote = 3; + numnote = 2; auxv = (elf_addr_t *) current->mm->saved_auxv; diff --git a/fs/buffer.c b/fs/buffer.c index 2066e4cb700..35fa34977e8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1478,8 +1478,10 @@ EXPORT_SYMBOL(__getblk); void __breadahead(struct block_device *bdev, sector_t block, int size) { struct buffer_head *bh = __getblk(bdev, block, size); - ll_rw_block(READA, 1, &bh); - brelse(bh); + if (likely(bh)) { + ll_rw_block(READA, 1, &bh); + brelse(bh); + } } EXPORT_SYMBOL(__breadahead); @@ -1497,7 +1499,7 @@ __bread(struct block_device *bdev, sector_t block, int size) { struct buffer_head *bh = __getblk(bdev, block, size); - if (!buffer_uptodate(bh)) + if (likely(bh) && !buffer_uptodate(bh)) bh = __bread_slow(bh); return bh; } @@ -1637,6 +1639,15 @@ out: } EXPORT_SYMBOL(block_invalidatepage); +int do_invalidatepage(struct page *page, unsigned long offset) +{ + int (*invalidatepage)(struct page *, unsigned long); + invalidatepage = page->mapping->a_ops->invalidatepage; + if (invalidatepage == NULL) + invalidatepage = block_invalidatepage; + return (*invalidatepage)(page, offset); +} + /* * We attach and possibly dirty the buffers atomically wrt * __set_page_dirty_buffers() via private_lock. try_to_free_buffers @@ -2696,7 +2707,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block, * they may have been added in ext3_writepage(). Make them * freeable here, so the page does not leak. */ - block_invalidatepage(page, 0); + do_invalidatepage(page, 0); unlock_page(page); return 0; /* don't care */ } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a327e03753a..43dbcb0b21e 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -3046,6 +3046,10 @@ HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) /* Serial */ HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) +#ifdef TIOCGLTC +COMPATIBLE_IOCTL(TIOCGLTC) +COMPATIBLE_IOCTL(TIOCSLTC) +#endif /* Usbdevfs */ HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) diff --git a/fs/dquot.c b/fs/dquot.c index 05f3327d64a..ea7644227a6 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -662,7 +662,7 @@ static void add_dquot_ref(struct super_block *sb, int type) restart: file_list_lock(); list_for_each(p, &sb->s_files) { - struct file *filp = list_entry(p, struct file, f_list); + struct file *filp = list_entry(p, struct file, f_u.fu_list); struct inode *inode = filp->f_dentry->d_inode; if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { struct dentry *dentry = dget(filp->f_dentry); diff --git a/fs/exec.c b/fs/exec.c index ba73797eb4c..10d493fea7c 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -630,10 +630,9 @@ static inline int de_thread(struct task_struct *tsk) /* * Account for the thread group leader hanging around: */ - count = 2; - if (thread_group_leader(current)) - count = 1; - else { + count = 1; + if (!thread_group_leader(current)) { + count = 2; /* * The SIGALRM timer survives the exec, but needs to point * at us as the new group leader now. We have a race with @@ -642,8 +641,10 @@ static inline int de_thread(struct task_struct *tsk) * before we can safely let the old group leader die. */ sig->real_timer.data = (unsigned long)current; + spin_unlock_irq(lock); if (del_timer_sync(&sig->real_timer)) add_timer(&sig->real_timer); + spin_lock_irq(lock); } while (atomic_read(&sig->count) > count) { sig->group_exit_task = current; @@ -655,7 +656,6 @@ static inline int de_thread(struct task_struct *tsk) } sig->group_exit_task = NULL; sig->notify_count = 0; - sig->real_timer.data = (unsigned long)current; spin_unlock_irq(lock); /* @@ -1417,19 +1417,16 @@ static void zap_threads (struct mm_struct *mm) static void coredump_wait(struct mm_struct *mm) { DECLARE_COMPLETION(startup_done); + int core_waiters; - mm->core_waiters++; /* let other threads block */ mm->core_startup_done = &startup_done; - /* give other threads a chance to run: */ - yield(); - zap_threads(mm); - if (--mm->core_waiters) { - up_write(&mm->mmap_sem); + core_waiters = mm->core_waiters; + up_write(&mm->mmap_sem); + + if (core_waiters) wait_for_completion(&startup_done); - } else - up_write(&mm->mmap_sem); BUG_ON(mm->core_waiters); } @@ -1463,11 +1460,21 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) current->fsuid = 0; /* Dump root private */ } mm->dumpable = 0; - init_completion(&mm->core_done); + + retval = -EAGAIN; spin_lock_irq(¤t->sighand->siglock); - current->signal->flags = SIGNAL_GROUP_EXIT; - current->signal->group_exit_code = exit_code; + if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { + current->signal->flags = SIGNAL_GROUP_EXIT; + current->signal->group_exit_code = exit_code; + retval = 0; + } spin_unlock_irq(¤t->sighand->siglock); + if (retval) { + up_write(&mm->mmap_sem); + goto fail; + } + + init_completion(&mm->core_done); coredump_wait(mm); /* diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index fdba4d1d3c6..e7d3f0522d0 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -440,6 +440,10 @@ static int ext2_alloc_branch(struct inode *inode, * the pointer to new one, then send parent to disk. */ bh = sb_getblk(inode->i_sb, parent); + if (!bh) { + err = -EIO; + break; + } lock_buffer(bh); memset(bh->b_data, 0, blocksize); branch[n].bh = bh; diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 0213db4911a..7992d21e0e0 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -20,6 +20,8 @@ #include <linux/quotaops.h> #include <linux/buffer_head.h> +#include "bitmap.h" + /* * balloc.c contains the blocks allocation and deallocation routines */ @@ -1010,7 +1012,7 @@ retry: * allocation within the reservation window. * * This will avoid keeping on searching the reservation list again and - * again when someboday is looking for a free block (without + * again when somebody is looking for a free block (without * reservation), and there are lots of free blocks, but they are all * being reserved. * @@ -1416,12 +1418,12 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) unsigned long bitmap_count, x; struct buffer_head *bitmap_bh = NULL; - lock_super(sb); es = EXT3_SB(sb)->s_es; desc_count = 0; bitmap_count = 0; gdp = NULL; + smp_rmb(); for (i = 0; i < ngroups; i++) { gdp = ext3_get_group_desc(sb, i, NULL); if (!gdp) @@ -1440,7 +1442,6 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) brelse(bitmap_bh); printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n", le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); - unlock_super(sb); return bitmap_count; #else desc_count = 0; diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c index 6c419b9ab0e..5b4ba3e246e 100644 --- a/fs/ext3/bitmap.c +++ b/fs/ext3/bitmap.c @@ -8,7 +8,7 @@ */ #include <linux/buffer_head.h> - +#include "bitmap.h" static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; diff --git a/fs/ext3/bitmap.h b/fs/ext3/bitmap.h new file mode 100644 index 00000000000..6ee503a6bb4 --- /dev/null +++ b/fs/ext3/bitmap.h @@ -0,0 +1,8 @@ +/* linux/fs/ext3/bitmap.c + * + * Copyright (C) 2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * +*/ + +extern unsigned long ext3_count_free (struct buffer_head *, unsigned int ); diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 6549945f9ac..df3f517c54a 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -26,6 +26,7 @@ #include <asm/byteorder.h> +#include "bitmap.h" #include "xattr.h" #include "acl.h" @@ -704,7 +705,6 @@ unsigned long ext3_count_free_inodes (struct super_block * sb) unsigned long bitmap_count, x; struct buffer_head *bitmap_bh = NULL; - lock_super (sb); es = EXT3_SB(sb)->s_es; desc_count = 0; bitmap_count = 0; @@ -727,7 +727,6 @@ unsigned long ext3_count_free_inodes (struct super_block * sb) brelse(bitmap_bh); printk("ext3_count_free_inodes: stored = %u, computed = %lu, %lu\n", le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count); - unlock_super(sb); return desc_count; #else desc_count = 0; diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 8b38f223279..5d9b00e2883 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -491,7 +491,7 @@ static unsigned long ext3_find_goal(struct inode *inode, long block, * the same format as ext3_get_branch() would do. We are calling it after * we had read the existing part of chain and partial points to the last * triple of that (one with zero ->key). Upon the exit we have the same - * picture as after the successful ext3_get_block(), excpet that in one + * picture as after the successful ext3_get_block(), except that in one * place chain is disconnected - *branch->p is still zero (we did not * set the last link), but branch->key contains the number that should * be placed into *branch->p to fill that gap. @@ -523,7 +523,6 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode, if (!nr) break; branch[n].key = cpu_to_le32(nr); - keys = n+1; /* * Get buffer_head for parent block, zero it out @@ -531,6 +530,9 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode, * parent to disk. */ bh = sb_getblk(inode->i_sb, parent); + if (!bh) + break; + keys = n+1; branch[n].bh = bh; lock_buffer(bh); BUFFER_TRACE(bh, "call get_create_access"); @@ -864,6 +866,10 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode, if (!*errp && buffer_mapped(&dummy)) { struct buffer_head *bh; bh = sb_getblk(inode->i_sb, dummy.b_blocknr); + if (!bh) { + *errp = -EIO; + goto err; + } if (buffer_new(&dummy)) { J_ASSERT(create != 0); J_ASSERT(handle != 0); @@ -896,6 +902,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode, } return bh; } +err: return NULL; } diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 50378d8ff84..b3c690a3b54 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -36,6 +36,8 @@ #include <linux/quotaops.h> #include <linux/buffer_head.h> #include <linux/smp_lock.h> + +#include "namei.h" #include "xattr.h" #include "acl.h" diff --git a/fs/ext3/namei.h b/fs/ext3/namei.h new file mode 100644 index 00000000000..f2ce2b0065c --- /dev/null +++ b/fs/ext3/namei.h @@ -0,0 +1,8 @@ +/* linux/fs/ext3/namei.h + * + * Copyright (C) 2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * +*/ + +extern struct dentry *ext3_get_parent(struct dentry *child); diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 57f79106267..1be78b4b4de 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -118,6 +118,8 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, int err; bh = sb_getblk(sb, blk); + if (!bh) + return ERR_PTR(-EIO); if ((err = ext3_journal_get_write_access(handle, bh))) { brelse(bh); bh = ERR_PTR(err); @@ -202,6 +204,10 @@ static int setup_new_group_blocks(struct super_block *sb, ext3_debug("update backup group %#04lx (+%d)\n", block, bit); gdb = sb_getblk(sb, block); + if (!gdb) { + err = -EIO; + goto exit_bh; + } if ((err = ext3_journal_get_write_access(handle, gdb))) { brelse(gdb); goto exit_bh; @@ -643,6 +649,10 @@ static void update_backups(struct super_block *sb, break; bh = sb_getblk(sb, group * bpg + blk_off); + if (!bh) { + err = -EIO; + break; + } ext3_debug("update metadata backup %#04lx\n", (unsigned long)bh->b_blocknr); if ((err = ext3_journal_get_write_access(handle, bh))) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 097383c1115..f594989ccb7 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -36,9 +36,12 @@ #include <linux/namei.h> #include <linux/quotaops.h> #include <linux/seq_file.h> + #include <asm/uaccess.h> + #include "xattr.h" #include "acl.h" +#include "namei.h" static int ext3_load_journal(struct super_block *, struct ext3_super_block *); static int ext3_create_journal(struct super_block *, struct ext3_super_block *, @@ -615,7 +618,6 @@ static struct super_operations ext3_sops = { #endif }; -struct dentry *ext3_get_parent(struct dentry *child); static struct export_operations ext3_export_ops = { .get_parent = ext3_get_parent, }; diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 269c7b92db9..430de9f63be 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -210,7 +210,7 @@ ext3_xattr_find_entry(struct ext3_xattr_entry **pentry, int name_index, return cmp ? -ENODATA : 0; } -int +static int ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { @@ -354,7 +354,7 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry, return buffer_size - rest; } -int +static int ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) { struct buffer_head *bh = NULL; @@ -626,7 +626,7 @@ struct ext3_xattr_block_find { struct buffer_head *bh; }; -int +static int ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i, struct ext3_xattr_block_find *bs) { @@ -859,7 +859,7 @@ struct ext3_xattr_ibody_find { struct ext3_iloc iloc; }; -int +static int ext3_xattr_ibody_find(struct inode *inode, struct ext3_xattr_info *i, struct ext3_xattr_ibody_find *is) { diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 895049b2ac9..ba824964b9b 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -222,6 +222,80 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size, return len; } +enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, }; + +/** + * fat_parse_long - Parse extended directory entry. + * + * This function returns zero on success, negative value on error, or one of + * the following: + * + * %PARSE_INVALID - Directory entry is invalid. + * %PARSE_NOT_LONGNAME - Directory entry does not contain longname. + * %PARSE_EOF - Directory has no more entries. + */ +static int fat_parse_long(struct inode *dir, loff_t *pos, + struct buffer_head **bh, struct msdos_dir_entry **de, + wchar_t **unicode, unsigned char *nr_slots) +{ + struct msdos_dir_slot *ds; + unsigned char id, slot, slots, alias_checksum; + + if (!*unicode) { + *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); + if (!*unicode) { + brelse(*bh); + return -ENOMEM; + } + } +parse_long: + slots = 0; + ds = (struct msdos_dir_slot *)*de; + id = ds->id; + if (!(id & 0x40)) + return PARSE_INVALID; + slots = id & ~0x40; + if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ + return PARSE_INVALID; + *nr_slots = slots; + alias_checksum = ds->alias_checksum; + + slot = slots; + while (1) { + int offset; + + slot--; + offset = slot * 13; + fat16_towchar(*unicode + offset, ds->name0_4, 5); + fat16_towchar(*unicode + offset + 5, ds->name5_10, 6); + fat16_towchar(*unicode + offset + 11, ds->name11_12, 2); + + if (ds->id & 0x40) + (*unicode)[offset + 13] = 0; + if (fat_get_entry(dir, pos, bh, de) < 0) + return PARSE_EOF; + if (slot == 0) + break; + ds = (struct msdos_dir_slot *)*de; + if (ds->attr != ATTR_EXT) + return PARSE_NOT_LONGNAME; + if ((ds->id & ~0x40) != slot) + goto parse_long; + if (ds->alias_checksum != alias_checksum) + goto parse_long; + } + if ((*de)->name[0] == DELETED_FLAG) + return PARSE_INVALID; + if ((*de)->attr == ATTR_EXT) + goto parse_long; + if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME)) + return PARSE_INVALID; + if (fat_checksum((*de)->name) != alias_checksum) + *nr_slots = 0; + + return 0; +} + /* * Return values: negative -> error, 0 -> not found, positive -> found, * value is the total amount of slots, including the shortname entry. @@ -259,68 +333,16 @@ parse_record: if (de->attr != ATTR_EXT && IS_FREE(de->name)) continue; if (de->attr == ATTR_EXT) { - struct msdos_dir_slot *ds; - unsigned char id; - unsigned char slot; - unsigned char slots; - unsigned char sum; - unsigned char alias_checksum; - - if (!unicode) { - unicode = (wchar_t *) - __get_free_page(GFP_KERNEL); - if (!unicode) { - brelse(bh); - return -ENOMEM; - } - } -parse_long: - slots = 0; - ds = (struct msdos_dir_slot *) de; - id = ds->id; - if (!(id & 0x40)) - continue; - slots = id & ~0x40; - if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ - continue; - nr_slots = slots; - alias_checksum = ds->alias_checksum; - - slot = slots; - while (1) { - int offset; - - slot--; - offset = slot * 13; - fat16_towchar(unicode + offset, ds->name0_4, 5); - fat16_towchar(unicode + offset + 5, ds->name5_10, 6); - fat16_towchar(unicode + offset + 11, ds->name11_12, 2); - - if (ds->id & 0x40) { - unicode[offset + 13] = 0; - } - if (fat_get_entry(inode, &cpos, &bh, &de) < 0) - goto EODir; - if (slot == 0) - break; - ds = (struct msdos_dir_slot *) de; - if (ds->attr != ATTR_EXT) - goto parse_record; - if ((ds->id & ~0x40) != slot) - goto parse_long; - if (ds->alias_checksum != alias_checksum) - goto parse_long; - } - if (de->name[0] == DELETED_FLAG) - continue; - if (de->attr == ATTR_EXT) - goto parse_long; - if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME)) + int status = fat_parse_long(inode, &cpos, &bh, &de, + &unicode, &nr_slots); + if (status < 0) + return status; + else if (status == PARSE_INVALID) continue; - for (sum = 0, i = 0; i < 11; i++) - sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i]; - if (sum != alias_checksum) - nr_slots = 0; + else if (status == PARSE_NOT_LONGNAME) + goto parse_record; + else if (status == PARSE_EOF) + goto EODir; } memcpy(work, de->name, sizeof(de->name)); @@ -408,8 +430,8 @@ struct fat_ioctl_filldir_callback { int short_len; }; -static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent, - filldir_t filldir, int short_only, int both) +static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, + filldir_t filldir, int short_only, int both) { struct super_block *sb = inode->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); @@ -458,9 +480,10 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent, bh = NULL; GetNew: - long_slots = 0; if (fat_get_entry(inode, &cpos, &bh, &de) == -1) goto EODir; +parse_record: + long_slots = 0; /* Check for long filename entry */ if (isvfat) { if (de->name[0] == DELETED_FLAG) @@ -475,69 +498,18 @@ GetNew: } if (isvfat && de->attr == ATTR_EXT) { - struct msdos_dir_slot *ds; - unsigned char id; - unsigned char slot; - unsigned char slots; - unsigned char sum; - unsigned char alias_checksum; - - if (!unicode) { - unicode = (wchar_t *)__get_free_page(GFP_KERNEL); - if (!unicode) { - filp->f_pos = cpos; - brelse(bh); - ret = -ENOMEM; - goto out; - } - } -ParseLong: - slots = 0; - ds = (struct msdos_dir_slot *) de; - id = ds->id; - if (!(id & 0x40)) - goto RecEnd; - slots = id & ~0x40; - if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ + int status = fat_parse_long(inode, &cpos, &bh, &de, + &unicode, &long_slots); + if (status < 0) { + filp->f_pos = cpos; + ret = status; + goto out; + } else if (status == PARSE_INVALID) goto RecEnd; - long_slots = slots; - alias_checksum = ds->alias_checksum; - - slot = slots; - while (1) { - int offset; - - slot--; - offset = slot * 13; - fat16_towchar(unicode + offset, ds->name0_4, 5); - fat16_towchar(unicode + offset + 5, ds->name5_10, 6); - fat16_towchar(unicode + offset + 11, ds->name11_12, 2); - - if (ds->id & 0x40) { - unicode[offset + 13] = 0; - } - if (fat_get_entry(inode, &cpos, &bh, &de) == -1) - goto EODir; - if (slot == 0) - break; - ds = (struct msdos_dir_slot *) de; - if (ds->attr != ATTR_EXT) - goto RecEnd; /* XXX */ - if ((ds->id & ~0x40) != slot) - goto ParseLong; - if (ds->alias_checksum != alias_checksum) - goto ParseLong; - } - if (de->name[0] == DELETED_FLAG) - goto RecEnd; - if (de->attr == ATTR_EXT) - goto ParseLong; - if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME)) - goto RecEnd; - for (sum = 0, i = 0; i < 11; i++) - sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i]; - if (sum != alias_checksum) - long_slots = 0; + else if (status == PARSE_NOT_LONGNAME) + goto parse_record; + else if (status == PARSE_EOF) + goto EODir; } if (sbi->options.dotsOK) { @@ -671,7 +643,7 @@ out: static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - return fat_readdirx(inode, filp, dirent, filldir, 0, 0); + return __fat_readdir(inode, filp, dirent, filldir, 0, 0); } static int fat_ioctl_filldir(void *__buf, const char *name, int name_len, @@ -760,8 +732,8 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, down(&inode->i_sem); ret = -ENOENT; if (!IS_DEADDIR(inode)) { - ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir, - short_only, both); + ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, + short_only, both); } up(&inode->i_sem); if (ret >= 0) diff --git a/fs/file_table.c b/fs/file_table.c index 86ec8ae985b..4dc20554654 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -56,13 +56,13 @@ void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) static inline void file_free_rcu(struct rcu_head *head) { - struct file *f = container_of(head, struct file, f_rcuhead); + struct file *f = container_of(head, struct file, f_u.fu_rcuhead); kmem_cache_free(filp_cachep, f); } static inline void file_free(struct file *f) { - call_rcu(&f->f_rcuhead, file_free_rcu); + call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); } /* Find an unused file structure and return a pointer to it. @@ -95,7 +95,7 @@ struct file *get_empty_filp(void) f->f_gid = current->fsgid; rwlock_init(&f->f_owner.lock); /* f->f_version: 0 */ - INIT_LIST_HEAD(&f->f_list); + INIT_LIST_HEAD(&f->f_u.fu_list); return f; over: @@ -225,15 +225,15 @@ void file_move(struct file *file, struct list_head *list) if (!list) return; file_list_lock(); - list_move(&file->f_list, list); + list_move(&file->f_u.fu_list, list); file_list_unlock(); } void file_kill(struct file *file) { - if (!list_empty(&file->f_list)) { + if (!list_empty(&file->f_u.fu_list)) { file_list_lock(); - list_del_init(&file->f_list); + list_del_init(&file->f_u.fu_list); file_list_unlock(); } } @@ -245,7 +245,7 @@ int fs_may_remount_ro(struct super_block *sb) /* Check that no files are currently opened for writing. */ file_list_lock(); list_for_each(p, &sb->s_files) { - struct file *file = list_entry(p, struct file, f_list); + struct file *file = list_entry(p, struct file, f_u.fu_list); struct inode *inode = file->f_dentry->d_inode; /* File with pending delete? */ diff --git a/fs/filesystems.c b/fs/filesystems.c index 44082bfdfec..9f1072836c8 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -12,6 +12,7 @@ #include <linux/kmod.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/sched.h> /* for 'current' */ #include <asm/uaccess.h> /* diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e94ab398b71..ffab4783ac6 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -230,7 +230,6 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) * The inode is clean, unused */ list_move(&inode->i_list, &inode_unused); - inodes_stat.nr_unused++; } } wake_up_inode(inode); @@ -238,14 +237,20 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) } /* - * Write out an inode's dirty pages. Called under inode_lock. + * Write out an inode's dirty pages. Called under inode_lock. Either the + * caller has ref on the inode (either via __iget or via syscall against an fd) + * or the inode has I_WILL_FREE set (via generic_forget_inode) */ static int -__writeback_single_inode(struct inode *inode, - struct writeback_control *wbc) +__writeback_single_inode(struct inode *inode, struct writeback_control *wbc) { wait_queue_head_t *wqh; + if (!atomic_read(&inode->i_count)) + WARN_ON(!(inode->i_state & I_WILL_FREE)); + else + WARN_ON(inode->i_state & I_WILL_FREE); + if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { list_move(&inode->i_list, &inode->i_sb->s_dirty); return 0; @@ -259,11 +264,9 @@ __writeback_single_inode(struct inode *inode, wqh = bit_waitqueue(&inode->i_state, __I_LOCK); do { - __iget(inode); spin_unlock(&inode_lock); __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); - iput(inode); spin_lock(&inode_lock); } while (inode->i_state & I_LOCK); } @@ -541,14 +544,15 @@ void sync_inodes(int wait) } /** - * write_inode_now - write an inode to disk - * @inode: inode to write to disk - * @sync: whether the write should be synchronous or not + * write_inode_now - write an inode to disk + * @inode: inode to write to disk + * @sync: whether the write should be synchronous or not + * + * This function commits an inode to disk immediately if it is dirty. This is + * primarily needed by knfsd. * - * This function commits an inode to disk immediately if it is - * dirty. This is primarily needed by knfsd. + * The caller must either have a ref on the inode or must have set I_WILL_FREE. */ - int write_inode_now(struct inode *inode, int sync) { int ret; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d4c869c6d01..a6f90a6c754 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -151,9 +151,9 @@ void fuse_release_background(struct fuse_req *req) /* * This function is called when a request is finished. Either a reply * has arrived or it was interrupted (and not yet sent) or some error - * occured during communication with userspace, or the device file was - * closed. It decreases the referece count for the request. In case - * of a background request the referece to the stored objects are + * occurred during communication with userspace, or the device file was + * closed. It decreases the reference count for the request. In case + * of a background request the reference to the stored objects are * released. The requester thread is woken up (if still waiting), and * finally the request is either freed or put on the unused_list * diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 29f1e9f6e85..70dba721aca 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -741,13 +741,14 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, if (inode && S_ISDIR(inode->i_mode)) { /* Don't allow creating an alias to a directory */ struct dentry *alias = d_find_alias(inode); - if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { + if (alias) { dput(alias); iput(inode); return ERR_PTR(-EIO); } } - return d_splice_alias(inode, entry); + d_add(entry, inode); + return NULL; } static int fuse_setxattr(struct dentry *entry, const char *name, diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 24d761518d8..5cb456f572c 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -349,22 +349,22 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, int isdir); /** - * Initialise file operations on a regular file + * Initialize file operations on a regular file */ void fuse_init_file_inode(struct inode *inode); /** - * Initialise inode operations on regular files and special files + * Initialize inode operations on regular files and special files */ void fuse_init_common(struct inode *inode); /** - * Initialise inode and file operations on a directory + * Initialize inode and file operations on a directory */ void fuse_init_dir(struct inode *inode); /** - * Initialise inode operations on a symlink + * Initialize inode operations on a symlink */ void fuse_init_symlink(struct inode *inode); @@ -411,7 +411,7 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc); /** * Decrement reference count of a request. If count goes to zero put - * on unused list (preallocated) or free reqest (not preallocated). + * on unused list (preallocated) or free request (not preallocated). */ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); @@ -431,7 +431,7 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); void request_send_background(struct fuse_conn *fc, struct fuse_req *req); /** - * Release inodes and file assiciated with background request + * Release inodes and file associated with background request */ void fuse_release_background(struct fuse_req *req); diff --git a/fs/inode.c b/fs/inode.c index 7d331652776..d8d04bd72b5 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1088,6 +1088,7 @@ static void generic_forget_inode(struct inode *inode) if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); + wake_up_inode(inode); destroy_inode(inode); } diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 0f224384f17..8210ac16a36 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -15,6 +15,7 @@ #include <linux/jffs2.h> #include <linux/mtd/mtd.h> #include <linux/completion.h> +#include <linux/sched.h> #include "nodelist.h" diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 996d922e503..316133c626b 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -18,6 +18,8 @@ #include <linux/mtd/mtd.h> #include <linux/crc32.h> #include <linux/mtd/nand.h> +#include <linux/jiffies.h> + #include "nodelist.h" /* For testing write failures */ diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 154f511c724..626a367bcd8 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -454,10 +454,10 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, { struct buffer_head *dotdot_bh; struct msdos_dir_entry *dotdot_de; - loff_t dotdot_i_pos; struct inode *old_inode, *new_inode; struct fat_slot_info old_sinfo, sinfo; struct timespec ts; + loff_t dotdot_i_pos, new_i_pos; int err, old_attrs, is_dir, update_dotdot, corrupt = 0; old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; @@ -516,28 +516,24 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, if (new_inode) { if (err) goto out; - if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) { - /* WTF??? Cry and fail. */ - printk(KERN_WARNING "msdos_rename: fs corrupted\n"); - goto out; - } - if (is_dir) { err = fat_dir_empty(new_inode); if (err) goto out; } + new_i_pos = MSDOS_I(new_inode)->i_pos; fat_detach(new_inode); } else { err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0, &ts, &sinfo); if (err) goto out; + new_i_pos = sinfo.i_pos; } new_dir->i_version++; fat_detach(old_inode); - fat_attach(old_inode, sinfo.i_pos); + fat_attach(old_inode, new_i_pos); if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else @@ -604,7 +600,7 @@ error_inode: fat_attach(old_inode, old_sinfo.i_pos); MSDOS_I(old_inode)->i_attrs = old_attrs; if (new_inode) { - fat_attach(new_inode, sinfo.i_pos); + fat_attach(new_inode, new_i_pos); if (corrupt) corrupt |= fat_sync_inode(new_inode); } else { diff --git a/fs/namei.c b/fs/namei.c index aaaa8103623..c5769c4fcab 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1311,9 +1311,6 @@ static inline int may_create(struct inode *dir, struct dentry *child, } /* - * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security - * reasons. - * * O_DIRECTORY translates into forcing a directory lookup. */ static inline int lookup_flags(unsigned int f) @@ -1323,9 +1320,6 @@ static inline int lookup_flags(unsigned int f) if (f & O_NOFOLLOW) retval &= ~LOOKUP_FOLLOW; - if ((f & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) - retval &= ~LOOKUP_FOLLOW; - if (f & O_DIRECTORY) retval |= LOOKUP_DIRECTORY; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index f2781ca4276..fc0f12ba89c 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1274,14 +1274,12 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat } if ((fattr->valid & NFS_ATTR_FATTR) == 0) { - spin_unlock(&inode->i_lock); return 0; } /* Has the inode gone and changed behind our back? */ if (nfsi->fileid != fattr->fileid || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { - spin_unlock(&inode->i_lock); return -EIO; } diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 8a8c34461d4..b638fb50074 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -533,7 +533,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) */ file_list_lock(); list_for_each(p, &sb->s_files) { - struct file * filp = list_entry(p, struct file, f_list); + struct file * filp = list_entry(p, struct file, f_u.fu_list); struct dentry * dentry = filp->f_dentry; struct inode * inode; struct file_operations *fops; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index effa6c0c467..e6a818a93f3 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -156,10 +156,13 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, WARN_ON(de && de->deleted); + if (de != NULL && !try_module_get(de->owner)) + goto out_mod; + inode = iget(sb, ino); if (!inode) - goto out_fail; - + goto out_ino; + PROC_I(inode)->pde = de; if (de) { if (de->mode) { @@ -171,20 +174,20 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, inode->i_size = de->size; if (de->nlink) inode->i_nlink = de->nlink; - if (!try_module_get(de->owner)) - goto out_fail; if (de->proc_iops) inode->i_op = de->proc_iops; if (de->proc_fops) inode->i_fop = de->proc_fops; } -out: return inode; -out_fail: +out_ino: + if (de != NULL) + module_put(de->owner); +out_mod: de_put(de); - goto out; + return NULL; } int proc_fill_super(struct super_block *s, void *data, int silent) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 44b02fc02eb..42afb5bef11 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1024,12 +1024,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); *mount_options |= 1 << REISERFS_QUOTA; } else { - if (REISERFS_SB(s)->s_qf_names[qtype]) { - kfree(REISERFS_SB(s)-> - s_qf_names[qtype]); - REISERFS_SB(s)->s_qf_names[qtype] = - NULL; - } + kfree(REISERFS_SB(s)->s_qf_names[qtype]); + REISERFS_SB(s)->s_qf_names[qtype] = NULL; } } if (c == 'f') { @@ -1158,11 +1154,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (!reiserfs_parse_options (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) { #ifdef CONFIG_QUOTA - for (i = 0; i < MAXQUOTAS; i++) - if (REISERFS_SB(s)->s_qf_names[i]) { - kfree(REISERFS_SB(s)->s_qf_names[i]); - REISERFS_SB(s)->s_qf_names[i] = NULL; - } + for (i = 0; i < MAXQUOTAS; i++) { + kfree(REISERFS_SB(s)->s_qf_names[i]); + REISERFS_SB(s)->s_qf_names[i] = NULL; + } #endif return -EINVAL; } @@ -1940,13 +1935,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) brelse(SB_BUFFER_WITH_SB(s)); #ifdef CONFIG_QUOTA for (j = 0; j < MAXQUOTAS; j++) { - if (sbi->s_qf_names[j]) - kfree(sbi->s_qf_names[j]); + kfree(sbi->s_qf_names[j]); + sbi->s_qf_names[j] = NULL; } #endif - if (sbi != NULL) { - kfree(sbi); - } + kfree(sbi); s->s_fs_info = NULL; return errval; diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 6703efa3c43..a47ac9aac8b 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -296,8 +296,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) } } - if (value) - kfree(value); + kfree(value); if (!error) { /* Release the old one */ diff --git a/fs/super.c b/fs/super.c index 6e57ee252e1..f60155ec778 100644 --- a/fs/super.c +++ b/fs/super.c @@ -513,7 +513,7 @@ static void mark_files_ro(struct super_block *sb) struct file *f; file_list_lock(); - list_for_each_entry(f, &sb->s_files, f_list) { + list_for_each_entry(f, &sb->s_files, f_u.fu_list) { if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) f->f_mode &= ~FMODE_WRITE; } diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 1c6f6b57ef1..ef46939c0c1 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -621,8 +621,7 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, } /* build the entry of long file name */ - for (cksum = i = 0; i < 11; i++) - cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i]; + cksum = fat_checksum(msdos_name); *nr_slots = usize / 13; for (ps = slots, i = *nr_slots; i > 0; i--, ps++) { @@ -888,10 +887,10 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, { struct buffer_head *dotdot_bh; struct msdos_dir_entry *dotdot_de; - loff_t dotdot_i_pos; struct inode *old_inode, *new_inode; struct fat_slot_info old_sinfo, sinfo; struct timespec ts; + loff_t dotdot_i_pos, new_i_pos; int err, is_dir, update_dotdot, corrupt = 0; old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; @@ -914,31 +913,24 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, ts = CURRENT_TIME_SEC; if (new_inode) { - err = vfat_find(new_dir, &new_dentry->d_name, &sinfo); - if (err) - goto out; - if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) { - /* WTF??? Cry and fail. */ - printk(KERN_WARNING "vfat_rename: fs corrupted\n"); - goto out; - } - if (is_dir) { err = fat_dir_empty(new_inode); if (err) goto out; } + new_i_pos = MSDOS_I(new_inode)->i_pos; fat_detach(new_inode); } else { err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0, &ts, &sinfo); if (err) goto out; + new_i_pos = sinfo.i_pos; } new_dir->i_version++; fat_detach(old_inode); - fat_attach(old_inode, sinfo.i_pos); + fat_attach(old_inode, new_i_pos); if (IS_DIRSYNC(new_dir)) { err = fat_sync_inode(old_inode); if (err) @@ -1002,7 +994,7 @@ error_inode: fat_detach(old_inode); fat_attach(old_inode, old_sinfo.i_pos); if (new_inode) { - fat_attach(new_inode, sinfo.i_pos); + fat_attach(new_inode, new_i_pos); if (corrupt) corrupt |= fat_sync_inode(new_inode); } else { diff --git a/fs/xattr.c b/fs/xattr.c index 3f9c64bea15..f6e00c0e114 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -143,7 +143,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) if (size) { if (size > XATTR_SIZE_MAX) size = XATTR_SIZE_MAX; - kvalue = kmalloc(size, GFP_KERNEL); + kvalue = kzalloc(size, GFP_KERNEL); if (!kvalue) return -ENOMEM; } @@ -154,11 +154,15 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) error = -EOPNOTSUPP; if (d->d_inode->i_op && d->d_inode->i_op->getxattr) error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); - else if (!strncmp(kname, XATTR_SECURITY_PREFIX, - sizeof XATTR_SECURITY_PREFIX - 1)) { + + if (!strncmp(kname, XATTR_SECURITY_PREFIX, + sizeof XATTR_SECURITY_PREFIX - 1)) { const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; - error = security_inode_getsecurity(d->d_inode, suffix, kvalue, - size); + int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue, + size, error); + /* Security module active: overwrite error value */ + if (rv != -EOPNOTSUPP) + error = rv; } if (error > 0) { if (size && copy_to_user(value, kvalue, error)) diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h index eb2cbd97d40..1a6295f2c2d 100644 --- a/include/asm-alpha/semaphore.h +++ b/include/asm-alpha/semaphore.h @@ -26,9 +26,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h index b768009c3a5..c6d51426e98 100644 --- a/include/asm-arm/arch-ixp2000/ixdp2x01.h +++ b/include/asm-arm/arch-ixp2000/ixdp2x01.h @@ -22,7 +22,7 @@ #define IXDP2X01_CPLD_REGION_SIZE 0x00100000 #define IXDP2X01_CPLD_VIRT_REG(reg) (volatile unsigned long*)(IXDP2X01_VIRT_CPLD_BASE | reg) -#define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg) +#define IXDP2X01_CPLD_PHYS_REG(reg) (IXDP2X01_PHYS_CPLD_BASE | reg) #define IXDP2X01_UART1_VIRT_BASE IXDP2X01_CPLD_VIRT_REG(0x40) #define IXDP2X01_UART1_PHYS_BASE IXDP2X01_CPLD_PHYS_REG(0x40) diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h index e350dcb544e..80d05ecad2f 100644 --- a/include/asm-arm/arch-ixp4xx/io.h +++ b/include/asm-arm/arch-ixp4xx/io.h @@ -113,7 +113,7 @@ __ixp4xx_writeb(u8 value, u32 addr) } static inline void -__ixp4xx_writesb(u32 bus_addr, u8 *vaddr, int count) +__ixp4xx_writesb(u32 bus_addr, const u8 *vaddr, int count) { while (count--) writeb(*vaddr++, bus_addr); @@ -136,7 +136,7 @@ __ixp4xx_writew(u16 value, u32 addr) } static inline void -__ixp4xx_writesw(u32 bus_addr, u16 *vaddr, int count) +__ixp4xx_writesw(u32 bus_addr, const u16 *vaddr, int count) { while (count--) writew(*vaddr++, bus_addr); @@ -154,7 +154,7 @@ __ixp4xx_writel(u32 value, u32 addr) } static inline void -__ixp4xx_writesl(u32 bus_addr, u32 *vaddr, int count) +__ixp4xx_writesl(u32 bus_addr, const u32 *vaddr, int count) { while (count--) writel(*vaddr++, bus_addr); diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index 366bafbdfbb..5a0d19b466b 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -397,9 +397,6 @@ static inline pte_t *pmd_page_kernel(pmd_t pmd) #define pgd_clear(pgdp) do { } while (0) #define set_pgd(pgd,pgdp) do { } while (0) -#define page_pte_prot(page,prot) mk_pte(page, prot) -#define page_pte(page) mk_pte(page, __pgprot(0)) - /* to find an entry in a page-table-directory */ #define pgd_index(addr) ((addr) >> PGDIR_SHIFT) diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h index 60f33e6eb80..71ca7d41268 100644 --- a/include/asm-arm/semaphore.h +++ b/include/asm-arm/semaphore.h @@ -24,8 +24,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \ } -#define __MUTEX_INITIALIZER(name) __SEMAPHORE_INIT(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INIT(name,count) diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index c49df635a80..d626e70fade 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -544,7 +544,6 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, asmlinkage int sys_fork(struct pt_regs *regs); asmlinkage int sys_vfork(struct pt_regs *regs); asmlinkage int sys_pipe(unsigned long *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h index f602cf57241..a590250277f 100644 --- a/include/asm-arm26/pgtable.h +++ b/include/asm-arm26/pgtable.h @@ -98,8 +98,6 @@ extern struct page *empty_zero_page; #define pfn_pte(pfn,prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))) #define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) #define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) -#define page_pte_prot(page,prot) mk_pte(page, prot) -#define page_pte(page) mk_pte(page, __pgprot(0)) /* * Terminology: PGD = Page Directory, PMD = Page Middle Directory, diff --git a/include/asm-arm26/semaphore.h b/include/asm-arm26/semaphore.h index c1b6a1edad9..ccf15e70410 100644 --- a/include/asm-arm26/semaphore.h +++ b/include/asm-arm26/semaphore.h @@ -25,9 +25,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INIT(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INIT(name,count) diff --git a/include/asm-arm26/unistd.h b/include/asm-arm26/unistd.h index dfa0b0c30aa..be4c2fb9c04 100644 --- a/include/asm-arm26/unistd.h +++ b/include/asm-arm26/unistd.h @@ -480,7 +480,6 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, asmlinkage int sys_fork(struct pt_regs *regs); asmlinkage int sys_vfork(struct pt_regs *regs); asmlinkage int sys_pipe(unsigned long *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h index 8ed7636ab31..39faf69bcf7 100644 --- a/include/asm-cris/semaphore.h +++ b/include/asm-cris/semaphore.h @@ -33,9 +33,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h index 28232ad2ff3..156a34bfc58 100644 --- a/include/asm-cris/unistd.h +++ b/include/asm-cris/unistd.h @@ -367,7 +367,6 @@ asmlinkage int sys_fork(long r10, long r11, long r12, long r13, asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs); asmlinkage int sys_pipe(unsigned long __user *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h index 473fb4bb632..b247e99dff4 100644 --- a/include/asm-frv/pgtable.h +++ b/include/asm-frv/pgtable.h @@ -436,8 +436,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) return pte; } -#define page_pte(page) page_pte_prot((page), __pgprot(0)) - /* to find an entry in a page-table-directory. */ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) #define pgd_index_k(addr) pgd_index(addr) diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h index 39354563080..b18396288df 100644 --- a/include/asm-frv/semaphore.h +++ b/include/asm-frv/semaphore.h @@ -47,9 +47,6 @@ struct semaphore { #define __SEMAPHORE_INITIALIZER(name,count) \ { count, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __SEM_DEBUG_INIT(name) } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h index fe6ef377429..81bae2a9919 100644 --- a/include/asm-h8300/semaphore.h +++ b/include/asm-h8300/semaphore.h @@ -35,9 +35,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h index 56a6401886f..56a4a5686c8 100644 --- a/include/asm-h8300/unistd.h +++ b/include/asm-h8300/unistd.h @@ -528,7 +528,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, asmlinkage int sys_execve(char *name, char **argv, char **envp, int dummy, ...); asmlinkage int sys_pipe(unsigned long *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index 8c454aa58ac..a515e2aed82 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -118,7 +118,8 @@ extern void release_lapic_nmi(void); extern void disable_timer_nmi_watchdog(void); extern void enable_timer_nmi_watchdog(void); extern void nmi_watchdog_tick (struct pt_regs * regs); -extern int APIC_init_uniprocessor (void); +extern int APIC_init(void); +extern void APIC_late_time_init(void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h index 6df1a53c190..29b851a18c6 100644 --- a/include/asm-i386/desc.h +++ b/include/asm-i386/desc.h @@ -17,6 +17,8 @@ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES]; DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]); +#define get_cpu_gdt_table(_cpu) (per_cpu(cpu_gdt_table,_cpu)) + DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); struct Xgt_desc_struct { @@ -60,7 +62,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr) { - _set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[entry], (int)addr, + _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr, offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89); } @@ -68,7 +70,7 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *ad static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size) { - _set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82); + _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82); } #define LDT_entry_a(info) \ @@ -109,7 +111,7 @@ static inline void write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 en static inline void load_TLS(struct thread_struct *t, unsigned int cpu) { -#define C(i) per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] +#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] C(0); C(1); C(2); #undef C } diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h index 622815bf324..9139b89497a 100644 --- a/include/asm-i386/hw_irq.h +++ b/include/asm-i386/hw_irq.h @@ -55,6 +55,7 @@ void init_8259A(int aeoi); void FASTCALL(send_IPI_self(int vector)); void init_VISWS_APIC_irqs(void); void setup_IO_APIC(void); +void IO_APIC_late_time_init(void); void disable_IO_APIC(void); void print_IO_APIC(void); int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); diff --git a/include/asm-i386/mach-default/smpboot_hooks.h b/include/asm-i386/mach-default/smpboot_hooks.h index 7f45f631105..d7c70c144f9 100644 --- a/include/asm-i386/mach-default/smpboot_hooks.h +++ b/include/asm-i386/mach-default/smpboot_hooks.h @@ -1,11 +1,6 @@ /* two abstractions specific to kernel/smpboot.c, mainly to cater to visws * which needs to alter them. */ -static inline void smpboot_clear_io_apic_irqs(void) -{ - io_apic_irqs = 0; -} - static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) { CMOS_WRITE(0xa, 0xf); @@ -32,13 +27,3 @@ static inline void smpboot_restore_warm_reset_vector(void) *((volatile long *) phys_to_virt(0x467)) = 0; } - -static inline void smpboot_setup_io_apic(void) -{ - /* - * Here we can be sure that there is an IO-APIC in the system. Let's - * go and set it up: - */ - if (!skip_ioapic_setup && nr_ioapics) - setup_IO_APIC(); -} diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h index 28a84f6185a..4a0637a3e20 100644 --- a/include/asm-i386/mach-es7000/mach_mpparse.h +++ b/include/asm-i386/mach-es7000/mach_mpparse.h @@ -16,7 +16,7 @@ static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, extern int parse_unisys_oem (char *oemptr); extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); -extern void setup_unisys(); +extern void setup_unisys(void); static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) diff --git a/include/asm-i386/mach-visws/smpboot_hooks.h b/include/asm-i386/mach-visws/smpboot_hooks.h index d926471fa35..14d8e0375f7 100644 --- a/include/asm-i386/mach-visws/smpboot_hooks.h +++ b/include/asm-i386/mach-visws/smpboot_hooks.h @@ -11,14 +11,7 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) /* for visws do nothing for any of these */ -static inline void smpboot_clear_io_apic_irqs(void) -{ -} - static inline void smpboot_restore_warm_reset_vector(void) { } -static inline void smpboot_setup_io_apic(void) -{ -} diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h index fa07bd6c752..74ef721b534 100644 --- a/include/asm-i386/pgtable-2level.h +++ b/include/asm-i386/pgtable-2level.h @@ -26,11 +26,6 @@ #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) -#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) - -#define pmd_page_kernel(pmd) \ -((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) - /* * All present user pages are user-executable: */ diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h index 2e3f4a344a2..f1a8b454920 100644 --- a/include/asm-i386/pgtable-3level.h +++ b/include/asm-i386/pgtable-3level.h @@ -74,11 +74,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte) */ static inline void pud_clear (pud_t * pud) { } -#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) - -#define pmd_page_kernel(pmd) \ -((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) - #define pud_page(pud) \ ((struct page *) __va(pud_val(pud) & PAGE_MASK)) diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 0e3ec809352..03f3c8ac638 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -323,8 +323,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) return pte; } -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - #define pmd_large(pmd) \ ((pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT)) @@ -369,6 +367,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pte_offset_kernel(dir, address) \ ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address)) +#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) + +#define pmd_page_kernel(pmd) \ + ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) + /* * Helper function that returns the kernel pagetable entry controlling * the virtual address 'address'. NULL means no pagetable entry present. diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h index ea563da63e2..6a42b2142fd 100644 --- a/include/asm-i386/semaphore.h +++ b/include/asm-i386/semaphore.h @@ -55,9 +55,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index acd5c26b69b..97d52ac49e4 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -167,6 +167,8 @@ struct __xchg_dummy { unsigned long a[100]; }; #define __xg(x) ((struct __xchg_dummy *)(x)) +#ifdef CONFIG_X86_CMPXCHG64 + /* * The semantics of XCHGCMP8B are a bit strange, this is why * there is a loop and the loading of %%eax and %%edx has to @@ -221,6 +223,8 @@ static inline void __set_64bit_var (unsigned long long *ptr, __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \ __set_64bit(ptr, ll_low(value), ll_high(value)) ) +#endif + /* * Note: no "lock" prefix even on SMP: xchg always implies lock anyway * Note 2: xchg has side effect, so that attribute volatile is necessary, @@ -259,7 +263,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz #ifdef CONFIG_X86_CMPXCHG #define __HAVE_ARCH_CMPXCHG 1 -#endif static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) @@ -275,13 +278,13 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, case 2: __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" : "=a"(prev) - : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "r"(new), "m"(*__xg(ptr)), "0"(old) : "memory"); return prev; case 4: __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" : "=a"(prev) - : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "r"(new), "m"(*__xg(ptr)), "0"(old) : "memory"); return prev; } @@ -291,6 +294,30 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define cmpxchg(ptr,o,n)\ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ (unsigned long)(n),sizeof(*(ptr)))) + +#endif + +#ifdef CONFIG_X86_CMPXCHG64 + +static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old, + unsigned long long new) +{ + unsigned long long prev; + __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3" + : "=A"(prev) + : "b"((unsigned long)new), + "c"((unsigned long)(new >> 32)), + "m"(*__xg(ptr)), + "0"(old) + : "memory"); + return prev; +} + +#define cmpxchg64(ptr,o,n)\ + ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\ + (unsigned long long)(n))) + +#endif #ifdef __KERNEL__ struct alt_instr { diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index fbaf90a3968..0f92e78dfea 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -448,7 +448,6 @@ asmlinkage int sys_clone(struct pt_regs regs); asmlinkage int sys_fork(struct pt_regs regs); asmlinkage int sys_vfork(struct pt_regs regs); asmlinkage int sys_pipe(unsigned long __user *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); asmlinkage long sys_iopl(unsigned long unused); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 3339c7b55a6..21e32a06bc8 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -236,9 +236,6 @@ ia64_phys_addr_valid (unsigned long addr) #define pte_modify(_pte, newprot) \ (__pte((pte_val(_pte) & ~_PAGE_CHG_MASK) | (pgprot_val(newprot) & _PAGE_CHG_MASK))) -#define page_pte_prot(page,prot) mk_pte(page, prot) -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - #define pte_none(pte) (!pte_val(pte)) #define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE)) #define pte_clear(mm,addr,pte) (pte_val(*(pte)) = 0UL) diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h index 3a2f0f3f78f..bb8906285fa 100644 --- a/include/asm-ia64/semaphore.h +++ b/include/asm-ia64/semaphore.h @@ -24,8 +24,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name, count) diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 3a0c6952465..6d96a67439b 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -383,8 +383,6 @@ struct sigaction; long sys_execve(char __user *filename, char __user * __user *argv, char __user * __user *envp, struct pt_regs *regs); asmlinkage long sys_pipe(void); -asmlinkage long sys_ptrace(long request, pid_t pid, - unsigned long addr, unsigned long data); asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h index 388e5ee9fa2..1cd5fd4a5b2 100644 --- a/include/asm-m32r/pgtable.h +++ b/include/asm-m32r/pgtable.h @@ -324,8 +324,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) return pte; } -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h index 53e3c60f21e..bf447c52a0a 100644 --- a/include/asm-m32r/semaphore.h +++ b/include/asm-m32r/semaphore.h @@ -32,9 +32,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h index 7a6be7727a9..0f589363f61 100644 --- a/include/asm-m32r/thread_info.h +++ b/include/asm-m32r/thread_info.h @@ -95,7 +95,7 @@ static inline struct thread_info *current_thread_info(void) } /* thread information allocation */ -#if CONFIG_DEBUG_STACK_USAGE +#ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ ({ \ struct thread_info *ret; \ diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h index 8552d8f45ab..ac399e1f7bc 100644 --- a/include/asm-m32r/unistd.h +++ b/include/asm-m32r/unistd.h @@ -452,7 +452,6 @@ asmlinkage int sys_clone(struct pt_regs regs); asmlinkage int sys_fork(struct pt_regs regs); asmlinkage int sys_vfork(struct pt_regs regs); asmlinkage int sys_pipe(unsigned long __user *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h index ab94cf3ed44..fd4c7cc3d3b 100644 --- a/include/asm-m68k/semaphore.h +++ b/include/asm-m68k/semaphore.h @@ -36,9 +36,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-m68k/sun3xflop.h b/include/asm-m68k/sun3xflop.h index 1ed3b787ee0..fda1eccf10a 100644 --- a/include/asm-m68k/sun3xflop.h +++ b/include/asm-m68k/sun3xflop.h @@ -27,10 +27,8 @@ /* We don't need no stinkin' I/O port allocation crap. */ #undef release_region -#undef check_region #undef request_region #define release_region(X, Y) do { } while(0) -#define check_region(X, Y) (0) #define request_region(X, Y, Z) (1) struct sun3xflop_private { diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h index cbabde4f8a4..c2554bcd174 100644 --- a/include/asm-m68k/unistd.h +++ b/include/asm-m68k/unistd.h @@ -444,7 +444,6 @@ asmlinkage long sys_mmap2( unsigned long fd, unsigned long pgoff); asmlinkage int sys_execve(char *name, char **argv, char **envp); asmlinkage int sys_pipe(unsigned long *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct pt_regs; struct sigaction; asmlinkage long sys_rt_sigaction(int sig, diff --git a/include/asm-m68knommu/ide.h b/include/asm-m68knommu/ide.h index b1cbf8bb923..836f0721ecf 100644 --- a/include/asm-m68knommu/ide.h +++ b/include/asm-m68knommu/ide.h @@ -163,13 +163,6 @@ ide_free_irq(unsigned int irq, void *dev_id) } -static IDE_INLINE int -ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return 0; -} - - static IDE_INLINE void ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) { diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h index febe85add50..17aee15906a 100644 --- a/include/asm-m68knommu/semaphore.h +++ b/include/asm-m68knommu/semaphore.h @@ -35,9 +35,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h index 84b6fa14459..5373988a7e5 100644 --- a/include/asm-m68knommu/unistd.h +++ b/include/asm-m68knommu/unistd.h @@ -504,7 +504,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long fd, unsigned long pgoff); asmlinkage int sys_execve(char *name, char **argv, char **envp); asmlinkage int sys_pipe(unsigned long *fildes); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct pt_regs; int sys_request_irq(unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *), diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h index 3e0a522c0f0..82166b254b2 100644 --- a/include/asm-mips/pgtable-64.h +++ b/include/asm-mips/pgtable-64.h @@ -169,7 +169,6 @@ static inline void pud_clear(pud_t *pudp) #define __pgd_offset(address) pgd_index(address) #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) #define __pmd_offset(address) pmd_index(address) -#define page_pte(page) page_pte_prot(page, __pgprot(0)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, 0) diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 1e8ae2723be..34facd99650 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -75,7 +75,6 @@ extern void paging_init(void); * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. */ -#define page_pte(page) page_pte_prot(page, __pgprot(0)) #define pmd_phys(pmd) (pmd_val(pmd) - PAGE_OFFSET) #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) #define pmd_page_kernel(pmd) pmd_val(pmd) diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h index c2c97dec661..3d6aa7c7ea8 100644 --- a/include/asm-mips/semaphore.h +++ b/include/asm-mips/semaphore.h @@ -45,9 +45,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - #define __DECLARE_SEMAPHORE_GENERIC(name, count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index c9eaf4c104d..89ea8b60e94 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -1177,7 +1177,6 @@ asmlinkage long sys_mmap2( unsigned long fd, unsigned long pgoff); asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs); asmlinkage int sys_pipe(nabi_no_regargs struct pt_regs regs); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h index 3243cf2cd22..b27bf7aeb25 100644 --- a/include/asm-parisc/ide.h +++ b/include/asm-parisc/ide.h @@ -22,7 +22,6 @@ #define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) #define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) -#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. */ diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h index f78bb2e3453..c9ee41cd070 100644 --- a/include/asm-parisc/semaphore.h +++ b/include/asm-parisc/semaphore.h @@ -49,9 +49,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h index e7a620c5c5e..80b7b98c70a 100644 --- a/include/asm-parisc/unistd.h +++ b/include/asm-parisc/unistd.h @@ -1011,7 +1011,6 @@ int sys_clone(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs); int sys_vfork(struct pt_regs *regs); int sys_pipe(int *fildes); -long sys_ptrace(long request, pid_t pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-ppc/semaphore.h b/include/asm-ppc/semaphore.h index 89e6e73be08..d592937359c 100644 --- a/include/asm-ppc/semaphore.h +++ b/include/asm-ppc/semaphore.h @@ -37,9 +37,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - #define __DECLARE_SEMAPHORE_GENERIC(name, count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h index 3173ab3d2eb..404c143e643 100644 --- a/include/asm-ppc/unistd.h +++ b/include/asm-ppc/unistd.h @@ -469,7 +469,6 @@ int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs); int sys_pipe(int __user *fildes); -int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h index aefe7753ea4..d9ecb996923 100644 --- a/include/asm-ppc64/semaphore.h +++ b/include/asm-ppc64/semaphore.h @@ -31,9 +31,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - #define __DECLARE_SEMAPHORE_GENERIC(name, count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h index 977bc980c1a..6b5fcbadbc5 100644 --- a/include/asm-ppc64/unistd.h +++ b/include/asm-ppc64/unistd.h @@ -467,7 +467,6 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs); int sys_pipe(int __user *fildes); -int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, size_t sigsetsize); diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h index 873def6f363..702cf436698 100644 --- a/include/asm-s390/semaphore.h +++ b/include/asm-s390/semaphore.h @@ -29,9 +29,6 @@ struct semaphore { #define __SEMAPHORE_INITIALIZER(name,count) \ { ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h index 0d51c484c2e..348a8813744 100644 --- a/include/asm-s390/setup.h +++ b/include/asm-s390/setup.h @@ -8,11 +8,14 @@ #ifndef _ASM_S390_SETUP_H #define _ASM_S390_SETUP_H +#include <asm/types.h> + #define PARMAREA 0x10400 #define COMMAND_LINE_SIZE 896 #define RAMDISK_ORIGIN 0x800000 #define RAMDISK_SIZE 0x800000 #define MEMORY_CHUNKS 16 /* max 0x7fff */ +#define IPL_PARMBLOCK_ORIGIN 0x2000 #ifndef __ASSEMBLY__ @@ -64,6 +67,53 @@ extern unsigned int console_irq; #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) +struct ipl_list_header { + u32 length; + u8 reserved[3]; + u8 version; +} __attribute__((packed)); + +struct ipl_block_fcp { + u32 length; + u8 pbt; + u8 reserved1[322-1]; + u16 devno; + u8 reserved2[4]; + u64 wwpn; + u64 lun; + u32 bootprog; + u8 reserved3[12]; + u64 br_lba; + u32 scp_data_len; + u8 reserved4[260]; + u8 scp_data[]; +} __attribute__((packed)); + +struct ipl_parameter_block { + union { + u32 length; + struct ipl_list_header header; + } hdr; + struct ipl_block_fcp fcp; +} __attribute__((packed)); + +#define IPL_MAX_SUPPORTED_VERSION (0) + +#define IPL_TYPE_FCP (0) + +/* + * IPL validity flags and parameters as detected in head.S + */ +extern u32 ipl_parameter_flags; +extern u16 ipl_devno; + +#define IPL_DEVNO_VALID (ipl_parameter_flags & 1) +#define IPL_PARMBLOCK_VALID (ipl_parameter_flags & 2) + +#define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ + IPL_PARMBLOCK_ORIGIN) +#define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.length) + #else #ifndef __s390x__ diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index 221e965da92..f97d92691f1 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -590,7 +590,6 @@ asmlinkage long sys_clone(struct pt_regs regs); asmlinkage long sys_fork(struct pt_regs regs); asmlinkage long sys_vfork(struct pt_regs regs); asmlinkage long sys_pipe(unsigned long __user *fildes); -asmlinkage long sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 0f4bcaae61b..aef8ae43de1 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -224,8 +224,6 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; } -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - #define pmd_page_kernel(pmd) \ ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h index b923a77a8a7..489f7847c5d 100644 --- a/include/asm-sh/semaphore.h +++ b/include/asm-sh/semaphore.h @@ -33,9 +33,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index ea89e8f223e..f2c8e14d1fd 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -503,7 +503,6 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs); -asmlinkage int sys_ptrace(long request, long pid, long addr, long data); asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char *buf, size_t count, long dummy, loff_t pos); asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char *buf, diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h index 51db4307bfa..51b05818e4e 100644 --- a/include/asm-sh64/pgtable.h +++ b/include/asm-sh64/pgtable.h @@ -457,9 +457,6 @@ extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; } -#define page_pte_prot(page, prot) mk_pte(page, prot) -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - typedef pte_t *pte_addr_t; #define pgtable_cache_init() do { } while (0) diff --git a/include/asm-sh64/semaphore.h b/include/asm-sh64/semaphore.h index fce22bb9a54..46952645914 100644 --- a/include/asm-sh64/semaphore.h +++ b/include/asm-sh64/semaphore.h @@ -40,9 +40,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h index caf92611650..7a941b800b6 100644 --- a/include/asm-sparc/floppy.h +++ b/include/asm-sparc/floppy.h @@ -17,10 +17,8 @@ /* We don't need no stinkin' I/O port allocation crap. */ #undef release_region -#undef check_region #undef request_region #define release_region(X, Y) do { } while(0) -#define check_region(X, Y) (0) #define request_region(X, Y, Z) (1) /* References: diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index a14e9867750..b33c35411e8 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -255,8 +255,6 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t) #define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte) #define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte) -#define page_pte_prot(page, prot) mk_pte(page, prot) -#define page_pte(page) mk_pte(page, __pgprot(0)) #define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot) BTFIXUPDEF_CALL(unsigned long, pte_pfn, pte_t) diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h index 60ac5fd9eb4..f74ba31e265 100644 --- a/include/asm-sparc/semaphore.h +++ b/include/asm-sparc/semaphore.h @@ -22,9 +22,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 8c6dfc6c7af..9a02879b235 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -231,9 +231,6 @@ extern struct page *mem_map_zero; #define pte_pfn(x) ((pte_val(x) & _PAGE_PADDR)>>PAGE_SHIFT) #define pte_page(x) pfn_to_page(pte_pfn(x)) -#define page_pte_prot(page, prot) mk_pte(page, prot) -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot) { pte_t __pte; diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h index 7419dd88b49..093dcc6788d 100644 --- a/include/asm-sparc64/semaphore.h +++ b/include/asm-sparc64/semaphore.h @@ -22,9 +22,6 @@ struct semaphore { { ATOMIC_INIT(count), \ __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - #define __DECLARE_SEMAPHORE_GENERIC(name, count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-um/cache.h b/include/asm-um/cache.h index 4b134fe8504..a10602a5b2d 100644 --- a/include/asm-um/cache.h +++ b/include/asm-um/cache.h @@ -1,10 +1,21 @@ #ifndef __UM_CACHE_H #define __UM_CACHE_H -/* These are x86 numbers */ -#define L1_CACHE_SHIFT 5 -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#include <linux/config.h> -#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ +#if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT) +# define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) +#elif defined(CONFIG_UML_X86) /* 64-bit */ +# define L1_CACHE_SHIFT 6 /* Should be 7 on Intel */ +#else +/* XXX: this was taken from x86, now it's completely random. Luckily only + * affects SMP padding. */ +# define L1_CACHE_SHIFT 5 +#endif + +/* XXX: this is valid for x86 and x86_64. */ +#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ + +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #endif diff --git a/include/asm-um/linkage.h b/include/asm-um/linkage.h index 7dfce37adc8..e3d62dcbd35 100644 --- a/include/asm-um/linkage.h +++ b/include/asm-um/linkage.h @@ -3,4 +3,12 @@ #include "asm/arch/linkage.h" +#include <linux/config.h> + +/* <linux/linkage.h> will pick sane defaults */ +#ifdef CONFIG_GPROF +#undef FASTCALL +#undef fastcall +#endif + #endif diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h index c514062bb69..df6cdecf6c1 100644 --- a/include/asm-v850/semaphore.h +++ b/include/asm-v850/semaphore.h @@ -18,9 +18,6 @@ struct semaphore { { ATOMIC_INIT (count), 0, \ __WAIT_QUEUE_HEAD_INITIALIZER ((name).wait) } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER (name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER (name,count) diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h index 3b552096c0e..5a86f8e976e 100644 --- a/include/asm-v850/unistd.h +++ b/include/asm-v850/unistd.h @@ -452,7 +452,6 @@ unsigned long sys_mmap2(unsigned long addr, size_t len, struct pt_regs; int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs); int sys_pipe (int *fildes); -int sys_ptrace(long request, long pid, long addr, long data); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/include/asm-x86_64/mtrr.h b/include/asm-x86_64/mtrr.h index c5959d6418b..66ac1c0f27e 100644 --- a/include/asm-x86_64/mtrr.h +++ b/include/asm-x86_64/mtrr.h @@ -25,6 +25,7 @@ #include <linux/config.h> #include <linux/ioctl.h> +#include <linux/compat.h> #define MTRR_IOCTL_BASE 'M' @@ -105,4 +106,36 @@ static __inline__ int mtrr_del_page (int reg, unsigned long base, #endif +#ifdef CONFIG_COMPAT + +struct mtrr_sentry32 +{ + compat_ulong_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ +}; + +struct mtrr_gentry32 +{ + compat_ulong_t regnum; /* Register number */ + compat_uint_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ +}; + +#define MTRR_IOCTL_BASE 'M' + +#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32) +#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32) +#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32) +#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32) +#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32) +#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32) +#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32) +#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32) +#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32) +#define MTRRIOC32_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) + +#endif /* CONFIG_COMPAT */ + #endif /* _LINUX_MTRR_H */ diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index dd8711ecaf2..7a07196a720 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -318,8 +318,6 @@ static inline int pmd_large(pmd_t pte) { * and a page entry and page directory to the page they refer to. */ -#define page_pte(page) page_pte_prot(page, __pgprot(0)) - /* * Level 4 access. */ diff --git a/include/asm-x86_64/semaphore.h b/include/asm-x86_64/semaphore.h index f325e39bf3b..a389aa6fe80 100644 --- a/include/asm-x86_64/semaphore.h +++ b/include/asm-x86_64/semaphore.h @@ -56,9 +56,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name,1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 11ba931cf82..3c494b65d33 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -780,8 +780,6 @@ asmlinkage long sys_pipe(int *fildes); #include <linux/types.h> #include <asm/ptrace.h> -asmlinkage long sys_ptrace(long request, long pid, - unsigned long addr, long data); asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs); asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on); struct sigaction; diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h index 09e89ab3eb6..2a10e193b92 100644 --- a/include/asm-xtensa/semaphore.h +++ b/include/asm-xtensa/semaphore.h @@ -29,9 +29,6 @@ struct semaphore { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ } -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) diff --git a/include/keys/user-type.h b/include/keys/user-type.h new file mode 100644 index 00000000000..26f6ec38577 --- /dev/null +++ b/include/keys/user-type.h @@ -0,0 +1,47 @@ +/* user-type.h: User-defined key type + * + * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.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. + */ + +#ifndef _KEYS_USER_TYPE_H +#define _KEYS_USER_TYPE_H + +#include <linux/key.h> +#include <linux/rcupdate.h> + +/*****************************************************************************/ +/* + * the payload for a key of type "user" + * - once filled in and attached to a key: + * - the payload struct is invariant may not be changed, only replaced + * - the payload must be read with RCU procedures or with the key semaphore + * held + * - the payload may only be replaced with the key semaphore write-locked + * - the key's data length is the size of the actual data, not including the + * payload wrapper + */ +struct user_key_payload { + struct rcu_head rcu; /* RCU destructor */ + unsigned short datalen; /* length of this data */ + char data[0]; /* actual data */ +}; + +extern struct key_type key_type_user; + +extern int user_instantiate(struct key *key, const void *data, size_t datalen); +extern int user_duplicate(struct key *key, const struct key *source); +extern int user_update(struct key *key, const void *data, size_t datalen); +extern int user_match(const struct key *key, const void *criterion); +extern void user_destroy(struct key *key); +extern void user_describe(const struct key *user, struct seq_file *m); +extern long user_read(const struct key *key, + char __user *buffer, size_t buflen); + + +#endif /* _KEYS_USER_TYPE_H */ diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 86dd5502b05..7d8ff97b3e9 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -40,6 +40,8 @@ * bitmap_weight(src, nbits) Hamming Weight: number set bits * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n + * bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src) + * bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit) * bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf * bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf * bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf @@ -104,6 +106,10 @@ extern int bitmap_scnlistprintf(char *buf, unsigned int len, const unsigned long *src, int nbits); extern int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits); +extern void bitmap_remap(unsigned long *dst, const unsigned long *src, + const unsigned long *old, const unsigned long *new, int bits); +extern int bitmap_bitremap(int oldbit, + const unsigned long *old, const unsigned long *new, int bits); extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order); extern void bitmap_release_region(unsigned long *bitmap, int pos, int order); extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index c937d6e6550..1db061bb6b0 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -190,6 +190,7 @@ extern int buffer_heads_over_limit; */ int try_to_release_page(struct page * page, gfp_t gfp_mask); int block_invalidatepage(struct page *page, unsigned long offset); +int do_invalidatepage(struct page *page, unsigned long offset); int block_write_full_page(struct page *page, get_block_t *get_block, struct writeback_control *wbc); int block_read_full_page(struct page*, get_block_t*); diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 86980c68234..1f7b2c09750 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -32,6 +32,7 @@ struct cpu { }; extern int register_cpu(struct cpu *, int, struct node *); +extern struct sys_device *get_cpu_sysdev(int cpu); #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *, struct node *); #endif diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index ff7f80f48df..d068176b7ad 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -23,6 +23,7 @@ #include <linux/completion.h> #include <linux/workqueue.h> #include <linux/cpumask.h> +#include <asm/div64.h> #define CPUFREQ_NAME_LEN 16 diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 9bdba8169b4..13e9f4a3ab2 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -12,6 +12,8 @@ * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. * For details of cpulist_scnprintf() and cpulist_parse(), see * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c. + * For details of cpu_remap(), see bitmap_bitremap in lib/bitmap.c + * For details of cpus_remap(), see bitmap_remap in lib/bitmap.c. * * The available cpumask operations are: * @@ -50,6 +52,8 @@ * int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing * int cpulist_parse(buf, map) Parse ascii string as cpulist + * int cpu_remap(oldbit, old, new) newbit = map(old, new)(oldbit) + * int cpus_remap(dst, src, old, new) *dst = map(old, new)(src) * * for_each_cpu_mask(cpu, mask) for-loop cpu over mask * @@ -294,6 +298,22 @@ static inline int __cpulist_parse(const char *buf, cpumask_t *dstp, int nbits) return bitmap_parselist(buf, dstp->bits, nbits); } +#define cpu_remap(oldbit, old, new) \ + __cpu_remap((oldbit), &(old), &(new), NR_CPUS) +static inline int __cpu_remap(int oldbit, + const cpumask_t *oldp, const cpumask_t *newp, int nbits) +{ + return bitmap_bitremap(oldbit, oldp->bits, newp->bits, nbits); +} + +#define cpus_remap(dst, src, old, new) \ + __cpus_remap(&(dst), &(src), &(old), &(new), NR_CPUS) +static inline void __cpus_remap(cpumask_t *dstp, const cpumask_t *srcp, + const cpumask_t *oldp, const cpumask_t *newp, int nbits) +{ + bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits); +} + #if NR_CPUS > 1 #define for_each_cpu_mask(cpu, mask) \ for ((cpu) = first_cpu(mask); \ diff --git a/include/linux/dmi.h b/include/linux/dmi.h index a415f1d93e9..05f4132622f 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -60,7 +60,7 @@ struct dmi_device { void *device_data; /* Type specific data */ }; -#if defined(CONFIG_X86) && !defined(CONFIG_X86_64) +#if defined(CONFIG_X86_32) extern int dmi_check_system(struct dmi_system_id *list); extern char * dmi_get_system_info(int field); diff --git a/include/linux/fs.h b/include/linux/fs.h index f83d997c558..6d6226732c9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -574,7 +574,14 @@ struct file_ra_state { #define RA_FLAG_INCACHE 0x02 /* file is already in cache */ struct file { - struct list_head f_list; + /* + * fu_list becomes invalid after file_free is called and queued via + * fu_rcuhead for RCU freeing + */ + union { + struct list_head fu_list; + struct rcu_head fu_rcuhead; + } f_u; struct dentry *f_dentry; struct vfsmount *f_vfsmnt; struct file_operations *f_op; @@ -598,7 +605,6 @@ struct file { spinlock_t f_ep_lock; #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; - struct rcu_head f_rcuhead; }; extern spinlock_t files_lock; #define file_list_lock() spin_lock(&files_lock); diff --git a/include/linux/fuse.h b/include/linux/fuse.h index acbeb96a335..f98854c2abd 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -61,7 +61,6 @@ struct fuse_kstatfs { #define FATTR_SIZE (1 << 3) #define FATTR_ATIME (1 << 4) #define FATTR_MTIME (1 << 5) -#define FATTR_CTIME (1 << 6) /** * Flags returned by the OPEN request diff --git a/include/linux/gameport.h b/include/linux/gameport.h index cd623eccdbe..2401dea2b86 100644 --- a/include/linux/gameport.h +++ b/include/linux/gameport.h @@ -12,6 +12,7 @@ #include <asm/io.h> #include <linux/list.h> #include <linux/device.h> +#include <linux/timer.h> struct gameport { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index f88577ca3b3..5e19a7ba69b 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -31,6 +31,7 @@ #include <linux/i2c-id.h> #include <linux/mod_devicetable.h> #include <linux/device.h> /* for struct device */ +#include <linux/sched.h> /* for completion */ #include <asm/semaphore.h> /* --- For i2c-isa ---------------------------------------------------- */ diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 92300325dbc..d79c8a4bc4f 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -25,10 +25,14 @@ /* How many different OSM's are we allowing */ #define I2O_MAX_DRIVERS 8 -#include <asm/io.h> -#include <asm/semaphore.h> /* Needed for MUTEX init macros */ #include <linux/pci.h> #include <linux/dma-mapping.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/workqueue.h> /* work_struct */ + +#include <asm/io.h> +#include <asm/semaphore.h> /* Needed for MUTEX init macros */ /* message queue empty */ #define I2O_QUEUE_EMPTY 0xffffffff diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4367ce4db52..f1925ccc9fe 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -307,7 +307,7 @@ struct sysinfo { char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ }; -/* Force a compilation error if condition is false */ +/* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) #ifdef CONFIG_SYSCTL diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h index 7a2e332067c..e8b8a7a5c49 100644 --- a/include/linux/key-ui.h +++ b/include/linux/key-ui.h @@ -24,7 +24,8 @@ extern spinlock_t key_serial_lock; #define KEY_WRITE 0x04 /* require permission to update / modify */ #define KEY_SEARCH 0x08 /* require permission to search (keyring) or find (key) */ #define KEY_LINK 0x10 /* require permission to link */ -#define KEY_ALL 0x1f /* all the above permissions */ +#define KEY_SETATTR 0x20 /* require permission to change attributes */ +#define KEY_ALL 0x3f /* all the above permissions */ /* * the keyring payload contains a list of the keys to which the keyring is diff --git a/include/linux/key.h b/include/linux/key.h index f1efa016dbf..53513a3be53 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -40,28 +40,32 @@ struct key; #define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */ #define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */ #define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */ -#define KEY_POS_ALL 0x1f000000 +#define KEY_POS_SETATTR 0x20000000 /* possessor can set key attributes */ +#define KEY_POS_ALL 0x3f000000 #define KEY_USR_VIEW 0x00010000 /* user permissions... */ #define KEY_USR_READ 0x00020000 #define KEY_USR_WRITE 0x00040000 #define KEY_USR_SEARCH 0x00080000 #define KEY_USR_LINK 0x00100000 -#define KEY_USR_ALL 0x001f0000 +#define KEY_USR_SETATTR 0x00200000 +#define KEY_USR_ALL 0x003f0000 #define KEY_GRP_VIEW 0x00000100 /* group permissions... */ #define KEY_GRP_READ 0x00000200 #define KEY_GRP_WRITE 0x00000400 #define KEY_GRP_SEARCH 0x00000800 #define KEY_GRP_LINK 0x00001000 -#define KEY_GRP_ALL 0x00001f00 +#define KEY_GRP_SETATTR 0x00002000 +#define KEY_GRP_ALL 0x00003f00 #define KEY_OTH_VIEW 0x00000001 /* third party permissions... */ #define KEY_OTH_READ 0x00000002 #define KEY_OTH_WRITE 0x00000004 #define KEY_OTH_SEARCH 0x00000008 #define KEY_OTH_LINK 0x00000010 -#define KEY_OTH_ALL 0x0000001f +#define KEY_OTH_SETATTR 0x00000020 +#define KEY_OTH_ALL 0x0000003f struct seq_file; struct user_struct; @@ -119,6 +123,7 @@ struct key { struct key_type *type; /* type of key */ struct rw_semaphore sem; /* change vs change sem */ struct key_user *user; /* owner of this key */ + void *security; /* security data for this key */ time_t expiry; /* time at which key expires (or 0) */ uid_t uid; gid_t gid; diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h index b6cc10bf8df..cbe7d800804 100644 --- a/include/linux/kobj_map.h +++ b/include/linux/kobj_map.h @@ -1,5 +1,7 @@ #ifdef __KERNEL__ +#include <asm/semaphore.h> + typedef struct kobject *kobj_probe_t(dev_t, int *, void *); struct kobj_map; diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 3fa786448db..ebdd41fd108 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -70,6 +70,18 @@ void kthread_bind(struct task_struct *k, unsigned int cpu); int kthread_stop(struct task_struct *k); /** + * kthread_stop_sem: stop a thread created by kthread_create(). + * @k: thread created by kthread_create(). + * @s: semaphore that @k waits on while idle. + * + * Does essentially the same thing as kthread_stop() above, but wakes + * @k by calling up(@s). + * + * Returns the result of threadfn(), or -EINTR if wake_up_process() + * was never called. */ +int kthread_stop_sem(struct task_struct *k, struct semaphore *s); + +/** * kthread_should_stop: should this kthread return now? * * When someone calls kthread_stop on your kthread, it will be woken diff --git a/include/linux/libata.h b/include/linux/libata.h index 00a8a573885..0ba3af7a123 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -172,6 +172,13 @@ enum hsm_task_states { HSM_ST_ERR, }; +enum ata_completion_errors { + AC_ERR_OTHER = (1 << 0), + AC_ERR_DEV = (1 << 1), + AC_ERR_ATA_BUS = (1 << 2), + AC_ERR_HOST_BUS = (1 << 3), +}; + /* forward declarations */ struct scsi_device; struct ata_port_operations; @@ -179,7 +186,7 @@ struct ata_port; struct ata_queued_cmd; /* typedefs */ -typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat); +typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int err_mask); struct ata_ioports { unsigned long cmd_addr; @@ -347,7 +354,6 @@ struct ata_port_operations { void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf); u8 (*check_status)(struct ata_port *ap); u8 (*check_altstatus)(struct ata_port *ap); - u8 (*check_err)(struct ata_port *ap); void (*dev_select)(struct ata_port *ap, unsigned int device); void (*phy_reset) (struct ata_port *ap); @@ -434,7 +440,6 @@ extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device); extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap); -extern u8 ata_chk_err(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); @@ -455,7 +460,7 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); -extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); +extern void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask); extern void ata_eng_timeout(struct ata_port *ap); extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); @@ -718,4 +723,21 @@ static inline int ata_try_flush_cache(const struct ata_device *dev) ata_id_has_flush_ext(dev->id); } +static inline unsigned int ac_err_mask(u8 status) +{ + if (status & ATA_BUSY) + return AC_ERR_ATA_BUS; + if (status & (ATA_ERR | ATA_DF)) + return AC_ERR_DEV; + return 0; +} + +static inline unsigned int __ac_err_mask(u8 status) +{ + unsigned int mask = ac_err_mask(status); + if (mask == 0) + return AC_ERR_OTHER; + return mask; +} + #endif /* __LINUX_LIBATA_H__ */ diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 7af8cb836e7..8b67cf837ca 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -154,6 +154,7 @@ struct mempolicy *get_vma_policy(struct task_struct *task, extern void numa_default_policy(void); extern void numa_policy_init(void); +extern void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new); extern struct mempolicy default_policy; #else @@ -226,6 +227,11 @@ static inline void numa_default_policy(void) { } +static inline void numa_policy_rebind(const nodemask_t *old, + const nodemask_t *new) +{ +} + #endif /* CONFIG_NUMA */ #endif /* __KERNEL__ */ diff --git a/include/linux/module.h b/include/linux/module.h index f05372b7fe7..84d75f3a8ac 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -554,7 +554,9 @@ static inline void MODULE_PARM_(void) { } #ifdef MODULE /* DEPRECATED: Do not use. */ #define MODULE_PARM(var,type) \ -struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \ +extern struct obsolete_modparm __parm_##var \ +__attribute__((section("__obsparm"))); \ +struct obsolete_modparm __parm_##var = \ { __stringify(var), type, &MODULE_PARM_ }; \ __MODULE_PARM_TYPE(var, type); #else diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 9a3d2725798..941da5c016a 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -282,6 +282,17 @@ static inline u8 fat_attr(struct inode *inode) MSDOS_I(inode)->i_attrs; } +static inline unsigned char fat_checksum(const __u8 *name) +{ + unsigned char s = name[0]; + s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2]; + s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4]; + s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6]; + s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8]; + s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10]; + return s; +} + static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) { return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 142963f01d2..fc28841f340 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -8,7 +8,10 @@ #include <linux/config.h> #include <linux/types.h> #include <linux/list.h> +#include <linux/string.h> + #include <linux/mtd/compatmac.h> + #include <asm/unaligned.h> #include <asm/system.h> #include <asm/io.h> diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index e96fe906250..4726ef7ba8e 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -12,6 +12,8 @@ * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. * For details of nodelist_scnprintf() and nodelist_parse(), see * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c. + * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c. + * For details of nodes_remap(), see bitmap_remap in lib/bitmap.c. * * The available nodemask operations are: * @@ -52,6 +54,8 @@ * int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing * int nodelist_parse(buf, map) Parse ascii string as nodelist + * int node_remap(oldbit, old, new) newbit = map(old, new)(oldbit) + * int nodes_remap(dst, src, old, new) *dst = map(old, new)(dst) * * for_each_node_mask(node, mask) for-loop node over mask * @@ -307,6 +311,22 @@ static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits) return bitmap_parselist(buf, dstp->bits, nbits); } +#define node_remap(oldbit, old, new) \ + __node_remap((oldbit), &(old), &(new), MAX_NUMNODES) +static inline int __node_remap(int oldbit, + const nodemask_t *oldp, const nodemask_t *newp, int nbits) +{ + return bitmap_bitremap(oldbit, oldp->bits, newp->bits, nbits); +} + +#define nodes_remap(dst, src, old, new) \ + __nodes_remap(&(dst), &(src), &(old), &(new), MAX_NUMNODES) +static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp, + const nodemask_t *oldp, const nodemask_t *newp, int nbits) +{ + bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits); +} + #if MAX_NUMNODES > 1 #define for_each_node_mask(node, mask) \ for ((node) = first_node(mask); \ diff --git a/include/linux/pm.h b/include/linux/pm.h index c61d5de837e..1514098d156 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -170,6 +170,7 @@ typedef int __bitwise suspend_disk_method_t; struct pm_ops { suspend_disk_method_t pm_disk_mode; + int (*valid)(suspend_state_t state); int (*prepare)(suspend_state_t state); int (*enter)(suspend_state_t state); int (*finish)(suspend_state_t state); diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 70191a5a148..cce25591eec 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -275,6 +275,7 @@ static inline int rcu_pending(int cpu) extern void rcu_init(void); extern void rcu_check_callbacks(int cpu, int user); extern void rcu_restart_cpu(int cpu); +extern long rcu_batches_completed(void); /* Exported interfaces */ extern void FASTCALL(call_rcu(struct rcu_head *head, diff --git a/include/linux/sched.h b/include/linux/sched.h index 1c30bc308ef..03b68a7b4b8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -940,7 +940,7 @@ extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); #else static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask) { - if (!cpus_intersects(new_mask, cpu_online_map)) + if (!cpu_isset(0, new_mask)) return -EINVAL; return 0; } @@ -1084,6 +1084,11 @@ extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned lon #define SEND_SIG_PRIV ((struct siginfo *) 1) #define SEND_SIG_FORCED ((struct siginfo *) 2) +static inline int is_si_special(const struct siginfo *info) +{ + return info <= SEND_SIG_FORCED; +} + /* True if we are on the alternate signal stack. */ static inline int on_sig_stack(unsigned long sp) @@ -1211,7 +1216,7 @@ extern void unhash_process(struct task_struct *p); /* * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring * subscriptions and synchronises with wait4(). Also used in procfs. Also - * pins the final release of task.io_context. + * pins the final release of task.io_context. Also protects ->cpuset. * * Nests both inside and outside of read_lock(&tasklist_lock). * It must not be nested with write_lock_irq(&tasklist_lock), diff --git a/include/linux/security.h b/include/linux/security.h index dac956ed98f..f7e0ae01871 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -30,6 +30,7 @@ #include <linux/shm.h> #include <linux/msg.h> #include <linux/sched.h> +#include <linux/key.h> struct ctl_table; @@ -385,6 +386,9 @@ struct swap_info_struct; * NULL to request the size of the buffer required. @size indicates * the size of @buffer in bytes. Note that @name is the remainder * of the attribute name after the security. prefix has been removed. + * @err is the return value from the preceding fs getxattr call, + * and can be used by the security module to determine whether it + * should try and canonicalize the attribute value. * Return number of bytes used/required on success. * @inode_setsecurity: * Set the security label associated with @name for @inode from the @@ -785,6 +789,27 @@ struct swap_info_struct; * @sk_free_security: * Deallocate security structure. * + * Security hooks affecting all Key Management operations + * + * @key_alloc: + * Permit allocation of a key and assign security data. Note that key does + * not have a serial number assigned at this point. + * @key points to the key. + * Return 0 if permission is granted, -ve error otherwise. + * @key_free: + * Notification of destruction; free security data. + * @key points to the key. + * No return value. + * @key_permission: + * See whether a specific operational right is granted to a process on a + * key. + * @key_ref refers to the key (key pointer + possession attribute bit). + * @context points to the process to provide the context against which to + * evaluate the security data on the key. + * @perm describes the combination of permissions required of this key. + * Return 1 if permission granted, 0 if permission denied and -ve it the + * normal permissions model should be effected. + * * Security hooks affecting all System V IPC operations. * * @ipc_permission: @@ -1091,7 +1116,7 @@ struct security_operations { int (*inode_getxattr) (struct dentry *dentry, char *name); int (*inode_listxattr) (struct dentry *dentry); int (*inode_removexattr) (struct dentry *dentry, char *name); - int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size); + int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size, int err); int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); @@ -1213,6 +1238,17 @@ struct security_operations { int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); void (*sk_free_security) (struct sock *sk); #endif /* CONFIG_SECURITY_NETWORK */ + + /* key management security hooks */ +#ifdef CONFIG_KEYS + int (*key_alloc)(struct key *key); + void (*key_free)(struct key *key); + int (*key_permission)(key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm); + +#endif /* CONFIG_KEYS */ + }; /* global variables */ @@ -1580,11 +1616,11 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name) return security_ops->inode_removexattr (dentry, name); } -static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) +static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) { if (unlikely (IS_PRIVATE (inode))) return 0; - return security_ops->inode_getsecurity(inode, name, buffer, size); + return security_ops->inode_getsecurity(inode, name, buffer, size, err); } static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) @@ -2222,7 +2258,7 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name) return cap_inode_removexattr(dentry, name); } -static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) +static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) { return -EOPNOTSUPP; } @@ -2761,5 +2797,45 @@ static inline void security_sk_free(struct sock *sk) } #endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_KEYS +#ifdef CONFIG_SECURITY +static inline int security_key_alloc(struct key *key) +{ + return security_ops->key_alloc(key); +} + +static inline void security_key_free(struct key *key) +{ + security_ops->key_free(key); +} + +static inline int security_key_permission(key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm) +{ + return security_ops->key_permission(key_ref, context, perm); +} + +#else + +static inline int security_key_alloc(struct key *key) +{ + return 0; +} + +static inline void security_key_free(struct key *key) +{ +} + +static inline int security_key_permission(key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm) +{ + return 0; +} + +#endif +#endif /* CONFIG_KEYS */ + #endif /* ! __LINUX_SECURITY_H */ diff --git a/include/linux/serial.h b/include/linux/serial.h index 12cd9cf65e8..33fc8cb8ddf 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -11,6 +11,7 @@ #define _LINUX_SERIAL_H #ifdef __KERNEL__ +#include <linux/types.h> #include <asm/page.h> /* diff --git a/include/linux/signal.h b/include/linux/signal.h index 7be18b5e2fb..5dd5f02c5c5 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -25,7 +25,6 @@ struct sigqueue { struct list_head list; - spinlock_t *lock; int flags; siginfo_t info; struct user_struct *user; diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index cdc99a27840..0e9682c9def 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -171,23 +171,42 @@ extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); #define write_lock_irq(lock) _write_lock_irq(lock) #define write_lock_bh(lock) _write_lock_bh(lock) -#define spin_unlock(lock) _spin_unlock(lock) -#define write_unlock(lock) _write_unlock(lock) -#define read_unlock(lock) _read_unlock(lock) +/* + * We inline the unlock functions in the nondebug case: + */ +#if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) +# define spin_unlock(lock) _spin_unlock(lock) +# define read_unlock(lock) _read_unlock(lock) +# define write_unlock(lock) _write_unlock(lock) +#else +# define spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock) +# define read_unlock(lock) __raw_read_unlock(&(lock)->raw_lock) +# define write_unlock(lock) __raw_write_unlock(&(lock)->raw_lock) +#endif + +#if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) +# define spin_unlock_irq(lock) _spin_unlock_irq(lock) +# define read_unlock_irq(lock) _read_unlock_irq(lock) +# define write_unlock_irq(lock) _write_unlock_irq(lock) +#else +# define spin_unlock_irq(lock) \ + do { __raw_spin_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0) +# define read_unlock_irq(lock) \ + do { __raw_read_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0) +# define write_unlock_irq(lock) \ + do { __raw_write_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0) +#endif #define spin_unlock_irqrestore(lock, flags) \ _spin_unlock_irqrestore(lock, flags) -#define spin_unlock_irq(lock) _spin_unlock_irq(lock) #define spin_unlock_bh(lock) _spin_unlock_bh(lock) #define read_unlock_irqrestore(lock, flags) \ _read_unlock_irqrestore(lock, flags) -#define read_unlock_irq(lock) _read_unlock_irq(lock) #define read_unlock_bh(lock) _read_unlock_bh(lock) #define write_unlock_irqrestore(lock, flags) \ _write_unlock_irqrestore(lock, flags) -#define write_unlock_irq(lock) _write_unlock_irq(lock) #define write_unlock_bh(lock) _write_unlock_bh(lock) #define spin_trylock_bh(lock) __cond_lock(_spin_trylock_bh(lock)) diff --git a/include/linux/suspend.h b/include/linux/suspend.h index ba448c76016..a61c04f804b 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -71,7 +71,12 @@ void restore_processor_state(void); struct saved_context; void __save_processor_state(struct saved_context *ctxt); void __restore_processor_state(struct saved_context *ctxt); -extern unsigned long get_usable_page(gfp_t gfp_mask); -extern void free_eaten_memory(void); +unsigned long get_safe_page(gfp_t gfp_mask); + +/* + * XXX: We try to keep some more pages free so that I/O operations succeed + * without paging. Might this be more? + */ +#define PAGES_FOR_IO 512 #endif /* _LINUX_SWSUSP_H */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a6f03e47373..c7007b1db91 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -491,6 +491,7 @@ asmlinkage long sys_nfsservctl(int cmd, asmlinkage long sys_syslog(int type, char __user *buf, int len); asmlinkage long sys_uselib(const char __user *library); asmlinkage long sys_ni_syscall(void); +asmlinkage long sys_ptrace(long request, long pid, long addr, long data); asmlinkage long sys_add_key(const char __user *_type, const char __user *_description, diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h index fc5bb4e91a5..7dac8f04d28 100644 --- a/include/linux/textsearch.h +++ b/include/linux/textsearch.h @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/err.h> +#include <linux/slab.h> struct ts_config; diff --git a/include/linux/timer.h b/include/linux/timer.h index 3340f3bd135..72f3a778110 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -12,16 +12,12 @@ struct timer_list { struct list_head entry; unsigned long expires; - unsigned long magic; - void (*function)(unsigned long); unsigned long data; struct timer_base_s *base; }; -#define TIMER_MAGIC 0x4b87ad6e - extern struct timer_base_s __init_timer_base; #define TIMER_INITIALIZER(_function, _expires, _data) { \ @@ -29,7 +25,6 @@ extern struct timer_base_s __init_timer_base; .expires = (_expires), \ .data = (_data), \ .base = &__init_timer_base, \ - .magic = TIMER_MAGIC, \ } #define DEFINE_TIMER(_name, _function, _expires, _data) \ @@ -38,6 +33,15 @@ extern struct timer_base_s __init_timer_base; void fastcall init_timer(struct timer_list * timer); +static inline void setup_timer(struct timer_list * timer, + void (*function)(unsigned long), + unsigned long data) +{ + timer->function = function; + timer->data = data; + init_timer(timer); +} + /*** * timer_pending - is a timer pending? * @timer: the timer in question @@ -74,8 +78,9 @@ extern unsigned long next_timer_interrupt(void); * Timers with an ->expired field in the past will be executed in the next * timer tick. */ -static inline void add_timer(struct timer_list * timer) +static inline void add_timer(struct timer_list *timer) { + BUG_ON(timer_pending(timer)); __mod_timer(timer, timer->expires); } diff --git a/include/linux/timex.h b/include/linux/timex.h index 7e050a2cc35..04a4a8cb4ed 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -282,6 +282,13 @@ static inline int ntp_synced(void) return !(time_status & STA_UNSYNC); } +/* Required to safely shift negative values */ +#define shift_right(x, s) ({ \ + __typeof__(x) __x = (x); \ + __typeof__(s) __s = (s); \ + __x < 0 ? -(-__x >> __s) : __x >> __s; \ +}) + #ifdef CONFIG_TIME_INTERPOLATION diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index c8592c7e8ea..e788bbc5657 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -17,6 +17,7 @@ #include <linux/config.h> #include <linux/device.h> +#include <linux/sched.h> /* task_struct, completion */ #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index e6b61fab66d..7529f4388bb 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -4,6 +4,7 @@ #include <linux/dma-mapping.h> #include <linux/list.h> #include <linux/types.h> +#include <linux/timer.h> struct request; struct scatterlist; diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index b0d44543737..c04405bead2 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -28,6 +28,7 @@ #define SCSI_TRANSPORT_FC_H #include <linux/config.h> +#include <linux/sched.h> struct scsi_transport_template; diff --git a/init/Kconfig b/init/Kconfig index d5a1a1228fa..3dcbd5bfd49 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -60,8 +60,8 @@ config INIT_ENV_ARG_LIMIT default 32 if !USERMODE default 128 if USERMODE help - This is the value of the two limits on the number of argument and of - env.var passed to init from the kernel command line. + Maximum of each of the number of arguments and environment + variables passed to init from the kernel command line. endmenu diff --git a/init/main.c b/init/main.c index f142d403534..4075d97e94b 100644 --- a/init/main.c +++ b/init/main.c @@ -64,10 +64,6 @@ #endif #endif -#ifdef CONFIG_X86_LOCAL_APIC -#include <asm/smp.h> -#endif - /* * Versions of gcc older than that listed below may actually compile * and link okay, but the end product can have subtle run time bugs. @@ -314,14 +310,7 @@ extern void setup_arch(char **); #ifndef CONFIG_SMP -#ifdef CONFIG_X86_LOCAL_APIC -static void __init smp_init(void) -{ - APIC_init_uniprocessor(); -} -#else #define smp_init() do { } while (0) -#endif static inline void setup_per_cpu_areas(void) { } static inline void smp_prepare_cpus(unsigned int maxcpus) { } diff --git a/kernel/Makefile b/kernel/Makefile index ff4dc02ce17..4f5a1453093 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_CPUSETS) += cpuset.o obj-$(CONFIG_IKCONFIG) += configs.o -obj-$(CONFIG_IKCONFIG_PROC) += configs.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o @@ -32,6 +31,7 @@ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SECCOMP) += seccomp.o +obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is diff --git a/kernel/cpu.c b/kernel/cpu.c index 53d8263ae12..3619e939182 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -17,6 +17,7 @@ /* This protects CPUs going up and down... */ DECLARE_MUTEX(cpucontrol); +EXPORT_SYMBOL_GPL(cpucontrol); static struct notifier_block *cpu_chain; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 28176d083f7..5a737ed9dac 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -32,6 +32,7 @@ #include <linux/kernel.h> #include <linux/kmod.h> #include <linux/list.h> +#include <linux/mempolicy.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/mount.h> @@ -60,6 +61,9 @@ struct cpuset { cpumask_t cpus_allowed; /* CPUs allowed to tasks in cpuset */ nodemask_t mems_allowed; /* Memory Nodes allowed to tasks */ + /* + * Count is atomic so can incr (fork) or decr (exit) without a lock. + */ atomic_t count; /* count tasks using this cpuset */ /* @@ -142,80 +146,91 @@ static struct vfsmount *cpuset_mount; static struct super_block *cpuset_sb = NULL; /* - * cpuset_sem should be held by anyone who is depending on the children - * or sibling lists of any cpuset, or performing non-atomic operations - * on the flags or *_allowed values of a cpuset, such as raising the - * CS_REMOVED flag bit iff it is not already raised, or reading and - * conditionally modifying the *_allowed values. One kernel global - * cpuset semaphore should be sufficient - these things don't change - * that much. - * - * The code that modifies cpusets holds cpuset_sem across the entire - * operation, from cpuset_common_file_write() down, single threading - * all cpuset modifications (except for counter manipulations from - * fork and exit) across the system. This presumes that cpuset - * modifications are rare - better kept simple and safe, even if slow. - * - * The code that reads cpusets, such as in cpuset_common_file_read() - * and below, only holds cpuset_sem across small pieces of code, such - * as when reading out possibly multi-word cpumasks and nodemasks, as - * the risks are less, and the desire for performance a little greater. - * The proc_cpuset_show() routine needs to hold cpuset_sem to insure - * that no cs->dentry is NULL, as it walks up the cpuset tree to root. - * - * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't - * (usually) grab cpuset_sem. These are the two most performance - * critical pieces of code here. The exception occurs on exit(), - * when a task in a notify_on_release cpuset exits. Then cpuset_sem + * We have two global cpuset semaphores below. They can nest. + * It is ok to first take manage_sem, then nest callback_sem. We also + * require taking task_lock() when dereferencing a tasks cpuset pointer. + * See "The task_lock() exception", at the end of this comment. + * + * A task must hold both semaphores to modify cpusets. If a task + * holds manage_sem, then it blocks others wanting that semaphore, + * ensuring that it is the only task able to also acquire callback_sem + * and be able to modify cpusets. It can perform various checks on + * the cpuset structure first, knowing nothing will change. It can + * also allocate memory while just holding manage_sem. While it is + * performing these checks, various callback routines can briefly + * acquire callback_sem to query cpusets. Once it is ready to make + * the changes, it takes callback_sem, blocking everyone else. + * + * Calls to the kernel memory allocator can not be made while holding + * callback_sem, as that would risk double tripping on callback_sem + * from one of the callbacks into the cpuset code from within + * __alloc_pages(). + * + * If a task is only holding callback_sem, then it has read-only + * access to cpusets. + * + * The task_struct fields mems_allowed and mems_generation may only + * be accessed in the context of that task, so require no locks. + * + * Any task can increment and decrement the count field without lock. + * So in general, code holding manage_sem or callback_sem can't rely + * on the count field not changing. However, if the count goes to + * zero, then only attach_task(), which holds both semaphores, can + * increment it again. Because a count of zero means that no tasks + * are currently attached, therefore there is no way a task attached + * to that cpuset can fork (the other way to increment the count). + * So code holding manage_sem or callback_sem can safely assume that + * if the count is zero, it will stay zero. Similarly, if a task + * holds manage_sem or callback_sem on a cpuset with zero count, it + * knows that the cpuset won't be removed, as cpuset_rmdir() needs + * both of those semaphores. + * + * A possible optimization to improve parallelism would be to make + * callback_sem a R/W semaphore (rwsem), allowing the callback routines + * to proceed in parallel, with read access, until the holder of + * manage_sem needed to take this rwsem for exclusive write access + * and modify some cpusets. + * + * The cpuset_common_file_write handler for operations that modify + * the cpuset hierarchy holds manage_sem across the entire operation, + * single threading all such cpuset modifications across the system. + * + * The cpuset_common_file_read() handlers only hold callback_sem across + * small pieces of code, such as when reading out possibly multi-word + * cpumasks and nodemasks. + * + * The fork and exit callbacks cpuset_fork() and cpuset_exit(), don't + * (usually) take either semaphore. These are the two most performance + * critical pieces of code here. The exception occurs on cpuset_exit(), + * when a task in a notify_on_release cpuset exits. Then manage_sem * is taken, and if the cpuset count is zero, a usermode call made * to /sbin/cpuset_release_agent with the name of the cpuset (path * relative to the root of cpuset file system) as the argument. * - * A cpuset can only be deleted if both its 'count' of using tasks is - * zero, and its list of 'children' cpusets is empty. Since all tasks - * in the system use _some_ cpuset, and since there is always at least - * one task in the system (init, pid == 1), therefore, top_cpuset - * always has either children cpusets and/or using tasks. So no need - * for any special hack to ensure that top_cpuset cannot be deleted. + * A cpuset can only be deleted if both its 'count' of using tasks + * is zero, and its list of 'children' cpusets is empty. Since all + * tasks in the system use _some_ cpuset, and since there is always at + * least one task in the system (init, pid == 1), therefore, top_cpuset + * always has either children cpusets and/or using tasks. So we don't + * need a special hack to ensure that top_cpuset cannot be deleted. + * + * The above "Tale of Two Semaphores" would be complete, but for: + * + * The task_lock() exception + * + * The need for this exception arises from the action of attach_task(), + * which overwrites one tasks cpuset pointer with another. It does + * so using both semaphores, however there are several performance + * critical places that need to reference task->cpuset without the + * expense of grabbing a system global semaphore. Therefore except as + * noted below, when dereferencing or, as in attach_task(), modifying + * a tasks cpuset pointer we use task_lock(), which acts on a spinlock + * (task->alloc_lock) already in the task_struct routinely used for + * such matters. */ -static DECLARE_MUTEX(cpuset_sem); -static struct task_struct *cpuset_sem_owner; -static int cpuset_sem_depth; - -/* - * The global cpuset semaphore cpuset_sem can be needed by the - * memory allocator to update a tasks mems_allowed (see the calls - * to cpuset_update_current_mems_allowed()) or to walk up the - * cpuset hierarchy to find a mem_exclusive cpuset see the calls - * to cpuset_excl_nodes_overlap()). - * - * But if the memory allocation is being done by cpuset.c code, it - * usually already holds cpuset_sem. Double tripping on a kernel - * semaphore deadlocks the current task, and any other task that - * subsequently tries to obtain the lock. - * - * Run all up's and down's on cpuset_sem through the following - * wrappers, which will detect this nested locking, and avoid - * deadlocking. - */ - -static inline void cpuset_down(struct semaphore *psem) -{ - if (cpuset_sem_owner != current) { - down(psem); - cpuset_sem_owner = current; - } - cpuset_sem_depth++; -} - -static inline void cpuset_up(struct semaphore *psem) -{ - if (--cpuset_sem_depth == 0) { - cpuset_sem_owner = NULL; - up(psem); - } -} +static DECLARE_MUTEX(manage_sem); +static DECLARE_MUTEX(callback_sem); /* * A couple of forward declarations required, due to cyclic reference loop: @@ -390,7 +405,7 @@ static inline struct cftype *__d_cft(struct dentry *dentry) } /* - * Call with cpuset_sem held. Writes path of cpuset into buf. + * Call with manage_sem held. Writes path of cpuset into buf. * Returns 0 on success, -errno on error. */ @@ -442,10 +457,11 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen) * status of the /sbin/cpuset_release_agent task, so no sense holding * our caller up for that. * - * The simple act of forking that task might require more memory, - * which might need cpuset_sem. So this routine must be called while - * cpuset_sem is not held, to avoid a possible deadlock. See also - * comments for check_for_release(), below. + * When we had only one cpuset semaphore, we had to call this + * without holding it, to avoid deadlock when call_usermodehelper() + * allocated memory. With two locks, we could now call this while + * holding manage_sem, but we still don't, so as to minimize + * the time manage_sem is held. */ static void cpuset_release_agent(const char *pathbuf) @@ -477,15 +493,15 @@ static void cpuset_release_agent(const char *pathbuf) * cs is notify_on_release() and now both the user count is zero and * the list of children is empty, prepare cpuset path in a kmalloc'd * buffer, to be returned via ppathbuf, so that the caller can invoke - * cpuset_release_agent() with it later on, once cpuset_sem is dropped. - * Call here with cpuset_sem held. + * cpuset_release_agent() with it later on, once manage_sem is dropped. + * Call here with manage_sem held. * * This check_for_release() routine is responsible for kmalloc'ing * pathbuf. The above cpuset_release_agent() is responsible for * kfree'ing pathbuf. The caller of these routines is responsible * for providing a pathbuf pointer, initialized to NULL, then - * calling check_for_release() with cpuset_sem held and the address - * of the pathbuf pointer, then dropping cpuset_sem, then calling + * calling check_for_release() with manage_sem held and the address + * of the pathbuf pointer, then dropping manage_sem, then calling * cpuset_release_agent() with pathbuf, as set by check_for_release(). */ @@ -516,7 +532,7 @@ static void check_for_release(struct cpuset *cs, char **ppathbuf) * One way or another, we guarantee to return some non-empty subset * of cpu_online_map. * - * Call with cpuset_sem held. + * Call with callback_sem held. */ static void guarantee_online_cpus(const struct cpuset *cs, cpumask_t *pmask) @@ -540,7 +556,7 @@ static void guarantee_online_cpus(const struct cpuset *cs, cpumask_t *pmask) * One way or another, we guarantee to return some non-empty subset * of node_online_map. * - * Call with cpuset_sem held. + * Call with callback_sem held. */ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask) @@ -555,22 +571,47 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask) } /* - * Refresh current tasks mems_allowed and mems_generation from - * current tasks cpuset. Call with cpuset_sem held. + * Refresh current tasks mems_allowed and mems_generation from current + * tasks cpuset. * - * This routine is needed to update the per-task mems_allowed - * data, within the tasks context, when it is trying to allocate - * memory (in various mm/mempolicy.c routines) and notices - * that some other task has been modifying its cpuset. + * Call without callback_sem or task_lock() held. May be called with + * or without manage_sem held. Will acquire task_lock() and might + * acquire callback_sem during call. + * + * The task_lock() is required to dereference current->cpuset safely. + * Without it, we could pick up the pointer value of current->cpuset + * in one instruction, and then attach_task could give us a different + * cpuset, and then the cpuset we had could be removed and freed, + * and then on our next instruction, we could dereference a no longer + * valid cpuset pointer to get its mems_generation field. + * + * This routine is needed to update the per-task mems_allowed data, + * within the tasks context, when it is trying to allocate memory + * (in various mm/mempolicy.c routines) and notices that some other + * task has been modifying its cpuset. */ static void refresh_mems(void) { - struct cpuset *cs = current->cpuset; + int my_cpusets_mem_gen; + + task_lock(current); + my_cpusets_mem_gen = current->cpuset->mems_generation; + task_unlock(current); - if (current->cpuset_mems_generation != cs->mems_generation) { + if (current->cpuset_mems_generation != my_cpusets_mem_gen) { + struct cpuset *cs; + nodemask_t oldmem = current->mems_allowed; + + down(&callback_sem); + task_lock(current); + cs = current->cpuset; guarantee_online_mems(cs, ¤t->mems_allowed); current->cpuset_mems_generation = cs->mems_generation; + task_unlock(current); + up(&callback_sem); + if (!nodes_equal(oldmem, current->mems_allowed)) + numa_policy_rebind(&oldmem, ¤t->mems_allowed); } } @@ -579,7 +620,7 @@ static void refresh_mems(void) * * One cpuset is a subset of another if all its allowed CPUs and * Memory Nodes are a subset of the other, and its exclusive flags - * are only set if the other's are set. + * are only set if the other's are set. Call holding manage_sem. */ static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q) @@ -597,7 +638,7 @@ static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q) * If we replaced the flag and mask values of the current cpuset * (cur) with those values in the trial cpuset (trial), would * our various subset and exclusive rules still be valid? Presumes - * cpuset_sem held. + * manage_sem held. * * 'cur' is the address of an actual, in-use cpuset. Operations * such as list traversal that depend on the actual address of the @@ -651,7 +692,7 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) * exclusive child cpusets * Build these two partitions by calling partition_sched_domains * - * Call with cpuset_sem held. May nest a call to the + * Call with manage_sem held. May nest a call to the * lock_cpu_hotplug()/unlock_cpu_hotplug() pair. */ @@ -696,6 +737,10 @@ static void update_cpu_domains(struct cpuset *cur) unlock_cpu_hotplug(); } +/* + * Call with manage_sem held. May take callback_sem during call. + */ + static int update_cpumask(struct cpuset *cs, char *buf) { struct cpuset trialcs; @@ -712,12 +757,18 @@ static int update_cpumask(struct cpuset *cs, char *buf) if (retval < 0) return retval; cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed); + down(&callback_sem); cs->cpus_allowed = trialcs.cpus_allowed; + up(&callback_sem); if (is_cpu_exclusive(cs) && !cpus_unchanged) update_cpu_domains(cs); return 0; } +/* + * Call with manage_sem held. May take callback_sem during call. + */ + static int update_nodemask(struct cpuset *cs, char *buf) { struct cpuset trialcs; @@ -732,9 +783,11 @@ static int update_nodemask(struct cpuset *cs, char *buf) return -ENOSPC; retval = validate_change(cs, &trialcs); if (retval == 0) { + down(&callback_sem); cs->mems_allowed = trialcs.mems_allowed; atomic_inc(&cpuset_mems_generation); cs->mems_generation = atomic_read(&cpuset_mems_generation); + up(&callback_sem); } return retval; } @@ -745,6 +798,8 @@ static int update_nodemask(struct cpuset *cs, char *buf) * CS_NOTIFY_ON_RELEASE) * cs: the cpuset to update * buf: the buffer where we read the 0 or 1 + * + * Call with manage_sem held. */ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) @@ -766,16 +821,27 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) return err; cpu_exclusive_changed = (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs)); + down(&callback_sem); if (turning_on) set_bit(bit, &cs->flags); else clear_bit(bit, &cs->flags); + up(&callback_sem); if (cpu_exclusive_changed) update_cpu_domains(cs); return 0; } +/* + * Attack task specified by pid in 'pidbuf' to cpuset 'cs', possibly + * writing the path of the old cpuset in 'ppathbuf' if it needs to be + * notified on release. + * + * Call holding manage_sem. May take callback_sem and task_lock of + * the task 'pid' during call. + */ + static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) { pid_t pid; @@ -792,7 +858,7 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) read_lock(&tasklist_lock); tsk = find_task_by_pid(pid); - if (!tsk) { + if (!tsk || tsk->flags & PF_EXITING) { read_unlock(&tasklist_lock); return -ESRCH; } @@ -810,10 +876,13 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) get_task_struct(tsk); } + down(&callback_sem); + task_lock(tsk); oldcs = tsk->cpuset; if (!oldcs) { task_unlock(tsk); + up(&callback_sem); put_task_struct(tsk); return -ESRCH; } @@ -824,6 +893,7 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) guarantee_online_cpus(cs, &cpus); set_cpus_allowed(tsk, cpus); + up(&callback_sem); put_task_struct(tsk); if (atomic_dec_and_test(&oldcs->count)) check_for_release(oldcs, ppathbuf); @@ -867,7 +937,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us } buffer[nbytes] = 0; /* nul-terminate */ - cpuset_down(&cpuset_sem); + down(&manage_sem); if (is_removed(cs)) { retval = -ENODEV; @@ -901,7 +971,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us if (retval == 0) retval = nbytes; out2: - cpuset_up(&cpuset_sem); + up(&manage_sem); cpuset_release_agent(pathbuf); out1: kfree(buffer); @@ -941,9 +1011,9 @@ static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs) { cpumask_t mask; - cpuset_down(&cpuset_sem); + down(&callback_sem); mask = cs->cpus_allowed; - cpuset_up(&cpuset_sem); + up(&callback_sem); return cpulist_scnprintf(page, PAGE_SIZE, mask); } @@ -952,9 +1022,9 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs) { nodemask_t mask; - cpuset_down(&cpuset_sem); + down(&callback_sem); mask = cs->mems_allowed; - cpuset_up(&cpuset_sem); + up(&callback_sem); return nodelist_scnprintf(page, PAGE_SIZE, mask); } @@ -995,7 +1065,6 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, goto out; } *s++ = '\n'; - *s = '\0'; retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page); out: @@ -1048,6 +1117,21 @@ static int cpuset_file_release(struct inode *inode, struct file *file) return 0; } +/* + * cpuset_rename - Only allow simple rename of directories in place. + */ +static int cpuset_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + if (!S_ISDIR(old_dentry->d_inode->i_mode)) + return -ENOTDIR; + if (new_dentry->d_inode) + return -EEXIST; + if (old_dir != new_dir) + return -EIO; + return simple_rename(old_dir, old_dentry, new_dir, new_dentry); +} + static struct file_operations cpuset_file_operations = { .read = cpuset_file_read, .write = cpuset_file_write, @@ -1060,6 +1144,7 @@ static struct inode_operations cpuset_dir_inode_operations = { .lookup = simple_lookup, .mkdir = cpuset_mkdir, .rmdir = cpuset_rmdir, + .rename = cpuset_rename, }; static int cpuset_create_file(struct dentry *dentry, int mode) @@ -1163,7 +1248,9 @@ struct ctr_struct { /* * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'. - * Return actual number of pids loaded. + * Return actual number of pids loaded. No need to task_lock(p) + * when reading out p->cpuset, as we don't really care if it changes + * on the next cycle, and we are not going to try to dereference it. */ static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs) { @@ -1205,6 +1292,12 @@ static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids) return cnt; } +/* + * Handle an open on 'tasks' file. Prepare a buffer listing the + * process id's of tasks currently attached to the cpuset being opened. + * + * Does not require any specific cpuset semaphores, and does not take any. + */ static int cpuset_tasks_open(struct inode *unused, struct file *file) { struct cpuset *cs = __d_cs(file->f_dentry->d_parent); @@ -1352,7 +1445,8 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode) if (!cs) return -ENOMEM; - cpuset_down(&cpuset_sem); + down(&manage_sem); + refresh_mems(); cs->flags = 0; if (notify_on_release(parent)) set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags); @@ -1366,25 +1460,27 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode) cs->parent = parent; + down(&callback_sem); list_add(&cs->sibling, &cs->parent->children); + up(&callback_sem); err = cpuset_create_dir(cs, name, mode); if (err < 0) goto err; /* - * Release cpuset_sem before cpuset_populate_dir() because it + * Release manage_sem before cpuset_populate_dir() because it * will down() this new directory's i_sem and if we race with * another mkdir, we might deadlock. */ - cpuset_up(&cpuset_sem); + up(&manage_sem); err = cpuset_populate_dir(cs->dentry); /* If err < 0, we have a half-filled directory - oh well ;) */ return 0; err: list_del(&cs->sibling); - cpuset_up(&cpuset_sem); + up(&manage_sem); kfree(cs); return err; } @@ -1406,29 +1502,32 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) /* the vfs holds both inode->i_sem already */ - cpuset_down(&cpuset_sem); + down(&manage_sem); + refresh_mems(); if (atomic_read(&cs->count) > 0) { - cpuset_up(&cpuset_sem); + up(&manage_sem); return -EBUSY; } if (!list_empty(&cs->children)) { - cpuset_up(&cpuset_sem); + up(&manage_sem); return -EBUSY; } parent = cs->parent; + down(&callback_sem); set_bit(CS_REMOVED, &cs->flags); if (is_cpu_exclusive(cs)) update_cpu_domains(cs); list_del(&cs->sibling); /* delete my sibling from parent->children */ - if (list_empty(&parent->children)) - check_for_release(parent, &pathbuf); spin_lock(&cs->dentry->d_lock); d = dget(cs->dentry); cs->dentry = NULL; spin_unlock(&d->d_lock); cpuset_d_remove_dir(d); dput(d); - cpuset_up(&cpuset_sem); + up(&callback_sem); + if (list_empty(&parent->children)) + check_for_release(parent, &pathbuf); + up(&manage_sem); cpuset_release_agent(pathbuf); return 0; } @@ -1488,16 +1587,26 @@ void __init cpuset_init_smp(void) * cpuset_fork - attach newly forked task to its parents cpuset. * @tsk: pointer to task_struct of forking parent process. * - * Description: By default, on fork, a task inherits its - * parent's cpuset. The pointer to the shared cpuset is - * automatically copied in fork.c by dup_task_struct(). - * This cpuset_fork() routine need only increment the usage - * counter in that cpuset. + * Description: A task inherits its parent's cpuset at fork(). + * + * A pointer to the shared cpuset was automatically copied in fork.c + * by dup_task_struct(). However, we ignore that copy, since it was + * not made under the protection of task_lock(), so might no longer be + * a valid cpuset pointer. attach_task() might have already changed + * current->cpuset, allowing the previously referenced cpuset to + * be removed and freed. Instead, we task_lock(current) and copy + * its present value of current->cpuset for our freshly forked child. + * + * At the point that cpuset_fork() is called, 'current' is the parent + * task, and the passed argument 'child' points to the child task. **/ -void cpuset_fork(struct task_struct *tsk) +void cpuset_fork(struct task_struct *child) { - atomic_inc(&tsk->cpuset->count); + task_lock(current); + child->cpuset = current->cpuset; + atomic_inc(&child->cpuset->count); + task_unlock(current); } /** @@ -1506,35 +1615,42 @@ void cpuset_fork(struct task_struct *tsk) * * Description: Detach cpuset from @tsk and release it. * - * Note that cpusets marked notify_on_release force every task - * in them to take the global cpuset_sem semaphore when exiting. - * This could impact scaling on very large systems. Be reluctant - * to use notify_on_release cpusets where very high task exit - * scaling is required on large systems. - * - * Don't even think about derefencing 'cs' after the cpuset use - * count goes to zero, except inside a critical section guarded - * by the cpuset_sem semaphore. If you don't hold cpuset_sem, - * then a zero cpuset use count is a license to any other task to - * nuke the cpuset immediately. + * Note that cpusets marked notify_on_release force every task in + * them to take the global manage_sem semaphore when exiting. + * This could impact scaling on very large systems. Be reluctant to + * use notify_on_release cpusets where very high task exit scaling + * is required on large systems. + * + * Don't even think about derefencing 'cs' after the cpuset use count + * goes to zero, except inside a critical section guarded by manage_sem + * or callback_sem. Otherwise a zero cpuset use count is a license to + * any other task to nuke the cpuset immediately, via cpuset_rmdir(). + * + * This routine has to take manage_sem, not callback_sem, because + * it is holding that semaphore while calling check_for_release(), + * which calls kmalloc(), so can't be called holding callback__sem(). + * + * We don't need to task_lock() this reference to tsk->cpuset, + * because tsk is already marked PF_EXITING, so attach_task() won't + * mess with it. **/ void cpuset_exit(struct task_struct *tsk) { struct cpuset *cs; - task_lock(tsk); + BUG_ON(!(tsk->flags & PF_EXITING)); + cs = tsk->cpuset; tsk->cpuset = NULL; - task_unlock(tsk); if (notify_on_release(cs)) { char *pathbuf = NULL; - cpuset_down(&cpuset_sem); + down(&manage_sem); if (atomic_dec_and_test(&cs->count)) check_for_release(cs, &pathbuf); - cpuset_up(&cpuset_sem); + up(&manage_sem); cpuset_release_agent(pathbuf); } else { atomic_dec(&cs->count); @@ -1555,11 +1671,11 @@ cpumask_t cpuset_cpus_allowed(const struct task_struct *tsk) { cpumask_t mask; - cpuset_down(&cpuset_sem); + down(&callback_sem); task_lock((struct task_struct *)tsk); guarantee_online_cpus(tsk->cpuset, &mask); task_unlock((struct task_struct *)tsk); - cpuset_up(&cpuset_sem); + up(&callback_sem); return mask; } @@ -1575,19 +1691,28 @@ void cpuset_init_current_mems_allowed(void) * If the current tasks cpusets mems_allowed changed behind our backs, * update current->mems_allowed and mems_generation to the new value. * Do not call this routine if in_interrupt(). + * + * Call without callback_sem or task_lock() held. May be called + * with or without manage_sem held. Unless exiting, it will acquire + * task_lock(). Also might acquire callback_sem during call to + * refresh_mems(). */ void cpuset_update_current_mems_allowed(void) { - struct cpuset *cs = current->cpuset; + struct cpuset *cs; + int need_to_refresh = 0; + task_lock(current); + cs = current->cpuset; if (!cs) - return; /* task is exiting */ - if (current->cpuset_mems_generation != cs->mems_generation) { - cpuset_down(&cpuset_sem); + goto done; + if (current->cpuset_mems_generation != cs->mems_generation) + need_to_refresh = 1; +done: + task_unlock(current); + if (need_to_refresh) refresh_mems(); - cpuset_up(&cpuset_sem); - } } /** @@ -1621,7 +1746,7 @@ int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl) /* * nearest_exclusive_ancestor() - Returns the nearest mem_exclusive - * ancestor to the specified cpuset. Call while holding cpuset_sem. + * ancestor to the specified cpuset. Call holding callback_sem. * If no ancestor is mem_exclusive (an unusual configuration), then * returns the root cpuset. */ @@ -1648,12 +1773,12 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs) * GFP_KERNEL allocations are not so marked, so can escape to the * nearest mem_exclusive ancestor cpuset. * - * Scanning up parent cpusets requires cpuset_sem. The __alloc_pages() + * Scanning up parent cpusets requires callback_sem. The __alloc_pages() * routine only calls here with __GFP_HARDWALL bit _not_ set if * it's a GFP_KERNEL allocation, and all nodes in the current tasks * mems_allowed came up empty on the first pass over the zonelist. * So only GFP_KERNEL allocations, if all nodes in the cpuset are - * short of memory, might require taking the cpuset_sem semaphore. + * short of memory, might require taking the callback_sem semaphore. * * The first loop over the zonelist in mm/page_alloc.c:__alloc_pages() * calls here with __GFP_HARDWALL always set in gfp_mask, enforcing @@ -1685,14 +1810,16 @@ int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) return 0; /* Not hardwall and node outside mems_allowed: scan up cpusets */ - cpuset_down(&cpuset_sem); - cs = current->cpuset; - if (!cs) - goto done; /* current task exiting */ - cs = nearest_exclusive_ancestor(cs); + down(&callback_sem); + + if (current->flags & PF_EXITING) /* Let dying task have memory */ + return 1; + task_lock(current); + cs = nearest_exclusive_ancestor(current->cpuset); + task_unlock(current); + allowed = node_isset(node, cs->mems_allowed); -done: - cpuset_up(&cpuset_sem); + up(&callback_sem); return allowed; } @@ -1705,7 +1832,7 @@ done: * determine if task @p's memory usage might impact the memory * available to the current task. * - * Acquires cpuset_sem - not suitable for calling from a fast path. + * Acquires callback_sem - not suitable for calling from a fast path. **/ int cpuset_excl_nodes_overlap(const struct task_struct *p) @@ -1713,18 +1840,27 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p) const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */ int overlap = 0; /* do cpusets overlap? */ - cpuset_down(&cpuset_sem); - cs1 = current->cpuset; - if (!cs1) - goto done; /* current task exiting */ - cs2 = p->cpuset; - if (!cs2) - goto done; /* task p is exiting */ - cs1 = nearest_exclusive_ancestor(cs1); - cs2 = nearest_exclusive_ancestor(cs2); + down(&callback_sem); + + task_lock(current); + if (current->flags & PF_EXITING) { + task_unlock(current); + goto done; + } + cs1 = nearest_exclusive_ancestor(current->cpuset); + task_unlock(current); + + task_lock((struct task_struct *)p); + if (p->flags & PF_EXITING) { + task_unlock((struct task_struct *)p); + goto done; + } + cs2 = nearest_exclusive_ancestor(p->cpuset); + task_unlock((struct task_struct *)p); + overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed); done: - cpuset_up(&cpuset_sem); + up(&callback_sem); return overlap; } @@ -1733,6 +1869,10 @@ done: * proc_cpuset_show() * - Print tasks cpuset path into seq_file. * - Used for /proc/<pid>/cpuset. + * - No need to task_lock(tsk) on this tsk->cpuset reference, as it + * doesn't really matter if tsk->cpuset changes after we read it, + * and we take manage_sem, keeping attach_task() from changing it + * anyway. */ static int proc_cpuset_show(struct seq_file *m, void *v) @@ -1747,10 +1887,8 @@ static int proc_cpuset_show(struct seq_file *m, void *v) return -ENOMEM; tsk = m->private; - cpuset_down(&cpuset_sem); - task_lock(tsk); + down(&manage_sem); cs = tsk->cpuset; - task_unlock(tsk); if (!cs) { retval = -EINVAL; goto out; @@ -1762,7 +1900,7 @@ static int proc_cpuset_show(struct seq_file *m, void *v) seq_puts(m, buf); seq_putc(m, '\n'); out: - cpuset_up(&cpuset_sem); + up(&manage_sem); kfree(buf); return retval; } diff --git a/kernel/exit.c b/kernel/exit.c index 79f52b85d6e..537394b25e8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -547,7 +547,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) if (p->pdeath_signal) /* We already hold the tasklist_lock here. */ - group_send_sig_info(p->pdeath_signal, (void *) 0, p); + group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p); /* Move the child from its dying parent to the new one. */ if (unlikely(traced)) { @@ -591,8 +591,8 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) int pgrp = process_group(p); if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { - __kill_pg_info(SIGHUP, (void *)1, pgrp); - __kill_pg_info(SIGCONT, (void *)1, pgrp); + __kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp); + __kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp); } } } @@ -727,8 +727,8 @@ static void exit_notify(struct task_struct *tsk) (t->signal->session == tsk->signal->session) && will_become_orphaned_pgrp(process_group(tsk), tsk) && has_stopped_jobs(process_group(tsk))) { - __kill_pg_info(SIGHUP, (void *)1, process_group(tsk)); - __kill_pg_info(SIGCONT, (void *)1, process_group(tsk)); + __kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk)); + __kill_pg_info(SIGCONT, SEND_SIG_PRIV, process_group(tsk)); } /* Let father know we died @@ -783,10 +783,6 @@ static void exit_notify(struct task_struct *tsk) /* If the process is dead, release it - nobody will wait for it */ if (state == EXIT_DEAD) release_task(tsk); - - /* PF_DEAD causes final put_task_struct after we schedule. */ - preempt_disable(); - tsk->flags |= PF_DEAD; } fastcall NORET_TYPE void do_exit(long code) @@ -873,7 +869,11 @@ fastcall NORET_TYPE void do_exit(long code) tsk->mempolicy = NULL; #endif - BUG_ON(!(current->flags & PF_DEAD)); + /* PF_DEAD causes final put_task_struct after we schedule. */ + preempt_disable(); + BUG_ON(tsk->flags & PF_DEAD); + tsk->flags |= PF_DEAD; + schedule(); BUG(); /* Avoid "noreturn function does return". */ @@ -1383,6 +1383,15 @@ repeat: switch (p->state) { case TASK_TRACED: + /* + * When we hit the race with PTRACE_ATTACH, + * we will not report this child. But the + * race means it has not yet been moved to + * our ptrace_children list, so we need to + * set the flag here to avoid a spurious ECHILD + * when the race happens with the only child. + */ + flag = 1; if (!my_ptrace_child(p)) continue; /*FALLTHROUGH*/ diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 13bcec151b5..39277dd6bf9 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -18,6 +18,7 @@ #include <linux/fs.h> #include <linux/err.h> #include <linux/proc_fs.h> +#include <linux/sched.h> /* for cond_resched */ #include <linux/mm.h> #include <asm/sections.h> diff --git a/kernel/kmod.c b/kernel/kmod.c index 44166e3bb8a..51a892063aa 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -131,14 +131,14 @@ struct subprocess_info { static int ____call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; - struct key *old_session; + struct key *new_session, *old_session; int retval; /* Unblock all signals and set the session keyring. */ - key_get(sub_info->ring); + new_session = key_get(sub_info->ring); flush_signals(current); spin_lock_irq(¤t->sighand->siglock); - old_session = __install_session_keyring(current, sub_info->ring); + old_session = __install_session_keyring(current, new_session); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); recalc_sigpending(); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index f3ea492ab44..ce4915dd683 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -35,6 +35,7 @@ #include <linux/spinlock.h> #include <linux/hash.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/moduleloader.h> #include <asm-generic/sections.h> diff --git a/kernel/kthread.c b/kernel/kthread.c index f50f174e92d..e75950a1092 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -165,6 +165,12 @@ EXPORT_SYMBOL(kthread_bind); int kthread_stop(struct task_struct *k) { + return kthread_stop_sem(k, NULL); +} +EXPORT_SYMBOL(kthread_stop); + +int kthread_stop_sem(struct task_struct *k, struct semaphore *s) +{ int ret; down(&kthread_stop_lock); @@ -178,7 +184,10 @@ int kthread_stop(struct task_struct *k) /* Now set kthread_should_stop() to true, and wake it up. */ kthread_stop_info.k = k; - wake_up_process(k); + if (s) + up(s); + else + wake_up_process(k); put_task_struct(k); /* Once it dies, reset stop ptr, gather result and we're done. */ @@ -189,7 +198,7 @@ int kthread_stop(struct task_struct *k) return ret; } -EXPORT_SYMBOL(kthread_stop); +EXPORT_SYMBOL(kthread_stop_sem); static __init int helper_init(void) { diff --git a/kernel/params.c b/kernel/params.c index 1a8614bac5d..47ba6954794 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/slab.h> #if 0 #define DEBUGP printk diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index bf374fceb39..91a89426494 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1225,7 +1225,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) /* * The task was cleaned up already, no future firings. */ - return; + goto out; /* * Fetch the current sample and update the timer's expiry time. @@ -1235,7 +1235,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) bump_cpu_timer(timer, now); if (unlikely(p->exit_state)) { clear_dead_task(timer, now); - return; + goto out; } read_lock(&tasklist_lock); /* arm_timer needs it. */ } else { @@ -1248,8 +1248,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) put_task_struct(p); timer->it.cpu.task = p = NULL; timer->it.cpu.expires.sched = 0; - read_unlock(&tasklist_lock); - return; + goto out_unlock; } else if (unlikely(p->exit_state) && thread_group_empty(p)) { /* * We've noticed that the thread is dead, but @@ -1257,8 +1256,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) * drop our task ref. */ clear_dead_task(timer, now); - read_unlock(&tasklist_lock); - return; + goto out_unlock; } cpu_clock_sample_group(timer->it_clock, p, &now); bump_cpu_timer(timer, now); @@ -1270,7 +1268,13 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) */ arm_timer(timer, now); +out_unlock: read_unlock(&tasklist_lock); + +out: + timer->it_overrun_last = timer->it_overrun; + timer->it_overrun = -1; + ++timer->it_requeue_pending; } /* diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index dda3cda73c7..ea55c7a1cd7 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -1295,13 +1295,6 @@ sys_clock_getres(clockid_t which_clock, struct timespec __user *tp) return error; } -static void nanosleep_wake_up(unsigned long __data) -{ - struct task_struct *p = (struct task_struct *) __data; - - wake_up_process(p); -} - /* * The standard says that an absolute nanosleep call MUST wake up at * the requested time in spite of clock settings. Here is what we do: @@ -1442,7 +1435,6 @@ static int common_nsleep(clockid_t which_clock, int flags, struct timespec *tsave) { struct timespec t, dum; - struct timer_list new_timer; DECLARE_WAITQUEUE(abs_wqueue, current); u64 rq_time = (u64)0; s64 left; @@ -1451,10 +1443,6 @@ static int common_nsleep(clockid_t which_clock, ¤t_thread_info()->restart_block; abs_wqueue.flags = 0; - init_timer(&new_timer); - new_timer.expires = 0; - new_timer.data = (unsigned long) current; - new_timer.function = nanosleep_wake_up; abs = flags & TIMER_ABSTIME; if (restart_block->fn == clock_nanosleep_restart) { @@ -1490,13 +1478,8 @@ static int common_nsleep(clockid_t which_clock, if (left < (s64)0) break; - new_timer.expires = jiffies + left; - __set_current_state(TASK_INTERRUPTIBLE); - add_timer(&new_timer); - - schedule(); + schedule_timeout_interruptible(left); - del_timer_sync(&new_timer); left = rq_time - get_jiffies_64(); } while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING)); diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 2f438d0eaa1..c71eb4579c0 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -4,7 +4,7 @@ EXTRA_CFLAGS += -DDEBUG endif obj-y := main.o process.o console.o pm.o -obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o obj-$(CONFIG_SUSPEND_SMP) += smp.o diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 761956e813f..027322a564f 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -30,7 +30,6 @@ extern int swsusp_check(void); extern int swsusp_read(void); extern void swsusp_close(void); extern int swsusp_resume(void); -extern int swsusp_free(void); static int noresume = 0; @@ -93,10 +92,7 @@ static void free_some_memory(void) printk("Freeing memory... "); while ((tmp = shrink_all_memory(10000))) { pages += tmp; - printk("\b%c", p[i]); - i++; - if (i > 3) - i = 0; + printk("\b%c", p[i++ % 4]); } printk("\bdone (%li pages freed)\n", pages); } @@ -178,13 +174,12 @@ int pm_suspend_disk(void) goto Done; if (in_suspend) { + device_resume(); pr_debug("PM: writing image.\n"); error = swsusp_write(); if (!error) power_down(pm_disk_mode); else { - /* swsusp_write can not fail in device_resume, - no need to do second device_resume */ swsusp_free(); unprepare_processes(); return error; @@ -252,14 +247,17 @@ static int software_resume(void) pr_debug("PM: Reading swsusp image.\n"); - if ((error = swsusp_read())) - goto Cleanup; + if ((error = swsusp_read())) { + swsusp_free(); + goto Thaw; + } pr_debug("PM: Preparing devices for restore.\n"); if ((error = device_suspend(PMSG_FREEZE))) { printk("Some devices failed to suspend\n"); - goto Free; + swsusp_free(); + goto Thaw; } mb(); @@ -268,9 +266,7 @@ static int software_resume(void) swsusp_resume(); pr_debug("PM: Restore failed, recovering.n"); device_resume(); - Free: - swsusp_free(); - Cleanup: + Thaw: unprepare_processes(); Done: /* For success case, the suspend path will release the lock */ diff --git a/kernel/power/main.c b/kernel/power/main.c index 22bdc93cc03..18d7d693fbb 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -167,6 +167,8 @@ static int enter_state(suspend_state_t state) { int error; + if (pm_ops->valid && !pm_ops->valid(state)) + return -ENODEV; if (down_trylock(&pm_sem)) return -EBUSY; @@ -236,7 +238,8 @@ static ssize_t state_show(struct subsystem * subsys, char * buf) char * s = buf; for (i = 0; i < PM_SUSPEND_MAX; i++) { - if (pm_states[i]) + if (pm_states[i] && pm_ops && (!pm_ops->valid + ||(pm_ops->valid && pm_ops->valid(i)))) s += sprintf(s,"%s ",pm_states[i]); } s += sprintf(s,"\n"); diff --git a/kernel/power/power.h b/kernel/power/power.h index 6748de23e83..d4fd96a135a 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -53,3 +53,20 @@ extern void thaw_processes(void); extern int pm_prepare_console(void); extern void pm_restore_console(void); + + +/* References to section boundaries */ +extern const void __nosave_begin, __nosave_end; + +extern unsigned int nr_copy_pages; +extern suspend_pagedir_t *pagedir_nosave; +extern suspend_pagedir_t *pagedir_save; + +extern asmlinkage int swsusp_arch_suspend(void); +extern asmlinkage int swsusp_arch_resume(void); + +extern int restore_highmem(void); +extern struct pbe * alloc_pagedir(unsigned nr_pages); +extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); +extern void swsusp_free(void); +extern int enough_swap(unsigned nr_pages); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c new file mode 100644 index 00000000000..42a62870439 --- /dev/null +++ b/kernel/power/snapshot.c @@ -0,0 +1,435 @@ +/* + * linux/kernel/power/snapshot.c + * + * This file provide system snapshot/restore functionality. + * + * Copyright (C) 1998-2005 Pavel Machek <pavel@suse.cz> + * + * This file is released under the GPLv2, and is based on swsusp.c. + * + */ + + +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/suspend.h> +#include <linux/smp_lock.h> +#include <linux/delay.h> +#include <linux/bitops.h> +#include <linux/spinlock.h> +#include <linux/kernel.h> +#include <linux/pm.h> +#include <linux/device.h> +#include <linux/bootmem.h> +#include <linux/syscalls.h> +#include <linux/console.h> +#include <linux/highmem.h> + +#include <asm/uaccess.h> +#include <asm/mmu_context.h> +#include <asm/pgtable.h> +#include <asm/tlbflush.h> +#include <asm/io.h> + +#include "power.h" + +#ifdef CONFIG_HIGHMEM +struct highmem_page { + char *data; + struct page *page; + struct highmem_page *next; +}; + +static struct highmem_page *highmem_copy; + +static int save_highmem_zone(struct zone *zone) +{ + unsigned long zone_pfn; + mark_free_pages(zone); + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { + struct page *page; + struct highmem_page *save; + void *kaddr; + unsigned long pfn = zone_pfn + zone->zone_start_pfn; + + if (!(pfn%1000)) + printk("."); + if (!pfn_valid(pfn)) + continue; + page = pfn_to_page(pfn); + /* + * This condition results from rvmalloc() sans vmalloc_32() + * and architectural memory reservations. This should be + * corrected eventually when the cases giving rise to this + * are better understood. + */ + if (PageReserved(page)) { + printk("highmem reserved page?!\n"); + continue; + } + BUG_ON(PageNosave(page)); + if (PageNosaveFree(page)) + continue; + save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC); + if (!save) + return -ENOMEM; + save->next = highmem_copy; + save->page = page; + save->data = (void *) get_zeroed_page(GFP_ATOMIC); + if (!save->data) { + kfree(save); + return -ENOMEM; + } + kaddr = kmap_atomic(page, KM_USER0); + memcpy(save->data, kaddr, PAGE_SIZE); + kunmap_atomic(kaddr, KM_USER0); + highmem_copy = save; + } + return 0; +} + + +static int save_highmem(void) +{ + struct zone *zone; + int res = 0; + + pr_debug("swsusp: Saving Highmem\n"); + for_each_zone (zone) { + if (is_highmem(zone)) + res = save_highmem_zone(zone); + if (res) + return res; + } + return 0; +} + +int restore_highmem(void) +{ + printk("swsusp: Restoring Highmem\n"); + while (highmem_copy) { + struct highmem_page *save = highmem_copy; + void *kaddr; + highmem_copy = save->next; + + kaddr = kmap_atomic(save->page, KM_USER0); + memcpy(kaddr, save->data, PAGE_SIZE); + kunmap_atomic(kaddr, KM_USER0); + free_page((long) save->data); + kfree(save); + } + return 0; +} +#else +static int save_highmem(void) { return 0; } +int restore_highmem(void) { return 0; } +#endif /* CONFIG_HIGHMEM */ + + +static int pfn_is_nosave(unsigned long pfn) +{ + unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; + unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT; + return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +} + +/** + * saveable - Determine whether a page should be cloned or not. + * @pfn: The page + * + * We save a page if it's Reserved, and not in the range of pages + * statically defined as 'unsaveable', or if it isn't reserved, and + * isn't part of a free chunk of pages. + */ + +static int saveable(struct zone *zone, unsigned long *zone_pfn) +{ + unsigned long pfn = *zone_pfn + zone->zone_start_pfn; + struct page *page; + + if (!pfn_valid(pfn)) + return 0; + + page = pfn_to_page(pfn); + BUG_ON(PageReserved(page) && PageNosave(page)); + if (PageNosave(page)) + return 0; + if (PageReserved(page) && pfn_is_nosave(pfn)) { + pr_debug("[nosave pfn 0x%lx]", pfn); + return 0; + } + if (PageNosaveFree(page)) + return 0; + + return 1; +} + +static unsigned count_data_pages(void) +{ + struct zone *zone; + unsigned long zone_pfn; + unsigned n; + + n = 0; + for_each_zone (zone) { + if (is_highmem(zone)) + continue; + mark_free_pages(zone); + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) + n += saveable(zone, &zone_pfn); + } + return n; +} + +static void copy_data_pages(struct pbe *pblist) +{ + struct zone *zone; + unsigned long zone_pfn; + struct pbe *pbe, *p; + + pbe = pblist; + for_each_zone (zone) { + if (is_highmem(zone)) + continue; + mark_free_pages(zone); + /* This is necessary for swsusp_free() */ + for_each_pb_page (p, pblist) + SetPageNosaveFree(virt_to_page(p)); + for_each_pbe (p, pblist) + SetPageNosaveFree(virt_to_page(p->address)); + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { + if (saveable(zone, &zone_pfn)) { + struct page *page; + page = pfn_to_page(zone_pfn + zone->zone_start_pfn); + BUG_ON(!pbe); + pbe->orig_address = (unsigned long)page_address(page); + /* copy_page is not usable for copying task structs. */ + memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE); + pbe = pbe->next; + } + } + } + BUG_ON(pbe); +} + + +/** + * free_pagedir - free pages allocated with alloc_pagedir() + */ + +static void free_pagedir(struct pbe *pblist) +{ + struct pbe *pbe; + + while (pblist) { + pbe = (pblist + PB_PAGE_SKIP)->next; + ClearPageNosave(virt_to_page(pblist)); + ClearPageNosaveFree(virt_to_page(pblist)); + free_page((unsigned long)pblist); + pblist = pbe; + } +} + +/** + * fill_pb_page - Create a list of PBEs on a given memory page + */ + +static inline void fill_pb_page(struct pbe *pbpage) +{ + struct pbe *p; + + p = pbpage; + pbpage += PB_PAGE_SKIP; + do + p->next = p + 1; + while (++p < pbpage); +} + +/** + * create_pbe_list - Create a list of PBEs on top of a given chain + * of memory pages allocated with alloc_pagedir() + */ + +void create_pbe_list(struct pbe *pblist, unsigned nr_pages) +{ + struct pbe *pbpage, *p; + unsigned num = PBES_PER_PAGE; + + for_each_pb_page (pbpage, pblist) { + if (num >= nr_pages) + break; + + fill_pb_page(pbpage); + num += PBES_PER_PAGE; + } + if (pbpage) { + for (num -= PBES_PER_PAGE - 1, p = pbpage; num < nr_pages; p++, num++) + p->next = p + 1; + p->next = NULL; + } + pr_debug("create_pbe_list(): initialized %d PBEs\n", num); +} + +static void *alloc_image_page(void) +{ + void *res = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); + if (res) { + SetPageNosave(virt_to_page(res)); + SetPageNosaveFree(virt_to_page(res)); + } + return res; +} + +/** + * alloc_pagedir - Allocate the page directory. + * + * First, determine exactly how many pages we need and + * allocate them. + * + * We arrange the pages in a chain: each page is an array of PBES_PER_PAGE + * struct pbe elements (pbes) and the last element in the page points + * to the next page. + * + * On each page we set up a list of struct_pbe elements. + */ + +struct pbe *alloc_pagedir(unsigned nr_pages) +{ + unsigned num; + struct pbe *pblist, *pbe; + + if (!nr_pages) + return NULL; + + pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); + pblist = alloc_image_page(); + /* FIXME: rewrite this ugly loop */ + for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; + pbe = pbe->next, num += PBES_PER_PAGE) { + pbe += PB_PAGE_SKIP; + pbe->next = alloc_image_page(); + } + if (!pbe) { /* get_zeroed_page() failed */ + free_pagedir(pblist); + pblist = NULL; + } + return pblist; +} + +/** + * Free pages we allocated for suspend. Suspend pages are alocated + * before atomic copy, so we need to free them after resume. + */ + +void swsusp_free(void) +{ + struct zone *zone; + unsigned long zone_pfn; + + for_each_zone(zone) { + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) + if (pfn_valid(zone_pfn + zone->zone_start_pfn)) { + struct page * page; + page = pfn_to_page(zone_pfn + zone->zone_start_pfn); + if (PageNosave(page) && PageNosaveFree(page)) { + ClearPageNosave(page); + ClearPageNosaveFree(page); + free_page((long) page_address(page)); + } + } + } +} + + +/** + * enough_free_mem - Make sure we enough free memory to snapshot. + * + * Returns TRUE or FALSE after checking the number of available + * free pages. + */ + +static int enough_free_mem(unsigned nr_pages) +{ + pr_debug("swsusp: available memory: %u pages\n", nr_free_pages()); + return nr_free_pages() > (nr_pages + PAGES_FOR_IO + + (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); +} + + +static struct pbe *swsusp_alloc(unsigned nr_pages) +{ + struct pbe *pblist, *p; + + if (!(pblist = alloc_pagedir(nr_pages))) { + printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); + return NULL; + } + create_pbe_list(pblist, nr_pages); + + for_each_pbe (p, pblist) { + p->address = (unsigned long)alloc_image_page(); + if (!p->address) { + printk(KERN_ERR "suspend: Allocating image pages failed.\n"); + swsusp_free(); + return NULL; + } + } + + return pblist; +} + +asmlinkage int swsusp_save(void) +{ + unsigned nr_pages; + + pr_debug("swsusp: critical section: \n"); + if (save_highmem()) { + printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n"); + restore_highmem(); + return -ENOMEM; + } + + drain_local_pages(); + nr_pages = count_data_pages(); + printk("swsusp: Need to copy %u pages\n", nr_pages); + + pr_debug("swsusp: pages needed: %u + %lu + %u, free: %u\n", + nr_pages, + (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE, + PAGES_FOR_IO, nr_free_pages()); + + /* This is needed because of the fixed size of swsusp_info */ + if (MAX_PBES < (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE) + return -ENOSPC; + + if (!enough_free_mem(nr_pages)) { + printk(KERN_ERR "swsusp: Not enough free memory\n"); + return -ENOMEM; + } + + if (!enough_swap(nr_pages)) { + printk(KERN_ERR "swsusp: Not enough free swap\n"); + return -ENOSPC; + } + + pagedir_nosave = swsusp_alloc(nr_pages); + if (!pagedir_nosave) + return -ENOMEM; + + /* During allocating of suspend pagedir, new cold pages may appear. + * Kill them. + */ + drain_local_pages(); + copy_data_pages(pagedir_nosave); + + /* + * End of critical section. From now on, we can write to memory, + * but we should not touch disk. This specially means we must _not_ + * touch swap space! Except we must write out our image of course. + */ + + nr_copy_pages = nr_pages; + + printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages); + return 0; +} diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 016504ccfcc..12db1d2ad61 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -1,11 +1,10 @@ /* * linux/kernel/power/swsusp.c * - * This file is to realize architecture-independent - * machine suspend feature using pretty near only high-level routines + * This file provides code to write suspend image to swap and read it back. * * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu> - * Copyright (C) 1998,2001-2004 Pavel Machek <pavel@suse.cz> + * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz> * * This file is released under the GPLv2. * @@ -47,11 +46,7 @@ #include <linux/utsname.h> #include <linux/version.h> #include <linux/delay.h> -#include <linux/reboot.h> #include <linux/bitops.h> -#include <linux/vt_kern.h> -#include <linux/kbd_kern.h> -#include <linux/keyboard.h> #include <linux/spinlock.h> #include <linux/genhd.h> #include <linux/kernel.h> @@ -63,10 +58,8 @@ #include <linux/swapops.h> #include <linux/bootmem.h> #include <linux/syscalls.h> -#include <linux/console.h> #include <linux/highmem.h> #include <linux/bio.h> -#include <linux/mount.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -84,16 +77,10 @@ #define MAXKEY 32 #define MAXIV 32 -/* References to section boundaries */ -extern const void __nosave_begin, __nosave_end; - -/* Variables to be preserved over suspend */ -static int nr_copy_pages_check; - extern char resume_file[]; /* Local variables that should not be affected by save */ -static unsigned int nr_copy_pages __nosavedata = 0; +unsigned int nr_copy_pages __nosavedata = 0; /* Suspend pagedir is allocated before final copy, therefore it must be freed after resume @@ -109,7 +96,7 @@ static unsigned int nr_copy_pages __nosavedata = 0; MMU hardware. */ suspend_pagedir_t *pagedir_nosave __nosavedata = NULL; -static suspend_pagedir_t *pagedir_save; +suspend_pagedir_t *pagedir_save; #define SWSUSP_SIG "S1SUSPEND" @@ -124,12 +111,6 @@ static struct swsusp_header { static struct swsusp_info swsusp_info; /* - * XXX: We try to keep some more pages free so that I/O operations succeed - * without paging. Might this be more? - */ -#define PAGES_FOR_IO 512 - -/* * Saving part... */ @@ -552,353 +533,6 @@ static int write_suspend_image(void) goto Done; } - -#ifdef CONFIG_HIGHMEM -struct highmem_page { - char *data; - struct page *page; - struct highmem_page *next; -}; - -static struct highmem_page *highmem_copy; - -static int save_highmem_zone(struct zone *zone) -{ - unsigned long zone_pfn; - mark_free_pages(zone); - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { - struct page *page; - struct highmem_page *save; - void *kaddr; - unsigned long pfn = zone_pfn + zone->zone_start_pfn; - - if (!(pfn%1000)) - printk("."); - if (!pfn_valid(pfn)) - continue; - page = pfn_to_page(pfn); - /* - * PageReserved results from rvmalloc() sans vmalloc_32() - * and architectural memory reservations. - * - * rvmalloc should not cause this, because all implementations - * appear to always be using vmalloc_32 on architectures with - * highmem. This is a good thing, because we would like to save - * rvmalloc pages. - * - * It appears to be triggered by pages which do not point to - * valid memory (see arch/i386/mm/init.c:one_highpage_init(), - * which sets PageReserved if the page does not point to valid - * RAM. - * - * XXX: must remove usage of PageReserved! - */ - if (PageReserved(page)) - continue; - BUG_ON(PageNosave(page)); - if (PageNosaveFree(page)) - continue; - save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC); - if (!save) - return -ENOMEM; - save->next = highmem_copy; - save->page = page; - save->data = (void *) get_zeroed_page(GFP_ATOMIC); - if (!save->data) { - kfree(save); - return -ENOMEM; - } - kaddr = kmap_atomic(page, KM_USER0); - memcpy(save->data, kaddr, PAGE_SIZE); - kunmap_atomic(kaddr, KM_USER0); - highmem_copy = save; - } - return 0; -} -#endif /* CONFIG_HIGHMEM */ - - -static int save_highmem(void) -{ -#ifdef CONFIG_HIGHMEM - struct zone *zone; - int res = 0; - - pr_debug("swsusp: Saving Highmem\n"); - for_each_zone (zone) { - if (is_highmem(zone)) - res = save_highmem_zone(zone); - if (res) - return res; - } -#endif - return 0; -} - -static int restore_highmem(void) -{ -#ifdef CONFIG_HIGHMEM - printk("swsusp: Restoring Highmem\n"); - while (highmem_copy) { - struct highmem_page *save = highmem_copy; - void *kaddr; - highmem_copy = save->next; - - kaddr = kmap_atomic(save->page, KM_USER0); - memcpy(kaddr, save->data, PAGE_SIZE); - kunmap_atomic(kaddr, KM_USER0); - free_page((long) save->data); - kfree(save); - } -#endif - return 0; -} - - -static int pfn_is_nosave(unsigned long pfn) -{ - unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; - unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT; - return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); -} - -/** - * saveable - Determine whether a page should be cloned or not. - * @pfn: The page - * - * We save a page if it's Reserved, and not in the range of pages - * statically defined as 'unsaveable', or if it isn't reserved, and - * isn't part of a free chunk of pages. - */ - -static int saveable(struct zone * zone, unsigned long * zone_pfn) -{ - unsigned long pfn = *zone_pfn + zone->zone_start_pfn; - struct page * page; - - if (!pfn_valid(pfn)) - return 0; - - page = pfn_to_page(pfn); - if (PageNosave(page)) - return 0; - if (pfn_is_nosave(pfn)) { - pr_debug("[nosave pfn 0x%lx]", pfn); - return 0; - } - if (PageNosaveFree(page)) - return 0; - - return 1; -} - -static void count_data_pages(void) -{ - struct zone *zone; - unsigned long zone_pfn; - - nr_copy_pages = 0; - - for_each_zone (zone) { - if (is_highmem(zone)) - continue; - mark_free_pages(zone); - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) - nr_copy_pages += saveable(zone, &zone_pfn); - } -} - - -static void copy_data_pages(void) -{ - struct zone *zone; - unsigned long zone_pfn; - struct pbe * pbe = pagedir_nosave; - - pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages); - for_each_zone (zone) { - if (is_highmem(zone)) - continue; - mark_free_pages(zone); - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { - if (saveable(zone, &zone_pfn)) { - struct page * page; - page = pfn_to_page(zone_pfn + zone->zone_start_pfn); - BUG_ON(!pbe); - pbe->orig_address = (long) page_address(page); - /* copy_page is not usable for copying task structs. */ - memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE); - pbe = pbe->next; - } - } - } - BUG_ON(pbe); -} - - -/** - * calc_nr - Determine the number of pages needed for a pbe list. - */ - -static int calc_nr(int nr_copy) -{ - return nr_copy + (nr_copy+PBES_PER_PAGE-2)/(PBES_PER_PAGE-1); -} - -/** - * free_pagedir - free pages allocated with alloc_pagedir() - */ - -static inline void free_pagedir(struct pbe *pblist) -{ - struct pbe *pbe; - - while (pblist) { - pbe = (pblist + PB_PAGE_SKIP)->next; - free_page((unsigned long)pblist); - pblist = pbe; - } -} - -/** - * fill_pb_page - Create a list of PBEs on a given memory page - */ - -static inline void fill_pb_page(struct pbe *pbpage) -{ - struct pbe *p; - - p = pbpage; - pbpage += PB_PAGE_SKIP; - do - p->next = p + 1; - while (++p < pbpage); -} - -/** - * create_pbe_list - Create a list of PBEs on top of a given chain - * of memory pages allocated with alloc_pagedir() - */ - -static void create_pbe_list(struct pbe *pblist, unsigned nr_pages) -{ - struct pbe *pbpage, *p; - unsigned num = PBES_PER_PAGE; - - for_each_pb_page (pbpage, pblist) { - if (num >= nr_pages) - break; - - fill_pb_page(pbpage); - num += PBES_PER_PAGE; - } - if (pbpage) { - for (num -= PBES_PER_PAGE - 1, p = pbpage; num < nr_pages; p++, num++) - p->next = p + 1; - p->next = NULL; - } - pr_debug("create_pbe_list(): initialized %d PBEs\n", num); -} - -/** - * alloc_pagedir - Allocate the page directory. - * - * First, determine exactly how many pages we need and - * allocate them. - * - * We arrange the pages in a chain: each page is an array of PBES_PER_PAGE - * struct pbe elements (pbes) and the last element in the page points - * to the next page. - * - * On each page we set up a list of struct_pbe elements. - */ - -static struct pbe * alloc_pagedir(unsigned nr_pages) -{ - unsigned num; - struct pbe *pblist, *pbe; - - if (!nr_pages) - return NULL; - - pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); - pblist = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); - for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; - pbe = pbe->next, num += PBES_PER_PAGE) { - pbe += PB_PAGE_SKIP; - pbe->next = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); - } - if (!pbe) { /* get_zeroed_page() failed */ - free_pagedir(pblist); - pblist = NULL; - } - return pblist; -} - -/** - * free_image_pages - Free pages allocated for snapshot - */ - -static void free_image_pages(void) -{ - struct pbe * p; - - for_each_pbe (p, pagedir_save) { - if (p->address) { - ClearPageNosave(virt_to_page(p->address)); - free_page(p->address); - p->address = 0; - } - } -} - -/** - * alloc_image_pages - Allocate pages for the snapshot. - */ - -static int alloc_image_pages(void) -{ - struct pbe * p; - - for_each_pbe (p, pagedir_save) { - p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD); - if (!p->address) - return -ENOMEM; - SetPageNosave(virt_to_page(p->address)); - } - return 0; -} - -/* Free pages we allocated for suspend. Suspend pages are alocated - * before atomic copy, so we need to free them after resume. - */ -void swsusp_free(void) -{ - BUG_ON(PageNosave(virt_to_page(pagedir_save))); - BUG_ON(PageNosaveFree(virt_to_page(pagedir_save))); - free_image_pages(); - free_pagedir(pagedir_save); -} - - -/** - * enough_free_mem - Make sure we enough free memory to snapshot. - * - * Returns TRUE or FALSE after checking the number of available - * free pages. - */ - -static int enough_free_mem(void) -{ - if (nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) { - pr_debug("swsusp: Not enough free pages: Have %d\n", - nr_free_pages()); - return 0; - } - return 1; -} - - /** * enough_swap - Make sure we have enough swap to save the image. * @@ -909,87 +543,14 @@ static int enough_free_mem(void) * We should only consider resume_device. */ -static int enough_swap(void) +int enough_swap(unsigned nr_pages) { struct sysinfo i; si_swapinfo(&i); - if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO)) { - pr_debug("swsusp: Not enough swap. Need %ld\n",i.freeswap); - return 0; - } - return 1; -} - -static int swsusp_alloc(void) -{ - int error; - - pagedir_nosave = NULL; - nr_copy_pages = calc_nr(nr_copy_pages); - nr_copy_pages_check = nr_copy_pages; - - pr_debug("suspend: (pages needed: %d + %d free: %d)\n", - nr_copy_pages, PAGES_FOR_IO, nr_free_pages()); - - if (!enough_free_mem()) - return -ENOMEM; - - if (!enough_swap()) - return -ENOSPC; - - if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE + - !!(nr_copy_pages % PBES_PER_PAGE)) - return -ENOSPC; - - if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { - printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); - return -ENOMEM; - } - create_pbe_list(pagedir_save, nr_copy_pages); - pagedir_nosave = pagedir_save; - if ((error = alloc_image_pages())) { - printk(KERN_ERR "suspend: Allocating image pages failed.\n"); - swsusp_free(); - return error; - } - - return 0; -} - -static int suspend_prepare_image(void) -{ - int error; - - pr_debug("swsusp: critical section: \n"); - if (save_highmem()) { - printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n"); - restore_highmem(); - return -ENOMEM; - } - - drain_local_pages(); - count_data_pages(); - printk("swsusp: Need to copy %u pages\n", nr_copy_pages); - - error = swsusp_alloc(); - if (error) - return error; - - /* During allocating of suspend pagedir, new cold pages may appear. - * Kill them. - */ - drain_local_pages(); - copy_data_pages(); - - /* - * End of critical section. From now on, we can write to memory, - * but we should not touch disk. This specially means we must _not_ - * touch swap space! Except we must write out our image of course. - */ - - printk("swsusp: critical section/: done (%d pages copied)\n", nr_copy_pages ); - return 0; + pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); + return i.freeswap > (nr_pages + PAGES_FOR_IO + + (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); } @@ -1001,7 +562,7 @@ static int suspend_prepare_image(void) int swsusp_write(void) { int error; - device_resume(); + lock_swapdevices(); error = write_suspend_image(); /* This will unlock ignored swap devices since writing is finished */ @@ -1011,14 +572,6 @@ int swsusp_write(void) } -extern asmlinkage int swsusp_arch_suspend(void); -extern asmlinkage int swsusp_arch_resume(void); - - -asmlinkage int swsusp_save(void) -{ - return suspend_prepare_image(); -} int swsusp_suspend(void) { @@ -1050,7 +603,6 @@ int swsusp_suspend(void) printk(KERN_ERR "Error %d suspending\n", error); /* Restore control flow magically appears here */ restore_processor_state(); - BUG_ON (nr_copy_pages_check != nr_copy_pages); restore_highmem(); device_power_up(); local_irq_enable(); @@ -1070,6 +622,11 @@ int swsusp_resume(void) * execution continues at place where swsusp_arch_suspend was called */ BUG_ON(!error); + /* The only reason why swsusp_arch_resume() can fail is memory being + * very tight, so we have to free it as soon as we can to avoid + * subsequent failures + */ + swsusp_free(); restore_processor_state(); restore_highmem(); touch_softlockup_watchdog(); @@ -1085,54 +642,28 @@ int swsusp_resume(void) * * We don't know which pages are usable until we allocate them. * - * Allocated but unusable (ie eaten) memory pages are linked together - * to create a list, so that we can free them easily - * - * We could have used a type other than (void *) - * for this purpose, but ... + * Allocated but unusable (ie eaten) memory pages are marked so that + * swsusp_free() can release them */ -static void **eaten_memory = NULL; - -static inline void eat_page(void *page) -{ - void **c; - - c = eaten_memory; - eaten_memory = page; - *eaten_memory = c; -} -unsigned long get_usable_page(gfp_t gfp_mask) +unsigned long get_safe_page(gfp_t gfp_mask) { unsigned long m; - m = get_zeroed_page(gfp_mask); - while (!PageNosaveFree(virt_to_page(m))) { - eat_page((void *)m); + do { m = get_zeroed_page(gfp_mask); - if (!m) - break; + if (m && PageNosaveFree(virt_to_page(m))) + /* This is for swsusp_free() */ + SetPageNosave(virt_to_page(m)); + } while (m && PageNosaveFree(virt_to_page(m))); + if (m) { + /* This is for swsusp_free() */ + SetPageNosave(virt_to_page(m)); + SetPageNosaveFree(virt_to_page(m)); } return m; } -void free_eaten_memory(void) -{ - unsigned long m; - void **c; - int i = 0; - - c = eaten_memory; - while (c) { - m = (unsigned long)c; - c = *c; - free_page(m); - i++; - } - eaten_memory = NULL; - pr_debug("swsusp: %d unused pages freed\n", i); -} - /** * check_pagedir - We ensure here that pages that the PBEs point to * won't collide with pages where we're going to restore from the loaded @@ -1150,7 +681,7 @@ static int check_pagedir(struct pbe *pblist) p->address = 0UL; for_each_pbe (p, pblist) { - p->address = get_usable_page(GFP_ATOMIC); + p->address = get_safe_page(GFP_ATOMIC); if (!p->address) return -ENOMEM; } @@ -1169,7 +700,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) unsigned long zone_pfn; struct pbe *pbpage, *tail, *p; void *m; - int rel = 0, error = 0; + int rel = 0; if (!pblist) /* a sanity check */ return NULL; @@ -1177,41 +708,37 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) pr_debug("swsusp: Relocating pagedir (%lu pages to check)\n", swsusp_info.pagedir_pages); - /* Set page flags */ + /* Clear page flags */ for_each_zone (zone) { for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) - SetPageNosaveFree(pfn_to_page(zone_pfn + + if (pfn_valid(zone_pfn + zone->zone_start_pfn)) + ClearPageNosaveFree(pfn_to_page(zone_pfn + zone->zone_start_pfn)); } - /* Clear orig addresses */ + /* Mark orig addresses */ for_each_pbe (p, pblist) - ClearPageNosaveFree(virt_to_page(p->orig_address)); + SetPageNosaveFree(virt_to_page(p->orig_address)); tail = pblist + PB_PAGE_SKIP; /* Relocate colliding pages */ for_each_pb_page (pbpage, pblist) { - if (!PageNosaveFree(virt_to_page((unsigned long)pbpage))) { - m = (void *)get_usable_page(GFP_ATOMIC | __GFP_COLD); - if (!m) { - error = -ENOMEM; - break; - } + if (PageNosaveFree(virt_to_page((unsigned long)pbpage))) { + m = (void *)get_safe_page(GFP_ATOMIC | __GFP_COLD); + if (!m) + return NULL; memcpy(m, (void *)pbpage, PAGE_SIZE); if (pbpage == pblist) pblist = (struct pbe *)m; else tail->next = (struct pbe *)m; - - eat_page((void *)pbpage); pbpage = (struct pbe *)m; /* We have to link the PBEs again */ - for (p = pbpage; p < pbpage + PB_PAGE_SKIP; p++) if (p->next) /* needed to save the end */ p->next = p + 1; @@ -1221,15 +748,13 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) tail = pbpage + PB_PAGE_SKIP; } - if (error) { - printk("\nswsusp: Out of memory\n\n"); - free_pagedir(pblist); - free_eaten_memory(); - pblist = NULL; - /* Is this even worth handling? It should never ever happen, and we - have just lost user's state, anyway... */ - } else - printk("swsusp: Relocated %d pages\n", rel); + /* This is for swsusp_free() */ + for_each_pb_page (pbpage, pblist) { + SetPageNosave(virt_to_page(pbpage)); + SetPageNosaveFree(virt_to_page(pbpage)); + } + + printk("swsusp: Relocated %d pages\n", rel); return pblist; } @@ -1447,9 +972,7 @@ static int read_pagedir(struct pbe *pblist) break; } - if (error) - free_pagedir(pblist); - else + if (!error) BUG_ON(i != swsusp_info.pagedir_pages); return error; @@ -1492,15 +1015,6 @@ static int read_suspend_image(void) if (!error) error = data_read(pagedir_nosave); - if (error) { /* We fail cleanly */ - free_eaten_memory(); - for_each_pbe (p, pagedir_nosave) - if (p->address) { - free_page(p->address); - p->address = 0UL; - } - free_pagedir(pagedir_nosave); - } return error; } diff --git a/kernel/printk.c b/kernel/printk.c index 4b8f0f9230a..3cb9708209b 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -10,7 +10,7 @@ * elsewhere, in preparation for a serial line console (someday). * Ted Ts'o, 2/11/93. * Modified for sysctl support, 1/8/97, Chris Horn. - * Fixed SMP synchronization, 08/08/99, Manfred Spraul + * Fixed SMP synchronization, 08/08/99, Manfred Spraul * manfreds@colorfullife.com * Rewrote bits to get rid of console_lock * 01Mar01 Andrew Morton <andrewm@uow.edu.au> @@ -148,7 +148,7 @@ static int __init console_setup(char *str) if (!strcmp(str, "ttyb")) strcpy(name, "ttyS1"); #endif - for(s = name; *s; s++) + for (s = name; *s; s++) if ((*s >= '0' && *s <= '9') || *s == ',') break; idx = simple_strtoul(s, NULL, 10); @@ -169,11 +169,11 @@ static int __init log_buf_len_setup(char *str) size = roundup_pow_of_two(size); if (size > log_buf_len) { unsigned long start, dest_idx, offset; - char * new_log_buf; + char *new_log_buf; new_log_buf = alloc_bootmem(size); if (!new_log_buf) { - printk("log_buf_len: allocation failed\n"); + printk(KERN_WARNING "log_buf_len: allocation failed\n"); goto out; } @@ -193,10 +193,9 @@ static int __init log_buf_len_setup(char *str) log_end -= offset; spin_unlock_irqrestore(&logbuf_lock, flags); - printk("log_buf_len: %d\n", log_buf_len); + printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len); } out: - return 1; } @@ -217,7 +216,7 @@ __setup("log_buf_len=", log_buf_len_setup); * 9 -- Return number of unread characters in the log buffer * 10 -- Return size of the log buffer */ -int do_syslog(int type, char __user * buf, int len) +int do_syslog(int type, char __user *buf, int len) { unsigned long i, j, limit, count; int do_clear = 0; @@ -244,7 +243,8 @@ int do_syslog(int type, char __user * buf, int len) error = -EFAULT; goto out; } - error = wait_event_interruptible(log_wait, (log_start - log_end)); + error = wait_event_interruptible(log_wait, + (log_start - log_end)); if (error) goto out; i = 0; @@ -264,7 +264,7 @@ int do_syslog(int type, char __user * buf, int len) error = i; break; case 4: /* Read/clear last kernel messages */ - do_clear = 1; + do_clear = 1; /* FALL THRU */ case 3: /* Read last kernel messages */ error = -EINVAL; @@ -288,11 +288,11 @@ int do_syslog(int type, char __user * buf, int len) limit = log_end; /* * __put_user() could sleep, and while we sleep - * printk() could overwrite the messages + * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ - for(i = 0; i < count && !error; i++) { + for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; @@ -306,10 +306,10 @@ int do_syslog(int type, char __user * buf, int len) if (error) break; error = i; - if(i != count) { + if (i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ - for(i=0;i<error;i++) { + for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; @@ -351,7 +351,7 @@ out: return error; } -asmlinkage long sys_syslog(int type, char __user * buf, int len) +asmlinkage long sys_syslog(int type, char __user *buf, int len) { return do_syslog(type, buf, len); } @@ -404,21 +404,19 @@ static void call_console_drivers(unsigned long start, unsigned long end) cur_index = start; start_print = start; while (cur_index != end) { - if ( msg_level < 0 && - ((end - cur_index) > 2) && - LOG_BUF(cur_index + 0) == '<' && - LOG_BUF(cur_index + 1) >= '0' && - LOG_BUF(cur_index + 1) <= '7' && - LOG_BUF(cur_index + 2) == '>') - { + if (msg_level < 0 && ((end - cur_index) > 2) && + LOG_BUF(cur_index + 0) == '<' && + LOG_BUF(cur_index + 1) >= '0' && + LOG_BUF(cur_index + 1) <= '7' && + LOG_BUF(cur_index + 2) == '>') { msg_level = LOG_BUF(cur_index + 1) - '0'; cur_index += 3; start_print = cur_index; } while (cur_index != end) { char c = LOG_BUF(cur_index); - cur_index++; + cur_index++; if (c == '\n') { if (msg_level < 0) { /* @@ -461,7 +459,7 @@ static void zap_locks(void) static unsigned long oops_timestamp; if (time_after_eq(jiffies, oops_timestamp) && - !time_after(jiffies, oops_timestamp + 30*HZ)) + !time_after(jiffies, oops_timestamp + 30 * HZ)) return; oops_timestamp = jiffies; @@ -495,7 +493,7 @@ __attribute__((weak)) unsigned long long printk_clock(void) /* * This is printk. It can be called from any context. We want it to work. - * + * * We try to grab the console_sem. If we succeed, it's easy - we log the output and * call the console drivers. If we fail to get the semaphore we place the output * into the log buffer and return. The current holder of the console_sem will @@ -639,13 +637,19 @@ EXPORT_SYMBOL(vprintk); #else -asmlinkage long sys_syslog(int type, char __user * buf, int len) +asmlinkage long sys_syslog(int type, char __user *buf, int len) { return 0; } -int do_syslog(int type, char __user * buf, int len) { return 0; } -static void call_console_drivers(unsigned long start, unsigned long end) {} +int do_syslog(int type, char __user *buf, int len) +{ + return 0; +} + +static void call_console_drivers(unsigned long start, unsigned long end) +{ +} #endif @@ -851,9 +855,9 @@ EXPORT_SYMBOL(console_start); * print any messages that were printed by the kernel before the * console driver was initialized. */ -void register_console(struct console * console) +void register_console(struct console *console) { - int i; + int i; unsigned long flags; if (preferred_console < 0) @@ -878,7 +882,8 @@ void register_console(struct console * console) * See if this console matches one we selected on * the command line. */ - for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) { + for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; + i++) { if (strcmp(console_cmdline[i].name, console->name) != 0) continue; if (console->index >= 0 && @@ -933,9 +938,9 @@ void register_console(struct console * console) } EXPORT_SYMBOL(register_console); -int unregister_console(struct console * console) +int unregister_console(struct console *console) { - struct console *a,*b; + struct console *a, *b; int res = 1; acquire_console_sem(); @@ -949,10 +954,10 @@ int unregister_console(struct console * console) b->next = a->next; res = 0; break; - } + } } } - + /* If last console is removed, we re-enable picking the first * one that gets registered. Without that, pmac early boot console * would prevent fbcon from taking over. @@ -994,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) { static DEFINE_SPINLOCK(ratelimit_lock); - static unsigned long toks = 10*5*HZ; + static unsigned long toks = 10 * 5 * HZ; static unsigned long last_msg; static int missed; unsigned long flags; @@ -1007,6 +1012,7 @@ int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) toks = ratelimit_burst * ratelimit_jiffies; if (toks >= ratelimit_jiffies) { int lost = missed; + missed = 0; toks -= ratelimit_jiffies; spin_unlock_irqrestore(&ratelimit_lock, flags); @@ -1021,7 +1027,7 @@ int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) EXPORT_SYMBOL(__printk_ratelimit); /* minimum time in jiffies between messages */ -int printk_ratelimit_jiffies = 5*HZ; +int printk_ratelimit_jiffies = 5 * HZ; /* number of messages we send before ratelimiting */ int printk_ratelimit_burst = 10; diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 019e04ec065..863eee8bff4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -56,6 +56,10 @@ void ptrace_untrace(task_t *child) signal_wake_up(child, 1); } } + if (child->signal->flags & SIGNAL_GROUP_EXIT) { + sigaddset(&child->pending.signal, SIGKILL); + signal_wake_up(child, 1); + } spin_unlock(&child->sighand->siglock); } @@ -77,8 +81,7 @@ void __ptrace_unlink(task_t *child) SET_LINKS(child); } - if (child->state == TASK_TRACED) - ptrace_untrace(child); + ptrace_untrace(child); } /* diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 2559d4b8f23..c4d159a21e0 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -154,6 +154,15 @@ void fastcall call_rcu_bh(struct rcu_head *head, } /* + * Return the number of RCU batches processed thus far. Useful + * for debug and statistics. + */ +long rcu_batches_completed(void) +{ + return rcu_ctrlblk.completed; +} + +/* * Invoke the completed RCU callbacks. They are expected to be in * a per-cpu list. */ @@ -501,6 +510,7 @@ void synchronize_kernel(void) } module_param(maxbatch, int, 0); +EXPORT_SYMBOL_GPL(rcu_batches_completed); EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */ EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */ EXPORT_SYMBOL_GPL(synchronize_rcu); diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c new file mode 100644 index 00000000000..9b58f1eff3c --- /dev/null +++ b/kernel/rcutorture.c @@ -0,0 +1,492 @@ +/* + * Read-Copy Update /proc-based torture test facility + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2005 + * + * Authors: Paul E. McKenney <paulmck@us.ibm.com> + * + * See also: Documentation/RCU/torture.txt + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kthread.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/rcupdate.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <asm/atomic.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/completion.h> +#include <linux/moduleparam.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/rcuref.h> +#include <linux/cpu.h> +#include <linux/random.h> +#include <linux/delay.h> +#include <linux/byteorder/swabb.h> +#include <linux/stat.h> + +MODULE_LICENSE("GPL"); + +static int nreaders = -1; /* # reader threads, defaults to 4*ncpus */ +static int stat_interval = 0; /* Interval between stats, in seconds. */ + /* Defaults to "only at end of test". */ +static int verbose = 0; /* Print more debug info. */ + +MODULE_PARM(nreaders, "i"); +MODULE_PARM_DESC(nreaders, "Number of RCU reader threads"); +MODULE_PARM(stat_interval, "i"); +MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s"); +MODULE_PARM(verbose, "i"); +MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s"); +#define TORTURE_FLAG "rcutorture: " +#define PRINTK_STRING(s) \ + do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0) +#define VERBOSE_PRINTK_STRING(s) \ + do { if (verbose) printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0) +#define VERBOSE_PRINTK_ERRSTRING(s) \ + do { if (verbose) printk(KERN_ALERT TORTURE_FLAG "!!! " s "\n"); } while (0) + +static char printk_buf[4096]; + +static int nrealreaders; +static struct task_struct *writer_task; +static struct task_struct **reader_tasks; +static struct task_struct *stats_task; + +#define RCU_TORTURE_PIPE_LEN 10 + +struct rcu_torture { + struct rcu_head rtort_rcu; + int rtort_pipe_count; + struct list_head rtort_free; +}; + +static int fullstop = 0; /* stop generating callbacks at test end. */ +static LIST_HEAD(rcu_torture_freelist); +static struct rcu_torture *rcu_torture_current = NULL; +static long rcu_torture_current_version = 0; +static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN]; +static DEFINE_SPINLOCK(rcu_torture_lock); +static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = + { 0 }; +static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) = + { 0 }; +static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1]; +atomic_t n_rcu_torture_alloc; +atomic_t n_rcu_torture_alloc_fail; +atomic_t n_rcu_torture_free; + +/* + * Allocate an element from the rcu_tortures pool. + */ +struct rcu_torture * +rcu_torture_alloc(void) +{ + struct list_head *p; + + spin_lock(&rcu_torture_lock); + if (list_empty(&rcu_torture_freelist)) { + atomic_inc(&n_rcu_torture_alloc_fail); + spin_unlock(&rcu_torture_lock); + return NULL; + } + atomic_inc(&n_rcu_torture_alloc); + p = rcu_torture_freelist.next; + list_del_init(p); + spin_unlock(&rcu_torture_lock); + return container_of(p, struct rcu_torture, rtort_free); +} + +/* + * Free an element to the rcu_tortures pool. + */ +static void +rcu_torture_free(struct rcu_torture *p) +{ + atomic_inc(&n_rcu_torture_free); + spin_lock(&rcu_torture_lock); + list_add_tail(&p->rtort_free, &rcu_torture_freelist); + spin_unlock(&rcu_torture_lock); +} + +static void +rcu_torture_cb(struct rcu_head *p) +{ + int i; + struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu); + + if (fullstop) { + /* Test is ending, just drop callbacks on the floor. */ + /* The next initialization will pick up the pieces. */ + return; + } + i = rp->rtort_pipe_count; + if (i > RCU_TORTURE_PIPE_LEN) + i = RCU_TORTURE_PIPE_LEN; + atomic_inc(&rcu_torture_wcount[i]); + if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) + rcu_torture_free(rp); + else + call_rcu(p, rcu_torture_cb); +} + +struct rcu_random_state { + unsigned long rrs_state; + unsigned long rrs_count; +}; + +#define RCU_RANDOM_MULT 39916801 /* prime */ +#define RCU_RANDOM_ADD 479001701 /* prime */ +#define RCU_RANDOM_REFRESH 10000 + +#define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 } + +/* + * Crude but fast random-number generator. Uses a linear congruential + * generator, with occasional help from get_random_bytes(). + */ +static long +rcu_random(struct rcu_random_state *rrsp) +{ + long refresh; + + if (--rrsp->rrs_count < 0) { + get_random_bytes(&refresh, sizeof(refresh)); + rrsp->rrs_state += refresh; + rrsp->rrs_count = RCU_RANDOM_REFRESH; + } + rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD; + return swahw32(rrsp->rrs_state); +} + +/* + * RCU torture writer kthread. Repeatedly substitutes a new structure + * for that pointed to by rcu_torture_current, freeing the old structure + * after a series of grace periods (the "pipeline"). + */ +static int +rcu_torture_writer(void *arg) +{ + int i; + long oldbatch = rcu_batches_completed(); + struct rcu_torture *rp; + struct rcu_torture *old_rp; + static DEFINE_RCU_RANDOM(rand); + + VERBOSE_PRINTK_STRING("rcu_torture_writer task started"); + do { + schedule_timeout_uninterruptible(1); + if (rcu_batches_completed() == oldbatch) + continue; + if ((rp = rcu_torture_alloc()) == NULL) + continue; + rp->rtort_pipe_count = 0; + udelay(rcu_random(&rand) & 0x3ff); + old_rp = rcu_torture_current; + rcu_assign_pointer(rcu_torture_current, rp); + smp_wmb(); + if (old_rp != NULL) { + i = old_rp->rtort_pipe_count; + if (i > RCU_TORTURE_PIPE_LEN) + i = RCU_TORTURE_PIPE_LEN; + atomic_inc(&rcu_torture_wcount[i]); + old_rp->rtort_pipe_count++; + call_rcu(&old_rp->rtort_rcu, rcu_torture_cb); + } + rcu_torture_current_version++; + oldbatch = rcu_batches_completed(); + } while (!kthread_should_stop() && !fullstop); + VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); + while (!kthread_should_stop()) + schedule_timeout_uninterruptible(1); + return 0; +} + +/* + * RCU torture reader kthread. Repeatedly dereferences rcu_torture_current, + * incrementing the corresponding element of the pipeline array. The + * counter in the element should never be greater than 1, otherwise, the + * RCU implementation is broken. + */ +static int +rcu_torture_reader(void *arg) +{ + int completed; + DEFINE_RCU_RANDOM(rand); + struct rcu_torture *p; + int pipe_count; + + VERBOSE_PRINTK_STRING("rcu_torture_reader task started"); + do { + rcu_read_lock(); + completed = rcu_batches_completed(); + p = rcu_dereference(rcu_torture_current); + if (p == NULL) { + /* Wait for rcu_torture_writer to get underway */ + rcu_read_unlock(); + schedule_timeout_interruptible(HZ); + continue; + } + udelay(rcu_random(&rand) & 0x7f); + preempt_disable(); + pipe_count = p->rtort_pipe_count; + if (pipe_count > RCU_TORTURE_PIPE_LEN) { + /* Should not happen, but... */ + pipe_count = RCU_TORTURE_PIPE_LEN; + } + ++__get_cpu_var(rcu_torture_count)[pipe_count]; + completed = rcu_batches_completed() - completed; + if (completed > RCU_TORTURE_PIPE_LEN) { + /* Should not happen, but... */ + completed = RCU_TORTURE_PIPE_LEN; + } + ++__get_cpu_var(rcu_torture_batch)[completed]; + preempt_enable(); + rcu_read_unlock(); + schedule(); + } while (!kthread_should_stop() && !fullstop); + VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping"); + while (!kthread_should_stop()) + schedule_timeout_uninterruptible(1); + return 0; +} + +/* + * Create an RCU-torture statistics message in the specified buffer. + */ +static int +rcu_torture_printk(char *page) +{ + int cnt = 0; + int cpu; + int i; + long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; + long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; + + for_each_cpu(cpu) { + for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { + pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i]; + batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i]; + } + } + for (i = RCU_TORTURE_PIPE_LEN - 1; i >= 0; i--) { + if (pipesummary[i] != 0) + break; + } + cnt += sprintf(&page[cnt], "rcutorture: "); + cnt += sprintf(&page[cnt], + "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d", + rcu_torture_current, + rcu_torture_current_version, + list_empty(&rcu_torture_freelist), + atomic_read(&n_rcu_torture_alloc), + atomic_read(&n_rcu_torture_alloc_fail), + atomic_read(&n_rcu_torture_free)); + cnt += sprintf(&page[cnt], "\nrcutorture: "); + if (i > 1) + cnt += sprintf(&page[cnt], "!!! "); + cnt += sprintf(&page[cnt], "Reader Pipe: "); + for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) + cnt += sprintf(&page[cnt], " %ld", pipesummary[i]); + cnt += sprintf(&page[cnt], "\nrcutorture: "); + cnt += sprintf(&page[cnt], "Reader Batch: "); + for (i = 0; i < RCU_TORTURE_PIPE_LEN; i++) + cnt += sprintf(&page[cnt], " %ld", batchsummary[i]); + cnt += sprintf(&page[cnt], "\nrcutorture: "); + cnt += sprintf(&page[cnt], "Free-Block Circulation: "); + for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { + cnt += sprintf(&page[cnt], " %d", + atomic_read(&rcu_torture_wcount[i])); + } + cnt += sprintf(&page[cnt], "\n"); + return cnt; +} + +/* + * Print torture statistics. Caller must ensure that there is only + * one call to this function at a given time!!! This is normally + * accomplished by relying on the module system to only have one copy + * of the module loaded, and then by giving the rcu_torture_stats + * kthread full control (or the init/cleanup functions when rcu_torture_stats + * thread is not running). + */ +static void +rcu_torture_stats_print(void) +{ + int cnt; + + cnt = rcu_torture_printk(printk_buf); + printk(KERN_ALERT "%s", printk_buf); +} + +/* + * Periodically prints torture statistics, if periodic statistics printing + * was specified via the stat_interval module parameter. + * + * No need to worry about fullstop here, since this one doesn't reference + * volatile state or register callbacks. + */ +static int +rcu_torture_stats(void *arg) +{ + VERBOSE_PRINTK_STRING("rcu_torture_stats task started"); + do { + schedule_timeout_interruptible(stat_interval * HZ); + rcu_torture_stats_print(); + } while (!kthread_should_stop()); + VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping"); + return 0; +} + +static void +rcu_torture_cleanup(void) +{ + int i; + + fullstop = 1; + if (writer_task != NULL) { + VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task"); + kthread_stop(writer_task); + } + writer_task = NULL; + + if (reader_tasks != NULL) { + for (i = 0; i < nrealreaders; i++) { + if (reader_tasks[i] != NULL) { + VERBOSE_PRINTK_STRING( + "Stopping rcu_torture_reader task"); + kthread_stop(reader_tasks[i]); + } + reader_tasks[i] = NULL; + } + kfree(reader_tasks); + reader_tasks = NULL; + } + rcu_torture_current = NULL; + + if (stats_task != NULL) { + VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task"); + kthread_stop(stats_task); + } + stats_task = NULL; + + /* Wait for all RCU callbacks to fire. */ + + for (i = 0; i < RCU_TORTURE_PIPE_LEN; i++) + synchronize_rcu(); + rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ + PRINTK_STRING("--- End of test"); +} + +static int +rcu_torture_init(void) +{ + int i; + int cpu; + int firsterr = 0; + + /* Process args and tell the world that the torturer is on the job. */ + + if (nreaders >= 0) + nrealreaders = nreaders; + else + nrealreaders = 2 * num_online_cpus(); + printk(KERN_ALERT TORTURE_FLAG + "--- Start of test: nreaders=%d stat_interval=%d verbose=%d\n", + nrealreaders, stat_interval, verbose); + fullstop = 0; + + /* Set up the freelist. */ + + INIT_LIST_HEAD(&rcu_torture_freelist); + for (i = 0; i < sizeof(rcu_tortures) / sizeof(rcu_tortures[0]); i++) { + list_add_tail(&rcu_tortures[i].rtort_free, + &rcu_torture_freelist); + } + + /* Initialize the statistics so that each run gets its own numbers. */ + + rcu_torture_current = NULL; + rcu_torture_current_version = 0; + atomic_set(&n_rcu_torture_alloc, 0); + atomic_set(&n_rcu_torture_alloc_fail, 0); + atomic_set(&n_rcu_torture_free, 0); + for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) + atomic_set(&rcu_torture_wcount[i], 0); + for_each_cpu(cpu) { + for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { + per_cpu(rcu_torture_count, cpu)[i] = 0; + per_cpu(rcu_torture_batch, cpu)[i] = 0; + } + } + + /* Start up the kthreads. */ + + VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task"); + writer_task = kthread_run(rcu_torture_writer, NULL, + "rcu_torture_writer"); + if (IS_ERR(writer_task)) { + firsterr = PTR_ERR(writer_task); + VERBOSE_PRINTK_ERRSTRING("Failed to create writer"); + writer_task = NULL; + goto unwind; + } + reader_tasks = kmalloc(nrealreaders * sizeof(reader_tasks[0]), + GFP_KERNEL); + if (reader_tasks == NULL) { + VERBOSE_PRINTK_ERRSTRING("out of memory"); + firsterr = -ENOMEM; + goto unwind; + } + for (i = 0; i < nrealreaders; i++) { + VERBOSE_PRINTK_STRING("Creating rcu_torture_reader task"); + reader_tasks[i] = kthread_run(rcu_torture_reader, NULL, + "rcu_torture_reader"); + if (IS_ERR(reader_tasks[i])) { + firsterr = PTR_ERR(reader_tasks[i]); + VERBOSE_PRINTK_ERRSTRING("Failed to create reader"); + reader_tasks[i] = NULL; + goto unwind; + } + } + if (stat_interval > 0) { + VERBOSE_PRINTK_STRING("Creating rcu_torture_stats task"); + stats_task = kthread_run(rcu_torture_stats, NULL, + "rcu_torture_stats"); + if (IS_ERR(stats_task)) { + firsterr = PTR_ERR(stats_task); + VERBOSE_PRINTK_ERRSTRING("Failed to create stats"); + stats_task = NULL; + goto unwind; + } + } + return 0; + +unwind: + rcu_torture_cleanup(); + return firsterr; +} + +module_init(rcu_torture_init); +module_exit(rcu_torture_cleanup); diff --git a/kernel/sched.c b/kernel/sched.c index 4f26c544d02..340dd238c16 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3877,7 +3877,6 @@ EXPORT_SYMBOL(cpu_present_map); #ifndef CONFIG_SMP cpumask_t cpu_online_map = CPU_MASK_ALL; -EXPORT_SYMBOL_GPL(cpu_online_map); cpumask_t cpu_possible_map = CPU_MASK_ALL; #endif diff --git a/kernel/signal.c b/kernel/signal.c index 6904bbbfe11..1bf3c39d610 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -277,7 +277,6 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, } else { INIT_LIST_HEAD(&q->list); q->flags = 0; - q->lock = NULL; q->user = get_uid(t->user); } return(q); @@ -652,8 +651,7 @@ static int check_kill_permission(int sig, struct siginfo *info, if (!valid_signal(sig)) return error; error = -EPERM; - if ((!info || ((unsigned long)info != 1 && - (unsigned long)info != 2 && SI_FROMUSER(info))) + if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) && ((sig != SIGCONT) || (current->signal->session != t->signal->session)) && (current->euid ^ t->suid) && (current->euid ^ t->uid) @@ -790,7 +788,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, * fast-pathed signals for kernel-internal things like SIGSTOP * or SIGKILL. */ - if ((unsigned long)info == 2) + if (info == SEND_SIG_FORCED) goto out_set; /* Real-time signals must be queued if sent by sigqueue, or @@ -802,19 +800,19 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, pass on the info struct. */ q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && - ((unsigned long) info < 2 || + (is_si_special(info) || info->si_code >= 0))); if (q) { list_add_tail(&q->list, &signals->list); switch ((unsigned long) info) { - case 0: + case (unsigned long) SEND_SIG_NOINFO: q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_USER; q->info.si_pid = current->pid; q->info.si_uid = current->uid; break; - case 1: + case (unsigned long) SEND_SIG_PRIV: q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_KERNEL; @@ -825,20 +823,13 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, copy_siginfo(&q->info, info); break; } - } else { - if (sig >= SIGRTMIN && info && (unsigned long)info != 1 - && info->si_code != SI_USER) + } else if (!is_si_special(info)) { + if (sig >= SIGRTMIN && info->si_code != SI_USER) /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). */ return -EAGAIN; - if (((unsigned long)info > 1) && (info->si_code == SI_TIMER)) - /* - * Set up a return to indicate that we dropped - * the signal. - */ - ret = info->si_sys_private; } out_set: @@ -859,12 +850,6 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) BUG(); assert_spin_locked(&t->sighand->siglock); - if (((unsigned long)info > 2) && (info->si_code == SI_TIMER)) - /* - * Set up a return to indicate that we dropped the signal. - */ - ret = info->si_sys_private; - /* Short-circuit ignored signals. */ if (sig_ignored(t, sig)) goto out; @@ -894,11 +879,13 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t) int ret; spin_lock_irqsave(&t->sighand->siglock, flags); - if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { + if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; + } + if (sigismember(&t->blocked, sig)) { sigdelset(&t->blocked, sig); - recalc_sigpending_tsk(t); } + recalc_sigpending_tsk(t); ret = specific_send_sig_info(sig, info, t); spin_unlock_irqrestore(&t->sighand->siglock, flags); @@ -908,15 +895,7 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t) void force_sig_specific(int sig, struct task_struct *t) { - unsigned long int flags; - - spin_lock_irqsave(&t->sighand->siglock, flags); - if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) - t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; - sigdelset(&t->blocked, sig); - recalc_sigpending_tsk(t); - specific_send_sig_info(sig, (void *)2, t); - spin_unlock_irqrestore(&t->sighand->siglock, flags); + force_sig_info(sig, SEND_SIG_FORCED, t); } /* @@ -1051,12 +1030,6 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) assert_spin_locked(&p->sighand->siglock); handle_stop_signal(sig, p); - if (((unsigned long)info > 2) && (info->si_code == SI_TIMER)) - /* - * Set up a return to indicate that we dropped the signal. - */ - ret = info->si_sys_private; - /* Short-circuit ignored signals. */ if (sig_ignored(p, sig)) return ret; @@ -1109,8 +1082,8 @@ void zap_other_threads(struct task_struct *p) if (t != p->group_leader) t->exit_signal = -1; + /* SIGKILL will be handled before any pending SIGSTOP */ sigaddset(&t->pending.signal, SIGKILL); - rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); signal_wake_up(t, 1); } } @@ -1286,10 +1259,13 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) return ret; } +#define __si_special(priv) \ + ((priv) ? SEND_SIG_PRIV : SEND_SIG_NOINFO) + int send_sig(int sig, struct task_struct *p, int priv) { - return send_sig_info(sig, (void*)(long)(priv != 0), p); + return send_sig_info(sig, __si_special(priv), p); } /* @@ -1309,7 +1285,7 @@ send_group_sig_info(int sig, struct siginfo *info, struct task_struct *p) void force_sig(int sig, struct task_struct *p) { - force_sig_info(sig, (void*)1L, p); + force_sig_info(sig, SEND_SIG_PRIV, p); } /* @@ -1334,13 +1310,13 @@ force_sigsegv(int sig, struct task_struct *p) int kill_pg(pid_t pgrp, int sig, int priv) { - return kill_pg_info(sig, (void *)(long)(priv != 0), pgrp); + return kill_pg_info(sig, __si_special(priv), pgrp); } int kill_proc(pid_t pid, int sig, int priv) { - return kill_proc_info(sig, (void *)(long)(priv != 0), pid); + return kill_proc_info(sig, __si_special(priv), pid); } /* @@ -1371,11 +1347,12 @@ void sigqueue_free(struct sigqueue *q) * pending queue. */ if (unlikely(!list_empty(&q->list))) { - read_lock(&tasklist_lock); - spin_lock_irqsave(q->lock, flags); + spinlock_t *lock = ¤t->sighand->siglock; + read_lock(&tasklist_lock); + spin_lock_irqsave(lock, flags); if (!list_empty(&q->list)) list_del_init(&q->list); - spin_unlock_irqrestore(q->lock, flags); + spin_unlock_irqrestore(lock, flags); read_unlock(&tasklist_lock); } q->flags &= ~SIGQUEUE_PREALLOC; @@ -1414,7 +1391,6 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) goto out; } - q->lock = &p->sighand->siglock; list_add_tail(&q->list, &p->pending.list); sigaddset(&p->pending.signal, sig); if (!sigismember(&p->blocked, sig)) @@ -1462,7 +1438,6 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) * We always use the shared queue for process-wide signals, * to avoid several races. */ - q->lock = &p->sighand->siglock; list_add_tail(&q->list, &p->signal->shared_pending.list); sigaddset(&p->signal->shared_pending.signal, sig); @@ -1881,9 +1856,9 @@ relock: /* Let the debugger run. */ ptrace_stop(signr, signr, info); - /* We're back. Did the debugger cancel the sig? */ + /* We're back. Did the debugger cancel the sig or group_exit? */ signr = current->exit_code; - if (signr == 0) + if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT) continue; current->exit_code = 0; @@ -2285,26 +2260,13 @@ sys_kill(int pid, int sig) return kill_something_info(sig, &info, pid); } -/** - * sys_tgkill - send signal to one specific thread - * @tgid: the thread group ID of the thread - * @pid: the PID of the thread - * @sig: signal to be sent - * - * This syscall also checks the tgid and returns -ESRCH even if the PID - * exists but it's not belonging to the target process anymore. This - * method solves the problem of threads exiting and PIDs getting reused. - */ -asmlinkage long sys_tgkill(int tgid, int pid, int sig) +static int do_tkill(int tgid, int pid, int sig) { - struct siginfo info; int error; + struct siginfo info; struct task_struct *p; - /* This is only valid for single tasks */ - if (pid <= 0 || tgid <= 0) - return -EINVAL; - + error = -ESRCH; info.si_signo = sig; info.si_errno = 0; info.si_code = SI_TKILL; @@ -2313,8 +2275,7 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig) read_lock(&tasklist_lock); p = find_task_by_pid(pid); - error = -ESRCH; - if (p && (p->tgid == tgid)) { + if (p && (tgid <= 0 || p->tgid == tgid)) { error = check_kill_permission(sig, &info, p); /* * The null signal is a permissions and process existence @@ -2328,47 +2289,40 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig) } } read_unlock(&tasklist_lock); + return error; } +/** + * sys_tgkill - send signal to one specific thread + * @tgid: the thread group ID of the thread + * @pid: the PID of the thread + * @sig: signal to be sent + * + * This syscall also checks the tgid and returns -ESRCH even if the PID + * exists but it's not belonging to the target process anymore. This + * method solves the problem of threads exiting and PIDs getting reused. + */ +asmlinkage long sys_tgkill(int tgid, int pid, int sig) +{ + /* This is only valid for single tasks */ + if (pid <= 0 || tgid <= 0) + return -EINVAL; + + return do_tkill(tgid, pid, sig); +} + /* * Send a signal to only one task, even if it's a CLONE_THREAD task. */ asmlinkage long sys_tkill(int pid, int sig) { - struct siginfo info; - int error; - struct task_struct *p; - /* This is only valid for single tasks */ if (pid <= 0) return -EINVAL; - info.si_signo = sig; - info.si_errno = 0; - info.si_code = SI_TKILL; - info.si_pid = current->tgid; - info.si_uid = current->uid; - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - error = -ESRCH; - if (p) { - error = check_kill_permission(sig, &info, p); - /* - * The null signal is a permissions and process existence - * probe. No signal is actually delivered. - */ - if (!error && sig && p->sighand) { - spin_lock_irq(&p->sighand->siglock); - handle_stop_signal(sig, p); - error = specific_send_sig_info(sig, &info, p); - spin_unlock_irq(&p->sighand->siglock); - } - } - read_unlock(&tasklist_lock); - return error; + return do_tkill(0, pid, sig); } asmlinkage long diff --git a/kernel/time.c b/kernel/time.c index a3c2100470e..245d595a13c 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -338,30 +338,20 @@ int do_adjtimex(struct timex *txc) if (mtemp >= MINSEC) { ltemp = (time_offset / mtemp) << (SHIFT_USEC - SHIFT_UPDATE); - if (ltemp < 0) - time_freq -= -ltemp >> SHIFT_KH; - else - time_freq += ltemp >> SHIFT_KH; + time_freq += shift_right(ltemp, SHIFT_KH); } else /* calibration interval too short (p. 12) */ result = TIME_ERROR; } else { /* PLL mode */ if (mtemp < MAXSEC) { ltemp *= mtemp; - if (ltemp < 0) - time_freq -= -ltemp >> (time_constant + - time_constant + - SHIFT_KF - SHIFT_USEC); - else - time_freq += ltemp >> (time_constant + + time_freq += shift_right(ltemp,(time_constant + time_constant + - SHIFT_KF - SHIFT_USEC); + SHIFT_KF - SHIFT_USEC)); } else /* calibration interval too long (p. 12) */ result = TIME_ERROR; } - if (time_freq > time_tolerance) - time_freq = time_tolerance; - else if (time_freq < -time_tolerance) - time_freq = -time_tolerance; + time_freq = min(time_freq, time_tolerance); + time_freq = max(time_freq, -time_tolerance); } /* STA_PLL || STA_PPSTIME */ } /* txc->modes & ADJ_OFFSET */ if (txc->modes & ADJ_TICK) { @@ -384,10 +374,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) txc->offset = save_adjust; else { - if (time_offset < 0) - txc->offset = -(-time_offset >> SHIFT_UPDATE); - else - txc->offset = time_offset >> SHIFT_UPDATE; + txc->offset = shift_right(time_offset, SHIFT_UPDATE); } txc->freq = time_freq + pps_freq; txc->maxerror = time_maxerror; diff --git a/kernel/timer.c b/kernel/timer.c index 6a2e5f8dc72..fd74268d866 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -46,6 +46,10 @@ static void time_interpolator_update(long delta_nsec); #define time_interpolator_update(x) #endif +u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; + +EXPORT_SYMBOL(jiffies_64); + /* * per-CPU timer vector definitions: */ @@ -91,30 +95,6 @@ static inline void set_running_timer(tvec_base_t *base, #endif } -static void check_timer_failed(struct timer_list *timer) -{ - static int whine_count; - if (whine_count < 16) { - whine_count++; - printk("Uninitialised timer!\n"); - printk("This is just a warning. Your computer is OK\n"); - printk("function=0x%p, data=0x%lx\n", - timer->function, timer->data); - dump_stack(); - } - /* - * Now fix it up - */ - timer->magic = TIMER_MAGIC; -} - -static inline void check_timer(struct timer_list *timer) -{ - if (timer->magic != TIMER_MAGIC) - check_timer_failed(timer); -} - - static void internal_add_timer(tvec_base_t *base, struct timer_list *timer) { unsigned long expires = timer->expires; @@ -177,7 +157,6 @@ void fastcall init_timer(struct timer_list *timer) { timer->entry.next = NULL; timer->base = &per_cpu(tvec_bases, raw_smp_processor_id()).t_base; - timer->magic = TIMER_MAGIC; } EXPORT_SYMBOL(init_timer); @@ -230,7 +209,6 @@ int __mod_timer(struct timer_list *timer, unsigned long expires) int ret = 0; BUG_ON(!timer->function); - check_timer(timer); base = lock_timer_base(timer, &flags); @@ -283,9 +261,6 @@ void add_timer_on(struct timer_list *timer, int cpu) unsigned long flags; BUG_ON(timer_pending(timer) || !timer->function); - - check_timer(timer); - spin_lock_irqsave(&base->t_base.lock, flags); timer->base = &base->t_base; internal_add_timer(base, timer); @@ -316,8 +291,6 @@ int mod_timer(struct timer_list *timer, unsigned long expires) { BUG_ON(!timer->function); - check_timer(timer); - /* * This is a common optimization triggered by the * networking code - if the timer is re-modified @@ -348,8 +321,6 @@ int del_timer(struct timer_list *timer) unsigned long flags; int ret = 0; - check_timer(timer); - if (timer_pending(timer)) { base = lock_timer_base(timer, &flags); if (timer_pending(timer)) { @@ -412,8 +383,6 @@ out: */ int del_timer_sync(struct timer_list *timer) { - check_timer(timer); - for (;;) { int ret = try_to_del_timer_sync(timer); if (ret >= 0) @@ -632,143 +601,118 @@ long time_next_adjust; */ static void second_overflow(void) { - long ltemp; - - /* Bump the maxerror field */ - time_maxerror += time_tolerance >> SHIFT_USEC; - if ( time_maxerror > NTP_PHASE_LIMIT ) { - time_maxerror = NTP_PHASE_LIMIT; - time_status |= STA_UNSYNC; - } - - /* - * Leap second processing. If in leap-insert state at - * the end of the day, the system clock is set back one - * second; if in leap-delete state, the system clock is - * set ahead one second. The microtime() routine or - * external clock driver will insure that reported time - * is always monotonic. The ugly divides should be - * replaced. - */ - switch (time_state) { - - case TIME_OK: - if (time_status & STA_INS) - time_state = TIME_INS; - else if (time_status & STA_DEL) - time_state = TIME_DEL; - break; - - case TIME_INS: - if (xtime.tv_sec % 86400 == 0) { - xtime.tv_sec--; - wall_to_monotonic.tv_sec++; - /* The timer interpolator will make time change gradually instead - * of an immediate jump by one second. - */ - time_interpolator_update(-NSEC_PER_SEC); - time_state = TIME_OOP; - clock_was_set(); - printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n"); + long ltemp; + + /* Bump the maxerror field */ + time_maxerror += time_tolerance >> SHIFT_USEC; + if (time_maxerror > NTP_PHASE_LIMIT) { + time_maxerror = NTP_PHASE_LIMIT; + time_status |= STA_UNSYNC; } - break; - - case TIME_DEL: - if ((xtime.tv_sec + 1) % 86400 == 0) { - xtime.tv_sec++; - wall_to_monotonic.tv_sec--; - /* Use of time interpolator for a gradual change of time */ - time_interpolator_update(NSEC_PER_SEC); - time_state = TIME_WAIT; - clock_was_set(); - printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n"); + + /* + * Leap second processing. If in leap-insert state at the end of the + * day, the system clock is set back one second; if in leap-delete + * state, the system clock is set ahead one second. The microtime() + * routine or external clock driver will insure that reported time is + * always monotonic. The ugly divides should be replaced. + */ + switch (time_state) { + case TIME_OK: + if (time_status & STA_INS) + time_state = TIME_INS; + else if (time_status & STA_DEL) + time_state = TIME_DEL; + break; + case TIME_INS: + if (xtime.tv_sec % 86400 == 0) { + xtime.tv_sec--; + wall_to_monotonic.tv_sec++; + /* + * The timer interpolator will make time change + * gradually instead of an immediate jump by one second + */ + time_interpolator_update(-NSEC_PER_SEC); + time_state = TIME_OOP; + clock_was_set(); + printk(KERN_NOTICE "Clock: inserting leap second " + "23:59:60 UTC\n"); + } + break; + case TIME_DEL: + if ((xtime.tv_sec + 1) % 86400 == 0) { + xtime.tv_sec++; + wall_to_monotonic.tv_sec--; + /* + * Use of time interpolator for a gradual change of + * time + */ + time_interpolator_update(NSEC_PER_SEC); + time_state = TIME_WAIT; + clock_was_set(); + printk(KERN_NOTICE "Clock: deleting leap second " + "23:59:59 UTC\n"); + } + break; + case TIME_OOP: + time_state = TIME_WAIT; + break; + case TIME_WAIT: + if (!(time_status & (STA_INS | STA_DEL))) + time_state = TIME_OK; } - break; - - case TIME_OOP: - time_state = TIME_WAIT; - break; - - case TIME_WAIT: - if (!(time_status & (STA_INS | STA_DEL))) - time_state = TIME_OK; - } - - /* - * Compute the phase adjustment for the next second. In - * PLL mode, the offset is reduced by a fixed factor - * times the time constant. In FLL mode the offset is - * used directly. In either mode, the maximum phase - * adjustment for each second is clamped so as to spread - * the adjustment over not more than the number of - * seconds between updates. - */ - if (time_offset < 0) { - ltemp = -time_offset; - if (!(time_status & STA_FLL)) - ltemp >>= SHIFT_KG + time_constant; - if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE) - ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE; - time_offset += ltemp; - time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); - } else { + + /* + * Compute the phase adjustment for the next second. In PLL mode, the + * offset is reduced by a fixed factor times the time constant. In FLL + * mode the offset is used directly. In either mode, the maximum phase + * adjustment for each second is clamped so as to spread the adjustment + * over not more than the number of seconds between updates. + */ ltemp = time_offset; if (!(time_status & STA_FLL)) - ltemp >>= SHIFT_KG + time_constant; - if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE) - ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE; + ltemp = shift_right(ltemp, SHIFT_KG + time_constant); + ltemp = min(ltemp, (MAXPHASE / MINSEC) << SHIFT_UPDATE); + ltemp = max(ltemp, -(MAXPHASE / MINSEC) << SHIFT_UPDATE); time_offset -= ltemp; time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); - } - - /* - * Compute the frequency estimate and additional phase - * adjustment due to frequency error for the next - * second. When the PPS signal is engaged, gnaw on the - * watchdog counter and update the frequency computed by - * the pll and the PPS signal. - */ - pps_valid++; - if (pps_valid == PPS_VALID) { /* PPS signal lost */ - pps_jitter = MAXTIME; - pps_stabil = MAXFREQ; - time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | - STA_PPSWANDER | STA_PPSERROR); - } - ltemp = time_freq + pps_freq; - if (ltemp < 0) - time_adj -= -ltemp >> - (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); - else - time_adj += ltemp >> - (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); + + /* + * Compute the frequency estimate and additional phase adjustment due + * to frequency error for the next second. When the PPS signal is + * engaged, gnaw on the watchdog counter and update the frequency + * computed by the pll and the PPS signal. + */ + pps_valid++; + if (pps_valid == PPS_VALID) { /* PPS signal lost */ + pps_jitter = MAXTIME; + pps_stabil = MAXFREQ; + time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | + STA_PPSWANDER | STA_PPSERROR); + } + ltemp = time_freq + pps_freq; + time_adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE)); #if HZ == 100 - /* Compensate for (HZ==100) != (1 << SHIFT_HZ). - * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14) - */ - if (time_adj < 0) - time_adj -= (-time_adj >> 2) + (-time_adj >> 5); - else - time_adj += (time_adj >> 2) + (time_adj >> 5); + /* + * Compensate for (HZ==100) != (1 << SHIFT_HZ). Add 25% and 3.125% to + * get 128.125; => only 0.125% error (p. 14) + */ + time_adj += shift_right(time_adj, 2) + shift_right(time_adj, 5); #endif #if HZ == 250 - /* Compensate for (HZ==250) != (1 << SHIFT_HZ). - * Add 1.5625% and 0.78125% to get 255.85938; => only 0.05% error (p. 14) - */ - if (time_adj < 0) - time_adj -= (-time_adj >> 6) + (-time_adj >> 7); - else - time_adj += (time_adj >> 6) + (time_adj >> 7); + /* + * Compensate for (HZ==250) != (1 << SHIFT_HZ). Add 1.5625% and + * 0.78125% to get 255.85938; => only 0.05% error (p. 14) + */ + time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7); #endif #if HZ == 1000 - /* Compensate for (HZ==1000) != (1 << SHIFT_HZ). - * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14) - */ - if (time_adj < 0) - time_adj -= (-time_adj >> 6) + (-time_adj >> 7); - else - time_adj += (time_adj >> 6) + (time_adj >> 7); + /* + * Compensate for (HZ==1000) != (1 << SHIFT_HZ). Add 1.5625% and + * 0.78125% to get 1023.4375; => only 0.05% error (p. 14) + */ + time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7); #endif } @@ -777,23 +721,20 @@ static void update_wall_time_one_tick(void) { long time_adjust_step, delta_nsec; - if ( (time_adjust_step = time_adjust) != 0 ) { - /* We are doing an adjtime thing. - * - * Prepare time_adjust_step to be within bounds. - * Note that a positive time_adjust means we want the clock - * to run faster. - * - * Limit the amount of the step to be in the range - * -tickadj .. +tickadj - */ - if (time_adjust > tickadj) - time_adjust_step = tickadj; - else if (time_adjust < -tickadj) - time_adjust_step = -tickadj; - - /* Reduce by this step the amount of time left */ - time_adjust -= time_adjust_step; + if ((time_adjust_step = time_adjust) != 0 ) { + /* + * We are doing an adjtime thing. Prepare time_adjust_step to + * be within bounds. Note that a positive time_adjust means we + * want the clock to run faster. + * + * Limit the amount of the step to be in the range + * -tickadj .. +tickadj + */ + time_adjust_step = min(time_adjust_step, (long)tickadj); + time_adjust_step = max(time_adjust_step, (long)-tickadj); + + /* Reduce by this step the amount of time left */ + time_adjust -= time_adjust_step; } delta_nsec = tick_nsec + time_adjust_step * 1000; /* @@ -801,13 +742,8 @@ static void update_wall_time_one_tick(void) * advance the tick more. */ time_phase += time_adj; - if (time_phase <= -FINENSEC) { - long ltemp = -time_phase >> (SHIFT_SCALE - 10); - time_phase += ltemp << (SHIFT_SCALE - 10); - delta_nsec -= ltemp; - } - else if (time_phase >= FINENSEC) { - long ltemp = time_phase >> (SHIFT_SCALE - 10); + if ((time_phase >= FINENSEC) || (time_phase <= -FINENSEC)) { + long ltemp = shift_right(time_phase, (SHIFT_SCALE - 10)); time_phase -= ltemp << (SHIFT_SCALE - 10); delta_nsec += ltemp; } @@ -1137,8 +1073,8 @@ fastcall signed long __sched schedule_timeout(signed long timeout) if (timeout < 0) { printk(KERN_ERR "schedule_timeout: wrong timeout " - "value %lx from %p\n", timeout, - __builtin_return_address(0)); + "value %lx from %p\n", timeout, + __builtin_return_address(0)); current->state = TASK_RUNNING; goto out; } @@ -1146,12 +1082,8 @@ fastcall signed long __sched schedule_timeout(signed long timeout) expire = timeout + jiffies; - init_timer(&timer); - timer.expires = expire; - timer.data = (unsigned long) current; - timer.function = process_timeout; - - add_timer(&timer); + setup_timer(&timer, process_timeout, (unsigned long)current); + __mod_timer(&timer, expire); schedule(); del_singleshot_timer_sync(&timer); @@ -1168,15 +1100,15 @@ EXPORT_SYMBOL(schedule_timeout); */ signed long __sched schedule_timeout_interruptible(signed long timeout) { - __set_current_state(TASK_INTERRUPTIBLE); - return schedule_timeout(timeout); + __set_current_state(TASK_INTERRUPTIBLE); + return schedule_timeout(timeout); } EXPORT_SYMBOL(schedule_timeout_interruptible); signed long __sched schedule_timeout_uninterruptible(signed long timeout) { - __set_current_state(TASK_UNINTERRUPTIBLE); - return schedule_timeout(timeout); + __set_current_state(TASK_UNINTERRUPTIBLE); + return schedule_timeout(timeout); } EXPORT_SYMBOL(schedule_timeout_uninterruptible); @@ -1516,16 +1448,18 @@ static void time_interpolator_update(long delta_nsec) if (!time_interpolator) return; - /* The interpolator compensates for late ticks by accumulating - * the late time in time_interpolator->offset. A tick earlier than - * expected will lead to a reset of the offset and a corresponding - * jump of the clock forward. Again this only works if the - * interpolator clock is running slightly slower than the regular clock - * and the tuning logic insures that. - */ + /* + * The interpolator compensates for late ticks by accumulating the late + * time in time_interpolator->offset. A tick earlier than expected will + * lead to a reset of the offset and a corresponding jump of the clock + * forward. Again this only works if the interpolator clock is running + * slightly slower than the regular clock and the tuning logic insures + * that. + */ counter = time_interpolator_get_counter(1); - offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator); + offset = time_interpolator->offset + + GET_TI_NSECS(counter, time_interpolator); if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) time_interpolator->offset = offset - delta_nsec; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 91bacb13a7e..7cee222231b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -12,6 +12,8 @@ * Andrew Morton <andrewm@uow.edu.au> * Kai Petzke <wpp@marie.physik.tu-berlin.de> * Theodore Ts'o <tytso@mit.edu> + * + * Made to use alloc_percpu by Christoph Lameter <clameter@sgi.com>. */ #include <linux/module.h> @@ -57,7 +59,7 @@ struct cpu_workqueue_struct { * per-CPU workqueues: */ struct workqueue_struct { - struct cpu_workqueue_struct cpu_wq[NR_CPUS]; + struct cpu_workqueue_struct *cpu_wq; const char *name; struct list_head list; /* Empty if single thread */ }; @@ -102,7 +104,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work) if (unlikely(is_single_threaded(wq))) cpu = 0; BUG_ON(!list_empty(&work->entry)); - __queue_work(wq->cpu_wq + cpu, work); + __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); ret = 1; } put_cpu(); @@ -118,7 +120,7 @@ static void delayed_work_timer_fn(unsigned long __data) if (unlikely(is_single_threaded(wq))) cpu = 0; - __queue_work(wq->cpu_wq + cpu, work); + __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); } int fastcall queue_delayed_work(struct workqueue_struct *wq, @@ -265,13 +267,13 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) if (is_single_threaded(wq)) { /* Always use cpu 0's area. */ - flush_cpu_workqueue(wq->cpu_wq + 0); + flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, 0)); } else { int cpu; lock_cpu_hotplug(); for_each_online_cpu(cpu) - flush_cpu_workqueue(wq->cpu_wq + cpu); + flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); unlock_cpu_hotplug(); } } @@ -279,7 +281,7 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq, int cpu) { - struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu; + struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu); struct task_struct *p; spin_lock_init(&cwq->lock); @@ -312,6 +314,7 @@ struct workqueue_struct *__create_workqueue(const char *name, if (!wq) return NULL; + wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct); wq->name = name; /* We don't need the distraction of CPUs appearing and vanishing. */ lock_cpu_hotplug(); @@ -353,7 +356,7 @@ static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu) unsigned long flags; struct task_struct *p; - cwq = wq->cpu_wq + cpu; + cwq = per_cpu_ptr(wq->cpu_wq, cpu); spin_lock_irqsave(&cwq->lock, flags); p = cwq->thread; cwq->thread = NULL; @@ -380,6 +383,7 @@ void destroy_workqueue(struct workqueue_struct *wq) spin_unlock(&workqueue_lock); } unlock_cpu_hotplug(); + free_percpu(wq->cpu_wq); kfree(wq); } @@ -458,7 +462,7 @@ int current_is_keventd(void) BUG_ON(!keventd_wq); - cwq = keventd_wq->cpu_wq + cpu; + cwq = per_cpu_ptr(keventd_wq->cpu_wq, cpu); if (current == cwq->thread) ret = 1; @@ -470,7 +474,7 @@ int current_is_keventd(void) /* Take the work from this (downed) CPU. */ static void take_over_work(struct workqueue_struct *wq, unsigned int cpu) { - struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu; + struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu); LIST_HEAD(list); struct work_struct *work; @@ -481,7 +485,7 @@ static void take_over_work(struct workqueue_struct *wq, unsigned int cpu) printk("Taking work for %s\n", wq->name); work = list_entry(list.next,struct work_struct,entry); list_del(&work->entry); - __queue_work(wq->cpu_wq + smp_processor_id(), work); + __queue_work(per_cpu_ptr(wq->cpu_wq, smp_processor_id()), work); } spin_unlock_irq(&cwq->lock); } @@ -508,15 +512,18 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, case CPU_ONLINE: /* Kick off worker threads. */ list_for_each_entry(wq, &workqueues, list) { - kthread_bind(wq->cpu_wq[hotcpu].thread, hotcpu); - wake_up_process(wq->cpu_wq[hotcpu].thread); + struct cpu_workqueue_struct *cwq; + + cwq = per_cpu_ptr(wq->cpu_wq, hotcpu); + kthread_bind(cwq->thread, hotcpu); + wake_up_process(cwq->thread); } break; case CPU_UP_CANCELED: list_for_each_entry(wq, &workqueues, list) { /* Unbind so it can run. */ - kthread_bind(wq->cpu_wq[hotcpu].thread, + kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread, smp_processor_id()); cleanup_workqueue_thread(wq, hotcpu); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 016e89a44ac..156822e3cc7 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -128,7 +128,7 @@ config DEBUG_HIGHMEM config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED depends on BUG - depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64) || FRV + depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV default !EMBEDDED help Say Y here to make BUG() panics output the file name and line number @@ -168,13 +168,34 @@ config DEBUG_FS If unsure, say N. +config DEBUG_VM + bool "Debug VM" + depends on DEBUG_KERNEL + help + Enable this to debug the virtual-memory system. + + If unsure, say N. + config FRAME_POINTER bool "Compile the kernel with frame pointers" depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML) default y if DEBUG_INFO && UML help If you say Y here the resulting kernel image will be slightly larger - and slower, but it might give very useful debugging information - on some architectures or you use external debuggers. + and slower, but it might give very useful debugging information on + some architectures or if you use external debuggers. If you don't debug the kernel, you can say N. +config RCU_TORTURE_TEST + tristate "torture tests for RCU" + depends on DEBUG_KERNEL + default n + help + This option provides a kernel module that runs torture tests + on the RCU infrastructure. The kernel module may be built + after the fact on the running kernel to be tested, if desired. + + Say Y here if you want RCU torture tests to start automatically + at boot time (you probably don't). + Say M if you want the RCU torture tests to build as a module. + Say N if you are unsure. diff --git a/lib/bitmap.c b/lib/bitmap.c index fb9371fdd44..23d3b1147fe 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -511,6 +511,172 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits) } EXPORT_SYMBOL(bitmap_parselist); +/* + * bitmap_pos_to_ord(buf, pos, bits) + * @buf: pointer to a bitmap + * @pos: a bit position in @buf (0 <= @pos < @bits) + * @bits: number of valid bit positions in @buf + * + * Map the bit at position @pos in @buf (of length @bits) to the + * ordinal of which set bit it is. If it is not set or if @pos + * is not a valid bit position, map to zero (0). + * + * If for example, just bits 4 through 7 are set in @buf, then @pos + * values 4 through 7 will get mapped to 0 through 3, respectively, + * and other @pos values will get mapped to 0. When @pos value 7 + * gets mapped to (returns) @ord value 3 in this example, that means + * that bit 7 is the 3rd (starting with 0th) set bit in @buf. + * + * The bit positions 0 through @bits are valid positions in @buf. + */ +static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) +{ + int ord = 0; + + if (pos >= 0 && pos < bits) { + int i; + + for (i = find_first_bit(buf, bits); + i < pos; + i = find_next_bit(buf, bits, i + 1)) + ord++; + if (i > pos) + ord = 0; + } + return ord; +} + +/** + * bitmap_ord_to_pos(buf, ord, bits) + * @buf: pointer to bitmap + * @ord: ordinal bit position (n-th set bit, n >= 0) + * @bits: number of valid bit positions in @buf + * + * Map the ordinal offset of bit @ord in @buf to its position in @buf. + * If @ord is not the ordinal offset of a set bit in @buf, map to zero (0). + * + * If for example, just bits 4 through 7 are set in @buf, then @ord + * values 0 through 3 will get mapped to 4 through 7, respectively, + * and all other @ord valuds will get mapped to 0. When @ord value 3 + * gets mapped to (returns) @pos value 7 in this example, that means + * that the 3rd set bit (starting with 0th) is at position 7 in @buf. + * + * The bit positions 0 through @bits are valid positions in @buf. + */ +static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits) +{ + int pos = 0; + + if (ord >= 0 && ord < bits) { + int i; + + for (i = find_first_bit(buf, bits); + i < bits && ord > 0; + i = find_next_bit(buf, bits, i + 1)) + ord--; + if (i < bits && ord == 0) + pos = i; + } + + return pos; +} + +/** + * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap + * @src: subset to be remapped + * @dst: remapped result + * @old: defines domain of map + * @new: defines range of map + * @bits: number of bits in each of these bitmaps + * + * Let @old and @new define a mapping of bit positions, such that + * whatever position is held by the n-th set bit in @old is mapped + * to the n-th set bit in @new. In the more general case, allowing + * for the possibility that the weight 'w' of @new is less than the + * weight of @old, map the position of the n-th set bit in @old to + * the position of the m-th set bit in @new, where m == n % w. + * + * If either of the @old and @new bitmaps are empty, or if@src and @dst + * point to the same location, then this routine does nothing. + * + * The positions of unset bits in @old are mapped to the position of + * the first set bit in @new. + * + * Apply the above specified mapping to @src, placing the result in + * @dst, clearing any bits previously set in @dst. + * + * The resulting value of @dst will have either the same weight as + * @src, or less weight in the general case that the mapping wasn't + * injective due to the weight of @new being less than that of @old. + * The resulting value of @dst will never have greater weight than + * that of @src, except perhaps in the case that one of the above + * conditions was not met and this routine just returned. + * + * For example, lets say that @old has bits 4 through 7 set, and + * @new has bits 12 through 15 set. This defines the mapping of bit + * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other + * bit positions to 12 (the first set bit in @new. So if say @src + * comes into this routine with bits 1, 5 and 7 set, then @dst should + * leave with bits 12, 13 and 15 set. + */ +void bitmap_remap(unsigned long *dst, const unsigned long *src, + const unsigned long *old, const unsigned long *new, + int bits) +{ + int s; + + if (bitmap_weight(old, bits) == 0) + return; + if (bitmap_weight(new, bits) == 0) + return; + if (dst == src) /* following doesn't handle inplace remaps */ + return; + + bitmap_zero(dst, bits); + for (s = find_first_bit(src, bits); + s < bits; + s = find_next_bit(src, bits, s + 1)) { + int x = bitmap_pos_to_ord(old, s, bits); + int y = bitmap_ord_to_pos(new, x, bits); + set_bit(y, dst); + } +} +EXPORT_SYMBOL(bitmap_remap); + +/** + * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit + * @oldbit - bit position to be mapped + * @old: defines domain of map + * @new: defines range of map + * @bits: number of bits in each of these bitmaps + * + * Let @old and @new define a mapping of bit positions, such that + * whatever position is held by the n-th set bit in @old is mapped + * to the n-th set bit in @new. In the more general case, allowing + * for the possibility that the weight 'w' of @new is less than the + * weight of @old, map the position of the n-th set bit in @old to + * the position of the m-th set bit in @new, where m == n % w. + * + * The positions of unset bits in @old are mapped to the position of + * the first set bit in @new. + * + * Apply the above specified mapping to bit position @oldbit, returning + * the new bit position. + * + * For example, lets say that @old has bits 4 through 7 set, and + * @new has bits 12 through 15 set. This defines the mapping of bit + * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other + * bit positions to 12 (the first set bit in @new. So if say @oldbit + * is 5, then this routine returns 13. + */ +int bitmap_bitremap(int oldbit, const unsigned long *old, + const unsigned long *new, int bits) +{ + int x = bitmap_pos_to_ord(old, oldbit, bits); + return bitmap_ord_to_pos(new, x, bits); +} +EXPORT_SYMBOL(bitmap_bitremap); + /** * bitmap_find_free_region - find a contiguous aligned mem region * @bitmap: an array of unsigned longs corresponding to the bitmap diff --git a/lib/extable.c b/lib/extable.c index 3f677a8f0c3..18df57c029d 100644 --- a/lib/extable.c +++ b/lib/extable.c @@ -16,9 +16,6 @@ #include <linux/sort.h> #include <asm/uaccess.h> -extern struct exception_table_entry __start___ex_table[]; -extern struct exception_table_entry __stop___ex_table[]; - #ifndef ARCH_HAS_SORT_EXTABLE /* * The exception table needs to be sorted so that the binary diff --git a/lib/idr.c b/lib/idr.c index 6414b2fb482..d226259c3c2 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -6,20 +6,20 @@ * Modified by George Anzinger to reuse immediately and to use * find bit instructions. Also removed _irq on spinlocks. * - * Small id to pointer translation service. + * Small id to pointer translation service. * - * It uses a radix tree like structure as a sparse array indexed + * It uses a radix tree like structure as a sparse array indexed * by the id to obtain the pointer. The bitmap makes allocating - * a new id quick. + * a new id quick. * * You call it to allocate an id (an int) an associate with that id a * pointer or what ever, we treat it as a (void *). You can pass this * id to a user for him to pass back at a later time. You then pass * that id to this code and it returns your pointer. - * You can release ids at any time. When all ids are released, most of + * You can release ids at any time. When all ids are released, most of * the memory is returned (we keep IDR_FREE_MAX) in a local pool so we - * don't need to go to the memory "store" during an id allocate, just + * don't need to go to the memory "store" during an id allocate, just * so you don't need to be too concerned about locking and conflicts * with the slab allocator. */ @@ -77,7 +77,7 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask) while (idp->id_free_cnt < IDR_FREE_MAX) { struct idr_layer *new; new = kmem_cache_alloc(idr_layer_cache, gfp_mask); - if(new == NULL) + if (new == NULL) return (0); free_layer(idp, new); } @@ -107,7 +107,7 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) if (m == IDR_SIZE) { /* no space available go back to previous layer. */ l++; - id = (id | ((1 << (IDR_BITS*l))-1)) + 1; + id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; if (!(p = pa[l])) { *starting_id = id; return -2; @@ -161,7 +161,7 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) { struct idr_layer *p, *new; int layers, v, id; - + id = starting_id; build_up: p = idp->top; @@ -225,6 +225,7 @@ build_up: int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id) { int rv; + rv = idr_get_new_above_int(idp, ptr, starting_id); /* * This is a cheap hack until the IDR code can be fixed to @@ -259,6 +260,7 @@ EXPORT_SYMBOL(idr_get_new_above); int idr_get_new(struct idr *idp, void *ptr, int *id) { int rv; + rv = idr_get_new_above_int(idp, ptr, 0); /* * This is a cheap hack until the IDR code can be fixed to @@ -306,11 +308,10 @@ static void sub_remove(struct idr *idp, int shift, int id) free_layer(idp, **paa); **paa-- = NULL; } - if ( ! *paa ) + if (!*paa) idp->layers = 0; - } else { + } else idr_remove_warning(id); - } } /** @@ -326,9 +327,8 @@ void idr_remove(struct idr *idp, int id) id &= MAX_ID_MASK; sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); - if ( idp->top && idp->top->count == 1 && - (idp->layers > 1) && - idp->top->ary[0]){ // We can drop a layer + if (idp->top && idp->top->count == 1 && (idp->layers > 1) && + idp->top->ary[0]) { // We can drop a layer p = idp->top->ary[0]; idp->top->bitmap = idp->top->count = 0; @@ -337,7 +337,6 @@ void idr_remove(struct idr *idp, int id) --idp->layers; } while (idp->id_free_cnt >= IDR_FREE_MAX) { - p = alloc_layer(idp); kmem_cache_free(idr_layer_cache, p); return; @@ -391,8 +390,8 @@ void *idr_find(struct idr *idp, int id) } EXPORT_SYMBOL(idr_find); -static void idr_cache_ctor(void * idr_layer, - kmem_cache_t *idr_layer_cache, unsigned long flags) +static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache, + unsigned long flags) { memset(idr_layer, 0, sizeof(struct idr_layer)); } @@ -400,7 +399,7 @@ static void idr_cache_ctor(void * idr_layer, static int init_id_cache(void) { if (!idr_layer_cache) - idr_layer_cache = kmem_cache_create("idr_layer_cache", + idr_layer_cache = kmem_cache_create("idr_layer_cache", sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL); return 0; } diff --git a/lib/kobject.c b/lib/kobject.c index 253d3004ace..a181abed89f 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -14,6 +14,7 @@ #include <linux/string.h> #include <linux/module.h> #include <linux/stat.h> +#include <linux/slab.h> /** * populate_dir - populate directory with attributes. diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 42c08ef828c..eddc9b3d387 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -5,6 +5,7 @@ */ #include <linux/module.h> #include <linux/kallsyms.h> +#include <linux/sched.h> unsigned int debug_smp_processor_id(void) { diff --git a/lib/sort.c b/lib/sort.c index ddc4d35df28..5f3b51ffa1d 100644 --- a/lib/sort.c +++ b/lib/sort.c @@ -7,6 +7,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/sort.h> +#include <linux/slab.h> static void u32_swap(void *a, void *b, int size) { diff --git a/lib/string.c b/lib/string.c index d886ef157c1..037a48acedb 100644 --- a/lib/string.c +++ b/lib/string.c @@ -36,11 +36,13 @@ int strnicmp(const char *s1, const char *s2, size_t len) /* Yes, Virginia, it had better be unsigned */ unsigned char c1, c2; - c1 = 0; c2 = 0; + c1 = c2 = 0; if (len) { do { - c1 = *s1; c2 = *s2; - s1++; s2++; + c1 = *s1; + c2 = *s2; + s1++; + s2++; if (!c1) break; if (!c2) @@ -55,7 +57,6 @@ int strnicmp(const char *s1, const char *s2, size_t len) } return (int)c1 - (int)c2; } - EXPORT_SYMBOL(strnicmp); #endif @@ -66,7 +67,7 @@ EXPORT_SYMBOL(strnicmp); * @src: Where to copy the string from */ #undef strcpy -char * strcpy(char * dest,const char *src) +char *strcpy(char *dest, const char *src) { char *tmp = dest; @@ -91,12 +92,13 @@ EXPORT_SYMBOL(strcpy); * count, the remainder of @dest will be padded with %NUL. * */ -char * strncpy(char * dest,const char *src,size_t count) +char *strncpy(char *dest, const char *src, size_t count) { char *tmp = dest; while (count) { - if ((*tmp = *src) != 0) src++; + if ((*tmp = *src) != 0) + src++; tmp++; count--; } @@ -122,7 +124,7 @@ size_t strlcpy(char *dest, const char *src, size_t size) size_t ret = strlen(src); if (size) { - size_t len = (ret >= size) ? size-1 : ret; + size_t len = (ret >= size) ? size - 1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } @@ -138,7 +140,7 @@ EXPORT_SYMBOL(strlcpy); * @src: The string to append to it */ #undef strcat -char * strcat(char * dest, const char * src) +char *strcat(char *dest, const char *src) { char *tmp = dest; @@ -146,7 +148,6 @@ char * strcat(char * dest, const char * src) dest++; while ((*dest++ = *src++) != '\0') ; - return tmp; } EXPORT_SYMBOL(strcat); @@ -162,7 +163,7 @@ EXPORT_SYMBOL(strcat); * Note that in contrast to strncpy, strncat ensures the result is * terminated. */ -char * strncat(char *dest, const char *src, size_t count) +char *strncat(char *dest, const char *src, size_t count) { char *tmp = dest; @@ -176,7 +177,6 @@ char * strncat(char *dest, const char *src, size_t count) } } } - return tmp; } EXPORT_SYMBOL(strncat); @@ -216,15 +216,14 @@ EXPORT_SYMBOL(strlcat); * @ct: Another string */ #undef strcmp -int strcmp(const char * cs,const char * ct) +int strcmp(const char *cs, const char *ct) { - register signed char __res; + signed char __res; while (1) { if ((__res = *cs - *ct++) != 0 || !*cs++) break; } - return __res; } EXPORT_SYMBOL(strcmp); @@ -237,16 +236,15 @@ EXPORT_SYMBOL(strcmp); * @ct: Another string * @count: The maximum number of bytes to compare */ -int strncmp(const char * cs,const char * ct,size_t count) +int strncmp(const char *cs, const char *ct, size_t count) { - register signed char __res = 0; + signed char __res = 0; while (count) { if ((__res = *cs - *ct++) != 0 || !*cs++) break; count--; } - return __res; } EXPORT_SYMBOL(strncmp); @@ -258,12 +256,12 @@ EXPORT_SYMBOL(strncmp); * @s: The string to be searched * @c: The character to search for */ -char * strchr(const char * s, int c) +char *strchr(const char *s, int c) { - for(; *s != (char) c; ++s) + for (; *s != (char)c; ++s) if (*s == '\0') return NULL; - return (char *) s; + return (char *)s; } EXPORT_SYMBOL(strchr); #endif @@ -274,7 +272,7 @@ EXPORT_SYMBOL(strchr); * @s: The string to be searched * @c: The character to search for */ -char * strrchr(const char * s, int c) +char *strrchr(const char *s, int c) { const char *p = s + strlen(s); do { @@ -296,8 +294,8 @@ EXPORT_SYMBOL(strrchr); char *strnchr(const char *s, size_t count, int c) { for (; count-- && *s != '\0'; ++s) - if (*s == (char) c) - return (char *) s; + if (*s == (char)c) + return (char *)s; return NULL; } EXPORT_SYMBOL(strnchr); @@ -308,7 +306,7 @@ EXPORT_SYMBOL(strnchr); * strlen - Find the length of a string * @s: The string to be sized */ -size_t strlen(const char * s) +size_t strlen(const char *s) { const char *sc; @@ -325,7 +323,7 @@ EXPORT_SYMBOL(strlen); * @s: The string to be sized * @count: The maximum number of bytes to search */ -size_t strnlen(const char * s, size_t count) +size_t strnlen(const char *s, size_t count) { const char *sc; @@ -358,7 +356,6 @@ size_t strspn(const char *s, const char *accept) return count; ++count; } - return count; } @@ -384,9 +381,8 @@ size_t strcspn(const char *s, const char *reject) } ++count; } - return count; -} +} EXPORT_SYMBOL(strcspn); #ifndef __HAVE_ARCH_STRPBRK @@ -395,14 +391,14 @@ EXPORT_SYMBOL(strcspn); * @cs: The string to be searched * @ct: The characters to search for */ -char * strpbrk(const char * cs,const char * ct) +char *strpbrk(const char *cs, const char *ct) { - const char *sc1,*sc2; + const char *sc1, *sc2; - for( sc1 = cs; *sc1 != '\0'; ++sc1) { - for( sc2 = ct; *sc2 != '\0'; ++sc2) { + for (sc1 = cs; *sc1 != '\0'; ++sc1) { + for (sc2 = ct; *sc2 != '\0'; ++sc2) { if (*sc1 == *sc2) - return (char *) sc1; + return (char *)sc1; } } return NULL; @@ -422,9 +418,10 @@ EXPORT_SYMBOL(strpbrk); * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. * Same semantics, slimmer shape. ;) */ -char * strsep(char **s, const char *ct) +char *strsep(char **s, const char *ct) { - char *sbegin = *s, *end; + char *sbegin = *s; + char *end; if (sbegin == NULL) return NULL; @@ -433,10 +430,8 @@ char * strsep(char **s, const char *ct) if (end) *end++ = '\0'; *s = end; - return sbegin; } - EXPORT_SYMBOL(strsep); #endif @@ -449,13 +444,12 @@ EXPORT_SYMBOL(strsep); * * Do not use memset() to access IO space, use memset_io() instead. */ -void * memset(void * s,int c,size_t count) +void *memset(void *s, int c, size_t count) { - char *xs = (char *) s; + char *xs = s; while (count--) *xs++ = c; - return s; } EXPORT_SYMBOL(memset); @@ -471,13 +465,13 @@ EXPORT_SYMBOL(memset); * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ -void * memcpy(void * dest,const void *src,size_t count) +void *memcpy(void *dest, const void *src, size_t count) { - char *tmp = (char *) dest, *s = (char *) src; + char *tmp = dest; + char *s = src; while (count--) *tmp++ = *s++; - return dest; } EXPORT_SYMBOL(memcpy); @@ -492,23 +486,24 @@ EXPORT_SYMBOL(memcpy); * * Unlike memcpy(), memmove() copes with overlapping areas. */ -void * memmove(void * dest,const void *src,size_t count) +void *memmove(void *dest, const void *src, size_t count) { - char *tmp, *s; + char *tmp; + const char *s; if (dest <= src) { - tmp = (char *) dest; - s = (char *) src; + tmp = dest; + s = src; while (count--) *tmp++ = *s++; - } - else { - tmp = (char *) dest + count; - s = (char *) src + count; + } else { + tmp = dest; + tmp += count; + s = src; + s += count; while (count--) *--tmp = *--s; - } - + } return dest; } EXPORT_SYMBOL(memmove); @@ -522,12 +517,12 @@ EXPORT_SYMBOL(memmove); * @count: The size of the area. */ #undef memcmp -int memcmp(const void * cs,const void * ct,size_t count) +int memcmp(const void *cs, const void *ct, size_t count) { const unsigned char *su1, *su2; int res = 0; - for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) if ((res = *su1 - *su2) != 0) break; return res; @@ -545,17 +540,17 @@ EXPORT_SYMBOL(memcmp); * returns the address of the first occurrence of @c, or 1 byte past * the area if @c is not found */ -void * memscan(void * addr, int c, size_t size) +void *memscan(void *addr, int c, size_t size) { - unsigned char * p = (unsigned char *) addr; + unsigned char *p = addr; while (size) { if (*p == c) - return (void *) p; + return (void *)p; p++; size--; } - return (void *) p; + return (void *)p; } EXPORT_SYMBOL(memscan); #endif @@ -566,18 +561,18 @@ EXPORT_SYMBOL(memscan); * @s1: The string to be searched * @s2: The string to search for */ -char * strstr(const char * s1,const char * s2) +char *strstr(const char *s1, const char *s2) { int l1, l2; l2 = strlen(s2); if (!l2) - return (char *) s1; + return (char *)s1; l1 = strlen(s1); while (l1 >= l2) { l1--; - if (!memcmp(s1,s2,l2)) - return (char *) s1; + if (!memcmp(s1, s2, l2)) + return (char *)s1; s1++; } return NULL; @@ -600,7 +595,7 @@ void *memchr(const void *s, int c, size_t n) const unsigned char *p = s; while (n-- != 0) { if ((unsigned char)c == *p++) { - return (void *)(p-1); + return (void *)(p - 1); } } return NULL; diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e4e9031dd9c..b07db5ca3f6 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -23,6 +23,7 @@ #include <linux/ctype.h> #include <linux/kernel.h> +#include <asm/page.h> /* for PAGE_SIZE */ #include <asm/div64.h> /** diff --git a/mm/filemap.c b/mm/filemap.c index 768687f1d46..5d6e4c2000d 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1030,8 +1030,8 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, desc.error = 0; do_generic_file_read(filp,ppos,&desc,file_read_actor); retval += desc.written; - if (!retval) { - retval = desc.error; + if (desc.error) { + retval = retval ?: desc.error; break; } } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 2076b1542b8..5abc57c2b8b 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -457,6 +457,7 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask, struct vm_area_struct *vma = NULL; struct mempolicy *pol = current->mempolicy; + cpuset_update_current_mems_allowed(); if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR)) return -EINVAL; if (flags & MPOL_F_ADDR) { @@ -1206,3 +1207,66 @@ void numa_default_policy(void) { do_set_mempolicy(MPOL_DEFAULT, NULL); } + +/* Migrate a policy to a different set of nodes */ +static void rebind_policy(struct mempolicy *pol, const nodemask_t *old, + const nodemask_t *new) +{ + nodemask_t tmp; + + if (!pol) + return; + + switch (pol->policy) { + case MPOL_DEFAULT: + break; + case MPOL_INTERLEAVE: + nodes_remap(tmp, pol->v.nodes, *old, *new); + pol->v.nodes = tmp; + current->il_next = node_remap(current->il_next, *old, *new); + break; + case MPOL_PREFERRED: + pol->v.preferred_node = node_remap(pol->v.preferred_node, + *old, *new); + break; + case MPOL_BIND: { + nodemask_t nodes; + struct zone **z; + struct zonelist *zonelist; + + nodes_clear(nodes); + for (z = pol->v.zonelist->zones; *z; z++) + node_set((*z)->zone_pgdat->node_id, nodes); + nodes_remap(tmp, nodes, *old, *new); + nodes = tmp; + + zonelist = bind_zonelist(&nodes); + + /* If no mem, then zonelist is NULL and we keep old zonelist. + * If that old zonelist has no remaining mems_allowed nodes, + * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. + */ + + if (zonelist) { + /* Good - got mem - substitute new zonelist */ + kfree(pol->v.zonelist); + pol->v.zonelist = zonelist; + } + break; + } + default: + BUG(); + break; + } +} + +/* + * Someone moved this task to different nodes. Fixup mempolicies. + * + * TODO - fixup current->mm->vma and shmfs/tmpfs/hugetlbfs policies as well, + * once we have a cpuset mechanism to mark which cpuset subtree is migrating. + */ +void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new) +{ + rebind_policy(current->mempolicy, old, new); +} diff --git a/mm/mmap.c b/mm/mmap.c index 5ecc2cf3e1d..320dda1778c 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1840,7 +1840,7 @@ asmlinkage long sys_munmap(unsigned long addr, size_t len) static inline void verify_mm_writelocked(struct mm_struct *mm) { -#ifdef CONFIG_DEBUG_KERNEL +#ifdef CONFIG_DEBUG_VM if (unlikely(down_read_trylock(&mm->mmap_sem))) { WARN_ON(1); up_read(&mm->mmap_sem); diff --git a/mm/pdflush.c b/mm/pdflush.c index d6781951267..52822c98c48 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c @@ -20,6 +20,7 @@ #include <linux/fs.h> // Needed by writeback.h #include <linux/writeback.h> // Prototypes pdflush_operation() #include <linux/kthread.h> +#include <linux/cpuset.h> /* @@ -170,12 +171,24 @@ static int __pdflush(struct pdflush_work *my_work) static int pdflush(void *dummy) { struct pdflush_work my_work; + cpumask_t cpus_allowed; /* * pdflush can spend a lot of time doing encryption via dm-crypt. We * don't want to do that at keventd's priority. */ set_user_nice(current, 0); + + /* + * Some configs put our parent kthread in a limited cpuset, + * which kthread() overrides, forcing cpus_allowed == CPU_MASK_ALL. + * Our needs are more modest - cut back to our cpusets cpus_allowed. + * This is needed as pdflush's are dynamically created and destroyed. + * The boottime pdflush's are easily placed w/o these 2 lines. + */ + cpus_allowed = cpuset_cpus_allowed(current); + set_cpus_allowed(current, cpus_allowed); + return __pdflush(&my_work); } diff --git a/mm/swap.c b/mm/swap.c index b89512877ec..96387e20184 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -270,7 +270,6 @@ void __pagevec_release_nonlru(struct pagevec *pvec) struct pagevec pages_to_free; pagevec_init(&pages_to_free, pvec->cold); - pages_to_free.cold = pvec->cold; for (i = 0; i < pagevec_count(pvec); i++) { struct page *page = pvec->pages[i]; diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index c13a2161bca..b58abcf44ed 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -31,11 +31,14 @@ static struct vfsmount *shm_mnt; static int __init init_tmpfs(void) { - register_filesystem(&tmpfs_fs_type); + BUG_ON(register_filesystem(&tmpfs_fs_type) != 0); + #ifdef CONFIG_TMPFS devfs_mk_dir("shm"); #endif shm_mnt = kern_mount(&tmpfs_fs_type); + BUG_ON(IS_ERR(shm_mnt)); + return 0; } module_init(init_tmpfs) diff --git a/mm/truncate.c b/mm/truncate.c index 60c8764bfac..29c18f68dc3 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -13,18 +13,9 @@ #include <linux/pagemap.h> #include <linux/pagevec.h> #include <linux/buffer_head.h> /* grr. try_to_release_page, - block_invalidatepage */ + do_invalidatepage */ -static int do_invalidatepage(struct page *page, unsigned long offset) -{ - int (*invalidatepage)(struct page *, unsigned long); - invalidatepage = page->mapping->a_ops->invalidatepage; - if (invalidatepage == NULL) - invalidatepage = block_invalidatepage; - return (*invalidatepage)(page, offset); -} - static inline void truncate_partial_page(struct page *page, unsigned partial) { memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index f5909a4c3fc..e19c2a52d00 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c @@ -48,7 +48,7 @@ static int checkentry(const char *tablename, const struct ipt_ip *ip, unsigned int hook_mask) { if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) { - printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n.", + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n", matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info))); return 0; } diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 2fcb244a9e1..0dd96919de3 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -116,6 +116,15 @@ endif clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ .tmp_gtkcheck zconf.tab.c zconf.tab.h lex.zconf.c +# Needed for systems without gettext +KBUILD_HAVE_NLS := $(shell \ + if echo "\#include <libint.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \ + then echo yes ; \ + else echo no ; fi) +ifeq ($(KBUILD_HAVE_NLS),no) +HOSTCFLAGS += -DKBUILD_NO_NLS +endif + # generated files seem to need this to find local include files HOSTCFLAGS_lex.zconf.o := -I$(src) HOSTCFLAGS_zconf.tab.o := -I$(src) diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index c3d25786a64..5fba1feff2a 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -8,7 +8,13 @@ #include "expr.h" -#include <libintl.h> +#ifndef KBUILD_NO_NLS +# include <libintl.h> +#else +# define gettext(Msgid) ((const char *) (Msgid)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +#endif #ifdef __cplusplus extern "C" { diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 457bec29511..d1ad40531ee 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -219,6 +219,7 @@ save_config_help[] = N_( search_help[] = N_( "\n" "Search for CONFIG_ symbols and display their relations.\n" + "Regular expressions are allowed.\n" "Example: search for \"^FOO\"\n" "Result:\n" "-----------------------------------------------------------------\n" @@ -531,7 +532,7 @@ again: cprint("--title"); cprint(_("Search Configuration Parameter")); cprint("--inputbox"); - cprint(_("Enter Keyword")); + cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)")); cprint("10"); cprint("75"); cprint(""); diff --git a/security/dummy.c b/security/dummy.c index 3d34f3de7e8..3ca5f2b828a 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -377,7 +377,7 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name) return 0; } -static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) +static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) { return -EOPNOTSUPP; } @@ -803,6 +803,23 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz return -EINVAL; } +#ifdef CONFIG_KEYS +static inline int dummy_key_alloc(struct key *key) +{ + return 0; +} + +static inline void dummy_key_free(struct key *key) +{ +} + +static inline int dummy_key_permission(key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm) +{ + return 0; +} +#endif /* CONFIG_KEYS */ struct security_operations dummy_security_ops; @@ -954,5 +971,11 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, sk_alloc_security); set_to_dummy_if_null(ops, sk_free_security); #endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_KEYS + set_to_dummy_if_null(ops, key_alloc); + set_to_dummy_if_null(ops, key_free); + set_to_dummy_if_null(ops, key_permission); +#endif /* CONFIG_KEYS */ + } diff --git a/security/keys/key.c b/security/keys/key.c index 2182be9e930..ccde17aff61 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -1,6 +1,6 @@ /* key.c: basic authentication token and access key management * - * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/security.h> #include <linux/workqueue.h> #include <linux/err.h> #include "internal.h" @@ -253,6 +254,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, struct key_user *user = NULL; struct key *key; size_t desclen, quotalen; + int ret; key = ERR_PTR(-EINVAL); if (!desc || !*desc) @@ -305,6 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->flags = 0; key->expiry = 0; key->payload.data = NULL; + key->security = NULL; if (!not_in_quota) key->flags |= 1 << KEY_FLAG_IN_QUOTA; @@ -315,16 +318,34 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->magic = KEY_DEBUG_MAGIC; #endif + /* let the security module know about the key */ + ret = security_key_alloc(key); + if (ret < 0) + goto security_error; + /* publish the key by giving it a serial number */ atomic_inc(&user->nkeys); key_alloc_serial(key); - error: +error: return key; - no_memory_3: +security_error: + kfree(key->description); + kmem_cache_free(key_jar, key); + if (!not_in_quota) { + spin_lock(&user->lock); + user->qnkeys--; + user->qnbytes -= quotalen; + spin_unlock(&user->lock); + } + key_user_put(user); + key = ERR_PTR(ret); + goto error; + +no_memory_3: kmem_cache_free(key_jar, key); - no_memory_2: +no_memory_2: if (!not_in_quota) { spin_lock(&user->lock); user->qnkeys--; @@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *type, const char *desc, spin_unlock(&user->lock); } key_user_put(user); - no_memory_1: +no_memory_1: key = ERR_PTR(-ENOMEM); goto error; - no_quota: +no_quota: spin_unlock(&user->lock); key_user_put(user); key = ERR_PTR(-EDQUOT); @@ -556,6 +577,8 @@ static void key_cleanup(void *data) key_check(key); + security_key_free(key); + /* deal with the user's key tracking and quota */ if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { spin_lock(&key->user->lock); @@ -700,8 +723,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref, int ret; /* need write permission on the key to update it */ - ret = -EACCES; - if (!key_permission(key_ref, KEY_WRITE)) + ret = key_permission(key_ref, KEY_WRITE); + if (ret < 0) goto error; ret = -EEXIST; @@ -711,7 +734,6 @@ static inline key_ref_t __key_update(key_ref_t key_ref, down_write(&key->sem); ret = key->type->update(key, payload, plen); - if (ret == 0) /* updating a negative key instantiates it */ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); @@ -768,9 +790,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* if we're going to allocate a new key, we're going to have * to modify the keyring */ - key_ref = ERR_PTR(-EACCES); - if (!key_permission(keyring_ref, KEY_WRITE)) + ret = key_permission(keyring_ref, KEY_WRITE); + if (ret < 0) { + key_ref = ERR_PTR(ret); goto error_3; + } /* search for an existing key of the same type and description in the * destination keyring @@ -780,8 +804,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, goto found_matching_key; /* decide on the permissions we want */ - perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK; - perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; + perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; + perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; if (ktype->read) perm |= KEY_POS_READ | KEY_USR_READ; @@ -840,16 +864,16 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) key_check(key); /* the key must be writable */ - ret = -EACCES; - if (!key_permission(key_ref, KEY_WRITE)) + ret = key_permission(key_ref, KEY_WRITE); + if (ret < 0) goto error; /* attempt to update it if supported */ ret = -EOPNOTSUPP; if (key->type->update) { down_write(&key->sem); - ret = key->type->update(key, payload, plen); + ret = key->type->update(key, payload, plen); if (ret == 0) /* updating a negative key instantiates it */ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4c670ee6acf..b7a468fabdf 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -624,8 +624,8 @@ long keyctl_keyring_search(key_serial_t ringid, /* link the resulting key to the destination keyring if we can */ if (dest_ref) { - ret = -EACCES; - if (!key_permission(key_ref, KEY_LINK)) + ret = key_permission(key_ref, KEY_LINK); + if (ret < 0) goto error6; ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref)); @@ -676,8 +676,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) key = key_ref_to_ptr(key_ref); /* see if we can read it directly */ - if (key_permission(key_ref, KEY_READ)) + ret = key_permission(key_ref, KEY_READ); + if (ret == 0) goto can_read_key; + if (ret != -EACCES) + goto error; /* we can't; see if it's searchable from this process's keyrings * - we automatically take account of the fact that it may be @@ -726,7 +729,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) if (uid == (uid_t) -1 && gid == (gid_t) -1) goto error; - key_ref = lookup_user_key(NULL, id, 1, 1, 0); + key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); if (IS_ERR(key_ref)) { ret = PTR_ERR(key_ref); goto error; @@ -786,7 +789,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) goto error; - key_ref = lookup_user_key(NULL, id, 1, 1, 0); + key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); if (IS_ERR(key_ref)) { ret = PTR_ERR(key_ref); goto error; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 0639396dd44..e1cc4dd7901 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/security.h> #include <linux/seq_file.h> #include <linux/err.h> #include <asm/uaccess.h> @@ -309,7 +310,9 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, int ret; keyring = key_alloc(&key_type_keyring, description, - uid, gid, KEY_POS_ALL | KEY_USR_ALL, not_in_quota); + uid, gid, + (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, + not_in_quota); if (!IS_ERR(keyring)) { ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); @@ -359,9 +362,11 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, key_check(keyring); /* top keyring must have search permission to begin the search */ - key_ref = ERR_PTR(-EACCES); - if (!key_task_permission(keyring_ref, context, KEY_SEARCH)) + err = key_task_permission(keyring_ref, context, KEY_SEARCH); + if (err < 0) { + key_ref = ERR_PTR(err); goto error; + } key_ref = ERR_PTR(-ENOTDIR); if (keyring->type != &key_type_keyring) @@ -402,8 +407,8 @@ descend: continue; /* key must have search permissions */ - if (!key_task_permission(make_key_ref(key, possessed), - context, KEY_SEARCH)) + if (key_task_permission(make_key_ref(key, possessed), + context, KEY_SEARCH) < 0) continue; /* we set a different error code if we find a negative key */ @@ -430,7 +435,7 @@ ascend: continue; if (!key_task_permission(make_key_ref(key, possessed), - context, KEY_SEARCH)) + context, KEY_SEARCH) < 0) continue; /* stack the current position */ @@ -521,7 +526,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, (!key->type->match || key->type->match(key, description)) && key_permission(make_key_ref(key, possessed), - perm) && + perm) < 0 && !test_bit(KEY_FLAG_REVOKED, &key->flags) ) goto found; @@ -617,7 +622,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) continue; if (!key_permission(make_key_ref(keyring, 0), - KEY_SEARCH)) + KEY_SEARCH) < 0) continue; /* found a potential candidate, but we still need to diff --git a/security/keys/permission.c b/security/keys/permission.c index 03db073ba45..e7f579c0eaf 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c @@ -10,6 +10,7 @@ */ #include <linux/module.h> +#include <linux/security.h> #include "internal.h" /*****************************************************************************/ @@ -63,7 +64,11 @@ use_these_perms: kperm = kperm & perm & KEY_ALL; - return kperm == perm; + if (kperm != perm) + return -EACCES; + + /* let LSM be the final arbiter */ + return security_key_permission(key_ref, context, perm); } /* end key_task_permission() */ diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index d42d2158ce1..566b1cc0118 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -39,7 +39,7 @@ struct key root_user_keyring = { .type = &key_type_keyring, .user = &root_key_user, .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), - .perm = KEY_POS_ALL | KEY_USR_ALL, + .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, .flags = 1 << KEY_FLAG_INSTANTIATED, .description = "_uid.0", #ifdef KEY_DEBUGGING @@ -54,7 +54,7 @@ struct key root_session_keyring = { .type = &key_type_keyring, .user = &root_key_user, .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), - .perm = KEY_POS_ALL | KEY_USR_ALL, + .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, .flags = 1 << KEY_FLAG_INSTANTIATED, .description = "_uid_ses.0", #ifdef KEY_DEBUGGING @@ -666,9 +666,8 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, goto invalid_key; /* check the permissions */ - ret = -EACCES; - - if (!key_task_permission(key_ref, context, perm)) + ret = key_task_permission(key_ref, context, perm); + if (ret < 0) goto invalid_key; error: diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index e446acba73d..cbda3b2780a 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -15,18 +15,10 @@ #include <linux/slab.h> #include <linux/seq_file.h> #include <linux/err.h> +#include <keys/user-type.h> #include <asm/uaccess.h> #include "internal.h" -static int user_instantiate(struct key *key, const void *data, size_t datalen); -static int user_duplicate(struct key *key, const struct key *source); -static int user_update(struct key *key, const void *data, size_t datalen); -static int user_match(const struct key *key, const void *criterion); -static void user_destroy(struct key *key); -static void user_describe(const struct key *user, struct seq_file *m); -static long user_read(const struct key *key, - char __user *buffer, size_t buflen); - /* * user defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload @@ -42,19 +34,13 @@ struct key_type key_type_user = { .read = user_read, }; -struct user_key_payload { - struct rcu_head rcu; /* RCU destructor */ - unsigned short datalen; /* length of this data */ - char data[0]; /* actual data */ -}; - EXPORT_SYMBOL_GPL(key_type_user); /*****************************************************************************/ /* * instantiate a user defined key */ -static int user_instantiate(struct key *key, const void *data, size_t datalen) +int user_instantiate(struct key *key, const void *data, size_t datalen) { struct user_key_payload *upayload; int ret; @@ -78,18 +64,20 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen) rcu_assign_pointer(key->payload.data, upayload); ret = 0; - error: +error: return ret; } /* end user_instantiate() */ +EXPORT_SYMBOL_GPL(user_instantiate); + /*****************************************************************************/ /* * duplicate a user defined key * - both keys' semaphores are locked against further modification * - the new key cannot yet be accessed */ -static int user_duplicate(struct key *key, const struct key *source) +int user_duplicate(struct key *key, const struct key *source) { struct user_key_payload *upayload, *spayload; int ret; @@ -112,6 +100,8 @@ static int user_duplicate(struct key *key, const struct key *source) } /* end user_duplicate() */ +EXPORT_SYMBOL_GPL(user_duplicate); + /*****************************************************************************/ /* * dispose of the old data from an updated user defined key @@ -131,7 +121,7 @@ static void user_update_rcu_disposal(struct rcu_head *rcu) * update a user defined key * - the key's semaphore is write-locked */ -static int user_update(struct key *key, const void *data, size_t datalen) +int user_update(struct key *key, const void *data, size_t datalen) { struct user_key_payload *upayload, *zap; int ret; @@ -163,26 +153,30 @@ static int user_update(struct key *key, const void *data, size_t datalen) call_rcu(&zap->rcu, user_update_rcu_disposal); - error: +error: return ret; } /* end user_update() */ +EXPORT_SYMBOL_GPL(user_update); + /*****************************************************************************/ /* * match users on their name */ -static int user_match(const struct key *key, const void *description) +int user_match(const struct key *key, const void *description) { return strcmp(key->description, description) == 0; } /* end user_match() */ +EXPORT_SYMBOL_GPL(user_match); + /*****************************************************************************/ /* * dispose of the data dangling from the corpse of a user */ -static void user_destroy(struct key *key) +void user_destroy(struct key *key) { struct user_key_payload *upayload = key->payload.data; @@ -190,11 +184,13 @@ static void user_destroy(struct key *key) } /* end user_destroy() */ +EXPORT_SYMBOL_GPL(user_destroy); + /*****************************************************************************/ /* * describe the user key */ -static void user_describe(const struct key *key, struct seq_file *m) +void user_describe(const struct key *key, struct seq_file *m) { seq_puts(m, key->description); @@ -202,13 +198,14 @@ static void user_describe(const struct key *key, struct seq_file *m) } /* end user_describe() */ +EXPORT_SYMBOL_GPL(user_describe); + /*****************************************************************************/ /* * read the key data * - the key's semaphore is read-locked */ -static long user_read(const struct key *key, - char __user *buffer, size_t buflen) +long user_read(const struct key *key, char __user *buffer, size_t buflen) { struct user_key_payload *upayload; long ret; @@ -228,3 +225,5 @@ static long user_read(const struct key *key, return ret; } /* end user_read() */ + +EXPORT_SYMBOL_GPL(user_read); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 447a1e0f48c..45c41490d52 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -122,11 +122,10 @@ static int task_alloc_security(struct task_struct *task) { struct task_security_struct *tsec; - tsec = kmalloc(sizeof(struct task_security_struct), GFP_KERNEL); + tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); if (!tsec) return -ENOMEM; - memset(tsec, 0, sizeof(struct task_security_struct)); tsec->magic = SELINUX_MAGIC; tsec->task = task; tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED; @@ -151,11 +150,10 @@ static int inode_alloc_security(struct inode *inode) struct task_security_struct *tsec = current->security; struct inode_security_struct *isec; - isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL); + isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL); if (!isec) return -ENOMEM; - memset(isec, 0, sizeof(struct inode_security_struct)); init_MUTEX(&isec->sem); INIT_LIST_HEAD(&isec->list); isec->magic = SELINUX_MAGIC; @@ -193,11 +191,10 @@ static int file_alloc_security(struct file *file) struct task_security_struct *tsec = current->security; struct file_security_struct *fsec; - fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC); + fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC); if (!fsec) return -ENOMEM; - memset(fsec, 0, sizeof(struct file_security_struct)); fsec->magic = SELINUX_MAGIC; fsec->file = file; if (tsec && tsec->magic == SELINUX_MAGIC) { @@ -227,11 +224,10 @@ static int superblock_alloc_security(struct super_block *sb) { struct superblock_security_struct *sbsec; - sbsec = kmalloc(sizeof(struct superblock_security_struct), GFP_KERNEL); + sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL); if (!sbsec) return -ENOMEM; - memset(sbsec, 0, sizeof(struct superblock_security_struct)); init_MUTEX(&sbsec->sem); INIT_LIST_HEAD(&sbsec->list); INIT_LIST_HEAD(&sbsec->isec_head); @@ -269,11 +265,10 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) if (family != PF_UNIX) return 0; - ssec = kmalloc(sizeof(*ssec), priority); + ssec = kzalloc(sizeof(*ssec), priority); if (!ssec) return -ENOMEM; - memset(ssec, 0, sizeof(*ssec)); ssec->magic = SELINUX_MAGIC; ssec->sk = sk; ssec->peer_sid = SECINITSID_UNLABELED; @@ -1483,11 +1478,10 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) { struct bprm_security_struct *bsec; - bsec = kmalloc(sizeof(struct bprm_security_struct), GFP_KERNEL); + bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL); if (!bsec) return -ENOMEM; - memset(bsec, 0, sizeof *bsec); bsec->magic = SELINUX_MAGIC; bsec->bprm = bprm; bsec->sid = SECINITSID_UNLABELED; @@ -1615,7 +1609,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) if (tty) { file_list_lock(); - file = list_entry(tty->tty_files.next, typeof(*file), f_list); + file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); if (file) { /* Revalidate access to controlling tty. Use inode_has_perm on the tty inode directly rather @@ -2211,12 +2205,6 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name, static int selinux_inode_getxattr (struct dentry *dentry, char *name) { - struct inode *inode = dentry->d_inode; - struct superblock_security_struct *sbsec = inode->i_sb->s_security; - - if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) - return -EOPNOTSUPP; - return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); } @@ -2247,33 +2235,54 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) return -EACCES; } -static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) +/* + * Copy the in-core inode security context value to the user. If the + * getxattr() prior to this succeeded, check to see if we need to + * canonicalize the value to be finally returned to the user. + * + * Permission check is handled by selinux_inode_getxattr hook. + */ +static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) { struct inode_security_struct *isec = inode->i_security; char *context; unsigned len; int rc; - /* Permission check handled by selinux_inode_getxattr hook.*/ - - if (strcmp(name, XATTR_SELINUX_SUFFIX)) - return -EOPNOTSUPP; + if (strcmp(name, XATTR_SELINUX_SUFFIX)) { + rc = -EOPNOTSUPP; + goto out; + } rc = security_sid_to_context(isec->sid, &context, &len); if (rc) - return rc; + goto out; + /* Probe for required buffer size */ if (!buffer || !size) { - kfree(context); - return len; + rc = len; + goto out_free; } + if (size < len) { - kfree(context); - return -ERANGE; + rc = -ERANGE; + goto out_free; + } + + if (err > 0) { + if ((len == err) && !(memcmp(context, buffer, len))) { + /* Don't need to canonicalize value */ + rc = err; + goto out_free; + } + memset(buffer, 0, size); } memcpy(buffer, context, len); + rc = len; +out_free: kfree(context); - return len; +out: + return rc; } static int selinux_inode_setsecurity(struct inode *inode, const char *name, @@ -2704,8 +2713,7 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int si if (rc) return rc; - if (info && ((unsigned long)info == 1 || - (unsigned long)info == 2 || SI_FROMKERNEL(info))) + if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) return 0; if (!sig) @@ -3599,11 +3607,10 @@ static int ipc_alloc_security(struct task_struct *task, struct task_security_struct *tsec = task->security; struct ipc_security_struct *isec; - isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); + isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); if (!isec) return -ENOMEM; - memset(isec, 0, sizeof(struct ipc_security_struct)); isec->magic = SELINUX_MAGIC; isec->sclass = sclass; isec->ipc_perm = perm; @@ -3631,11 +3638,10 @@ static int msg_msg_alloc_security(struct msg_msg *msg) { struct msg_security_struct *msec; - msec = kmalloc(sizeof(struct msg_security_struct), GFP_KERNEL); + msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL); if (!msec) return -ENOMEM; - memset(msec, 0, sizeof(struct msg_security_struct)); msec->magic = SELINUX_MAGIC; msec->msg = msg; msec->sid = SECINITSID_UNLABELED; diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 718d7be9f4d..b10c34e8a74 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -114,13 +114,12 @@ static struct sel_netif *sel_netif_lookup(struct net_device *dev) if (likely(netif != NULL)) goto out; - new = kmalloc(sizeof(*new), GFP_ATOMIC); + new = kzalloc(sizeof(*new), GFP_ATOMIC); if (!new) { netif = ERR_PTR(-ENOMEM); goto out; } - memset(new, 0, sizeof(*new)); nsec = &new->nsec; ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index a45cc971e73..fdc38238972 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -105,7 +105,7 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf, ssize_t length; int new_value; - if (count < 0 || count >= PAGE_SIZE) + if (count >= PAGE_SIZE) return -ENOMEM; if (*ppos != 0) { /* No partial writes. */ @@ -155,7 +155,7 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf, int new_value; extern int selinux_disable(void); - if (count < 0 || count >= PAGE_SIZE) + if (count >= PAGE_SIZE) return -ENOMEM; if (*ppos != 0) { /* No partial writes. */ @@ -242,7 +242,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf, goto out; } - if ((count < 0) || (count > 64 * 1024 * 1024) + if ((count > 64 * 1024 * 1024) || (data = vmalloc(count)) == NULL) { length = -ENOMEM; goto out; @@ -284,7 +284,7 @@ static ssize_t sel_write_context(struct file * file, const char __user * buf, if (length) return length; - if (count < 0 || count >= PAGE_SIZE) + if (count >= PAGE_SIZE) return -ENOMEM; if (*ppos != 0) { /* No partial writes. */ @@ -332,7 +332,7 @@ static ssize_t sel_write_checkreqprot(struct file * file, const char __user * bu if (length) return length; - if (count < 0 || count >= PAGE_SIZE) + if (count >= PAGE_SIZE) return -ENOMEM; if (*ppos != 0) { /* No partial writes. */ @@ -424,15 +424,13 @@ static ssize_t sel_write_access(struct file * file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kmalloc(size+1, GFP_KERNEL); + scon = kzalloc(size+1, GFP_KERNEL); if (!scon) return length; - memset(scon, 0, size+1); - tcon = kmalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size+1, GFP_KERNEL); if (!tcon) goto out; - memset(tcon, 0, size+1); length = -EINVAL; if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) @@ -475,15 +473,13 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kmalloc(size+1, GFP_KERNEL); + scon = kzalloc(size+1, GFP_KERNEL); if (!scon) return length; - memset(scon, 0, size+1); - tcon = kmalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size+1, GFP_KERNEL); if (!tcon) goto out; - memset(tcon, 0, size+1); length = -EINVAL; if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) @@ -536,15 +532,13 @@ static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kmalloc(size+1, GFP_KERNEL); + scon = kzalloc(size+1, GFP_KERNEL); if (!scon) return length; - memset(scon, 0, size+1); - tcon = kmalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size+1, GFP_KERNEL); if (!tcon) goto out; - memset(tcon, 0, size+1); length = -EINVAL; if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) @@ -595,15 +589,13 @@ static ssize_t sel_write_user(struct file * file, char *buf, size_t size) return length; length = -ENOMEM; - con = kmalloc(size+1, GFP_KERNEL); + con = kzalloc(size+1, GFP_KERNEL); if (!con) return length; - memset(con, 0, size+1); - user = kmalloc(size+1, GFP_KERNEL); + user = kzalloc(size+1, GFP_KERNEL); if (!user) goto out; - memset(user, 0, size+1); length = -EINVAL; if (sscanf(buf, "%s %s", con, user) != 2) @@ -658,15 +650,13 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kmalloc(size+1, GFP_KERNEL); + scon = kzalloc(size+1, GFP_KERNEL); if (!scon) return length; - memset(scon, 0, size+1); - tcon = kmalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size+1, GFP_KERNEL); if (!tcon) goto out; - memset(tcon, 0, size+1); length = -EINVAL; if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) @@ -739,7 +729,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, if (!filep->f_op) goto out; - if (count < 0 || count > PAGE_SIZE) { + if (count > PAGE_SIZE) { ret = -EINVAL; goto out; } @@ -800,7 +790,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, if (!filep->f_op) goto out; - if (count < 0 || count >= PAGE_SIZE) { + if (count >= PAGE_SIZE) { length = -ENOMEM; goto out; } @@ -858,7 +848,7 @@ static ssize_t sel_commit_bools_write(struct file *filep, if (!filep->f_op) goto out; - if (count < 0 || count >= PAGE_SIZE) { + if (count >= PAGE_SIZE) { length = -ENOMEM; goto out; } @@ -924,7 +914,7 @@ static void sel_remove_bools(struct dentry *de) file_list_lock(); list_for_each(p, &sb->s_files) { - struct file * filp = list_entry(p, struct file, f_list); + struct file * filp = list_entry(p, struct file, f_u.fu_list); struct dentry * dentry = filp->f_dentry; if (dentry->d_parent != de) { @@ -1032,7 +1022,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file * file, ssize_t ret; int new_value; - if (count < 0 || count >= PAGE_SIZE) { + if (count >= PAGE_SIZE) { ret = -ENOMEM; goto out; } diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index daf28800746..d2737edba54 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -220,10 +220,9 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) u32 len; int rc; - booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); + booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); if (!booldatum) return -1; - memset(booldatum, 0, sizeof(struct cond_bool_datum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -321,10 +320,9 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum goto err; } - list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); + list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); if (!list) goto err; - memset(list, 0, sizeof(*list)); list->node = node_ptr; if (!data->head) @@ -414,11 +412,10 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) if (rc < 0) goto err; - expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL); + expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); if (!expr) { goto err; } - memset(expr, 0, sizeof(struct cond_expr)); expr->expr_type = le32_to_cpu(buf[0]); expr->bool = le32_to_cpu(buf[1]); @@ -460,10 +457,9 @@ int cond_read_list(struct policydb *p, void *fp) len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { - node = kmalloc(sizeof(struct cond_node), GFP_KERNEL); + node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); if (!node) goto err; - memset(node, 0, sizeof(struct cond_node)); if (cond_read_node(p, node, fp) != 0) goto err; diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d515154128c..47024a6e184 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -39,12 +39,11 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src) n = src->node; prev = NULL; while (n) { - new = kmalloc(sizeof(*new), GFP_ATOMIC); + new = kzalloc(sizeof(*new), GFP_ATOMIC); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } - memset(new, 0, sizeof(*new)); new->startbit = n->startbit; new->map = n->map; new->next = NULL; @@ -150,10 +149,9 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value) if (!value) return 0; - new = kmalloc(sizeof(*new), GFP_ATOMIC); + new = kzalloc(sizeof(*new), GFP_ATOMIC); if (!new) return -ENOMEM; - memset(new, 0, sizeof(*new)); new->startbit = bit & ~(MAPSIZE - 1); new->map = (MAPBIT << (bit - new->startbit)); @@ -232,13 +230,12 @@ int ebitmap_read(struct ebitmap *e, void *fp) printk(KERN_ERR "security: ebitmap: truncated map\n"); goto bad; } - n = kmalloc(sizeof(*n), GFP_KERNEL); + n = kzalloc(sizeof(*n), GFP_KERNEL); if (!n) { printk(KERN_ERR "security: ebitmap: out of memory\n"); rc = -ENOMEM; goto bad; } - memset(n, 0, sizeof(*n)); n->startbit = le32_to_cpu(buf[0]); diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 26661fcc00c..24e5ec95763 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -15,11 +15,10 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), struct hashtab *p; u32 i; - p = kmalloc(sizeof(*p), GFP_KERNEL); + p = kzalloc(sizeof(*p), GFP_KERNEL); if (p == NULL) return p; - memset(p, 0, sizeof(*p)); p->size = size; p->nel = 0; p->hash_value = hash_value; @@ -55,10 +54,9 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum) if (cur && (h->keycmp(h, key, cur->key) == 0)) return -EEXIST; - newnode = kmalloc(sizeof(*newnode), GFP_KERNEL); + newnode = kzalloc(sizeof(*newnode), GFP_KERNEL); if (newnode == NULL) return -ENOMEM; - memset(newnode, 0, sizeof(*newnode)); newnode->key = key; newnode->datum = datum; if (prev) { diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 8e6262d12aa..2f5f539875f 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -121,12 +121,11 @@ static int roles_init(struct policydb *p) int rc; struct role_datum *role; - role = kmalloc(sizeof(*role), GFP_KERNEL); + role = kzalloc(sizeof(*role), GFP_KERNEL); if (!role) { rc = -ENOMEM; goto out; } - memset(role, 0, sizeof(*role)); role->value = ++p->p_roles.nprim; if (role->value != OBJECT_R_VAL) { rc = -EINVAL; @@ -851,12 +850,11 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) __le32 buf[2]; u32 len; - perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); + perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL); if (!perdatum) { rc = -ENOMEM; goto out; } - memset(perdatum, 0, sizeof(*perdatum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -893,12 +891,11 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) u32 len, nel; int i, rc; - comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); + comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); if (!comdatum) { rc = -ENOMEM; goto out; } - memset(comdatum, 0, sizeof(*comdatum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -950,10 +947,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, lc = NULL; for (i = 0; i < ncons; i++) { - c = kmalloc(sizeof(*c), GFP_KERNEL); + c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) return -ENOMEM; - memset(c, 0, sizeof(*c)); if (lc) { lc->next = c; @@ -969,10 +965,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, le = NULL; depth = -1; for (j = 0; j < nexpr; j++) { - e = kmalloc(sizeof(*e), GFP_KERNEL); + e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) return -ENOMEM; - memset(e, 0, sizeof(*e)); if (le) { le->next = e; @@ -1033,12 +1028,11 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) u32 len, len2, ncons, nel; int i, rc; - cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); + cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); if (!cladatum) { rc = -ENOMEM; goto out; } - memset(cladatum, 0, sizeof(*cladatum)); rc = next_entry(buf, fp, sizeof(u32)*6); if (rc < 0) @@ -1127,12 +1121,11 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) __le32 buf[2]; u32 len; - role = kmalloc(sizeof(*role), GFP_KERNEL); + role = kzalloc(sizeof(*role), GFP_KERNEL); if (!role) { rc = -ENOMEM; goto out; } - memset(role, 0, sizeof(*role)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -1188,12 +1181,11 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) __le32 buf[3]; u32 len; - typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); + typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL); if (!typdatum) { rc = -ENOMEM; return rc; } - memset(typdatum, 0, sizeof(*typdatum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -1261,12 +1253,11 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) __le32 buf[2]; u32 len; - usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); + usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); if (!usrdatum) { rc = -ENOMEM; goto out; } - memset(usrdatum, 0, sizeof(*usrdatum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -1316,12 +1307,11 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) __le32 buf[2]; u32 len; - levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); + levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); if (!levdatum) { rc = -ENOMEM; goto out; } - memset(levdatum, 0, sizeof(*levdatum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -1368,12 +1358,11 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) __le32 buf[3]; u32 len; - catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); + catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); if (!catdatum) { rc = -ENOMEM; goto out; } - memset(catdatum, 0, sizeof(*catdatum)); rc = next_entry(buf, fp, sizeof buf); if (rc < 0) @@ -1567,12 +1556,11 @@ int policydb_read(struct policydb *p, void *fp) nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { - tr = kmalloc(sizeof(*tr), GFP_KERNEL); + tr = kzalloc(sizeof(*tr), GFP_KERNEL); if (!tr) { rc = -ENOMEM; goto bad; } - memset(tr, 0, sizeof(*tr)); if (ltr) { ltr->next = tr; } else { @@ -1593,12 +1581,11 @@ int policydb_read(struct policydb *p, void *fp) nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { - ra = kmalloc(sizeof(*ra), GFP_KERNEL); + ra = kzalloc(sizeof(*ra), GFP_KERNEL); if (!ra) { rc = -ENOMEM; goto bad; } - memset(ra, 0, sizeof(*ra)); if (lra) { lra->next = ra; } else { @@ -1627,12 +1614,11 @@ int policydb_read(struct policydb *p, void *fp) nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { - c = kmalloc(sizeof(*c), GFP_KERNEL); + c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) { rc = -ENOMEM; goto bad; } - memset(c, 0, sizeof(*c)); if (l) { l->next = c; } else { @@ -1743,12 +1729,11 @@ int policydb_read(struct policydb *p, void *fp) if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL); + newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); if (!newgenfs) { rc = -ENOMEM; goto bad; } - memset(newgenfs, 0, sizeof(*newgenfs)); newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL); if (!newgenfs->fstype) { @@ -1790,12 +1775,11 @@ int policydb_read(struct policydb *p, void *fp) goto bad; len = le32_to_cpu(buf[0]); - newc = kmalloc(sizeof(*newc), GFP_KERNEL); + newc = kzalloc(sizeof(*newc), GFP_KERNEL); if (!newc) { rc = -ENOMEM; goto bad; } - memset(newc, 0, sizeof(*newc)); newc->u.name = kmalloc(len + 1,GFP_KERNEL); if (!newc->u.name) { @@ -1843,12 +1827,11 @@ int policydb_read(struct policydb *p, void *fp) nel = le32_to_cpu(buf[0]); lrt = NULL; for (i = 0; i < nel; i++) { - rt = kmalloc(sizeof(*rt), GFP_KERNEL); + rt = kzalloc(sizeof(*rt), GFP_KERNEL); if (!rt) { rc = -ENOMEM; goto bad; } - memset(rt, 0, sizeof(*rt)); if (lrt) lrt->next = rt; else diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index aecdded55e7..44eb4d74908 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1531,12 +1531,11 @@ int security_get_user_sids(u32 fromsid, } usercon.user = user->value; - mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC); + mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC); if (!mysids) { rc = -ENOMEM; goto out_unlock; } - memset(mysids, 0, maxnel*sizeof(*mysids)); ebitmap_for_each_bit(&user->roles, rnode, i) { if (!ebitmap_node_get_bit(rnode, i)) @@ -1566,13 +1565,12 @@ int security_get_user_sids(u32 fromsid, mysids[mynel++] = sid; } else { maxnel += SIDS_NEL; - mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC); + mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); if (!mysids2) { rc = -ENOMEM; kfree(mysids); goto out_unlock; } - memset(mysids2, 0, maxnel*sizeof(*mysids2)); memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); kfree(mysids); mysids = mysids2; @@ -1714,12 +1712,11 @@ int security_get_bools(int *len, char ***names, int **values) goto out; } - *names = (char**)kmalloc(sizeof(char*) * *len, GFP_ATOMIC); + *names = (char**)kcalloc(*len, sizeof(char*), GFP_ATOMIC); if (!*names) goto err; - memset(*names, 0, sizeof(char*) * *len); - *values = (int*)kmalloc(sizeof(int) * *len, GFP_ATOMIC); + *values = (int*)kcalloc(*len, sizeof(int), GFP_ATOMIC); if (!*values) goto err; diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c index 3ecef4689f1..fd25aca2512 100644 --- a/sound/oss/ac97_codec.c +++ b/sound/oss/ac97_codec.c @@ -55,6 +55,7 @@ #include <linux/pci.h> #include <linux/ac97_codec.h> #include <asm/uaccess.h> +#include <asm/semaphore.h> #define CODEC_ID_BUFSZ 14 diff --git a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c index d2b9beda8ac..b3ea719d33d 100644 --- a/sound/oss/awe_wave.c +++ b/sound/oss/awe_wave.c @@ -6062,7 +6062,7 @@ static int awe_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id io1 = pnp_port_start(dev,0); io2 = pnp_port_start(dev,1); io3 = pnp_port_start(dev,2); - printk(KERN_INFO "AWE32: A PnP Wave Table was detected at IO's %#x,%#x,%#x\n.", + printk(KERN_INFO "AWE32: A PnP Wave Table was detected at IO's %#x,%#x,%#x.\n", io1, io2, io3); setup_ports(io1, io2, io3); diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c index 6ec308f5d93..7c59e2d4003 100644 --- a/sound/oss/cs4232.c +++ b/sound/oss/cs4232.c @@ -195,10 +195,12 @@ static int __init probe_cs4232(struct address_info *hw_config, int isapnp_config CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */ CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff); /* WSS base */ - if (check_region(0x388, 4)) /* Not free */ + if (!request_region(0x388, 4, "FM")) /* Not free */ CS_OUT3(0x48, 0x00, 0x00) /* FM base off */ - else + else { + release_region(0x388, 4); CS_OUT3(0x48, 0x03, 0x88); /* FM base 0x388 */ + } CS_OUT3(0x42, 0x00, 0x00); /* SB base off */ CS_OUT2(0x22, irq); /* SB+WSS IRQ */ diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c index b92ba892163..b1a4eeb9dc0 100644 --- a/sound/oss/wavfront.c +++ b/sound/oss/wavfront.c @@ -2434,7 +2434,7 @@ static int __init detect_wavefront (int irq, int io_base) consumes 16. */ - if (check_region (io_base, 16)) { + if (!request_region (io_base, 16, "wavfront")) { printk (KERN_ERR LOGNAME "IO address range 0x%x - 0x%x " "already in use - ignored\n", dev.base, dev.base+15); @@ -2466,10 +2466,13 @@ static int __init detect_wavefront (int irq, int io_base) } else { printk (KERN_WARNING LOGNAME "not raw, but no " "hardware version!\n"); + release_region (io_base, 16); return 0; } if (!wf_raw) { + /* will re-acquire region in install_wavefront() */ + release_region (io_base, 16); return 1; } else { printk (KERN_INFO LOGNAME @@ -2489,6 +2492,7 @@ static int __init detect_wavefront (int irq, int io_base) if (wavefront_hw_reset ()) { printk (KERN_WARNING LOGNAME "hardware reset failed\n"); + release_region (io_base, 16); return 0; } @@ -2496,6 +2500,8 @@ static int __init detect_wavefront (int irq, int io_base) dev.has_fx = (detect_wffx () == 0); + /* will re-acquire region in install_wavefront() */ + release_region (io_base, 16); return 1; } @@ -2804,17 +2810,27 @@ static int __init wavefront_init (int atboot) } static int __init install_wavefront (void) - { + if (!request_region (dev.base+2, 6, "wavefront synth")) + return -1; + + if (dev.has_fx) { + if (!request_region (dev.base+8, 8, "wavefront fx")) { + release_region (dev.base+2, 6); + return -1; + } + } + if ((dev.synth_dev = register_sound_synth (&wavefront_fops, -1)) < 0) { printk (KERN_ERR LOGNAME "cannot register raw synth\n"); - return -1; + goto err_out; } #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ if ((dev.oss_dev = sound_alloc_synthdev()) == -1) { printk (KERN_ERR LOGNAME "Too many sequencers\n"); - return -1; + /* FIXME: leak: should unregister sound synth */ + goto err_out; } else { synth_devs[dev.oss_dev] = &wavefront_operations; } @@ -2827,20 +2843,20 @@ static int __init install_wavefront (void) sound_unload_synthdev (dev.oss_dev); #endif /* OSS_SUPPORT_SEQ */ - return -1; + goto err_out; } - request_region (dev.base+2, 6, "wavefront synth"); - - if (dev.has_fx) { - request_region (dev.base+8, 8, "wavefront fx"); - } - if (wavefront_config_midi ()) { printk (KERN_WARNING LOGNAME "could not initialize MIDI.\n"); } return dev.oss_dev; + +err_out: + release_region (dev.base+2, 6); + if (dev.has_fx) + release_region (dev.base+8, 8); + return -1; } static void __exit uninstall_wavefront (void) |