[kernel] r11630 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series
Maximilian Attems
maks at alioth.debian.org
Fri Jun 13 10:08:47 UTC 2008
Author: maks
Date: Fri Jun 13 10:08:46 2008
New Revision: 11630
Log:
update to 2.6.26-rc6-git1
no conflicts
Added:
dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.26-rc6-git1
Modified:
dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.26-rc6-git1
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.26-rc6-git1 Fri Jun 13 10:08:46 2008
@@ -0,0 +1,1889 @@
+diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
+index e65736c..63e59b8 100644
+--- a/Documentation/cciss.txt
++++ b/Documentation/cciss.txt
+@@ -21,6 +21,11 @@ This driver is known to work with the following cards:
+ * SA E200
+ * SA E200i
+ * SA E500
++ * SA P212
++ * SA P410
++ * SA P410i
++ * SA P411
++ * SA P812
+
+ Detecting drive failures:
+ -------------------------
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 9d43042..88aac5f 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1202,6 +1202,7 @@ M: pj at sgi.com
+ M: menage at google.com
+ L: linux-kernel at vger.kernel.org
+ W: http://www.bullopensource.org/cpuset/
++W: http://oss.sgi.com/projects/cpusets/
+ S: Supported
+
+ CRAMFS FILESYSTEM
+@@ -3329,9 +3330,11 @@ L: video4linux-list at redhat.com
+ W: http://www.isely.net/pvrusb2/
+ S: Maintained
+
+-PXA2xx SUPPORT
+-P: Nicolas Pitre
+-M: nico at cam.org
++PXA2xx/PXA3xx SUPPORT
++P: Eric Miao
++M: eric.miao at marvell.com
++P: Russell King
++M: linux at arm.linux.org.uk
+ L: linux-arm-kernel at lists.arm.linux.org.uk (subscribers-only)
+ S: Maintained
+
+diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c
+index ba5a9f3..454f254 100644
+--- a/arch/m68knommu/platform/coldfire/timers.c
++++ b/arch/m68knommu/platform/coldfire/timers.c
+@@ -111,7 +111,13 @@ void hw_timer_init(void)
+
+ __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
+ mcftmr_cycles_per_jiffy = FREQ / HZ;
+- __raw_writetrr(mcftmr_cycles_per_jiffy, TA(MCFTIMER_TRR));
++ /*
++ * The coldfire timer runs from 0 to TRR included, then 0
++ * again and so on. It counts thus actually TRR + 1 steps
++ * for 1 tick, not TRR. So if you want n cycles,
++ * initialize TRR with n - 1.
++ */
++ __raw_writetrr(mcftmr_cycles_per_jiffy - 1, TA(MCFTIMER_TRR));
+ __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+ MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
+
+diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
+index b4b36e0..183db26 100644
+--- a/arch/um/os-Linux/start_up.c
++++ b/arch/um/os-Linux/start_up.c
+@@ -121,8 +121,10 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit)
+ {
+ int status, n, ret = 0;
+
+- if (ptrace(PTRACE_CONT, pid, 0, 0) < 0)
+- fatal_perror("stop_ptraced_child : ptrace failed");
++ if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) {
++ perror("stop_ptraced_child : ptrace failed");
++ return -1;
++ }
+ CATCH_EINTR(n = waitpid(pid, &status, 0));
+ if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
+ int exit_with = WEXITSTATUS(status);
+@@ -212,7 +214,7 @@ static void __init check_sysemu(void)
+ if (n < 0)
+ fatal_perror("check_sysemu : wait failed");
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+- fatal("check_sysemu : expected SIGTRAP, got status = %d",
++ fatal("check_sysemu : expected SIGTRAP, got status = %d\n",
+ status);
+
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+@@ -254,9 +256,11 @@ static void __init check_sysemu(void)
+
+ if (WIFSTOPPED(status) &&
+ (WSTOPSIG(status) == (SIGTRAP|0x80))) {
+- if (!count)
+- fatal("check_ptrace : SYSEMU_SINGLESTEP "
+- "doesn't singlestep");
++ if (!count) {
++ non_fatal("check_ptrace : SYSEMU_SINGLESTEP "
++ "doesn't singlestep");
++ goto fail;
++ }
+ n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
+ os_getpid());
+ if (n < 0)
+@@ -266,9 +270,12 @@ static void __init check_sysemu(void)
+ }
+ else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
+ count++;
+- else
+- fatal("check_ptrace : expected SIGTRAP or "
+- "(SIGTRAP | 0x80), got status = %d", status);
++ else {
++ non_fatal("check_ptrace : expected SIGTRAP or "
++ "(SIGTRAP | 0x80), got status = %d\n",
++ status);
++ goto fail;
++ }
+ }
+ if (stop_ptraced_child(pid, 0, 0) < 0)
+ goto fail_stopped;
+diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
+index b487cbe..229f7a5 100644
+--- a/arch/um/os-Linux/sys-i386/registers.c
++++ b/arch/um/os-Linux/sys-i386/registers.c
+@@ -6,7 +6,7 @@
+
+ #include <errno.h>
+ #include <sys/ptrace.h>
+-#include <asm/user.h>
++#include <sys/user.h>
+ #include "kern_constants.h"
+ #include "longjmp.h"
+ #include "user.h"
+@@ -76,7 +76,7 @@ int put_fp_registers(int pid, unsigned long *regs)
+
+ void arch_init_registers(int pid)
+ {
+- struct user_fxsr_struct fpx_regs;
++ struct user_fpxregs_struct fpx_regs;
+ int err;
+
+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
+diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
+index 9615eee..05191bb 100644
+--- a/arch/x86/kernel/rtc.c
++++ b/arch/x86/kernel/rtc.c
+@@ -4,6 +4,8 @@
+ #include <linux/acpi.h>
+ #include <linux/bcd.h>
+ #include <linux/mc146818rtc.h>
++#include <linux/platform_device.h>
++#include <linux/pnp.h>
+
+ #include <asm/time.h>
+ #include <asm/vsyscall.h>
+@@ -197,3 +199,35 @@ unsigned long long native_read_tsc(void)
+ }
+ EXPORT_SYMBOL(native_read_tsc);
+
++
++static struct resource rtc_resources[] = {
++ [0] = {
++ .start = RTC_PORT(0),
++ .end = RTC_PORT(1),
++ .flags = IORESOURCE_IO,
++ },
++ [1] = {
++ .start = RTC_IRQ,
++ .end = RTC_IRQ,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static struct platform_device rtc_device = {
++ .name = "rtc_cmos",
++ .id = -1,
++ .resource = rtc_resources,
++ .num_resources = ARRAY_SIZE(rtc_resources),
++};
++
++static __init int add_rtc_cmos(void)
++{
++#ifdef CONFIG_PNP
++ if (!pnp_platform_devices)
++ platform_device_register(&rtc_device);
++#else
++ platform_device_register(&rtc_device);
++#endif /* CONFIG_PNP */
++ return 0;
++}
++device_initcall(add_rtc_cmos);
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index e336b05..5f1e1cc 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -53,15 +53,16 @@
+ #include <linux/scatterlist.h>
+
+ #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
+-#define DRIVER_NAME "HP CISS Driver (v 3.6.14)"
+-#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14)
++#define DRIVER_NAME "HP CISS Driver (v 3.6.20)"
++#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 20)
+
+ /* Embedded module documentation macros - see modules.h */
+ MODULE_AUTHOR("Hewlett-Packard Company");
+-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14");
++MODULE_DESCRIPTION("Driver for HP Smart Array Controllers");
+ MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
+- " SA6i P600 P800 P400 P400i E200 E200i E500");
+-MODULE_VERSION("3.6.14");
++ " SA6i P600 P800 P400 P400i E200 E200i E500 P700m"
++ " Smart Array G2 Series SAS/SATA Controllers");
++MODULE_VERSION("3.6.20");
+ MODULE_LICENSE("GPL");
+
+ #include "cciss_cmd.h"
+@@ -90,6 +91,11 @@ static const struct pci_device_id cciss_pci_device_id[] = {
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D},
++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241},
++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243},
++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245},
++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247},
++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249},
+ {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
+ {0,}
+@@ -123,6 +129,11 @@ static struct board_type products[] = {
+ {0x3215103C, "Smart Array E200i", &SA5_access, 120},
+ {0x3237103C, "Smart Array E500", &SA5_access, 512},
+ {0x323D103C, "Smart Array P700m", &SA5_access, 512},
++ {0x3241103C, "Smart Array P212", &SA5_access, 384},
++ {0x3243103C, "Smart Array P410", &SA5_access, 384},
++ {0x3245103C, "Smart Array P410i", &SA5_access, 384},
++ {0x3247103C, "Smart Array P411", &SA5_access, 384},
++ {0x3249103C, "Smart Array P812", &SA5_access, 384},
+ {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
+ };
+
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index d307bf2..2d854bb 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -749,7 +749,7 @@ config NVRAM
+ if RTC_LIB=n
+
+ config RTC
+- tristate "Enhanced Real Time Clock Support"
++ tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
+ depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
+ && !ARM && !SUPERH && !S390 && !AVR32
+ ---help---
+@@ -1036,9 +1036,9 @@ config HPET
+ non-periodic and/or periodic.
+
+ config HPET_RTC_IRQ
+- bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC
+- default n
+- depends on HPET
++ bool
++ default HPET_EMULATE_RTC
++ depends on RTC && HPET
+ help
+ If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It
+ is assumed the platform called hpet_alloc with the RTC IRQ values for
+diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
+index 55c97f6..07b4d8f 100644
+--- a/drivers/char/agp/ati-agp.c
++++ b/drivers/char/agp/ati-agp.c
+@@ -458,6 +458,10 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
+ .chipset_name = "IGP9100/M",
+ },
+ {
++ .device_id = PCI_DEVICE_ID_ATI_RS350_133,
++ .chipset_name = "IGP9000/M",
++ },
++ {
+ .device_id = PCI_DEVICE_ID_ATI_RS350_200,
+ .chipset_name = "IGP9100/M",
+ },
+diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
+index 2398e86..a00869c 100644
+--- a/drivers/char/generic_nvram.c
++++ b/drivers/char/generic_nvram.c
+@@ -133,7 +133,7 @@ static struct miscdevice nvram_dev = {
+
+ int __init nvram_init(void)
+ {
+- printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n",
++ printk(KERN_INFO "Generic non-volatile memory driver v%s\n",
+ NVRAM_VERSION);
+ return misc_register(&nvram_dev);
+ }
+diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
+index 5cc651e..27fdc08 100644
+--- a/drivers/char/hw_random/intel-rng.c
++++ b/drivers/char/hw_random/intel-rng.c
+@@ -273,7 +273,7 @@ static int __init intel_rng_hw_init(void *_intel_rng_hw)
+ if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
+ (dvc != INTEL_FWH_DEVICE_CODE_8M &&
+ dvc != INTEL_FWH_DEVICE_CODE_4M)) {
+- printk(KERN_ERR PFX "FWH not detected\n");
++ printk(KERN_NOTICE PFX "FWH not detected\n");
+ return -ENODEV;
+ }
+
+diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
+index 7f7e798..d9a0a53 100644
+--- a/drivers/char/keyboard.c
++++ b/drivers/char/keyboard.c
+@@ -677,12 +677,7 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
+
+ static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
+ {
+- unsigned int uni;
+- if (kbd->kbdmode == VC_UNICODE)
+- uni = value;
+- else
+- uni = conv_8bit_to_uni(value);
+- k_unicode(vc, uni, up_flag);
++ k_unicode(vc, conv_8bit_to_uni(value), up_flag);
+ }
+
+ static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
+diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
+index 7817d22..1081091 100644
+--- a/drivers/isdn/sc/ioctl.c
++++ b/drivers/isdn/sc/ioctl.c
+@@ -226,6 +226,7 @@ int sc_ioctl(int card, scs_ioctl *data)
+ */
+ if (copy_from_user(spid, data->dataptr, SCIOC_SPIDSIZE)) {
+ kfree(rcvmsg);
++ kfree(spid);
+ return -EFAULT;
+ }
+
+diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
+index be624a0..c303e7f 100644
+--- a/drivers/mmc/host/wbsd.c
++++ b/drivers/mmc/host/wbsd.c
+@@ -1457,17 +1457,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
+ int ret;
+
+ /*
+- * Allocate interrupt.
+- */
+-
+- ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host);
+- if (ret)
+- return ret;
+-
+- host->irq = irq;
+-
+- /*
+- * Set up tasklets.
++ * Set up tasklets. Must be done before requesting interrupt.
+ */
+ tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
+ (unsigned long)host);
+@@ -1480,6 +1470,15 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
+ tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
+ (unsigned long)host);
+
++ /*
++ * Allocate interrupt.
++ */
++ ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host);
++ if (ret)
++ return ret;
++
++ host->irq = irq;
++
+ return 0;
+ }
+
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index 60f8afc..4949dc4 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -256,6 +256,17 @@ config RTC_DRV_S35390A
+ This driver can also be built as a module. If so the module
+ will be called rtc-s35390a.
+
++config RTC_DRV_FM3130
++ tristate "Ramtron FM3130"
++ help
++ If you say Y here you will get support for the
++ Ramtron FM3130 RTC chips.
++ Ramtron FM3130 is a chip with two separate devices inside,
++ RTC clock and FRAM. This driver provides only RTC functionality.
++
++ This driver can also be built as a module. If so the module
++ will be called rtc-fm3130.
++
+ endif # I2C
+
+ comment "SPI RTC drivers"
+diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
+index ebe871c..b6e14d5 100644
+--- a/drivers/rtc/Makefile
++++ b/drivers/rtc/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
+ obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
+ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
+ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
++obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
+ obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
+ obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
+ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
+@@ -41,6 +42,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
+ obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
+ obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
+ obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
++obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o
+ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
+ obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
+ obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
+@@ -54,4 +56,3 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
+ obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
+ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
+ obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+-obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o
+diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
+index 42244f1..2ef8cdf 100644
+--- a/drivers/rtc/rtc-at32ap700x.c
++++ b/drivers/rtc/rtc-at32ap700x.c
+@@ -94,8 +94,11 @@ static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ {
+ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+
++ spin_lock_irq(&rtc->lock);
+ rtc_time_to_tm(rtc->alarm_time, &alrm->time);
+- alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
++ alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
++ alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0;
++ spin_unlock_irq(&rtc->lock);
+
+ return 0;
+ }
+@@ -119,7 +122,7 @@ static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ spin_lock_irq(&rtc->lock);
+ rtc->alarm_time = alarm_unix_time;
+ rtc_writel(rtc, TOP, rtc->alarm_time);
+- if (alrm->pending)
++ if (alrm->enabled)
+ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+ | RTC_BIT(CTRL_TOPEN));
+ else
+diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
+index d060a06..d7bb9ba 100644
+--- a/drivers/rtc/rtc-cmos.c
++++ b/drivers/rtc/rtc-cmos.c
+@@ -905,19 +905,7 @@ static struct pnp_driver cmos_pnp_driver = {
+ .resume = cmos_pnp_resume,
+ };
+
+-static int __init cmos_init(void)
+-{
+- return pnp_register_driver(&cmos_pnp_driver);
+-}
+-module_init(cmos_init);
+-
+-static void __exit cmos_exit(void)
+-{
+- pnp_unregister_driver(&cmos_pnp_driver);
+-}
+-module_exit(cmos_exit);
+-
+-#else /* no PNP */
++#endif /* CONFIG_PNP */
+
+ /*----------------------------------------------------------------*/
+
+@@ -958,20 +946,33 @@ static struct platform_driver cmos_platform_driver = {
+
+ static int __init cmos_init(void)
+ {
++#ifdef CONFIG_PNP
++ if (pnp_platform_devices)
++ return pnp_register_driver(&cmos_pnp_driver);
++ else
++ return platform_driver_probe(&cmos_platform_driver,
++ cmos_platform_probe);
++#else
+ return platform_driver_probe(&cmos_platform_driver,
+ cmos_platform_probe);
++#endif /* CONFIG_PNP */
+ }
+ module_init(cmos_init);
+
+ static void __exit cmos_exit(void)
+ {
++#ifdef CONFIG_PNP
++ if (pnp_platform_devices)
++ pnp_unregister_driver(&cmos_pnp_driver);
++ else
++ platform_driver_unregister(&cmos_platform_driver);
++#else
+ platform_driver_unregister(&cmos_platform_driver);
++#endif /* CONFIG_PNP */
+ }
+ module_exit(cmos_exit);
+
+
+-#endif /* !PNP */
+-
+ MODULE_AUTHOR("David Brownell");
+ MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
+new file mode 100644
+index 0000000..11644c8
+--- /dev/null
++++ b/drivers/rtc/rtc-fm3130.c
+@@ -0,0 +1,501 @@
++/*
++ * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip.
++ *
++ * Copyright (C) 2008 Sergey Lapin
++ * Based on ds1307 driver by James Chapman and David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/i2c.h>
++#include <linux/rtc.h>
++#include <linux/bcd.h>
++
++#define FM3130_RTC_CONTROL (0x0)
++#define FM3130_CAL_CONTROL (0x1)
++#define FM3130_RTC_SECONDS (0x2)
++#define FM3130_RTC_MINUTES (0x3)
++#define FM3130_RTC_HOURS (0x4)
++#define FM3130_RTC_DAY (0x5)
++#define FM3130_RTC_DATE (0x6)
++#define FM3130_RTC_MONTHS (0x7)
++#define FM3130_RTC_YEARS (0x8)
++
++#define FM3130_ALARM_SECONDS (0x9)
++#define FM3130_ALARM_MINUTES (0xa)
++#define FM3130_ALARM_HOURS (0xb)
++#define FM3130_ALARM_DATE (0xc)
++#define FM3130_ALARM_MONTHS (0xd)
++#define FM3130_ALARM_WP_CONTROL (0xe)
++
++#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */
++#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */
++#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */
++#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */
++#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */
++#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */
++#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */
++#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */
++#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */
++
++#define FM3130_CLOCK_REGS 7
++#define FM3130_ALARM_REGS 5
++
++struct fm3130 {
++ u8 reg_addr_time;
++ u8 reg_addr_alarm;
++ u8 regs[15];
++ struct i2c_msg msg[4];
++ struct i2c_client *client;
++ struct rtc_device *rtc;
++ int data_valid;
++ int alarm;
++};
++static const struct i2c_device_id fm3130_id[] = {
++ { "fm3130-rtc", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, fm3130_id);
++
++#define FM3130_MODE_NORMAL 0
++#define FM3130_MODE_WRITE 1
++#define FM3130_MODE_READ 2
++
++static void fm3130_rtc_mode(struct device *dev, int mode)
++{
++ struct fm3130 *fm3130 = dev_get_drvdata(dev);
++
++ fm3130->regs[FM3130_RTC_CONTROL] =
++ i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
++ switch (mode) {
++ case FM3130_MODE_NORMAL:
++ fm3130->regs[FM3130_RTC_CONTROL] &=
++ ~(FM3130_RTC_CONTROL_BIT_WRITE |
++ FM3130_RTC_CONTROL_BIT_READ);
++ break;
++ case FM3130_MODE_WRITE:
++ fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE;
++ break;
++ case FM3130_MODE_READ:
++ fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ;
++ break;
++ default:
++ dev_dbg(dev, "invalid mode %d\n", mode);
++ break;
++ }
++ /* Checking for alarm */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
++ fm3130->alarm = 1;
++ fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
++ }
++ i2c_smbus_write_byte_data(fm3130->client,
++ FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]);
++}
++
++static int fm3130_get_time(struct device *dev, struct rtc_time *t)
++{
++ struct fm3130 *fm3130 = dev_get_drvdata(dev);
++ int tmp;
++
++ if (!fm3130->data_valid) {
++ /* We have invalid data in RTC, probably due
++ to battery faults or other problems. Return EIO
++ for now, it will allow us to set data later insted
++ of error during probing which disables device */
++ return -EIO;
++ }
++ fm3130_rtc_mode(dev, FM3130_MODE_READ);
++
++ /* read the RTC date and time registers all at once */
++ tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
++ fm3130->msg, 2);
++ if (tmp != 2) {
++ dev_err(dev, "%s error %d\n", "read", tmp);
++ return -EIO;
++ }
++
++ fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
++
++ dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x"
++ "%02x %02x %02x %02x %02x %02x %02x\n",
++ "read",
++ fm3130->regs[0], fm3130->regs[1],
++ fm3130->regs[2], fm3130->regs[3],
++ fm3130->regs[4], fm3130->regs[5],
++ fm3130->regs[6], fm3130->regs[7],
++ fm3130->regs[8], fm3130->regs[9],
++ fm3130->regs[0xa], fm3130->regs[0xb],
++ fm3130->regs[0xc], fm3130->regs[0xd],
++ fm3130->regs[0xe]);
++
++ t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
++ t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
++ tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
++ t->tm_hour = BCD2BIN(tmp);
++ t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
++ t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
++ tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
++ t->tm_mon = BCD2BIN(tmp) - 1;
++
++ /* assume 20YY not 19YY, and ignore CF bit */
++ t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100;
++
++ dev_dbg(dev, "%s secs=%d, mins=%d, "
++ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
++ "read", t->tm_sec, t->tm_min,
++ t->tm_hour, t->tm_mday,
++ t->tm_mon, t->tm_year, t->tm_wday);
++
++ /* initial clock setting can be undefined */
++ return rtc_valid_tm(t);
++}
++
++
++static int fm3130_set_time(struct device *dev, struct rtc_time *t)
++{
++ struct fm3130 *fm3130 = dev_get_drvdata(dev);
++ int tmp, i;
++ u8 *buf = fm3130->regs;
++
++ dev_dbg(dev, "%s secs=%d, mins=%d, "
++ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
++ "write", t->tm_sec, t->tm_min,
++ t->tm_hour, t->tm_mday,
++ t->tm_mon, t->tm_year, t->tm_wday);
++
++ /* first register addr */
++ buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec);
++ buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min);
++ buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour);
++ buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1);
++ buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday);
++ buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1);
++
++ /* assume 20YY not 19YY */
++ tmp = t->tm_year - 100;
++ buf[FM3130_RTC_YEARS] = BIN2BCD(tmp);
++
++ dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x"
++ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
++ "write", buf[0], buf[1], buf[2], buf[3],
++ buf[4], buf[5], buf[6], buf[7],
++ buf[8], buf[9], buf[0xa], buf[0xb],
++ buf[0xc], buf[0xd], buf[0xe]);
++
++ fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
++
++ /* Writing time registers, we don't support multibyte transfers */
++ for (i = 0; i < FM3130_CLOCK_REGS; i++) {
++ i2c_smbus_write_byte_data(fm3130->client,
++ FM3130_RTC_SECONDS + i,
++ fm3130->regs[FM3130_RTC_SECONDS + i]);
++ }
++
++ fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
++
++ /* We assume here that data are valid once written */
++ if (!fm3130->data_valid)
++ fm3130->data_valid = 1;
++ return 0;
++}
++
++static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++ struct fm3130 *fm3130 = dev_get_drvdata(dev);
++ int tmp;
++ struct rtc_time *tm = &alrm->time;
++ /* read the RTC alarm registers all at once */
++ tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
++ &fm3130->msg[2], 2);
++ if (tmp != 2) {
++ dev_err(dev, "%s error %d\n", "read", tmp);
++ return -EIO;
++ }
++ dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
++ fm3130->regs[FM3130_ALARM_SECONDS],
++ fm3130->regs[FM3130_ALARM_MINUTES],
++ fm3130->regs[FM3130_ALARM_HOURS],
++ fm3130->regs[FM3130_ALARM_DATE],
++ fm3130->regs[FM3130_ALARM_MONTHS]);
++
++
++ tm->tm_sec = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
++ tm->tm_min = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
++ tm->tm_hour = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
++ tm->tm_mday = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
++ tm->tm_mon = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
++ if (tm->tm_mon > 0)
++ tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
++ dev_dbg(dev, "%s secs=%d, mins=%d, "
++ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
++ "read alarm", tm->tm_sec, tm->tm_min,
++ tm->tm_hour, tm->tm_mday,
++ tm->tm_mon, tm->tm_year, tm->tm_wday);
++
++ return 0;
++}
++
++static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++ struct fm3130 *fm3130 = dev_get_drvdata(dev);
++ struct rtc_time *tm = &alrm->time;
++ int i;
++
++ dev_dbg(dev, "%s secs=%d, mins=%d, "
++ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
++ "write alarm", tm->tm_sec, tm->tm_min,
++ tm->tm_hour, tm->tm_mday,
++ tm->tm_mon, tm->tm_year, tm->tm_wday);
++
++ if (tm->tm_sec != -1)
++ fm3130->regs[FM3130_ALARM_SECONDS] =
++ BIN2BCD(tm->tm_sec) | 0x80;
++
++ if (tm->tm_min != -1)
++ fm3130->regs[FM3130_ALARM_MINUTES] =
++ BIN2BCD(tm->tm_min) | 0x80;
++
++ if (tm->tm_hour != -1)
++ fm3130->regs[FM3130_ALARM_HOURS] =
++ BIN2BCD(tm->tm_hour) | 0x80;
++
++ if (tm->tm_mday != -1)
++ fm3130->regs[FM3130_ALARM_DATE] =
++ BIN2BCD(tm->tm_mday) | 0x80;
++
++ if (tm->tm_mon != -1)
++ fm3130->regs[FM3130_ALARM_MONTHS] =
++ BIN2BCD(tm->tm_mon + 1) | 0x80;
++
++ dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
++ fm3130->regs[FM3130_ALARM_SECONDS],
++ fm3130->regs[FM3130_ALARM_MINUTES],
++ fm3130->regs[FM3130_ALARM_HOURS],
++ fm3130->regs[FM3130_ALARM_DATE],
++ fm3130->regs[FM3130_ALARM_MONTHS]);
++ /* Writing time registers, we don't support multibyte transfers */
++ for (i = 0; i < FM3130_ALARM_REGS; i++) {
++ i2c_smbus_write_byte_data(fm3130->client,
++ FM3130_ALARM_SECONDS + i,
++ fm3130->regs[FM3130_ALARM_SECONDS + i]);
++ }
++ fm3130->regs[FM3130_RTC_CONTROL] =
++ i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
++ /* Checking for alarm */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
++ fm3130->alarm = 1;
++ fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
++ }
++ if (alrm->enabled) {
++ i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
++ (fm3130->regs[FM3130_RTC_CONTROL] &
++ ~(FM3130_RTC_CONTROL_BIT_CAL)) |
++ FM3130_RTC_CONTROL_BIT_AEN);
++ } else {
++ i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
++ fm3130->regs[FM3130_RTC_CONTROL] &
++ ~(FM3130_RTC_CONTROL_BIT_AEN));
++ }
++ return 0;
++}
++
++static const struct rtc_class_ops fm3130_rtc_ops = {
++ .read_time = fm3130_get_time,
++ .set_time = fm3130_set_time,
++ .read_alarm = fm3130_read_alarm,
++ .set_alarm = fm3130_set_alarm,
++};
++
++static struct i2c_driver fm3130_driver;
++
++static int __devinit fm3130_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct fm3130 *fm3130;
++ int err = -ENODEV;
++ int tmp;
++ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
++
++ if (!i2c_check_functionality(adapter,
++ I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
++ return -EIO;
++
++ fm3130 = kzalloc(sizeof(struct fm3130), GFP_KERNEL);
++
++ if (!fm3130)
++ return -ENOMEM;
++
++ fm3130->client = client;
++ i2c_set_clientdata(client, fm3130);
++ fm3130->reg_addr_time = FM3130_RTC_SECONDS;
++ fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
++
++ /* Messages to read time */
++ fm3130->msg[0].addr = client->addr;
++ fm3130->msg[0].flags = 0;
++ fm3130->msg[0].len = 1;
++ fm3130->msg[0].buf = &fm3130->reg_addr_time;
++
++ fm3130->msg[1].addr = client->addr;
++ fm3130->msg[1].flags = I2C_M_RD;
++ fm3130->msg[1].len = FM3130_CLOCK_REGS;
++ fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
++
++ /* Messages to read alarm */
++ fm3130->msg[2].addr = client->addr;
++ fm3130->msg[2].flags = 0;
++ fm3130->msg[2].len = 1;
++ fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
++
++ fm3130->msg[3].addr = client->addr;
++ fm3130->msg[3].flags = I2C_M_RD;
++ fm3130->msg[3].len = FM3130_ALARM_REGS;
++ fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
++
++ fm3130->data_valid = 0;
++
++ tmp = i2c_transfer(adapter, fm3130->msg, 4);
++ if (tmp != 4) {
++ pr_debug("read error %d\n", tmp);
++ err = -EIO;
++ goto exit_free;
++ }
++
++ fm3130->regs[FM3130_RTC_CONTROL] =
++ i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
++ fm3130->regs[FM3130_CAL_CONTROL] =
++ i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
++
++ /* Checking for alarm */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
++ fm3130->alarm = 1;
++ fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
++ }
++
++ /* Disabling calibration mode */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL)
++ i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
++ fm3130->regs[FM3130_RTC_CONTROL] &
++ ~(FM3130_RTC_CONTROL_BIT_CAL));
++ dev_warn(&client->dev, "Disabling calibration mode!\n");
++
++ /* Disabling read and write modes */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
++ fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ)
++ i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
++ fm3130->regs[FM3130_RTC_CONTROL] &
++ ~(FM3130_RTC_CONTROL_BIT_READ |
++ FM3130_RTC_CONTROL_BIT_WRITE));
++ dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
++
++ /* oscillator off? turn it on, so clock can tick. */
++ if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
++ i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
++ fm3130->regs[FM3130_CAL_CONTROL] &
++ ~(FM3130_CAL_CONTROL_BIT_nOSCEN));
++
++ /* oscillator fault? clear flag, and warn */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB)
++ dev_warn(&client->dev, "Low battery!\n");
++
++ /* oscillator fault? clear flag, and warn */
++ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
++ i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
++ fm3130->regs[FM3130_RTC_CONTROL] &
++ ~FM3130_RTC_CONTROL_BIT_POR);
++ dev_warn(&client->dev, "SET TIME!\n");
++ }
++ /* ACS is controlled by alarm */
++ i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
++
++ /* TODO */
++ /* TODO need to sanity check alarm */
++ tmp = fm3130->regs[FM3130_RTC_SECONDS];
++ tmp = BCD2BIN(tmp & 0x7f);
++ if (tmp > 60)
++ goto exit_bad;
++ tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
++ if (tmp > 60)
++ goto exit_bad;
++
++ tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
++ if (tmp == 0 || tmp > 31)
++ goto exit_bad;
++
++ tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
++ if (tmp == 0 || tmp > 12)
++ goto exit_bad;
++
++ tmp = fm3130->regs[FM3130_RTC_HOURS];
++
++ fm3130->data_valid = 1;
++
++exit_bad:
++ if (!fm3130->data_valid)
++ dev_dbg(&client->dev,
++ "%s: %02x %02x %02x %02x %02x %02x %02x %02x"
++ "%02x %02x %02x %02x %02x %02x %02x\n",
++ "bogus registers",
++ fm3130->regs[0], fm3130->regs[1],
++ fm3130->regs[2], fm3130->regs[3],
++ fm3130->regs[4], fm3130->regs[5],
++ fm3130->regs[6], fm3130->regs[7],
++ fm3130->regs[8], fm3130->regs[9],
++ fm3130->regs[0xa], fm3130->regs[0xb],
++ fm3130->regs[0xc], fm3130->regs[0xd],
++ fm3130->regs[0xe]);
++
++ /* We won't bail out here because we just got invalid data.
++ Time setting from u-boot doesn't work anyway */
++ fm3130->rtc = rtc_device_register(client->name, &client->dev,
++ &fm3130_rtc_ops, THIS_MODULE);
++ if (IS_ERR(fm3130->rtc)) {
++ err = PTR_ERR(fm3130->rtc);
++ dev_err(&client->dev,
++ "unable to register the class device\n");
++ goto exit_free;
++ }
++ return 0;
++exit_free:
++ kfree(fm3130);
++ return err;
++}
++
++static int __devexit fm3130_remove(struct i2c_client *client)
++{
++ struct fm3130 *fm3130 = i2c_get_clientdata(client);
++
++ rtc_device_unregister(fm3130->rtc);
++ kfree(fm3130);
++ return 0;
++}
++
++static struct i2c_driver fm3130_driver = {
++ .driver = {
++ .name = "rtc-fm3130",
++ .owner = THIS_MODULE,
++ },
++ .probe = fm3130_probe,
++ .remove = __devexit_p(fm3130_remove),
++ .id_table = fm3130_id,
++};
++
++static int __init fm3130_init(void)
++{
++ return i2c_add_driver(&fm3130_driver);
++}
++module_init(fm3130_init);
++
++static void __exit fm3130_exit(void)
++{
++ i2c_del_driver(&fm3130_driver);
++}
++module_exit(fm3130_exit);
++
++MODULE_DESCRIPTION("RTC driver for FM3130");
++MODULE_AUTHOR("Sergey Lapin <slapin at ossfans.org>");
++MODULE_LICENSE("GPL");
++
+diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
+index 35ac9d9..c14b243 100644
+--- a/drivers/video/cirrusfb.c
++++ b/drivers/video/cirrusfb.c
+@@ -2432,9 +2432,9 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
+ info->screen_size = board_size;
+ cinfo->unmap = cirrusfb_pci_unmap;
+
+- printk(KERN_INFO " RAM (%lu kB) at 0xx%lx, ",
+- info->screen_size >> 10, board_addr);
+- printk(KERN_INFO "Cirrus Logic chipset on PCI bus\n");
++ printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
++ "Logic chipset on PCI bus\n",
++ info->screen_size >> 10, board_addr);
+ pci_set_drvdata(pdev, info);
+
+ ret = cirrusfb_register(info);
+diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
+index fb9e672..c18880d 100644
+--- a/drivers/video/hgafb.c
++++ b/drivers/video/hgafb.c
+@@ -279,7 +279,7 @@ static void hga_blank(int blank_mode)
+
+ static int __init hga_card_detect(void)
+ {
+- int count=0;
++ int count = 0;
+ void __iomem *p, *q;
+ unsigned short p_save, q_save;
+
+@@ -303,20 +303,18 @@ static int __init hga_card_detect(void)
+ writew(0x55aa, p); if (readw(p) == 0x55aa) count++;
+ writew(p_save, p);
+
+- if (count != 2) {
+- return 0;
+- }
++ if (count != 2)
++ goto error;
+
+ /* Ok, there is definitely a card registering at the correct
+ * memory location, so now we do an I/O port test.
+ */
+
+- if (!test_hga_b(0x66, 0x0f)) { /* cursor low register */
+- return 0;
+- }
+- if (!test_hga_b(0x99, 0x0f)) { /* cursor low register */
+- return 0;
+- }
++ if (!test_hga_b(0x66, 0x0f)) /* cursor low register */
++ goto error;
++
++ if (!test_hga_b(0x99, 0x0f)) /* cursor low register */
++ goto error;
+
+ /* See if the card is a Hercules, by checking whether the vsync
+ * bit of the status register is changing. This test lasts for
+@@ -331,7 +329,7 @@ static int __init hga_card_detect(void)
+ }
+
+ if (p_save == q_save)
+- return 0;
++ goto error;
+
+ switch (inb_p(HGA_STATUS_PORT) & 0x70) {
+ case 0x10:
+@@ -348,6 +346,12 @@ static int __init hga_card_detect(void)
+ break;
+ }
+ return 1;
++error:
++ if (release_io_ports)
++ release_region(0x3b0, 12);
++ if (release_io_port)
++ release_region(0x3bf, 1);
++ return 0;
+ }
+
+ /**
+diff --git a/fs/fat/file.c b/fs/fat/file.c
+index 27cc116..771326b 100644
+--- a/fs/fat/file.c
++++ b/fs/fat/file.c
+@@ -257,26 +257,34 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+ }
+ EXPORT_SYMBOL_GPL(fat_getattr);
+
+-static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode,
+- mode_t mode)
++static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
++ struct inode *inode, umode_t *mode_ptr)
+ {
+- mode_t mask, req = mode & ~S_IFMT;
++ mode_t mask, perm;
+
+- if (S_ISREG(mode))
++ /*
++ * Note, the basic check is already done by a caller of
++ * (attr->ia_mode & ~MSDOS_VALID_MODE)
++ */
++
++ if (S_ISREG(inode->i_mode))
+ mask = sbi->options.fs_fmask;
+ else
+ mask = sbi->options.fs_dmask;
+
++ perm = *mode_ptr & ~(S_IFMT | mask);
++
+ /*
+ * Of the r and x bits, all (subject to umask) must be present. Of the
+ * w bits, either all (subject to umask) or none must be present.
+ */
+- req &= ~mask;
+- if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
++ if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
+ return -EPERM;
+- if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask)))
++ if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
+ return -EPERM;
+
++ *mode_ptr &= S_IFMT | perm;
++
+ return 0;
+ }
+
+@@ -299,7 +307,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
+ {
+ struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
+ struct inode *inode = dentry->d_inode;
+- int mask, error = 0;
++ int error = 0;
+ unsigned int ia_valid;
+
+ lock_kernel();
+@@ -332,12 +340,13 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
+ error = 0;
+ goto out;
+ }
++
+ if (((attr->ia_valid & ATTR_UID) &&
+ (attr->ia_uid != sbi->options.fs_uid)) ||
+ ((attr->ia_valid & ATTR_GID) &&
+ (attr->ia_gid != sbi->options.fs_gid)) ||
+ ((attr->ia_valid & ATTR_MODE) &&
+- fat_check_mode(sbi, inode, attr->ia_mode) < 0))
++ (attr->ia_mode & ~MSDOS_VALID_MODE)))
+ error = -EPERM;
+
+ if (error) {
+@@ -346,15 +355,16 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
+ goto out;
+ }
+
+- error = inode_setattr(inode, attr);
+- if (error)
+- goto out;
++ /*
++ * We don't return -EPERM here. Yes, strange, but this is too
++ * old behavior.
++ */
++ if (attr->ia_valid & ATTR_MODE) {
++ if (fat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
++ attr->ia_valid &= ~ATTR_MODE;
++ }
+
+- if (S_ISDIR(inode->i_mode))
+- mask = sbi->options.fs_dmask;
+- else
+- mask = sbi->options.fs_fmask;
+- inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
++ error = inode_setattr(inode, attr);
+ out:
+ unlock_kernel();
+ return error;
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 1740362..ab8ccc9 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -315,9 +315,9 @@ struct mem_size_stats {
+ };
+
+ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+- void *private)
++ struct mm_walk *walk)
+ {
+- struct mem_size_stats *mss = private;
++ struct mem_size_stats *mss = walk->private;
+ struct vm_area_struct *vma = mss->vma;
+ pte_t *pte, ptent;
+ spinlock_t *ptl;
+@@ -365,19 +365,21 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ return 0;
+ }
+
+-static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range };
+-
+ static int show_smap(struct seq_file *m, void *v)
+ {
+ struct vm_area_struct *vma = v;
+ struct mem_size_stats mss;
+ int ret;
++ struct mm_walk smaps_walk = {
++ .pmd_entry = smaps_pte_range,
++ .mm = vma->vm_mm,
++ .private = &mss,
++ };
+
+ memset(&mss, 0, sizeof mss);
+ mss.vma = vma;
+ if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+- walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
+- &smaps_walk, &mss);
++ walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
+
+ ret = show_map(m, v);
+ if (ret)
+@@ -426,9 +428,9 @@ const struct file_operations proc_smaps_operations = {
+ };
+
+ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
+- unsigned long end, void *private)
++ unsigned long end, struct mm_walk *walk)
+ {
+- struct vm_area_struct *vma = private;
++ struct vm_area_struct *vma = walk->private;
+ pte_t *pte, ptent;
+ spinlock_t *ptl;
+ struct page *page;
+@@ -452,8 +454,6 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
+ return 0;
+ }
+
+-static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range };
+-
+ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -476,11 +476,17 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
+ return -ESRCH;
+ mm = get_task_mm(task);
+ if (mm) {
++ static struct mm_walk clear_refs_walk;
++ memset(&clear_refs_walk, 0, sizeof(clear_refs_walk));
++ clear_refs_walk.pmd_entry = clear_refs_pte_range;
++ clear_refs_walk.mm = mm;
+ down_read(&mm->mmap_sem);
+- for (vma = mm->mmap; vma; vma = vma->vm_next)
++ for (vma = mm->mmap; vma; vma = vma->vm_next) {
++ clear_refs_walk.private = vma;
+ if (!is_vm_hugetlb_page(vma))
+- walk_page_range(mm, vma->vm_start, vma->vm_end,
+- &clear_refs_walk, vma);
++ walk_page_range(vma->vm_start, vma->vm_end,
++ &clear_refs_walk);
++ }
+ flush_tlb_mm(mm);
+ up_read(&mm->mmap_sem);
+ mmput(mm);
+@@ -528,9 +534,9 @@ static int add_to_pagemap(unsigned long addr, u64 pfn,
+ }
+
+ static int pagemap_pte_hole(unsigned long start, unsigned long end,
+- void *private)
++ struct mm_walk *walk)
+ {
+- struct pagemapread *pm = private;
++ struct pagemapread *pm = walk->private;
+ unsigned long addr;
+ int err = 0;
+ for (addr = start; addr < end; addr += PAGE_SIZE) {
+@@ -547,24 +553,45 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte)
+ return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
+ }
+
++static unsigned long pte_to_pagemap_entry(pte_t pte)
++{
++ unsigned long pme = 0;
++ if (is_swap_pte(pte))
++ pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte))
++ | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP;
++ else if (pte_present(pte))
++ pme = PM_PFRAME(pte_pfn(pte))
++ | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT;
++ return pme;
++}
++
+ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+- void *private)
++ struct mm_walk *walk)
+ {
+- struct pagemapread *pm = private;
++ struct vm_area_struct *vma;
++ struct pagemapread *pm = walk->private;
+ pte_t *pte;
+ int err = 0;
+
++ /* find the first VMA at or above 'addr' */
++ vma = find_vma(walk->mm, addr);
+ for (; addr != end; addr += PAGE_SIZE) {
+ u64 pfn = PM_NOT_PRESENT;
+- pte = pte_offset_map(pmd, addr);
+- if (is_swap_pte(*pte))
+- pfn = PM_PFRAME(swap_pte_to_pagemap_entry(*pte))
+- | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP;
+- else if (pte_present(*pte))
+- pfn = PM_PFRAME(pte_pfn(*pte))
+- | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT;
+- /* unmap so we're not in atomic when we copy to userspace */
+- pte_unmap(pte);
++
++ /* check to see if we've left 'vma' behind
++ * and need a new, higher one */
++ if (vma && (addr >= vma->vm_end))
++ vma = find_vma(walk->mm, addr);
++
++ /* check that 'vma' actually covers this address,
++ * and that it isn't a huge page vma */
++ if (vma && (vma->vm_start <= addr) &&
++ !is_vm_hugetlb_page(vma)) {
++ pte = pte_offset_map(pmd, addr);
++ pfn = pte_to_pagemap_entry(*pte);
++ /* unmap before userspace copy */
++ pte_unmap(pte);
++ }
+ err = add_to_pagemap(addr, pfn, pm);
+ if (err)
+ return err;
+@@ -675,8 +702,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ * user buffer is tracked in "pm", and the walk
+ * will stop when we hit the end of the buffer.
+ */
+- ret = walk_page_range(mm, start_vaddr, end_vaddr,
+- &pagemap_walk, &pm);
++ ret = walk_page_range(start_vaddr, end_vaddr,
++ &pagemap_walk);
+ if (ret == PM_END_OF_BUFFER)
+ ret = 0;
+ /* don't need mmap_sem for these, but this looks cleaner */
+diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
+index 83d1f28..3e81064 100644
+--- a/include/asm-m68k/bitops.h
++++ b/include/asm-m68k/bitops.h
+@@ -410,8 +410,49 @@ static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
+ res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
+ return (p - addr) * 32 + res;
+ }
+-#define ext2_find_next_bit(addr, size, off) \
+- generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
++
++static inline int ext2_find_first_bit(const void *vaddr, unsigned size)
++{
++ const unsigned long *p = vaddr, *addr = vaddr;
++ int res;
++
++ if (!size)
++ return 0;
++
++ size = (size >> 5) + ((size & 31) > 0);
++ while (*p++ == 0UL) {
++ if (--size == 0)
++ return (p - addr) << 5;
++ }
++
++ --p;
++ for (res = 0; res < 32; res++)
++ if (ext2_test_bit(res, p))
++ break;
++ return (p - addr) * 32 + res;
++}
++
++static inline int ext2_find_next_bit(const void *vaddr, unsigned size,
++ unsigned offset)
++{
++ const unsigned long *addr = vaddr;
++ const unsigned long *p = addr + (offset >> 5);
++ int bit = offset & 31UL, res;
++
++ if (offset >= size)
++ return size;
++
++ if (bit) {
++ /* Look for one in first longword */
++ for (res = bit; res < 32; res++)
++ if (ext2_test_bit(res, p))
++ return (p - addr) * 32 + res;
++ p++;
++ }
++ /* No set bit yet, search remaining full bytes for a set bit */
++ res = ext2_find_first_bit(p, size - 32 * (p - addr));
++ return (p - addr) * 32 + res;
++}
+
+ #endif /* __KERNEL__ */
+
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index c31a9cd..586a943 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -760,16 +760,17 @@ unsigned long unmap_vmas(struct mmu_gather **tlb,
+ * (see walk_page_range for more details)
+ */
+ struct mm_walk {
+- int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *);
+- int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *);
+- int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *);
+- int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *);
+- int (*pte_hole)(unsigned long, unsigned long, void *);
++ int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, struct mm_walk *);
++ int (*pud_entry)(pud_t *, unsigned long, unsigned long, struct mm_walk *);
++ int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *);
++ int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *);
++ int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *);
++ struct mm_struct *mm;
++ void *private;
+ };
+
+-int walk_page_range(const struct mm_struct *, unsigned long addr,
+- unsigned long end, const struct mm_walk *walk,
+- void *private);
++int walk_page_range(unsigned long addr, unsigned long end,
++ struct mm_walk *walk);
+ void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+ unsigned long end, unsigned long floor, unsigned long ceiling);
+ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 9b940e6..eafc9d6 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -716,6 +716,7 @@
+ #define PCI_DEVICE_ID_HP_CISSA 0x3220
+ #define PCI_DEVICE_ID_HP_CISSC 0x3230
+ #define PCI_DEVICE_ID_HP_CISSD 0x3238
++#define PCI_DEVICE_ID_HP_CISSE 0x323a
+ #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
+
+ #define PCI_VENDOR_ID_PCTECH 0x1042
+diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
+index 9883bc9..fff1d27 100644
+--- a/include/linux/proc_fs.h
++++ b/include/linux/proc_fs.h
+@@ -9,6 +9,8 @@
+
+ struct net;
+ struct completion;
++struct mm_struct;
++
+ /*
+ * The proc filesystem constants/structures
+ */
+@@ -101,8 +103,6 @@ extern spinlock_t proc_subdir_lock;
+ extern void proc_root_init(void);
+ extern void proc_misc_init(void);
+
+-struct mm_struct;
+-
+ void proc_flush_task(struct task_struct *task);
+ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
+ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
+diff --git a/ipc/shm.c b/ipc/shm.c
+index d05f6b5..790240c 100644
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -1058,16 +1058,16 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
+ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
+ {
+ struct shmid_kernel *shp = it;
+- char *format;
+
+-#define SMALL_STRING "%10d %10d %4o %10u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
+-#define BIG_STRING "%10d %10d %4o %21u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
++#if BITS_PER_LONG <= 32
++#define SIZE_SPEC "%10lu"
++#else
++#define SIZE_SPEC "%21lu"
++#endif
+
+- if (sizeof(size_t) <= sizeof(int))
+- format = SMALL_STRING;
+- else
+- format = BIG_STRING;
+- return seq_printf(s, format,
++ return seq_printf(s,
++ "%10d %10d %4o " SIZE_SPEC " %5u %5u "
++ "%5lu %5u %5u %5u %5u %10lu %10lu %10lu\n",
+ shp->shm_perm.key,
+ shp->shm_perm.id,
+ shp->shm_perm.mode,
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+index 1e0250c..d4998f8 100644
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -699,8 +699,9 @@ static int __register_kprobes(struct kprobe **kps, int num,
+ return -EINVAL;
+ for (i = 0; i < num; i++) {
+ ret = __register_kprobe(kps[i], called_from);
+- if (ret < 0 && i > 0) {
+- unregister_kprobes(kps, i);
++ if (ret < 0) {
++ if (i > 0)
++ unregister_kprobes(kps, i);
+ break;
+ }
+ }
+@@ -776,8 +777,9 @@ static int __register_jprobes(struct jprobe **jps, int num,
+ jp->kp.break_handler = longjmp_break_handler;
+ ret = __register_kprobe(&jp->kp, called_from);
+ }
+- if (ret < 0 && i > 0) {
+- unregister_jprobes(jps, i);
++ if (ret < 0) {
++ if (i > 0)
++ unregister_jprobes(jps, i);
+ break;
+ }
+ }
+@@ -920,8 +922,9 @@ static int __register_kretprobes(struct kretprobe **rps, int num,
+ return -EINVAL;
+ for (i = 0; i < num; i++) {
+ ret = __register_kretprobe(rps[i], called_from);
+- if (ret < 0 && i > 0) {
+- unregister_kretprobes(rps, i);
++ if (ret < 0) {
++ if (i > 0)
++ unregister_kretprobes(rps, i);
+ break;
+ }
+ }
+diff --git a/lib/radix-tree.c b/lib/radix-tree.c
+index bd52171..169a2f8 100644
+--- a/lib/radix-tree.c
++++ b/lib/radix-tree.c
+@@ -88,6 +88,57 @@ static inline gfp_t root_gfp_mask(struct radix_tree_root *root)
+ return root->gfp_mask & __GFP_BITS_MASK;
+ }
+
++static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
++ int offset)
++{
++ __set_bit(offset, node->tags[tag]);
++}
++
++static inline void tag_clear(struct radix_tree_node *node, unsigned int tag,
++ int offset)
++{
++ __clear_bit(offset, node->tags[tag]);
++}
++
++static inline int tag_get(struct radix_tree_node *node, unsigned int tag,
++ int offset)
++{
++ return test_bit(offset, node->tags[tag]);
++}
++
++static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag)
++{
++ root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT));
++}
++
++static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag)
++{
++ root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT));
++}
++
++static inline void root_tag_clear_all(struct radix_tree_root *root)
++{
++ root->gfp_mask &= __GFP_BITS_MASK;
++}
++
++static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag)
++{
++ return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT));
++}
++
++/*
++ * Returns 1 if any slot in the node has this tag set.
++ * Otherwise returns 0.
++ */
++static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag)
++{
++ int idx;
++ for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
++ if (node->tags[tag][idx])
++ return 1;
++ }
++ return 0;
++}
+ /*
+ * This assumes that the caller has performed appropriate preallocation, and
+ * that the caller has pinned this thread of control to the current CPU.
+@@ -124,6 +175,17 @@ static void radix_tree_node_rcu_free(struct rcu_head *head)
+ {
+ struct radix_tree_node *node =
+ container_of(head, struct radix_tree_node, rcu_head);
++
++ /*
++ * must only free zeroed nodes into the slab. radix_tree_shrink
++ * can leave us with a non-NULL entry in the first slot, so clear
++ * that here to make sure.
++ */
++ tag_clear(node, 0, 0);
++ tag_clear(node, 1, 0);
++ node->slots[0] = NULL;
++ node->count = 0;
++
+ kmem_cache_free(radix_tree_node_cachep, node);
+ }
+
+@@ -165,59 +227,6 @@ out:
+ }
+ EXPORT_SYMBOL(radix_tree_preload);
+
+-static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
+- int offset)
+-{
+- __set_bit(offset, node->tags[tag]);
+-}
+-
+-static inline void tag_clear(struct radix_tree_node *node, unsigned int tag,
+- int offset)
+-{
+- __clear_bit(offset, node->tags[tag]);
+-}
+-
+-static inline int tag_get(struct radix_tree_node *node, unsigned int tag,
+- int offset)
+-{
+- return test_bit(offset, node->tags[tag]);
+-}
+-
+-static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag)
+-{
+- root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT));
+-}
+-
+-
+-static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag)
+-{
+- root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT));
+-}
+-
+-static inline void root_tag_clear_all(struct radix_tree_root *root)
+-{
+- root->gfp_mask &= __GFP_BITS_MASK;
+-}
+-
+-static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag)
+-{
+- return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT));
+-}
+-
+-/*
+- * Returns 1 if any slot in the node has this tag set.
+- * Otherwise returns 0.
+- */
+-static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag)
+-{
+- int idx;
+- for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
+- if (node->tags[tag][idx])
+- return 1;
+- }
+- return 0;
+-}
+-
+ /*
+ * Return the maximum key which can be store into a
+ * radix tree with height HEIGHT.
+@@ -930,11 +939,6 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
+ newptr = radix_tree_ptr_to_indirect(newptr);
+ root->rnode = newptr;
+ root->height--;
+- /* must only free zeroed nodes into the slab */
+- tag_clear(to_free, 0, 0);
+- tag_clear(to_free, 1, 0);
+- to_free->slots[0] = NULL;
+- to_free->count = 0;
+ radix_tree_node_free(to_free);
+ }
+ }
+diff --git a/mm/pagewalk.c b/mm/pagewalk.c
+index 0afd238..d5878be 100644
+--- a/mm/pagewalk.c
++++ b/mm/pagewalk.c
+@@ -3,14 +3,14 @@
+ #include <linux/sched.h>
+
+ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+- const struct mm_walk *walk, void *private)
++ struct mm_walk *walk)
+ {
+ pte_t *pte;
+ int err = 0;
+
+ pte = pte_offset_map(pmd, addr);
+ for (;;) {
+- err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private);
++ err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, walk);
+ if (err)
+ break;
+ addr += PAGE_SIZE;
+@@ -24,7 +24,7 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ }
+
+ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
+- const struct mm_walk *walk, void *private)
++ struct mm_walk *walk)
+ {
+ pmd_t *pmd;
+ unsigned long next;
+@@ -35,15 +35,15 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd)) {
+ if (walk->pte_hole)
+- err = walk->pte_hole(addr, next, private);
++ err = walk->pte_hole(addr, next, walk);
+ if (err)
+ break;
+ continue;
+ }
+ if (walk->pmd_entry)
+- err = walk->pmd_entry(pmd, addr, next, private);
++ err = walk->pmd_entry(pmd, addr, next, walk);
+ if (!err && walk->pte_entry)
+- err = walk_pte_range(pmd, addr, next, walk, private);
++ err = walk_pte_range(pmd, addr, next, walk);
+ if (err)
+ break;
+ } while (pmd++, addr = next, addr != end);
+@@ -52,7 +52,7 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
+ }
+
+ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+- const struct mm_walk *walk, void *private)
++ struct mm_walk *walk)
+ {
+ pud_t *pud;
+ unsigned long next;
+@@ -63,15 +63,15 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud)) {
+ if (walk->pte_hole)
+- err = walk->pte_hole(addr, next, private);
++ err = walk->pte_hole(addr, next, walk);
+ if (err)
+ break;
+ continue;
+ }
+ if (walk->pud_entry)
+- err = walk->pud_entry(pud, addr, next, private);
++ err = walk->pud_entry(pud, addr, next, walk);
+ if (!err && (walk->pmd_entry || walk->pte_entry))
+- err = walk_pmd_range(pud, addr, next, walk, private);
++ err = walk_pmd_range(pud, addr, next, walk);
+ if (err)
+ break;
+ } while (pud++, addr = next, addr != end);
+@@ -85,15 +85,15 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+ * @addr: starting address
+ * @end: ending address
+ * @walk: set of callbacks to invoke for each level of the tree
+- * @private: private data passed to the callback function
+ *
+ * Recursively walk the page table for the memory area in a VMA,
+ * calling supplied callbacks. Callbacks are called in-order (first
+ * PGD, first PUD, first PMD, first PTE, second PTE... second PMD,
+ * etc.). If lower-level callbacks are omitted, walking depth is reduced.
+ *
+- * Each callback receives an entry pointer, the start and end of the
+- * associated range, and a caller-supplied private data pointer.
++ * Each callback receives an entry pointer and the start and end of the
++ * associated range, and a copy of the original mm_walk for access to
++ * the ->private or ->mm fields.
+ *
+ * No locks are taken, but the bottom level iterator will map PTE
+ * directories from highmem if necessary.
+@@ -101,9 +101,8 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+ * If any callback returns a non-zero value, the walk is aborted and
+ * the return value is propagated back to the caller. Otherwise 0 is returned.
+ */
+-int walk_page_range(const struct mm_struct *mm,
+- unsigned long addr, unsigned long end,
+- const struct mm_walk *walk, void *private)
++int walk_page_range(unsigned long addr, unsigned long end,
++ struct mm_walk *walk)
+ {
+ pgd_t *pgd;
+ unsigned long next;
+@@ -112,21 +111,24 @@ int walk_page_range(const struct mm_struct *mm,
+ if (addr >= end)
+ return err;
+
+- pgd = pgd_offset(mm, addr);
++ if (!walk->mm)
++ return -EINVAL;
++
++ pgd = pgd_offset(walk->mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd)) {
+ if (walk->pte_hole)
+- err = walk->pte_hole(addr, next, private);
++ err = walk->pte_hole(addr, next, walk);
+ if (err)
+ break;
+ continue;
+ }
+ if (walk->pgd_entry)
+- err = walk->pgd_entry(pgd, addr, next, private);
++ err = walk->pgd_entry(pgd, addr, next, walk);
+ if (!err &&
+ (walk->pud_entry || walk->pmd_entry || walk->pte_entry))
+- err = walk_pud_range(pgd, addr, next, walk, private);
++ err = walk_pud_range(pgd, addr, next, walk);
+ if (err)
+ break;
+ } while (pgd++, addr = next, addr != end);
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 9a29901..967d30c 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1307,7 +1307,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
+ struct scan_control *sc)
+ {
+ int priority;
+- int ret = 0;
++ unsigned long ret = 0;
+ unsigned long total_scanned = 0;
+ unsigned long nr_reclaimed = 0;
+ struct reclaim_state *reclaim_state = current->reclaim_state;
+diff --git a/security/dummy.c b/security/dummy.c
+index f50c6c3..b891688 100644
+--- a/security/dummy.c
++++ b/security/dummy.c
+@@ -27,6 +27,8 @@
+ #include <linux/hugetlb.h>
+ #include <linux/ptrace.h>
+ #include <linux/file.h>
++#include <linux/prctl.h>
++#include <linux/securebits.h>
+
+ static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
+ {
+@@ -607,7 +609,27 @@ static int dummy_task_kill (struct task_struct *p, struct siginfo *info,
+ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5, long *rc_p)
+ {
+- return 0;
++ switch (option) {
++ case PR_CAPBSET_READ:
++ *rc_p = (cap_valid(arg2) ? 1 : -EINVAL);
++ break;
++ case PR_GET_KEEPCAPS:
++ *rc_p = issecure(SECURE_KEEP_CAPS);
++ break;
++ case PR_SET_KEEPCAPS:
++ if (arg2 > 1)
++ *rc_p = -EINVAL;
++ else if (arg2)
++ current->securebits |= issecure_mask(SECURE_KEEP_CAPS);
++ else
++ current->securebits &=
++ ~issecure_mask(SECURE_KEEP_CAPS);
++ break;
++ default:
++ return 0;
++ }
++
++ return 1;
+ }
+
+ static void dummy_task_reparent_to_init (struct task_struct *p)
Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 (original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 Fri Jun 13 10:08:46 2008
@@ -1,4 +1,4 @@
-#+ bugfix/all/patch-2.6.26-rc5-git3
++ bugfix/all/patch-2.6.26-rc6-git1
+ debian/version.patch
+ debian/kernelvariables.patch
+ debian/doc-build-parallel.patch
More information about the Kernel-svn-changes
mailing list