aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/cpu-hotplug.txt9
-rw-r--r--Documentation/filesystems/v9fs.txt16
-rw-r--r--Documentation/sysctl/kernel.txt10
-rw-r--r--arch/h8300/Kconfig.debug2
-rw-r--r--arch/h8300/defconfig2
-rw-r--r--arch/i386/kernel/mpparse.c2
-rw-r--r--arch/m32r/kernel/sys_m32r.c61
-rw-r--r--arch/m68k/kernel/process.c3
-rw-r--r--arch/powerpc/kernel/head_64.S4
-rw-r--r--arch/powerpc/kernel/lparcfg.c6
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c16
-rw-r--r--arch/powerpc/kernel/setup_64.c4
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c4
-rw-r--r--arch/powerpc/kernel/time.c282
-rw-r--r--arch/powerpc/platforms/powermac/feature.c10
-rw-r--r--arch/powerpc/platforms/pseries/smp.c2
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c8
-rw-r--r--arch/ppc/xmon/start.c15
-rw-r--r--arch/x86_64/defconfig6
-rw-r--r--drivers/block/pktcdvd.c82
-rw-r--r--drivers/char/agp/Kconfig55
-rw-r--r--drivers/char/agp/amd64-agp.c6
-rw-r--r--drivers/char/agp/sworks-agp.c4
-rw-r--r--drivers/char/sysrq.c2
-rw-r--r--drivers/fc4/fc.c2
-rw-r--r--drivers/ieee1394/sbp2.c10
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c14
-rw-r--r--drivers/net/irda/irda-usb.c90
-rw-r--r--drivers/net/irda/irda-usb.h7
-rw-r--r--drivers/net/wireless/ipw2200.c6
-rw-r--r--drivers/s390/block/Kconfig14
-rw-r--r--drivers/s390/block/Makefile2
-rw-r--r--drivers/s390/block/dasd.c97
-rw-r--r--drivers/s390/block/dasd_3990_erp.c3
-rw-r--r--drivers/s390/block/dasd_eckd.h1
-rw-r--r--drivers/s390/block/dasd_eer.c1090
-rw-r--r--drivers/s390/block/dasd_int.h38
-rw-r--r--drivers/s390/cio/qdio.c13
-rw-r--r--drivers/spi/spi.c5
-rw-r--r--drivers/video/aty/radeon_pm.c19
-rw-r--r--fs/9p/v9fs.c2
-rw-r--r--fs/proc/inode.c4
-rw-r--r--fs/proc/root.c17
-rw-r--r--include/asm-m32r/system.h2
-rw-r--r--include/asm-m68k/irq.h2
-rw-r--r--include/asm-m68k/raw_io.h1
-rw-r--r--include/asm-ppc/machdep.h13
-rw-r--r--include/asm-s390/dasd.h13
-rw-r--r--include/linux/acpi.h3
-rw-r--r--include/linux/mm.h4
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/swap.h2
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--kernel/auditsc.c6
-rw-r--r--kernel/sys_ni.c2
-rw-r--r--kernel/sysctl.c18
-rw-r--r--lib/iomap_copy.c2
-rw-r--r--mm/mempolicy.c4
-rw-r--r--mm/nommu.c2
-rw-r--r--mm/oom_kill.c123
-rw-r--r--mm/page_alloc.c2
-rw-r--r--net/core/skbuff.c10
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c18
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c16
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/xfrm/xfrm_policy.c2
-rw-r--r--sound/core/control_compat.c16
67 files changed, 554 insertions, 1757 deletions
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index e71bc6cbbc5..57a09f99ecb 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -46,10 +46,12 @@ maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using
maxcpus=2 will only boot 2. You can choose to bring the
other cpus later online, read FAQ's for more info.
-additional_cpus=n [x86_64, s390 only] use this to limit hotpluggable cpus.
- This option sets
+additional_cpus*=n Use this to limit hotpluggable cpus. This option sets
cpu_possible_map = cpu_present_map + additional_cpus
+(*) Option valid only for following architectures
+- x86_64, ia64, s390
+
ia64 and x86_64 use the number of disabled local apics in ACPI tables MADT
to determine the number of potentially hot-pluggable cpus. The implementation
should only rely on this to count the #of cpus, but *MUST* not rely on the
@@ -57,6 +59,9 @@ apicid values in those tables for disabled apics. In the event BIOS doesnt
mark such hot-pluggable cpus as disabled entries, one could use this
parameter "additional_cpus=x" to represent those cpus in the cpu_possible_map.
+s390 uses the number of cpus it detects at IPL time to also the number of bits
+in cpu_possible_map. If it is desired to add additional cpus at a later time
+the number should be specified using this option or the possible_cpus option.
possible_cpus=n [s390 only] use this to set hotpluggable cpus.
This option sets possible_cpus bits in
diff --git a/Documentation/filesystems/v9fs.txt b/Documentation/filesystems/v9fs.txt
index 4e92feb6b50..24c7a9c41f0 100644
--- a/Documentation/filesystems/v9fs.txt
+++ b/Documentation/filesystems/v9fs.txt
@@ -57,8 +57,6 @@ OPTIONS
port=n port to connect to on the remote server
- timeout=n request timeouts (in ms) (default 60000ms)
-
noextend force legacy mode (no 9P2000.u semantics)
uid attempt to mount as a particular uid
@@ -74,10 +72,16 @@ OPTIONS
RESOURCES
=========
-The Linux version of the 9P server, along with some client-side utilities
-can be found at http://v9fs.sf.net (along with a CVS repository of the
-development branch of this module). There are user and developer mailing
-lists here, as well as a bug-tracker.
+The Linux version of the 9P server is now maintained under the npfs project
+on sourceforge (http://sourceforge.net/projects/npfs).
+
+There are user and developer mailing lists available through the v9fs project
+on sourceforge (http://sourceforge.net/projects/v9fs).
+
+News and other information is maintained on SWiK (http://swik.net/v9fs).
+
+Bug reports may be issued through the kernel.org bugzilla
+(http://bugzilla.kernel.org)
For more information on the Plan 9 Operating System check out
http://plan9.bell-labs.com/plan9
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 9f11d36a8c1..b0c7ab93dcb 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -16,6 +16,7 @@ before actually making adjustments.
Currently, these files might (depending on your configuration)
show up in /proc/sys/kernel:
+- acpi_video_flags
- acct
- core_pattern
- core_uses_pid
@@ -57,6 +58,15 @@ show up in /proc/sys/kernel:
==============================================================
+acpi_video_flags:
+
+flags
+
+See Doc*/kernel/power/video.txt, it allows mode of video boot to be
+set during run time.
+
+==============================================================
+
acct:
highwater lowwater frequency
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
index 55034d08abf..e0e9bcb015a 100644
--- a/arch/h8300/Kconfig.debug
+++ b/arch/h8300/Kconfig.debug
@@ -34,7 +34,7 @@ config GDB_DEBUG
help
gdb stub exception support
-config CONFIG_SH_STANDARD_BIOS
+config SH_STANDARD_BIOS
bool "Use gdb protocol serial console"
depends on (!H8300H_SIM && !H8S_SIM)
help
diff --git a/arch/h8300/defconfig b/arch/h8300/defconfig
index 9d9b491cfc2..8f1ec329715 100644
--- a/arch/h8300/defconfig
+++ b/arch/h8300/defconfig
@@ -328,7 +328,7 @@ CONFIG_FULLDEBUG=y
CONFIG_NO_KERNEL_MSG=y
# CONFIG_SYSCALL_PRINT is not set
# CONFIG_GDB_DEBUG is not set
-# CONFIG_CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_DEFAULT_CMDLINE is not set
# CONFIG_BLKDEV_RESERVE is not set
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 0102f3d50e5..e7609abf379 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -710,7 +710,7 @@ void __init get_smp_config (void)
* Read the physical hardware table. Anything here will
* override the defaults.
*/
- if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
+ if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
smp_found_config = 0;
printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index fe55b28d372..670cb49210a 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -29,28 +29,7 @@
/*
* sys_tas() - test-and-set
- * linuxthreads testing version
*/
-#ifndef CONFIG_SMP
-asmlinkage int sys_tas(int *addr)
-{
- int oldval;
- unsigned long flags;
-
- if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
- return -EFAULT;
- local_irq_save(flags);
- oldval = *addr;
- if (!oldval)
- *addr = 1;
- local_irq_restore(flags);
- return oldval;
-}
-#else /* CONFIG_SMP */
-#include <linux/spinlock.h>
-
-static DEFINE_SPINLOCK(tas_lock);
-
asmlinkage int sys_tas(int *addr)
{
int oldval;
@@ -58,15 +37,43 @@ asmlinkage int sys_tas(int *addr)
if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
return -EFAULT;
- _raw_spin_lock(&tas_lock);
- oldval = *addr;
- if (!oldval)
- *addr = 1;
- _raw_spin_unlock(&tas_lock);
+ /* atomic operation:
+ * oldval = *addr; *addr = 1;
+ */
+ __asm__ __volatile__ (
+ DCACHE_CLEAR("%0", "r4", "%1")
+ " .fillinsn\n"
+ "1:\n"
+ " lock %0, @%1 -> unlock %2, @%1\n"
+ "2:\n"
+ /* NOTE:
+ * The m32r processor can accept interrupts only
+ * at the 32-bit instruction boundary.
+ * So, in the above code, the "unlock" instruction
+ * can be executed continuously after the "lock"
+ * instruction execution without any interruptions.
+ */
+ ".section .fixup,\"ax\"\n"
+ " .balign 4\n"
+ "3: ldi %0, #%3\n"
+ " seth r14, #high(2b)\n"
+ " or3 r14, r14, #low(2b)\n"
+ " jmp r14\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .balign 4\n"
+ " .long 1b,3b\n"
+ ".previous\n"
+ : "=&r" (oldval)
+ : "r" (addr), "r" (1), "i"(-EFAULT)
+ : "r14", "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+ , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+ );
return oldval;
}
-#endif /* CONFIG_SMP */
/*
* sys_pipe() is the normal C calling standard for creating
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 3f9cb55d035..2d8ad0727b6 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -129,6 +129,9 @@ void machine_power_off(void)
for (;;);
}
+void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
+
void show_regs(struct pt_regs * regs)
{
printk("\n");
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 41565962939..2b03a09fe5e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -157,8 +157,7 @@ _GLOBAL(__secondary_hold)
SET_REG_IMMEDIATE(r4, .hmt_init)
mtctr r4
bctr
-#else
-#ifdef CONFIG_SMP
+#elif defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
mtctr r4
mr r3,r24
@@ -166,7 +165,6 @@ _GLOBAL(__secondary_hold)
#else
BUG_OPCODE
#endif
-#endif
/* This value is used to mark exception frames on the stack. */
.section ".toc","aw"
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 1ae96a8ed7e..e789fef4eb8 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -341,7 +341,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
const char *system_id = "";
unsigned int *lp_index_ptr, lp_index = 0;
struct device_node *rtas_node;
- int *lrdrp;
+ int *lrdrp = NULL;
rootdn = find_path_device("/");
if (rootdn) {
@@ -362,7 +362,9 @@ static int lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "partition_id=%d\n", (int)lp_index);
rtas_node = find_path_device("/rtas");
- lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);
+ if (rtas_node)
+ lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity",
+ NULL);
if (lrdrp == NULL) {
partition_potential_processors = vdso_data->processorCount;
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index d9a459c144d..8a731ea877b 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -79,15 +79,8 @@ EXPORT_SYMBOL(sys_sigreturn);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strcasecmp);
EXPORT_SYMBOL(csum_partial);
@@ -185,9 +178,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
EXPORT_SYMBOL(cuda_request);
EXPORT_SYMBOL(cuda_poll);
#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_PPC_PMAC
-EXPORT_SYMBOL(sys_ctrler);
-#endif
#ifdef CONFIG_VT
EXPORT_SYMBOL(kd_mksound);
#endif
@@ -205,7 +195,6 @@ EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memchr);
@@ -214,7 +203,6 @@ EXPORT_SYMBOL(screen_info);
#endif
#ifdef CONFIG_PPC32
-EXPORT_SYMBOL(__delay);
EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(tb_ticks_per_jiffy);
@@ -222,10 +210,6 @@ EXPORT_SYMBOL(console_drivers);
EXPORT_SYMBOL(cacheable_memcpy);
#endif
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-EXPORT_SYMBOL(__down_interruptible);
-
#ifdef CONFIG_8xx
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index a717dff695e..f96c49b03ba 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -311,8 +311,6 @@ void smp_release_cpus(void)
DBG(" <- smp_release_cpus()\n");
}
-#else
-#define smp_release_cpus()
#endif /* CONFIG_SMP || CONFIG_KEXEC */
/*
@@ -473,10 +471,12 @@ void __init setup_system(void)
check_smt_enabled();
smp_setup_cpu_maps();
+#ifdef CONFIG_SMP
/* Release secondary cpus out of their spinloops at 0x60 now that
* we can map physical -> logical CPU ids
*/
smp_release_cpus();
+#endif
printk("Starting Linux PPC64 %s\n", system_utsname.version);
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 475249dc235..cd75ab2908f 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -176,7 +176,6 @@ struct timex32 {
};
extern int do_adjtimex(struct timex *);
-extern void ppc_adjtimex(void);
asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp)
{
@@ -209,9 +208,6 @@ asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp)
ret = do_adjtimex(&txc);
- /* adjust the conversion of TB to time of day to track adjtimex */
- ppc_adjtimex();
-
if(put_user(txc.modes, &utp->modes) ||
__put_user(txc.offset, &utp->offset) ||
__put_user(txc.freq, &utp->freq) ||
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 1886045a2fd..2a7ddc57937 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -50,6 +50,7 @@
#include <linux/security.h>
#include <linux/percpu.h>
#include <linux/rtc.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <asm/processor.h>
@@ -99,7 +100,15 @@ EXPORT_SYMBOL(tb_ticks_per_usec);
unsigned long tb_ticks_per_sec;
u64 tb_to_xs;
unsigned tb_to_us;
-unsigned long processor_freq;
+
+#define TICKLEN_SCALE (SHIFT_SCALE - 10)
+u64 last_tick_len; /* units are ns / 2^TICKLEN_SCALE */
+u64 ticklen_to_xs; /* 0.64 fraction */
+
+/* If last_tick_len corresponds to about 1/HZ seconds, then
+ last_tick_len << TICKLEN_SHIFT will be about 2^63. */
+#define TICKLEN_SHIFT (63 - 30 - TICKLEN_SCALE + SHIFT_HZ)
+
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL_GPL(rtc_lock);
@@ -113,10 +122,6 @@ extern unsigned long wall_jiffies;
extern struct timezone sys_tz;
static long timezone_offset;
-void ppc_adjtimex(void);
-
-static unsigned adjusting_time = 0;
-
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
@@ -178,8 +183,7 @@ static __inline__ void timer_check_rtc(void)
*/
if (ppc_md.set_rtc_time && ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
- abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ &&
- jiffies - wall_jiffies == 1) {
+ abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ) {
struct rtc_time tm;
to_tm(xtime.tv_sec + 1 + timezone_offset, &tm);
tm.tm_year -= 1900;
@@ -226,15 +230,14 @@ void do_gettimeofday(struct timeval *tv)
if (__USE_RTC()) {
/* do this the old way */
unsigned long flags, seq;
- unsigned int sec, nsec, usec, lost;
+ unsigned int sec, nsec, usec;
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
sec = xtime.tv_sec;
nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp);
- lost = jiffies - wall_jiffies;
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
- usec = nsec / 1000 + lost * (1000000 / HZ);
+ usec = nsec / 1000;
while (usec >= 1000000) {
usec -= 1000000;
++sec;
@@ -248,23 +251,6 @@ void do_gettimeofday(struct timeval *tv)
EXPORT_SYMBOL(do_gettimeofday);
-/* Synchronize xtime with do_gettimeofday */
-
-static inline void timer_sync_xtime(unsigned long cur_tb)
-{
-#ifdef CONFIG_PPC64
- /* why do we do this? */
- struct timeval my_tv;
-
- __do_gettimeofday(&my_tv, cur_tb);
-
- if (xtime.tv_sec <= my_tv.tv_sec) {
- xtime.tv_sec = my_tv.tv_sec;
- xtime.tv_nsec = my_tv.tv_usec * 1000;
- }
-#endif
-}
-
/*
* There are two copies of tb_to_xs and stamp_xsec so that no
* lock is needed to access and use these values in
@@ -323,15 +309,30 @@ static __inline__ void timer_recalc_offset(u64 cur_tb)
{
unsigned long offset;
u64 new_stamp_xsec;
+ u64 tlen, t2x;
if (__USE_RTC())
return;
+ tlen = current_tick_length();
offset = cur_tb - do_gtod.varp->tb_orig_stamp;
- if ((offset & 0x80000000u) == 0)
- return;
- new_stamp_xsec = do_gtod.varp->stamp_xsec
- + mulhdu(offset, do_gtod.varp->tb_to_xs);
- update_gtod(cur_tb, new_stamp_xsec, do_gtod.varp->tb_to_xs);
+ if (tlen == last_tick_len && offset < 0x80000000u) {
+ /* check that we're still in sync; if not, resync */
+ struct timeval tv;
+ __do_gettimeofday(&tv, cur_tb);
+ if (tv.tv_sec <= xtime.tv_sec &&
+ (tv.tv_sec < xtime.tv_sec ||
+ tv.tv_usec * 1000 <= xtime.tv_nsec))
+ return;
+ }
+ if (tlen != last_tick_len) {
+ t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs);
+ last_tick_len = tlen;
+ } else
+ t2x = do_gtod.varp->tb_to_xs;
+ new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
+ do_div(new_stamp_xsec, 1000000000);
+ new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
+ update_gtod(cur_tb, new_stamp_xsec, t2x);
}
#ifdef CONFIG_SMP
@@ -462,13 +463,10 @@ void timer_interrupt(struct pt_regs * regs)
write_seqlock(&xtime_lock);
tb_last_jiffy += tb_ticks_per_jiffy;
tb_last_stamp = per_cpu(last_jiffy, cpu);
- timer_recalc_offset(tb_last_jiffy);
do_timer(regs);
- timer_sync_xtime(tb_last_jiffy);
+ timer_recalc_offset(tb_last_jiffy);
timer_check_rtc();
write_sequnlock(&xtime_lock);
- if (adjusting_time && (time_adjust == 0))
- ppc_adjtimex();
}
next_dec = tb_ticks_per_jiffy - ticks;
@@ -492,16 +490,18 @@ void timer_interrupt(struct pt_regs * regs)
void wakeup_decrementer(void)
{
- int i;
+ unsigned long ticks;
- set_dec(tb_ticks_per_jiffy);
/*
- * We don't expect this to be called on a machine with a 601,
- * so using get_tbl is fine.
+ * The timebase gets saved on sleep and restored on wakeup,
+ * so all we need to do is to reset the decrementer.
*/
- tb_last_stamp = tb_last_jiffy = get_tb();
- for_each_cpu(i)
- per_cpu(last_jiffy, i) = tb_last_stamp;
+ ticks = tb_ticks_since(__get_cpu_var(last_jiffy));
+ if (ticks < tb_ticks_per_jiffy)
+ ticks = tb_ticks_per_jiffy - ticks;
+ else
+ ticks = 1;
+ set_dec(ticks);
}
#ifdef CONFIG_SMP
@@ -541,8 +541,8 @@ int do_settimeofday(struct timespec *tv)
time_t wtm_sec, new_sec = tv->tv_sec;
long wtm_nsec, new_nsec = tv->tv_nsec;
unsigned long flags;
- long int tb_delta;
- u64 new_xsec, tb_delta_xs;
+ u64 new_xsec;
+ unsigned long tb_delta;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -563,9 +563,19 @@ int do_settimeofday(struct timespec *tv)
first_settimeofday = 0;
}
#endif
+
+ /*
+ * Subtract off the number of nanoseconds since the
+ * beginning of the last tick.
+ * Note that since we don't increment jiffies_64 anywhere other
+ * than in do_timer (since we don't have a lost tick problem),
+ * wall_jiffies will always be the same as jiffies,
+ * and therefore the (jiffies - wall_jiffies) computation
+ * has been removed.
+ */
tb_delta = tb_ticks_since(tb_last_stamp);
- tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
- tb_delta_xs = mulhdu(tb_delta, do_gtod.varp->tb_to_xs);
+ tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
+ new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
@@ -580,12 +590,12 @@ int do_settimeofday(struct timespec *tv)
ntp_clear();
- new_xsec = 0;
- if (new_nsec != 0) {
- new_xsec = (u64)new_nsec * XSEC_PER_SEC;
+ new_xsec = xtime.tv_nsec;
+ if (new_xsec != 0) {
+ new_xsec *= XSEC_PER_SEC;
do_div(new_xsec, NSEC_PER_SEC);
}
- new_xsec += (u64)new_sec * XSEC_PER_SEC - tb_delta_xs;
+ new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
@@ -671,7 +681,7 @@ void __init time_init(void)
unsigned long flags;
unsigned long tm = 0;
struct div_result res;
- u64 scale;
+ u64 scale, x;
unsigned shift;
if (ppc_md.time_init != NULL)
@@ -693,11 +703,36 @@ void __init time_init(void)
}
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+ tb_ticks_per_sec = ppc_tb_freq;
tb_ticks_per_usec = ppc_tb_freq / 1000000;
tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
- div128_by_32(1024*1024, 0, tb_ticks_per_sec, &res);
- tb_to_xs = res.result_low;
+
+ /*
+ * Calculate the length of each tick in ns. It will not be
+ * exactly 1e9/HZ unless ppc_tb_freq is divisible by HZ.
+ * We compute 1e9 * tb_ticks_per_jiffy / ppc_tb_freq,
+ * rounded up.
+ */
+ x = (u64) NSEC_PER_SEC * tb_ticks_per_jiffy + ppc_tb_freq - 1;
+ do_div(x, ppc_tb_freq);
+ tick_nsec = x;
+ last_tick_len = x << TICKLEN_SCALE;
+
+ /*
+ * Compute ticklen_to_xs, which is a factor which gets multiplied
+ * by (last_tick_len << TICKLEN_SHIFT) to get a tb_to_xs value.
+ * It is computed as:
+ * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9)
+ * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT
+ * so as to give the result as a 0.64 fixed-point fraction.
+ */
+ div128_by_32(1ULL << (64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT), 0,
+ tb_ticks_per_jiffy, &res);
+ div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res);
+ ticklen_to_xs = res.result_low;
+
+ /* Compute tb_to_xs from tick_nsec */
+ tb_to_xs = mulhdu(last_tick_len << TICKLEN_SHIFT, ticklen_to_xs);
/*
* Compute scale factor for sched_clock.
@@ -724,6 +759,14 @@ void __init time_init(void)
tm = get_boot_time();
write_seqlock_irqsave(&xtime_lock, flags);
+
+ /* If platform provided a timezone (pmac), we correct the time */
+ if (timezone_offset) {
+ sys_tz.tz_minuteswest = -timezone_offset / 60;
+ sys_tz.tz_dsttime = 0;
+ tm -= timezone_offset;
+ }
+
xtime.tv_sec = tm;
xtime.tv_nsec = 0;
do_gtod.varp = &do_gtod.vars[0];
@@ -738,18 +781,11 @@ void __init time_init(void)
vdso_data->tb_orig_stamp = tb_last_jiffy;
vdso_data->tb_update_count = 0;
vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
- vdso_data->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
+ vdso_data->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
vdso_data->tb_to_xs = tb_to_xs;
time_freq = 0;
- /* If platform provided a timezone (pmac), we correct the time */
- if (timezone_offset) {
- sys_tz.tz_minuteswest = -timezone_offset / 60;
- sys_tz.tz_dsttime = 0;
- xtime.tv_sec -= timezone_offset;
- }
-
last_rtc_update = xtime.tv_sec;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
@@ -759,126 +795,6 @@ void __init time_init(void)
set_dec(tb_ticks_per_jiffy);
}
-/*
- * After adjtimex is called, adjust the conversion of tb ticks
- * to microseconds to keep do_gettimeofday synchronized
- * with ntpd.
- *
- * Use the time_adjust, time_freq and time_offset computed by adjtimex to
- * adjust the frequency.
- */
-
-/* #define DEBUG_PPC_ADJTIMEX 1 */
-
-void ppc_adjtimex(void)
-{
-#ifdef CONFIG_PPC64
- unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec,
- new_tb_to_xs, new_xsec, new_stamp_xsec;
- unsigned long tb_ticks_per_sec_delta;
- long delta_freq, ltemp;
- struct div_result divres;
- unsigned long flags;
- long singleshot_ppm = 0;
-
- /*
- * Compute parts per million frequency adjustment to
- * accomplish the time adjustment implied by time_offset to be
- * applied over the elapsed time indicated by time_constant.
- * Use SHIFT_USEC to get it into the same units as
- * time_freq.
- */
- if ( time_offset < 0 ) {
- ltemp = -time_offset;
- ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
- ltemp >>= SHIFT_KG + time_constant;
- ltemp = -ltemp;
- } else {
- ltemp = time_offset;
- ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
- ltemp >>= SHIFT_KG + time_constant;
- }
-
- /* If there is a single shot time adjustment in progress */
- if ( time_adjust ) {
-#ifdef DEBUG_PPC_ADJTIMEX
- printk("ppc_adjtimex: ");
- if ( adjusting_time == 0 )
- printk("starting ");
- printk("single shot time_adjust = %ld\n", time_adjust);
-#endif
-
- adjusting_time = 1;
-
- /*
- * Compute parts per million frequency adjustment
- * to match time_adjust
- */
- singleshot_ppm = tickadj * HZ;
- /*
- * The adjustment should be tickadj*HZ to match the code in
- * linux/kernel/timer.c, but experiments show that this is too
- * large. 3/4 of tickadj*HZ seems about right
- */
- singleshot_ppm -= singleshot_ppm / 4;
- /* Use SHIFT_USEC to get it into the same units as time_freq */
- singleshot_ppm <<= SHIFT_USEC;
- if ( time_adjust < 0 )
- singleshot_ppm = -singleshot_ppm;
- }
- else {
-#ifdef DEBUG_PPC_ADJTIMEX
- if ( adjusting_time )
- printk("ppc_adjtimex: ending single shot time_adjust\n");
-#endif
- adjusting_time = 0;
- }
-
- /* Add up all of the frequency adjustments */
- delta_freq = time_freq + ltemp + singleshot_ppm;
-
- /*
- * Compute a new value for tb_ticks_per_sec based on
- * the frequency adjustment
- */
- den = 1000000 * (1 << (SHIFT_USEC - 8));
- if ( delta_freq < 0 ) {
- tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den;
- new_tb_ticks_per_sec = tb_ticks_per_sec + tb_ticks_per_sec_delta;
- }
- else {
- tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den;
- new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta;
- }
-
-#ifdef DEBUG_PPC_ADJTIMEX
- printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);
- printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
-#endif
-
- /*
- * Compute a new value of tb_to_xs (used to convert tb to
- * microseconds) and a new value of stamp_xsec which is the
- * time (in 1/2^20 second units) corresponding to
- * tb_orig_stamp. This new value of stamp_xsec compensates
- * for the change in frequency (implied by the new tb_to_xs)
- * which guarantees that the current time remains the same.
- */
- write_seqlock_irqsave( &xtime_lock, flags );
- tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp;
- div128_by_32(1024*1024, 0, new_tb_ticks_per_sec, &divres);
- new_tb_to_xs = divres.result_low;
- new_xsec = mulhdu(tb_ticks, new_tb_to_xs);
-
- old_xsec = mulhdu(tb_ticks, do_gtod.varp->tb_to_xs);
- new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
-
- update_gtod(do_gtod.varp->tb_orig_stamp, new_stamp_xsec, new_tb_to_xs);
-
- write_sequnlock_irqrestore( &xtime_lock, flags );
-#endif /* CONFIG_PPC64 */
-}
-
#define FEBRUARY 2
#define STARTOFTIME 1970
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 558dd069209..34714d3ea69 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -1646,10 +1646,10 @@ static void intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
KL0_SCC_CELL_ENABLE);
MACIO_BIC(KEYLARGO_FCR1,
- /*KL1_USB2_CELL_ENABLE |*/
KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
+ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+ KL1_EIDE0_ENABLE);
if (pmac_mb.board_flags & PMAC_MB_MOBILE)
MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
@@ -2183,7 +2183,7 @@ static struct pmac_mb_def pmac_mb_defs[] = {
},
{ "PowerMac10,1", "Mac mini",
PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,
+ PMAC_MB_MAY_SLEEP,
},
{ "iMac,1", "iMac (first generation)",
PMAC_TYPE_ORIG_IMAC, paddington_features,
@@ -2295,11 +2295,11 @@ static struct pmac_mb_def pmac_mb_defs[] = {
},
{ "PowerBook5,8", "PowerBook G4 15\"",
PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE,
},
{ "PowerBook5,9", "PowerBook G4 17\"",
PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE,
},
{ "PowerBook6,1", "PowerBook G4 12\"",
PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 8e6b1ed1396..8d710af5075 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -292,7 +292,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
if (start_cpu == RTAS_UNKNOWN_SERVICE)
return 1;
- status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
+ status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, pcpu);
if (status != 0) {
printk(KERN_ERR "start-cpu failed: %i\n", status);
return 0;
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 15bd9b448a4..82adb460134 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -93,15 +93,8 @@ EXPORT_SYMBOL(test_and_change_bit);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strcasecmp);
EXPORT_SYMBOL(__div64_32);
@@ -253,7 +246,6 @@ EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(cacheable_memcpy);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memchr);
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index 4344cbe9b5c..484f5bb1aa3 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -146,19 +146,6 @@ xmon_map_scc(void)
static int scc_initialized = 0;
void xmon_init_scc(void);
-extern void cuda_poll(void);
-
-static inline void do_poll_adb(void)
-{
-#ifdef CONFIG_ADB_PMU
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll_adb();
-#endif /* CONFIG_ADB_PMU */
-#ifdef CONFIG_ADB_CUDA
- if (sys_ctrler == SYS_CTRLER_CUDA)
- cuda_poll();
-#endif /* CONFIG_ADB_CUDA */
-}
int
xmon_write(void *handle, void *ptr, int nb)
@@ -189,7 +176,7 @@ xmon_write(void *handle, void *ptr, int nb)
ct = 0;
for (i = 0; i < nb; ++i) {
while ((*sccc & TXRDY) == 0)
- do_poll_adb();
+ ;
c = p[i];
if (c == '\n' && !ct) {
c = '\r';
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index b337136f28b..ce4de61ed85 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc3
-# Mon Feb 13 22:31:24 2006
+# Linux kernel version: 2.6.16-rc3-git9
+# Sat Feb 18 00:27:03 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -1317,7 +1317,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 93e44d0292a..bc9b2bcd7db 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -58,6 +58,7 @@
#include <linux/suspend.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi.h>
#include <asm/uaccess.h>
@@ -380,6 +381,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
+ rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->ref_count++;
rq->flags |= REQ_NOMERGE;
@@ -1495,40 +1497,42 @@ static int pkt_set_write_settings(struct pktcdvd_device *pd)
}
/*
- * 0 -- we can write to this track, 1 -- we can't
+ * 1 -- we can write to this track, 0 -- we can't
*/
-static int pkt_good_track(track_information *ti)
+static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
{
- /*
- * only good for CD-RW at the moment, not DVD-RW
- */
+ switch (pd->mmc3_profile) {
+ case 0x1a: /* DVD+RW */
+ case 0x12: /* DVD-RAM */
+ /* The track is always writable on DVD+RW/DVD-RAM */
+ return 1;
+ default:
+ break;
+ }
- /*
- * FIXME: only for FP
- */
- if (ti->fp == 0)
+ if (!ti->packet || !ti->fp)
return 0;
/*
* "good" settings as per Mt Fuji.
*/
- if (ti->rt == 0 && ti->blank == 0 && ti->packet == 1)
- return 0;
+ if (ti->rt == 0 && ti->blank == 0)
+ return 1;
- if (ti->rt == 0 && ti->blank == 1 && ti->packet == 1)
- return 0;
+ if (ti->rt == 0 && ti->blank == 1)
+ return 1;
- if (ti->rt == 1 && ti->blank == 0 && ti->packet == 1)
- return 0;
+ if (ti->rt == 1 && ti->blank == 0)
+ return 1;
printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
- return 1;
+ return 0;
}
/*
- * 0 -- we can write to this disc, 1 -- we can't
+ * 1 -- we can write to this disc, 0 -- we can't
*/
-static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
+static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
{
switch (pd->mmc3_profile) {
case 0x0a: /* CD-RW */
@@ -1537,10 +1541,10 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
case 0x1a: /* DVD+RW */
case 0x13: /* DVD-RW */
case 0x12: /* DVD-RAM */
- return 0;
+ return 1;
default:
VPRINTK("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
- return 1;
+ return 0;
}
/*
@@ -1549,25 +1553,25 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
*/
if (di->disc_type == 0xff) {
printk("pktcdvd: Unknown disc. No track?\n");
- return 1;
+ return 0;
}
if (di->disc_type != 0x20 && di->disc_type != 0) {
printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type);
- return 1;
+ return 0;
}
if (di->erasable == 0) {
printk("pktcdvd: Disc not erasable\n");
- return 1;
+ return 0;
}
if (di->border_status == PACKET_SESSION_RESERVED) {
printk("pktcdvd: Can't write to last track (reserved)\n");
- return 1;
+ return 0;
}
- return 0;
+ return 1;
}
static int pkt_probe_settings(struct pktcdvd_device *pd)
@@ -1592,23 +1596,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
return ret;
}
- if (pkt_good_disc(pd, &di))
- return -ENXIO;
+ if (!pkt_writable_disc(pd, &di))
+ return -EROFS;
- switch (pd->mmc3_profile) {
- case 0x1a: /* DVD+RW */
- printk("pktcdvd: inserted media is DVD+RW\n");
- break;
- case 0x13: /* DVD-RW */
- printk("pktcdvd: inserted media is DVD-RW\n");
- break;
- case 0x12: /* DVD-RAM */
- printk("pktcdvd: inserted media is DVD-RAM\n");
- break;
- default:
- printk("pktcdvd: inserted media is CD-R%s\n", di.erasable ? "W" : "");
- break;
- }
pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR;
track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
@@ -1617,9 +1607,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
return ret;
}
- if (pkt_good_track(&ti)) {
+ if (!pkt_writable_track(pd, &ti)) {
printk("pktcdvd: can't write to this track\n");
- return -ENXIO;
+ return -EROFS;
}
/*
@@ -1633,7 +1623,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
}
if (pd->settings.size > PACKET_MAX_SECTORS) {
printk("pktcdvd: packet size is too big\n");
- return -ENXIO;
+ return -EROFS;
}
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -1675,7 +1665,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
break;
default:
printk("pktcdvd: unknown data mode\n");
- return 1;
+ return -EROFS;
}
return 0;
}
@@ -1886,7 +1876,7 @@ static int pkt_open_write(struct pktcdvd_device *pd)
if ((ret = pkt_probe_settings(pd))) {
VPRINTK("pktcdvd: %s failed probe\n", pd->name);
- return -EROFS;
+ return ret;
}
if ((ret = pkt_set_write_settings(pd))) {
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 486ed8a11b5..a4d425d2dce 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -15,22 +15,23 @@ config AGP
due to kernel allocation issues), you could use PCI accesses
and have up to a couple gigs of texture space.
- Note that this is the only means to have XFree4/GLX use
+ Note that this is the only means to have X/GLX use
write-combining with MTRR support on the AGP bus. Without it, OpenGL
direct rendering will be a lot slower but still faster than PIO.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
To compile this driver as a module, choose M here: the
module will be called agpgart.
+ You should say Y here if you want to use GLX or DRI.
+
+ If unsure, say N.
+
config AGP_ALI
tristate "ALI chipset support"
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
+ X on the following ALi chipsets. The supported chipsets
include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
For the ALi-chipset question, ALi suggests you refer to
<http://www.ali.com.tw/eng/support/index.shtml>.
@@ -40,28 +41,19 @@ config AGP_ALI
timing issues, this chipset cannot do AGP 2x with the G200.
This is a hardware limitation. AGP 1x seems to be fine, though.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
config AGP_ATI
tristate "ATI chipset support"
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.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ This option gives you AGP support for the GLX component of
+ X on the ATI RadeonIGP family of chipsets.
config AGP_AMD
tristate "AMD Irongate, 761, and 762 chipset support"
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.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ X on AMD Irongate, 761, and 762 chipsets.
config AGP_AMD64
tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
@@ -69,45 +61,38 @@ config AGP_AMD64
default y if GART_IOMMU
help
This option gives you AGP support for the GLX component of
- XFree86 4.x using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
+ X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
You still need an external AGP bridge like the AMD 8151, VIA
K8T400M, SiS755. It may also support other AGP bridges when loaded
with agp_try_unsupported=1.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y
config AGP_INTEL
tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
depends on AGP && X86
help
- This option gives you AGP support for the GLX component of XFree86 4.x
+ This option gives you AGP support for the GLX component of X
on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
- E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G,
- 852GM, 855GM, 865G and I915 integrated graphics chipsets.
+ E7205 and E7505 chipsets and full support for the 810, 815, 830M,
+ 845G, 852GM, 855GM, 865G and I915 integrated graphics chipsets.
+
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI, or if you have any Intel integrated graphics
- chipsets. If unsure, say Y.
config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
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
- include nForce and nForce2
+ X on NVIDIA chipsets including nForce and nForce2
config AGP_SIS
tristate "SiS chipset support"
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.
+ X on Silicon Integrated Systems [SiS] chipsets.
Note that 5591/5592 AGP chipsets are NOT supported.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
config AGP_SWORKS
tristate "Serverworks LE/HE chipset support"
@@ -121,10 +106,7 @@ config AGP_VIA
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.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ X on VIA MVP3/Apollo Pro chipsets.
config AGP_I460
tristate "Intel 460GX chipset support"
@@ -159,9 +141,6 @@ config AGP_EFFICEON
This option gives you AGP support for the Transmeta Efficeon
series processors with integrated northbridges.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y.
-
config AGP_SGI_TIOCA
tristate "SGI TIO chipset AGP support"
depends on AGP && (IA64_SGI_SN2 || IA64_GENERIC)
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 9964c508c11..1251b2515bb 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -516,8 +516,10 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
- if ( (apbase & 0x7fff) >> (32 - 25) )
- return -ENODEV;
+ if ( (apbase & 0x7fff) >> (32 - 25) ) {
+ printk(KERN_INFO PFX "aperture base > 4G\n");
+ return -ENODEV;
+ }
apbase = (apbase & 0x7fff) << 25;
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 268f78d926d..efef9999f1c 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -468,9 +468,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
switch (pdev->device) {
case 0x0006:
- /* ServerWorks CNB20HE
- Fail silently.*/
- printk (KERN_ERR PFX "Detected ServerWorks CNB20HE chipset: No AGP present.\n");
+ printk (KERN_ERR PFX "ServerWorks CNB20HE is unsupported due to lack of documentation.\n");
return -ENODEV;
case PCI_DEVICE_ID_SERVERWORKS_HE:
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5765f672e85..d58f8231885 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -243,7 +243,7 @@ static struct sysrq_key_op sysrq_term_op = {
static void moom_callback(void *ignored)
{
- out_of_memory(GFP_KERNEL, 0);
+ out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0);
}
static DECLARE_WORK(moom_work, moom_callback, NULL);
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 5c8943509cc..66d03f242d3 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -1053,7 +1053,7 @@ static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
int i;
fcmd = &_fcmd;
- memset(fcmd, 0, sizeof(fcmd));
+ memset(fcmd, 0, sizeof(fcp_cmnd));
FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
fch = &fcmd->fch;
FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 18d7eda3885..c2c776fbda0 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2082,9 +2082,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
SBP2_DEBUG("sbp2_check_sbp2_response");
- switch (SCpnt->cmnd[0]) {
-
- case INQUIRY:
+ if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
/*
* Make sure data length is ok. Minimum length is 36 bytes
*/
@@ -2097,13 +2095,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
*/
scsi_buf[2] |= 2;
scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-
- break;
-
- default:
- break;
}
- return;
}
/*
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 69c04945591..ded2c33f5b8 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1019,8 +1019,8 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
INVALIDATE_CACHED_RANGE(map, from, size)
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
- UDELAY(map, chip, adr, usec)
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \
+ UDELAY(map, chip, cmd_adr, usec)
/*
* Extra notes:
@@ -1052,7 +1052,7 @@ do { \
spin_lock(chip->mutex); \
} while (0)
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \
do { \
spin_unlock(chip->mutex); \
INVALIDATE_CACHED_RANGE(map, adr, len); \
@@ -1284,7 +1284,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
map_write(map, datum, adr);
chip->state = mode;
- INVALIDATE_CACHE_UDELAY(map, chip,
+ INVALIDATE_CACHE_UDELAY(map, chip, adr,
adr, map_bankwidth(map),
chip->word_write_time);
@@ -1572,8 +1572,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
map_write(map, CMD(0xd0), cmd_adr);
chip->state = FL_WRITING;
- INVALIDATE_CACHE_UDELAY(map, chip,
- cmd_adr, len,
+ INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr,
+ adr, len,
chip->buffer_write_time);
timeo = jiffies + (HZ/2);
@@ -1744,7 +1744,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->state = FL_ERASING;
chip->erase_suspended = 0;
- INVALIDATE_CACHE_UDELAY(map, chip,
+ INVALIDATE_CACHE_UDELAY(map, chip, adr,
adr, len,
chip->erase_time*1000/2);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index fa176ffb4ad..8936058a3cc 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -108,6 +108,7 @@ static void irda_usb_close(struct irda_usb_cb *self);
static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void irda_usb_receive(struct urb *urb, struct pt_regs *regs);
+static void irda_usb_rx_defer_expired(unsigned long data);
static int irda_usb_net_open(struct net_device *dev);
static int irda_usb_net_close(struct net_device *dev);
static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -677,6 +678,12 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* on the interrupt pipe and hang the Rx URB only when an interrupt is
* received.
* Jean II
+ *
+ * Note : don't read the above as what we are currently doing, but as
+ * something we could do with KC dongle. Also don't forget that the
+ * interrupt pipe is not part of the original standard, so this would
+ * need to be optional...
+ * Jean II
*/
/*------------------------------------------------------------------*/
@@ -704,10 +711,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
/* Reinitialize URB */
usb_fill_bulk_urb(urb, self->usbdev,
usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep),
- skb->data, skb->truesize,
+ skb->data, IRDA_SKB_MAX_MTU,
irda_usb_receive, skb);
- /* Note : unlink *must* be synchronous because of the code in
- * irda_usb_net_close() -> free the skb - Jean II */
urb->status = 0;
/* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */
@@ -734,6 +739,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
struct irda_skb_cb *cb;
struct sk_buff *newskb;
struct sk_buff *dataskb;
+ struct urb *next_urb;
int docopy;
IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
@@ -755,20 +761,37 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
if (urb->status != 0) {
switch (urb->status) {
case -EILSEQ:
- self->stats.rx_errors++;
self->stats.rx_crc_errors++;
- break;
+ /* Also precursor to a hot-unplug on UHCI. */
+ /* Fallthrough... */
case -ECONNRESET: /* -104 */
- IRDA_DEBUG(0, "%s(), Connection Reset (-104), transfer_flags 0x%04X \n", __FUNCTION__, urb->transfer_flags);
+ /* Random error, if I remember correctly */
/* uhci_cleanup_unlink() is going to kill the Rx
* URB just after we return. No problem, at this
* point the URB will be idle ;-) - Jean II */
- break;
+ case -ESHUTDOWN: /* -108 */
+ /* That's usually a hot-unplug. Submit will fail... */
+ case -ETIMEDOUT: /* -110 */
+ /* Usually precursor to a hot-unplug on OHCI. */
default:
- IRDA_DEBUG(0, "%s(), RX status %d,transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
+ self->stats.rx_errors++;
+ IRDA_DEBUG(0, "%s(), RX status %d, transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
break;
}
- goto done;
+ /* If we received an error, we don't want to resubmit the
+ * Rx URB straight away but to give the USB layer a little
+ * bit of breathing room.
+ * We are in the USB thread context, therefore there is a
+ * danger of recursion (new URB we submit fails, we come
+ * back here).
+ * With recent USB stack (2.6.15+), I'm seeing that on
+ * hot unplug of the dongle...
+ * Lowest effective timer is 10ms...
+ * Jean II */
+ self->rx_defer_timer.function = &irda_usb_rx_defer_expired;
+ self->rx_defer_timer.data = (unsigned long) urb;
+ mod_timer(&self->rx_defer_timer, jiffies + (10 * HZ / 1000));
+ return;
}
/* Check for empty frames */
@@ -845,13 +868,45 @@ done:
* idle slot....
* Jean II */
/* Note : with this scheme, we could submit the idle URB before
- * processing the Rx URB. Another time... Jean II */
+ * processing the Rx URB. I don't think it would buy us anything as
+ * we are running in the USB thread context. Jean II */
+ next_urb = self->idle_rx_urb;
- /* Submit the idle URB to replace the URB we've just received */
- irda_usb_submit(self, skb, self->idle_rx_urb);
/* Recycle Rx URB : Now, the idle URB is the present one */
urb->context = NULL;
self->idle_rx_urb = urb;
+
+ /* Submit the idle URB to replace the URB we've just received.
+ * Do it last to avoid race conditions... Jean II */
+ irda_usb_submit(self, skb, next_urb);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * In case of errors, we want the USB layer to have time to recover.
+ * Now, it is time to resubmit ouur Rx URB...
+ */
+static void irda_usb_rx_defer_expired(unsigned long data)
+{
+ struct urb *urb = (struct urb *) data;
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
+ struct irda_usb_cb *self;
+ struct irda_skb_cb *cb;
+ struct urb *next_urb;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+ /* Find ourselves */
+ cb = (struct irda_skb_cb *) skb->cb;
+ IRDA_ASSERT(cb != NULL, return;);
+ self = (struct irda_usb_cb *) cb->context;
+ IRDA_ASSERT(self != NULL, return;);
+
+ /* Same stuff as when Rx is done, see above... */
+ next_urb = self->idle_rx_urb;
+ urb->context = NULL;
+ self->idle_rx_urb = urb;
+ irda_usb_submit(self, skb, next_urb);
}
/*------------------------------------------------------------------*/
@@ -990,6 +1045,9 @@ static int irda_usb_net_close(struct net_device *netdev)
/* Stop network Tx queue */
netif_stop_queue(netdev);
+ /* Kill defered Rx URB */
+ del_timer(&self->rx_defer_timer);
+
/* Deallocate all the Rx path buffers (URBs and skb) */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
struct urb *urb = self->rx_urb[i];
@@ -1365,6 +1423,7 @@ static int irda_usb_probe(struct usb_interface *intf,
self = net->priv;
self->netdev = net;
spin_lock_init(&self->lock);
+ init_timer(&self->rx_defer_timer);
/* Create all of the needed urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
@@ -1498,6 +1557,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
* This will stop/desactivate the Tx path. - Jean II */
self->present = 0;
+ /* Kill defered Rx URB */
+ del_timer(&self->rx_defer_timer);
+
/* We need to have irq enabled to unlink the URBs. That's OK,
* at this point the Tx path is gone - Jean II */
spin_unlock_irqrestore(&self->lock, flags);
@@ -1507,11 +1569,11 @@ static void irda_usb_disconnect(struct usb_interface *intf)
/* Accept no more transmissions */
/*netif_device_detach(self->netdev);*/
netif_stop_queue(self->netdev);
- /* Stop all the receive URBs */
+ /* Stop all the receive URBs. Must be synchronous. */
for (i = 0; i < IU_MAX_RX_URBS; i++)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
- * Toggle flags to make sure it's synchronous. */
+ * Make sure it's synchronous to avoid races. */
usb_kill_urb(self->tx_urb);
usb_kill_urb(self->speed_urb);
}
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index bd8f6654232..4026af42dd4 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -136,8 +136,6 @@ struct irda_usb_cb {
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
- wait_queue_head_t wait_q; /* for timeouts */
-
struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
@@ -147,17 +145,18 @@ struct irda_usb_cb {
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos;
- hashbin_t *tx_list; /* Queued transmit skb's */
char *speed_buff; /* Buffer for speed changes */
struct timeval stamp;
struct timeval now;
- spinlock_t lock; /* For serializing operations */
+ spinlock_t lock; /* For serializing Tx operations */
__u16 xbofs; /* Current xbofs setting */
__s16 new_xbofs; /* xbofs we need to set */
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
+
+ struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
};
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 14beab4bc91..287676ad80d 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4616,9 +4616,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
}
default:
- IPW_ERROR("Unknown notification: "
- "subtype=%d,flags=0x%2x,size=%d\n",
- notif->subtype, notif->flags, notif->size);
+ IPW_DEBUG_NOTIF("Unknown notification: "
+ "subtype=%d,flags=0x%2x,size=%d\n",
+ notif->subtype, notif->flags, notif->size);
}
}
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6912399d093..6f50cc9323d 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -55,21 +55,13 @@ config DASD_DIAG
Disks under VM. If you are not running under VM or unsure what it is,
say "N".
-config DASD_EER
- tristate "Extended error reporting (EER)"
- depends on DASD
- help
- This driver provides a character device interface to the
- DASD extended error reporting. This is only needed if you want to
- use applications written for the EER facility.
-
config DASD_CMB
tristate "Compatibility interface for DASD channel measurement blocks"
depends on DASD
help
- This driver provides an additional interface to the channel
- measurement facility, which is normally accessed though sysfs, with
- a set of ioctl functions specific to the dasd driver.
+ This driver provides an additional interface to the channel measurement
+ facility, which is normally accessed though sysfs, with a set of
+ ioctl functions specific to the dasd driver.
This is only needed if you want to use applications written for
linux-2.4 dasd channel measurement facility interface.
diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile
index 0c0d871e8f5..58c6780134f 100644
--- a/drivers/s390/block/Makefile
+++ b/drivers/s390/block/Makefile
@@ -5,7 +5,6 @@
dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o
dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o
dasd_diag_mod-objs := dasd_diag.o
-dasd_eer_mod-objs := dasd_eer.o
dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \
dasd_genhd.o dasd_erp.o
@@ -14,6 +13,5 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o
obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o
obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o
obj-$(CONFIG_DASD_CMB) += dasd_cmb.o
-obj-$(CONFIG_DASD_EER) += dasd_eer.o
obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
obj-$(CONFIG_DCSSBLK) += dcssblk.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 08c88fcd896..af1d5b404ce 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/buffer_head.h>
#include <linux/hdreg.h>
-#include <linux/notifier.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -58,7 +57,6 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
static void dasd_flush_ccw_queue(struct dasd_device *, int);
static void dasd_tasklet(struct dasd_device *);
static void do_kick_device(void *data);
-static void dasd_disable_eer(struct dasd_device *device);
/*
* SECTION: Operations on the device structure.
@@ -153,10 +151,13 @@ dasd_state_new_to_known(struct dasd_device *device)
static inline void
dasd_state_known_to_new(struct dasd_device * device)
{
- /* disable extended error reporting for this device */
- dasd_disable_eer(device);
/* Forget the discipline information. */
+ if (device->discipline)
+ module_put(device->discipline->owner);
device->discipline = NULL;
+ if (device->base_discipline)
+ module_put(device->base_discipline->owner);
+ device->base_discipline = NULL;
device->state = DASD_STATE_NEW;
dasd_free_queue(device);
@@ -871,9 +872,6 @@ dasd_handle_state_change_pending(struct dasd_device *device)
struct dasd_ccw_req *cqr;
struct list_head *l, *n;
- /* first of all call extended error reporting */
- dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL);
-
device->stopped &= ~DASD_STOPPED_PENDING;
/* restart all 'running' IO on queue */
@@ -1093,19 +1091,6 @@ restart:
}
goto restart;
}
-
- /* first of all call extended error reporting */
- if (device->eer && cqr->status == DASD_CQR_FAILED) {
- dasd_write_eer_trigger(DASD_EER_FATALERROR,
- device, cqr);
-
- /* restart request */
- cqr->status = DASD_CQR_QUEUED;
- cqr->retries = 255;
- device->stopped |= DASD_STOPPED_QUIESCE;
- goto restart;
- }
-
/* Process finished ERP request. */
if (cqr->refers) {
__dasd_process_erp(device, cqr);
@@ -1243,8 +1228,7 @@ __dasd_start_head(struct dasd_device * device)
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
/* check FAILFAST */
if (device->stopped & ~DASD_STOPPED_PENDING &&
- test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
- (!device->eer)) {
+ test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
cqr->status = DASD_CQR_FAILED;
dasd_schedule_bh(device);
}
@@ -1880,9 +1864,10 @@ dasd_generic_remove (struct ccw_device *cdev)
*/
int
dasd_generic_set_online (struct ccw_device *cdev,
- struct dasd_discipline *discipline)
+ struct dasd_discipline *base_discipline)
{
+ struct dasd_discipline *discipline;
struct dasd_device *device;
int rc;
@@ -1890,6 +1875,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
if (IS_ERR(device))
return PTR_ERR(device);
+ discipline = base_discipline;
if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
@@ -1901,6 +1887,16 @@ dasd_generic_set_online (struct ccw_device *cdev,
}
discipline = dasd_diag_discipline_pointer;
}
+ if (!try_module_get(base_discipline->owner)) {
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ if (!try_module_get(discipline->owner)) {
+ module_put(base_discipline->owner);
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ device->base_discipline = base_discipline;
device->discipline = discipline;
rc = discipline->check_device(device);
@@ -1909,6 +1905,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
"dasd_generic couldn't online device %s "
"with discipline %s rc=%i\n",
cdev->dev.bus_id, discipline->name, rc);
+ module_put(discipline->owner);
+ module_put(base_discipline->owner);
dasd_delete_device(device);
return rc;
}
@@ -1986,9 +1984,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
switch (event) {
case CIO_GONE:
case CIO_NO_PATH:
- /* first of all call extended error reporting */
- dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL);
-
if (device->state < DASD_STATE_BASIC)
break;
/* Device is active. We want to keep it. */
@@ -2046,51 +2041,6 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
put_driver(drv);
}
-/*
- * notifications for extended error reports
- */
-static struct notifier_block *dasd_eer_chain;
-
-int
-dasd_register_eer_notifier(struct notifier_block *nb)
-{
- return notifier_chain_register(&dasd_eer_chain, nb);
-}
-
-int
-dasd_unregister_eer_notifier(struct notifier_block *nb)
-{
- return notifier_chain_unregister(&dasd_eer_chain, nb);
-}
-
-/*
- * Notify the registered error reporting module of a problem
- */
-void
-dasd_write_eer_trigger(unsigned int id, struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- if (device->eer) {
- struct dasd_eer_trigger temp;
- temp.id = id;
- temp.device = device;
- temp.cqr = cqr;
- notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER,
- (void *)&temp);
- }
-}
-
-/*
- * Tell the registered error reporting module to disable error reporting for
- * a given device and to cleanup any private data structures on that device.
- */
-static void
-dasd_disable_eer(struct dasd_device *device)
-{
- notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device);
-}
-
-
static int __init
dasd_init(void)
{
@@ -2172,11 +2122,6 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online);
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
-EXPORT_SYMBOL(dasd_register_eer_notifier);
-EXPORT_SYMBOL(dasd_unregister_eer_notifier);
-EXPORT_SYMBOL(dasd_write_eer_trigger);
-
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index c811380b907..4ee0f934e32 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1108,9 +1108,6 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
case 0x0B:
DEV_MESSAGE(KERN_WARNING, device, "%s",
"FORMAT F - Volume is suspended duplex");
- /* call extended error reporting (EER) */
- dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device,
- erp->refers);
break;
case 0x0C:
DEV_MESSAGE(KERN_WARNING, device, "%s",
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index e15dd797805..bc3823d3522 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -29,7 +29,6 @@
#define DASD_ECKD_CCW_PSF 0x27
#define DASD_ECKD_CCW_RSSD 0x3e
#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
-#define DASD_ECKD_CCW_SNSS 0x54
#define DASD_ECKD_CCW_DEFINE_EXTENT 0x63
#define DASD_ECKD_CCW_WRITE_MT 0x85
#define DASD_ECKD_CCW_READ_MT 0x86
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
deleted file mode 100644
index f70cd7716b2..00000000000
--- a/drivers/s390/block/dasd_eer.c
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- * character device driver for extended error reporting
- *
- *
- * Copyright (C) 2005 IBM Corporation
- * extended error reporting for DASD ECKD devices
- * Author(s): Stefan Weinhuber <wein@de.ibm.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <linux/notifier.h>
-
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-#include <asm/atomic.h>
-#include <asm/ebcdic.h>
-
-#include "dasd_int.h"
-#include "dasd_eckd.h"
-
-
-MODULE_LICENSE("GPL");
-
-MODULE_AUTHOR("Stefan Weinhuber <wein@de.ibm.com>");
-MODULE_DESCRIPTION("DASD extended error reporting module");
-
-
-#ifdef PRINTK_HEADER
-#undef PRINTK_HEADER
-#endif /* PRINTK_HEADER */
-#define PRINTK_HEADER "dasd(eer):"
-
-
-
-
-
-/*****************************************************************************/
-/* the internal buffer */
-/*****************************************************************************/
-
-/*
- * The internal buffer is meant to store obaque blobs of data, so it doesn't
- * know of higher level concepts like triggers.
- * It consists of a number of pages that are used as a ringbuffer. Each data
- * blob is stored in a simple record that consists of an integer, which
- * contains the size of the following data, and the data bytes themselfes.
- *
- * To allow for multiple independent readers we create one internal buffer
- * each time the device is opened and destroy the buffer when the file is
- * closed again.
- *
- * One record can be written to a buffer by using the functions
- * - dasd_eer_start_record (one time per record to write the size to the buffer
- * and reserve the space for the data)
- * - dasd_eer_write_buffer (one or more times per record to write the data)
- * The data can be written in several steps but you will have to compute
- * the total size up front for the invocation of dasd_eer_start_record.
- * If the ringbuffer is full, dasd_eer_start_record will remove the required
- * number of old records.
- *
- * A record is typically read in two steps, first read the integer that
- * specifies the size of the following data, then read the data.
- * Both can be done by
- * - dasd_eer_read_buffer
- *
- * For all mentioned functions you need to get the bufferlock first and keep it
- * until a complete record is written or read.
- */
-
-
-/*
- * Alle information necessary to keep track of an internal buffer is kept in
- * a struct eerbuffer. The buffer specific to a file pointer is strored in
- * the private_data field of that file. To be able to write data to all
- * existing buffers, each buffer is also added to the bufferlist.
- * If the user doesn't want to read a complete record in one go, we have to
- * keep track of the rest of the record. residual stores the number of bytes
- * that are still to deliver. If the rest of the record is invalidated between
- * two reads then residual will be set to -1 so that the next read will fail.
- * All entries in the eerbuffer structure are protected with the bufferlock.
- * To avoid races between writing to a buffer on the one side and creating
- * and destroying buffers on the other side, the bufferlock must also be used
- * to protect the bufferlist.
- */
-
-struct eerbuffer {
- struct list_head list;
- char **buffer;
- int buffersize;
- int buffer_page_count;
- int head;
- int tail;
- int residual;
-};
-
-LIST_HEAD(bufferlist);
-
-static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED;
-
-DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
-
-/*
- * How many free bytes are available on the buffer.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_get_free_bytes(struct eerbuffer *eerb)
-{
- if (eerb->head < eerb->tail) {
- return eerb->tail - eerb->head - 1;
- } else
- return eerb->buffersize - eerb->head + eerb->tail -1;
-}
-
-/*
- * How many bytes of buffer space are used.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_get_filled_bytes(struct eerbuffer *eerb)
-{
-
- if (eerb->head >= eerb->tail) {
- return eerb->head - eerb->tail;
- } else
- return eerb->buffersize - eerb->tail + eerb->head;
-}
-
-/*
- * The dasd_eer_write_buffer function just copies count bytes of data
- * to the buffer. Make sure to call dasd_eer_start_record first, to
- * make sure that enough free space is available.
- * needs to be called with bufferlock held
- */
-static void
-dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data)
-{
-
- unsigned long headindex,localhead;
- unsigned long rest, len;
- char *nextdata;
-
- nextdata = data;
- rest = count;
- while (rest > 0) {
- headindex = eerb->head / PAGE_SIZE;
- localhead = eerb->head % PAGE_SIZE;
- len = min(rest, (PAGE_SIZE - localhead));
- memcpy(eerb->buffer[headindex]+localhead, nextdata, len);
- nextdata += len;
- rest -= len;
- eerb->head += len;
- if ( eerb->head == eerb->buffersize )
- eerb->head = 0; /* wrap around */
- if (eerb->head > eerb->buffersize) {
- MESSAGE(KERN_ERR, "%s", "runaway buffer head.");
- BUG();
- }
- }
-}
-
-/*
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data)
-{
-
- unsigned long tailindex,localtail;
- unsigned long rest, len, finalcount;
- char *nextdata;
-
- finalcount = min(count, dasd_eer_get_filled_bytes(eerb));
- nextdata = data;
- rest = finalcount;
- while (rest > 0) {
- tailindex = eerb->tail / PAGE_SIZE;
- localtail = eerb->tail % PAGE_SIZE;
- len = min(rest, (PAGE_SIZE - localtail));
- memcpy(nextdata, eerb->buffer[tailindex]+localtail, len);
- nextdata += len;
- rest -= len;
- eerb->tail += len;
- if ( eerb->tail == eerb->buffersize )
- eerb->tail = 0; /* wrap around */
- if (eerb->tail > eerb->buffersize) {
- MESSAGE(KERN_ERR, "%s", "runaway buffer tail.");
- BUG();
- }
- }
- return finalcount;
-}
-
-/*
- * Whenever you want to write a blob of data to the internal buffer you
- * have to start by using this function first. It will write the number
- * of bytes that will be written to the buffer. If necessary it will remove
- * old records to make room for the new one.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_start_record(struct eerbuffer *eerb, int count)
-{
- int tailcount;
- if (count + sizeof(count) > eerb->buffersize)
- return -ENOMEM;
- while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) {
- if (eerb->residual > 0) {
- eerb->tail += eerb->residual;
- if (eerb->tail >= eerb->buffersize)
- eerb->tail -= eerb->buffersize;
- eerb->residual = -1;
- }
- dasd_eer_read_buffer(eerb, sizeof(tailcount),
- (char*)(&tailcount));
- eerb->tail += tailcount;
- if (eerb->tail >= eerb->buffersize)
- eerb->tail -= eerb->buffersize;
- }
- dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count));
-
- return 0;
-};
-
-/*
- * release pages that are not used anymore
- */
-static void
-dasd_eer_free_buffer_pages(char **buf, int no_pages)
-{
- int i;
-
- for (i = 0; i < no_pages; ++i) {
- free_page((unsigned long)buf[i]);
- }
-}
-
-/*
- * allocate a new set of memory pages
- */
-static int
-dasd_eer_allocate_buffer_pages(char **buf, int no_pages)
-{
- int i;
-
- for (i = 0; i < no_pages; ++i) {
- buf[i] = (char *) get_zeroed_page(GFP_KERNEL);
- if (!buf[i]) {
- dasd_eer_free_buffer_pages(buf, i);
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-/*
- * empty the buffer by resetting head and tail
- * In case there is a half read data blob in the buffer, we set residual
- * to -1 to indicate that the remainder of the blob is lost.
- */
-static void
-dasd_eer_purge_buffer(struct eerbuffer *eerb)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&bufferlock, flags);
- if (eerb->residual > 0)
- eerb->residual = -1;
- eerb->tail=0;
- eerb->head=0;
- spin_unlock_irqrestore(&bufferlock, flags);
-}
-
-/*
- * set the size of the buffer, newsize is the new number of pages to be used
- * we don't try to copy any data back an forth, so any resize will also purge
- * the buffer
- */
-static int
-dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize)
-{
- int i, oldcount, reuse;
- char **new;
- char **old;
- unsigned long flags;
-
- if (newsize < 1)
- return -EINVAL;
- if (eerb->buffer_page_count == newsize) {
- /* documented behaviour is that any successfull invocation
- * will purge all records */
- dasd_eer_purge_buffer(eerb);
- return 0;
- }
- new = kmalloc(newsize*sizeof(char*), GFP_KERNEL);
- if (!new)
- return -ENOMEM;
-
- reuse=min(eerb->buffer_page_count, newsize);
- for (i = 0; i < reuse; ++i) {
- new[i] = eerb->buffer[i];
- }
- if (eerb->buffer_page_count < newsize) {
- if (dasd_eer_allocate_buffer_pages(
- &new[eerb->buffer_page_count],
- newsize - eerb->buffer_page_count)) {
- kfree(new);
- return -ENOMEM;
- }
- }
-
- spin_lock_irqsave(&bufferlock, flags);
- old = eerb->buffer;
- eerb->buffer = new;
- if (eerb->residual > 0)
- eerb->residual = -1;
- eerb->tail = 0;
- eerb->head = 0;
- oldcount = eerb->buffer_page_count;
- eerb->buffer_page_count = newsize;
- spin_unlock_irqrestore(&bufferlock, flags);
-
- if (oldcount > newsize) {
- for (i = newsize; i < oldcount; ++i) {
- free_page((unsigned long)old[i]);
- }
- }
- kfree(old);
-
- return 0;
-}
-
-
-/*****************************************************************************/
-/* The extended error reporting functionality */
-/*****************************************************************************/
-
-/*
- * When a DASD device driver wants to report an error, it calls the
- * function dasd_eer_write_trigger (via a notifier mechanism) and gives the
- * respective trigger ID as parameter.
- * Currently there are four kinds of triggers:
- *
- * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems
- * DASD_EER_PPRCSUSPEND: PPRC was suspended
- * DASD_EER_NOPATH: There is no path to the device left.
- * DASD_EER_STATECHANGE: The state of the device has changed.
- *
- * For the first three triggers all required information can be supplied by
- * the caller. For these triggers a record is written by the function
- * dasd_eer_write_standard_trigger.
- *
- * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE
- * trigger, we have to gather the necessary sense data first. We cannot queue
- * the necessary SNSS (sense subsystem status) request immediatly, since we
- * are likely to run in a deadlock situation. Instead, we schedule a
- * work_struct that calls the function dasd_eer_sense_subsystem_status to
- * create and start an SNSS request asynchronously.
- *
- * To avoid memory allocations at runtime, the necessary memory is allocated
- * when the extended error reporting is enabled for a device (by
- * dasd_eer_probe). There is one private eer data structure for each eer
- * enabled DASD device. It contains memory for the work_struct, one SNSS cqr
- * and a flags field that is used to coordinate the use of the cqr. The call
- * to write a state change trigger can come in at any time, so we have one flag
- * CQR_IN_USE that protects the cqr itself. When this flag indicates that the
- * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a
- * second request but sets the SNSS_REQUESTED flag instead.
- *
- * When the request is finished, the callback function dasd_eer_SNSS_cb
- * is called. This function will invoke the function
- * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also
- * check the SNSS_REQUESTED flag and if it is set it will call
- * dasd_eer_sense_subsystem_status again.
- *
- * To avoid race conditions during the handling of the lock, the flags must
- * be protected by the snsslock.
- */
-
-struct dasd_eer_private {
- struct dasd_ccw_req *cqr;
- unsigned long flags;
- struct work_struct worker;
-};
-
-static void dasd_eer_destroy(struct dasd_device *device,
- struct dasd_eer_private *eer);
-static int
-dasd_eer_write_trigger(struct dasd_eer_trigger *trigger);
-static void dasd_eer_sense_subsystem_status(void *data);
-static int dasd_eer_notify(struct notifier_block *self,
- unsigned long action, void *data);
-
-struct workqueue_struct *dasd_eer_workqueue;
-
-#define SNSS_DATA_SIZE 44
-static spinlock_t snsslock = SPIN_LOCK_UNLOCKED;
-
-#define DASD_EER_BUSID_SIZE 10
-struct dasd_eer_header {
- __u32 total_size;
- __u32 trigger;
- __u64 tv_sec;
- __u64 tv_usec;
- char busid[DASD_EER_BUSID_SIZE];
-} __attribute__ ((packed));
-
-static struct notifier_block dasd_eer_nb = {
- .notifier_call = dasd_eer_notify,
-};
-
-/*
- * flags for use with dasd_eer_private
- */
-#define CQR_IN_USE 0
-#define SNSS_REQUESTED 1
-
-/*
- * This function checks if extended error reporting is available for a given
- * dasd_device. If yes, then it creates and returns a struct dasd_eer,
- * otherwise it returns an -EPERM error pointer.
- */
-struct dasd_eer_private *
-dasd_eer_probe(struct dasd_device *device)
-{
- struct dasd_eer_private *private;
-
- if (!(device && device->discipline
- && !strcmp(device->discipline->name, "ECKD"))) {
- return ERR_PTR(-EPERM);
- }
- /* allocate the private data structure */
- private = (struct dasd_eer_private *)kmalloc(
- sizeof(struct dasd_eer_private), GFP_KERNEL);
- if (!private) {
- return ERR_PTR(-ENOMEM);
- }
- INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status,
- (void *)device);
- private->cqr = dasd_kmalloc_request("ECKD",
- 1 /* SNSS */ ,
- SNSS_DATA_SIZE ,
- device);
- if (!private->cqr) {
- kfree(private);
- return ERR_PTR(-ENOMEM);
- }
- private->flags = 0;
- return private;
-};
-
-/*
- * If our private SNSS request is queued, remove it from the
- * dasd ccw queue so we can free the requests memory.
- */
-static void
-dasd_eer_dequeue_SNSS_request(struct dasd_device *device,
- struct dasd_eer_private *eer)
-{
- struct list_head *lst, *nxt;
- struct dasd_ccw_req *cqr, *erpcqr;
- dasd_erp_fn_t erp_fn;
-
- spin_lock_irq(get_ccwdev_lock(device->cdev));
- list_for_each_safe(lst, nxt, &device->ccw_queue) {
- cqr = list_entry(lst, struct dasd_ccw_req, list);
- /* we are looking for two kinds or requests */
- /* first kind: our SNSS request: */
- if (cqr == eer->cqr) {
- if (cqr->status == DASD_CQR_IN_IO)
- device->discipline->term_IO(cqr);
- list_del(&cqr->list);
- break;
- }
- /* second kind: ERP requests for our SNSS request */
- if (cqr->refers) {
- /* If this erp request chain ends in our cqr, then */
- /* cal the erp_postaction to clean it up */
- erpcqr = cqr;
- while (erpcqr->refers) {
- erpcqr = erpcqr->refers;
- }
- if (erpcqr == eer->cqr) {
- erp_fn = device->discipline->erp_postaction(
- cqr);
- erp_fn(cqr);
- }
- continue;
- }
- }
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
-}
-
-/*
- * This function dismantles a struct dasd_eer that was created by
- * dasd_eer_probe. Since we want to free our private data structure,
- * we must make sure that the memory is not in use anymore.
- * We have to flush the work queue and remove a possible SNSS request
- * from the dasd queue.
- */
-static void
-dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer)
-{
- flush_workqueue(dasd_eer_workqueue);
- dasd_eer_dequeue_SNSS_request(device, eer);
- dasd_kfree_request(eer->cqr, device);
- kfree(eer);
-};
-
-/*
- * enable the extended error reporting for a particular device
- */
-static int
-dasd_eer_enable_on_device(struct dasd_device *device)
-{
- void *eer;
- if (!device)
- return -ENODEV;
- if (device->eer)
- return 0;
- if (!try_module_get(THIS_MODULE)) {
- return -EINVAL;
- }
- eer = (void *)dasd_eer_probe(device);
- if (IS_ERR(eer)) {
- module_put(THIS_MODULE);
- return PTR_ERR(eer);
- }
- device->eer = eer;
- return 0;
-}
-
-/*
- * enable the extended error reporting for a particular device
- */
-static int
-dasd_eer_disable_on_device(struct dasd_device *device)
-{
- struct dasd_eer_private *eer = device->eer;
-
- if (!device)
- return -ENODEV;
- if (!device->eer)
- return 0;
- device->eer = NULL;
- dasd_eer_destroy(device,eer);
- module_put(THIS_MODULE);
-
- return 0;
-}
-
-/*
- * Set extended error reporting (eer)
- * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
- */
-static int
-dasd_ioctl_set_eer(struct block_device *bdev, int no, long args)
-{
- struct dasd_device *device;
- int intval;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (bdev != bdev->bd_contains)
- /* Error-reporting is not allowed for partitions */
- return -EINVAL;
- if (get_user(intval, (int __user *) args))
- return -EFAULT;
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
-
- intval = (intval != 0);
- DEV_MESSAGE (KERN_DEBUG, device,
- "set eer on device to %d", intval);
- if (intval)
- return dasd_eer_enable_on_device(device);
- else
- return dasd_eer_disable_on_device(device);
-}
-
-/*
- * Get value of extended error reporting.
- * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
- */
-static int
-dasd_ioctl_get_eer(struct block_device *bdev, int no, long args)
-{
- struct dasd_device *device;
-
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
- return put_user((device->eer != NULL), (int __user *) args);
-}
-
-/*
- * The following function can be used for those triggers that have
- * all necessary data available when the function is called.
- * If the parameter cqr is not NULL, the chain of requests will be searched
- * for valid sense data, and all valid sense data sets will be added to
- * the triggers data.
- */
-static int
-dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- struct dasd_ccw_req *temp_cqr;
- int data_size;
- struct timeval tv;
- struct dasd_eer_header header;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- /* go through cqr chain and count the valid sense data sets */
- temp_cqr = cqr;
- data_size = 0;
- while (temp_cqr) {
- if (temp_cqr->irb.esw.esw0.erw.cons)
- data_size += 32;
- temp_cqr = temp_cqr->refers;
- }
-
- header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
- header.trigger = trigger;
- do_gettimeofday(&tv);
- header.tv_sec = tv.tv_sec;
- header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
-
- spin_lock_irqsave(&bufferlock, flags);
- list_for_each_entry(eerb, &bufferlist, list) {
- dasd_eer_start_record(eerb, header.total_size);
- dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header));
- temp_cqr = cqr;
- while (temp_cqr) {
- if (temp_cqr->irb.esw.esw0.erw.cons)
- dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw);
- temp_cqr = temp_cqr->refers;
- }
- dasd_eer_write_buffer(eerb, 4,"EOR");
- }
- spin_unlock_irqrestore(&bufferlock, flags);
-
- wake_up_interruptible(&dasd_eer_read_wait_queue);
-
- return 0;
-}
-
-/*
- * This function writes a DASD_EER_STATECHANGE trigger.
- */
-static void
-dasd_eer_write_SNSS_trigger(struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- int data_size;
- int snss_rc;
- struct timeval tv;
- struct dasd_eer_header header;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
- if (snss_rc)
- data_size = 0;
- else
- data_size = SNSS_DATA_SIZE;
-
- header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
- header.trigger = DASD_EER_STATECHANGE;
- do_gettimeofday(&tv);
- header.tv_sec = tv.tv_sec;
- header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
-
- spin_lock_irqsave(&bufferlock, flags);
- list_for_each_entry(eerb, &bufferlist, list) {
- dasd_eer_start_record(eerb, header.total_size);
- dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header));
- if (!snss_rc)
- dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data);
- dasd_eer_write_buffer(eerb, 4,"EOR");
- }
- spin_unlock_irqrestore(&bufferlock, flags);
-
- wake_up_interruptible(&dasd_eer_read_wait_queue);
-}
-
-/*
- * callback function for use with SNSS request
- */
-static void
-dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data)
-{
- struct dasd_device *device;
- struct dasd_eer_private *private;
- unsigned long irqflags;
-
- device = (struct dasd_device *)data;
- private = (struct dasd_eer_private *)device->eer;
- dasd_eer_write_SNSS_trigger(device, cqr);
- spin_lock_irqsave(&snsslock, irqflags);
- if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) {
- clear_bit(CQR_IN_USE, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- return;
- };
- clear_bit(CQR_IN_USE, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- dasd_eer_sense_subsystem_status(device);
- return;
-}
-
-/*
- * clean a used cqr before using it again
- */
-static void
-dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr)
-{
- struct ccw1 *cpaddr = cqr->cpaddr;
- void *data = cqr->data;
-
- memset(cqr, 0, sizeof(struct dasd_ccw_req));
- memset(cpaddr, 0, sizeof(struct ccw1));
- memset(data, 0, SNSS_DATA_SIZE);
- cqr->cpaddr = cpaddr;
- cqr->data = data;
- strncpy((char *) &cqr->magic, "ECKD", 4);
- ASCEBC((char *) &cqr->magic, 4);
- set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
-}
-
-/*
- * build and start an SNSS request
- * This function is called from a work queue so we have to
- * pass the dasd_device pointer as a void pointer.
- */
-static void
-dasd_eer_sense_subsystem_status(void *data)
-{
- struct dasd_device *device;
- struct dasd_eer_private *private;
- struct dasd_ccw_req *cqr;
- struct ccw1 *ccw;
- unsigned long irqflags;
-
- device = (struct dasd_device *)data;
- private = (struct dasd_eer_private *)device->eer;
- if (!private) /* device not eer enabled any more */
- return;
- cqr = private->cqr;
- spin_lock_irqsave(&snsslock, irqflags);
- if(test_and_set_bit(CQR_IN_USE, &private->flags)) {
- set_bit(SNSS_REQUESTED, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- return;
- };
- spin_unlock_irqrestore(&snsslock, irqflags);
- dasd_eer_clean_SNSS_request(cqr);
- cqr->device = device;
- cqr->retries = 255;
- cqr->expires = 10 * HZ;
-
- ccw = cqr->cpaddr;
- ccw->cmd_code = DASD_ECKD_CCW_SNSS;
- ccw->count = SNSS_DATA_SIZE;
- ccw->flags = 0;
- ccw->cda = (__u32)(addr_t)cqr->data;
-
- cqr->buildclk = get_clock();
- cqr->status = DASD_CQR_FILLED;
- cqr->callback = dasd_eer_SNSS_cb;
- cqr->callback_data = (void *)device;
- dasd_add_request_head(cqr);
-
- return;
-}
-
-/*
- * This function is called for all triggers. It calls the appropriate
- * function that writes the actual trigger records.
- */
-static int
-dasd_eer_write_trigger(struct dasd_eer_trigger *trigger)
-{
- int rc;
- struct dasd_eer_private *private = trigger->device->eer;
-
- switch (trigger->id) {
- case DASD_EER_FATALERROR:
- case DASD_EER_PPRCSUSPEND:
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, trigger->cqr);
- break;
- case DASD_EER_NOPATH:
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, NULL);
- break;
- case DASD_EER_STATECHANGE:
- if (queue_work(dasd_eer_workqueue, &private->worker)) {
- rc=0;
- } else {
- /* If the work_struct was already queued, it can't
- * be queued again. But this is OK since we don't
- * need to have it queued twice.
- */
- rc = -EBUSY;
- }
- break;
- default: /* unknown trigger, so we write it without any sense data */
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, NULL);
- break;
- }
- return rc;
-}
-
-/*
- * This function is registered with the dasd device driver and gets called
- * for all dasd eer notifications.
- */
-static int dasd_eer_notify(struct notifier_block *self,
- unsigned long action, void *data)
-{
- switch (action) {
- case DASD_EER_DISABLE:
- dasd_eer_disable_on_device((struct dasd_device *)data);
- break;
- case DASD_EER_TRIGGER:
- dasd_eer_write_trigger((struct dasd_eer_trigger *)data);
- break;
- }
- return NOTIFY_OK;
-}
-
-
-/*****************************************************************************/
-/* the device operations */
-/*****************************************************************************/
-
-/*
- * On the one side we need a lock to access our internal buffer, on the
- * other side a copy_to_user can sleep. So we need to copy the data we have
- * to transfer in a readbuffer, which is protected by the readbuffer_mutex.
- */
-static char readbuffer[PAGE_SIZE];
-DECLARE_MUTEX(readbuffer_mutex);
-
-
-static int
-dasd_eer_open(struct inode *inp, struct file *filp)
-{
- struct eerbuffer *eerb;
- unsigned long flags;
-
- eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL);
- eerb->head = 0;
- eerb->tail = 0;
- eerb->residual = 0;
- eerb->buffer_page_count = 1;
- eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
- eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*),
- GFP_KERNEL);
- if (!eerb->buffer)
- return -ENOMEM;
- if (dasd_eer_allocate_buffer_pages(eerb->buffer,
- eerb->buffer_page_count)) {
- kfree(eerb->buffer);
- return -ENOMEM;
- }
- filp->private_data = eerb;
- spin_lock_irqsave(&bufferlock, flags);
- list_add(&eerb->list, &bufferlist);
- spin_unlock_irqrestore(&bufferlock, flags);
-
- return nonseekable_open(inp,filp);
-}
-
-static int
-dasd_eer_close(struct inode *inp, struct file *filp)
-{
- struct eerbuffer *eerb;
- unsigned long flags;
-
- eerb = (struct eerbuffer *)filp->private_data;
- spin_lock_irqsave(&bufferlock, flags);
- list_del(&eerb->list);
- spin_unlock_irqrestore(&bufferlock, flags);
- dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count);
- kfree(eerb->buffer);
- kfree(eerb);
-
- return 0;
-}
-
-static long
-dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int intval;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- switch (cmd) {
- case DASD_EER_PURGE:
- dasd_eer_purge_buffer(eerb);
- return 0;
- case DASD_EER_SETBUFSIZE:
- if (get_user(intval, (int __user *)arg))
- return -EFAULT;
- return dasd_eer_resize_buffer(eerb, intval);
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-static ssize_t
-dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
- int tc,rc;
- int tailcount,effective_count;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- if(down_interruptible(&readbuffer_mutex))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&bufferlock, flags);
-
- if (eerb->residual < 0) { /* the remainder of this record */
- /* has been deleted */
- eerb->residual = 0;
- spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
- return -EIO;
- } else if (eerb->residual > 0) {
- /* OK we still have a second half of a record to deliver */
- effective_count = min(eerb->residual, (int)count);
- eerb->residual -= effective_count;
- } else {
- tc = 0;
- while (!tc) {
- tc = dasd_eer_read_buffer(eerb,
- sizeof(tailcount), (char*)(&tailcount));
- if (!tc) {
- /* no data available */
- spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- rc = wait_event_interruptible(
- dasd_eer_read_wait_queue,
- eerb->head != eerb->tail);
- if (rc) {
- return rc;
- }
- if(down_interruptible(&readbuffer_mutex))
- return -ERESTARTSYS;
- spin_lock_irqsave(&bufferlock, flags);
- }
- }
- WARN_ON(tc != sizeof(tailcount));
- effective_count = min(tailcount,(int)count);
- eerb->residual = tailcount - effective_count;
- }
-
- tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer);
- WARN_ON(tc != effective_count);
-
- spin_unlock_irqrestore(&bufferlock, flags);
-
- if (copy_to_user(buf, readbuffer, effective_count)) {
- up(&readbuffer_mutex);
- return -EFAULT;
- }
-
- up(&readbuffer_mutex);
- return effective_count;
-}
-
-static unsigned int
-dasd_eer_poll (struct file *filp, poll_table *ptable)
-{
- unsigned int mask;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- poll_wait(filp, &dasd_eer_read_wait_queue, ptable);
- spin_lock_irqsave(&bufferlock, flags);
- if (eerb->head != eerb->tail)
- mask = POLLIN | POLLRDNORM ;
- else
- mask = 0;
- spin_unlock_irqrestore(&bufferlock, flags);
- return mask;
-}
-
-static struct file_operations dasd_eer_fops = {
- .open = &dasd_eer_open,
- .release = &dasd_eer_close,
- .unlocked_ioctl = &dasd_eer_ioctl,
- .compat_ioctl = &dasd_eer_ioctl,
- .read = &dasd_eer_read,
- .poll = &dasd_eer_poll,
- .owner = THIS_MODULE,
-};
-
-static struct miscdevice dasd_eer_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "dasd_eer",
- .fops = &dasd_eer_fops,
-};
-
-
-/*****************************************************************************/
-/* Init and exit */
-/*****************************************************************************/
-
-static int
-__init dasd_eer_init(void)
-{
- int rc;
-
- dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer");
- if (!dasd_eer_workqueue) {
- MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not "
- "create workqueue \n");
- rc = -ENOMEM;
- goto out;
- }
-
- rc = dasd_register_eer_notifier(&dasd_eer_nb);
- if (rc) {
- MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
- "register error reporting");
- goto queue;
- }
-
- dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer);
- dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer);
-
- /* we don't need our own character device,
- * so we just register as misc device */
- rc = misc_register(&dasd_eer_dev);
- if (rc) {
- MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
- "register misc device");
- goto unregister;
- }
-
- return 0;
-
-unregister:
- dasd_unregister_eer_notifier(&dasd_eer_nb);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
- dasd_ioctl_set_eer);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
- dasd_ioctl_get_eer);
-queue:
- destroy_workqueue(dasd_eer_workqueue);
-out:
- return rc;
-
-}
-module_init(dasd_eer_init);
-
-static void
-__exit dasd_eer_exit(void)
-{
- dasd_unregister_eer_notifier(&dasd_eer_nb);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
- dasd_ioctl_set_eer);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
- dasd_ioctl_get_eer);
- destroy_workqueue(dasd_eer_workqueue);
-
- WARN_ON(misc_deregister(&dasd_eer_dev) != 0);
-}
-module_exit(dasd_eer_exit);
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1b08fa13fd..0592354cc60 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -275,34 +275,6 @@ struct dasd_discipline {
extern struct dasd_discipline *dasd_diag_discipline_pointer;
-
-/*
- * Notification numbers for extended error reporting notifications:
- * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
- * eer pointer) is freed. The error reporting module needs to do all necessary
- * cleanup steps.
- * The DASD_EER_TRIGGER notification sends the actual error reports (triggers).
- */
-#define DASD_EER_DISABLE 0
-#define DASD_EER_TRIGGER 1
-
-/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */
-#define DASD_EER_FATALERROR 1
-#define DASD_EER_NOPATH 2
-#define DASD_EER_STATECHANGE 3
-#define DASD_EER_PPRCSUSPEND 4
-
-/*
- * The dasd_eer_trigger structure contains all data that we need to send
- * along with an DASD_EER_TRIGGER notification.
- */
-struct dasd_eer_trigger {
- unsigned int id;
- struct dasd_device *device;
- struct dasd_ccw_req *cqr;
-};
-
-
struct dasd_device {
/* Block device stuff. */
struct gendisk *gdp;
@@ -316,11 +288,9 @@ struct dasd_device {
unsigned long flags; /* per device flags */
unsigned short features; /* copy of devmap-features (read-only!) */
- /* extended error reporting stuff (eer) */
- void *eer;
-
/* Device discipline stuff. */
struct dasd_discipline *discipline;
+ struct dasd_discipline *base_discipline;
char *private;
/* Device state and target state. */
@@ -519,12 +489,6 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
int dasd_generic_set_offline (struct ccw_device *cdev);
int dasd_generic_notify(struct ccw_device *, int);
void dasd_generic_auto_online (struct ccw_driver *);
-int dasd_register_eer_notifier(struct notifier_block *);
-int dasd_unregister_eer_notifier(struct notifier_block *);
-void dasd_write_eer_trigger(unsigned int , struct dasd_device *,
- struct dasd_ccw_req *);
-
-
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 45ce032772f..9ed37dc9a1b 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -165,8 +165,13 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"eqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT2(1,trace,"eqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
@@ -195,8 +200,13 @@ qdio_do_sqbs(struct qdio_q *q, unsigned char state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"sqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT3(1,trace,"sqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
@@ -1187,8 +1197,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used)
return 1;
-
- if (!q->siga_sync)
+ if (!q->siga_sync && !irq->is_qebsm)
/* we'll check for more primed buffers in qeth_stop_polling */
return 0;
if (irq->is_qebsm) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 791c4dc550a..94f5e8ed83a 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -90,7 +90,7 @@ static int spi_suspend(struct device *dev, pm_message_t message)
int value;
struct spi_driver *drv = to_spi_driver(dev->driver);
- if (!drv->suspend)
+ if (!drv || !drv->suspend)
return 0;
/* suspend will stop irqs and dma; no more i/o */
@@ -105,7 +105,7 @@ static int spi_resume(struct device *dev)
int value;
struct spi_driver *drv = to_spi_driver(dev->driver);
- if (!drv->resume)
+ if (!drv || !drv->resume)
return 0;
/* resume may restart the i/o queue */
@@ -449,7 +449,6 @@ void spi_unregister_master(struct spi_master *master)
{
(void) device_for_each_child(master->cdev.dev, NULL, __unregister);
class_device_unregister(&master->cdev);
- master->cdev.dev = NULL;
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 556895e9964..1f8d805c61e 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -1321,8 +1321,6 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
mdelay( 15);
}
-#ifdef CONFIG_PPC_OF
-
static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
{
u32 tmp, tmp2;
@@ -1836,6 +1834,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
}
+#ifdef CONFIG_PPC_OF
+
static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
{
OUTREG(MC_CNTL, rinfo->save_regs[46]);
@@ -2728,13 +2728,23 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
printk("radeonfb: Dynamic Clock Power Management disabled\n");
}
+#if defined(CONFIG_PM)
/* Check if we can power manage on suspend/resume. We can do
* D2 on M6, M7 and M9, and we can resume from D3 cold a few other
* "Mac" cards, but that's all. We need more infos about what the
* BIOS does tho. Right now, all this PM stuff is pmac-only for that
* reason. --BenH
*/
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
+ /* Special case for Samsung P35 laptops
+ */
+ if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
+ (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
+ (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
+ (rinfo->pdev->subsystem_device == 0xc00c)) {
+ rinfo->reinit_func = radeon_reinitialize_M10;
+ rinfo->pm_mode |= radeon_pm_off;
+ }
+#if defined(CONFIG_PPC_PMAC)
if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
@@ -2778,7 +2788,8 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
#endif
}
-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PM) */
}
void radeonfb_pm_exit(struct radeonfb_info *rinfo)
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 5250c428fc1..ef338654914 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -66,7 +66,7 @@ static match_table_t tokens = {
{Opt_afid, "afid=%u"},
{Opt_rfdno, "rfdno=%u"},
{Opt_wfdno, "wfdno=%u"},
- {Opt_debug, "debug=%u"},
+ {Opt_debug, "debug=%x"},
{Opt_name, "name=%s"},
{Opt_remotename, "aname=%s"},
{Opt_unix, "proto=unix"},
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 6573f31f1fd..075d3e94560 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -204,10 +204,6 @@ int proc_fill_super(struct super_block *s, void *data, int silent)
root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
if (!root_inode)
goto out_no_root;
- /*
- * Fixup the root inode's nlink value
- */
- root_inode->i_nlink += nr_processes();
root_inode->i_uid = 0;
root_inode->i_gid = 0;
s->s_root = d_alloc_root(root_inode);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 68896283c8a..c3fd3611112 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -80,16 +80,16 @@ void __init proc_root_init(void)
proc_bus = proc_mkdir("bus", NULL);
}
-static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
+)
{
- /*
- * nr_threads is actually protected by the tasklist_lock;
- * however, it's conventional to do reads, especially for
- * reporting, without any locking whatsoever.
- */
- if (dir->i_ino == PROC_ROOT_INO) /* check for safety... */
- dir->i_nlink = proc_root.nlink + nr_threads;
+ generic_fillattr(dentry->d_inode, stat);
+ stat->nlink = proc_root.nlink + nr_processes();
+ return 0;
+}
+static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+{
if (!proc_lookup(dir, dentry, nd)) {
return NULL;
}
@@ -134,6 +134,7 @@ static struct file_operations proc_root_operations = {
*/
static struct inode_operations proc_root_inode_operations = {
.lookup = proc_root_lookup,
+ .getattr = proc_root_getattr,
};
/*
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index 06c12a037cb..d6a2c613be6 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -239,7 +239,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
" bra 2f; \n"
" .fillinsn \n"
"1:"
- M32R_UNLOCK" %2, @%1; \n"
+ M32R_UNLOCK" %0, @%1; \n"
" .fillinsn \n"
"2:"
: "=&r" (retval)
diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h
index 325c86f8512..9ac047c400c 100644
--- a/include/asm-m68k/irq.h
+++ b/include/asm-m68k/irq.h
@@ -79,7 +79,7 @@ static __inline__ int irq_canonicalize(int irq)
extern void (*enable_irq)(unsigned int);
extern void (*disable_irq)(unsigned int);
-#define enable_irq_nosync enable_irq
+#define disable_irq_nosync disable_irq
struct pt_regs;
diff --git a/include/asm-m68k/raw_io.h b/include/asm-m68k/raw_io.h
index 5439bcaa57c..811ccd25d4a 100644
--- a/include/asm-m68k/raw_io.h
+++ b/include/asm-m68k/raw_io.h
@@ -336,6 +336,7 @@ static inline void raw_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
: "d0", "a0", "a1", "d6");
}
+#define __raw_writel raw_outl
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index 39200def8d1..a3e8a45e45a 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -154,19 +154,6 @@ extern char cmd_line[COMMAND_LINE_SIZE];
extern void setup_pci_ptrs(void);
-/*
- * Power macintoshes have either a CUDA or a PMU controlling
- * system reset, power, NVRAM, RTC.
- */
-typedef enum sys_ctrler_kind {
- SYS_CTRLER_UNKNOWN = 0,
- SYS_CTRLER_CUDA = 1,
- SYS_CTRLER_PMU = 2,
- SYS_CTRLER_SMU = 3,
-} sys_ctrler_t;
-
-extern sys_ctrler_t sys_ctrler;
-
#ifdef CONFIG_SMP
struct smp_ops_t {
void (*message_pass)(int target, int msg);
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h
index c744ff33b1d..1630c26e8f4 100644
--- a/include/asm-s390/dasd.h
+++ b/include/asm-s390/dasd.h
@@ -204,8 +204,7 @@ typedef struct attrib_data_t {
*
* Here ist how the ioctl-nr should be used:
* 0 - 31 DASD driver itself
- * 32 - 229 still open
- * 230 - 239 DASD extended error reporting
+ * 32 - 239 still open
* 240 - 255 reserved for EMC
*******************************************************************************/
@@ -237,22 +236,12 @@ typedef struct attrib_data_t {
#define BIODASDPSRD _IOR(DASD_IOCTL_LETTER,4,dasd_rssd_perf_stats_t)
/* Get Attributes (cache operations) */
#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER,5,attrib_data_t)
-/* retrieve extended error-reporting value */
-#define BIODASDEERGET _IOR(DASD_IOCTL_LETTER,6,int)
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t)
/* Set Attributes (cache operations) */
#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t)
-/* retrieve extended error-reporting value */
-#define BIODASDEERSET _IOW(DASD_IOCTL_LETTER,3,int)
-
-
-/* remove all records from the eer buffer */
-#define DASD_EER_PURGE _IO(DASD_IOCTL_LETTER,230)
-/* set the number of pages that are used for the internal eer buffer */
-#define DASD_EER_SETBUFSIZE _IOW(DASD_IOCTL_LETTER,230,int)
#endif /* DASD_H */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 84d3d9f034c..d3bc25e6d27 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -427,7 +427,8 @@ extern int acpi_mp_config;
extern struct acpi_table_mcfg_config *pci_mmcfg_config;
extern int pci_mmcfg_config_num;
-extern int sbf_port ;
+extern int sbf_port;
+extern unsigned long acpi_video_flags;
#else /* !CONFIG_ACPI */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 26e1663a5cb..498ff8778fb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1051,7 +1051,11 @@ int shrink_slab(unsigned long scanned, gfp_t gfp_mask,
void drop_pagecache(void);
void drop_slab(void);
+#ifndef CONFIG_MMU
+#define randomize_va_space 0
+#else
extern int randomize_va_space;
+#endif
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 547d649b274..b4dc6e2e10c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -398,7 +398,7 @@ extern struct inode_operations nfs_symlink_inode_operations;
extern int nfs_register_sysctl(void);
extern void nfs_unregister_sysctl(void);
#else
-#define nfs_register_sysctl() do { } while(0)
+#define nfs_register_sysctl() 0
#define nfs_unregister_sysctl() do { } while(0)
#endif
diff --git a/include/linux/swap.h b/include/linux/swap.h
index f3e17d5963c..d572b19afb7 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -147,7 +147,7 @@ struct swap_list_t {
#define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
/* linux/mm/oom_kill.c */
-extern void out_of_memory(gfp_t gfp_mask, int order);
+extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order);
/* linux/mm/memory.c */
extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 32a4139c4ad..0e92bf7ec28 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -146,6 +146,7 @@ enum
KERN_RANDOMIZE=68, /* int: randomize virtual address space */
KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */
KERN_SPIN_RETRY=70, /* int: number of spinlock retries */
+ KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */
};
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 685c25175d9..d7e7e637b92 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -841,7 +841,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
for (aux = context->aux; aux; aux = aux->next) {
- ab = audit_log_start(context, GFP_KERNEL, aux->type);
+ ab = audit_log_start(context, gfp_mask, aux->type);
if (!ab)
continue; /* audit_panic has been called */
@@ -878,14 +878,14 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
}
if (context->pwd && context->pwdmnt) {
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
+ ab = audit_log_start(context, gfp_mask, AUDIT_CWD);
if (ab) {
audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
audit_log_end(ab);
}
}
for (i = 0; i < context->name_count; i++) {
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
+ ab = audit_log_start(context, gfp_mask, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 17313b99e53..1067090db6b 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -104,6 +104,8 @@ cond_syscall(sys_setreuid16);
cond_syscall(sys_setuid16);
cond_syscall(sys_vm86old);
cond_syscall(sys_vm86);
+cond_syscall(compat_sys_ipc);
+cond_syscall(compat_sys_sysctl);
/* arch-specific weak syscall entries */
cond_syscall(sys_pciconfig_read);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 7654d55c47f..c05a2b7125e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -44,14 +44,12 @@
#include <linux/limits.h>
#include <linux/dcache.h>
#include <linux/syscalls.h>
+#include <linux/nfs_fs.h>
+#include <linux/acpi.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
-#ifdef CONFIG_ROOT_NFS
-#include <linux/nfs_fs.h>
-#endif
-
#if defined(CONFIG_SYSCTL)
/* External variables not in a header file. */
@@ -638,6 +636,7 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+#if defined(CONFIG_MMU)
{
.ctl_name = KERN_RANDOMIZE,
.procname = "randomize_va_space",
@@ -646,6 +645,7 @@ static ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+#endif
#if defined(CONFIG_S390) && defined(CONFIG_SMP)
{
.ctl_name = KERN_SPIN_RETRY,
@@ -656,6 +656,16 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+#ifdef CONFIG_ACPI_SLEEP
+ {
+ .ctl_name = KERN_ACPI_VIDEO_FLAGS,
+ .procname = "acpi_video_flags",
+ .data = &acpi_video_flags,
+ .maxlen = sizeof (unsigned long),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#endif
{ .ctl_name = 0 }
};
diff --git a/lib/iomap_copy.c b/lib/iomap_copy.c
index a6b1e271d53..351045f4f63 100644
--- a/lib/iomap_copy.c
+++ b/lib/iomap_copy.c
@@ -15,8 +15,8 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include <linux/io.h>
#include <linux/module.h>
+#include <linux/io.h>
/**
* __iowrite32_copy - copy data to MMIO space, in 32-bit units
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index bedfa4f09c8..880831bd300 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -587,7 +587,7 @@ redo:
}
list_add(&page->lru, &newlist);
nr_pages++;
- if (nr_pages > MIGRATE_CHUNK_SIZE);
+ if (nr_pages > MIGRATE_CHUNK_SIZE)
break;
}
err = migrate_pages(pagelist, &newlist, &moved, &failed);
@@ -808,7 +808,7 @@ static int get_nodes(nodemask_t *nodes, const unsigned long __user *nmask,
nodes_clear(*nodes);
if (maxnode == 0 || !nmask)
return 0;
- if (maxnode > PAGE_SIZE)
+ if (maxnode > PAGE_SIZE*BITS_PER_BYTE)
return -EINVAL;
nlongs = BITS_TO_LONGS(maxnode);
diff --git a/mm/nommu.c b/mm/nommu.c
index c10262d6823..99d21020ec9 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -57,6 +57,8 @@ EXPORT_SYMBOL(vmalloc);
EXPORT_SYMBOL(vfree);
EXPORT_SYMBOL(vmalloc_to_page);
EXPORT_SYMBOL(vmalloc_32);
+EXPORT_SYMBOL(vmap);
+EXPORT_SYMBOL(vunmap);
/*
* Handle all mappings that got truncated by a "truncate()"
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index b05ab8f2a56..8123fad5a48 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -58,15 +58,17 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
/*
* Processes which fork a lot of child processes are likely
- * a good choice. We add the vmsize of the children if they
+ * a good choice. We add half the vmsize of the children if they
* have an own mm. This prevents forking servers to flood the
- * machine with an endless amount of children
+ * machine with an endless amount of children. In case a single
+ * child is eating the vast majority of memory, adding only half
+ * to the parents will make the child our kill candidate of choice.
*/
list_for_each(tsk, &p->children) {
struct task_struct *chld;
chld = list_entry(tsk, struct task_struct, sibling);
if (chld->mm != p->mm && chld->mm)
- points += chld->mm->total_vm;
+ points += chld->mm->total_vm/2 + 1;
}
/*
@@ -131,17 +133,47 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
}
/*
+ * Types of limitations to the nodes from which allocations may occur
+ */
+#define CONSTRAINT_NONE 1
+#define CONSTRAINT_MEMORY_POLICY 2
+#define CONSTRAINT_CPUSET 3
+
+/*
+ * Determine the type of allocation constraint.
+ */
+static inline int constrained_alloc(struct zonelist *zonelist, gfp_t gfp_mask)
+{
+#ifdef CONFIG_NUMA
+ struct zone **z;
+ nodemask_t nodes = node_online_map;
+
+ for (z = zonelist->zones; *z; z++)
+ if (cpuset_zone_allowed(*z, gfp_mask))
+ node_clear((*z)->zone_pgdat->node_id,
+ nodes);
+ else
+ return CONSTRAINT_CPUSET;
+
+ if (!nodes_empty(nodes))
+ return CONSTRAINT_MEMORY_POLICY;
+#endif
+
+ return CONSTRAINT_NONE;
+}
+
+/*
* Simple selection loop. We chose the process with the highest
* number of 'points'. We expect the caller will lock the tasklist.
*
* (not docbooked, we don't want this one cluttering up the manual)
*/
-static struct task_struct * select_bad_process(void)
+static struct task_struct *select_bad_process(unsigned long *ppoints)
{
- unsigned long maxpoints = 0;
struct task_struct *g, *p;
struct task_struct *chosen = NULL;
struct timespec uptime;
+ *ppoints = 0;
do_posix_clock_monotonic_gettime(&uptime);
do_each_thread(g, p) {
@@ -169,9 +201,9 @@ static struct task_struct * select_bad_process(void)
return p;
points = badness(p, uptime.tv_sec);
- if (points > maxpoints || !chosen) {
+ if (points > *ppoints || !chosen) {
chosen = p;
- maxpoints = points;
+ *ppoints = points;
}
} while_each_thread(g, p);
return chosen;
@@ -182,7 +214,7 @@ static struct task_struct * select_bad_process(void)
* CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that
* we select a process with CAP_SYS_RAW_IO set).
*/
-static void __oom_kill_task(task_t *p)
+static void __oom_kill_task(task_t *p, const char *message)
{
if (p->pid == 1) {
WARN_ON(1);
@@ -198,8 +230,8 @@ static void __oom_kill_task(task_t *p)
return;
}
task_unlock(p);
- printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n",
- p->pid, p->comm);
+ printk(KERN_ERR "%s: Killed process %d (%s).\n",
+ message, p->pid, p->comm);
/*
* We give our sacrificial lamb high priority and access to
@@ -212,7 +244,7 @@ static void __oom_kill_task(task_t *p)
force_sig(SIGKILL, p);
}
-static struct mm_struct *oom_kill_task(task_t *p)
+static struct mm_struct *oom_kill_task(task_t *p, const char *message)
{
struct mm_struct *mm = get_task_mm(p);
task_t * g, * q;
@@ -224,35 +256,38 @@ static struct mm_struct *oom_kill_task(task_t *p)
return NULL;
}
- __oom_kill_task(p);
+ __oom_kill_task(p, message);
/*
* kill all processes that share the ->mm (i.e. all threads),
* but are in a different thread group
*/
do_each_thread(g, q)
if (q->mm == mm && q->tgid != p->tgid)
- __oom_kill_task(q);
+ __oom_kill_task(q, message);
while_each_thread(g, q);
return mm;
}
-static struct mm_struct *oom_kill_process(struct task_struct *p)
+static struct mm_struct *oom_kill_process(struct task_struct *p,
+ unsigned long points, const char *message)
{
struct mm_struct *mm;
struct task_struct *c;
struct list_head *tsk;
+ printk(KERN_ERR "Out of Memory: Kill process %d (%s) score %li and "
+ "children.\n", p->pid, p->comm, points);
/* Try to kill a child first */
list_for_each(tsk, &p->children) {
c = list_entry(tsk, struct task_struct, sibling);
if (c->mm == p->mm)
continue;
- mm = oom_kill_task(c);
+ mm = oom_kill_task(c, message);
if (mm)
return mm;
}
- return oom_kill_task(p);
+ return oom_kill_task(p, message);
}
/**
@@ -263,10 +298,11 @@ static struct mm_struct *oom_kill_process(struct task_struct *p)
* OR try to be smart about which process to kill. Note that we
* don't have to be perfect here, we just have to be good.
*/
-void out_of_memory(gfp_t gfp_mask, int order)
+void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
{
struct mm_struct *mm = NULL;
- task_t * p;
+ task_t *p;
+ unsigned long points;
if (printk_ratelimit()) {
printk("oom-killer: gfp_mask=0x%x, order=%d\n",
@@ -277,25 +313,48 @@ void out_of_memory(gfp_t gfp_mask, int order)
cpuset_lock();
read_lock(&tasklist_lock);
+
+ /*
+ * Check if there were limitations on the allocation (only relevant for
+ * NUMA) that may require different handling.
+ */
+ switch (constrained_alloc(zonelist, gfp_mask)) {
+ case CONSTRAINT_MEMORY_POLICY:
+ mm = oom_kill_process(current, points,
+ "No available memory (MPOL_BIND)");
+ break;
+
+ case CONSTRAINT_CPUSET:
+ mm = oom_kill_process(current, points,
+ "No available memory in cpuset");
+ break;
+
+ case CONSTRAINT_NONE:
retry:
- p = select_bad_process();
+ /*
+ * Rambo mode: Shoot down a process and hope it solves whatever
+ * issues we may have.
+ */
+ p = select_bad_process(&points);
- if (PTR_ERR(p) == -1UL)
- goto out;
+ if (PTR_ERR(p) == -1UL)
+ goto out;
- /* Found nothing?!?! Either we hang forever, or we panic. */
- if (!p) {
- read_unlock(&tasklist_lock);
- cpuset_unlock();
- panic("Out of memory and no killable processes...\n");
- }
+ /* Found nothing?!?! Either we hang forever, or we panic. */
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ cpuset_unlock();
+ panic("Out of memory and no killable processes...\n");
+ }
- mm = oom_kill_process(p);
- if (!mm)
- goto retry;
+ mm = oom_kill_process(p, points, "Out of memory");
+ if (!mm)
+ goto retry;
+
+ break;
+ }
- out:
- read_unlock(&tasklist_lock);
+out:
cpuset_unlock();
if (mm)
mmput(mm);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 208812b2559..791690d7d3f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1015,7 +1015,7 @@ rebalance:
if (page)
goto got_pg;
- out_of_memory(gfp_mask, order);
+ out_of_memory(zonelist, gfp_mask, order);
goto restart;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6766f118f07..2144952d1c6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -411,6 +411,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
C(pkt_type);
C(ip_summed);
C(priority);
+#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
+ C(ipvs_property);
+#endif
C(protocol);
n->destructor = NULL;
#ifdef CONFIG_NETFILTER
@@ -422,13 +425,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
C(nfct_reasm);
nf_conntrack_get_reasm(skb->nfct_reasm);
#endif
-#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
- C(ipvs_property);
-#endif
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
- C(nfct_reasm);
- nf_conntrack_get_reasm(skb->nfct_reasm);
-#endif
#ifdef CONFIG_BRIDGE_NETFILTER
C(nf_bridge);
nf_bridge_get(skb->nf_bridge);
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index c1a61462507..1741d555ad0 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
} *inside;
struct ip_conntrack_tuple inner, target;
int hdrlen = (*pskb)->nh.iph->ihl * 4;
+ unsigned long statusbit;
if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
return 0;
@@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
/* Change outer to look the reply to an incoming packet
* (proto 0 means don't invert per-proto part). */
+ if (manip == IP_NAT_MANIP_SRC)
+ statusbit = IPS_SRC_NAT;
+ else
+ statusbit = IPS_DST_NAT;
- /* Obviously, we need to NAT destination IP, but source IP
- should be NAT'ed only if it is from a NAT'd host.
+ /* Invert if this is reply dir. */
+ if (dir == IP_CT_DIR_REPLY)
+ statusbit ^= IPS_NAT_MASK;
- Explanation: some people use NAT for anonymizing. Also,
- CERT recommends dropping all packets from private IP
- addresses (although ICMP errors from internal links with
- such addresses are not too uncommon, as Alan Cox points
- out) */
- if (manip != IP_NAT_MANIP_SRC
- || ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) {
+ if (ct->status & statusbit) {
invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
if (!manip_pkt(0, pskb, 0, &target, manip))
return 0;
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 7c3f7d38024..ab1f88fa21e 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct ip_conntrack *ct;
- enum ip_conntrack_info ctinfo;
unsigned int ret;
+ u_int32_t daddr = (*pskb)->nh.iph->daddr;
ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN
- && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-
- if (ct->tuplehash[dir].tuple.dst.ip !=
- ct->tuplehash[!dir].tuple.src.ip) {
- dst_release((*pskb)->dst);
- (*pskb)->dst = NULL;
- }
+ && daddr != (*pskb)->nh.iph->daddr) {
+ dst_release((*pskb)->dst);
+ (*pskb)->dst = NULL;
}
return ret;
}
@@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum,
ct->tuplehash[!dir].tuple.src.ip
#ifdef CONFIG_XFRM
|| ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[dir].tuple.src.u.all
+ ct->tuplehash[!dir].tuple.src.u.all
#endif
)
return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 92ead3cf956..faea8a120ee 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -458,7 +458,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
mtu = IPV6_MIN_MTU;
t->dev->mtu = mtu;
- if ((len = sizeof (*ipv6h) + ipv6h->payload_len) > mtu) {
+ if ((len = sizeof (*ipv6h) + ntohs(ipv6h->payload_len)) > mtu) {
rel_type = ICMPV6_PKT_TOOBIG;
rel_code = 0;
rel_info = mtu;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 98ec53bd3ac..5e6b05ac126 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -885,8 +885,6 @@ restart:
* We can't enlist stable bundles either.
*/
write_unlock_bh(&policy->lock);
-
- xfrm_pol_put(policy);
if (dst)
dst_free(dst);
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 418c6d4e5da..a529b62972b 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -167,7 +167,7 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
int *countp)
{
struct snd_kcontrol *kctl;
- struct snd_ctl_elem_info info;
+ struct snd_ctl_elem_info *info;
int err;
down_read(&card->controls_rwsem);
@@ -176,13 +176,19 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
up_read(&card->controls_rwsem);
return -ENXIO;
}
- info.id = *id;
- err = kctl->info(kctl, &info);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (info == NULL) {
+ up_read(&card->controls_rwsem);
+ return -ENOMEM;
+ }
+ info->id = *id;
+ err = kctl->info(kctl, info);
up_read(&card->controls_rwsem);
if (err >= 0) {
- err = info.type;
- *countp = info.count;
+ err = info->type;
+ *countp = info->count;
}
+ kfree(info);
return err;
}