[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