--- /dev/null
+From 540b60e24f3f4781d80e47122f0c4486a03375b8 Mon Sep 17 00:00:00 2001
+From: Alexander Gordeev <agordeev@redhat.com>
+Date: Fri, 9 Mar 2012 14:59:13 +0100
+Subject: genirq: Fix incorrect check for forced IRQ thread handler
+
+From: Alexander Gordeev <agordeev@redhat.com>
+
+commit 540b60e24f3f4781d80e47122f0c4486a03375b8 upstream.
+
+We do not want a bitwise AND between boolean operands
+
+Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Link: http://lkml.kernel.org/r/20120309135912.GA2114@dhcp-26-207.brq.redhat.com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/irq/manage.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -770,7 +770,7 @@ static int irq_thread(void *data)
+ struct irqaction *action);
+ int wake;
+
+- if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
++ if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
+ &action->thread_flags))
+ handler_fn = irq_forced_thread_fn;
+ else
--- /dev/null
+From a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 Mon Sep 17 00:00:00 2001
+From: Russell King <linux@arm.linux.org.uk>
+Date: Mon, 5 Mar 2012 15:07:25 -0800
+Subject: genirq: Fix long-term regression in genirq irq_set_irq_type() handling
+
+From: Russell King <linux@arm.linux.org.uk>
+
+commit a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 upstream.
+
+In 2008, commit 0c5d1eb77a8be ("genirq: record trigger type") modified the
+way set_irq_type() handles the 'no trigger' condition. However, this has
+an adverse effect on PCMCIA support on Intel StrongARM and probably PXA
+platforms.
+
+PCMCIA has several status signals on the socket which can trigger
+interrupts; some of these status signals depend on the card's mode
+(whether it is configured in memory or IO mode). For example, cards have
+a 'Ready/IRQ' signal: in memory mode, this provides an indication to
+PCMCIA that the card has finished its power up initialization. In IO
+mode, it provides the device interrupt signal. Other status signals
+switch between on-board battery status and loud speaker output.
+
+In classical PCMCIA implementations, where you have a specific socket
+controller, the controller provides a method to mask interrupts from the
+socket, and importantly ignore any state transitions on the pins which
+correspond with interrupts once masked. This masking prevents unwanted
+events caused by the removal and application of socket power being
+forwarded.
+
+However, on platforms where there is no socket controller, the PCMCIA
+status and interrupt signals are routed to standard edge-triggered GPIOs.
+These GPIOs can be configured to interrupt on rising edge, falling edge,
+or never. This is where the problems start.
+
+Edge triggered interrupts are required to record events while disabled via
+the usual methods of {free,request,disable,enable}_irq() to prevent
+problems with dropped interrupts (eg, the 8390 driver uses disable_irq()
+to defer the delivery of interrupts). As a result, these interfaces can
+not be used to implement the desired behaviour.
+
+The side effect of this is that if the 'Ready/IRQ' GPIO is disabled via
+disable_irq() on suspend, and enabled via enable_irq() after resume, we
+will record the state transitions caused by powering events as valid
+interrupts, and foward them to the card driver, which may attempt to
+access a card which is not powered up.
+
+This leads delays resume while drivers spin in their interrupt handlers,
+and complaints from drivers before they realize what's happened.
+
+Moreover, in the case of the 'Ready/IRQ' signal, this is requested and
+freed by the card driver itself; the PCMCIA core has no idea whether the
+interrupt is requested, and, therefore, whether a call to disable_irq()
+would be valid. (We tried this around 2.4.17 / 2.5.1 kernel era, and
+ended up throwing it out because of this problem.)
+
+Therefore, it was decided back in around 2002 to disable the edge
+triggering instead, resulting in all state transitions on the GPIO being
+ignored. That's what we actually need the hardware to do.
+
+The commit above changes this behaviour; it explicitly prevents the 'no
+trigger' state being selected.
+
+The reason that request_irq() does not accept the 'no trigger' state is
+for compatibility with existing drivers which do not provide their desired
+triggering configuration. The set_irq_type() function is 'new' and not
+used by non-trigger aware drivers.
+
+Therefore, revert this change, and restore previously working platforms
+back to their former state.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Cc: linux@arm.linux.org.uk
+Cc: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/irq/chip.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/kernel/irq/chip.c
++++ b/kernel/irq/chip.c
+@@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, u
+ return -EINVAL;
+
+ type &= IRQ_TYPE_SENSE_MASK;
+- if (type != IRQ_TYPE_NONE)
+- ret = __irq_set_trigger(desc, irq, type);
++ ret = __irq_set_trigger(desc, irq, type);
+ irq_put_desc_busunlock(desc, flags);
+ return ret;
+ }
--- /dev/null
+From 89e984e2c2cd14f77ccb26c47726ac7f13b70ae8 Mon Sep 17 00:00:00 2001
+From: Or Gerlitz <ogerlitz@mellanox.com>
+Date: Mon, 5 Mar 2012 18:21:44 +0200
+Subject: IB/iser: Post initial receive buffers before sending the final login request
+
+From: Or Gerlitz <ogerlitz@mellanox.com>
+
+commit 89e984e2c2cd14f77ccb26c47726ac7f13b70ae8 upstream.
+
+An iser target may send iscsi NO-OP PDUs as soon as it marks the iSER
+iSCSI session as fully operative. This means that there is window
+where there are no posted receive buffers on the initiator side, so
+it's possible for the iSER RC connection to break because of RNR NAK /
+retry errors. To fix this, rely on the flags bits in the login
+request to have FFP (0x3) in the lower nibble as a marker for the
+final login request, and post an initial chunk of receive buffers
+before sending that login request instead of after getting the login
+response.
+
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/iser/iscsi_iser.c | 18 +++-------------
+ drivers/infiniband/ulp/iser/iscsi_iser.h | 1
+ drivers/infiniband/ulp/iser/iser_initiator.c | 30 +++++++++++++++------------
+ 3 files changed, 22 insertions(+), 27 deletions(-)
+
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -354,6 +354,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_se
+ }
+ ib_conn = ep->dd_data;
+
++ if (iser_alloc_rx_descriptors(ib_conn))
++ return -ENOMEM;
++
+ /* binds the iSER connection retrieved from the previously
+ * connected ep_handle to the iSCSI layer connection. exchanges
+ * connection pointers */
+@@ -388,19 +391,6 @@ iscsi_iser_conn_stop(struct iscsi_cls_co
+ iser_conn->ib_conn = NULL;
+ }
+
+-static int
+-iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
+-{
+- struct iscsi_conn *conn = cls_conn->dd_data;
+- int err;
+-
+- err = iser_conn_set_full_featured_mode(conn);
+- if (err)
+- return err;
+-
+- return iscsi_conn_start(cls_conn);
+-}
+-
+ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
+ {
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+@@ -686,7 +676,7 @@ static struct iscsi_transport iscsi_iser
+ .get_conn_param = iscsi_conn_get_param,
+ .get_ep_param = iscsi_iser_get_ep_param,
+ .get_session_param = iscsi_session_get_param,
+- .start_conn = iscsi_iser_conn_start,
++ .start_conn = iscsi_conn_start,
+ .stop_conn = iscsi_iser_conn_stop,
+ /* iscsi host params */
+ .get_host_param = iscsi_host_get_param,
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -365,4 +365,5 @@ int iser_dma_map_task_data(struct iscsi_
+ void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
+ int iser_initialize_task_headers(struct iscsi_task *task,
+ struct iser_tx_desc *tx_desc);
++int iser_alloc_rx_descriptors(struct iser_conn *ib_conn);
+ #endif
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -170,7 +170,7 @@ static void iser_create_send_desc(struct
+ }
+
+
+-static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
++int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
+ {
+ int i, j;
+ u64 dma_addr;
+@@ -236,23 +236,24 @@ void iser_free_rx_descriptors(struct ise
+ kfree(ib_conn->rx_descs);
+ }
+
+-/**
+- * iser_conn_set_full_featured_mode - (iSER API)
+- */
+-int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
++static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
+ {
+ struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+- iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
++ iser_dbg("req op %x flags %x\n", req->opcode, req->flags);
++ /* check if this is the last login - going to full feature phase */
++ if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE)
++ return 0;
+
+- /* Check that there is no posted recv or send buffers left - */
+- /* they must be consumed during the login phase */
+- BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
+- BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+-
+- if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
+- return -ENOMEM;
++ /*
++ * Check that there is one posted recv buffer (for the last login
++ * response) and no posted send buffers left - they must have been
++ * consumed during previous login phases.
++ */
++ WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1);
++ WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+
++ iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
+ /* Initial post receive buffers */
+ if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
+ return -ENOMEM;
+@@ -421,6 +422,9 @@ int iser_send_control(struct iscsi_conn
+ err = iser_post_recvl(iser_conn->ib_conn);
+ if (err)
+ goto send_control_error;
++ err = iser_post_rx_bufs(conn, task->hdr);
++ if (err)
++ goto send_control_error;
+ }
+
+ err = iser_post_send(iser_conn->ib_conn, mdesc);
--- /dev/null
+From f910381a55cdaa097030291f272f6e6e4380c39a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <levinsasha928@gmail.com>
+Date: Thu, 15 Mar 2012 12:36:13 -0400
+Subject: math: Introduce div64_long
+
+From: Sasha Levin <levinsasha928@gmail.com>
+
+commit f910381a55cdaa097030291f272f6e6e4380c39a upstream.
+
+Add a div64_long macro which is used to devide a 64bit number by a long (which
+can be 4 bytes on 32bit systems and 8 bytes on 64bit systems).
+
+Suggested-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
+Cc: johnstul@us.ibm.com
+Link: http://lkml.kernel.org/r/1331829374-31543-1-git-send-email-levinsasha928@gmail.com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/math64.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/include/linux/math64.h
++++ b/include/linux/math64.h
+@@ -6,6 +6,8 @@
+
+ #if BITS_PER_LONG == 64
+
++#define div64_long(x,y) div64_s64((x),(y))
++
+ /**
+ * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
+ *
+@@ -45,6 +47,8 @@ static inline s64 div64_s64(s64 dividend
+
+ #elif BITS_PER_LONG == 32
+
++#define div64_long(x,y) div_s64((x),(y))
++
+ #ifndef div_u64_rem
+ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
+ {
--- /dev/null
+From 1a5a9906d4e8d1976b701f889d8f35d54b928f25 Mon Sep 17 00:00:00 2001
+From: Andrea Arcangeli <aarcange@redhat.com>
+Date: Wed, 21 Mar 2012 16:33:42 -0700
+Subject: mm: thp: fix pmd_bad() triggering in code paths holding mmap_sem read mode
+
+From: Andrea Arcangeli <aarcange@redhat.com>
+
+commit 1a5a9906d4e8d1976b701f889d8f35d54b928f25 upstream.
+
+In some cases it may happen that pmd_none_or_clear_bad() is called with
+the mmap_sem hold in read mode. In those cases the huge page faults can
+allocate hugepmds under pmd_none_or_clear_bad() and that can trigger a
+false positive from pmd_bad() that will not like to see a pmd
+materializing as trans huge.
+
+It's not khugepaged causing the problem, khugepaged holds the mmap_sem
+in write mode (and all those sites must hold the mmap_sem in read mode
+to prevent pagetables to go away from under them, during code review it
+seems vm86 mode on 32bit kernels requires that too unless it's
+restricted to 1 thread per process or UP builds). The race is only with
+the huge pagefaults that can convert a pmd_none() into a
+pmd_trans_huge().
+
+Effectively all these pmd_none_or_clear_bad() sites running with
+mmap_sem in read mode are somewhat speculative with the page faults, and
+the result is always undefined when they run simultaneously. This is
+probably why it wasn't common to run into this. For example if the
+madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page
+fault, the hugepage will not be zapped, if the page fault runs first it
+will be zapped.
+
+Altering pmd_bad() not to error out if it finds hugepmds won't be enough
+to fix this, because zap_pmd_range would then proceed to call
+zap_pte_range (which would be incorrect if the pmd become a
+pmd_trans_huge()).
+
+The simplest way to fix this is to read the pmd in the local stack
+(regardless of what we read, no need of actual CPU barriers, only
+compiler barrier needed), and be sure it is not changing under the code
+that computes its value. Even if the real pmd is changing under the
+value we hold on the stack, we don't care. If we actually end up in
+zap_pte_range it means the pmd was not none already and it was not huge,
+and it can't become huge from under us (khugepaged locking explained
+above).
+
+All we need is to enforce that there is no way anymore that in a code
+path like below, pmd_trans_huge can be false, but pmd_none_or_clear_bad
+can run into a hugepmd. The overhead of a barrier() is just a compiler
+tweak and should not be measurable (I only added it for THP builds). I
+don't exclude different compiler versions may have prevented the race
+too by caching the value of *pmd on the stack (that hasn't been
+verified, but it wouldn't be impossible considering
+pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none are all inlines
+and there's no external function called in between pmd_trans_huge and
+pmd_none_or_clear_bad).
+
+ if (pmd_trans_huge(*pmd)) {
+ if (next-addr != HPAGE_PMD_SIZE) {
+ VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem));
+ split_huge_page_pmd(vma->vm_mm, pmd);
+ } else if (zap_huge_pmd(tlb, vma, pmd, addr))
+ continue;
+ /* fall through */
+ }
+ if (pmd_none_or_clear_bad(pmd))
+
+Because this race condition could be exercised without special
+privileges this was reported in CVE-2012-1179.
+
+The race was identified and fully explained by Ulrich who debugged it.
+I'm quoting his accurate explanation below, for reference.
+
+====== start quote =======
+ mapcount 0 page_mapcount 1
+ kernel BUG at mm/huge_memory.c:1384!
+
+ At some point prior to the panic, a "bad pmd ..." message similar to the
+ following is logged on the console:
+
+ mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7).
+
+ The "bad pmd ..." message is logged by pmd_clear_bad() before it clears
+ the page's PMD table entry.
+
+ 143 void pmd_clear_bad(pmd_t *pmd)
+ 144 {
+ -> 145 pmd_ERROR(*pmd);
+ 146 pmd_clear(pmd);
+ 147 }
+
+ After the PMD table entry has been cleared, there is an inconsistency
+ between the actual number of PMD table entries that are mapping the page
+ and the page's map count (_mapcount field in struct page). When the page
+ is subsequently reclaimed, __split_huge_page() detects this inconsistency.
+
+ 1381 if (mapcount != page_mapcount(page))
+ 1382 printk(KERN_ERR "mapcount %d page_mapcount %d\n",
+ 1383 mapcount, page_mapcount(page));
+ -> 1384 BUG_ON(mapcount != page_mapcount(page));
+
+ The root cause of the problem is a race of two threads in a multithreaded
+ process. Thread B incurs a page fault on a virtual address that has never
+ been accessed (PMD entry is zero) while Thread A is executing an madvise()
+ system call on a virtual address within the same 2 MB (huge page) range.
+
+ virtual address space
+ .---------------------.
+ | |
+ | |
+ .-|---------------------|
+ | | |
+ | | |<-- B(fault)
+ | | |
+ 2 MB | |/////////////////////|-.
+ huge < |/////////////////////| > A(range)
+ page | |/////////////////////|-'
+ | | |
+ | | |
+ '-|---------------------|
+ | |
+ | |
+ '---------------------'
+
+ - Thread A is executing an madvise(..., MADV_DONTNEED) system call
+ on the virtual address range "A(range)" shown in the picture.
+
+ sys_madvise
+ // Acquire the semaphore in shared mode.
+ down_read(¤t->mm->mmap_sem)
+ ...
+ madvise_vma
+ switch (behavior)
+ case MADV_DONTNEED:
+ madvise_dontneed
+ zap_page_range
+ unmap_vmas
+ unmap_page_range
+ zap_pud_range
+ zap_pmd_range
+ //
+ // Assume that this huge page has never been accessed.
+ // I.e. content of the PMD entry is zero (not mapped).
+ //
+ if (pmd_trans_huge(*pmd)) {
+ // We don't get here due to the above assumption.
+ }
+ //
+ // Assume that Thread B incurred a page fault and
+ .---------> // sneaks in here as shown below.
+ | //
+ | if (pmd_none_or_clear_bad(pmd))
+ | {
+ | if (unlikely(pmd_bad(*pmd)))
+ | pmd_clear_bad
+ | {
+ | pmd_ERROR
+ | // Log "bad pmd ..." message here.
+ | pmd_clear
+ | // Clear the page's PMD entry.
+ | // Thread B incremented the map count
+ | // in page_add_new_anon_rmap(), but
+ | // now the page is no longer mapped
+ | // by a PMD entry (-> inconsistency).
+ | }
+ | }
+ |
+ v
+ - Thread B is handling a page fault on virtual address "B(fault)" shown
+ in the picture.
+
+ ...
+ do_page_fault
+ __do_page_fault
+ // Acquire the semaphore in shared mode.
+ down_read_trylock(&mm->mmap_sem)
+ ...
+ handle_mm_fault
+ if (pmd_none(*pmd) && transparent_hugepage_enabled(vma))
+ // We get here due to the above assumption (PMD entry is zero).
+ do_huge_pmd_anonymous_page
+ alloc_hugepage_vma
+ // Allocate a new transparent huge page here.
+ ...
+ __do_huge_pmd_anonymous_page
+ ...
+ spin_lock(&mm->page_table_lock)
+ ...
+ page_add_new_anon_rmap
+ // Here we increment the page's map count (starts at -1).
+ atomic_set(&page->_mapcount, 0)
+ set_pmd_at
+ // Here we set the page's PMD entry which will be cleared
+ // when Thread A calls pmd_clear_bad().
+ ...
+ spin_unlock(&mm->page_table_lock)
+
+ The mmap_sem does not prevent the race because both threads are acquiring
+ it in shared mode (down_read). Thread B holds the page_table_lock while
+ the page's map count and PMD table entry are updated. However, Thread A
+ does not synchronize on that lock.
+
+====== end quote =======
+
+[akpm@linux-foundation.org: checkpatch fixes]
+Reported-by: Ulrich Obergfell <uobergfe@redhat.com>
+Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Dave Jones <davej@redhat.com>
+Acked-by: Larry Woodman <lwoodman@redhat.com>
+Acked-by: Rik van Riel <riel@redhat.com>
+Cc: Mark Salter <msalter@redhat.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@linuxfoundation.org>
+
+---
+ arch/x86/kernel/vm86_32.c | 2 +
+ fs/proc/task_mmu.c | 9 ++++++
+ include/asm-generic/pgtable.h | 61 ++++++++++++++++++++++++++++++++++++++++++
+ mm/memcontrol.c | 4 ++
+ mm/memory.c | 16 ++++++++---
+ mm/mempolicy.c | 2 -
+ mm/mincore.c | 2 -
+ mm/pagewalk.c | 2 -
+ mm/swapfile.c | 4 --
+ 9 files changed, 92 insertions(+), 10 deletions(-)
+
+--- a/arch/x86/kernel/vm86_32.c
++++ b/arch/x86/kernel/vm86_32.c
+@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm
+ spinlock_t *ptl;
+ int i;
+
++ down_write(&mm->mmap_sem);
+ pgd = pgd_offset(mm, 0xA0000);
+ if (pgd_none_or_clear_bad(pgd))
+ goto out;
+@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm
+ }
+ pte_unmap_unlock(pte, ptl);
+ out:
++ up_write(&mm->mmap_sem);
+ flush_tlb();
+ }
+
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -407,6 +407,9 @@ static int smaps_pte_range(pmd_t *pmd, u
+ } else {
+ spin_unlock(&walk->mm->page_table_lock);
+ }
++
++ if (pmd_trans_unstable(pmd))
++ return 0;
+ /*
+ * The mmap_sem held all the way back in m_start() is what
+ * keeps khugepaged out of here and from collapsing things
+@@ -505,6 +508,8 @@ static int clear_refs_pte_range(pmd_t *p
+ struct page *page;
+
+ split_huge_page_pmd(walk->mm, pmd);
++ if (pmd_trans_unstable(pmd))
++ return 0;
+
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+ for (; addr != end; pte++, addr += PAGE_SIZE) {
+@@ -668,6 +673,8 @@ static int pagemap_pte_range(pmd_t *pmd,
+ int err = 0;
+
+ split_huge_page_pmd(walk->mm, pmd);
++ if (pmd_trans_unstable(pmd))
++ return 0;
+
+ /* find the first VMA at or above 'addr' */
+ vma = find_vma(walk->mm, addr);
+@@ -959,6 +966,8 @@ static int gather_pte_stats(pmd_t *pmd,
+ spin_unlock(&walk->mm->page_table_lock);
+ }
+
++ if (pmd_trans_unstable(pmd))
++ return 0;
+ orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+ do {
+ struct page *page = can_gather_numa_stats(*pte, md->vma, addr);
+--- a/include/asm-generic/pgtable.h
++++ b/include/asm-generic/pgtable.h
+@@ -425,6 +425,8 @@ extern void untrack_pfn_vma(struct vm_ar
+ unsigned long size);
+ #endif
+
++#ifdef CONFIG_MMU
++
+ #ifndef CONFIG_TRANSPARENT_HUGEPAGE
+ static inline int pmd_trans_huge(pmd_t pmd)
+ {
+@@ -441,7 +443,66 @@ static inline int pmd_write(pmd_t pmd)
+ return 0;
+ }
+ #endif /* __HAVE_ARCH_PMD_WRITE */
++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
++
++/*
++ * This function is meant to be used by sites walking pagetables with
++ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and
++ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd
++ * into a null pmd and the transhuge page fault can convert a null pmd
++ * into an hugepmd or into a regular pmd (if the hugepage allocation
++ * fails). While holding the mmap_sem in read mode the pmd becomes
++ * stable and stops changing under us only if it's not null and not a
++ * transhuge pmd. When those races occurs and this function makes a
++ * difference vs the standard pmd_none_or_clear_bad, the result is
++ * undefined so behaving like if the pmd was none is safe (because it
++ * can return none anyway). The compiler level barrier() is critically
++ * important to compute the two checks atomically on the same pmdval.
++ */
++static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
++{
++ /* depend on compiler for an atomic pmd read */
++ pmd_t pmdval = *pmd;
++ /*
++ * The barrier will stabilize the pmdval in a register or on
++ * the stack so that it will stop changing under the code.
++ */
++#ifdef CONFIG_TRANSPARENT_HUGEPAGE
++ barrier();
+ #endif
++ if (pmd_none(pmdval))
++ return 1;
++ if (unlikely(pmd_bad(pmdval))) {
++ if (!pmd_trans_huge(pmdval))
++ pmd_clear_bad(pmd);
++ return 1;
++ }
++ return 0;
++}
++
++/*
++ * This is a noop if Transparent Hugepage Support is not built into
++ * the kernel. Otherwise it is equivalent to
++ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in
++ * places that already verified the pmd is not none and they want to
++ * walk ptes while holding the mmap sem in read mode (write mode don't
++ * need this). If THP is not enabled, the pmd can't go away under the
++ * code even if MADV_DONTNEED runs, but if THP is enabled we need to
++ * run a pmd_trans_unstable before walking the ptes after
++ * split_huge_page_pmd returns (because it may have run when the pmd
++ * become null, but then a page fault can map in a THP and not a
++ * regular page).
++ */
++static inline int pmd_trans_unstable(pmd_t *pmd)
++{
++#ifdef CONFIG_TRANSPARENT_HUGEPAGE
++ return pmd_none_or_trans_huge_or_clear_bad(pmd);
++#else
++ return 0;
++#endif
++}
++
++#endif /* CONFIG_MMU */
+
+ #endif /* !__ASSEMBLY__ */
+
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -5290,6 +5290,8 @@ static int mem_cgroup_count_precharge_pt
+ spinlock_t *ptl;
+
+ split_huge_page_pmd(walk->mm, pmd);
++ if (pmd_trans_unstable(pmd))
++ return 0;
+
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+ for (; addr != end; pte++, addr += PAGE_SIZE)
+@@ -5451,6 +5453,8 @@ static int mem_cgroup_move_charge_pte_ra
+ spinlock_t *ptl;
+
+ split_huge_page_pmd(walk->mm, pmd);
++ if (pmd_trans_unstable(pmd))
++ return 0;
+ retry:
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+ for (; addr != end; addr += PAGE_SIZE) {
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -1228,16 +1228,24 @@ static inline unsigned long zap_pmd_rang
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_trans_huge(*pmd)) {
+- if (next-addr != HPAGE_PMD_SIZE) {
++ if (next - addr != HPAGE_PMD_SIZE) {
+ VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem));
+ split_huge_page_pmd(vma->vm_mm, pmd);
+ } else if (zap_huge_pmd(tlb, vma, pmd))
+- continue;
++ goto next;
+ /* fall through */
+ }
+- if (pmd_none_or_clear_bad(pmd))
+- continue;
++ /*
++ * Here there can be other concurrent MADV_DONTNEED or
++ * trans huge page faults running, and if the pmd is
++ * none or trans huge it can change under us. This is
++ * because MADV_DONTNEED holds the mmap_sem in read
++ * mode.
++ */
++ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
++ goto next;
+ next = zap_pte_range(tlb, vma, pmd, addr, next, details);
++next:
+ cond_resched();
+ } while (pmd++, addr = next, addr != end);
+
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -511,7 +511,7 @@ static inline int check_pmd_range(struct
+ do {
+ next = pmd_addr_end(addr, end);
+ split_huge_page_pmd(vma->vm_mm, pmd);
+- if (pmd_none_or_clear_bad(pmd))
++ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+ continue;
+ if (check_pte_range(vma, pmd, addr, next, nodes,
+ flags, private))
+--- a/mm/mincore.c
++++ b/mm/mincore.c
+@@ -161,7 +161,7 @@ static void mincore_pmd_range(struct vm_
+ }
+ /* fall through */
+ }
+- if (pmd_none_or_clear_bad(pmd))
++ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+ mincore_unmapped_range(vma, addr, next, vec);
+ else
+ mincore_pte_range(vma, pmd, addr, next, vec);
+--- a/mm/pagewalk.c
++++ b/mm/pagewalk.c
+@@ -59,7 +59,7 @@ again:
+ continue;
+
+ split_huge_page_pmd(walk->mm, pmd);
+- if (pmd_none_or_clear_bad(pmd))
++ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+ goto again;
+ err = walk_pte_range(pmd, addr, next, walk);
+ if (err)
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+- if (unlikely(pmd_trans_huge(*pmd)))
+- continue;
+- if (pmd_none_or_clear_bad(pmd))
++ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+ continue;
+ ret = unuse_pte_range(vma, pmd, addr, next, entry, page);
+ if (ret)
--- /dev/null
+From a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <levinsasha928@gmail.com>
+Date: Thu, 15 Mar 2012 12:36:14 -0400
+Subject: ntp: Fix integer overflow when setting time
+
+From: Sasha Levin <levinsasha928@gmail.com>
+
+commit a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33 upstream.
+
+'long secs' is passed as divisor to div_s64, which accepts a 32bit
+divisor. On 64bit machines that value is trimmed back from 8 bytes
+back to 4, causing a divide by zero when the number is bigger than
+(1 << 32) - 1 and all 32 lower bits are 0.
+
+Use div64_long() instead.
+
+Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
+Cc: johnstul@us.ibm.com
+Link: http://lkml.kernel.org/r/1331829374-31543-2-git-send-email-levinsasha928@gmail.com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/time/ntp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -275,7 +275,7 @@ static inline s64 ntp_update_offset_fll(
+
+ time_status |= STA_MODE;
+
+- return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
++ return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
+ }
+
+ static void ntp_update_offset(long offset)
--- /dev/null
+From 62ebeed8d00aef75eac4fd6c161cae75a41965ca Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Thu, 1 Mar 2012 00:40:08 +0400
+Subject: p54spi: Release GPIO lines and IRQ on error in p54spi_probe
+
+From: Max Filippov <jcmvbkbc@gmail.com>
+
+commit 62ebeed8d00aef75eac4fd6c161cae75a41965ca upstream.
+
+This makes it possible to reload driver if insmod has failed due to
+missing firmware.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+Acked-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/p54/p54spi.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/p54/p54spi.c
++++ b/drivers/net/wireless/p54/p54spi.c
+@@ -623,19 +623,19 @@ static int __devinit p54spi_probe(struct
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ dev_err(&priv->spi->dev, "spi_setup failed");
+- goto err_free_common;
++ goto err_free;
+ }
+
+ ret = gpio_request(p54spi_gpio_power, "p54spi power");
+ if (ret < 0) {
+ dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
+- goto err_free_common;
++ goto err_free;
+ }
+
+ ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
+ if (ret < 0) {
+ dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
+- goto err_free_common;
++ goto err_free_gpio_power;
+ }
+
+ gpio_direction_output(p54spi_gpio_power, 0);
+@@ -646,7 +646,7 @@ static int __devinit p54spi_probe(struct
+ priv->spi);
+ if (ret < 0) {
+ dev_err(&priv->spi->dev, "request_irq() failed");
+- goto err_free_common;
++ goto err_free_gpio_irq;
+ }
+
+ irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
+@@ -678,6 +678,12 @@ static int __devinit p54spi_probe(struct
+ return 0;
+
+ err_free_common:
++ free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
++err_free_gpio_irq:
++ gpio_free(p54spi_gpio_irq);
++err_free_gpio_power:
++ gpio_free(p54spi_gpio_power);
++err_free:
+ p54_free_common(priv->hw);
+ return ret;
+ }
--- /dev/null
+From d42a179b941a9e4cc6cf41d0f3cbadd75fc48a89 Mon Sep 17 00:00:00 2001
+From: Gertjan van Wingerde <gwingerde@gmail.com>
+Date: Sat, 11 Feb 2012 21:58:09 +0100
+Subject: rt2x00: Add support for D-Link DWA-127 to rt2800usb.
+
+From: Gertjan van Wingerde <gwingerde@gmail.com>
+
+commit d42a179b941a9e4cc6cf41d0f3cbadd75fc48a89 upstream.
+
+This is an RT3070 based device.
+
+Reported-by: Mikhail Kryshen <mikhail@kryshen.net>
+Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
+Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rt2x00/rt2800usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800usb.c
++++ b/drivers/net/wireless/rt2x00/rt2800usb.c
+@@ -839,6 +839,7 @@ static struct usb_device_id rt2800usb_de
+ { USB_DEVICE(0x07d1, 0x3c0f) },
+ { USB_DEVICE(0x07d1, 0x3c11) },
+ { USB_DEVICE(0x07d1, 0x3c16) },
++ { USB_DEVICE(0x2001, 0x3c1b) },
+ /* Draytek */
+ { USB_DEVICE(0x07fa, 0x7712) },
+ /* Edimax */
--- /dev/null
+From 41c7f7424259ff11009449f87c95656f69f9b186 Mon Sep 17 00:00:00 2001
+From: Rabin Vincent <rabin.vincent@stericsson.com>
+Date: Tue, 22 Nov 2011 11:03:14 +0100
+Subject: rtc: Disable the alarm in the hardware (v2)
+
+From: Rabin Vincent <rabin.vincent@stericsson.com>
+
+commit 41c7f7424259ff11009449f87c95656f69f9b186 upstream.
+
+Currently, the RTC code does not disable the alarm in the hardware.
+
+This means that after a sequence such as the one below (the files are in the
+RTC sysfs), the box will boot up after 2 minutes even though we've
+asked for the alarm to be turned off.
+
+ # echo $((`cat since_epoch`)+120) > wakealarm
+ # echo 0 > wakealarm
+ # poweroff
+
+Fix this by disabling the alarm when there are no timers to run.
+
+The original version of this patch was reverted. This version
+disables the irq directly instead of setting a disabled timer
+in the future.
+
+Cc: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
+[Merged in the second revision from Rabin]
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/rtc/interface.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/rtc/interface.c
++++ b/drivers/rtc/interface.c
+@@ -762,6 +762,14 @@ static int rtc_timer_enqueue(struct rtc_
+ return 0;
+ }
+
++static void rtc_alarm_disable(struct rtc_device *rtc)
++{
++ if (!rtc->ops || !rtc->ops->alarm_irq_enable)
++ return;
++
++ rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
++}
++
+ /**
+ * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
+ * @rtc rtc device
+@@ -783,8 +791,10 @@ static void rtc_timer_remove(struct rtc_
+ struct rtc_wkalrm alarm;
+ int err;
+ next = timerqueue_getnext(&rtc->timerqueue);
+- if (!next)
++ if (!next) {
++ rtc_alarm_disable(rtc);
+ return;
++ }
+ alarm.time = rtc_ktime_to_tm(next->expires);
+ alarm.enabled = 1;
+ err = __rtc_set_alarm(rtc, &alarm);
+@@ -846,7 +856,8 @@ again:
+ err = __rtc_set_alarm(rtc, &alarm);
+ if (err == -ETIME)
+ goto again;
+- }
++ } else
++ rtc_alarm_disable(rtc);
+
+ mutex_unlock(&rtc->ops_lock);
+ }
--- /dev/null
+From 7f66c2f93e5779625c10d262c84537427a2673ca Mon Sep 17 00:00:00 2001
+From: Simon Graham <simon.graham@virtualcomputer.com>
+Date: Tue, 7 Feb 2012 18:07:38 -0600
+Subject: rtlwifi: Handle previous allocation failures when freeing device memory
+
+From: Simon Graham <simon.graham@virtualcomputer.com>
+
+commit 7f66c2f93e5779625c10d262c84537427a2673ca upstream.
+
+Handle previous allocation failures when freeing device memory
+
+Signed-off-by: Simon Graham <simon.graham@virtualcomputer.com>
+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@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/rtlwifi/pci.c
++++ b/drivers/net/wireless/rtlwifi/pci.c
+@@ -1180,10 +1180,12 @@ static void _rtl_pci_free_tx_ring(struct
+ ring->idx = (ring->idx + 1) % ring->entries;
+ }
+
+- pci_free_consistent(rtlpci->pdev,
+- sizeof(*ring->desc) * ring->entries,
+- ring->desc, ring->dma);
+- ring->desc = NULL;
++ if (ring->desc) {
++ pci_free_consistent(rtlpci->pdev,
++ sizeof(*ring->desc) * ring->entries,
++ ring->desc, ring->dma);
++ ring->desc = NULL;
++ }
+ }
+
+ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
+@@ -1207,12 +1209,14 @@ static void _rtl_pci_free_rx_ring(struct
+ kfree_skb(skb);
+ }
+
+- pci_free_consistent(rtlpci->pdev,
++ if (rtlpci->rx_ring[rx_queue_idx].desc) {
++ pci_free_consistent(rtlpci->pdev,
+ sizeof(*rtlpci->rx_ring[rx_queue_idx].
+ desc) * rtlpci->rxringcount,
+ rtlpci->rx_ring[rx_queue_idx].desc,
+ rtlpci->rx_ring[rx_queue_idx].dma);
+- rtlpci->rx_ring[rx_queue_idx].desc = NULL;
++ rtlpci->rx_ring[rx_queue_idx].desc = NULL;
++ }
+ }
+ }
+
--- /dev/null
+From ebecdcc12fed5d3c81853dea61a0a78a5aefab52 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Fri, 2 Mar 2012 15:23:36 -0600
+Subject: rtlwifi: rtl8192c: Prevent sleeping from invalid context in rtl8192cu
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit ebecdcc12fed5d3c81853dea61a0a78a5aefab52 upstream.
+
+When driver rtl8192cu is used with the debug level set to 3 or greater,
+the result is "sleeping function called from invalid context" due to
+an rcu_read_lock() call in the DM refresh routine in driver rtl8192c.
+This lock is not necessary as the USB driver does not use the struct
+being protected, thus the lock is set only when a PCI interface is
+active.
+
+This bug is reported in https://bugzilla.kernel.org/show_bug.cgi?id=42775.
+
+Reported-by: Ronald Wahl <ronald.wahl@raritan.com>
+Tested-by: Ronald Wahl <ronald.wahl@raritan.com>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Cc: Ronald Wahl <ronald.wahl@raritan.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+@@ -1218,13 +1218,18 @@ static void rtl92c_dm_refresh_rate_adapt
+ ("PreState = %d, CurState = %d\n",
+ p_ra->pre_ratr_state, p_ra->ratr_state));
+
+- rcu_read_lock();
+- sta = ieee80211_find_sta(mac->vif, mac->bssid);
++ /* Only the PCI card uses sta in the update rate table
++ * callback routine */
++ if (rtlhal->interface == INTF_PCI) {
++ rcu_read_lock();
++ sta = ieee80211_find_sta(mac->vif, mac->bssid);
++ }
+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
+ p_ra->ratr_state);
+
+ p_ra->pre_ratr_state = p_ra->ratr_state;
+- rcu_read_unlock();
++ if (rtlhal->interface == INTF_PCI)
++ rcu_read_unlock();
+ }
+ }
+ }
--- /dev/null
+From a9b89e2567c743483e6354f64d7a7e3a8c101e9e Mon Sep 17 00:00:00 2001
+From: Jingjun Wu <jingjun_wu@realsil.com.cn>
+Date: Fri, 2 Mar 2012 20:52:14 -0600
+Subject: rtlwifi: rtl8192ce: Fix loss of receive performance
+
+From: Jingjun Wu <jingjun_wu@realsil.com.cn>
+
+commit a9b89e2567c743483e6354f64d7a7e3a8c101e9e upstream.
+
+Driver rtl8192ce when used with the RTL8188CE device would start at about
+20 Mbps on a 54 Mbps connection, but quickly drop to 1 Mbps. One of the
+symptoms is that the AP would need to retransmit each packet 4 of 5 times
+before the driver would acknowledge it. Recovery is possible only by
+unloading and reloading the driver. This problem was reported at
+https://bugzilla.redhat.com/show_bug.cgi?id=770207.
+
+The problem is due to a missing update of the gain setting.
+
+Signed-off-by: Jingjun Wu <jingjun_wu@realsil.com.cn>
+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@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+@@ -523,6 +523,10 @@ void rtl92c_dm_write_dig(struct ieee8021
+ dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
+ dm_digtable.backoff_val));
+
++ dm_digtable.cur_igvalue += 2;
++ if (dm_digtable.cur_igvalue > 0x3f)
++ dm_digtable.cur_igvalue = 0x3f;
++
+ if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+ dm_digtable.cur_igvalue);
--- /dev/null
+From 48752f6513012a1b078da08b145d5c40a644f058 Mon Sep 17 00:00:00 2001
+From: Greg Rose <gregory.v.rose@intel.com>
+Date: Wed, 8 Feb 2012 00:45:00 +0000
+Subject: rtnetlink: Fix VF IFLA policy
+
+From: Greg Rose <gregory.v.rose@intel.com>
+
+commit 48752f6513012a1b078da08b145d5c40a644f058 upstream.
+
+Add VF spoof check to IFLA policy. The original patch I submitted to
+add the spoof checking feature to rtnl failed to add the proper policy
+rule that identifies the data type and len. This patch corrects that
+oversight. No bugs have been reported against this but it may cause
+some problem for the netlink message parsing that uses the policy
+table.
+
+Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
+Tested-by: Sibai Li <sibai.li@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/core/rtnetlink.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -1071,6 +1071,8 @@ static const struct nla_policy ifla_vf_p
+ .len = sizeof(struct ifla_vf_vlan) },
+ [IFLA_VF_TX_RATE] = { .type = NLA_BINARY,
+ .len = sizeof(struct ifla_vf_tx_rate) },
++ [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY,
++ .len = sizeof(struct ifla_vf_spoofchk) },
+ };
+
+ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
--- /dev/null
+From 9b96fbacda34079dea0638ee1e92c56286f6114a Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Tue, 13 Mar 2012 13:27:23 +0100
+Subject: serial: PL011: clear pending interrupts
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+commit 9b96fbacda34079dea0638ee1e92c56286f6114a upstream.
+
+Chanho Min reported that when the boot loader transfers
+control to the kernel, there may be pending interrupts
+causing the UART to lock up in an eternal loop trying to
+pick tokens from the FIFO (since the RX interrupt flag
+indicates there are tokens) while in practice there are
+no tokens - in fact there is only a pending IRQ flag.
+
+This patch address the issue with a combination of two
+patches suggested by Russell King that clears and mask
+all interrupts at probe() and clears any pending error
+and RX interrupts at port startup time.
+
+We suspect the spurious interrupts are a side-effect of
+switching the UART from FIFO to non-FIFO mode.
+
+Cc: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
+Reported-by: Chanho Min <chanho0207@gmail.com>
+Suggested-by: Russell King <linux@arm.linux.org.uk>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Reviewed-by: Jong-Sung Kim <neidhard.kim@lge.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/amba-pl011.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -1376,6 +1376,10 @@ static int pl011_startup(struct uart_por
+
+ uap->port.uartclk = clk_get_rate(uap->clk);
+
++ /* Clear pending error and receive interrupts */
++ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
++ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
++
+ /*
+ * Allocate the IRQ
+ */
+@@ -1410,10 +1414,6 @@ static int pl011_startup(struct uart_por
+ cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
+ writew(cr, uap->port.membase + UART011_CR);
+
+- /* Clear pending error interrupts */
+- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
+- uap->port.membase + UART011_ICR);
+-
+ /*
+ * initialise the old status of the modem signals
+ */
+@@ -1428,6 +1428,9 @@ static int pl011_startup(struct uart_por
+ * as well.
+ */
+ spin_lock_irq(&uap->port.lock);
++ /* Clear out any spuriously appearing RX interrupts */
++ writew(UART011_RTIS | UART011_RXIS,
++ uap->port.membase + UART011_ICR);
+ uap->im = UART011_RTIM;
+ if (!pl011_dma_rx_running(uap))
+ uap->im |= UART011_RXIM;
+@@ -1904,6 +1907,10 @@ static int pl011_probe(struct amba_devic
+ goto unmap;
+ }
+
++ /* Ensure interrupts from this UART are masked and cleared */
++ writew(0, uap->port.membase + UART011_IMSC);
++ writew(0xffff, uap->port.membase + UART011_ICR);
++
+ uap->vendor = vendor;
+ uap->lcrh_rx = vendor->lcrh_rx;
+ uap->lcrh_tx = vendor->lcrh_tx;
cdc-wdm-don-t-clear-wdm_read-unless-entire-read-buffer-is-emptied.patch
usb-fsl_udc_core-fix-scheduling-while-atomic-dump-message.patch
usb-fix-build-error-due-to-dma_mask-is-not-at-pdev_archdata-at-arm.patch
+usb-qcserial-add-several-new-serial-devices.patch
+usb-qcserial-don-t-grab-qmi-port-on-gobi-1000-devices.patch
+usb-serial-add-support-for-the-sealevel-sealink-8-2038-rohs-device.patch
+usb-cp210x-update-to-support-cp2105-and-multiple-interface-devices.patch
+usb-serial-mos7840-fixed-mcs7820-device-attach-problem.patch
+rt2x00-add-support-for-d-link-dwa-127-to-rt2800usb.patch
+rtlwifi-handle-previous-allocation-failures-when-freeing-device-memory.patch
+rtlwifi-rtl8192c-prevent-sleeping-from-invalid-context-in-rtl8192cu.patch
+rtlwifi-rtl8192ce-fix-loss-of-receive-performance.patch
+serial-pl011-clear-pending-interrupts.patch
+math-introduce-div64_long.patch
+ntp-fix-integer-overflow-when-setting-time.patch
+uevent-send-events-in-correct-order-according-to-seqnum-v3.patch
+genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch
+genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch
+rtc-disable-the-alarm-in-the-hardware-v2.patch
+p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch
+rtnetlink-fix-vf-ifla-policy.patch
+ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch
+x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch
+mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch
--- /dev/null
+From 7b60a18da393ed70db043a777fd9e6d5363077c4 Mon Sep 17 00:00:00 2001
+From: Andrew Vagin <avagin@openvz.org>
+Date: Wed, 7 Mar 2012 14:49:56 +0400
+Subject: uevent: send events in correct order according to seqnum (v3)
+
+From: Andrew Vagin <avagin@openvz.org>
+
+commit 7b60a18da393ed70db043a777fd9e6d5363077c4 upstream.
+
+The queue handling in the udev daemon assumes that the events are
+ordered.
+
+Before this patch uevent_seqnum is incremented under sequence_lock,
+than an event is send uner uevent_sock_mutex. I want to say that code
+contained a window between incrementing seqnum and sending an event.
+
+This patch locks uevent_sock_mutex before incrementing uevent_seqnum.
+
+v2: delete sequence_lock, uevent_seqnum is protected by uevent_sock_mutex
+v3: unlock the mutex before the goto exit
+
+Thanks for Kay for the comments.
+
+Signed-off-by: Andrew Vagin <avagin@openvz.org>
+Tested-By: Kay Sievers <kay.sievers@vrfy.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/kobject_uevent.c | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -29,16 +29,17 @@
+
+ u64 uevent_seqnum;
+ char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
+-static DEFINE_SPINLOCK(sequence_lock);
+ #ifdef CONFIG_NET
+ struct uevent_sock {
+ struct list_head list;
+ struct sock *sk;
+ };
+ static LIST_HEAD(uevent_sock_list);
+-static DEFINE_MUTEX(uevent_sock_mutex);
+ #endif
+
++/* This lock protects uevent_seqnum and uevent_sock_list */
++static DEFINE_MUTEX(uevent_sock_mutex);
++
+ /* the strings here must match the enum in include/linux/kobject.h */
+ static const char *kobject_actions[] = {
+ [KOBJ_ADD] = "add",
+@@ -136,7 +137,6 @@ int kobject_uevent_env(struct kobject *k
+ struct kobject *top_kobj;
+ struct kset *kset;
+ const struct kset_uevent_ops *uevent_ops;
+- u64 seq;
+ int i = 0;
+ int retval = 0;
+ #ifdef CONFIG_NET
+@@ -243,17 +243,16 @@ int kobject_uevent_env(struct kobject *k
+ else if (action == KOBJ_REMOVE)
+ kobj->state_remove_uevent_sent = 1;
+
++ mutex_lock(&uevent_sock_mutex);
+ /* we will send an event, so request a new sequence number */
+- spin_lock(&sequence_lock);
+- seq = ++uevent_seqnum;
+- spin_unlock(&sequence_lock);
+- retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
+- if (retval)
++ retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
++ if (retval) {
++ mutex_unlock(&uevent_sock_mutex);
+ goto exit;
++ }
+
+ #if defined(CONFIG_NET)
+ /* send netlink message */
+- mutex_lock(&uevent_sock_mutex);
+ list_for_each_entry(ue_sk, &uevent_sock_list, list) {
+ struct sock *uevent_sock = ue_sk->sk;
+ struct sk_buff *skb;
+@@ -287,8 +286,8 @@ int kobject_uevent_env(struct kobject *k
+ } else
+ retval = -ENOMEM;
+ }
+- mutex_unlock(&uevent_sock_mutex);
+ #endif
++ mutex_unlock(&uevent_sock_mutex);
+
+ /* call uevent_helper, usually only enabled during early boot */
+ if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
--- /dev/null
+From a5360a53a7ccad5ed9ccef210b94fef13c6e5529 Mon Sep 17 00:00:00 2001
+From: Preston Fick <preston.fick@silabs.com>
+Date: Fri, 24 Feb 2012 13:42:39 -0600
+Subject: usb: cp210x: Update to support CP2105 and multiple interface devices
+
+From: Preston Fick <preston.fick@silabs.com>
+
+commit a5360a53a7ccad5ed9ccef210b94fef13c6e5529 upstream.
+
+This patch updates the cp210x driver to support CP210x multiple
+interface devices devices from Silicon Labs. The existing driver
+always sends control requests to interface 0, which is hardcoded in
+the usb_control_msg function calls. This only allows for single
+interface devices to be used, and causes a bug when using ports on an
+interface other than 0 in the multiple interface devices.
+
+Here are the changes included in this patch:
+- Updated the device list to contain the Silicon Labs factory default
+ VID/PID for multiple interface CP210x devices
+- Created a cp210x_port_private struct created for each port on
+ startup, this struct holds the interface number
+- Added a cp210x_release function to clean up the cp210x_port_private
+ memory created on startup
+- Modified usb_get_config and usb_set_config to get a pointer to the
+ cp210x_port_private struct, and use the interface number there in the
+ usb_control_message wIndex param
+
+Signed-off-by: Preston Fick <preston.fick@silabs.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/cp210x.c | 44 +++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 41 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct u
+ unsigned int, unsigned int);
+ static void cp210x_break_ctl(struct tty_struct *, int);
+ static int cp210x_startup(struct usb_serial *);
++static void cp210x_release(struct usb_serial *);
+ static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
+
+ static int debug;
+@@ -121,6 +122,8 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
++ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
++ { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
+ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
+ { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
+@@ -149,6 +152,10 @@ static const struct usb_device_id id_tab
+
+ MODULE_DEVICE_TABLE(usb, id_table);
+
++struct cp210x_port_private {
++ __u8 bInterfaceNumber;
++};
++
+ static struct usb_driver cp210x_driver = {
+ .name = "cp210x",
+ .probe = usb_serial_probe,
+@@ -174,6 +181,7 @@ static struct usb_serial_driver cp210x_d
+ .tiocmget = cp210x_tiocmget,
+ .tiocmset = cp210x_tiocmset,
+ .attach = cp210x_startup,
++ .release = cp210x_release,
+ .dtr_rts = cp210x_dtr_rts
+ };
+
+@@ -261,6 +269,7 @@ static int cp210x_get_config(struct usb_
+ unsigned int *data, int size)
+ {
+ struct usb_serial *serial = port->serial;
++ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ __le32 *buf;
+ int result, i, length;
+
+@@ -276,7 +285,7 @@ static int cp210x_get_config(struct usb_
+ /* Issue the request, attempting to read 'size' bytes */
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ request, REQTYPE_DEVICE_TO_HOST, 0x0000,
+- 0, buf, size, 300);
++ port_priv->bInterfaceNumber, buf, size, 300);
+
+ /* Convert data into an array of integers */
+ for (i = 0; i < length; i++)
+@@ -304,6 +313,7 @@ static int cp210x_set_config(struct usb_
+ unsigned int *data, int size)
+ {
+ struct usb_serial *serial = port->serial;
++ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ __le32 *buf;
+ int result, i, length;
+
+@@ -325,12 +335,12 @@ static int cp210x_set_config(struct usb_
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, 0x0000,
+- 0, buf, size, 300);
++ port_priv->bInterfaceNumber, buf, size, 300);
+ } else {
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, data[0],
+- 0, NULL, 0, 300);
++ port_priv->bInterfaceNumber, NULL, 0, 300);
+ }
+
+ kfree(buf);
+@@ -830,11 +840,39 @@ static void cp210x_break_ctl (struct tty
+
+ static int cp210x_startup(struct usb_serial *serial)
+ {
++ struct cp210x_port_private *port_priv;
++ int i;
++
+ /* cp210x buffers behave strangely unless device is reset */
+ usb_reset_device(serial->dev);
++
++ for (i = 0; i < serial->num_ports; i++) {
++ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
++ if (!port_priv)
++ return -ENOMEM;
++
++ memset(port_priv, 0x00, sizeof(*port_priv));
++ port_priv->bInterfaceNumber =
++ serial->interface->cur_altsetting->desc.bInterfaceNumber;
++
++ usb_set_serial_port_data(serial->port[i], port_priv);
++ }
++
+ return 0;
+ }
+
++static void cp210x_release(struct usb_serial *serial)
++{
++ struct cp210x_port_private *port_priv;
++ int i;
++
++ for (i = 0; i < serial->num_ports; i++) {
++ port_priv = usb_get_serial_port_data(serial->port[i]);
++ kfree(port_priv);
++ usb_set_serial_port_data(serial->port[i], NULL);
++ }
++}
++
+ static int __init cp210x_init(void)
+ {
+ int retval;
--- /dev/null
+From 2db4d87070e87d198ab630e66a898b45eff316d9 Mon Sep 17 00:00:00 2001
+From: Thomas Tuttle <ttuttle@chromium.org>
+Date: Wed, 1 Feb 2012 16:07:17 -0500
+Subject: USB: qcserial: add several new serial devices
+
+From: Thomas Tuttle <ttuttle@chromium.org>
+
+commit 2db4d87070e87d198ab630e66a898b45eff316d9 upstream.
+
+Signed-off-by: Thomas Tuttle <ttuttle@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/qcserial.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -35,6 +35,11 @@ static const struct usb_device_id id_tab
+ {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
+ {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
++ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi QDL device */
++ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi QDL device */
++ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi QDL device */
++ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi QDL device */
++ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+ {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+ {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+@@ -85,7 +90,16 @@ static const struct usb_device_id id_tab
+ {USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
+ {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
+ {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
++
++ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
++ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
++ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
++ {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
++ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
++ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
+ {USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
++ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
++ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, id_table);
--- /dev/null
+From c192c8e71a2ded01170c1a992cd21aaedc822756 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dcbw@redhat.com>
+Date: Fri, 24 Feb 2012 13:08:43 -0600
+Subject: USB: qcserial: don't grab QMI port on Gobi 1000 devices
+
+From: Dan Williams <dcbw@redhat.com>
+
+commit c192c8e71a2ded01170c1a992cd21aaedc822756 upstream.
+
+Gobi 1000 devices have a different port layout, which wasn't respected
+by the current driver, and thus it grabbed the QMI/net port. In the
+near future we'll be attaching another driver to the QMI/net port for
+these devices (cdc-wdm and qmi_wwan) so make sure the qcserial driver
+doesn't claim them. This patch also prevents qcserial from binding to
+interfaces 0 and 1 on 1K devices because those interfaces do not
+respond.
+
+Signed-off-by: Dan Williams <dcbw@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/qcserial.c | 105 ++++++++++++++++++++++++------------------
+ 1 file changed, 62 insertions(+), 43 deletions(-)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -23,39 +23,44 @@
+
+ static int debug;
+
++#define DEVICE_G1K(v, p) \
++ USB_DEVICE(v, p), .driver_info = 1
++
+ static const struct usb_device_id id_table[] = {
+- {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
+- {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+- {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
+- {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
+- {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
+- {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
+- {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
+- {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
+- {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+- {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
+- {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+- {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi QDL device */
+- {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi QDL device */
+- {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi QDL device */
+- {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi QDL device */
+- {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi QDL device */
+- {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+- {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+- {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+- {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
+- {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
+- {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
+- {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
+- {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
+- {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
+- {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
+- {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
+- {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
+- {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
+- {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
+- {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
+- {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
++ /* Gobi 1000 devices */
++ {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
++ {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
++ {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
++ {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
++ {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
++ {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
++ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */
++ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */
++ {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
++ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
++ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
++ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
++ {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
++ {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
++ {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
++ {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
++ {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
++ {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
++ {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
++ {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
++ {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
++ {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
++ {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
++ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
++ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
++ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
++
++ /* Gobi 2000 devices */
++ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
++ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */
++ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */
++ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */
++ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */
+ {USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
+ {USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */
+@@ -91,6 +96,8 @@ static const struct usb_device_id id_tab
+ {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
+ {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+
++ /* Gobi 3000 devices */
++ {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
+ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
+@@ -121,8 +128,10 @@ static int qcprobe(struct usb_serial *se
+ int retval = -ENODEV;
+ __u8 nintf;
+ __u8 ifnum;
++ bool is_gobi1k = id->driver_info ? true : false;
+
+ dbg("%s", __func__);
++ dbg("Is Gobi 1000 = %d", is_gobi1k);
+
+ nintf = serial->dev->actconfig->desc.bNumInterfaces;
+ dbg("Num Interfaces = %d", nintf);
+@@ -170,15 +179,25 @@ static int qcprobe(struct usb_serial *se
+
+ case 3:
+ case 4:
+- /* Composite mode */
+- /* ifnum == 0 is a broadband network adapter */
+- if (ifnum == 1) {
+- /*
+- * Diagnostics Monitor (serial line 9600 8N1)
+- * Qualcomm DM protocol
+- * use "libqcdm" (ModemManager) for communication
+- */
+- dbg("Diagnostics Monitor found");
++ /* Composite mode; don't bind to the QMI/net interface as that
++ * gets handled by other drivers.
++ */
++
++ /* Gobi 1K USB layout:
++ * 0: serial port (doesn't respond)
++ * 1: serial port (doesn't respond)
++ * 2: AT-capable modem port
++ * 3: QMI/net
++ *
++ * Gobi 2K+ USB layout:
++ * 0: QMI/net
++ * 1: DM/DIAG (use libqcdm from ModemManager for communication)
++ * 2: AT-capable modem port
++ * 3: NMEA
++ */
++
++ if (ifnum == 1 && !is_gobi1k) {
++ dbg("Gobi 2K+ DM/DIAG interface found");
+ retval = usb_set_interface(serial->dev, ifnum, 0);
+ if (retval < 0) {
+ dev_err(&serial->dev->dev,
+@@ -197,13 +216,13 @@ static int qcprobe(struct usb_serial *se
+ retval = -ENODEV;
+ kfree(data);
+ }
+- } else if (ifnum==3) {
++ } else if (ifnum==3 && !is_gobi1k) {
+ /*
+ * NMEA (serial line 9600 8N1)
+ * # echo "\$GPS_START" > /dev/ttyUSBx
+ * # echo "\$GPS_STOP" > /dev/ttyUSBx
+ */
+- dbg("NMEA GPS interface found");
++ dbg("Gobi 2K+ NMEA GPS interface found");
+ retval = usb_set_interface(serial->dev, ifnum, 0);
+ if (retval < 0) {
+ dev_err(&serial->dev->dev,
--- /dev/null
+From 6d161b99f875269ad4ffa44375e1e54bca6fd02e Mon Sep 17 00:00:00 2001
+From: Scott Dial <scott.dial@scientiallc.com>
+Date: Fri, 24 Feb 2012 19:04:09 -0500
+Subject: usb-serial: Add support for the Sealevel SeaLINK+8 2038-ROHS device
+
+From: Scott Dial <scott.dial@scientiallc.com>
+
+commit 6d161b99f875269ad4ffa44375e1e54bca6fd02e upstream.
+
+This patch adds new device IDs to the ftdi_sio module to support
+the new Sealevel SeaLINK+8 2038-ROHS device.
+
+Signed-off-by: Scott Dial <scott.dial@scientiallc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 4 ++++
+ drivers/usb/serial/ftdi_sio_ids.h | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -536,6 +536,10 @@ static struct usb_device_id id_table_com
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
+ { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
+ { USB_DEVICE(OCT_VID, OCT_US101_PID) },
+ { USB_DEVICE(OCT_VID, OCT_DK201_PID) },
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -689,6 +689,10 @@
+ #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
+ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
+ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
++#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */
++#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */
++#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */
++#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */
+
+ /*
+ * JETI SPECTROMETER SPECBOS 1201
--- /dev/null
+From 093ea2d3a766cb8a4c4de57efec6c0a127a58792 Mon Sep 17 00:00:00 2001
+From: Donald Lee <donald@asix.com.tw>
+Date: Wed, 14 Mar 2012 15:26:33 +0800
+Subject: USB: serial: mos7840: Fixed MCS7820 device attach problem
+
+From: Donald Lee <donald@asix.com.tw>
+
+commit 093ea2d3a766cb8a4c4de57efec6c0a127a58792 upstream.
+
+A MCS7820 device supports two serial ports and a MCS7840 device supports
+four serial ports. Both devices use the same driver, but the attach function
+in driver was unable to correctly handle the port numbers for MCS7820
+device. This problem has been fixed in this patch and this fix has been
+verified on x86 Linux kernel 3.2.9 with both MCS7820 and MCS7840 devices.
+
+Signed-off-by: Donald Lee <donald@asix.com.tw>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/mos7840.c | 81 +++++++++++++++++++++++++++++--------------
+ 1 file changed, 56 insertions(+), 25 deletions(-)
+
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -174,6 +174,7 @@
+
+ #define CLK_MULTI_REGISTER ((__u16)(0x02))
+ #define CLK_START_VALUE_REGISTER ((__u16)(0x03))
++#define GPIO_REGISTER ((__u16)(0x07))
+
+ #define SERIAL_LCR_DLAB ((__u16)(0x0080))
+
+@@ -1103,14 +1104,25 @@ static int mos7840_open(struct tty_struc
+ mos7840_port->read_urb = port->read_urb;
+
+ /* set up our bulk in urb */
+-
+- usb_fill_bulk_urb(mos7840_port->read_urb,
+- serial->dev,
+- usb_rcvbulkpipe(serial->dev,
+- port->bulk_in_endpointAddress),
+- port->bulk_in_buffer,
+- mos7840_port->read_urb->transfer_buffer_length,
+- mos7840_bulk_in_callback, mos7840_port);
++ if ((serial->num_ports == 2)
++ && ((((__u16)port->number -
++ (__u16)(port->serial->minor)) % 2) != 0)) {
++ usb_fill_bulk_urb(mos7840_port->read_urb,
++ serial->dev,
++ usb_rcvbulkpipe(serial->dev,
++ (port->bulk_in_endpointAddress) + 2),
++ port->bulk_in_buffer,
++ mos7840_port->read_urb->transfer_buffer_length,
++ mos7840_bulk_in_callback, mos7840_port);
++ } else {
++ usb_fill_bulk_urb(mos7840_port->read_urb,
++ serial->dev,
++ usb_rcvbulkpipe(serial->dev,
++ port->bulk_in_endpointAddress),
++ port->bulk_in_buffer,
++ mos7840_port->read_urb->transfer_buffer_length,
++ mos7840_bulk_in_callback, mos7840_port);
++ }
+
+ dbg("mos7840_open: bulkin endpoint is %d",
+ port->bulk_in_endpointAddress);
+@@ -1521,13 +1533,25 @@ static int mos7840_write(struct tty_stru
+ memcpy(urb->transfer_buffer, current_position, transfer_size);
+
+ /* fill urb with data and submit */
+- usb_fill_bulk_urb(urb,
+- serial->dev,
+- usb_sndbulkpipe(serial->dev,
+- port->bulk_out_endpointAddress),
+- urb->transfer_buffer,
+- transfer_size,
+- mos7840_bulk_out_data_callback, mos7840_port);
++ if ((serial->num_ports == 2)
++ && ((((__u16)port->number -
++ (__u16)(port->serial->minor)) % 2) != 0)) {
++ usb_fill_bulk_urb(urb,
++ serial->dev,
++ usb_sndbulkpipe(serial->dev,
++ (port->bulk_out_endpointAddress) + 2),
++ urb->transfer_buffer,
++ transfer_size,
++ mos7840_bulk_out_data_callback, mos7840_port);
++ } else {
++ usb_fill_bulk_urb(urb,
++ serial->dev,
++ usb_sndbulkpipe(serial->dev,
++ port->bulk_out_endpointAddress),
++ urb->transfer_buffer,
++ transfer_size,
++ mos7840_bulk_out_data_callback, mos7840_port);
++ }
+
+ data1 = urb->transfer_buffer;
+ dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
+@@ -1840,7 +1864,7 @@ static int mos7840_send_cmd_write_baud_r
+
+ } else {
+ #ifdef HW_flow_control
+- / *setting h/w flow control bit to 0 */
++ /* setting h/w flow control bit to 0 */
+ Data = 0xb;
+ mos7840_port->shadowMCR = Data;
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+@@ -2310,19 +2334,26 @@ static int mos7840_ioctl(struct tty_stru
+
+ static int mos7840_calc_num_ports(struct usb_serial *serial)
+ {
+- int mos7840_num_ports = 0;
++ __u16 Data = 0x00;
++ int ret = 0;
++ int mos7840_num_ports;
+
+- dbg("numberofendpoints: cur %d, alt %d",
+- (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
+- (int)serial->interface->altsetting->desc.bNumEndpoints);
+- if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
+- mos7840_num_ports = serial->num_ports = 2;
+- } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
++ ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
++ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
++
++ if ((Data & 0x01) == 0) {
++ mos7840_num_ports = 2;
++ serial->num_bulk_in = 2;
++ serial->num_bulk_out = 2;
++ serial->num_ports = 2;
++ } else {
++ mos7840_num_ports = 4;
+ serial->num_bulk_in = 4;
+ serial->num_bulk_out = 4;
+- mos7840_num_ports = serial->num_ports = 4;
++ serial->num_ports = 4;
+ }
+- dbg ("mos7840_num_ports = %d", mos7840_num_ports);
++
+ return mos7840_num_ports;
+ }
+
--- /dev/null
+From 73d63d038ee9f769f5e5b46792d227fe20e442c5 Mon Sep 17 00:00:00 2001
+From: Suresh Siddha <suresh.b.siddha@intel.com>
+Date: Mon, 12 Mar 2012 11:36:33 -0700
+Subject: x86/ioapic: Add register level checks to detect bogus io-apic entries
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Suresh Siddha <suresh.b.siddha@intel.com>
+
+commit 73d63d038ee9f769f5e5b46792d227fe20e442c5 upstream.
+
+With the recent changes to clear_IO_APIC_pin() which tries to
+clear remoteIRR bit explicitly, some of the users started to see
+"Unable to reset IRR for apic .." messages.
+
+Close look shows that these are related to bogus IO-APIC entries
+which return's all 1's for their io-apic registers. And the
+above mentioned error messages are benign. But kernel should
+have ignored such io-apic's in the first place.
+
+Check if register 0, 1, 2 of the listed io-apic are all 1's and
+ignore such io-apic.
+
+Reported-by: Álvaro Castillo <midgoon@gmail.com>
+Tested-by: Jon Dufresne <jon@jondufresne.org>
+Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
+Cc: yinghai@kernel.org
+Cc: kernel-team@fedoraproject.org
+Cc: Josh Boyer <jwboyer@redhat.com>
+Link: http://lkml.kernel.org/r/1331577393.31585.94.camel@sbsiddha-desk.sc.intel.com
+[ Performed minor cleanup of affected code. ]
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/apic/io_apic.c | 40 ++++++++++++++++++++++++++++++++--------
+ 1 file changed, 32 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/kernel/apic/io_apic.c
++++ b/arch/x86/kernel/apic/io_apic.c
+@@ -3927,18 +3927,36 @@ int mp_find_ioapic_pin(int ioapic, u32 g
+ static __init int bad_ioapic(unsigned long address)
+ {
+ if (nr_ioapics >= MAX_IO_APICS) {
+- printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded "
+- "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
++ pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
++ MAX_IO_APICS, nr_ioapics);
+ return 1;
+ }
+ if (!address) {
+- printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address"
+- " found in table, skipping!\n");
++ pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n");
+ return 1;
+ }
+ return 0;
+ }
+
++static __init int bad_ioapic_register(int idx)
++{
++ union IO_APIC_reg_00 reg_00;
++ union IO_APIC_reg_01 reg_01;
++ union IO_APIC_reg_02 reg_02;
++
++ reg_00.raw = io_apic_read(idx, 0);
++ reg_01.raw = io_apic_read(idx, 1);
++ reg_02.raw = io_apic_read(idx, 2);
++
++ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) {
++ pr_warn("I/O APIC 0x%x registers return all ones, skipping!\n",
++ mpc_ioapic_addr(idx));
++ return 1;
++ }
++
++ return 0;
++}
++
+ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+ {
+ int idx = 0;
+@@ -3955,6 +3973,12 @@ void __init mp_register_ioapic(int id, u
+ ioapics[idx].mp_config.apicaddr = address;
+
+ set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++
++ if (bad_ioapic_register(idx)) {
++ clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
++ return;
++ }
++
+ ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
+ ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
+
+@@ -3975,10 +3999,10 @@ void __init mp_register_ioapic(int id, u
+ if (gsi_cfg->gsi_end >= gsi_top)
+ gsi_top = gsi_cfg->gsi_end + 1;
+
+- printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+- "GSI %d-%d\n", idx, mpc_ioapic_id(idx),
+- mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
+- gsi_cfg->gsi_base, gsi_cfg->gsi_end);
++ pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n",
++ idx, mpc_ioapic_id(idx),
++ mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
++ gsi_cfg->gsi_base, gsi_cfg->gsi_end);
+
+ nr_ioapics++;
+ }