--- /dev/null
+From stable-bounces@linux.kernel.org Sun Jul 27 16:55:10 2008
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Sun, 27 Jul 2008 23:55:02 GMT
+Subject: ARM: fix fls() for 64-bit arguments
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807272355.m6RNt2Gm015715@hera.kernel.org>
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+commit 0c65f459ce6c8bd873a61b3ae1e57858ab1debf3 upstream
+
+arm's fls() is implemented as a macro, causing it to misbehave when passed
+64-bit arguments. Fix.
+
+Cc: Nickolay Vinogradov <nickolay@protei.ru>
+Tested-by: Krzysztof Halasa <khc@pm.waw.pl>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/asm-arm/bitops.h | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/include/asm-arm/bitops.h
++++ b/include/asm-arm/bitops.h
+@@ -277,9 +277,16 @@ static inline int constant_fls(int x)
+ * the clz instruction for much better code efficiency.
+ */
+
+-#define fls(x) \
++#define __fls(x) \
+ ( __builtin_constant_p(x) ? constant_fls(x) : \
+ ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
++
++/* Implement fls() in C so that 64-bit args are suitably truncated */
++static inline int fls(int x)
++{
++ return __fls(x);
++}
++
+ #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
+ #define __ffs(x) (ffs(x) - 1)
+ #define ffz(x) __ffs( ~(x) )
--- /dev/null
+From stable-bounces@linux.kernel.org Tue Jul 22 13:05:29 2008
+From: Miao Xie <miaox@cn.fujitsu.com>
+Date: Tue, 22 Jul 2008 20:05:21 GMT
+Subject: cpusets: fix wrong domain attr updates
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807222005.m6MK5LsX030481@hera.kernel.org>
+
+From: Miao Xie <miaox@cn.fujitsu.com>
+
+commit 91cd4d6ef0abb1f65e81f8fe37e7d3c10344e38c upstream
+
+Fix wrong domain attr updates, or we will always update the first sched
+domain attr.
+
+Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
+Cc: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
+Cc: Paul Jackson <pj@sgi.com>
+Cc: Nick Piggin <nickpiggin@yahoo.com.au>
+Cc: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/cpuset.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/kernel/cpuset.c
++++ b/kernel/cpuset.c
+@@ -679,7 +679,9 @@ restart:
+ if (apn == b->pn) {
+ cpus_or(*dp, *dp, b->cpus_allowed);
+ b->pn = -1;
+- update_domain_attr(dattr, b);
++ if (dattr)
++ update_domain_attr(dattr
++ + nslot, b);
+ }
+ }
+ nslot++;
--- /dev/null
+From stable-bounces@linux.kernel.org Mon Jul 14 23:38:14 2008
+From: Dave Airlie <airlied@linux.ie>
+Date: Tue, 15 Jul 2008 07:05:59 +0100 (IST)
+Subject: drm/radeon: fixup issue with radeon and PAT support.
+To: stable@kernel.org
+Message-ID: <alpine.DEB.0.82.0807150704470.6038@skynet.skynet.ie>
+
+From: Dave Airlie <airlied@linux.ie>
+
+commit 242e3df80b8d25ed681c278512df0993725f25dd upstream
+
+With new userspace libpciaccess we can get a conflicting mapping
+on the PCIE GART table in the video RAM. Always try and map it _wc.
+
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/drm/drmP.h | 1 +
+ drivers/char/drm/drm_memory.c | 5 +++++
+ drivers/char/drm/radeon_cp.c | 2 +-
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/drm/drm_memory.c
++++ b/drivers/char/drm/drm_memory.c
+@@ -167,6 +167,11 @@ void drm_core_ioremap(struct drm_map *ma
+ }
+ EXPORT_SYMBOL(drm_core_ioremap);
+
++void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev)
++{
++ map->handle = ioremap_wc(map->offset, map->size);
++}
++EXPORT_SYMBOL(drm_core_ioremap_wc);
+ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+ {
+ if (!map->handle || !map->size)
+--- a/drivers/char/drm/drmP.h
++++ b/drivers/char/drm/drmP.h
+@@ -1089,6 +1089,7 @@ extern int drm_mm_remove_space_from_tail
+ extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
+
+ extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
++extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev);
+ extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
+
+ static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
+--- a/drivers/char/drm/radeon_cp.c
++++ b/drivers/char/drm/radeon_cp.c
+@@ -1154,7 +1154,7 @@ static int radeon_do_init_cp(struct drm_
+ dev_priv->gart_info.mapping.size =
+ dev_priv->gart_info.table_size;
+
+- drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
++ drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
+ dev_priv->gart_info.addr =
+ dev_priv->gart_info.mapping.handle;
+
--- /dev/null
+From stable-bounces@linux.kernel.org Tue Jul 22 13:05:23 2008
+From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+Date: Tue, 22 Jul 2008 20:05:17 GMT
+Subject: Fix build on COMPAT platforms when CONFIG_EPOLL is disabled
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807222005.m6MK5HSg030434@hera.kernel.org>
+
+From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+
+commit 5f17156fc55abac476d180e480bedb0f07f01b14 upstream
+
+Add missing cond_syscall() entry for compat_sys_epoll_pwait.
+
+Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+Cc: Davide Libenzi <davidel@xmailserver.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/sys_ni.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/kernel/sys_ni.c
++++ b/kernel/sys_ni.c
+@@ -59,6 +59,7 @@ cond_syscall(sys_epoll_create);
+ cond_syscall(sys_epoll_ctl);
+ cond_syscall(sys_epoll_wait);
+ cond_syscall(sys_epoll_pwait);
++cond_syscall(compat_sys_epoll_pwait);
+ cond_syscall(sys_semget);
+ cond_syscall(sys_semop);
+ cond_syscall(sys_semtimedop);
--- /dev/null
+From stable-bounces@linux.kernel.org Thu Jul 24 15:05:28 2008
+From: Jens Axboe <jens.axboe@oracle.com>
+Date: Thu, 24 Jul 2008 22:05:15 GMT
+Subject: ide-cd: fix oops when using growisofs
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807242205.m6OM5Fpx016312@hera.kernel.org>
+
+From: Jens Axboe <jens.axboe@oracle.com>
+
+commit e8e7b9eb11c34ee18bde8b7011af41938d1ad667 upstream
+
+cdrom_read_capacity() will blindly return the capacity from the device
+without sanity-checking it. This later causes code in fs/buffer.c to
+oops.
+
+Fix this by checking that the device is telling us sensible things.
+
+From: Jens Axboe <jens.axboe@oracle.com>
+Cc: Michael Buesch <mb@bu3sch.de>
+Cc: Jan Kara <jack@suse.cz>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Borislav Petkov <petkovbb@googlemail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[bart: print device name instead of driver name]
+Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+[harvey: blocklen is a big-endian value]
+Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
+Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ide/ide-cd.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -1308,13 +1308,30 @@ static int cdrom_read_capacity(ide_drive
+ req.cmd_flags |= REQ_QUIET;
+
+ stat = ide_cd_queue_pc(drive, &req);
+- if (stat == 0) {
+- *capacity = 1 + be32_to_cpu(capbuf.lba);
+- *sectors_per_frame =
+- be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
++ if (stat)
++ return stat;
++
++ /*
++ * Sanity check the given block size
++ */
++ switch (capbuf.blocklen) {
++ case __constant_cpu_to_be32(512):
++ case __constant_cpu_to_be32(1024):
++ case __constant_cpu_to_be32(2048):
++ case __constant_cpu_to_be32(4096):
++ break;
++ default:
++ printk(KERN_ERR "%s: weird block size %u\n",
++ drive->name, capbuf.blocklen);
++ printk(KERN_ERR "%s: default to 2kb block size\n",
++ drive->name);
++ capbuf.blocklen = __constant_cpu_to_be32(2048);
++ break;
+ }
+
+- return stat;
++ *capacity = 1 + be32_to_cpu(capbuf.lba);
++ *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
++ return 0;
+ }
+
+ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
--- /dev/null
+From stable-bounces@linux.kernel.org Tue Jul 22 13:05:23 2008
+From: Mathieu Desnoyers <compudj@krystal.dyndns.org>
+Date: Tue, 22 Jul 2008 20:05:14 GMT
+Subject: markers: fix duplicate modpost entry
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807222005.m6MK5Eji030413@hera.kernel.org>
+
+From: Mathieu Desnoyers <compudj@krystal.dyndns.org>
+
+commit: d35cb360c29956510b2fe1a953bd4968536f7216
+
+When a kernel was rebuilt, the previous Module.markers was not cleared.
+It caused markers with different format strings to appear as duplicates
+when a markers was changed. This problem is present since
+scripts/mod/modpost.c started to generate Module.markers, commit
+b2e3e658b344c6bcfb8fb694100ab2f2b5b2edb0
+
+It therefore applies to 2.6.25, 2.6.26 and linux-next.
+
+I merely merged the patches from Roland, Wenji and Takashi here.
+
+Credits to
+Roland McGrath <roland@redhat.com>
+Wenji Huang <wenji.huang@oracle.com>
+and
+Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
+
+for providing the individual fixes.
+
+- Changelog :
+ - Integrated Takashi's Makefile modification to clear Module.markers upon
+ make clean.
+
+Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+Cc: Roland McGrath <roland@redhat.com>
+Cc: Wenji Huang <wenji.huang@oracle.com>
+Cc: Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Makefile | 3 ++-
+ scripts/Makefile.modpost | 1 +
+ scripts/mod/modpost.c | 3 ++-
+ 3 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -1133,7 +1133,8 @@ clean: archclean $(clean-dirs)
+ @find . $(RCS_FIND_IGNORE) \
+ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+- -o -name '*.symtypes' -o -name 'modules.order' \) \
++ -o -name '*.symtypes' -o -name 'modules.order' \
++ -o -name 'Module.markers' \) \
+ -type f -print | xargs rm -f
+
+ # mrproper - Delete all generated files, including .config
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -101,6 +101,7 @@ quiet_cmd_kernel-mod = MODPOST $@
+ cmd_kernel-mod = $(modpost) $@
+
+ vmlinux.o: FORCE
++ @rm -fr $(kernelmarkersfile)
+ $(call cmd,kernel-mod)
+
+ # Declare generated files as targets for modpost
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -1992,7 +1992,8 @@ static void read_markers(const char *fna
+ mod->skip = 1;
+ }
+
+- add_marker(mod, marker, fmt);
++ if (!mod->skip)
++ add_marker(mod, marker, fmt);
+ }
+ return;
+ fail:
--- /dev/null
+From stable-bounces@linux.kernel.org Tue Jul 22 13:05:29 2008
+From: Alexey Dobriyan <adobriyan@gmail.com>
+Date: Tue, 22 Jul 2008 20:05:19 GMT
+Subject: proc: fix /proc/*/pagemap some more
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807222005.m6MK5J5f030454@hera.kernel.org>
+
+From: Alexey Dobriyan <adobriyan@gmail.com>
+
+commit ee1e6ab6056a8b9c19377257002da98b83819531 upstream
+
+struct pagemap_walk was placed on stack, some hooks are initialized, the
+rest (->pgd_entry, ->pud_entry, ->pte_entry) are valid but junk.
+
+Reported-by: Eric Sesterhenn <snakebyte@gmx.de>
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+Cc: "Vegard Nossum" <vegard.nossum@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/proc/task_mmu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -636,7 +636,7 @@ static ssize_t pagemap_read(struct file
+ struct pagemapread pm;
+ int pagecount;
+ int ret = -ESRCH;
+- struct mm_walk pagemap_walk;
++ struct mm_walk pagemap_walk = {};
+ unsigned long src;
+ unsigned long svpfn;
+ unsigned long start_vaddr;
--- /dev/null
+From stable-bounces@linux.kernel.org Thu Jul 24 15:05:38 2008
+From: David Brownell <dbrownell@users.sourceforge.net>
+Date: Thu, 24 Jul 2008 22:05:26 GMT
+Subject: rtc-at91rm9200: avoid spurious irqs
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807242205.m6OM5Qg3016519@hera.kernel.org>
+
+From: David Brownell <dbrownell@users.sourceforge.net>
+
+commit 449321b39f6c6ebfa15d6da24f134240bd51db29 upstream
+
+This fixes kernel http://bugzilla.kernel.org/show_bug.cgi?id=11112 (bogus
+RTC update IRQs reported) for rtc-at91rm9200 by scrubbing old IRQ status
+before enabling IRQs.
+
+It also removes nonfunctional periodic IRQ support from this driver;
+only update IRQs are reported, or provided by the hardware.
+
+I suspect some other RTCs probably have versions of #11112; it's easy to
+overlook, since most non-RTC drivers don't care about spurious IRQs:
+they're not reported to userspace.
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Report-by: W Unruh <unruh@physics.ubc.ca>
+Cc: Andrew Victor <avictor.za@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/rtc/rtc-at91rm9200.c | 16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+--- a/drivers/rtc/rtc-at91rm9200.c
++++ b/drivers/rtc/rtc-at91rm9200.c
+@@ -175,8 +175,10 @@ static int at91_rtc_setalarm(struct devi
+ | BIN2BCD(tm.tm_mday) << 24
+ | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
+
+- if (alrm->enabled)
++ if (alrm->enabled) {
++ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
++ }
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
+ at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
+@@ -195,28 +197,22 @@ static int at91_rtc_ioctl(struct device
+
+ pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
+
++ /* important: scrub old status before enabling IRQs */
+ switch (cmd) {
+ case RTC_AIE_OFF: /* alarm off */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
+ break;
+ case RTC_AIE_ON: /* alarm on */
++ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+ break;
+ case RTC_UIE_OFF: /* update off */
+- case RTC_PIE_OFF: /* periodic off */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
+ break;
+ case RTC_UIE_ON: /* update on */
+- case RTC_PIE_ON: /* periodic on */
++ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
+ break;
+- case RTC_IRQP_READ: /* read periodic alarm frequency */
+- ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
+- break;
+- case RTC_IRQP_SET: /* set periodic alarm frequency */
+- if (arg != AT91_RTC_FREQ)
+- ret = -EINVAL;
+- break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
fix-typos-from-signal_32-64.h-merge.patch
x86-reboot-quirks-add-dell-precision-workstation-t5400.patch
usb-fix-usb-serial-pm-counter-decrement-for-disconnected-interfaces.patch
+drm-radeon-fixup-issue-with-radeon-and-pat-support.patch
+x86-suspend-acpi-enter-big-real-mode.patch
+markers-fix-duplicate-modpost-entry.patch
+fix-build-on-compat-platforms-when-config_epoll-is-disabled.patch
+proc-fix-proc-pagemap-some-more.patch
+cpusets-fix-wrong-domain-attr-updates.patch
+x86-fix-crash-due-to-missing-debugctlmsr-on-amd-k6-3.patch
+ide-cd-fix-oops-when-using-growisofs.patch
+rtc-at91rm9200-avoid-spurious-irqs.patch
+vmlinux.lds-move-__attribute__-functions-back-into-final-.text-section.patch
+arm-fix-fls-for-64-bit-arguments.patch
+tcp-clear-probes_out-more-aggressively-in-tcp_ack.patch
+sparc64-fix-lockdep-issues-in-ldc-protocol-layer.patch
+sparc64-fix-cpufreq-notifier-registry.patch
+sparc64-do-not-define-bio_vmerge_boundary.patch
--- /dev/null
+From bceff746aadaf2323db12b211b19abca3d8ce790 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Mon, 21 Jul 2008 13:17:38 -0700
+Subject: sparc64: Do not define BIO_VMERGE_BOUNDARY.
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 74988bd85d1cb97987534fd7ffbc570e81145418 ]
+
+The IOMMU code and the block layer can split things
+up using different rules, so this can't work reliably.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/asm-sparc64/io.h | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/include/asm-sparc64/io.h
++++ b/include/asm-sparc64/io.h
+@@ -16,7 +16,6 @@
+ /* BIO layer definitions. */
+ extern unsigned long kern_base, kern_size;
+ #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+-#define BIO_VMERGE_BOUNDARY 8192
+
+ static inline u8 _inb(unsigned long addr)
+ {
--- /dev/null
+From f2df9aeeaee637dad3fb1c22420b7fd685380dc3 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Wed, 23 Jul 2008 16:21:07 -0700
+Subject: sparc64: Fix cpufreq notifier registry.
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 7ae93f51d7fa8b9130d47e0b7d17979a165c5bc3 ]
+
+Based upon a report by Daniel Smolik.
+
+We do it too early, which triggers a BUG in
+cpufreq_register_notifier().
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/kernel/time.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/arch/sparc64/kernel/time.c
++++ b/arch/sparc64/kernel/time.c
+@@ -883,6 +883,16 @@ static struct notifier_block sparc64_cpu
+ .notifier_call = sparc64_cpufreq_notifier
+ };
+
++static int __init register_sparc64_cpufreq_notifier(void)
++{
++
++ cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
++ CPUFREQ_TRANSITION_NOTIFIER);
++ return 0;
++}
++
++core_initcall(register_sparc64_cpufreq_notifier);
++
+ #endif /* CONFIG_CPU_FREQ */
+
+ static int sparc64_next_event(unsigned long delta,
+@@ -1049,11 +1059,6 @@ void __init time_init(void)
+ sparc64_clockevent.mult, sparc64_clockevent.shift);
+
+ setup_sparc64_timer();
+-
+-#ifdef CONFIG_CPU_FREQ
+- cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
+- CPUFREQ_TRANSITION_NOTIFIER);
+-#endif
+ }
+
+ unsigned long long sched_clock(void)
--- /dev/null
+From c6e4b2cc2b65fbcfcfce739d5f6aa9de65881387 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Tue, 22 Jul 2008 22:34:29 -0700
+Subject: sparc64: Fix lockdep issues in LDC protocol layer.
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit b7c2a75725dee9b5643a0aae3a4cb47f52e00a49 ]
+
+We're calling request_irq() with a IRQs disabled.
+
+No straightforward fix exists because we want to
+enable these IRQs and setup state atomically before
+getting into the IRQ handler the first time.
+
+What happens now is that we mark the VIRQ to not be
+automatically enabled by request_irq(). Then we
+make explicit enable_irq() calls when we grab the
+LDC channel.
+
+This way we don't need to call request_irq() illegally
+under the LDC channel lock any more.
+
+Bump LDC version and release date.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/kernel/irq.c | 10 +++++++++-
+ arch/sparc64/kernel/ldc.c | 38 +++++++++++++++++++-------------------
+ 2 files changed, 28 insertions(+), 20 deletions(-)
+
+--- a/arch/sparc64/kernel/irq.c
++++ b/arch/sparc64/kernel/irq.c
+@@ -621,8 +621,9 @@ unsigned int sun4v_build_irq(u32 devhand
+ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
+ {
+ struct irq_handler_data *data;
+- struct ino_bucket *bucket;
+ unsigned long hv_err, cookie;
++ struct ino_bucket *bucket;
++ struct irq_desc *desc;
+ unsigned int virt_irq;
+
+ bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
+@@ -643,6 +644,13 @@ unsigned int sun4v_build_virq(u32 devhan
+ if (unlikely(!data))
+ return 0;
+
++ /* In order to make the LDC channel startup sequence easier,
++ * especially wrt. locking, we do not let request_irq() enable
++ * the interrupt.
++ */
++ desc = irq_desc + virt_irq;
++ desc->status |= IRQ_NOAUTOEN;
++
+ set_irq_chip_data(virt_irq, data);
+
+ /* Catch accidental accesses to these things. IMAP/ICLR handling
+--- a/arch/sparc64/kernel/ldc.c
++++ b/arch/sparc64/kernel/ldc.c
+@@ -1,6 +1,6 @@
+ /* ldc.c: Logical Domain Channel link-layer protocol driver.
+ *
+- * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
++ * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
+ */
+
+ #include <linux/kernel.h>
+@@ -23,8 +23,8 @@
+
+ #define DRV_MODULE_NAME "ldc"
+ #define PFX DRV_MODULE_NAME ": "
+-#define DRV_MODULE_VERSION "1.0"
+-#define DRV_MODULE_RELDATE "June 25, 2007"
++#define DRV_MODULE_VERSION "1.1"
++#define DRV_MODULE_RELDATE "July 22, 2008"
+
+ static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+@@ -1235,13 +1235,9 @@ int ldc_bind(struct ldc_channel *lp, con
+ unsigned long hv_err, flags;
+ int err = -EINVAL;
+
+- spin_lock_irqsave(&lp->lock, flags);
+-
+- if (!name)
+- goto out_err;
+-
+- if (lp->state != LDC_STATE_INIT)
+- goto out_err;
++ if (!name ||
++ (lp->state != LDC_STATE_INIT))
++ return -EINVAL;
+
+ snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
+ snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
+@@ -1250,25 +1246,32 @@ int ldc_bind(struct ldc_channel *lp, con
+ IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+ lp->rx_irq_name, lp);
+ if (err)
+- goto out_err;
++ return err;
+
+ err = request_irq(lp->cfg.tx_irq, ldc_tx,
+ IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+ lp->tx_irq_name, lp);
+- if (err)
+- goto out_free_rx_irq;
++ if (err) {
++ free_irq(lp->cfg.rx_irq, lp);
++ return err;
++ }
++
+
++ spin_lock_irqsave(&lp->lock, flags);
++
++ enable_irq(lp->cfg.rx_irq);
++ enable_irq(lp->cfg.tx_irq);
+
+ lp->flags |= LDC_FLAG_REGISTERED_IRQS;
+
+ err = -ENODEV;
+ hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+ if (hv_err)
+- goto out_free_tx_irq;
++ goto out_free_irqs;
+
+ hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+ if (hv_err)
+- goto out_free_tx_irq;
++ goto out_free_irqs;
+
+ hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+ if (hv_err)
+@@ -1304,14 +1307,11 @@ out_unmap_rx:
+ out_unmap_tx:
+ sun4v_ldc_tx_qconf(lp->id, 0, 0);
+
+-out_free_tx_irq:
++out_free_irqs:
+ lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
+ free_irq(lp->cfg.tx_irq, lp);
+-
+-out_free_rx_irq:
+ free_irq(lp->cfg.rx_irq, lp);
+
+-out_err:
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return err;
--- /dev/null
+From stable-bounces@linux.kernel.org Fri Jul 25 16:53:44 2008
+From: David Miller <davem@davemloft.net>
+Date: Fri, 25 Jul 2008 16:53:38 -0700 (PDT)
+Subject: tcp: Clear probes_out more aggressively in tcp_ack().
+To: stable@kernel.org
+Message-ID: <20080725.165338.168896319.davem@davemloft.net>
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 4b53fb67e385b856a991d402096379dab462170a ]
+
+This is based upon an excellent bug report from Eric Dumazet.
+
+tcp_ack() should clear ->icsk_probes_out even if there are packets
+outstanding. Otherwise if we get a sequence of ACKs while we do have
+packets outstanding over and over again, we'll never clear the
+probes_out value and eventually think the connection is too sick and
+we'll reset it.
+
+This appears to be some "optimization" added to tcp_ack() in the 2.4.x
+timeframe. In 2.2.x, probes_out is pretty much always cleared by
+tcp_ack().
+
+Here is Eric's original report:
+
+----------------------------------------
+Apparently, we can in some situations reset TCP connections in a couple of seconds when some frames are lost.
+
+In order to reproduce the problem, please try the following program on linux-2.6.25.*
+
+Setup some iptables rules to allow two frames per second sent on loopback interface to tcp destination port 12000
+
+iptables -N SLOWLO
+iptables -A SLOWLO -m hashlimit --hashlimit 2 --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name slow2 -j ACCEPT
+iptables -A SLOWLO -j DROP
+
+iptables -A OUTPUT -o lo -p tcp --dport 12000 -j SLOWLO
+
+Then run the attached program and see the output :
+
+# ./loop
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,200ms,1)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,200ms,3)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,200ms,5)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,200ms,7)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,200ms,9)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,200ms,11)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,201ms,13)
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+ESTAB 0 40 127.0.0.1:54455 127.0.0.1:12000 timer:(persist,188ms,15)
+write(): Connection timed out
+wrote 890 bytes but was interrupted after 9 seconds
+ESTAB 0 0 127.0.0.1:12000 127.0.0.1:54455
+Exiting read() because no data available (4000 ms timeout).
+read 860 bytes
+
+While this tcp session makes progress (sending frames with 50 bytes of payload, every 500ms), linux tcp stack decides to reset it, when tcp_retries 2 is reached (default value : 15)
+
+tcpdump :
+
+15:30:28.856695 IP 127.0.0.1.56554 > 127.0.0.1.12000: S 33788768:33788768(0) win 32792 <mss 16396,nop,nop,sackOK,nop,wscale 7>
+15:30:28.856711 IP 127.0.0.1.12000 > 127.0.0.1.56554: S 33899253:33899253(0) ack 33788769 win 32792 <mss 16396,nop,nop,sackOK,nop,wscale 7>
+15:30:29.356947 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 1:61(60) ack 1 win 257
+15:30:29.356966 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 61 win 257
+15:30:29.866415 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 61:111(50) ack 1 win 257
+15:30:29.866427 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 111 win 257
+15:30:30.366516 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 111:161(50) ack 1 win 257
+15:30:30.366527 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 161 win 257
+15:30:30.876196 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 161:211(50) ack 1 win 257
+15:30:30.876207 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 211 win 257
+15:30:31.376282 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 211:261(50) ack 1 win 257
+15:30:31.376290 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 261 win 257
+15:30:31.885619 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 261:311(50) ack 1 win 257
+15:30:31.885631 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 311 win 257
+15:30:32.385705 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 311:361(50) ack 1 win 257
+15:30:32.385715 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 361 win 257
+15:30:32.895249 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 361:411(50) ack 1 win 257
+15:30:32.895266 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 411 win 257
+15:30:33.395341 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 411:461(50) ack 1 win 257
+15:30:33.395351 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 461 win 257
+15:30:33.918085 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 461:511(50) ack 1 win 257
+15:30:33.918096 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 511 win 257
+15:30:34.418163 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 511:561(50) ack 1 win 257
+15:30:34.418172 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 561 win 257
+15:30:34.927685 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 561:611(50) ack 1 win 257
+15:30:34.927698 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 611 win 257
+15:30:35.427757 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 611:661(50) ack 1 win 257
+15:30:35.427766 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 661 win 257
+15:30:35.937359 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 661:711(50) ack 1 win 257
+15:30:35.937376 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 711 win 257
+15:30:36.437451 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 711:761(50) ack 1 win 257
+15:30:36.437464 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 761 win 257
+15:30:36.947022 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 761:811(50) ack 1 win 257
+15:30:36.947039 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 811 win 257
+15:30:37.447135 IP 127.0.0.1.56554 > 127.0.0.1.12000: P 811:861(50) ack 1 win 257
+15:30:37.447203 IP 127.0.0.1.12000 > 127.0.0.1.56554: . ack 861 win 257
+15:30:41.448171 IP 127.0.0.1.12000 > 127.0.0.1.56554: F 1:1(0) ack 861 win 257
+15:30:41.448189 IP 127.0.0.1.56554 > 127.0.0.1.12000: R 33789629:33789629(0) win 0
+
+Source of program :
+
+/*
+ * small producer/consumer program.
+ * setup a listener on 127.0.0.1:12000
+ * Forks a child
+ * child connect to 127.0.0.1, and sends 10 bytes on this tcp socket every 100 ms
+ * Father accepts connection, and read all data
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/poll.h>
+
+int port = 12000;
+char buffer[4096];
+int main(int argc, char *argv[])
+{
+ int lfd = socket(AF_INET, SOCK_STREAM, 0);
+ struct sockaddr_in socket_address;
+ time_t t0, t1;
+ int on = 1, sfd, res;
+ unsigned long total = 0;
+ socklen_t alen = sizeof(socket_address);
+ pid_t pid;
+
+ time(&t0);
+ socket_address.sin_family = AF_INET;
+ socket_address.sin_port = htons(port);
+ socket_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ if (lfd == -1) {
+ perror("socket()");
+ return 1;
+ }
+ setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
+ if (bind(lfd, (struct sockaddr *)&socket_address, sizeof(socket_address)) == -1) {
+ perror("bind");
+ close(lfd);
+ return 1;
+ }
+ if (listen(lfd, 1) == -1) {
+ perror("listen()");
+ close(lfd);
+ return 1;
+ }
+ pid = fork();
+ if (pid == 0) {
+ int i, cfd = socket(AF_INET, SOCK_STREAM, 0);
+ close(lfd);
+ if (connect(cfd, (struct sockaddr *)&socket_address, sizeof(socket_address)) == -1) {
+ perror("connect()");
+ return 1;
+ }
+ for (i = 0 ; ;) {
+ res = write(cfd, "blablabla\n", 10);
+ if (res > 0) total += res;
+ else if (res == -1) {
+ perror("write()");
+ break;
+ } else break;
+ usleep(100000);
+ if (++i == 10) {
+ system("ss -on dst 127.0.0.1:12000");
+ i = 0;
+ }
+ }
+ time(&t1);
+ fprintf(stderr, "wrote %lu bytes but was interrupted after %g seconds\n", total, difftime(t1, t0));
+ system("ss -on | grep 127.0.0.1:12000");
+ close(cfd);
+ return 0;
+ }
+ sfd = accept(lfd, (struct sockaddr *)&socket_address, &alen);
+ if (sfd == -1) {
+ perror("accept");
+ return 1;
+ }
+ close(lfd);
+ while (1) {
+ struct pollfd pfd[1];
+ pfd[0].fd = sfd;
+ pfd[0].events = POLLIN;
+ if (poll(pfd, 1, 4000) == 0) {
+ fprintf(stderr, "Exiting read() because no data available (4000 ms timeout).\n");
+ break;
+ }
+ res = read(sfd, buffer, sizeof(buffer));
+ if (res > 0) total += res;
+ else if (res == 0) break;
+ else perror("read()");
+ }
+ fprintf(stderr, "read %lu bytes\n", total);
+ close(sfd);
+ return 0;
+}
+----------------------------------------
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/ipv4/tcp_input.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3273,6 +3273,7 @@ static int tcp_ack(struct sock *sk, stru
+ * log. Something worked...
+ */
+ sk->sk_err_soft = 0;
++ icsk->icsk_probes_out = 0;
+ tp->rcv_tstamp = tcp_time_stamp;
+ prior_packets = tp->packets_out;
+ if (!prior_packets)
+@@ -3305,8 +3306,6 @@ static int tcp_ack(struct sock *sk, stru
+ return 1;
+
+ no_queue:
+- icsk->icsk_probes_out = 0;
+-
+ /* If this ack opens up a zero window, clear backoff. It was
+ * being used to time the probes, and is probably far higher than
+ * it needs to be for normal retransmission.
--- /dev/null
+From stable-bounces@linux.kernel.org Sun Jul 27 10:30:13 2008
+From: Jan Beulich <jbeulich@novell.com>
+Date: Sun, 27 Jul 2008 17:30:04 GMT
+Subject: vmlinux.lds: move __attribute__((__cold__)) functions back into final .text section
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807271730.m6RHU4vX029154@hera.kernel.org>
+
+From: Jan Beulich <jbeulich@novell.com>
+
+commit fb5e2b379732e1a6ea32392980bb42e0212db842 upstream
+
+Due to the addition of __attribute__((__cold__)) to a few symbols
+without adjusting the linker scripts, those symbols currently may end
+up outside the [_stext,_etext) range, as they get placed in
+.text.unlikely by (at least) gcc 4.3.0. This may confuse code not only
+outside of the kernel, symbol_put_addr()'s BUG() could also trigger.
+Hence we need to add .text.unlikely (and for future uses of
+__attribute__((__hot__)) also .text.hot) to the TEXT_TEXT() macro.
+
+Issue observed by Lukas Lipavsky.
+
+Signed-off-by: Jan Beulich <jbeulich@novell.com>
+Tested-by: Lukas Lipavsky <llipavsky@suse.cz>
+Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/asm-generic/vmlinux.lds.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -204,6 +204,7 @@
+ * during second ld run in second ld pass when generating System.map */
+ #define TEXT_TEXT \
+ ALIGN_FUNCTION(); \
++ *(.text.hot) \
+ *(.text) \
+ *(.ref.text) \
+ *(.text.init.refok) \
+@@ -213,7 +214,8 @@
+ CPU_KEEP(init.text) \
+ CPU_KEEP(exit.text) \
+ MEM_KEEP(init.text) \
+- MEM_KEEP(exit.text)
++ MEM_KEEP(exit.text) \
++ *(.text.unlikely)
+
+
+ /* sched.text is aling to function alignment to secure we have same
--- /dev/null
+From stable-bounces@linux.kernel.org Tue Jul 22 13:55:19 2008
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+Date: Tue, 22 Jul 2008 20:55:04 GMT
+Subject: x86: fix crash due to missing debugctlmsr on AMD K6-3
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200807222055.m6MKt4Yx011935@hera.kernel.org>
+
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+
+commit d536b1f86591fb081c7a56eab04e711eb4dab951 upstream
+
+currently if you use PTRACE_SINGLEBLOCK on AMD K6-3 (i586) it will crash.
+Kernel now wrongly assumes existing DEBUGCTLMSR MSR register there.
+
+Removed the assumption also for some other non-K6 CPUs but I am not sure there
+(but it can only bring small inefficiency there if my assumption is wrong).
+
+Based on info from Roland McGrath, Chuck Ebbert and Mikulas Patocka.
+More info at:
+ https://bugzilla.redhat.com/show_bug.cgi?id=456175
+
+Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/Kconfig.cpu | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/Kconfig.cpu
++++ b/arch/x86/Kconfig.cpu
+@@ -414,4 +414,4 @@ config X86_MINIMUM_CPU_FAMILY
+
+ config X86_DEBUGCTLMSR
+ def_bool y
+- depends on !(M586MMX || M586TSC || M586 || M486 || M386)
++ depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
--- /dev/null
+From stable-bounces@linux.kernel.org Tue Jul 15 15:55:35 2008
+From: H. Peter Anvin <hpa@zytor.com>
+Date: Wed, 16 Jul 2008 00:55:04 +0200
+Subject: x86, suspend, acpi: enter Big Real Mode
+To: stable@kernel.org
+Cc: "Rafael J. Wysocki" <rjw@sisk.pl>, Thomas Gleixner <tglx@linutronix.de>, "H. Peter Anvin" <hpa@zytor.com>
+Message-ID: <20080715225504.GA30520@elte.hu>
+Content-Disposition: inline
+
+From: H. Peter Anvin <hpa@zytor.com>
+
+Commit 3bf2e77453a87c22eb57ed4926760ac131c84459 upstream
+
+x86, suspend, acpi: enter Big Real Mode
+
+The explanation for recent video BIOS suspend quirk failures is that
+the VESA BIOS expects to be entered in Big Real Mode (*.limit = 0xffffffff)
+instead of ordinary Real Mode (*.limit = 0xffff).
+
+This patch changes the segment descriptors to Big Real Mode instead.
+
+The segment descriptor registers (what Intel calls "segment cache") is
+always active. The only thing that changes based on CR0.PE is how it is
+*loaded* and the interpretation of the CS flags.
+
+The segment descriptor registers contain of the following sub-registers:
+selector (the "visible" part), base, limit and flags. In protected mode
+or long mode, they are loaded from descriptors (or fs.base or gs.base can
+be manipulated directly in long mode.) In real mode, the only thing
+changed by a segment register load is the selector and the base, where the
+base <- selector << 4. In particular, *the limit and the flags are not
+changed*.
+
+As far as the handling of the CS flags: a code segment cannot be writable
+in protected mode, whereas it is "just another segment" in real mode, so
+there is some kind of quirk that kicks in for this when CR0.PE <- 0. I'm
+not sure if this is accomplished by actually changing the cs.flags register
+or just changing the interpretation; it might be something that is
+CPU-specific. In particular, the Transmeta CPUs had an explicit "CS is
+writable if you're in real mode" override, so even if you had loaded CS
+with an execute-only segment it'd be writable (but not readable!) on return
+to real mode. I'm not at all sure if that is how other CPUs behave.
+
+Signed-off-by: "H. Peter Anvin" <hpa@zytor.com>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+---
+ arch/x86/kernel/acpi/sleep.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/kernel/acpi/sleep.c
++++ b/arch/x86/kernel/acpi/sleep.c
+@@ -23,6 +23,15 @@ static unsigned long acpi_realmode;
+ static char temp_stack[10240];
+ #endif
+
++/* XXX: this macro should move to asm-x86/segment.h and be shared with the
++ boot code... */
++#define GDT_ENTRY(flags, base, limit) \
++ (((u64)(base & 0xff000000) << 32) | \
++ ((u64)flags << 40) | \
++ ((u64)(limit & 0x00ff0000) << 32) | \
++ ((u64)(base & 0x00ffffff) << 16) | \
++ ((u64)(limit & 0x0000ffff)))
++
+ /**
+ * acpi_save_state_mem - save kernel state
+ *
+@@ -58,11 +67,11 @@ int acpi_save_state_mem(void)
+ ((char *)&header->wakeup_gdt - (char *)acpi_realmode))
+ << 16);
+ /* GDT[1]: real-mode-like code segment */
+- header->wakeup_gdt[1] = (0x009bULL << 40) +
+- ((u64)acpi_wakeup_address << 16) + 0xffff;
++ header->wakeup_gdt[1] =
++ GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
+ /* GDT[2]: real-mode-like data segment */
+- header->wakeup_gdt[2] = (0x0093ULL << 40) +
+- ((u64)acpi_wakeup_address << 16) + 0xffff;
++ header->wakeup_gdt[2] =
++ GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
+
+ #ifndef CONFIG_64BIT
+ store_gdt((struct desc_ptr *)&header->pmode_gdt);