--- /dev/null
+From b6d6c5175809934e04a606d9193ef04924a7a7d9 Mon Sep 17 00:00:00 2001
+From: Ed Cashin <ecashin@coraid.com>
+Date: Wed, 18 Feb 2009 14:48:13 -0800
+Subject: aoe: ignore vendor extension AoE responses
+
+From: Ed Cashin <ecashin@coraid.com>
+
+commit b6d6c5175809934e04a606d9193ef04924a7a7d9 upstream.
+
+The Welland ME-747K-SI AoE target generates unsolicited AoE responses that
+are marked as vendor extensions. Instead of ignoring these packets, the
+aoe driver was generating kernel messages for each unrecognized response
+received. This patch corrects the behavior.
+
+Signed-off-by: Ed Cashin <ecashin@coraid.com>
+Reported-by: <karaluh@karaluh.pl>
+Tested-by: <karaluh@karaluh.pl>
+Cc: Alex Buell <alex.buell@munted.org.uk>
+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/block/aoe/aoe.h | 1 +
+ drivers/block/aoe/aoenet.c | 2 ++
+ 2 files changed, 3 insertions(+)
+
+--- a/drivers/block/aoe/aoe.h
++++ b/drivers/block/aoe/aoe.h
+@@ -18,6 +18,7 @@
+ enum {
+ AOECMD_ATA,
+ AOECMD_CFG,
++ AOECMD_VEND_MIN = 0xf0,
+
+ AOEFL_RSP = (1<<3),
+ AOEFL_ERR = (1<<2),
+--- a/drivers/block/aoe/aoenet.c
++++ b/drivers/block/aoe/aoenet.c
+@@ -154,6 +154,8 @@ aoenet_rcv(struct sk_buff *skb, struct n
+ aoecmd_cfg_rsp(skb);
+ break;
+ default:
++ if (h->cmd >= AOECMD_VEND_MIN)
++ break; /* don't complain about vendor commands */
+ printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
+ }
+ exit:
--- /dev/null
+From 69765529d701c838df19ea1f5ad2f33a528261ae Mon Sep 17 00:00:00 2001
+From: Steve French <sfrench@us.ibm.com>
+Date: Tue, 17 Feb 2009 01:29:40 +0000
+Subject: [CIFS] Fix oops in cifs_strfromUCS_le mounting to servers which do not specify their OS
+
+From: Steve French <sfrench@us.ibm.com>
+
+commit 69765529d701c838df19ea1f5ad2f33a528261ae upstream.
+
+Fixes kernel bug #10451 http://bugzilla.kernel.org/show_bug.cgi?id=10451
+
+Certain NAS appliances do not set the operating system or network operating system
+fields in the session setup response on the wire. cifs was oopsing on the unexpected
+zero length response fields (when trying to null terminate a zero length field).
+
+This fixes the oops.
+
+Acked-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/cifs/CHANGES | 2 ++
+ fs/cifs/sess.c | 4 ++--
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/CHANGES
++++ b/fs/cifs/CHANGES
+@@ -1,3 +1,5 @@
++Fix oops in cifs_dfs_ref.c when prefixpath is not reachable when using DFS.
++
+ Version 1.54
+ ------------
+ Fix premature write failure on congested networks (we would give up
+--- a/fs/cifs/sess.c
++++ b/fs/cifs/sess.c
+@@ -228,7 +228,7 @@ static int decode_unicode_ssetup(char **
+
+ kfree(ses->serverOS);
+ /* UTF-8 string will not grow more than four times as big as UCS-16 */
+- ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
++ ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
+ if (ses->serverOS != NULL)
+ cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
+ data += 2 * (len + 1);
+@@ -241,7 +241,7 @@ static int decode_unicode_ssetup(char **
+ return rc;
+
+ kfree(ses->serverNOS);
+- ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
++ ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
+ if (ses->serverNOS != NULL) {
+ cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
+ nls_cp);
--- /dev/null
+From 4c41bd0ec953954158f92bed5d3062645062b98e Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 16 Feb 2009 21:29:31 +0100
+Subject: JFFS2: fix mount crash caused by removed nodes
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 4c41bd0ec953954158f92bed5d3062645062b98e upstream.
+
+At scan time we observed following scenario:
+
+ node A inserted
+ node B inserted
+ node C inserted -> sets overlapped flag on node B
+
+ node A is removed due to CRC failure -> overlapped flag on node B remains
+
+ while (tn->overlapped)
+ tn = tn_prev(tn);
+
+ ==> crash, when tn_prev(B) is referenced.
+
+When the ultimate node is removed at scan time and the overlapped flag
+is set on the penultimate node, then nothing updates the overlapped
+flag of that node. The overlapped iterators blindly expect that the
+ultimate node does not have the overlapped flag set, which causes the
+scan code to crash.
+
+It would be a huge overhead to go through the node chain on node
+removal and fix up the overlapped flags, so detecting such a case on
+the fly in the overlapped iterators is a simpler and reliable
+solution.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/jffs2/readinode.c | 42 +++++++++++++++++++++++++++++++++---------
+ 1 file changed, 33 insertions(+), 9 deletions(-)
+
+--- a/fs/jffs2/readinode.c
++++ b/fs/jffs2/readinode.c
+@@ -220,7 +220,7 @@ static int jffs2_add_tn_to_tree(struct j
+ struct jffs2_tmp_dnode_info *tn)
+ {
+ uint32_t fn_end = tn->fn->ofs + tn->fn->size;
+- struct jffs2_tmp_dnode_info *this;
++ struct jffs2_tmp_dnode_info *this, *ptn;
+
+ dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
+
+@@ -251,11 +251,18 @@ static int jffs2_add_tn_to_tree(struct j
+ if (this) {
+ /* If the node is coincident with another at a lower address,
+ back up until the other node is found. It may be relevant */
+- while (this->overlapped)
+- this = tn_prev(this);
+-
+- /* First node should never be marked overlapped */
+- BUG_ON(!this);
++ while (this->overlapped) {
++ ptn = tn_prev(this);
++ if (!ptn) {
++ /*
++ * We killed a node which set the overlapped
++ * flags during the scan. Fix it up.
++ */
++ this->overlapped = 0;
++ break;
++ }
++ this = ptn;
++ }
+ dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
+ }
+
+@@ -360,7 +367,17 @@ static int jffs2_add_tn_to_tree(struct j
+ }
+ if (!this->overlapped)
+ break;
+- this = tn_prev(this);
++
++ ptn = tn_prev(this);
++ if (!ptn) {
++ /*
++ * We killed a node which set the overlapped
++ * flags during the scan. Fix it up.
++ */
++ this->overlapped = 0;
++ break;
++ }
++ this = ptn;
+ }
+ }
+
+@@ -456,8 +473,15 @@ static int jffs2_build_inode_fragtree(st
+ eat_last(&rii->tn_root, &last->rb);
+ ver_insert(&ver_root, last);
+
+- if (unlikely(last->overlapped))
+- continue;
++ if (unlikely(last->overlapped)) {
++ if (pen)
++ continue;
++ /*
++ * We killed a node which set the overlapped
++ * flags during the scan. Fix it up.
++ */
++ last->overlapped = 0;
++ }
+
+ /* Now we have a bunch of nodes in reverse version
+ order, in the tree at ver_root. Most of the time,
--- /dev/null
+From f2dbcfa738368c8a40d4a5f0b65dc9879577cb21 Mon Sep 17 00:00:00 2001
+From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Date: Wed, 18 Feb 2009 14:48:32 -0800
+Subject: mm: clean up for early_pfn_to_nid()
+
+From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+
+commit f2dbcfa738368c8a40d4a5f0b65dc9879577cb21 upstream.
+
+What's happening is that the assertion in mm/page_alloc.c:move_freepages()
+is triggering:
+
+ BUG_ON(page_zone(start_page) != page_zone(end_page));
+
+Once I knew this is what was happening, I added some annotations:
+
+ if (unlikely(page_zone(start_page) != page_zone(end_page))) {
+ printk(KERN_ERR "move_freepages: Bogus zones: "
+ "start_page[%p] end_page[%p] zone[%p]\n",
+ start_page, end_page, zone);
+ printk(KERN_ERR "move_freepages: "
+ "start_zone[%p] end_zone[%p]\n",
+ page_zone(start_page), page_zone(end_page));
+ printk(KERN_ERR "move_freepages: "
+ "start_pfn[0x%lx] end_pfn[0x%lx]\n",
+ page_to_pfn(start_page), page_to_pfn(end_page));
+ printk(KERN_ERR "move_freepages: "
+ "start_nid[%d] end_nid[%d]\n",
+ page_to_nid(start_page), page_to_nid(end_page));
+ ...
+
+And here's what I got:
+
+ move_freepages: Bogus zones: start_page[2207d0000] end_page[2207dffc0] zone[fffff8103effcb00]
+ move_freepages: start_zone[fffff8103effcb00] end_zone[fffff8003fffeb00]
+ move_freepages: start_pfn[0x81f600] end_pfn[0x81f7ff]
+ move_freepages: start_nid[1] end_nid[0]
+
+My memory layout on this box is:
+
+[ 0.000000] Zone PFN ranges:
+[ 0.000000] Normal 0x00000000 -> 0x0081ff5d
+[ 0.000000] Movable zone start PFN for each node
+[ 0.000000] early_node_map[8] active PFN ranges
+[ 0.000000] 0: 0x00000000 -> 0x00020000
+[ 0.000000] 1: 0x00800000 -> 0x0081f7ff
+[ 0.000000] 1: 0x0081f800 -> 0x0081fe50
+[ 0.000000] 1: 0x0081fed1 -> 0x0081fed8
+[ 0.000000] 1: 0x0081feda -> 0x0081fedb
+[ 0.000000] 1: 0x0081fedd -> 0x0081fee5
+[ 0.000000] 1: 0x0081fee7 -> 0x0081ff51
+[ 0.000000] 1: 0x0081ff59 -> 0x0081ff5d
+
+So it's a block move in that 0x81f600-->0x81f7ff region which triggers
+the problem.
+
+This patch:
+
+Declaration of early_pfn_to_nid() is scattered over per-arch include
+files, and it seems it's complicated to know when the declaration is used.
+ I think it makes fix-for-memmap-init not easy.
+
+This patch moves all declaration to include/linux/mm.h
+
+After this,
+ if !CONFIG_NODES_POPULATES_NODE_MAP && !CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+ -> Use static definition in include/linux/mm.h
+ else if !CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+ -> Use generic definition in mm/page_alloc.c
+ else
+ -> per-arch back end function will be called.
+
+Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Tested-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Reported-by: David Miller <davem@davemlloft.net>
+Cc: Mel Gorman <mel@csn.ul.ie>
+Cc: Heiko Carstens <heiko.carstens@de.ibm.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>
+
+---
+ arch/ia64/include/asm/mmzone.h | 4 ----
+ arch/ia64/mm/numa.c | 2 +-
+ arch/x86/mm/numa_64.c | 2 +-
+ include/asm-x86/mmzone_32.h | 2 --
+ include/asm-x86/mmzone_64.h | 2 --
+ include/linux/mm.h | 19 ++++++++++++++++---
+ mm/page_alloc.c | 8 +++++++-
+ 7 files changed, 25 insertions(+), 14 deletions(-)
+
+--- a/arch/ia64/include/asm/mmzone.h
++++ b/arch/ia64/include/asm/mmzone.h
+@@ -31,10 +31,6 @@ static inline int pfn_to_nid(unsigned lo
+ #endif
+ }
+
+-#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+-extern int early_pfn_to_nid(unsigned long pfn);
+-#endif
+-
+ #ifdef CONFIG_IA64_DIG /* DIG systems are small */
+ # define MAX_PHYSNODE_ID 8
+ # define NR_NODE_MEMBLKS (MAX_NUMNODES * 8)
+--- a/arch/ia64/mm/numa.c
++++ b/arch/ia64/mm/numa.c
+@@ -58,7 +58,7 @@ paddr_to_nid(unsigned long paddr)
+ * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
+ * the section resides.
+ */
+-int early_pfn_to_nid(unsigned long pfn)
++int __meminit __early_pfn_to_nid(unsigned long pfn)
+ {
+ int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
+
+--- a/arch/x86/mm/numa_64.c
++++ b/arch/x86/mm/numa_64.c
+@@ -145,7 +145,7 @@ int __init compute_hash_shift(struct boo
+ return shift;
+ }
+
+-int early_pfn_to_nid(unsigned long pfn)
++int __meminit __early_pfn_to_nid(unsigned long pfn)
+ {
+ return phys_to_nid(pfn << PAGE_SHIFT);
+ }
+--- a/include/asm-x86/mmzone_32.h
++++ b/include/asm-x86/mmzone_32.h
+@@ -32,8 +32,6 @@ static inline void get_memcfg_numa(void)
+ get_memcfg_numa_flat();
+ }
+
+-extern int early_pfn_to_nid(unsigned long pfn);
+-
+ extern void resume_map_numa_kva(pgd_t *pgd);
+
+ #else /* !CONFIG_NUMA */
+--- a/include/asm-x86/mmzone_64.h
++++ b/include/asm-x86/mmzone_64.h
+@@ -41,8 +41,6 @@ static inline __attribute__((pure)) int
+ #define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
+ NODE_DATA(nid)->node_spanned_pages)
+
+-extern int early_pfn_to_nid(unsigned long pfn);
+-
+ #ifdef CONFIG_NUMA_EMU
+ #define FAKE_NODE_MIN_SIZE (64 * 1024 * 1024)
+ #define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL))
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -1027,10 +1027,23 @@ extern void free_bootmem_with_active_reg
+ typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
+ extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
+ extern void sparse_memory_present_with_active_regions(int nid);
+-#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+-extern int early_pfn_to_nid(unsigned long pfn);
+-#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+ #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
++
++#if !defined(CONFIG_ARCH_POPULATES_NODE_MAP) && \
++ !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID)
++static inline int __early_pfn_to_nid(unsigned long pfn)
++{
++ return 0;
++}
++#else
++/* please see mm/page_alloc.c */
++extern int __meminit early_pfn_to_nid(unsigned long pfn);
++#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
++/* there is a per-arch backend function. */
++extern int __meminit __early_pfn_to_nid(unsigned long pfn);
++#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
++#endif
++
+ extern void set_dma_reserve(unsigned long new_dma_reserve);
+ extern void memmap_init_zone(unsigned long, int, unsigned long,
+ unsigned long, enum memmap_context);
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2949,7 +2949,7 @@ static int __meminit next_active_region_
+ * was used and there are no special requirements, this is a convenient
+ * alternative
+ */
+-int __meminit early_pfn_to_nid(unsigned long pfn)
++int __meminit __early_pfn_to_nid(unsigned long pfn)
+ {
+ int i;
+
+@@ -2965,6 +2965,12 @@ int __meminit early_pfn_to_nid(unsigned
+ }
+ #endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
++int __meminit early_pfn_to_nid(unsigned long pfn)
++{
++ return __early_pfn_to_nid(pfn);
++}
++
++
+ /* Basic iterator support to walk early_node_map[] */
+ #define for_each_active_range_index_in_nid(i, nid) \
+ for (i = first_active_region_index_in_nid(nid); i != -1; \
--- /dev/null
+From cc2559bccc72767cb446f79b071d96c30c26439b Mon Sep 17 00:00:00 2001
+From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Date: Wed, 18 Feb 2009 14:48:33 -0800
+Subject: mm: fix memmap init for handling memory hole
+
+From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+
+commit cc2559bccc72767cb446f79b071d96c30c26439b upstream.
+
+Now, early_pfn_in_nid(PFN, NID) may returns false if PFN is a hole.
+and memmap initialization was not done. This was a trouble for
+sparc boot.
+
+To fix this, the PFN should be initialized and marked as PG_reserved.
+This patch changes early_pfn_in_nid() return true if PFN is a hole.
+
+Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Reported-by: David Miller <davem@davemlloft.net>
+Tested-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Cc: Mel Gorman <mel@csn.ul.ie>
+Cc: Heiko Carstens <heiko.carstens@de.ibm.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>
+
+---
+ arch/ia64/mm/numa.c | 2 +-
+ include/linux/mmzone.h | 2 +-
+ mm/page_alloc.c | 23 ++++++++++++++++++++---
+ 3 files changed, 22 insertions(+), 5 deletions(-)
+
+--- a/arch/ia64/mm/numa.c
++++ b/arch/ia64/mm/numa.c
+@@ -70,7 +70,7 @@ int __meminit __early_pfn_to_nid(unsigne
+ return node_memblk[i].nid;
+ }
+
+- return 0;
++ return -1;
+ }
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -978,7 +978,7 @@ void sparse_init(void);
+ #endif /* CONFIG_SPARSEMEM */
+
+ #ifdef CONFIG_NODES_SPAN_OTHER_NODES
+-#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid))
++bool early_pfn_in_nid(unsigned long pfn, int nid);
+ #else
+ #define early_pfn_in_nid(pfn, nid) (1)
+ #endif
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2960,16 +2960,33 @@ int __meminit __early_pfn_to_nid(unsigne
+ if (start_pfn <= pfn && pfn < end_pfn)
+ return early_node_map[i].nid;
+ }
+-
+- return 0;
++ /* This is a memory hole */
++ return -1;
+ }
+ #endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+ int __meminit early_pfn_to_nid(unsigned long pfn)
+ {
+- return __early_pfn_to_nid(pfn);
++ int nid;
++
++ nid = __early_pfn_to_nid(pfn);
++ if (nid >= 0)
++ return nid;
++ /* just returns 0 */
++ return 0;
+ }
+
++#ifdef CONFIG_NODES_SPAN_OTHER_NODES
++bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
++{
++ int nid;
++
++ nid = __early_pfn_to_nid(pfn);
++ if (nid >= 0 && nid != node)
++ return false;
++ return true;
++}
++#endif
+
+ /* Basic iterator support to walk early_node_map[] */
+ #define for_each_active_range_index_in_nid(i, nid) \
--- /dev/null
+From e0ae4f5503235ba4449ffb5bcb4189edcef4d584 Mon Sep 17 00:00:00 2001
+From: Yinghai Lu <yinghai@kernel.org>
+Date: Tue, 17 Feb 2009 20:40:09 -0800
+Subject: PCI quirk: enable MSI on 8132
+
+From: Yinghai Lu <yinghai@kernel.org>
+
+commit e0ae4f5503235ba4449ffb5bcb4189edcef4d584 upstream.
+
+David reported that LSI SAS doesn't work with MSI. It turns out that
+his BIOS doesn't enable it, but the HT MSI 8132 does support HT MSI.
+Add quirk to enable it
+
+Reported-by: David Lang <david@lang.hm>
+Signed-off-by: Yinghai Lu <yinghai@kernel.org>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/quirks.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1856,7 +1856,6 @@ static void __devinit quirk_msi_ht_cap(s
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
+ quirk_msi_ht_cap);
+
+-
+ /* The nVidia CK804 chipset may have 2 HT MSI mappings.
+ * MSI are supported if the MSI capability set in any of these mappings.
+ */
+@@ -1907,6 +1906,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S
+ PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
+ ht_enable_msi_mapping);
+
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
++ ht_enable_msi_mapping);
++
+ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
+ {
+ struct pci_dev *host_bridge;
--- /dev/null
+From 046ee5d26ac91316a8ac0a29c0b33139dc9da20d Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@gmail.com>
+Date: Tue, 17 Feb 2009 14:31:12 -0600
+Subject: rtl8187: New USB ID's for RTL8187L
+
+From: Larry Finger <Larry.Finger@gmail.com>
+
+commit 046ee5d26ac91316a8ac0a29c0b33139dc9da20d upstream.
+
+Add new USB ID codes. These come from two postings on forums and
+mailing lists, and four are derived from the .inf that accompanies
+the latest Realtek Windows driver for the RTL8187L.
+
+Thanks to Viktor Ilijašić <viktor.ilijasic@gmail.com> and Xose Vazquez
+Perez <xose.vazquez@gmail.com> for reporting these new ID's.
+
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/rtl8187_dev.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/net/wireless/rtl8187_dev.c
++++ b/drivers/net/wireless/rtl8187_dev.c
+@@ -40,6 +40,10 @@ static struct usb_device_id rtl8187_tabl
+ {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
+ {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B},
+ {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B},
++ /* Surecom */
++ {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187},
++ /* Logitech */
++ {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187},
+ /* Netgear */
+ {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},
+ {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187},
+@@ -49,8 +53,16 @@ static struct usb_device_id rtl8187_tabl
+ /* Sitecom */
+ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187},
+ {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B},
++ /* Sphairon Access Systems GmbH */
++ {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187},
++ /* Dick Smith Electronics */
++ {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187},
+ /* Abocom */
+ {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187},
++ /* Qcom */
++ {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187},
++ /* AirLive */
++ {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187},
+ {}
+ };
+
--- /dev/null
+From b73a77494292b930642fbf87de3e3196593f7593 Mon Sep 17 00:00:00 2001
+From: HighPoint Linux Team <linux@highpoint-tech.com>
+Date: Thu, 12 Feb 2009 11:28:31 +0800
+Subject: SCSI: hptiop: Add new PCI device ID
+
+From: HighPoint Linux Team <linux@highpoint-tech.com>
+
+commit b73a77494292b930642fbf87de3e3196593f7593 upstream.
+
+Signed-off-by: HighPoint Linux Team <linux@highpoint-tech.com>
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/hptiop.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/scsi/hptiop.c
++++ b/drivers/scsi/hptiop.c
+@@ -1251,6 +1251,7 @@ static struct pci_device_id hptiop_id_ta
+ { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
+ { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
+ { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
++ { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
+ { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },
+ { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },
+ { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },
--- /dev/null
+From 4034cc68157bfa0b6622efe368488d3d3e20f4e6 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Sat, 21 Feb 2009 11:04:45 +0900
+Subject: SCSI: sd: revive sd_index_lock
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 4034cc68157bfa0b6622efe368488d3d3e20f4e6 upstream.
+
+Commit f27bac2761cab5a2e212dea602d22457a9aa6943 which converted sd to
+use ida instead of idr incorrectly removed sd_index_lock around id
+allocation and free. idr/ida do have internal locks but they protect
+their free object lists not the allocation itself. The caller is
+responsible for that. This missing synchronization led to the same id
+being assigned to multiple devices leading to oops.
+
+Reported and tracked down by Stuart Hayes of Dell.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/sd.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -99,6 +99,7 @@ static void scsi_disk_release(struct dev
+ static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
+ static void sd_print_result(struct scsi_disk *, int);
+
++static DEFINE_SPINLOCK(sd_index_lock);
+ static DEFINE_IDA(sd_index_ida);
+
+ /* This semaphore is used to mediate the 0->1 reference get in the
+@@ -1817,7 +1818,9 @@ static int sd_probe(struct device *dev)
+ if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
+ goto out_put;
+
++ spin_lock(&sd_index_lock);
+ error = ida_get_new(&sd_index_ida, &index);
++ spin_unlock(&sd_index_lock);
+ } while (error == -EAGAIN);
+
+ if (error)
+@@ -1891,7 +1894,9 @@ static int sd_probe(struct device *dev)
+ return 0;
+
+ out_free_index:
++ spin_lock(&sd_index_lock);
+ ida_remove(&sd_index_ida, index);
++ spin_unlock(&sd_index_lock);
+ out_put:
+ put_disk(gd);
+ out_free:
+@@ -1941,7 +1946,9 @@ static void scsi_disk_release(struct dev
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct gendisk *disk = sdkp->disk;
+
++ spin_lock(&sd_index_lock);
+ ida_remove(&sd_index_ida, sdkp->index);
++ spin_unlock(&sd_index_lock);
+
+ disk->private_data = NULL;
+ put_disk(disk);
vfs-separate-fmode_pread-fmode_pwrite-into-separate-flags.patch
seq_file-properly-cope-with-pread.patch
vt-declare-pio_cmap-gio_cmap-as-compatbile-ioctls.patch
+aoe-ignore-vendor-extension-aoe-responses.patch
+fix-oops-in-cifs_strfromucs_le-mounting-to-servers-which-do-not-specify-their-os.patch
+jffs2-fix-mount-crash-caused-by-removed-nodes.patch
+mm-clean-up-for-early_pfn_to_nid.patch
+mm-fix-memmap-init-for-handling-memory-hole.patch
+pci-quirk-enable-msi-on-8132.patch
+rtl8187-new-usb-id-s-for-rtl8187l.patch
+scsi-hptiop-add-new-pci-device-id.patch
+scsi-sd-revive-sd_index_lock.patch
+timerfd-add-flags-check.patch
+usb-cdc-acm-add-usb-id-for-motomagx-phones.patch
+usb-usb_get_string-should-check-the-descriptor-type.patch
+usb-usb-storage-add-ignore_residue-flag-for-genesys-logic-adapters.patch
+watchdog-ks8695_wdt.c-clock_tick_rate-undeclared.patch
+watchdog-rc32434_wdt-fix-watchdog-driver.patch
+watchdog-rc32434_wdt-fix-sections.patch
--- /dev/null
+From 610d18f4128ebbd88845d0fc60cce67b49af881e Mon Sep 17 00:00:00 2001
+From: Davide Libenzi <davidel@xmailserver.org>
+Date: Wed, 18 Feb 2009 14:48:18 -0800
+Subject: timerfd: add flags check
+
+From: Davide Libenzi <davidel@xmailserver.org>
+
+commit 610d18f4128ebbd88845d0fc60cce67b49af881e upstream.
+
+As requested by Michael, add a missing check for valid flags in
+timerfd_settime(), and make it return EINVAL in case some extra bits are
+set.
+
+Michael said:
+If this is to be any use to userland apps that want to check flag
+support (perhaps it is too late already), then the sooner we get it
+into the kernel the better: 2.6.29 would be good; earlier stables as
+well would be even better.
+
+[akpm@linux-foundation.org: remove unused TFD_FLAGS_SET]
+Acked-by: Michael Kerrisk <mtk.manpages@gmail.com>
+Signed-off-by: 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>
+
+---
+ fs/timerfd.c | 12 ++++++------
+ include/linux/timerfd.h | 16 ++++++++++++----
+ 2 files changed, 18 insertions(+), 10 deletions(-)
+
+--- a/fs/timerfd.c
++++ b/fs/timerfd.c
+@@ -188,10 +188,9 @@ SYSCALL_DEFINE2(timerfd_create, int, clo
+ BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
+
+- if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK))
+- return -EINVAL;
+- if (clockid != CLOCK_MONOTONIC &&
+- clockid != CLOCK_REALTIME)
++ if ((flags & ~TFD_CREATE_FLAGS) ||
++ (clockid != CLOCK_MONOTONIC &&
++ clockid != CLOCK_REALTIME))
+ return -EINVAL;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+@@ -203,7 +202,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clo
+ hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
+
+ ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
+- flags & (O_CLOEXEC | O_NONBLOCK));
++ flags & TFD_SHARED_FCNTL_FLAGS);
+ if (ufd < 0)
+ kfree(ctx);
+
+@@ -221,7 +220,8 @@ SYSCALL_DEFINE4(timerfd_settime, int, uf
+ if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
+ return -EFAULT;
+
+- if (!timespec_valid(&ktmr.it_value) ||
++ if ((flags & ~TFD_SETTIME_FLAGS) ||
++ !timespec_valid(&ktmr.it_value) ||
+ !timespec_valid(&ktmr.it_interval))
+ return -EINVAL;
+
+--- a/include/linux/timerfd.h
++++ b/include/linux/timerfd.h
+@@ -11,13 +11,21 @@
+ /* For O_CLOEXEC and O_NONBLOCK */
+ #include <linux/fcntl.h>
+
+-/* Flags for timerfd_settime. */
++/*
++ * CAREFUL: Check include/asm-generic/fcntl.h when defining
++ * new flags, since they might collide with O_* ones. We want
++ * to re-use O_* flags that couldn't possibly have a meaning
++ * from eventfd, in order to leave a free define-space for
++ * shared O_* flags.
++ */
+ #define TFD_TIMER_ABSTIME (1 << 0)
+-
+-/* Flags for timerfd_create. */
+ #define TFD_CLOEXEC O_CLOEXEC
+ #define TFD_NONBLOCK O_NONBLOCK
+
++#define TFD_SHARED_FCNTL_FLAGS (TFD_CLOEXEC | TFD_NONBLOCK)
++/* Flags for timerfd_create. */
++#define TFD_CREATE_FLAGS TFD_SHARED_FCNTL_FLAGS
++/* Flags for timerfd_settime. */
++#define TFD_SETTIME_FLAGS TFD_TIMER_ABSTIME
+
+ #endif /* _LINUX_TIMERFD_H */
+-
--- /dev/null
+From 155df65ae11dfc322214c6f887185929c809df1b Mon Sep 17 00:00:00 2001
+From: Dmitriy Taychenachev <dimichxp@gmail.com>
+Date: Wed, 25 Feb 2009 12:36:51 +0800
+Subject: USB: cdc-acm: add usb id for motomagx phones
+
+From: Dmitriy Taychenachev <dimichxp@gmail.com>
+
+commit 155df65ae11dfc322214c6f887185929c809df1b upstream.
+
+The Motorola MOTOMAGX phones (Z6, E8, Zn5 so far) are providing
+combined ACM/BLAN USB configuration. Since it has Vendor Specific
+class, the corresponding drivers (cdc-acm, zaurus) can't find it just
+by interface info. This patch adds usb id so the cdc-acm driver can
+properly handle this combined device.
+
+Signed-off-by: Dmitriy Taychenachev <dimichxp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1365,6 +1365,8 @@ static struct usb_device_id acm_ids[] =
+ { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */
+ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+ },
++ { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
++ },
+
+ /* control interfaces with various AT-command sets */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
--- /dev/null
+From 5126a2674ddac0804450f59da25a058cca629d38 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 23 Feb 2009 12:02:05 -0500
+Subject: USB: usb-storage: add IGNORE_RESIDUE flag for Genesys Logic adapters
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 5126a2674ddac0804450f59da25a058cca629d38 upstream.
+
+This patch (as1219) adds the IGNORE_RESIDUE flag to the unusual_devs
+entries for Genesys Logic's USB-IDE adapter. Although this device
+usually gets the residue correct, there is one command crucial to the
+operation of CD and DVD drives which it messes up.
+
+Tested-by: Mike Lampard <mike@mtgambier.net>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/storage/unusual_devs.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -953,13 +953,13 @@ UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0x
+ "Genesys Logic",
+ "USB to IDE Optical",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+- US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
++ US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
+
+ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff,
+ "Genesys Logic",
+ "USB to IDE Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+- US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
++ US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
+
+ /* Reported by Hanno Boeck <hanno@gmx.de>
+ * Taken from the Lycoris Kernel */
--- /dev/null
+From 67f5a4ba9741fcef3f4db3509ad03565d9e33af2 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 20 Feb 2009 16:33:08 -0500
+Subject: USB: usb_get_string should check the descriptor type
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 67f5a4ba9741fcef3f4db3509ad03565d9e33af2 upstream.
+
+This patch (as1218) fixes a problem with a radio-control joystick used
+in the "walkera 4#3" helicopter. This device responds to the initial
+Get-String-Descriptor request for string 0 (which is really the list
+of supported languages) by sending its config descriptor! The
+usb_get_string() routine needs to check whether it got the right
+type of descriptor.
+
+Oddly enough, this sort of check is already present in
+usb_get_descriptor(). The patch changes the error code from -EPROTO
+to -ENODATA, because -EPROTO shows up in so many other contexts to
+indicate a hardware failure rather than a firmware error.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Guillermo Jarabo <williamjap@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/message.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -651,7 +651,7 @@ int usb_get_descriptor(struct usb_device
+ if (result <= 0 && result != -ETIMEDOUT)
+ continue;
+ if (result > 1 && ((u8 *)buf)[1] != type) {
+- result = -EPROTO;
++ result = -ENODATA;
+ continue;
+ }
+ break;
+@@ -694,8 +694,13 @@ static int usb_get_string(struct usb_dev
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (USB_DT_STRING << 8) + index, langid, buf, size,
+ USB_CTRL_GET_TIMEOUT);
+- if (!(result == 0 || result == -EPIPE))
+- break;
++ if (result == 0 || result == -EPIPE)
++ continue;
++ if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
++ result = -ENODATA;
++ continue;
++ }
++ break;
+ }
+ return result;
+ }
--- /dev/null
+From b02c387892fc6b3cc59c78ab2f79413d55f50190 Mon Sep 17 00:00:00 2001
+From: Alexey Dobriyan <adobriyan@gmail.com>
+Date: Thu, 12 Feb 2009 13:42:41 +0300
+Subject: WATCHDOG: ks8695_wdt.c: 'CLOCK_TICK_RATE' undeclared
+
+From: Alexey Dobriyan <adobriyan@gmail.com>
+
+commit b02c387892fc6b3cc59c78ab2f79413d55f50190 upstream.
+
+On arm-acs5k_tiny:
+
+drivers/watchdog/ks8695_wdt.c:68: error: 'CLOCK_TICK_RATE' undeclared
+ (first use in this function)
+
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/watchdog/ks8695_wdt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/watchdog/ks8695_wdt.c
++++ b/drivers/watchdog/ks8695_wdt.c
+@@ -21,6 +21,7 @@
+ #include <linux/watchdog.h>
+ #include <linux/io.h>
+ #include <linux/uaccess.h>
++#include <mach/timex.h>
+ #include <mach/regs-timer.h>
+
+ #define WDT_DEFAULT_TIME 5 /* seconds */
--- /dev/null
+From d9a8798c4bab5ccd40e45e011f668099cfb3eb83 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <n0-1@freewrt.org>
+Date: Sun, 8 Feb 2009 16:44:42 +0100
+Subject: WATCHDOG: rc32434_wdt: fix sections
+
+From: Phil Sutter <n0-1@freewrt.org>
+
+commit d9a8798c4bab5ccd40e45e011f668099cfb3eb83 upstream.
+
+Fix init and exit sections.
+
+Signed-off-by: Phil Sutter <n0-1@freewrt.org>
+Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/watchdog/rc32434_wdt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/watchdog/rc32434_wdt.c
++++ b/drivers/watchdog/rc32434_wdt.c
+@@ -33,7 +33,7 @@
+ #include <asm/time.h>
+ #include <asm/mach-rc32434/integ.h>
+
+-#define VERSION "0.3"
++#define VERSION "0.4"
+
+ static struct {
+ unsigned long inuse;
+@@ -241,10 +241,10 @@ static struct miscdevice rc32434_wdt_mis
+ .fops = &rc32434_wdt_fops,
+ };
+
+-static char banner[] = KERN_INFO KBUILD_MODNAME
++static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME
+ ": Watchdog Timer version " VERSION ", timer margin: %d sec\n";
+
+-static int rc32434_wdt_probe(struct platform_device *pdev)
++static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
+ {
+ int ret;
+ struct resource *r;
+@@ -279,7 +279,7 @@ unmap:
+ return ret;
+ }
+
+-static int rc32434_wdt_remove(struct platform_device *pdev)
++static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
+ {
+ misc_deregister(&rc32434_wdt_miscdev);
+ iounmap(wdt_reg);
+@@ -288,8 +288,8 @@ static int rc32434_wdt_remove(struct pla
+
+ static struct platform_driver rc32434_wdt = {
+ .probe = rc32434_wdt_probe,
+- .remove = rc32434_wdt_remove,
+- .driver = {
++ .remove = __devexit_p(rc32434_wdt_remove),
++ .driver = {
+ .name = "rc32434_wdt",
+ }
+ };
--- /dev/null
+From 0af98d37e85e6958eb84987b1f60da3b54008317 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <n0-1@freewrt.org>
+Date: Sun, 8 Feb 2009 16:44:42 +0100
+Subject: WATCHDOG: rc32434_wdt: fix watchdog driver
+
+From: Phil Sutter <n0-1@freewrt.org>
+
+commit 0af98d37e85e6958eb84987b1f60da3b54008317 upstream.
+
+The existing driver code wasn't working. Neither the timeout was set
+correctly, nor system reset was being triggered, as the driver seemed
+to keep the WDT alive himself. There was also some unnecessary code.
+
+Signed-off-by: Phil Sutter <n0-1@freewrt.org>
+Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/watchdog/rc32434_wdt.c | 158 ++++++++++++++++-------------------------
+ 1 file changed, 64 insertions(+), 94 deletions(-)
+
+--- a/drivers/watchdog/rc32434_wdt.c
++++ b/drivers/watchdog/rc32434_wdt.c
+@@ -33,104 +33,89 @@
+ #include <asm/time.h>
+ #include <asm/mach-rc32434/integ.h>
+
+-#define MAX_TIMEOUT 20
+-#define RC32434_WDT_INTERVAL (15 * HZ)
+-
+-#define VERSION "0.2"
++#define VERSION "0.3"
+
+ static struct {
+- struct completion stop;
+- int running;
+- struct timer_list timer;
+- int queue;
+- int default_ticks;
+ unsigned long inuse;
+ } rc32434_wdt_device;
+
+ static struct integ __iomem *wdt_reg;
+-static int ticks = 100 * HZ;
+
+ static int expect_close;
+-static int timeout;
++
++/* Board internal clock speed in Hz,
++ * the watchdog timer ticks at. */
++extern unsigned int idt_cpu_freq;
++
++/* translate wtcompare value to seconds and vice versa */
++#define WTCOMP2SEC(x) (x / idt_cpu_freq)
++#define SEC2WTCOMP(x) (x * idt_cpu_freq)
++
++/* Use a default timeout of 20s. This should be
++ * safe for CPU clock speeds up to 400MHz, as
++ * ((2 ^ 32) - 1) / (400MHz / 2) = 21s. */
++#define WATCHDOG_TIMEOUT 20
++
++static int timeout = WATCHDOG_TIMEOUT;
+
+ static int nowayout = WATCHDOG_NOWAYOUT;
+ module_param(nowayout, int, 0);
+ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
++/* apply or and nand masks to data read from addr and write back */
++#define SET_BITS(addr, or, nand) \
++ writel((readl(&addr) | or) & ~nand, &addr)
+
+ static void rc32434_wdt_start(void)
+ {
+- u32 val;
++ u32 or, nand;
+
+- if (!rc32434_wdt_device.inuse) {
+- writel(0, &wdt_reg->wtcount);
++ /* zero the counter before enabling */
++ writel(0, &wdt_reg->wtcount);
+
+- val = RC32434_ERR_WRE;
+- writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs);
++ /* don't generate a non-maskable interrupt,
++ * do a warm reset instead */
++ nand = 1 << RC32434_ERR_WNE;
++ or = 1 << RC32434_ERR_WRE;
+
+- val = RC32434_WTC_EN;
+- writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc);
+- }
+- rc32434_wdt_device.running++;
+-}
++ /* reset the ERRCS timeout bit in case it's set */
++ nand |= 1 << RC32434_ERR_WTO;
+
+-static void rc32434_wdt_stop(void)
+-{
+- u32 val;
+-
+- if (rc32434_wdt_device.running) {
++ SET_BITS(wdt_reg->errcs, or, nand);
+
+- val = ~RC32434_WTC_EN;
+- writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
++ /* reset WTC timeout bit and enable WDT */
++ nand = 1 << RC32434_WTC_TO;
++ or = 1 << RC32434_WTC_EN;
+
+- val = ~RC32434_ERR_WRE;
+- writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs);
++ SET_BITS(wdt_reg->wtc, or, nand);
++}
+
+- rc32434_wdt_device.running = 0;
+- }
++static void rc32434_wdt_stop(void)
++{
++ /* Disable WDT */
++ SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN);
+ }
+
+-static void rc32434_wdt_set(int new_timeout)
++static int rc32434_wdt_set(int new_timeout)
+ {
+- u32 cmp = new_timeout * HZ;
+- u32 state, val;
++ int max_to = WTCOMP2SEC((u32)-1);
+
++ if (new_timeout < 0 || new_timeout > max_to) {
++ printk(KERN_ERR KBUILD_MODNAME
++ ": timeout value must be between 0 and %d",
++ max_to);
++ return -EINVAL;
++ }
+ timeout = new_timeout;
+- /*
+- * store and disable WTC
+- */
+- state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN);
+- val = ~RC32434_WTC_EN;
+- writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
+-
+- writel(0, &wdt_reg->wtcount);
+- writel(cmp, &wdt_reg->wtcompare);
+-
+- /*
+- * restore WTC
+- */
++ writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare);
+
+- writel(readl(&wdt_reg->wtc) | state, &wdt_reg);
+-}
+-
+-static void rc32434_wdt_reset(void)
+-{
+- ticks = rc32434_wdt_device.default_ticks;
++ return 0;
+ }
+
+-static void rc32434_wdt_update(unsigned long unused)
++static void rc32434_wdt_ping(void)
+ {
+- if (rc32434_wdt_device.running)
+- ticks--;
+-
+ writel(0, &wdt_reg->wtcount);
+-
+- if (rc32434_wdt_device.queue && ticks)
+- mod_timer(&rc32434_wdt_device.timer,
+- jiffies + RC32434_WDT_INTERVAL);
+- else
+- complete(&rc32434_wdt_device.stop);
+ }
+
+ static int rc32434_wdt_open(struct inode *inode, struct file *file)
+@@ -141,19 +126,23 @@ static int rc32434_wdt_open(struct inode
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
++ rc32434_wdt_start();
++ rc32434_wdt_ping();
++
+ return nonseekable_open(inode, file);
+ }
+
+ static int rc32434_wdt_release(struct inode *inode, struct file *file)
+ {
+- if (expect_close && nowayout == 0) {
++ if (expect_close == 42) {
+ rc32434_wdt_stop();
+ printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n");
+ module_put(THIS_MODULE);
+- } else
++ } else {
+ printk(KERN_CRIT KBUILD_MODNAME
+ ": device closed unexpectedly. WDT will not stop !\n");
+-
++ rc32434_wdt_ping();
++ }
+ clear_bit(0, &rc32434_wdt_device.inuse);
+ return 0;
+ }
+@@ -173,10 +162,10 @@ static ssize_t rc32434_wdt_write(struct
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+- expect_close = 1;
++ expect_close = 42;
+ }
+ }
+- rc32434_wdt_update(0);
++ rc32434_wdt_ping();
+ return len;
+ }
+ return 0;
+@@ -196,11 +185,11 @@ static long rc32434_wdt_ioctl(struct fil
+ };
+ switch (cmd) {
+ case WDIOC_KEEPALIVE:
+- rc32434_wdt_reset();
++ rc32434_wdt_ping();
+ break;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+- value = readl(&wdt_reg->wtcount);
++ value = 0;
+ if (copy_to_user(argp, &value, sizeof(int)))
+ return -EFAULT;
+ break;
+@@ -217,6 +206,7 @@ static long rc32434_wdt_ioctl(struct fil
+ break;
+ case WDIOS_DISABLECARD:
+ rc32434_wdt_stop();
++ break;
+ default:
+ return -EINVAL;
+ }
+@@ -224,11 +214,9 @@ static long rc32434_wdt_ioctl(struct fil
+ case WDIOC_SETTIMEOUT:
+ if (copy_from_user(&new_timeout, argp, sizeof(int)))
+ return -EFAULT;
+- if (new_timeout < 1)
++ if (rc32434_wdt_set(new_timeout))
+ return -EINVAL;
+- if (new_timeout > MAX_TIMEOUT)
+- return -EINVAL;
+- rc32434_wdt_set(new_timeout);
++ /* Fall through */
+ case WDIOC_GETTIMEOUT:
+ return copy_to_user(argp, &timeout, sizeof(int));
+ default:
+@@ -261,7 +249,7 @@ static int rc32434_wdt_probe(struct plat
+ int ret;
+ struct resource *r;
+
+- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res");
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res");
+ if (!r) {
+ printk(KERN_ERR KBUILD_MODNAME
+ "failed to retrieve resources\n");
+@@ -276,24 +264,12 @@ static int rc32434_wdt_probe(struct plat
+ }
+
+ ret = misc_register(&rc32434_wdt_miscdev);
+-
+ if (ret < 0) {
+ printk(KERN_ERR KBUILD_MODNAME
+ "failed to register watchdog device\n");
+ goto unmap;
+ }
+
+- init_completion(&rc32434_wdt_device.stop);
+- rc32434_wdt_device.queue = 0;
+-
+- clear_bit(0, &rc32434_wdt_device.inuse);
+-
+- setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L);
+-
+- rc32434_wdt_device.default_ticks = ticks;
+-
+- rc32434_wdt_start();
+-
+ printk(banner, timeout);
+
+ return 0;
+@@ -305,14 +281,8 @@ unmap:
+
+ static int rc32434_wdt_remove(struct platform_device *pdev)
+ {
+- if (rc32434_wdt_device.queue) {
+- rc32434_wdt_device.queue = 0;
+- wait_for_completion(&rc32434_wdt_device.stop);
+- }
+ misc_deregister(&rc32434_wdt_miscdev);
+-
+ iounmap(wdt_reg);
+-
+ return 0;
+ }
+