[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