diff options
| -rw-r--r-- | driver/sysfs-fix-condition-check-in-sysfs_drop_dentry.patch | 32 | ||||
| -rw-r--r-- | driver/sysfs-fix-race-condition-around-sd-s_dentry-take-2.patch | 131 | ||||
| -rw-r--r-- | driver/sysfs-store-sysfs-inode-nrs-in-s_ino-to-avoid-readdir-oopses.patch | 115 | ||||
| -rw-r--r-- | gregkh/hpet_patches_45.patch | 490 | ||||
| -rw-r--r-- | series | 6 | ||||
| -rw-r--r-- | version | 2 |
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)) { @@ -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 @@ -1 +1 @@ -2.6.22-rc4-git4 +2.6.22-rc4-git5 |
