[kernel/f16] af_netlink: force credentials passing [CVE-2012-3520]
Justin M. Forbes
jforbes at fedoraproject.org
Thu Aug 23 17:17:00 UTC 2012
commit e0bf103272d5ce120abb56f97a237c11a1412547
Author: Justin M. Forbes <jforbes at redhat.com>
Date: Thu Aug 23 12:15:02 2012 -0500
af_netlink: force credentials passing [CVE-2012-3520]
af_netlink-credentials-cve-2012-3520.patch | 114 ++
kernel.spec | 16 +-
linux-3.4.10-queue.patch | 2464 ++++++++++++++++++++++++++++
3 files changed, 2593 insertions(+), 1 deletions(-)
---
diff --git a/af_netlink-credentials-cve-2012-3520.patch b/af_netlink-credentials-cve-2012-3520.patch
new file mode 100644
index 0000000..c324a4a
--- /dev/null
+++ b/af_netlink-credentials-cve-2012-3520.patch
@@ -0,0 +1,114 @@
+Subject: [PATCH] af_netlink: force credentials passing [CVE-2012-3520]
+From: Eric Dumazet <eric.dumazet at gmail.com>
+To: David Miller <davem at davemloft.net>
+Cc: netdev <netdev at vger.kernel.org>, Petr Matousek <pmatouse at redhat.com>,
+ Florian Weimer <fweimer at redhat.com>,
+ Pablo Neira Ayuso <pablo at netfilter.org>
+Content-Type: text/plain; charset="UTF-8"
+Date: Tue, 21 Aug 2012 18:21:17 +0200
+Message-ID: <1345566077.5158.530.camel at edumazet-glaptop>
+Mime-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Sender: netdev-owner at vger.kernel.org
+Precedence: bulk
+List-ID: <netdev.vger.kernel.org>
+X-Mailing-List: netdev at vger.kernel.org
+X-RedHat-Spam-Score: -6.999 (BAYES_00,DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID)
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22
+X-Scanned-By: MIMEDefang 2.68 on 10.5.110.16
+Status: RO
+Content-Length: 3042
+Lines: 91
+
+From: Eric Dumazet <edumazet at google.com>
+
+Pablo Neira Ayuso discovered that avahi and
+potentially NetworkManager accept spoofed Netlink messages because of a
+kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data
+to the receiver if the sender did not provide such data, instead of not
+including any such data at all or including the correct data from the
+peer (as it is the case with AF_UNIX).
+
+This bug was introduced in commit 16e572626961
+(af_unix: dont send SCM_CREDENTIALS by default)
+
+This patch forces passing credentials for netlink, as
+before the regression.
+
+Another fix would be to not add SCM_CREDENTIALS in
+netlink messages if not provided by the sender, but it
+might break some programs.
+
+With help from Florian Weimer & Petr Matousek
+
+This issue is designated as CVE-2012-3520
+
+Signed-off-by: Eric Dumazet <edumazet at google.com>
+Cc: Petr Matousek <pmatouse at redhat.com>
+Cc: Florian Weimer <fweimer at redhat.com>
+Cc: Pablo Neira Ayuso <pablo at netfilter.org>
+---
+ include/net/scm.h | 4 +++-
+ net/netlink/af_netlink.c | 2 +-
+ net/unix/af_unix.c | 4 ++--
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/scm.h b/include/net/scm.h
+index 079d788..7dc0854 100644
+--- a/include/net/scm.h
++++ b/include/net/scm.h
+@@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
+ }
+
+ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
+- struct scm_cookie *scm)
++ struct scm_cookie *scm, bool forcecreds)
+ {
+ memset(scm, 0, sizeof(*scm));
++ if (forcecreds)
++ scm_set_cred(scm, task_tgid(current), current_cred());
+ unix_get_peersec_dgram(sock, scm);
+ if (msg->msg_controllen <= 0)
+ return 0;
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 5463969..1445d73 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ if (NULL == siocb->scm)
+ siocb->scm = &scm;
+
+- err = scm_send(sock, msg, siocb->scm);
++ err = scm_send(sock, msg, siocb->scm, true);
+ if (err < 0)
+ return err;
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index e4768c1..c5ee4ff 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ if (NULL == siocb->scm)
+ siocb->scm = &tmp_scm;
+ wait_for_unix_gc();
+- err = scm_send(sock, msg, siocb->scm);
++ err = scm_send(sock, msg, siocb->scm, false);
+ if (err < 0)
+ return err;
+
+@@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ if (NULL == siocb->scm)
+ siocb->scm = &tmp_scm;
+ wait_for_unix_gc();
+- err = scm_send(sock, msg, siocb->scm);
++ err = scm_send(sock, msg, siocb->scm, false);
+ if (err < 0)
+ return err;
+
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe netdev" in
+the body of a message to majordomo at vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/kernel.spec b/kernel.spec
index d891486..f84d837 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -54,7 +54,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
-%global baserelease 1
+%global baserelease 2
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@@ -718,6 +718,11 @@ Patch22070: net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch
Patch22071: sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch
Patch22072: tcp-Apply-device-TSO-segment-limit-earlier.patch
+Patch22075: af_netlink-credentials-cve-2012-3520.patch
+
+#Patches from the 3.4.10 stable queue
+Patch22100: linux-3.4.10-queue.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -1341,6 +1346,11 @@ ApplyPatch net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch
ApplyPatch sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch
ApplyPatch tcp-Apply-device-TSO-segment-limit-earlier.patch
+ApplyPatch af_netlink-credentials-cve-2012-3520.patch
+
+#Patches from the 3.4.10 stable queue
+ApplyPatch linux-3.4.10-queue.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2039,6 +2049,10 @@ fi
# and build.
%changelog
+* Thu Aug 23 2012 Justin M. Forbes <jforbes at redhat.com> 3.4.9-2
+- af_netlink: force credentials passing [CVE-2012-3520]
+- Add patches from 3.4.10 queue
+
* Wed Aug 15 2012 Justin M. Forbes <jforbes at redhat.com> 3.4.9-1
- Linux 3.4.9
diff --git a/linux-3.4.10-queue.patch b/linux-3.4.10-queue.patch
new file mode 100644
index 0000000..72cfb19
--- /dev/null
+++ b/linux-3.4.10-queue.patch
@@ -0,0 +1,2464 @@
+From a2367db2ec5e7fc6fe93e221e0fcdee81b053daf Mon Sep 17 00:00:00 2001
+From: Fabio Estevam <festevam at gmail.com>
+Date: Tue, 3 Jul 2012 15:33:29 -0300
+Subject: dma: imx-dma: Fix kernel crash due to missing clock conversion
+
+From: Fabio Estevam <festevam at gmail.com>
+
+commit a2367db2ec5e7fc6fe93e221e0fcdee81b053daf upstream.
+
+With the new i.MX clock infrastructure we need to request the dma clocks
+seperately: ahb and ipg clocks.
+
+This fixes the following kernel crash and make audio to be functional again:
+
+root at freescale /home$ aplay audio48k16S.wav
+Playing WAVE 'audio48k16S.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
+Unable to handle kernel NULL pointer dereference at virtual address 00000000
+pgd = c7b74000
+[00000000] *pgd=a7bb5831, *pte=00000000, *ppte=00000000
+Internal error: Oops: 17 [#1] PREEMPT ARM
+Modules linked in:
+CPU: 0 Not tainted (3.5.0-rc5-next-20120702-00007-g3028b64 #1128)
+PC is at snd_dmaengine_pcm_get_chan+0x8/0x10
+LR is at snd_imx_pcm_hw_params+0x18/0xdc
+pc : [<c02d3cf8>] lr : [<c02e95ec>] psr: a0000013
+sp : c7b45e30 ip : ffffffff fp : c7ae58e0
+r10: 00000000 r9 : c7ae981c r8 : c7b88800
+r7 : c7ae5a60 r6 : c7ae5b20 r5 : c7ae9810 r4 : c7afa060
+r3 : 00000000 r2 : 00000001 r1 : c7b88800 r0 : c7afa060
+Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
+Control: 0005317f Table: a7b74000 DAC: 00000015
+Process aplay (pid: 701, stack limit = 0xc7b44270)
+Stack: (0xc7b45e30 to 0xc7b46000)
+5e20: 00100000 00000029 c7b88800 c02db870
+5e40: c7ae5a60 c02d4594 00000010 01ae5a60 c7ae5a60 c7ae9810 c7ae9810 c7afa060
+5e60: c7ae5b20 c7ae5a60 c7b88800 c02e3ef0 c02e3e08 c7b1e400 c7afa060 c7b88800
+5e80: 00000000 c0014da8 c7b44000 00000000 bec566ac c02cd400 c7afa060 c7afa060
+5ea0: bec56800 c7b88800 c0014da8 c02cdd7c c04ee710 c04ee7b8 00000003 c005fc74
+5ec0: 00000000 7fffffff c7b45f00 c7afa060 c7b67420 c7ba3070 00000004 c0014da8
+5ee0: c7b44000 00000000 bec566ac c02ced88 c04e95f8 b6f5ab04 c7b45fb0 0145a468
+5f00: 0145a600 bec566bc bec56800 c7b67420 c7ba3070 c00d499c c7b45f18 c7b45f18
+5f20: 0000001a 00000004 00000001 c7b44000 c0527f40 00000009 00000008 00000000
+5f40: c7b44000 c002c9ec 00000001 c04f0ab0 c04ebec0 00000101 00000000 0000000a
+5f60: 60000093 c7b67420 bec56800 c25c4111 00000004 c0014da8 c7b44000 00000000
+5f80: bec566ac c00d4f38 b6ffb658 00000000 c0522d80 0145a468 b6fd5000 0145a418
+5fa0: 00000036 c0014c00 0145a468 b6fd5000 00000004 c25c4111 bec56800 00020001
+5fc0: 0145a468 b6fd5000 0145a418 00000036 0145a468 0145a600 bec566bc bec566ac
+5fe0: 0145a468 bec56388 b6f65ce4 b6dcebec 20000010 00000004 00000000 00000000
+[<c02d3cf8>] (snd_dmaengine_pcm_get_chan+0x8/0x10) from [<c02e95ec>] (snd_imx_pcm_hw_params+0x18/0xdc)
+[<c02e95ec>] (snd_imx_pcm_hw_params+0x18/0xdc) from [<c02e3ef0>] (soc_pcm_hw_params+0xe8/0x1f0)
+[<c02e3ef0>] (soc_pcm_hw_params+0xe8/0x1f0) from [<c02cd400>] (snd_pcm_hw_params+0x124/0x474)
+[<c02cd400>] (snd_pcm_hw_params+0x124/0x474) from [<c02cdd7c>] (snd_pcm_common_ioctl1+0x4b4/0xf74)
+[<c02cdd7c>] (snd_pcm_common_ioctl1+0x4b4/0xf74) from [<c02ced88>] (snd_pcm_playback_ioctl1+0x30/0x510)
+[<c02ced88>] (snd_pcm_playback_ioctl1+0x30/0x510) from [<c00d499c>] (do_vfs_ioctl+0x80/0x5e4)
+[<c00d499c>] (do_vfs_ioctl+0x80/0x5e4) from [<c00d4f38>] (sys_ioctl+0x38/0x60)
+[<c00d4f38>] (sys_ioctl+0x38/0x60) from [<c0014c00>] (ret_fast_syscall+0x0/0x2c)
+Code: e593000c e12fff1e e59030a0 e59330bc (e5930000)
+---[ end trace fa518c8ba3a74e97 ]--
+
+Reported-by: Javier Martin <javier.martin at vista-silicon.com>
+Signed-off-by: Fabio Estevam <fabio.estevam at freescale.com>
+Acked-by: Sascha Hauer <s.hauer at pengutronix.de>
+Signed-off-by: Vinod Koul <vinod.koul at linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/dma/imx-dma.c | 36 +++++++++++++++++++++++++-----------
+ 1 file changed, 25 insertions(+), 11 deletions(-)
+
+--- a/drivers/dma/imx-dma.c
++++ b/drivers/dma/imx-dma.c
+@@ -172,7 +172,8 @@ struct imxdma_engine {
+ struct device_dma_parameters dma_parms;
+ struct dma_device dma_device;
+ void __iomem *base;
+- struct clk *dma_clk;
++ struct clk *dma_ahb;
++ struct clk *dma_ipg;
+ spinlock_t lock;
+ struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS];
+ struct imxdma_channel channel[IMX_DMA_CHANNELS];
+@@ -976,10 +977,20 @@ static int __init imxdma_probe(struct pl
+ return 0;
+ }
+
+- imxdma->dma_clk = clk_get(NULL, "dma");
+- if (IS_ERR(imxdma->dma_clk))
+- return PTR_ERR(imxdma->dma_clk);
+- clk_enable(imxdma->dma_clk);
++ imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg");
++ if (IS_ERR(imxdma->dma_ipg)) {
++ ret = PTR_ERR(imxdma->dma_ipg);
++ goto err_clk;
++ }
++
++ imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb");
++ if (IS_ERR(imxdma->dma_ahb)) {
++ ret = PTR_ERR(imxdma->dma_ahb);
++ goto err_clk;
++ }
++
++ clk_prepare_enable(imxdma->dma_ipg);
++ clk_prepare_enable(imxdma->dma_ahb);
+
+ /* reset DMA module */
+ imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR);
+@@ -988,16 +999,14 @@ static int __init imxdma_probe(struct pl
+ ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma);
+ if (ret) {
+ dev_warn(imxdma->dev, "Can't register IRQ for DMA\n");
+- kfree(imxdma);
+- return ret;
++ goto err_enable;
+ }
+
+ ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma);
+ if (ret) {
+ dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");
+ free_irq(MX1_DMA_INT, NULL);
+- kfree(imxdma);
+- return ret;
++ goto err_enable;
+ }
+ }
+
+@@ -1094,7 +1103,10 @@ err_init:
+ free_irq(MX1_DMA_INT, NULL);
+ free_irq(MX1_DMA_ERR, NULL);
+ }
+-
++err_enable:
++ clk_disable_unprepare(imxdma->dma_ipg);
++ clk_disable_unprepare(imxdma->dma_ahb);
++err_clk:
+ kfree(imxdma);
+ return ret;
+ }
+@@ -1114,7 +1126,9 @@ static int __exit imxdma_remove(struct p
+ free_irq(MX1_DMA_ERR, NULL);
+ }
+
+- kfree(imxdma);
++ clk_disable_unprepare(imxdma->dma_ipg);
++ clk_disable_unprepare(imxdma->dma_ahb);
++ kfree(imxdma);
+
+ return 0;
+ }
+From 0d8957c8a90bbb5d34fab9a304459448a5131e06 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+Date: Tue, 7 Aug 2012 09:54:14 +0200
+Subject: drm/i915: correctly order the ring init sequence
+
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+
+commit 0d8957c8a90bbb5d34fab9a304459448a5131e06 upstream.
+
+We may only start to set up the new register values after having
+confirmed that the ring is truely off. Otherwise the hw might lose the
+newly written register values. This is caught later on in the init
+sequence, when we check whether the register writes have stuck.
+
+Reviewed-by: Jani Nikula <jani.nikula at intel.com>
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522
+Tested-by: Yang Guang <guang.a.yang at intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
+@@ -258,8 +258,6 @@ static int init_ring_common(struct intel
+ I915_WRITE_HEAD(ring, 0);
+ ring->write_tail(ring, 0);
+
+- /* Initialize the ring. */
+- I915_WRITE_START(ring, obj->gtt_offset);
+ head = I915_READ_HEAD(ring) & HEAD_ADDR;
+
+ /* G45 ring initialization fails to reset head to zero */
+@@ -285,6 +283,11 @@ static int init_ring_common(struct intel
+ }
+ }
+
++ /* Initialize the ring. This must happen _after_ we've cleared the ring
++ * registers with the above sequence (the readback of the HEAD registers
++ * also enforces ordering), otherwise the hw might lose the new ring
++ * register values. */
++ I915_WRITE_START(ring, obj->gtt_offset);
+ I915_WRITE_CTL(ring,
+ ((ring->size - PAGE_SIZE) & RING_NR_PAGES)
+ | RING_VALID);
+From 4344b813f105a19f793f1fd93ad775b784648b95 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+Date: Fri, 10 Aug 2012 11:10:20 +0200
+Subject: drm/i915: ignore eDP bpc settings from vbt
+
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+
+commit 4344b813f105a19f793f1fd93ad775b784648b95 upstream.
+
+This has originally been introduced to not oversubscribe the dp links
+in
+
+commit 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18
+Author: Zhenyu Wang <zhenyuw at linux.intel.com>
+Date: Tue Jan 12 05:38:31 2010 +0800
+
+ drm/i915: fix pixel color depth setting on eDP
+
+Since then we've fixed up the dp link bandwidth calculation code and
+should now automatically fall back to 6bpc dithering. So this is
+unnecessary.
+
+Furthermore it seems to break the new MacbookPro with retina display,
+hence let's just rip this out.
+
+Reported-by: Benoit Gschwind <gschwind at gnu-log.net>
+Cc: Benoit Gschwind <gschwind at gnu-log.net>
+Cc: Francois Rigaut <frigaut at gmail.com>
+Tested-by: Benoit Gschwind <gschwind at gnu-log.net>
+Tested-by: Bernhard Froemel <froemel at vmars tuwien.ac.at>
+Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+--
+
+Testing feedback highgly welcome, and thanks for Benoit for finding
+out that the bpc computations are busted.
+-Daniel
+
+---
+ drivers/gpu/drm/i915/intel_display.c | 11 -----------
+ 1 file changed, 11 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -4982,17 +4982,6 @@ static bool intel_choose_pipe_bpp_dither
+ continue;
+ }
+
+- if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+- /* Use VBT settings if we have an eDP panel */
+- unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+-
+- if (edp_bpc < display_bpc) {
+- DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+- display_bpc = edp_bpc;
+- }
+- continue;
+- }
+-
+ /* Not one of the known troublemakers, check the EDID */
+ list_for_each_entry(connector, &dev->mode_config.connector_list,
+ head) {
+From 2514bc510d0c3aadcc5204056bb440fa36845147 Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes at virtuousgeek.org>
+Date: Thu, 21 Jun 2012 15:13:50 -0700
+Subject: drm/i915: prefer wide & slow to fast & narrow in DP configs
+
+From: Jesse Barnes <jbarnes at virtuousgeek.org>
+
+commit 2514bc510d0c3aadcc5204056bb440fa36845147 upstream.
+
+High frequency link configurations have the potential to cause trouble
+with long and/or cheap cables, so prefer slow and wide configurations
+instead. This patch has the potential to cause trouble for eDP
+configurations that lie about available lanes, so if we run into that we
+can make it conditional on eDP.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45801
+Tested-by: peter at colberg.org
+Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
+Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Cc: Jonathan Nieder <jrnieder at gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_dp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_dp.c
++++ b/drivers/gpu/drm/i915/intel_dp.c
+@@ -712,8 +712,8 @@ intel_dp_mode_fixup(struct drm_encoder *
+
+ bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+
+- for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+- for (clock = 0; clock <= max_clock; clock++) {
++ for (clock = 0; clock <= max_clock; clock++) {
++ for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+ int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
+
+ if (intel_dp_link_required(mode->clock, bpp)
+From 35a38556d900b9cb5dfa2529c93944b847f8a8a4 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+Date: Sun, 12 Aug 2012 22:17:14 +0200
+Subject: drm/i915: reorder edp disabling to fix ivb MacBook Air
+
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+
+commit 35a38556d900b9cb5dfa2529c93944b847f8a8a4 upstream.
+
+eDP is tons of fun. It turns out that at least the new MacBook Air 5,1
+model absolutely doesn't like the new force vdd dance we've introduced
+in
+
+commit 6cb49835da0426f69a2931bc2a0a8156344b0e41
+Author: Daniel Vetter <daniel.vetter at ffwll.ch>
+Date: Sun May 20 17:14:50 2012 +0200
+
+ drm/i915: enable vdd when switching off the eDP panel
+
+But that patch also tried to fix some neat edp sequence issue with the
+force_vdd timings. Closer inspection reveals that we've raised
+force_vdd only to do the aux channel communication dp_sink_dpms. If we
+move the edp_panel_off below that, we don't need any force_vdd for the
+disable sequence, which makes the Air happy.
+
+Unfortunately the reporter of the original bug that the above commit
+fixed is travelling, so we can't test whether this regresses things.
+But my theory is that since we don't check for any power-off ->
+force_vdd-on delays in edp_panel_vdd_on, this was the actual
+root-cause of this failure. With that force_vdd dance completely
+eliminated, I'm hopeful the original bug stays fixed, too.
+
+For reference the old bug, which hopefully doesn't get broken by this:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=43163
+
+In any case, regression fixers win over plain bugfixes, so this needs
+to go in asap.
+
+v2: The crucial pieces seems to be to clear the force_vdd flag
+uncoditionally, too, in edp_panel_off. Looks like this is left behind
+by the firmware somehow.
+
+v3: The Apple firmware seems to switch off the panel on it's own, hence
+we still need to keep force_vdd on, but properly clear it when switching
+the panel off.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45671
+Tested-by: Roberto Romer <sildurin at gmail.com>
+Tested-by: Daniel Wagner <wagi at monom.org>
+Tested-by: Keith Packard <keithp at keithp.com>
+Cc: Keith Packard <keithp at keithp.com>
+Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_dp.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_dp.c
++++ b/drivers/gpu/drm/i915/intel_dp.c
+@@ -1156,10 +1156,14 @@ static void ironlake_edp_panel_off(struc
+ WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
+
+ pp = ironlake_get_pp_control(dev_priv);
+- pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
++ /* We need to switch off panel power _and_ force vdd, for otherwise some
++ * panels get very unhappy and cease to work. */
++ pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+
++ intel_dp->want_panel_vdd = false;
++
+ ironlake_wait_panel_off(intel_dp);
+ }
+
+@@ -1269,11 +1273,9 @@ static void intel_dp_prepare(struct drm_
+ * ensure that we have vdd while we switch off the panel. */
+ ironlake_edp_panel_vdd_on(intel_dp);
+ ironlake_edp_backlight_off(intel_dp);
+- ironlake_edp_panel_off(intel_dp);
+-
+ intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
++ ironlake_edp_panel_off(intel_dp);
+ intel_dp_link_down(intel_dp);
+- ironlake_edp_panel_vdd_off(intel_dp, false);
+ }
+
+ static void intel_dp_commit(struct drm_encoder *encoder)
+@@ -1308,11 +1310,9 @@ intel_dp_dpms(struct drm_encoder *encode
+ /* Switching the panel off requires vdd. */
+ ironlake_edp_panel_vdd_on(intel_dp);
+ ironlake_edp_backlight_off(intel_dp);
+- ironlake_edp_panel_off(intel_dp);
+-
+ intel_dp_sink_dpms(intel_dp, mode);
++ ironlake_edp_panel_off(intel_dp);
+ intel_dp_link_down(intel_dp);
+- ironlake_edp_panel_vdd_off(intel_dp, false);
+
+ if (is_cpu_edp(intel_dp))
+ ironlake_edp_pll_off(encoder);
+From af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 Mon Sep 17 00:00:00 2001
+From: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
+Date: Thu, 26 Jul 2012 20:53:19 +0200
+Subject: drm/nvd0/disp: mask off high 16 bit of negative cursor x-coordinate
+
+From: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
+
+commit af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 upstream.
+
+Signed-off-by: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/nvd0_display.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/nouveau/nvd0_display.c
++++ b/drivers/gpu/drm/nouveau/nvd0_display.c
+@@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *c
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ int ch = EVO_CURS(nv_crtc->index);
+
+- evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x);
++ evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff));
+ evo_piow(crtc->dev, ch, 0x0080, 0x00000000);
+ return 0;
+ }
+From 2f292004dd1fb005788dc0a9cdd5559812ed866e Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher at amd.com>
+Date: Mon, 6 Aug 2012 10:03:59 -0400
+Subject: drm/radeon: add some new SI pci ids
+
+From: Alex Deucher <alexander.deucher at amd.com>
+
+commit 2f292004dd1fb005788dc0a9cdd5559812ed866e upstream.
+
+Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ include/drm/drm_pciids.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/include/drm/drm_pciids.h
++++ b/include/drm/drm_pciids.h
+@@ -217,9 +217,12 @@
+ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
++ {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
++ {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
++ {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+From 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 Mon Sep 17 00:00:00 2001
+From: Jerome Glisse <jglisse at redhat.com>
+Date: Fri, 27 Jul 2012 16:32:24 -0400
+Subject: drm/radeon: do not reenable crtc after moving vram start address
+
+From: Jerome Glisse <jglisse at redhat.com>
+
+commit 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 upstream.
+
+It seems we can not update the crtc scanout address. After disabling
+crtc, update to base address do not take effect after crtc being
+reenable leading to at least frame being scanout from the old crtc
+base address. Disabling crtc display request lead to same behavior.
+
+So after changing the vram address if we don't keep crtc disabled
+we will have the GPU trying to read some random system memory address
+with some iommu this will broke the crtc engine and will lead to
+broken display and iommu error message.
+
+So to avoid this, disable crtc. For flicker less boot we will need
+to avoid moving the vram start address.
+
+This patch should also fix :
+
+https://bugs.freedesktop.org/show_bug.cgi?id=42373
+
+Signed-off-by: Jerome Glisse <jglisse at redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/evergreen.c | 57 -----------------------------------
+ drivers/gpu/drm/radeon/radeon_asic.h | 8 +---
+ drivers/gpu/drm/radeon/rv515.c | 13 -------
+ 3 files changed, 2 insertions(+), 76 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/evergreen.c
++++ b/drivers/gpu/drm/radeon/evergreen.c
+@@ -1117,24 +1117,8 @@ void evergreen_agp_enable(struct radeon_
+
+ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
+ {
+- save->vga_control[0] = RREG32(D1VGA_CONTROL);
+- save->vga_control[1] = RREG32(D2VGA_CONTROL);
+ save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
+ save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
+- save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
+- save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
+- if (rdev->num_crtc >= 4) {
+- save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
+- save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
+- save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
+- save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
+- }
+- if (rdev->num_crtc >= 6) {
+- save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
+- save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
+- save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
+- save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+- }
+
+ /* Stop all video */
+ WREG32(VGA_RENDER_CONTROL, 0);
+@@ -1245,47 +1229,6 @@ void evergreen_mc_resume(struct radeon_d
+ /* Unlock host access */
+ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
+ mdelay(1);
+- /* Restore video state */
+- WREG32(D1VGA_CONTROL, save->vga_control[0]);
+- WREG32(D2VGA_CONTROL, save->vga_control[1]);
+- if (rdev->num_crtc >= 4) {
+- WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
+- WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
+- }
+- if (rdev->num_crtc >= 6) {
+- WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
+- WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
+- }
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
+- if (rdev->num_crtc >= 4) {
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
+- }
+- if (rdev->num_crtc >= 6) {
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+- }
+- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
+- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
+- if (rdev->num_crtc >= 4) {
+- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
+- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
+- }
+- if (rdev->num_crtc >= 6) {
+- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
+- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
+- }
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+- if (rdev->num_crtc >= 4) {
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+- }
+- if (rdev->num_crtc >= 6) {
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+- }
+ WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
+ }
+
+--- a/drivers/gpu/drm/radeon/radeon_asic.h
++++ b/drivers/gpu/drm/radeon/radeon_asic.h
+@@ -262,13 +262,10 @@ extern int rs690_mc_wait_for_idle(struct
+ * rv515
+ */
+ struct rv515_mc_save {
+- u32 d1vga_control;
+- u32 d2vga_control;
+ u32 vga_render_control;
+ u32 vga_hdp_control;
+- u32 d1crtc_control;
+- u32 d2crtc_control;
+ };
++
+ int rv515_init(struct radeon_device *rdev);
+ void rv515_fini(struct radeon_device *rdev);
+ uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+@@ -401,11 +398,10 @@ void r700_cp_fini(struct radeon_device *
+ * evergreen
+ */
+ struct evergreen_mc_save {
+- u32 vga_control[6];
+ u32 vga_render_control;
+ u32 vga_hdp_control;
+- u32 crtc_control[6];
+ };
++
+ void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev);
+ int evergreen_init(struct radeon_device *rdev);
+ void evergreen_fini(struct radeon_device *rdev);
+--- a/drivers/gpu/drm/radeon/rv515.c
++++ b/drivers/gpu/drm/radeon/rv515.c
+@@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct ra
+
+ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
+ {
+- save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL);
+- save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);
+ save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);
+ save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
+- save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL);
+- save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);
+
+ /* Stop all video */
+ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
+@@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_devic
+ /* Unlock host access */
+ WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
+ mdelay(1);
+- /* Restore video state */
+- WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control);
+- WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control);
+- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
+- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
+- WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control);
+- WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control);
+- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
+- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
+ WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
+ }
+
+From 5b23c9045a8b61352986270b2d109edf5085e113 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher at amd.com>
+Date: Tue, 31 Jul 2012 11:05:11 -0400
+Subject: drm/radeon: fix bank tiling parameters on cayman
+
+From: Alex Deucher <alexander.deucher at amd.com>
+
+commit 5b23c9045a8b61352986270b2d109edf5085e113 upstream.
+
+Handle the 16 bank case.
+
+Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/ni.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -880,10 +880,18 @@ static void cayman_gpu_init(struct radeo
+ if (rdev->flags & RADEON_IS_IGP)
+ rdev->config.cayman.tile_config |= 1 << 4;
+ else {
+- if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT)
+- rdev->config.cayman.tile_config |= 1 << 4;
+- else
++ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
++ case 0: /* four banks */
+ rdev->config.cayman.tile_config |= 0 << 4;
++ break;
++ case 1: /* eight banks */
++ rdev->config.cayman.tile_config |= 1 << 4;
++ break;
++ case 2: /* sixteen banks */
++ default:
++ rdev->config.cayman.tile_config |= 2 << 4;
++ break;
++ }
+ }
+ rdev->config.cayman.tile_config |=
+ ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
+From c8d15edc17d836686d1f071e564800e1a2724fa6 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher at amd.com>
+Date: Tue, 31 Jul 2012 11:01:10 -0400
+Subject: drm/radeon: fix bank tiling parameters on evergreen
+
+From: Alex Deucher <alexander.deucher at amd.com>
+
+commit c8d15edc17d836686d1f071e564800e1a2724fa6 upstream.
+
+Handle the 16 bank case.
+
+Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/evergreen.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/evergreen.c
++++ b/drivers/gpu/drm/radeon/evergreen.c
+@@ -2085,10 +2085,18 @@ static void evergreen_gpu_init(struct ra
+ if (rdev->flags & RADEON_IS_IGP)
+ rdev->config.evergreen.tile_config |= 1 << 4;
+ else {
+- if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT)
+- rdev->config.evergreen.tile_config |= 1 << 4;
+- else
++ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
++ case 0: /* four banks */
+ rdev->config.evergreen.tile_config |= 0 << 4;
++ break;
++ case 1: /* eight banks */
++ rdev->config.evergreen.tile_config |= 1 << 4;
++ break;
++ case 2: /* sixteen banks */
++ default:
++ rdev->config.evergreen.tile_config |= 2 << 4;
++ break;
++ }
+ }
+ rdev->config.evergreen.tile_config |=
+ ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8;
+From 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher at amd.com>
+Date: Thu, 26 Jul 2012 13:38:52 -0400
+Subject: drm/radeon: properly handle crtc powergating
+
+From: Alex Deucher <alexander.deucher at amd.com>
+
+commit 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab upstream.
+
+Need to make sure the crtc is gated on before modesetting.
+Explicitly gate the crtc on in prepare() and set a flag
+so that the dpms functions don't gate it off during
+mode set.
+
+Noticed by sylware on IRC.
+
+Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++--
+ drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 ++++
+ drivers/gpu/drm/radeon/radeon_mode.h | 1 +
+ 3 files changed, 17 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc
+ /* adjust pm to dpms changes BEFORE enabling crtcs */
+ radeon_pm_compute_clocks(rdev);
+ /* disable crtc pair power gating before programming */
+- if (ASIC_IS_DCE6(rdev))
++ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
+ atombios_powergate_crtc(crtc, ATOM_DISABLE);
+ atombios_enable_crtc(crtc, ATOM_ENABLE);
+ if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
+@@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc
+ atombios_enable_crtc(crtc, ATOM_DISABLE);
+ radeon_crtc->enabled = false;
+ /* power gating is per-pair */
+- if (ASIC_IS_DCE6(rdev)) {
++ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) {
+ struct drm_crtc *other_crtc;
+ struct radeon_crtc *other_radeon_crtc;
+ list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) {
+@@ -1634,18 +1634,28 @@ static bool atombios_crtc_mode_fixup(str
+ static void atombios_crtc_prepare(struct drm_crtc *crtc)
+ {
+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct radeon_device *rdev = dev->dev_private;
+
++ radeon_crtc->in_mode_set = true;
+ /* pick pll */
+ radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);
+
++ /* disable crtc pair power gating before programming */
++ if (ASIC_IS_DCE6(rdev))
++ atombios_powergate_crtc(crtc, ATOM_DISABLE);
++
+ atombios_lock_crtc(crtc, ATOM_ENABLE);
+ atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+ }
+
+ static void atombios_crtc_commit(struct drm_crtc *crtc)
+ {
++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
++
+ atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+ atombios_lock_crtc(crtc, ATOM_DISABLE);
++ radeon_crtc->in_mode_set = false;
+ }
+
+ static void atombios_crtc_disable(struct drm_crtc *crtc)
+--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
++++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct d
+
+ static void radeon_crtc_prepare(struct drm_crtc *crtc)
+ {
++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc *crtci;
+
++ radeon_crtc->in_mode_set = true;
+ /*
+ * The hardware wedges sometimes if you reconfigure one CRTC
+ * whilst another is running (see fdo bug #24611).
+@@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct d
+
+ static void radeon_crtc_commit(struct drm_crtc *crtc)
+ {
++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc *crtci;
+
+@@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct dr
+ if (crtci->enabled)
+ radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
+ }
++ radeon_crtc->in_mode_set = false;
+ }
+
+ static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
+--- a/drivers/gpu/drm/radeon/radeon_mode.h
++++ b/drivers/gpu/drm/radeon/radeon_mode.h
+@@ -266,6 +266,7 @@ struct radeon_crtc {
+ u16 lut_r[256], lut_g[256], lut_b[256];
+ bool enabled;
+ bool can_tile;
++ bool in_mode_set;
+ uint32_t crtc_offset;
+ struct drm_gem_object *cursor_bo;
+ uint64_t cursor_addr;
+From 7e731bc9a12339f344cddf82166b82633d99dd86 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso at mit.edu>
+Date: Sun, 5 Aug 2012 23:28:16 -0400
+Subject: ext4: avoid kmemcheck complaint from reading uninitialized memory
+
+From: Theodore Ts'o <tytso at mit.edu>
+
+commit 7e731bc9a12339f344cddf82166b82633d99dd86 upstream.
+
+Commit 03179fe923 introduced a kmemcheck complaint in
+ext4_da_get_block_prep() because we save and restore
+ei->i_da_metadata_calc_last_lblock even though it is left
+uninitialized in the case where i_da_metadata_calc_len is zero.
+
+This doesn't hurt anything, but silencing the kmemcheck complaint
+makes it easier for people to find real bugs.
+
+Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45631
+(which is marked as a regression).
+
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ fs/ext4/super.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -932,6 +932,7 @@ static struct inode *ext4_alloc_inode(st
+ ei->i_reserved_meta_blocks = 0;
+ ei->i_allocated_meta_blocks = 0;
+ ei->i_da_metadata_calc_len = 0;
++ ei->i_da_metadata_calc_last_lblock = 0;
+ spin_lock_init(&(ei->i_block_reservation_lock));
+ #ifdef CONFIG_QUOTA
+ ei->i_reserved_quota = 0;
+From 89a4e48f8479f8145eca9698f39fe188c982212f Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso at mit.edu>
+Date: Fri, 17 Aug 2012 08:54:52 -0400
+Subject: ext4: fix kernel BUG on large-scale rm -rf commands
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Theodore Ts'o <tytso at mit.edu>
+
+commit 89a4e48f8479f8145eca9698f39fe188c982212f upstream.
+
+Commit 968dee7722: "ext4: fix hole punch failure when depth is greater
+than 0" introduced a regression in v3.5.1/v3.6-rc1 which caused kernel
+crashes when users ran run "rm -rf" on large directory hierarchy on
+ext4 filesystems on RAID devices:
+
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000028
+
+ Process rm (pid: 18229, threadinfo ffff8801276bc000, task ffff880123631710)
+ Call Trace:
+ [<ffffffff81236483>] ? __ext4_handle_dirty_metadata+0x83/0x110
+ [<ffffffff812353d3>] ext4_ext_truncate+0x193/0x1d0
+ [<ffffffff8120a8cf>] ? ext4_mark_inode_dirty+0x7f/0x1f0
+ [<ffffffff81207e05>] ext4_truncate+0xf5/0x100
+ [<ffffffff8120cd51>] ext4_evict_inode+0x461/0x490
+ [<ffffffff811a1312>] evict+0xa2/0x1a0
+ [<ffffffff811a1513>] iput+0x103/0x1f0
+ [<ffffffff81196d84>] do_unlinkat+0x154/0x1c0
+ [<ffffffff8118cc3a>] ? sys_newfstatat+0x2a/0x40
+ [<ffffffff81197b0b>] sys_unlinkat+0x1b/0x50
+ [<ffffffff816135e9>] system_call_fastpath+0x16/0x1b
+ Code: 8b 4d 20 0f b7 41 02 48 8d 04 40 48 8d 04 81 49 89 45 18 0f b7 49 02 48 83 c1 01 49 89 4d 00 e9 ae f8 ff ff 0f 1f 00 49 8b 45 28 <48> 8b 40 28 49 89 45 20 e9 85 f8 ff ff 0f 1f 80 00 00 00
+
+ RIP [<ffffffff81233164>] ext4_ext_remove_space+0xa34/0xdf0
+
+This could be reproduced as follows:
+
+The problem in commit 968dee7722 was that caused the variable 'i' to
+be left uninitialized if the truncate required more space than was
+available in the journal. This resulted in the function
+ext4_ext_truncate_extend_restart() returning -EAGAIN, which caused
+ext4_ext_remove_space() to restart the truncate operation after
+starting a new jbd2 handle.
+
+Reported-by: Maciej Żenczykowski <maze at google.com>
+Reported-by: Marti Raudsepp <marti at juffo.org>
+Tested-by: Fengguang Wu <fengguang.wu at intel.com>
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ fs/ext4/extents.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2596,6 +2596,7 @@ cont:
+ }
+ path[0].p_depth = depth;
+ path[0].p_hdr = ext_inode_hdr(inode);
++ i = 0;
+
+ if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
+ err = -EIO;
+From 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso at mit.edu>
+Date: Thu, 16 Aug 2012 11:59:04 -0400
+Subject: ext4: fix long mount times on very big file systems
+
+From: Theodore Ts'o <tytso at mit.edu>
+
+commit 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 upstream.
+
+Commit 8aeb00ff85a: "ext4: fix overhead calculation used by
+ext4_statfs()" introduced a O(n**2) calculation which makes very large
+file systems take forever to mount. Fix this with an optimization for
+non-bigalloc file systems. (For bigalloc file systems the overhead
+needs to be set in the the superblock.)
+
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ fs/ext4/super.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2969,6 +2969,10 @@ static int count_overhead(struct super_b
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ int s, j, count = 0;
+
++ if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC))
++ return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
++ sbi->s_itb_per_group + 2);
++
+ first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
+ (grp * EXT4_BLOCKS_PER_GROUP(sb));
+ last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;
+From d796c52ef0b71a988364f6109aeb63d79c5b116b Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso at mit.edu>
+Date: Sun, 5 Aug 2012 19:04:57 -0400
+Subject: ext4: make sure the journal sb is written in ext4_clear_journal_err()
+
+From: Theodore Ts'o <tytso at mit.edu>
+
+commit d796c52ef0b71a988364f6109aeb63d79c5b116b upstream.
+
+After we transfer set the EXT4_ERROR_FS bit in the file system
+superblock, it's not enough to call jbd2_journal_clear_err() to clear
+the error indication from journal superblock --- we need to call
+jbd2_journal_update_sb_errno() as well. Otherwise, when the root file
+system is mounted read-only, the journal is replayed, and the error
+indicator is transferred to the superblock --- but the s_errno field
+in the jbd2 superblock is left set (since although we cleared it in
+memory, we never flushed it out to disk).
+
+This can end up confusing e2fsck. We should make e2fsck more robust
+in this case, but the kernel shouldn't be leaving things in this
+confused state, either.
+
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ fs/ext4/super.c | 1 +
+ fs/jbd2/journal.c | 3 ++-
+ include/linux/jbd2.h | 1 +
+ 3 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4227,6 +4227,7 @@ static void ext4_clear_journal_err(struc
+ ext4_commit_super(sb, 1);
+
+ jbd2_journal_clear_err(journal);
++ jbd2_journal_update_sb_errno(journal);
+ }
+ }
+
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1340,7 +1340,7 @@ static void jbd2_mark_journal_empty(jour
+ * Update a journal's errno. Write updated superblock to disk waiting for IO
+ * to complete.
+ */
+-static void jbd2_journal_update_sb_errno(journal_t *journal)
++void jbd2_journal_update_sb_errno(journal_t *journal)
+ {
+ journal_superblock_t *sb = journal->j_superblock;
+
+@@ -1352,6 +1352,7 @@ static void jbd2_journal_update_sb_errno
+
+ jbd2_write_superblock(journal, WRITE_SYNC);
+ }
++EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
+
+ /*
+ * Read the superblock for a given journal, performing initial
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1091,6 +1091,7 @@ extern int jbd2_journal_destroy (j
+ extern int jbd2_journal_recover (journal_t *journal);
+ extern int jbd2_journal_wipe (journal_t *, int);
+ extern int jbd2_journal_skip_recovery (journal_t *);
++extern void jbd2_journal_update_sb_errno(journal_t *);
+ extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t,
+ unsigned long, int);
+ extern void __jbd2_journal_abort_hard (journal_t *);
+From fb6ccff667712c46b4501b920ea73a326e49626a Mon Sep 17 00:00:00 2001
+From: Zach Brown <zab at redhat.com>
+Date: Tue, 24 Jul 2012 12:10:11 -0700
+Subject: fuse: verify all ioctl retry iov elements
+
+From: Zach Brown <zab at redhat.com>
+
+commit fb6ccff667712c46b4501b920ea73a326e49626a upstream.
+
+Commit 7572777eef78ebdee1ecb7c258c0ef94d35bad16 attempted to verify that
+the total iovec from the client doesn't overflow iov_length() but it
+only checked the first element. The iovec could still overflow by
+starting with a small element. The obvious fix is to check all the
+elements.
+
+The overflow case doesn't look dangerous to the kernel as the copy is
+limited by the length after the overflow. This fix restores the
+intention of returning an error instead of successfully copying less
+than the iovec represented.
+
+I found this by code inspection. I built it but don't have a test case.
+I'm cc:ing stable because the initial commit did as well.
+
+Signed-off-by: Zach Brown <zab at redhat.com>
+Signed-off-by: Miklos Szeredi <mszeredi at suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ fs/fuse/file.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -1698,7 +1698,7 @@ static int fuse_verify_ioctl_iov(struct
+ size_t n;
+ u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
+
+- for (n = 0; n < count; n++) {
++ for (n = 0; n < count; n++, iov++) {
+ if (iov->iov_len > (size_t) max)
+ return -ENOMEM;
+ max -= iov->iov_len;
+From 220329916c72ee3d54ae7262b215a050f04a18fc Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bvanassche at acm.org>
+Date: Tue, 14 Aug 2012 13:18:53 +0000
+Subject: IB/srp: Fix a race condition
+
+From: Bart Van Assche <bvanassche at acm.org>
+
+commit 220329916c72ee3d54ae7262b215a050f04a18fc upstream.
+
+Avoid a crash caused by the scmnd->scsi_done(scmnd) call in
+srp_process_rsp() being invoked with scsi_done == NULL. This can
+happen if a reply is received during or after a command abort.
+
+Reported-by: Joseph Glanville <joseph.glanville at orionvm.com.au>
+Reference: http://marc.info/?l=linux-rdma&m=134314367801595
+Acked-by: David Dillow <dillowda at ornl.gov>
+Signed-off-by: Bart Van Assche <bvanassche at acm.org>
+Signed-off-by: Roland Dreier <roland at purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c | 87 ++++++++++++++++++++++++++----------
+ 1 file changed, 63 insertions(+), 24 deletions(-)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_c
+ scmnd->sc_data_direction);
+ }
+
+-static void srp_remove_req(struct srp_target_port *target,
+- struct srp_request *req, s32 req_lim_delta)
++/**
++ * srp_claim_req - Take ownership of the scmnd associated with a request.
++ * @target: SRP target port.
++ * @req: SRP request.
++ * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
++ * ownership of @req->scmnd if it equals @scmnd.
++ *
++ * Return value:
++ * Either NULL or a pointer to the SCSI command the caller became owner of.
++ */
++static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
++ struct srp_request *req,
++ struct scsi_cmnd *scmnd)
+ {
+ unsigned long flags;
+
+- srp_unmap_data(req->scmnd, target, req);
++ spin_lock_irqsave(&target->lock, flags);
++ if (!scmnd) {
++ scmnd = req->scmnd;
++ req->scmnd = NULL;
++ } else if (req->scmnd == scmnd) {
++ req->scmnd = NULL;
++ } else {
++ scmnd = NULL;
++ }
++ spin_unlock_irqrestore(&target->lock, flags);
++
++ return scmnd;
++}
++
++/**
++ * srp_free_req() - Unmap data and add request to the free request list.
++ */
++static void srp_free_req(struct srp_target_port *target,
++ struct srp_request *req, struct scsi_cmnd *scmnd,
++ s32 req_lim_delta)
++{
++ unsigned long flags;
++
++ srp_unmap_data(scmnd, target, req);
++
+ spin_lock_irqsave(&target->lock, flags);
+ target->req_lim += req_lim_delta;
+- req->scmnd = NULL;
+ list_add_tail(&req->list, &target->free_reqs);
+ spin_unlock_irqrestore(&target->lock, flags);
+ }
+
+ static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
+ {
+- req->scmnd->result = DID_RESET << 16;
+- req->scmnd->scsi_done(req->scmnd);
+- srp_remove_req(target, req, 0);
++ struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL);
++
++ if (scmnd) {
++ scmnd->result = DID_RESET << 16;
++ scmnd->scsi_done(scmnd);
++ srp_free_req(target, req, scmnd, 0);
++ }
+ }
+
+ static int srp_reconnect_target(struct srp_target_port *target)
+@@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_t
+ complete(&target->tsk_mgmt_done);
+ } else {
+ req = &target->req_ring[rsp->tag];
+- scmnd = req->scmnd;
+- if (!scmnd)
++ scmnd = srp_claim_req(target, req, NULL);
++ if (!scmnd) {
+ shost_printk(KERN_ERR, target->scsi_host,
+ "Null scmnd for RSP w/tag %016llx\n",
+ (unsigned long long) rsp->tag);
++
++ spin_lock_irqsave(&target->lock, flags);
++ target->req_lim += be32_to_cpu(rsp->req_lim_delta);
++ spin_unlock_irqrestore(&target->lock, flags);
++
++ return;
++ }
+ scmnd->result = rsp->status;
+
+ if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
+@@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_t
+ else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
+ scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
+
+- srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta));
++ srp_free_req(target, req, scmnd,
++ be32_to_cpu(rsp->req_lim_delta));
++
+ scmnd->host_scribble = NULL;
+ scmnd->scsi_done(scmnd);
+ }
+@@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *s
+ {
+ struct srp_target_port *target = host_to_target(scmnd->device->host);
+ struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
+- int ret = SUCCESS;
+
+ shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
+
+- if (!req || target->qp_in_error)
+- return FAILED;
+- if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
+- SRP_TSK_ABORT_TASK))
++ if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd))
+ return FAILED;
++ srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
++ SRP_TSK_ABORT_TASK);
++ srp_free_req(target, req, scmnd, 0);
++ scmnd->result = DID_ABORT << 16;
+
+- if (req->scmnd) {
+- if (!target->tsk_mgmt_status) {
+- srp_remove_req(target, req, 0);
+- scmnd->result = DID_ABORT << 16;
+- } else
+- ret = FAILED;
+- }
+-
+- return ret;
++ return SUCCESS;
+ }
+
+ static int srp_reset_device(struct scsi_cmnd *scmnd)
+From 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 Mon Sep 17 00:00:00 2001
+From: Jason Wessel <jason.wessel at windriver.com>
+Date: Sun, 12 Aug 2012 07:16:43 -0500
+Subject: pmac_zilog,kdb: Fix console poll hook to return instead of loop
+
+From: Jason Wessel <jason.wessel at windriver.com>
+
+commit 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 upstream.
+
+kdb <-> kgdb transitioning does not work properly with this UART
+driver because the get character routine loops indefinitely as opposed
+to returning NO_POLL_CHAR per the expectation of the KDB I/O driver
+API.
+
+The symptom is a kernel hang when trying to switch debug modes.
+
+Signed-off-by: Jason Wessel <jason.wessel at windriver.com>
+Cc: Alan Cox <alan at linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/tty/serial/pmac_zilog.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/serial/pmac_zilog.c
++++ b/drivers/tty/serial/pmac_zilog.c
+@@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_p
+ static int pmz_poll_get_char(struct uart_port *port)
+ {
+ struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
++ int tries = 2;
+
+- while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0)
+- udelay(5);
+- return read_zsdata(uap);
++ while (tries) {
++ if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0)
++ return read_zsdata(uap);
++ if (tries--)
++ udelay(5);
++ }
++
++ return NO_POLL_CHAR;
+ }
+
+ static void pmz_poll_put_char(struct uart_port *port, unsigned char c)
+From a769f9577232afe2c754606a83aad85127e7052a Mon Sep 17 00:00:00 2001
+From: Jeongdo Son <sohn9086 at gmail.com>
+Date: Fri, 15 Jun 2012 02:28:01 +0900
+Subject: rt2x00: Add support for BUFFALO WLI-UC-GNM2 to rt2800usb.
+
+From: Jeongdo Son <sohn9086 at gmail.com>
+
+commit a769f9577232afe2c754606a83aad85127e7052a upstream.
+
+This is a RT3070 based device.
+
+Signed-off-by: Jeongdo Son <sohn9086 at gmail.com>
+Signed-off-by: John W. Linville <linville at tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at 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
+@@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_de
+ { USB_DEVICE(0x0411, 0x015d) },
+ { USB_DEVICE(0x0411, 0x016f) },
+ { USB_DEVICE(0x0411, 0x01a2) },
++ { USB_DEVICE(0x0411, 0x01ee) },
+ /* Corega */
+ { USB_DEVICE(0x07aa, 0x002f) },
+ { USB_DEVICE(0x07aa, 0x003c) },
+From 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 Mon Sep 17 00:00:00 2001
+From: Heiko Carstens <heiko.carstens at de.ibm.com>
+Date: Tue, 7 Aug 2012 09:48:13 +0200
+Subject: s390/compat: fix compat wrappers for process_vm system calls
+
+From: Heiko Carstens <heiko.carstens at de.ibm.com>
+
+commit 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 upstream.
+
+The compat wrappers incorrectly called the non compat versions of
+the system process_vm system calls.
+
+Signed-off-by: Heiko Carstens <heiko.carstens at de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky at de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ arch/s390/kernel/compat_wrapper.S | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/kernel/compat_wrapper.S
++++ b/arch/s390/kernel/compat_wrapper.S
+@@ -1636,7 +1636,7 @@ ENTRY(compat_sys_process_vm_readv_wrappe
+ llgfr %r6,%r6 # unsigned long
+ llgf %r0,164(%r15) # unsigned long
+ stg %r0,160(%r15)
+- jg sys_process_vm_readv
++ jg compat_sys_process_vm_readv
+
+ ENTRY(compat_sys_process_vm_writev_wrapper)
+ lgfr %r2,%r2 # compat_pid_t
+@@ -1646,4 +1646,4 @@ ENTRY(compat_sys_process_vm_writev_wrapp
+ llgfr %r6,%r6 # unsigned long
+ llgf %r0,164(%r15) # unsigned long
+ stg %r0,160(%r15)
+- jg sys_process_vm_writev
++ jg compat_sys_process_vm_writev
+From e85871218513c54f7dfdb6009043cb638f2fecbe Mon Sep 17 00:00:00 2001
+From: Heiko Carstens <heiko.carstens at de.ibm.com>
+Date: Wed, 8 Aug 2012 09:32:20 +0200
+Subject: s390/compat: fix mmap compat system calls
+
+From: Heiko Carstens <heiko.carstens at de.ibm.com>
+
+commit e85871218513c54f7dfdb6009043cb638f2fecbe upstream.
+
+The native 31 bit and the compat behaviour for the mmap system calls differ:
+
+In native 31 bit mode the passed in address for the mmap system call will be
+unmodified passed to sys_mmap_pgoff().
+In compat mode however the passed in address will be modified with
+compat_ptr() which masks out the most significant bit.
+
+The result is that in native 31 bit mode each mmap request (with MAP_FIXED)
+will fail where the most significat bit is set, while in compat mode it
+may succeed.
+
+This odd behaviour was introduced with d3815898 "[S390] mmap: add missing
+compat_ptr conversion to both mmap compat syscalls".
+
+To restore a consistent behaviour accross native and compat mode this
+patch functionally reverts the above mentioned commit.
+
+Signed-off-by: Heiko Carstens <heiko.carstens at de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky at de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ arch/s390/kernel/compat_linux.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/s390/kernel/compat_linux.c
++++ b/arch/s390/kernel/compat_linux.c
+@@ -612,7 +612,6 @@ asmlinkage unsigned long old32_mmap(stru
+ return -EFAULT;
+ if (a.offset & ~PAGE_MASK)
+ return -EINVAL;
+- a.addr = (unsigned long) compat_ptr(a.addr);
+ return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+ a.offset >> PAGE_SHIFT);
+ }
+@@ -623,7 +622,6 @@ asmlinkage long sys32_mmap2(struct mmap_
+
+ if (copy_from_user(&a, arg, sizeof(a)))
+ return -EFAULT;
+- a.addr = (unsigned long) compat_ptr(a.addr);
+ return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+ }
+
+From d81a5d1956731c453b85c141458d4ff5d6cc5366 Mon Sep 17 00:00:00 2001
+From: Gustavo Padovan <gustavo.padovan at collabora.co.uk>
+Date: Tue, 10 Jul 2012 19:10:06 -0300
+Subject: USB: add USB_VENDOR_AND_INTERFACE_INFO() macro
+
+From: Gustavo Padovan <gustavo.padovan at collabora.co.uk>
+
+commit d81a5d1956731c453b85c141458d4ff5d6cc5366 upstream.
+
+A lot of Broadcom Bluetooth devices provides vendor specific interface
+class and we are getting flooded by patches adding new device support.
+This change will help us enable support for any other Broadcom with vendor
+specific device that arrives in the future.
+
+Only the product id changes for those devices, so this macro would be
+perfect for us:
+
+{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }
+
+Signed-off-by: Marcel Holtmann <marcel at holtmann.org>
+Signed-off-by: Gustavo Padovan <gustavo.padovan at collabora.co.uk>
+Acked-by: Henrik Rydberg <rydberg at bitmath.se>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ include/linux/usb.h | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -783,6 +783,27 @@ static inline int usb_make_path(struct u
+ .bInterfaceSubClass = (sc), \
+ .bInterfaceProtocol = (pr)
+
++/**
++ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces
++ * @vend: the 16 bit USB Vendor ID
++ * @cl: bInterfaceClass value
++ * @sc: bInterfaceSubClass value
++ * @pr: bInterfaceProtocol value
++ *
++ * This macro is used to create a struct usb_device_id that matches a
++ * specific vendor with a specific class of interfaces.
++ *
++ * This is especially useful when explicitly matching devices that have
++ * vendor specific bDeviceClass values, but standards-compliant interfaces.
++ */
++#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \
++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
++ | USB_DEVICE_ID_MATCH_VENDOR, \
++ .idVendor = (vend), \
++ .bInterfaceClass = (cl), \
++ .bInterfaceSubClass = (sc), \
++ .bInterfaceProtocol = (pr)
++
+ /* ----------------------------------------------------------------------- */
+
+ /* Stuff for dynamic usb ids */
+From 7724a1edbe463b06d4e7831a41149ba095b16c53 Mon Sep 17 00:00:00 2001
+From: Ozan Çağlayan <ozancag at gmail.com>
+Date: Fri, 10 Aug 2012 17:25:10 +0300
+Subject: USB: ftdi_sio: Add VID/PID for Kondo Serial USB
+
+From: Ozan Çağlayan <ozancag at gmail.com>
+
+commit 7724a1edbe463b06d4e7831a41149ba095b16c53 upstream.
+
+This adds VID/PID for Kondo Kagaku Co. Ltd. Serial USB Adapter
+interface:
+http://www.kondo-robot.com/EN/wp/?cat=28
+
+Tested by controlling an RCB3 board using libRCB3.
+
+Signed-off-by: Ozan Çağlayan <ozancag at gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -811,6 +811,7 @@ static struct usb_device_id id_table_com
+ { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
+ { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+ { USB_DEVICE(PI_VID, PI_E861_PID) },
++ { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
+ { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
+ { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -795,6 +795,13 @@
+ #define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */
+
+ /*
++ * Kondo Kagaku Co.Ltd.
++ * http://www.kondo-robot.com/EN
++ */
++#define KONDO_VID 0x165c
++#define KONDO_USB_SERIAL_PID 0x0002
++
++/*
+ * Bayer Ascensia Contour blood glucose meter USB-converter cable.
+ * http://winglucofacts.com/cables/
+ */
+From b1b552a69b8805e7e338074a9e8b670b4a795218 Mon Sep 17 00:00:00 2001
+From: Michael Grzeschik <m.grzeschik at pengutronix.de>
+Date: Wed, 8 Aug 2012 11:48:10 +0200
+Subject: usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop
+
+From: Michael Grzeschik <m.grzeschik at pengutronix.de>
+
+commit b1b552a69b8805e7e338074a9e8b670b4a795218 upstream.
+
+This patch fixes an issue introduced by patch:
+
+ 72c973d usb: gadget: add usb_endpoint_descriptor to struct usb_ep
+
+Without this patch we see a kworker taking 100% CPU, after this sequence:
+
+- Connect gadget to a windows host
+- load g_ether
+- ifconfig up <ip>; ifconfig down; ifconfig up
+- ping <windows host>
+
+The "ifconfig down" results in calling eth_stop(), which will call
+usb_ep_disable() and, if the carrier is still ok, usb_ep_enable():
+
+ usb_ep_disable(link->in_ep);
+ usb_ep_disable(link->out_ep);
+ if (netif_carrier_ok(net)) {
+ usb_ep_enable(link->in_ep);
+ usb_ep_enable(link->out_ep);
+ }
+
+The ep should stay enabled, but will not, as ep_disable set the desc
+pointer to NULL, therefore the subsequent ep_enable will fail. This leads
+to permanent rescheduling of the eth_work() worker as usb_ep_queue()
+(called by the worker) will fail due to the unconfigured endpoint.
+
+We fix this issue by saving the ep descriptors and re-assign them before
+usb_ep_enable().
+
+Cc: Tatyana Brokhman <tlinder at codeaurora.org>
+Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
+Signed-off-by: Marc Kleine-Budde <mkl at pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/gadget/u_ether.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/gadget/u_ether.c
++++ b/drivers/usb/gadget/u_ether.c
+@@ -669,6 +669,8 @@ static int eth_stop(struct net_device *n
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->port_usb) {
+ struct gether *link = dev->port_usb;
++ const struct usb_endpoint_descriptor *in;
++ const struct usb_endpoint_descriptor *out;
+
+ if (link->close)
+ link->close(link);
+@@ -682,10 +684,14 @@ static int eth_stop(struct net_device *n
+ * their own pace; the network stack can handle old packets.
+ * For the moment we leave this here, since it works.
+ */
++ in = link->in_ep->desc;
++ out = link->out_ep->desc;
+ usb_ep_disable(link->in_ep);
+ usb_ep_disable(link->out_ep);
+ if (netif_carrier_ok(net)) {
+ DBG(dev, "host still using in/out endpoints\n");
++ link->in_ep->desc = in;
++ link->out_ep->desc = out;
+ usb_ep_enable(link->in_ep);
+ usb_ep_enable(link->out_ep);
+ }
+From f1b5c997e68533df1f96dcd3068a231bca495603 Mon Sep 17 00:00:00 2001
+From: Bjørn Mork <bjorn at mork.no>
+Date: Wed, 15 Aug 2012 15:43:33 +0200
+Subject: USB: option: add ZTE K5006-Z
+
+From: Bjørn Mork <bjorn at mork.no>
+
+commit f1b5c997e68533df1f96dcd3068a231bca495603 upstream.
+
+The ZTE (Vodafone) K5006-Z use the following
+interface layout:
+
+00 DIAG
+01 secondary
+02 modem
+03 networkcard
+04 storage
+
+Ignoring interface #3 which is handled by the qmi_wwan
+driver.
+
+Signed-off-by: Bjørn Mork <bjorn at mork.no>
+Cc: Thomas Schäfer <tschaefer at t-online.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -886,6 +886,8 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
+From 5c263b92f828af6a8cf54041db45ceae5af8f2ab Mon Sep 17 00:00:00 2001
+From: Mark Ferrell <mferrell at uplogix.com>
+Date: Tue, 24 Jul 2012 14:15:13 -0500
+Subject: usb: serial: mos7840: Fixup mos7840_chars_in_buffer()
+
+From: Mark Ferrell <mferrell at uplogix.com>
+
+commit 5c263b92f828af6a8cf54041db45ceae5af8f2ab upstream.
+
+ * Use the buffer content length as opposed to the total buffer size. This can
+ be a real problem when using the mos7840 as a usb serial-console as all
+ kernel output is truncated during boot.
+
+Signed-off-by: Mark Ferrell <mferrell at uplogix.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/serial/mos7840.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -1189,9 +1189,12 @@ static int mos7840_chars_in_buffer(struc
+ }
+
+ spin_lock_irqsave(&mos7840_port->pool_lock, flags);
+- for (i = 0; i < NUM_URBS; ++i)
+- if (mos7840_port->busy[i])
+- chars += URB_TRANSFER_BUFFER_SIZE;
++ for (i = 0; i < NUM_URBS; ++i) {
++ if (mos7840_port->busy[i]) {
++ struct urb *urb = mos7840_port->write_urb_pool[i];
++ chars += urb->transfer_buffer_length;
++ }
++ }
+ spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+ dbg("%s - returns %d", __func__, chars);
+ return chars;
+From ee6f827df9107139e8960326e49e1376352ced4d Mon Sep 17 00:00:00 2001
+From: fangxiaozhi <huananhu at huawei.com>
+Date: Wed, 8 Aug 2012 09:24:45 +0000
+Subject: USB: support the new interfaces of Huawei Data Card devices in option driver
+
+From: fangxiaozhi <huananhu at huawei.com>
+
+commit ee6f827df9107139e8960326e49e1376352ced4d upstream.
+
+In this patch, we add new declarations into option.c to support the new
+interfaces of Huawei Data Card devices. And at the same time, remove the
+redundant declarations from option.c.
+
+Signed-off-by: fangxiaozhi <huananhu at huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 279 +++++++++++++++++---------------------------
+ 1 file changed, 111 insertions(+), 168 deletions(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -80,85 +80,9 @@ static void option_instat_callback(struc
+ #define OPTION_PRODUCT_GTM380_MODEM 0x7201
+
+ #define HUAWEI_VENDOR_ID 0x12D1
+-#define HUAWEI_PRODUCT_E600 0x1001
+-#define HUAWEI_PRODUCT_E220 0x1003
+-#define HUAWEI_PRODUCT_E220BIS 0x1004
+-#define HUAWEI_PRODUCT_E1401 0x1401
+-#define HUAWEI_PRODUCT_E1402 0x1402
+-#define HUAWEI_PRODUCT_E1403 0x1403
+-#define HUAWEI_PRODUCT_E1404 0x1404
+-#define HUAWEI_PRODUCT_E1405 0x1405
+-#define HUAWEI_PRODUCT_E1406 0x1406
+-#define HUAWEI_PRODUCT_E1407 0x1407
+-#define HUAWEI_PRODUCT_E1408 0x1408
+-#define HUAWEI_PRODUCT_E1409 0x1409
+-#define HUAWEI_PRODUCT_E140A 0x140A
+-#define HUAWEI_PRODUCT_E140B 0x140B
+-#define HUAWEI_PRODUCT_E140C 0x140C
+-#define HUAWEI_PRODUCT_E140D 0x140D
+-#define HUAWEI_PRODUCT_E140E 0x140E
+-#define HUAWEI_PRODUCT_E140F 0x140F
+-#define HUAWEI_PRODUCT_E1410 0x1410
+-#define HUAWEI_PRODUCT_E1411 0x1411
+-#define HUAWEI_PRODUCT_E1412 0x1412
+-#define HUAWEI_PRODUCT_E1413 0x1413
+-#define HUAWEI_PRODUCT_E1414 0x1414
+-#define HUAWEI_PRODUCT_E1415 0x1415
+-#define HUAWEI_PRODUCT_E1416 0x1416
+-#define HUAWEI_PRODUCT_E1417 0x1417
+-#define HUAWEI_PRODUCT_E1418 0x1418
+-#define HUAWEI_PRODUCT_E1419 0x1419
+-#define HUAWEI_PRODUCT_E141A 0x141A
+-#define HUAWEI_PRODUCT_E141B 0x141B
+-#define HUAWEI_PRODUCT_E141C 0x141C
+-#define HUAWEI_PRODUCT_E141D 0x141D
+-#define HUAWEI_PRODUCT_E141E 0x141E
+-#define HUAWEI_PRODUCT_E141F 0x141F
+-#define HUAWEI_PRODUCT_E1420 0x1420
+-#define HUAWEI_PRODUCT_E1421 0x1421
+-#define HUAWEI_PRODUCT_E1422 0x1422
+-#define HUAWEI_PRODUCT_E1423 0x1423
+-#define HUAWEI_PRODUCT_E1424 0x1424
+-#define HUAWEI_PRODUCT_E1425 0x1425
+-#define HUAWEI_PRODUCT_E1426 0x1426
+-#define HUAWEI_PRODUCT_E1427 0x1427
+-#define HUAWEI_PRODUCT_E1428 0x1428
+-#define HUAWEI_PRODUCT_E1429 0x1429
+-#define HUAWEI_PRODUCT_E142A 0x142A
+-#define HUAWEI_PRODUCT_E142B 0x142B
+-#define HUAWEI_PRODUCT_E142C 0x142C
+-#define HUAWEI_PRODUCT_E142D 0x142D
+-#define HUAWEI_PRODUCT_E142E 0x142E
+-#define HUAWEI_PRODUCT_E142F 0x142F
+-#define HUAWEI_PRODUCT_E1430 0x1430
+-#define HUAWEI_PRODUCT_E1431 0x1431
+-#define HUAWEI_PRODUCT_E1432 0x1432
+-#define HUAWEI_PRODUCT_E1433 0x1433
+-#define HUAWEI_PRODUCT_E1434 0x1434
+-#define HUAWEI_PRODUCT_E1435 0x1435
+-#define HUAWEI_PRODUCT_E1436 0x1436
+-#define HUAWEI_PRODUCT_E1437 0x1437
+-#define HUAWEI_PRODUCT_E1438 0x1438
+-#define HUAWEI_PRODUCT_E1439 0x1439
+-#define HUAWEI_PRODUCT_E143A 0x143A
+-#define HUAWEI_PRODUCT_E143B 0x143B
+-#define HUAWEI_PRODUCT_E143C 0x143C
+-#define HUAWEI_PRODUCT_E143D 0x143D
+-#define HUAWEI_PRODUCT_E143E 0x143E
+-#define HUAWEI_PRODUCT_E143F 0x143F
+ #define HUAWEI_PRODUCT_K4505 0x1464
+ #define HUAWEI_PRODUCT_K3765 0x1465
+-#define HUAWEI_PRODUCT_E14AC 0x14AC
+-#define HUAWEI_PRODUCT_K3806 0x14AE
+ #define HUAWEI_PRODUCT_K4605 0x14C6
+-#define HUAWEI_PRODUCT_K5005 0x14C8
+-#define HUAWEI_PRODUCT_K3770 0x14C9
+-#define HUAWEI_PRODUCT_K3771 0x14CA
+-#define HUAWEI_PRODUCT_K4510 0x14CB
+-#define HUAWEI_PRODUCT_K4511 0x14CC
+-#define HUAWEI_PRODUCT_ETS1220 0x1803
+-#define HUAWEI_PRODUCT_E353 0x1506
+-#define HUAWEI_PRODUCT_E173S 0x1C05
+
+ #define QUANTA_VENDOR_ID 0x0408
+ #define QUANTA_PRODUCT_Q101 0xEA02
+@@ -615,104 +539,123 @@ static const struct usb_device_id option
+ { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
+ { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
+ { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) },
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */
+- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) },
++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) },
++
++
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
+From b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
+Date: Wed, 23 May 2012 18:57:20 +0100
+Subject: xen: mark local pages as FOREIGN in the m2p_override
+
+From: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
+
+commit b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f upstream.
+
+When the frontend and the backend reside on the same domain, even if we
+add pages to the m2p_override, these pages will never be returned by
+mfn_to_pfn because the check "get_phys_to_machine(pfn) != mfn" will
+always fail, so the pfn of the frontend will be returned instead
+(resulting in a deadlock because the frontend pages are already locked).
+
+INFO: task qemu-system-i38:1085 blocked for more than 120 seconds.
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+qemu-system-i38 D ffff8800cfc137c0 0 1085 1 0x00000000
+ ffff8800c47ed898 0000000000000282 ffff8800be4596b0 00000000000137c0
+ ffff8800c47edfd8 ffff8800c47ec010 00000000000137c0 00000000000137c0
+ ffff8800c47edfd8 00000000000137c0 ffffffff82213020 ffff8800be4596b0
+Call Trace:
+ [<ffffffff81101ee0>] ? __lock_page+0x70/0x70
+ [<ffffffff81a0fdd9>] schedule+0x29/0x70
+ [<ffffffff81a0fe80>] io_schedule+0x60/0x80
+ [<ffffffff81101eee>] sleep_on_page+0xe/0x20
+ [<ffffffff81a0e1ca>] __wait_on_bit_lock+0x5a/0xc0
+ [<ffffffff81101ed7>] __lock_page+0x67/0x70
+ [<ffffffff8106f750>] ? autoremove_wake_function+0x40/0x40
+ [<ffffffff811867e6>] ? bio_add_page+0x36/0x40
+ [<ffffffff8110b692>] set_page_dirty_lock+0x52/0x60
+ [<ffffffff81186021>] bio_set_pages_dirty+0x51/0x70
+ [<ffffffff8118c6b4>] do_blockdev_direct_IO+0xb24/0xeb0
+ [<ffffffff811e71a0>] ? ext3_get_blocks_handle+0xe00/0xe00
+ [<ffffffff8118ca95>] __blockdev_direct_IO+0x55/0x60
+ [<ffffffff811e71a0>] ? ext3_get_blocks_handle+0xe00/0xe00
+ [<ffffffff811e91c8>] ext3_direct_IO+0xf8/0x390
+ [<ffffffff811e71a0>] ? ext3_get_blocks_handle+0xe00/0xe00
+ [<ffffffff81004b60>] ? xen_mc_flush+0xb0/0x1b0
+ [<ffffffff81104027>] generic_file_aio_read+0x737/0x780
+ [<ffffffff813bedeb>] ? gnttab_map_refs+0x15b/0x1e0
+ [<ffffffff811038f0>] ? find_get_pages+0x150/0x150
+ [<ffffffff8119736c>] aio_rw_vect_retry+0x7c/0x1d0
+ [<ffffffff811972f0>] ? lookup_ioctx+0x90/0x90
+ [<ffffffff81198856>] aio_run_iocb+0x66/0x1a0
+ [<ffffffff811998b8>] do_io_submit+0x708/0xb90
+ [<ffffffff81199d50>] sys_io_submit+0x10/0x20
+ [<ffffffff81a18d69>] system_call_fastpath+0x16/0x1b
+
+The explanation is in the comment within the code:
+
+We need to do this because the pages shared by the frontend
+(xen-blkfront) can be already locked (lock_page, called by
+do_read_cache_page); when the userspace backend tries to use them
+with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
+do_blockdev_direct_IO is going to try to lock the same pages
+again resulting in a deadlock.
+
+A simplified call graph looks like this:
+
+pygrub QEMU
+-----------------------------------------------
+do_read_cache_page io_submit
+ | |
+lock_page ext3_direct_IO
+ |
+ bio_add_page
+ |
+ lock_page
+
+Internally the xen-blkback uses m2p_add_override to swizzle (temporarily)
+a 'struct page' to have a different MFN (so that it can point to another
+guest). It also can easily find out whether another pfn corresponding
+to the mfn exists in the m2p, and can set the FOREIGN bit
+in the p2m, making sure that mfn_to_pfn returns the pfn of the backend.
+
+This allows the backend to perform direct_IO on these pages, but as a
+side effect prevents the frontend from using get_user_pages_fast on
+them while they are being shared with the backend.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ arch/x86/xen/p2m.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+--- a/arch/x86/xen/p2m.c
++++ b/arch/x86/xen/p2m.c
+@@ -686,6 +686,7 @@ int m2p_add_override(unsigned long mfn,
+ unsigned long uninitialized_var(address);
+ unsigned level;
+ pte_t *ptep = NULL;
++ int ret = 0;
+
+ pfn = page_to_pfn(page);
+ if (!PageHighMem(page)) {
+@@ -721,6 +722,24 @@ int m2p_add_override(unsigned long mfn,
+ list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
+ spin_unlock_irqrestore(&m2p_override_lock, flags);
+
++ /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in
++ * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other
++ * pfn so that the following mfn_to_pfn(mfn) calls will return the
++ * pfn from the m2p_override (the backend pfn) instead.
++ * We need to do this because the pages shared by the frontend
++ * (xen-blkfront) can be already locked (lock_page, called by
++ * do_read_cache_page); when the userspace backend tries to use them
++ * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
++ * do_blockdev_direct_IO is going to try to lock the same pages
++ * again resulting in a deadlock.
++ * As a side effect get_user_pages_fast might not be safe on the
++ * frontend pages while they are being shared with the backend,
++ * because mfn_to_pfn (that ends up being called by GUPF) will
++ * return the backend pfn rather than the frontend pfn. */
++ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
++ if (ret == 0 && get_phys_to_machine(pfn) == mfn)
++ set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(m2p_add_override);
+@@ -732,6 +751,7 @@ int m2p_remove_override(struct page *pag
+ unsigned long uninitialized_var(address);
+ unsigned level;
+ pte_t *ptep = NULL;
++ int ret = 0;
+
+ pfn = page_to_pfn(page);
+ mfn = get_phys_to_machine(pfn);
+@@ -801,6 +821,22 @@ int m2p_remove_override(struct page *pag
+ } else
+ set_phys_to_machine(pfn, page->index);
+
++ /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
++ * somewhere in this domain, even before being added to the
++ * m2p_override (see comment above in m2p_add_override).
++ * If there are no other entries in the m2p_override corresponding
++ * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for
++ * the original pfn (the one shared by the frontend): the backend
++ * cannot do any IO on this page anymore because it has been
++ * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of
++ * the original pfn causes mfn_to_pfn(mfn) to return the frontend
++ * pfn again. */
++ mfn &= ~FOREIGN_FRAME_BIT;
++ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
++ if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
++ m2p_find_override(mfn) == NULL)
++ set_phys_to_machine(pfn, mfn);
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(m2p_remove_override);
+From 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Date: Mon, 2 Jul 2012 13:36:23 -0700
+Subject: xhci: Add Etron XHCI_TRUST_TX_LENGTH quirk.
+
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+
+commit 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 upstream.
+
+Gary reports that with recent kernels, he notices more xHCI driver
+warnings:
+
+xhci_hcd 0000:03:00.0: WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?
+
+We think his Etron xHCI host controller may have the same buggy behavior
+as the Fresco Logic xHCI host. When a short transfer is received, the
+host will mark the transfer as successfully completed when it should be
+marking it with a short completion.
+
+Fix this by turning on the XHCI_TRUST_TX_LENGTH quirk when the Etron
+host is discovered. Note that Gary has revision 1, but if Etron fixes
+this bug in future revisions, the quirk will have no effect.
+
+This patch should be backported to kernels as old as 2.6.36, that
+contain a backported version of commit
+1530bbc6272d9da1e39ef8e06190d42c13a02733 "xhci: Add new short TX quirk
+for Fresco Logic host."
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Reported-by: Gary E. Miller <gem at rellim.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -95,6 +95,7 @@ static void xhci_pci_quirks(struct devic
+ pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
+ xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
++ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+ }
+ if (pdev->vendor == PCI_VENDOR_ID_VIA)
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
+From 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Date: Thu, 26 Jul 2012 12:03:59 -0700
+Subject: xhci: Fix bug after deq ptr set to link TRB.
+
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+
+commit 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 upstream.
+
+This patch fixes a particularly nasty bug that was revealed by the ring
+expansion patches. The bug has been present since the very beginning of
+the xHCI driver history, and could have caused general protection faults
+from bad memory accesses.
+
+The first thing to note is that a Set TR Dequeue Pointer command can
+move the dequeue pointer to a link TRB, if the canceled or stalled
+transfer TD ended just before a link TRB. The function to increment the
+dequeue pointer, inc_deq, was written before cancellation and stall
+support was added. It assumed that the dequeue pointer could never
+point to a link TRB. It would unconditionally increment the dequeue
+pointer at the start of the function, check if the pointer was now on a
+link TRB, and move it to the top of the next segment if so.
+
+This means that if a Set TR Dequeue Point command moved the dequeue
+pointer to a link TRB, a subsequent call to inc_deq() would move the
+pointer off the segment and into la-la-land. It would then read from
+that memory to determine if it was a link TRB. Other functions would
+often call inc_deq() until the dequeue pointer matched some other
+pointer, which means this function would quite happily read all of
+system memory before wrapping around to the right pointer value.
+
+Often, there would be another endpoint segment from a different ring
+allocated from the same DMA pool, which would be contiguous to the
+segment inc_deq just stepped off of. inc_deq would eventually find the
+link TRB in that segment, and blindly move the dequeue pointer back to
+the top of the correct ring segment.
+
+The only reason the original code worked at all is because there was
+only one ring segment. With the ring expansion patches, the dequeue
+pointer would eventually wrap into place, but the dequeue segment would
+be out-of-sync. On the second TD after the dequeue pointer was moved to
+a link TRB, trb_in_td() would fail (because the dequeue pointer and
+dequeue segment were out-of-sync), and this message would appear:
+
+ERROR Transfer event TRB DMA ptr not part of current TD
+
+This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0
+port: "Transfer event TRB DMA ptr not part of current TD", "rejecting
+I/O to offline device"),
+
+ https://bugzilla.kernel.org/show_bug.cgi?id=43333
+
+and possibly other general protection fault bugs as well.
+
+This patch should be backported to kernels as old as 2.6.31. A separate
+patch will be created for kernels older than 3.4, since inc_deq was
+modified in 3.4 and this patch will not apply.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Tested-by: James Ettle <theholyettlz at googlemail.com>
+Tested-by: Matthew Hall <mhall at mhcomputing.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xh
+ */
+ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
+ {
+- union xhci_trb *next;
+ unsigned long long addr;
+
+ ring->deq_updates++;
+
+- /* If this is not event ring, there is one more usable TRB */
++ /*
++ * If this is not event ring, and the dequeue pointer
++ * is not on a link TRB, there is one more usable TRB
++ */
+ if (ring->type != TYPE_EVENT &&
+ !last_trb(xhci, ring, ring->deq_seg, ring->dequeue))
+ ring->num_trbs_free++;
+- next = ++(ring->dequeue);
+
+- /* Update the dequeue pointer further if that was a link TRB or we're at
+- * the end of an event ring segment (which doesn't have link TRBS)
+- */
+- while (last_trb(xhci, ring, ring->deq_seg, next)) {
+- if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci,
+- ring, ring->deq_seg, next)) {
+- ring->cycle_state = (ring->cycle_state ? 0 : 1);
++ do {
++ /*
++ * Update the dequeue pointer further if that was a link TRB or
++ * we're at the end of an event ring segment (which doesn't have
++ * link TRBS)
++ */
++ if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) {
++ if (ring->type == TYPE_EVENT &&
++ last_trb_on_last_seg(xhci, ring,
++ ring->deq_seg, ring->dequeue)) {
++ ring->cycle_state = (ring->cycle_state ? 0 : 1);
++ }
++ ring->deq_seg = ring->deq_seg->next;
++ ring->dequeue = ring->deq_seg->trbs;
++ } else {
++ ring->dequeue++;
+ }
+- ring->deq_seg = ring->deq_seg->next;
+- ring->dequeue = ring->deq_seg->trbs;
+- next = ring->dequeue;
+- }
++ } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue));
++
+ addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
+ }
+
+From 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Date: Mon, 23 Jul 2012 16:06:08 -0700
+Subject: xhci: Increase reset timeout for Renesas 720201 host.
+
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+
+commit 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b upstream.
+
+The NEC/Renesas 720201 xHCI host controller does not complete its reset
+within 250 milliseconds. In fact, it takes about 9 seconds to reset the
+host controller, and 1 second for the host to be ready for doorbell
+rings. Extend the reset and CNR polling timeout to 10 seconds each.
+
+This patch should be backported to kernels as old as 2.6.31, that
+contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci:
+BIOS handoff and HW initialization."
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Reported-by: Edwin Klein Mentink <e.kleinmentink at zonnet.nl>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci)
+ xhci_writel(xhci, command, &xhci->op_regs->command);
+
+ ret = handshake(xhci, &xhci->op_regs->command,
+- CMD_RESET, 0, 250 * 1000);
++ CMD_RESET, 0, 10 * 1000 * 1000);
+ if (ret)
+ return ret;
+
+@@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci)
+ * xHCI cannot write to any doorbells or operational registers other
+ * than status until the "Controller Not Ready" flag is cleared.
+ */
+- ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
++ ret = handshake(xhci, &xhci->op_regs->status,
++ STS_CNR, 0, 10 * 1000 * 1000);
+
+ for (i = 0; i < 2; ++i) {
+ xhci->bus_state[i].port_c_suspend = 0;
+From e95829f474f0db3a4d940cae1423783edd966027 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Date: Mon, 23 Jul 2012 18:59:30 +0300
+Subject: xhci: Switch PPT ports to EHCI on shutdown.
+
+From: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+
+commit e95829f474f0db3a4d940cae1423783edd966027 upstream.
+
+The Intel desktop boards DH77EB and DH77DF have a hardware issue that
+can be worked around by BIOS. If the USB ports are switched to xHCI on
+shutdown, the xHCI host will send a spurious interrupt, which will wake
+the system. Some BIOS will work around this, but not all.
+
+The bug can be avoided if the USB ports are switched back to EHCI on
+shutdown. The Intel Windows driver switches the ports back to EHCI, so
+change the Linux xHCI driver to do the same.
+
+Unfortunately, we can't tell the two effected boards apart from other
+working motherboards, because the vendors will change the DMI strings
+for the DH77EB and DH77DF boards to their own custom names. One example
+is Compulab's mini-desktop, the Intense-PC. Instead, key off the
+Panther Point xHCI host PCI vendor and device ID, and switch the ports
+over for all PPT xHCI hosts.
+
+The only impact this will have on non-effected boards is to add a couple
+hundred milliseconds delay on boot when the BIOS has to switch the ports
+over from EHCI to xHCI.
+
+This patch should be backported to kernels as old as 3.0, that contain
+the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support
+EHCI/xHCI port switching."
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Reported-by: Denis Turischev <denis at compulab.co.il>
+Tested-by: Denis Turischev <denis at compulab.co.il>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+---
+ drivers/usb/host/pci-quirks.c | 7 +++++++
+ drivers/usb/host/pci-quirks.h | 1 +
+ drivers/usb/host/xhci-pci.c | 9 +++++++++
+ drivers/usb/host/xhci.c | 3 +++
+ drivers/usb/host/xhci.h | 1 +
+ 5 files changed, 21 insertions(+)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -800,6 +800,13 @@ void usb_enable_xhci_ports(struct pci_de
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_xhci_ports);
+
++void usb_disable_xhci_ports(struct pci_dev *xhci_pdev)
++{
++ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0);
++ pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0);
++}
++EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);
++
+ /**
+ * PCI Quirks for xHCI.
+ *
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -10,6 +10,7 @@ void usb_amd_quirk_pll_disable(void);
+ void usb_amd_quirk_pll_enable(void);
+ bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
+ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
++void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+ #else
+ static inline void usb_amd_quirk_pll_disable(void) {}
+ static inline void usb_amd_quirk_pll_enable(void) {}
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -90,6 +90,15 @@ static void xhci_pci_quirks(struct devic
+ xhci->quirks |= XHCI_EP_LIMIT_QUIRK;
+ xhci->limit_active_eps = 64;
+ xhci->quirks |= XHCI_SW_BW_CHECKING;
++ /*
++ * PPT desktop boards DH77EB and DH77DF will power back on after
++ * a few seconds of being shutdown. The fix for this is to
++ * switch the ports from xHCI to EHCI on shutdown. We can't use
++ * DMI information to find those particular boards (since each
++ * vendor will change the board name), so we have to key off all
++ * PPT chipsets.
++ */
++ xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+ }
+ if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
+ pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -659,6 +659,9 @@ void xhci_shutdown(struct usb_hcd *hcd)
+ {
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
++ if (xhci->quirks && XHCI_SPURIOUS_REBOOT)
++ usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
++
+ spin_lock_irq(&xhci->lock);
+ xhci_halt(xhci);
+ spin_unlock_irq(&xhci->lock);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1486,6 +1486,7 @@ struct xhci_hcd {
+ #define XHCI_SW_BW_CHECKING (1 << 8)
+ #define XHCI_AMD_0x96_HOST (1 << 9)
+ #define XHCI_TRUST_TX_LENGTH (1 << 10)
++#define XHCI_SPURIOUS_REBOOT (1 << 13)
+ unsigned int num_active_eps;
+ unsigned int limit_active_eps;
+ /* There are two roothubs to keep track of bus suspend info for */
More information about the scm-commits
mailing list