aboutsummaryrefslogtreecommitdiffstats
diff options
-rw-r--r--driver/sysfs-fix-condition-check-in-sysfs_drop_dentry.patch32
-rw-r--r--driver/sysfs-fix-race-condition-around-sd-s_dentry-take-2.patch131
-rw-r--r--driver/sysfs-store-sysfs-inode-nrs-in-s_ino-to-avoid-readdir-oopses.patch115
-rw-r--r--gregkh/hpet_patches_45.patch490
-rw-r--r--series6
-rw-r--r--version2
6 files changed, 494 insertions, 282 deletions
diff --git a/driver/sysfs-fix-condition-check-in-sysfs_drop_dentry.patch b/driver/sysfs-fix-condition-check-in-sysfs_drop_dentry.patch
deleted file mode 100644
index 7b6b8daebba67b..00000000000000
--- a/driver/sysfs-fix-condition-check-in-sysfs_drop_dentry.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From htejun@gmail.com Tue Jun 12 09:21:21 2007
-From: Tejun Heo <htejun@gmail.com>
-Date: Mon, 11 Jun 2007 14:03:27 +0900
-Subject: sysfs: fix condition check in sysfs_drop_dentry()
-To: <greg@kroah.com>, <akpm@linux-foundation.org>, <cebbert@redhat.com>, <sandeen@redhat.com>, <maneesh@in.ibm.com>, <cs@tequila.co.jp>
-Message-ID: <20070611050327.GL29122@htj.dyndns.org>
-Content-Disposition: inline
-
-From: Tejun Heo <htejun@gmail.com>
-
-The condition check doesn't make much sense as it basically always
-succeeds. This causes NULL dereferencing on certain cases. It seems
-that parentheses are put in the wrong place. Fix it.
-
-Signed-off-by: Tejun Heo <htejun@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- fs/sysfs/inode.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/fs/sysfs/inode.c
-+++ b/fs/sysfs/inode.c
-@@ -252,7 +252,7 @@ void sysfs_drop_dentry(struct sysfs_dire
- if (dentry) {
- spin_lock(&dcache_lock);
- spin_lock(&dentry->d_lock);
-- if (!(d_unhashed(dentry) && dentry->d_inode)) {
-+ if (!d_unhashed(dentry) && dentry->d_inode) {
- inode = dentry->d_inode;
- spin_lock(&inode->i_lock);
- __iget(inode);
diff --git a/driver/sysfs-fix-race-condition-around-sd-s_dentry-take-2.patch b/driver/sysfs-fix-race-condition-around-sd-s_dentry-take-2.patch
deleted file mode 100644
index 22e4a4081edd19..00000000000000
--- a/driver/sysfs-fix-race-condition-around-sd-s_dentry-take-2.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-From htejun@gmail.com Tue Jun 12 09:22:08 2007
-From: Tejun Heo <htejun@gmail.com>
-Date: Mon, 11 Jun 2007 14:04:01 +0900
-Subject: sysfs: fix race condition around sd->s_dentry, take#2
-To: <greg@kroah.com>, <akpm@linux-foundation.org>, <cebbert@redhat.com>, <sandeen@redhat.com>, <maneesh@in.ibm.com>, <cs@tequila.co.jp>
-Message-ID: <20070611050401.GM29122@htj.dyndns.org>
-Content-Disposition: inline
-
-From: Tejun Heo <htejun@gmail.com>
-
-Allowing attribute and symlink dentries to be reclaimed means
-sd->s_dentry can change dynamically. However, updates to the field
-are unsynchronized leading to race conditions. This patch adds
-sysfs_lock and use it to synchronize updates to sd->s_dentry.
-
-Due to the locking around ->d_iput, the check in sysfs_drop_dentry()
-is complex. sysfs_lock only protect sd->s_dentry pointer itself. The
-validity of the dentry is protected by dcache_lock, so whether dentry
-is alive or not can only be tested while holding both locks.
-
-This is minimal backport of sysfs_drop_dentry() rewrite in devel
-branch.
-
-Signed-off-by: Tejun Heo <htejun@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- fs/sysfs/dir.c | 22 ++++++++++++++++++++--
- fs/sysfs/inode.c | 18 +++++++++++++++++-
- fs/sysfs/sysfs.h | 1 +
- 3 files changed, 38 insertions(+), 3 deletions(-)
-
---- a/fs/sysfs/dir.c
-+++ b/fs/sysfs/dir.c
-@@ -13,14 +13,26 @@
- #include "sysfs.h"
-
- DECLARE_RWSEM(sysfs_rename_sem);
-+spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
-
- static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
- {
- struct sysfs_dirent * sd = dentry->d_fsdata;
-
- if (sd) {
-- BUG_ON(sd->s_dentry != dentry);
-- sd->s_dentry = NULL;
-+ /* sd->s_dentry is protected with sysfs_lock. This
-+ * allows sysfs_drop_dentry() to dereference it.
-+ */
-+ spin_lock(&sysfs_lock);
-+
-+ /* The dentry might have been deleted or another
-+ * lookup could have happened updating sd->s_dentry to
-+ * point the new dentry. Ignore if it isn't pointing
-+ * to this dentry.
-+ */
-+ if (sd->s_dentry == dentry)
-+ sd->s_dentry = NULL;
-+ spin_unlock(&sysfs_lock);
- sysfs_put(sd);
- }
- iput(inode);
-@@ -247,7 +259,10 @@ static int sysfs_attach_attr(struct sysf
- }
-
- dentry->d_fsdata = sysfs_get(sd);
-+ /* protect sd->s_dentry against sysfs_d_iput */
-+ spin_lock(&sysfs_lock);
- sd->s_dentry = dentry;
-+ spin_unlock(&sysfs_lock);
- error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
- if (error) {
- sysfs_put(sd);
-@@ -269,7 +284,10 @@ static int sysfs_attach_link(struct sysf
- int err = 0;
-
- dentry->d_fsdata = sysfs_get(sd);
-+ /* protect sd->s_dentry against sysfs_d_iput */
-+ spin_lock(&sysfs_lock);
- sd->s_dentry = dentry;
-+ spin_unlock(&sysfs_lock);
- err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
- if (!err) {
- dentry->d_op = &sysfs_dentry_ops;
---- a/fs/sysfs/inode.c
-+++ b/fs/sysfs/inode.c
-@@ -246,9 +246,23 @@ static inline void orphan_all_buffers(st
- */
- void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
- {
-- struct dentry * dentry = sd->s_dentry;
-+ struct dentry *dentry = NULL;
- struct inode *inode;
-
-+ /* We're not holding a reference to ->s_dentry dentry but the
-+ * field will stay valid as long as sysfs_lock is held.
-+ */
-+ spin_lock(&sysfs_lock);
-+ spin_lock(&dcache_lock);
-+
-+ /* dget dentry if it's still alive */
-+ if (sd->s_dentry && sd->s_dentry->d_inode)
-+ dentry = dget_locked(sd->s_dentry);
-+
-+ spin_unlock(&dcache_lock);
-+ spin_unlock(&sysfs_lock);
-+
-+ /* drop dentry */
- if (dentry) {
- spin_lock(&dcache_lock);
- spin_lock(&dentry->d_lock);
-@@ -268,6 +282,8 @@ void sysfs_drop_dentry(struct sysfs_dire
- spin_unlock(&dentry->d_lock);
- spin_unlock(&dcache_lock);
- }
-+
-+ dput(dentry);
- }
- }
-
---- a/fs/sysfs/sysfs.h
-+++ b/fs/sysfs/sysfs.h
-@@ -33,6 +33,7 @@ extern const unsigned char * sysfs_get_n
- extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
- extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
-
-+extern spinlock_t sysfs_lock;
- extern struct rw_semaphore sysfs_rename_sem;
- extern struct super_block * sysfs_sb;
- extern const struct file_operations sysfs_dir_operations;
diff --git a/driver/sysfs-store-sysfs-inode-nrs-in-s_ino-to-avoid-readdir-oopses.patch b/driver/sysfs-store-sysfs-inode-nrs-in-s_ino-to-avoid-readdir-oopses.patch
deleted file mode 100644
index ad22681aeb5dbc..00000000000000
--- a/driver/sysfs-store-sysfs-inode-nrs-in-s_ino-to-avoid-readdir-oopses.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-From htejun@gmail.com Tue Jun 12 09:20:09 2007
-From: Eric Sandeen <sandeen@sandeen.net>
-Date: Mon, 11 Jun 2007 14:02:45 +0900
-Subject: sysfs: store sysfs inode nrs in s_ino to avoid readdir oopses
-To: <greg@kroah.com>, <akpm@linux-foundation.org>, <cebbert@redhat.com>, <sandeen@redhat.com>, <maneesh@in.ibm.com>, <cs@tequila.co.jp>
-Message-ID: <20070611050245.GK29122@htj.dyndns.org>
-Content-Disposition: inline
-
-
-From: Eric Sandeen <sandeen@sandeen.net>
-
-Backport of
-ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.22-rc1/2.6.22-rc1-mm1/broken-out/gregkh-driver-sysfs-allocate-inode-number-using-ida.patch
-
-For regular files in sysfs, sysfs_readdir wants to traverse
-sysfs_dirent->s_dentry->d_inode->i_ino to get to the inode number.
-But, the dentry can be reclaimed under memory pressure, and there is
-no synchronization with readdir. This patch follows Tejun's scheme of
-allocating and storing an inode number in the new s_ino member of a
-sysfs_dirent, when dirents are created, and retrieving it from there
-for readdir, so that the pointer chain doesn't have to be traversed.
-
-Tejun's upstream patch uses a new-ish "ida" allocator which brings
-along some extra complexity; this -stable patch has a brain-dead
-incrementing counter which does not guarantee uniqueness, but because
-sysfs doesn't hash inodes as iunique expects, uniqueness wasn't
-guaranteed today anyway.
-
-Signed-off-by: Eric Sandeen <sandeen@redhat.com>
-Signed-off-by: Tejun Heo <htejun@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- fs/sysfs/dir.c | 16 +++++++++++-----
- fs/sysfs/inode.c | 1 +
- fs/sysfs/mount.c | 1 +
- fs/sysfs/sysfs.h | 1 +
- 4 files changed, 14 insertions(+), 5 deletions(-)
-
---- a/fs/sysfs/dir.c
-+++ b/fs/sysfs/dir.c
-@@ -30,6 +30,14 @@ static struct dentry_operations sysfs_de
- .d_iput = sysfs_d_iput,
- };
-
-+static unsigned int sysfs_inode_counter;
-+ino_t sysfs_get_inum(void)
-+{
-+ if (unlikely(sysfs_inode_counter < 3))
-+ sysfs_inode_counter = 3;
-+ return sysfs_inode_counter++;
-+}
-+
- /*
- * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
- */
-@@ -41,6 +49,7 @@ static struct sysfs_dirent * __sysfs_new
- if (!sd)
- return NULL;
-
-+ sd->s_ino = sysfs_get_inum();
- atomic_set(&sd->s_count, 1);
- atomic_set(&sd->s_event, 1);
- INIT_LIST_HEAD(&sd->s_children);
-@@ -509,7 +518,7 @@ static int sysfs_readdir(struct file * f
-
- switch (i) {
- case 0:
-- ino = dentry->d_inode->i_ino;
-+ ino = parent_sd->s_ino;
- if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
- break;
- filp->f_pos++;
-@@ -538,10 +547,7 @@ static int sysfs_readdir(struct file * f
-
- name = sysfs_get_name(next);
- len = strlen(name);
-- if (next->s_dentry)
-- ino = next->s_dentry->d_inode->i_ino;
-- else
-- ino = iunique(sysfs_sb, 2);
-+ ino = next->s_ino;
-
- if (filldir(dirent, name, len, filp->f_pos, ino,
- dt_type(next)) < 0)
---- a/fs/sysfs/inode.c
-+++ b/fs/sysfs/inode.c
-@@ -141,6 +141,7 @@ struct inode * sysfs_new_inode(mode_t mo
- inode->i_mapping->a_ops = &sysfs_aops;
- inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
- inode->i_op = &sysfs_inode_operations;
-+ inode->i_ino = sd->s_ino;
- lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
-
- if (sd->s_iattr) {
---- a/fs/sysfs/mount.c
-+++ b/fs/sysfs/mount.c
-@@ -33,6 +33,7 @@ static struct sysfs_dirent sysfs_root =
- .s_element = NULL,
- .s_type = SYSFS_ROOT,
- .s_iattr = NULL,
-+ .s_ino = 1,
- };
-
- static void sysfs_clear_inode(struct inode *inode)
---- a/fs/sysfs/sysfs.h
-+++ b/fs/sysfs/sysfs.h
-@@ -5,6 +5,7 @@ struct sysfs_dirent {
- void * s_element;
- int s_type;
- umode_t s_mode;
-+ ino_t s_ino;
- struct dentry * s_dentry;
- struct iattr * s_iattr;
- atomic_t s_event;
diff --git a/gregkh/hpet_patches_45.patch b/gregkh/hpet_patches_45.patch
new file mode 100644
index 00000000000000..bc7af741e51808
--- /dev/null
+++ b/gregkh/hpet_patches_45.patch
@@ -0,0 +1,490 @@
+From: http://www.linuxpowertop.org/patches/hpet_patches_45.patch
+Subject: Force HPET to be enabled for my laptop
+
+
+---
+ arch/i386/kernel/apic.c | 3 +
+ arch/i386/kernel/hpet.c | 101 ++++++++++++++-----------------------------
+ arch/i386/kernel/i8253.c | 26 +++++------
+ arch/i386/kernel/quirks.c | 101 +++++++++++++++++++++++++++++++++++++++++++
+ include/asm-i386/hpet.h | 3 +
+ include/linux/clockchips.h | 1
+ kernel/time/tick-broadcast.c | 17 +++----
+ kernel/time/tick-common.c | 20 +++++---
+ kernel/time/timekeeping.c | 2
+ 9 files changed, 178 insertions(+), 96 deletions(-)
+
+--- a/arch/i386/kernel/apic.c
++++ b/arch/i386/kernel/apic.c
+@@ -263,6 +263,9 @@ static void lapic_timer_setup(enum clock
+ v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+ apic_write_around(APIC_LVTT, v);
+ break;
++ case CLOCK_EVT_MODE_RESUME:
++ /* Nothing to do here */
++ break;
+ }
+
+ local_irq_restore(flags);
+--- a/arch/i386/kernel/hpet.c
++++ b/arch/i386/kernel/hpet.c
+@@ -125,6 +125,7 @@ static struct clock_event_device hpet_cl
+ .set_next_event = hpet_next_event,
+ .shift = 32,
+ .irq = 0,
++ .rating = 50,
+ };
+
+ static void hpet_start_counter(void)
+@@ -139,6 +140,12 @@ static void hpet_start_counter(void)
+ hpet_writel(cfg, HPET_CFG);
+ }
+
++static void hpet_restart_counter(void)
++{
++ ich_force_hpet_resume();
++ hpet_start_counter();
++}
++
+ static void hpet_enable_int(void)
+ {
+ unsigned long cfg = hpet_readl(HPET_CFG);
+@@ -187,6 +194,10 @@ static void hpet_set_mode(enum clock_eve
+ cfg &= ~HPET_TN_ENABLE;
+ hpet_writel(cfg, HPET_T0_CFG);
+ break;
++
++ case CLOCK_EVT_MODE_RESUME:
++ hpet_enable_int();
++ break;
+ }
+ }
+
+@@ -217,6 +228,7 @@ static struct clocksource clocksource_hp
+ .mask = HPET_MASK,
+ .shift = HPET_SHIFT,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++ .resume = hpet_restart_counter,
+ };
+
+ /*
+@@ -228,6 +240,9 @@ int __init hpet_enable(void)
+ uint64_t hpet_freq;
+ u64 tmp;
+
++ if (hpet_virt_address)
++ return 0;
++
+ if (!is_hpet_capable())
+ return 0;
+
+@@ -291,7 +306,6 @@ int __init hpet_enable(void)
+
+ clocksource_register(&clocksource_hpet);
+
+-
+ if (id & HPET_ID_LEGSUP) {
+ hpet_enable_int();
+ hpet_reserve_platform_timers(id);
+@@ -314,6 +328,26 @@ out_nohpet:
+ }
+
+
++static int __init hpet_late_init(void)
++{
++ if (boot_hpet_disable)
++ return -ENODEV;
++
++ if (!hpet_address) {
++ if (!force_hpet_address)
++ return -ENODEV;
++
++ hpet_address = force_hpet_address;
++ hpet_enable();
++ if (!hpet_virt_address)
++ return -ENODEV;
++ }
++
++ return 0;
++}
++module_init(hpet_late_init);
++
++
+ #ifdef CONFIG_HPET_EMULATE_RTC
+
+ /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
+@@ -524,68 +558,3 @@ irqreturn_t hpet_rtc_interrupt(int irq,
+ return IRQ_HANDLED;
+ }
+ #endif
+-
+-
+-/*
+- * Suspend/resume part
+- */
+-
+-#ifdef CONFIG_PM
+-
+-static int hpet_suspend(struct sys_device *sys_device, pm_message_t state)
+-{
+- unsigned long cfg = hpet_readl(HPET_CFG);
+-
+- cfg &= ~(HPET_CFG_ENABLE|HPET_CFG_LEGACY);
+- hpet_writel(cfg, HPET_CFG);
+-
+- return 0;
+-}
+-
+-static int hpet_resume(struct sys_device *sys_device)
+-{
+- unsigned int id;
+-
+- hpet_start_counter();
+-
+- id = hpet_readl(HPET_ID);
+-
+- if (id & HPET_ID_LEGSUP)
+- hpet_enable_int();
+-
+- return 0;
+-}
+-
+-static struct sysdev_class hpet_class = {
+- set_kset_name("hpet"),
+- .suspend = hpet_suspend,
+- .resume = hpet_resume,
+-};
+-
+-static struct sys_device hpet_device = {
+- .id = 0,
+- .cls = &hpet_class,
+-};
+-
+-
+-static __init int hpet_register_sysfs(void)
+-{
+- int err;
+-
+- if (!is_hpet_capable())
+- return 0;
+-
+- err = sysdev_class_register(&hpet_class);
+-
+- if (!err) {
+- err = sysdev_register(&hpet_device);
+- if (err)
+- sysdev_class_unregister(&hpet_class);
+- }
+-
+- return err;
+-}
+-
+-device_initcall(hpet_register_sysfs);
+-
+-#endif
+--- a/arch/i386/kernel/i8253.c
++++ b/arch/i386/kernel/i8253.c
+@@ -3,11 +3,11 @@
+ *
+ */
+ #include <linux/clockchips.h>
+-#include <linux/spinlock.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <linux/jiffies.h>
+-#include <linux/sysdev.h>
+ #include <linux/module.h>
+-#include <linux/init.h>
++#include <linux/spinlock.h>
+
+ #include <asm/smp.h>
+ #include <asm/delay.h>
+@@ -41,26 +41,24 @@ static void init_pit_timer(enum clock_ev
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(0x34, PIT_MODE);
+- udelay(10);
+ outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
+- udelay(10);
+ outb(LATCH >> 8 , PIT_CH0); /* MSB */
+ break;
+
+- /*
+- * Avoid unnecessary state transitions, as it confuses
+- * Geode / Cyrix based boxen.
+- */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+- if (evt->mode == CLOCK_EVT_MODE_UNUSED)
+- break;
+ case CLOCK_EVT_MODE_UNUSED:
+- if (evt->mode == CLOCK_EVT_MODE_SHUTDOWN)
+- break;
++ outb_p(0x30, PIT_MODE);
++ outb_p(0, PIT_CH0); /* LSB */
++ outb_p(0, PIT_CH0); /* MSB */
++ break;
++
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* One shot setup */
+ outb_p(0x38, PIT_MODE);
+- udelay(10);
++ break;
++
++ case CLOCK_EVT_MODE_RESUME:
++ /* Nothing to do here */
+ break;
+ }
+ spin_unlock_irqrestore(&i8253_lock, flags);
+--- a/arch/i386/kernel/quirks.c
++++ b/arch/i386/kernel/quirks.c
+@@ -4,6 +4,8 @@
+ #include <linux/pci.h>
+ #include <linux/irq.h>
+
++#include <asm/hpet.h>
++
+ #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
+
+ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+@@ -48,3 +50,102 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance);
+ #endif
++
++#if defined(CONFIG_HPET_TIMER)
++unsigned long force_hpet_address;
++
++static void __iomem *rcba_base;
++
++void ich_force_hpet_resume(void)
++{
++ u32 val;
++
++ if (!force_hpet_address)
++ return;
++
++ if (rcba_base == NULL)
++ BUG();
++
++ /* read the Function Disable register, dword mode only */
++ val = readl(rcba_base + 0x3404);
++ if (!(val & 0x80)) {
++ /* HPET disabled in HPTC. Trying to enable */
++ writel(val | 0x80, rcba_base + 0x3404);
++ }
++
++ val = readl(rcba_base + 0x3404);
++ if (!(val & 0x80))
++ BUG();
++ else
++ printk(KERN_DEBUG "Force enabled HPET at resume\n");
++
++ return;
++}
++
++static void ich_force_enable_hpet(struct pci_dev *dev)
++{
++ u32 val, rcba;
++ int err = 0;
++
++ if (hpet_address || force_hpet_address)
++ return;
++
++ pci_read_config_dword(dev, 0xF0, &rcba);
++ rcba &= 0xFFFFC000;
++ if (rcba == 0) {
++ printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
++ return;
++ }
++
++ /* use bits 31:14, 16 kB aligned */
++ rcba_base = ioremap_nocache(rcba, 0x4000);
++ if (rcba_base == NULL) {
++ printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
++ return;
++ }
++
++ /* read the Function Disable register, dword mode only */
++ val = readl(rcba_base + 0x3404);
++
++ if (val & 0x80) {
++ /* HPET is enabled in HPTC. Just not reported by BIOS */
++ val = val & 0x3;
++ force_hpet_address = 0xFED00000 | (val << 12);
++ printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++ force_hpet_address);
++ iounmap(rcba_base);
++ return;
++ }
++
++ /* HPET disabled in HPTC. Trying to enable */
++ writel(val | 0x80, rcba_base + 0x3404);
++
++ val = readl(rcba_base + 0x3404);
++ if (!(val & 0x80)) {
++ err = 1;
++ } else {
++ val = val & 0x3;
++ force_hpet_address = 0xFED00000 | (val << 12);
++ }
++
++ if (err) {
++ force_hpet_address = 0;
++ iounmap(rcba_base);
++ printk(KERN_DEBUG "Failed to force enable HPET\n");
++ } else {
++ printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++ force_hpet_address);
++ }
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
++ ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,
++ ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,
++ ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,
++ ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
++ ich_force_enable_hpet);
++#endif
+--- a/include/asm-i386/hpet.h
++++ b/include/asm-i386/hpet.h
+@@ -89,6 +89,7 @@
+ #define HPET_TICK_RATE (HZ * 100000UL)
+
+ extern unsigned long hpet_address; /* hpet memory map physical address */
++extern unsigned long force_hpet_address;
+ extern int is_hpet_enabled(void);
+
+ #ifdef CONFIG_X86_64
+@@ -102,6 +103,8 @@ extern int hpet_readl(unsigned long a);
+ extern int hpet_enable(void);
+ #endif
+
++void ich_force_hpet_resume(void);
++
+ #ifdef CONFIG_HPET_EMULATE_RTC
+ extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
+ extern int hpet_set_rtc_irq_bit(unsigned long bit_mask);
+--- a/include/linux/clockchips.h
++++ b/include/linux/clockchips.h
+@@ -23,6 +23,7 @@ enum clock_event_mode {
+ CLOCK_EVT_MODE_SHUTDOWN,
+ CLOCK_EVT_MODE_PERIODIC,
+ CLOCK_EVT_MODE_ONESHOT,
++ CLOCK_EVT_MODE_RESUME,
+ };
+
+ /* Clock event notification values */
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -58,8 +58,9 @@ static void tick_broadcast_start_periodi
+ */
+ int tick_check_broadcast_device(struct clock_event_device *dev)
+ {
+- if (tick_broadcast_device.evtdev ||
+- (dev->features & CLOCK_EVT_FEAT_C3STOP))
++ if ((tick_broadcast_device.evtdev &&
++ tick_broadcast_device.evtdev->rating >= dev->rating) ||
++ (dev->features & CLOCK_EVT_FEAT_C3STOP))
+ return 0;
+
+ clockevents_exchange_device(NULL, dev);
+@@ -299,7 +300,7 @@ void tick_suspend_broadcast(void)
+ spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+ bc = tick_broadcast_device.evtdev;
+- if (bc && tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
++ if (bc)
+ clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+
+ spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+@@ -316,6 +317,8 @@ int tick_resume_broadcast(void)
+ bc = tick_broadcast_device.evtdev;
+
+ if (bc) {
++ clockevents_set_mode(bc, CLOCK_EVT_MODE_RESUME);
++
+ switch (tick_broadcast_device.mode) {
+ case TICKDEV_MODE_PERIODIC:
+ if(!cpus_empty(tick_broadcast_mask))
+@@ -490,11 +493,9 @@ out:
+ */
+ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+ {
+- if (bc->mode != CLOCK_EVT_MODE_ONESHOT) {
+- bc->event_handler = tick_handle_oneshot_broadcast;
+- clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+- bc->next_event.tv64 = KTIME_MAX;
+- }
++ bc->event_handler = tick_handle_oneshot_broadcast;
++ clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
++ bc->next_event.tv64 = KTIME_MAX;
+ }
+
+ /*
+--- a/kernel/time/tick-common.c
++++ b/kernel/time/tick-common.c
+@@ -200,7 +200,7 @@ static int tick_check_new_device(struct
+
+ cpu = smp_processor_id();
+ if (!cpu_isset(cpu, newdev->cpumask))
+- goto out;
++ goto out_bc;
+
+ td = &per_cpu(tick_cpu_device, cpu);
+ curdev = td->evtdev;
+@@ -265,7 +265,7 @@ out_bc:
+ */
+ if (tick_check_broadcast_device(newdev))
+ ret = NOTIFY_STOP;
+-out:
++
+ spin_unlock_irqrestore(&tick_device_lock, flags);
+
+ return ret;
+@@ -318,12 +318,17 @@ static void tick_resume(void)
+ {
+ struct tick_device *td = &__get_cpu_var(tick_cpu_device);
+ unsigned long flags;
++ int broadcast = tick_resume_broadcast();
+
+ spin_lock_irqsave(&tick_device_lock, flags);
+- if (td->mode == TICKDEV_MODE_PERIODIC)
+- tick_setup_periodic(td->evtdev, 0);
+- else
+- tick_resume_oneshot();
++ clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
++
++ if (!broadcast) {
++ if (td->mode == TICKDEV_MODE_PERIODIC)
++ tick_setup_periodic(td->evtdev, 0);
++ else
++ tick_resume_oneshot();
++ }
+ spin_unlock_irqrestore(&tick_device_lock, flags);
+ }
+
+@@ -360,8 +365,7 @@ static int tick_notify(struct notifier_b
+ break;
+
+ case CLOCK_EVT_NOTIFY_RESUME:
+- if (!tick_resume_broadcast())
+- tick_resume();
++ tick_resume();
+ break;
+
+ default:
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -275,6 +275,8 @@ static int timekeeping_resume(struct sys
+
+ clocksource_resume();
+
++ clocksource_resume();
++
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ if (now && (now > timekeeping_suspend_time)) {
diff --git a/series b/series
index 788e2ecd5771aa..d59b7477e779fa 100644
--- a/series
+++ b/series
@@ -5,10 +5,10 @@ gregkh/sysfs-test.patch
gregkh/detect-atomic-counter-underflows.patch
+# HPET force on from powertop web site Will go upstream soon.
+gregkh/hpet_patches_45.patch
+
# driver patches queued for 2.6.22
-driver/sysfs-store-sysfs-inode-nrs-in-s_ino-to-avoid-readdir-oopses.patch
-driver/sysfs-fix-condition-check-in-sysfs_drop_dentry.patch
-driver/sysfs-fix-race-condition-around-sd-s_dentry-take-2.patch
# driver patches for after 2.6.22 is out
driver/sysfs-rules.patch
diff --git a/version b/version
index e2a23646b10cba..597f4b3da97b5a 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-2.6.22-rc4-git4
+2.6.22-rc4-git5