]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Mar 2012 23:13:18 +0000 (16:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Mar 2012 23:13:18 +0000 (16:13 -0700)
added patches:
asoc-fsl-p1022ds-tell-the-wm8776-codec-driver-that-it-s-the-master.patch
asoc-pxa-ssp-atomically-set-stream-active-masks.patch
bluetooth-add-ar30xx-device-id-on-asus-laptops.patch
bootmem-sparsemem-remove-limit-constraint-in-alloc_bootmem_section.patch
drm-radeon-kms-add-connector-quirk-for-fujitsu-d3003-s2-board.patch
drm-radeon-kms-fix-analog-load-detection-on-dvi-i-connectors.patch
drm-radeon-restrict-offset-for-legacy-hardware-cursor.patch
hid-add-extra-hotkeys-in-asus-aio-keyboards.patch
hid-add-more-hotkeys-in-asus-aio-keyboards.patch
hugetlbfs-avoid-taking-i_mutex-from-hugetlbfs_read.patch
md-bitmap-ensure-to-load-bitmap-when-creating-via-sysfs.patch
md-raid1-raid10-avoid-deadlock-during-resync-recovery.patch
target-don-t-set-wbus16-or-sync-bits-in-inquiry-response.patch
target-fix-16-bit-target-ports-for-set-target-port-groups-emulation.patch
tcm_fc-fix-fc_exch-memory-leak-in-ft_send_resp_status.patch
tcm_loop-set-residual-field-for-scsi-commands.patch
udlfb-remove-sysfs-framebuffer-device-with-usb-.disconnect.patch

19 files changed:
queue-3.0/asoc-fsl-p1022ds-tell-the-wm8776-codec-driver-that-it-s-the-master.patch [new file with mode: 0644]
queue-3.0/asoc-pxa-ssp-atomically-set-stream-active-masks.patch [new file with mode: 0644]
queue-3.0/bluetooth-add-ar30xx-device-id-on-asus-laptops.patch [new file with mode: 0644]
queue-3.0/bootmem-sparsemem-remove-limit-constraint-in-alloc_bootmem_section.patch [new file with mode: 0644]
queue-3.0/drm-radeon-kms-add-connector-quirk-for-fujitsu-d3003-s2-board.patch [new file with mode: 0644]
queue-3.0/drm-radeon-kms-fix-analog-load-detection-on-dvi-i-connectors.patch [new file with mode: 0644]
queue-3.0/drm-radeon-restrict-offset-for-legacy-hardware-cursor.patch [new file with mode: 0644]
queue-3.0/hid-add-extra-hotkeys-in-asus-aio-keyboards.patch [new file with mode: 0644]
queue-3.0/hid-add-more-hotkeys-in-asus-aio-keyboards.patch [new file with mode: 0644]
queue-3.0/hugetlbfs-avoid-taking-i_mutex-from-hugetlbfs_read.patch [new file with mode: 0644]
queue-3.0/md-bitmap-ensure-to-load-bitmap-when-creating-via-sysfs.patch [new file with mode: 0644]
queue-3.0/md-raid1-raid10-avoid-deadlock-during-resync-recovery.patch [new file with mode: 0644]
queue-3.0/rtnetlink-fix-vf-ifla-policy.patch [deleted file]
queue-3.0/series
queue-3.0/target-don-t-set-wbus16-or-sync-bits-in-inquiry-response.patch [new file with mode: 0644]
queue-3.0/target-fix-16-bit-target-ports-for-set-target-port-groups-emulation.patch [new file with mode: 0644]
queue-3.0/tcm_fc-fix-fc_exch-memory-leak-in-ft_send_resp_status.patch [new file with mode: 0644]
queue-3.0/tcm_loop-set-residual-field-for-scsi-commands.patch [new file with mode: 0644]
queue-3.0/udlfb-remove-sysfs-framebuffer-device-with-usb-.disconnect.patch [new file with mode: 0644]

diff --git a/queue-3.0/asoc-fsl-p1022ds-tell-the-wm8776-codec-driver-that-it-s-the-master.patch b/queue-3.0/asoc-fsl-p1022ds-tell-the-wm8776-codec-driver-that-it-s-the-master.patch
new file mode 100644 (file)
index 0000000..33744af
--- /dev/null
@@ -0,0 +1,86 @@
+From 70ac07bb633dee75ac554195b9a4d69adfa7803c Mon Sep 17 00:00:00 2001
+From: Timur Tabi <timur@freescale.com>
+Date: Fri, 16 Mar 2012 16:32:52 -0500
+Subject: ASoC: fsl: p1022ds: tell the WM8776 codec driver that it's the master
+
+From: Timur Tabi <timur@freescale.com>
+
+commit 70ac07bb633dee75ac554195b9a4d69adfa7803c upstream.
+
+The WM8776 codec driver requires the machine driver to set one of the
+SND_SOC_DAIFMT_CBx_xxx values.  The P1022DS machine driver should be setting
+SND_SOC_DAIFMT_CBM_CFM, but since that value was zero, no one noticed.
+
+Commit 75d9ac46 ("ASoC: Allow DAI formats to be specified in the
+dai_link"), however, changed the value of SND_SOC_DAIFMT_CBM_CFM from zero
+to a non-zero value, which means that it now needs to be specifically set
+by the machine driver.
+
+We also set SND_SOC_DAIFMT_NB_NF, for the same reason.
+
+Signed-off-by: Timur Tabi <timur@freescale.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/fsl/p1022_ds.c |   24 ++++++++++++++++--------
+ 1 file changed, 16 insertions(+), 8 deletions(-)
+
+--- a/sound/soc/fsl/p1022_ds.c
++++ b/sound/soc/fsl/p1022_ds.c
+@@ -390,7 +390,8 @@ static int p1022_ds_probe(struct platfor
+       }
+       if (strcasecmp(sprop, "i2s-slave") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_I2S;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+@@ -407,31 +408,38 @@ static int p1022_ds_probe(struct platfor
+               }
+               mdata->clk_frequency = *iprop;
+       } else if (strcasecmp(sprop, "i2s-master") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_I2S;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else if (strcasecmp(sprop, "lj-slave") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+       } else if (strcasecmp(sprop, "lj-master") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else if (strcasecmp(sprop, "rj-slave") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+       } else if (strcasecmp(sprop, "rj-master") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else if (strcasecmp(sprop, "ac97-slave") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_AC97;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+       } else if (strcasecmp(sprop, "ac97-master") == 0) {
+-              mdata->dai_format = SND_SOC_DAIFMT_AC97;
++              mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else {
diff --git a/queue-3.0/asoc-pxa-ssp-atomically-set-stream-active-masks.patch b/queue-3.0/asoc-pxa-ssp-atomically-set-stream-active-masks.patch
new file mode 100644 (file)
index 0000000..e882014
--- /dev/null
@@ -0,0 +1,120 @@
+From 273b72c8ce6b28df6b49423d775c3e59072c73c5 Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Mon, 19 Mar 2012 09:12:53 +0100
+Subject: ASoC: pxa-ssp: atomically set stream active masks
+
+From: Daniel Mack <zonque@gmail.com>
+
+commit 273b72c8ce6b28df6b49423d775c3e59072c73c5 upstream.
+
+PXA's SSP engine fails to take its current channel phase into account
+when enabling a stream while the engine is already running. This
+results in randomly swapped left/right channels on either the record
+or the playback side, depending on which one was enabled first.
+
+The following patch fixes this by factoring out the bit field
+modifications in question to a separate function that pauses the
+engine temporarily, modifies the bits and kicks it off again
+afterwards. Appearantly, a transition of SSCR0_SSE syncs both
+directions properly.
+
+The patch has been rolled out to quite a number of devices over the
+last weeks and seems to fix the issue reliably.
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+Reported-and-tested-by: Sven Neumann <s.neumann@raumfeld.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/pxa/pxa-ssp.c |   61 ++++++++++++++++++++++++++++--------------------
+ 1 file changed, 36 insertions(+), 25 deletions(-)
+
+--- a/sound/soc/pxa/pxa-ssp.c
++++ b/sound/soc/pxa/pxa-ssp.c
+@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_
+       return 0;
+ }
++static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
++                                  struct ssp_device *ssp, int value)
++{
++      uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
++      uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
++      uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
++      uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
++
++      if (value && (sscr0 & SSCR0_SSE))
++              pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
++
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++              if (value)
++                      sscr1 |= SSCR1_TSRE;
++              else
++                      sscr1 &= ~SSCR1_TSRE;
++      } else {
++              if (value)
++                      sscr1 |= SSCR1_RSRE;
++              else
++                      sscr1 &= ~SSCR1_RSRE;
++      }
++
++      pxa_ssp_write_reg(ssp, SSCR1, sscr1);
++
++      if (value) {
++              pxa_ssp_write_reg(ssp, SSSR, sssr);
++              pxa_ssp_write_reg(ssp, SSPSP, sspsp);
++              pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
++      }
++}
++
+ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
+                          struct snd_soc_dai *cpu_dai)
+ {
+@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pc
+               pxa_ssp_enable(ssp);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+-              val = pxa_ssp_read_reg(ssp, SSCR1);
+-              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+-                      val |= SSCR1_TSRE;
+-              else
+-                      val |= SSCR1_RSRE;
+-              pxa_ssp_write_reg(ssp, SSCR1, val);
++              pxa_ssp_set_running_bit(substream, ssp, 1);
+               val = pxa_ssp_read_reg(ssp, SSSR);
+               pxa_ssp_write_reg(ssp, SSSR, val);
+               break;
+       case SNDRV_PCM_TRIGGER_START:
+-              val = pxa_ssp_read_reg(ssp, SSCR1);
+-              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+-                      val |= SSCR1_TSRE;
+-              else
+-                      val |= SSCR1_RSRE;
+-              pxa_ssp_write_reg(ssp, SSCR1, val);
+-              pxa_ssp_enable(ssp);
++              pxa_ssp_set_running_bit(substream, ssp, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+-              val = pxa_ssp_read_reg(ssp, SSCR1);
+-              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+-                      val &= ~SSCR1_TSRE;
+-              else
+-                      val &= ~SSCR1_RSRE;
+-              pxa_ssp_write_reg(ssp, SSCR1, val);
++              pxa_ssp_set_running_bit(substream, ssp, 0);
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               pxa_ssp_disable(ssp);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+-              val = pxa_ssp_read_reg(ssp, SSCR1);
+-              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+-                      val &= ~SSCR1_TSRE;
+-              else
+-                      val &= ~SSCR1_RSRE;
+-              pxa_ssp_write_reg(ssp, SSCR1, val);
++              pxa_ssp_set_running_bit(substream, ssp, 0);
+               break;
+       default:
diff --git a/queue-3.0/bluetooth-add-ar30xx-device-id-on-asus-laptops.patch b/queue-3.0/bluetooth-add-ar30xx-device-id-on-asus-laptops.patch
new file mode 100644 (file)
index 0000000..5c94fff
--- /dev/null
@@ -0,0 +1,63 @@
+From 6b6ba88b5bb8779156b21bb957520a448c3642e2 Mon Sep 17 00:00:00 2001
+From: Keng-Yu Lin <kengyu@canonical.com>
+Date: Wed, 30 Nov 2011 18:32:37 +0800
+Subject: Bluetooth: Add AR30XX device ID on Asus laptops
+
+From: Keng-Yu Lin <kengyu@canonical.com>
+
+commit 6b6ba88b5bb8779156b21bb957520a448c3642e2 upstream.
+
+The ID is found on Asus K54HR and K53U.
+Blacklist the AR3011-based device ID [0489:e03d]
+and add to ath3k.c for firmware loading.
+
+Below is the output of usb-devices script:
+
+Before the fiwmware loading:
+
+T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=12  MxCh= 0
+D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
+P:  Vendor=0489 ProdID=e03d Rev=00.01
+C:  #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+I:  If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+
+After the fiwmware loading:
+
+T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  5 Spd=12  MxCh= 0
+D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
+P:  Vendor=0cf3 ProdID=3005 Rev=00.01
+C:  #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+I:  If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+
+Signed-off-by: Keng-Yu Lin <kengyu@canonical.com>
+Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
+Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/bluetooth/ath3k.c |    1 +
+ drivers/bluetooth/btusb.c |    1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/bluetooth/ath3k.c
++++ b/drivers/bluetooth/ath3k.c
+@@ -64,6 +64,7 @@ static struct usb_device_id ath3k_table[
+       { USB_DEVICE(0x0CF3, 0x3002) },
+       { USB_DEVICE(0x13d3, 0x3304) },
+       { USB_DEVICE(0x0930, 0x0215) },
++      { USB_DEVICE(0x0489, 0xE03D) },
+       /* Atheros AR9285 Malbec with sflash firmware */
+       { USB_DEVICE(0x03F0, 0x311D) },
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -116,6 +116,7 @@ static struct usb_device_id blacklist_ta
+       { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
++      { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+       /* Atheros AR9285 Malbec with sflash firmware */
+       { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
diff --git a/queue-3.0/bootmem-sparsemem-remove-limit-constraint-in-alloc_bootmem_section.patch b/queue-3.0/bootmem-sparsemem-remove-limit-constraint-in-alloc_bootmem_section.patch
new file mode 100644 (file)
index 0000000..a94f312
--- /dev/null
@@ -0,0 +1,142 @@
+From f5bf18fa22f8c41a13eb8762c7373eb3a93a7333 Mon Sep 17 00:00:00 2001
+From: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
+Date: Wed, 21 Mar 2012 16:34:07 -0700
+Subject: bootmem/sparsemem: remove limit constraint in alloc_bootmem_section
+
+From: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
+
+commit f5bf18fa22f8c41a13eb8762c7373eb3a93a7333 upstream.
+
+While testing AMS (Active Memory Sharing) / CMO (Cooperative Memory
+Overcommit) on powerpc, we tripped the following:
+
+  kernel BUG at mm/bootmem.c:483!
+  cpu 0x0: Vector: 700 (Program Check) at [c000000000c03940]
+      pc: c000000000a62bd8: .alloc_bootmem_core+0x90/0x39c
+      lr: c000000000a64bcc: .sparse_early_usemaps_alloc_node+0x84/0x29c
+      sp: c000000000c03bc0
+     msr: 8000000000021032
+    current = 0xc000000000b0cce0
+    paca    = 0xc000000001d80000
+      pid   = 0, comm = swapper
+  kernel BUG at mm/bootmem.c:483!
+  enter ? for help
+  [c000000000c03c80] c000000000a64bcc
+  .sparse_early_usemaps_alloc_node+0x84/0x29c
+  [c000000000c03d50] c000000000a64f10 .sparse_init+0x12c/0x28c
+  [c000000000c03e20] c000000000a474f4 .setup_arch+0x20c/0x294
+  [c000000000c03ee0] c000000000a4079c .start_kernel+0xb4/0x460
+  [c000000000c03f90] c000000000009670 .start_here_common+0x1c/0x2c
+
+This is
+
+        BUG_ON(limit && goal + size > limit);
+
+and after some debugging, it seems that
+
+       goal = 0x7ffff000000
+       limit = 0x80000000000
+
+and sparse_early_usemaps_alloc_node ->
+sparse_early_usemaps_alloc_pgdat_section calls
+
+       return alloc_bootmem_section(usemap_size() * count, section_nr);
+
+This is on a system with 8TB available via the AMS pool, and as a quirk
+of AMS in firmware, all of that memory shows up in node 0.  So, we end
+up with an allocation that will fail the goal/limit constraints.
+
+In theory, we could "fall-back" to alloc_bootmem_node() in
+sparse_early_usemaps_alloc_node(), but since we actually have HOTREMOVE
+defined, we'll BUG_ON() instead.  A simple solution appears to be to
+unconditionally remove the limit condition in alloc_bootmem_section,
+meaning allocations are allowed to cross section boundaries (necessary
+for systems of this size).
+
+Johannes Weiner pointed out that if alloc_bootmem_section() no longer
+guarantees section-locality, we need check_usemap_section_nr() to print
+possible cross-dependencies between node descriptors and the usemaps
+allocated through it.  That makes the two loops in
+sparse_early_usemaps_alloc_node() identical, so re-factor the code a
+bit.
+
+[akpm@linux-foundation.org: code simplification]
+Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
+Cc: Dave Hansen <haveblue@us.ibm.com>
+Cc: Anton Blanchard <anton@au1.ibm.com>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: Ben Herrenschmidt <benh@kernel.crashing.org>
+Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Acked-by: Mel Gorman <mgorman@suse.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/bootmem.c |    5 ++---
+ mm/sparse.c  |   30 +++++++++++-------------------
+ 2 files changed, 13 insertions(+), 22 deletions(-)
+
+--- a/mm/bootmem.c
++++ b/mm/bootmem.c
+@@ -768,14 +768,13 @@ void * __init alloc_bootmem_section(unsi
+                                   unsigned long section_nr)
+ {
+       bootmem_data_t *bdata;
+-      unsigned long pfn, goal, limit;
++      unsigned long pfn, goal;
+       pfn = section_nr_to_pfn(section_nr);
+       goal = pfn << PAGE_SHIFT;
+-      limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
+       bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
+-      return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
++      return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0);
+ }
+ #endif
+--- a/mm/sparse.c
++++ b/mm/sparse.c
+@@ -353,29 +353,21 @@ static void __init sparse_early_usemaps_
+       usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid),
+                                                                usemap_count);
+-      if (usemap) {
+-              for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+-                      if (!present_section_nr(pnum))
+-                              continue;
+-                      usemap_map[pnum] = usemap;
+-                      usemap += size;
++      if (!usemap) {
++              usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
++              if (!usemap) {
++                      printk(KERN_WARNING "%s: allocation failed\n", __func__);
++                      return;
+               }
+-              return;
+       }
+-      usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
+-      if (usemap) {
+-              for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+-                      if (!present_section_nr(pnum))
+-                              continue;
+-                      usemap_map[pnum] = usemap;
+-                      usemap += size;
+-                      check_usemap_section_nr(nodeid, usemap_map[pnum]);
+-              }
+-              return;
++      for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
++              if (!present_section_nr(pnum))
++                      continue;
++              usemap_map[pnum] = usemap;
++              usemap += size;
++              check_usemap_section_nr(nodeid, usemap_map[pnum]);
+       }
+-
+-      printk(KERN_WARNING "%s: allocation failed\n", __func__);
+ }
+ #ifndef CONFIG_SPARSEMEM_VMEMMAP
diff --git a/queue-3.0/drm-radeon-kms-add-connector-quirk-for-fujitsu-d3003-s2-board.patch b/queue-3.0/drm-radeon-kms-add-connector-quirk-for-fujitsu-d3003-s2-board.patch
new file mode 100644 (file)
index 0000000..76b5930
--- /dev/null
@@ -0,0 +1,45 @@
+From 4c1b2d2da3451f5c8dd59bd7e05bd9729d2aee05 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 16 Mar 2012 12:22:10 -0400
+Subject: drm/radeon/kms: add connector quirk for Fujitsu D3003-S2 board
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 4c1b2d2da3451f5c8dd59bd7e05bd9729d2aee05 upstream.
+
+vbios lists DVI-I port as VGA and DVI-D.
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=47007
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/radeon_atombios.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_atombios.c
++++ b/drivers/gpu/drm/radeon/radeon_atombios.c
+@@ -484,6 +484,20 @@ static bool radeon_atom_apply_quirks(str
+               struct radeon_device *rdev = dev->dev_private;
+               *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
+       }
++
++      /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
++      if ((dev->pdev->device == 0x9802) &&
++          (dev->pdev->subsystem_vendor == 0x1734) &&
++          (dev->pdev->subsystem_device == 0x11bd)) {
++              if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
++                      *connector_type = DRM_MODE_CONNECTOR_DVII;
++                      *line_mux = 0x3103;
++              } else if (*connector_type == DRM_MODE_CONNECTOR_DVID) {
++                      *connector_type = DRM_MODE_CONNECTOR_DVII;
++              }
++      }
++
++
+       return true;
+ }
diff --git a/queue-3.0/drm-radeon-kms-fix-analog-load-detection-on-dvi-i-connectors.patch b/queue-3.0/drm-radeon-kms-fix-analog-load-detection-on-dvi-i-connectors.patch
new file mode 100644 (file)
index 0000000..7bdc10f
--- /dev/null
@@ -0,0 +1,37 @@
+From e00e8b5e760cbbe9067daeae5454d67c44c8d035 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 16 Mar 2012 12:22:09 -0400
+Subject: drm/radeon/kms: fix analog load detection on DVI-I connectors
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit e00e8b5e760cbbe9067daeae5454d67c44c8d035 upstream.
+
+We digital encoders have a detect function as well (for
+DP to VGA bridges), so we make sure we choose the analog
+one here.
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=47007
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/radeon_connectors.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_connectors.c
++++ b/drivers/gpu/drm/radeon/radeon_connectors.c
+@@ -990,6 +990,10 @@ radeon_dvi_detect(struct drm_connector *
+                       encoder = obj_to_encoder(obj);
++                      if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
++                          encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
++                              continue;
++
+                       encoder_funcs = encoder->helper_private;
+                       if (encoder_funcs->detect) {
+                               if (ret != connector_status_connected) {
diff --git a/queue-3.0/drm-radeon-restrict-offset-for-legacy-hardware-cursor.patch b/queue-3.0/drm-radeon-restrict-offset-for-legacy-hardware-cursor.patch
new file mode 100644 (file)
index 0000000..e0e3be1
--- /dev/null
@@ -0,0 +1,124 @@
+From c4353016dac10133fa5d8535af83f0c4845a2915 Mon Sep 17 00:00:00 2001
+From: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed, 14 Mar 2012 17:12:41 +0100
+Subject: drm/radeon: Restrict offset for legacy hardware cursor.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michel Dänzer <michel.daenzer@amd.com>
+
+commit c4353016dac10133fa5d8535af83f0c4845a2915 upstream.
+
+The hardware only takes 27 bits for the offset, so larger offsets are
+truncated, and the hardware cursor shows random bits other than the intended
+ones.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=46796
+
+Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+---
+ drivers/gpu/drm/radeon/radeon_cursor.c |   13 +++++++++++--
+ drivers/gpu/drm/radeon/radeon_object.c |   18 +++++++++++++++++-
+ drivers/gpu/drm/radeon/radeon_object.h |    2 ++
+ 3 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon_cursor.c
++++ b/drivers/gpu/drm/radeon/radeon_cursor.c
+@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_cr
+                          uint32_t height)
+ {
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
++      struct radeon_device *rdev = crtc->dev->dev_private;
+       struct drm_gem_object *obj;
++      struct radeon_bo *robj;
+       uint64_t gpu_addr;
+       int ret;
+@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_cr
+               return -ENOENT;
+       }
+-      ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
++      robj = gem_to_radeon_bo(obj);
++      ret = radeon_bo_reserve(robj, false);
++      if (unlikely(ret != 0))
++              goto fail;
++      /* Only 27 bit offset for legacy cursor */
++      ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
++                                     ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
++                                     &gpu_addr);
++      radeon_bo_unreserve(robj);
+       if (ret)
+               goto fail;
+@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_cr
+       radeon_crtc->cursor_height = height;
+       radeon_lock_cursor(crtc, true);
+-      /* XXX only 27 bit offset for legacy cursor */
+       radeon_set_cursor(crtc, obj, gpu_addr);
+       radeon_show_cursor(crtc);
+       radeon_lock_cursor(crtc, false);
+--- a/drivers/gpu/drm/radeon/radeon_object.c
++++ b/drivers/gpu/drm/radeon/radeon_object.c
+@@ -204,7 +204,8 @@ void radeon_bo_unref(struct radeon_bo **
+               *bo = NULL;
+ }
+-int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
++int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
++                           u64 *gpu_addr)
+ {
+       int r, i;
+@@ -212,6 +213,7 @@ int radeon_bo_pin(struct radeon_bo *bo,
+               bo->pin_count++;
+               if (gpu_addr)
+                       *gpu_addr = radeon_bo_gpu_offset(bo);
++              WARN_ON_ONCE(max_offset != 0);
+               return 0;
+       }
+       radeon_ttm_placement_from_domain(bo, domain);
+@@ -219,6 +221,15 @@ int radeon_bo_pin(struct radeon_bo *bo,
+               /* force to pin into visible video ram */
+               bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
+       }
++      if (max_offset) {
++              u64 lpfn = max_offset >> PAGE_SHIFT;
++
++              if (!bo->placement.lpfn)
++                      bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT;
++
++              if (lpfn < bo->placement.lpfn)
++                      bo->placement.lpfn = lpfn;
++      }
+       for (i = 0; i < bo->placement.num_placement; i++)
+               bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
+       r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
+@@ -232,6 +243,11 @@ int radeon_bo_pin(struct radeon_bo *bo,
+       return r;
+ }
++int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
++{
++      return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr);
++}
++
+ int radeon_bo_unpin(struct radeon_bo *bo)
+ {
+       int r, i;
+--- a/drivers/gpu/drm/radeon/radeon_object.h
++++ b/drivers/gpu/drm/radeon/radeon_object.h
+@@ -144,6 +144,8 @@ extern int radeon_bo_kmap(struct radeon_
+ extern void radeon_bo_kunmap(struct radeon_bo *bo);
+ extern void radeon_bo_unref(struct radeon_bo **bo);
+ extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
++extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
++                                  u64 max_offset, u64 *gpu_addr);
+ extern int radeon_bo_unpin(struct radeon_bo *bo);
+ extern int radeon_bo_evict_vram(struct radeon_device *rdev);
+ extern void radeon_bo_force_delete(struct radeon_device *rdev);
diff --git a/queue-3.0/hid-add-extra-hotkeys-in-asus-aio-keyboards.patch b/queue-3.0/hid-add-extra-hotkeys-in-asus-aio-keyboards.patch
new file mode 100644 (file)
index 0000000..8aa952b
--- /dev/null
@@ -0,0 +1,65 @@
+From 3596bb929f2abd3433c2eaa5755fad48ac207af1 Mon Sep 17 00:00:00 2001
+From: Keng-Yu Lin <kengyu@canonical.com>
+Date: Thu, 2 Feb 2012 10:31:26 +0100
+Subject: HID: add extra hotkeys in Asus AIO keyboards
+
+From: Keng-Yu Lin <kengyu@canonical.com>
+
+commit 3596bb929f2abd3433c2eaa5755fad48ac207af1 upstream.
+
+The Asus All-In-One PC has a wireless keyboard with wifi toggle,
+brightness up, brightness down and display off hotkeys.
+
+This patch adds suppoort for these hotkeys.
+
+Signed-off-by: Keng-Yu Lin <kengyu@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-chicony.c |    5 +++++
+ drivers/hid/hid-core.c    |    1 +
+ drivers/hid/hid-ids.h     |    1 +
+ 3 files changed, 7 insertions(+)
+
+--- a/drivers/hid/hid-chicony.c
++++ b/drivers/hid/hid-chicony.c
+@@ -45,6 +45,10 @@ static int ch_input_mapping(struct hid_d
+       case 0xff09: ch_map_key_clear(BTN_9);   break;
+       case 0xff0a: ch_map_key_clear(BTN_A);   break;
+       case 0xff0b: ch_map_key_clear(BTN_B);   break;
++      case 0x00f1: ch_map_key_clear(KEY_WLAN);        break;
++      case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN);      break;
++      case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP);        break;
++      case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF); break;
+       default:
+               return 0;
+       }
+@@ -53,6 +57,7 @@ static int ch_input_mapping(struct hid_d
+ static const struct hid_device_id ch_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
+       { }
+ };
+ MODULE_DEVICE_TABLE(hid, ch_devices);
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1372,6 +1372,7 @@ static const struct hid_device_id hid_ha
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -189,6 +189,7 @@
+ #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD    0x0418
+ #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH     0xb19d
+ #define USB_DEVICE_ID_CHICONY_WIRELESS        0x0618
++#define USB_DEVICE_ID_CHICONY_WIRELESS2       0x1123
+ #define USB_VENDOR_ID_CHUNGHWAT               0x2247
+ #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH    0x0001
diff --git a/queue-3.0/hid-add-more-hotkeys-in-asus-aio-keyboards.patch b/queue-3.0/hid-add-more-hotkeys-in-asus-aio-keyboards.patch
new file mode 100644 (file)
index 0000000..6668cd5
--- /dev/null
@@ -0,0 +1,32 @@
+From 6c30d5a53229aad22bb675e0bd6eb518ecaa4316 Mon Sep 17 00:00:00 2001
+From: Keng-Yu Lin <kengyu@canonical.com>
+Date: Mon, 30 Jan 2012 14:25:45 +0800
+Subject: HID: add more hotkeys in Asus AIO keyboards
+
+From: Keng-Yu Lin <kengyu@canonical.com>
+
+commit 6c30d5a53229aad22bb675e0bd6eb518ecaa4316 upstream.
+
+Add support for the camera key. The hotkey for
+Asus S.H.E(Super Hybrid Engine) mode is mapped to KEY_KEY_PROG1
+just for notifying the userspace.
+
+Signed-off-by: Keng-Yu Lin <kengyu@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-chicony.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/hid/hid-chicony.c
++++ b/drivers/hid/hid-chicony.c
+@@ -49,6 +49,8 @@ static int ch_input_mapping(struct hid_d
+       case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN);      break;
+       case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP);        break;
+       case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF); break;
++      case 0x00f7: ch_map_key_clear(KEY_CAMERA);      break;
++      case 0x00f8: ch_map_key_clear(KEY_PROG1);       break;
+       default:
+               return 0;
+       }
diff --git a/queue-3.0/hugetlbfs-avoid-taking-i_mutex-from-hugetlbfs_read.patch b/queue-3.0/hugetlbfs-avoid-taking-i_mutex-from-hugetlbfs_read.patch
new file mode 100644 (file)
index 0000000..2ff5243
--- /dev/null
@@ -0,0 +1,137 @@
+From a05b0855fd15504972dba2358e5faa172a1e50ba Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+Date: Wed, 21 Mar 2012 16:34:08 -0700
+Subject: hugetlbfs: avoid taking i_mutex from hugetlbfs_read()
+
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+
+commit a05b0855fd15504972dba2358e5faa172a1e50ba upstream.
+
+Taking i_mutex in hugetlbfs_read() can result in deadlock with mmap as
+explained below
+
+ Thread A:
+  read() on hugetlbfs
+   hugetlbfs_read() called
+    i_mutex grabbed
+     hugetlbfs_read_actor() called
+      __copy_to_user() called
+       page fault is triggered
+ Thread B, sharing address space with A:
+  mmap() the same file
+   ->mmap_sem is grabbed on task_B->mm->mmap_sem
+    hugetlbfs_file_mmap() is called
+     attempt to grab ->i_mutex and block waiting for A to give it up
+ Thread A:
+  pagefault handled blocked on attempt to grab task_A->mm->mmap_sem,
+ which happens to be the same thing as task_B->mm->mmap_sem.  Block waiting
+ for B to give it up.
+
+AFAIU the i_mutex locking was added to hugetlbfs_read() as per
+http://lkml.indiana.edu/hypermail/linux/kernel/0707.2/3066.html to take
+care of the race between truncate and read.  This patch fixes this by
+looking at page->mapping under lock_page() (find_lock_page()) to ensure
+that the inode didn't get truncated in the range during a parallel read.
+
+Ideally we can extend the patch to make sure we don't increase i_size in
+mmap.  But that will break userspace, because applications will now have
+to use truncate(2) to increase i_size in hugetlbfs.
+
+Based on the original patch from Hillf Danton.
+
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+Cc: Hillf Danton <dhillf@gmail.com>
+Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Hugh Dickins <hughd@google.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/hugetlbfs/inode.c |   25 +++++++++----------------
+ 1 file changed, 9 insertions(+), 16 deletions(-)
+
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -238,17 +238,10 @@ static ssize_t hugetlbfs_read(struct fil
+       loff_t isize;
+       ssize_t retval = 0;
+-      mutex_lock(&inode->i_mutex);
+-
+       /* validate length */
+       if (len == 0)
+               goto out;
+-      isize = i_size_read(inode);
+-      if (!isize)
+-              goto out;
+-
+-      end_index = (isize - 1) >> huge_page_shift(h);
+       for (;;) {
+               struct page *page;
+               unsigned long nr, ret;
+@@ -256,18 +249,21 @@ static ssize_t hugetlbfs_read(struct fil
+               /* nr is the maximum number of bytes to copy from this page */
+               nr = huge_page_size(h);
++              isize = i_size_read(inode);
++              if (!isize)
++                      goto out;
++              end_index = (isize - 1) >> huge_page_shift(h);
+               if (index >= end_index) {
+                       if (index > end_index)
+                               goto out;
+                       nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
+-                      if (nr <= offset) {
++                      if (nr <= offset)
+                               goto out;
+-                      }
+               }
+               nr = nr - offset;
+               /* Find the page */
+-              page = find_get_page(mapping, index);
++              page = find_lock_page(mapping, index);
+               if (unlikely(page == NULL)) {
+                       /*
+                        * We have a HOLE, zero out the user-buffer for the
+@@ -279,17 +275,18 @@ static ssize_t hugetlbfs_read(struct fil
+                       else
+                               ra = 0;
+               } else {
++                      unlock_page(page);
++
+                       /*
+                        * We have the page, copy it to user space buffer.
+                        */
+                       ra = hugetlbfs_read_actor(page, offset, buf, len, nr);
+                       ret = ra;
++                      page_cache_release(page);
+               }
+               if (ra < 0) {
+                       if (retval == 0)
+                               retval = ra;
+-                      if (page)
+-                              page_cache_release(page);
+                       goto out;
+               }
+@@ -299,16 +296,12 @@ static ssize_t hugetlbfs_read(struct fil
+               index += offset >> huge_page_shift(h);
+               offset &= ~huge_page_mask(h);
+-              if (page)
+-                      page_cache_release(page);
+-
+               /* short read or no more work */
+               if ((ret != nr) || (len == 0))
+                       break;
+       }
+ out:
+       *ppos = ((loff_t)index << huge_page_shift(h)) + offset;
+-      mutex_unlock(&inode->i_mutex);
+       return retval;
+ }
diff --git a/queue-3.0/md-bitmap-ensure-to-load-bitmap-when-creating-via-sysfs.patch b/queue-3.0/md-bitmap-ensure-to-load-bitmap-when-creating-via-sysfs.patch
new file mode 100644 (file)
index 0000000..b23e59f
--- /dev/null
@@ -0,0 +1,34 @@
+From 4474ca42e2577563a919fd3ed782e2ec55bf11a2 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Mon, 19 Mar 2012 12:46:37 +1100
+Subject: md/bitmap: ensure to load bitmap when creating via sysfs.
+
+From: NeilBrown <neilb@suse.de>
+
+commit 4474ca42e2577563a919fd3ed782e2ec55bf11a2 upstream.
+
+When commit 69e51b449d383e (md/bitmap:  separate out loading a bitmap...)
+created bitmap_load, it missed calling it after bitmap_create when a
+bitmap is created through the sysfs interface.
+So if a bitmap is added this way, we don't allocate memory properly
+and can crash.
+
+This is suitable for any -stable release since 2.6.35.
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/bitmap.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1982,6 +1982,8 @@ location_store(mddev_t *mddev, const cha
+                       if (mddev->pers) {
+                               mddev->pers->quiesce(mddev, 1);
+                               rv = bitmap_create(mddev);
++                              if (!rv)
++                                      rv = bitmap_load(mddev);
+                               if (rv) {
+                                       bitmap_destroy(mddev);
+                                       mddev->bitmap_info.offset = 0;
diff --git a/queue-3.0/md-raid1-raid10-avoid-deadlock-during-resync-recovery.patch b/queue-3.0/md-raid1-raid10-avoid-deadlock-during-resync-recovery.patch
new file mode 100644 (file)
index 0000000..b48b5e1
--- /dev/null
@@ -0,0 +1,92 @@
+From d6b42dcb995e6acd7cc276774e751ffc9f0ef4bf Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Mon, 19 Mar 2012 12:46:38 +1100
+Subject: md/raid1,raid10: avoid deadlock during resync/recovery.
+
+From: NeilBrown <neilb@suse.de>
+
+commit d6b42dcb995e6acd7cc276774e751ffc9f0ef4bf upstream.
+
+If RAID1 or RAID10 is used under LVM or some other stacking
+block device, it is possible to enter a deadlock during
+resync or recovery.
+This can happen if the upper level block device creates
+two requests to the RAID1 or RAID10.  The first request gets
+processed, blocks recovery and queue requests for underlying
+requests in current->bio_list.  A resync request then starts
+which will wait for those requests and block new IO.
+
+But then the second request to the RAID1/10 will be attempted
+and it cannot progress until the resync request completes,
+which cannot progress until the underlying device requests complete,
+which are on a queue behind that second request.
+
+So allow that second request to proceed even though there is
+a resync request about to start.
+
+This is suitable for any -stable kernel.
+
+Reported-by: Ray Morris <support@bettercgi.com>
+Tested-by: Ray Morris <support@bettercgi.com>
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/raid1.c  |   17 +++++++++++++++--
+ drivers/md/raid10.c |   17 +++++++++++++++--
+ 2 files changed, 30 insertions(+), 4 deletions(-)
+
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -614,9 +614,22 @@ static void wait_barrier(conf_t *conf)
+       spin_lock_irq(&conf->resync_lock);
+       if (conf->barrier) {
+               conf->nr_waiting++;
+-              wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
++              /* Wait for the barrier to drop.
++               * However if there are already pending
++               * requests (preventing the barrier from
++               * rising completely), and the
++               * pre-process bio queue isn't empty,
++               * then don't wait, as we need to empty
++               * that queue to get the nr_pending
++               * count down.
++               */
++              wait_event_lock_irq(conf->wait_barrier,
++                                  !conf->barrier ||
++                                  (conf->nr_pending &&
++                                   current->bio_list &&
++                                   !bio_list_empty(current->bio_list)),
+                                   conf->resync_lock,
+-                                  );
++                      );
+               conf->nr_waiting--;
+       }
+       conf->nr_pending++;
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -667,9 +667,22 @@ static void wait_barrier(conf_t *conf)
+       spin_lock_irq(&conf->resync_lock);
+       if (conf->barrier) {
+               conf->nr_waiting++;
+-              wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
++              /* Wait for the barrier to drop.
++               * However if there are already pending
++               * requests (preventing the barrier from
++               * rising completely), and the
++               * pre-process bio queue isn't empty,
++               * then don't wait, as we need to empty
++               * that queue to get the nr_pending
++               * count down.
++               */
++              wait_event_lock_irq(conf->wait_barrier,
++                                  !conf->barrier ||
++                                  (conf->nr_pending &&
++                                   current->bio_list &&
++                                   !bio_list_empty(current->bio_list)),
+                                   conf->resync_lock,
+-                                  );
++                      );
+               conf->nr_waiting--;
+       }
+       conf->nr_pending++;
diff --git a/queue-3.0/rtnetlink-fix-vf-ifla-policy.patch b/queue-3.0/rtnetlink-fix-vf-ifla-policy.patch
deleted file mode 100644 (file)
index 70b37fb..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 48752f6513012a1b078da08b145d5c40a644f058 Mon Sep 17 00:00:00 2001
-From: Greg Rose <gregory.v.rose@intel.com>
-Date: Wed, 8 Feb 2012 00:45:00 +0000
-Subject: rtnetlink: Fix VF IFLA policy
-
-From: Greg Rose <gregory.v.rose@intel.com>
-
-commit 48752f6513012a1b078da08b145d5c40a644f058 upstream.
-
-Add VF spoof check to IFLA policy.  The original patch I submitted to
-add the spoof checking feature to rtnl failed to add the proper policy
-rule that identifies the data type and len.  This patch corrects that
-oversight.  No bugs have been reported against this but it may cause
-some problem for the netlink message parsing that uses the policy
-table.
-
-Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
-Tested-by: Sibai Li <sibai.li@intel.com>
-Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- net/core/rtnetlink.c |    2 ++
- 1 file changed, 2 insertions(+)
-
---- a/net/core/rtnetlink.c
-+++ b/net/core/rtnetlink.c
-@@ -1071,6 +1071,8 @@ static const struct nla_policy ifla_vf_p
-                                   .len = sizeof(struct ifla_vf_vlan) },
-       [IFLA_VF_TX_RATE]       = { .type = NLA_BINARY,
-                                   .len = sizeof(struct ifla_vf_tx_rate) },
-+      [IFLA_VF_SPOOFCHK]      = { .type = NLA_BINARY,
-+                                  .len = sizeof(struct ifla_vf_spoofchk) },
- };
- static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
index b8c499e76a374c284f5a7f4371ceb2738f4fb0fd..62d66bf2c3f3372c4ade5471211804fcb90c770f 100644 (file)
@@ -38,7 +38,23 @@ genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch
 genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch
 rtc-disable-the-alarm-in-the-hardware-v2.patch
 p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch
-rtnetlink-fix-vf-ifla-policy.patch
 ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch
 x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch
 mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch
+bootmem-sparsemem-remove-limit-constraint-in-alloc_bootmem_section.patch
+hugetlbfs-avoid-taking-i_mutex-from-hugetlbfs_read.patch
+asoc-fsl-p1022ds-tell-the-wm8776-codec-driver-that-it-s-the-master.patch
+asoc-pxa-ssp-atomically-set-stream-active-masks.patch
+tcm_loop-set-residual-field-for-scsi-commands.patch
+udlfb-remove-sysfs-framebuffer-device-with-usb-.disconnect.patch
+tcm_fc-fix-fc_exch-memory-leak-in-ft_send_resp_status.patch
+md-bitmap-ensure-to-load-bitmap-when-creating-via-sysfs.patch
+md-raid1-raid10-avoid-deadlock-during-resync-recovery.patch
+drm-radeon-restrict-offset-for-legacy-hardware-cursor.patch
+drm-radeon-kms-fix-analog-load-detection-on-dvi-i-connectors.patch
+drm-radeon-kms-add-connector-quirk-for-fujitsu-d3003-s2-board.patch
+target-don-t-set-wbus16-or-sync-bits-in-inquiry-response.patch
+target-fix-16-bit-target-ports-for-set-target-port-groups-emulation.patch
+bluetooth-add-ar30xx-device-id-on-asus-laptops.patch
+hid-add-extra-hotkeys-in-asus-aio-keyboards.patch
+hid-add-more-hotkeys-in-asus-aio-keyboards.patch
diff --git a/queue-3.0/target-don-t-set-wbus16-or-sync-bits-in-inquiry-response.patch b/queue-3.0/target-don-t-set-wbus16-or-sync-bits-in-inquiry-response.patch
new file mode 100644 (file)
index 0000000..402190e
--- /dev/null
@@ -0,0 +1,38 @@
+From effc6cc8828257c32c37635e737f14fd6e19ecd7 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Mon, 13 Feb 2012 16:18:16 -0800
+Subject: target: Don't set WBUS16 or SYNC bits in INQUIRY response
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit effc6cc8828257c32c37635e737f14fd6e19ecd7 upstream.
+
+SPC-4 says about the WBUS16 and SYNC bits:
+
+    The meanings of these fields are specific to SPI-5 (see 6.4.3).
+    For SCSI transport protocols other than the SCSI Parallel
+    Interface, these fields are reserved.
+
+We don't have a SPI fabric module, so we should never set these bits.
+(The comment was misleading, since it only mentioned Sync but the
+actual code set WBUS16 too).
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_cdb.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/target/target_core_cdb.c
++++ b/drivers/target/target_core_cdb.c
+@@ -106,7 +106,7 @@ target_emulate_inquiry_std(struct se_cmd
+               return 0;
+       }
+-      buf[7] = 0x32; /* Sync=1 and CmdQue=1 */
++      buf[7] = 0x2; /* CmdQue=1 */
+       /*
+        * Do not include vendor, product, reversion info in INQUIRY
diff --git a/queue-3.0/target-fix-16-bit-target-ports-for-set-target-port-groups-emulation.patch b/queue-3.0/target-fix-16-bit-target-ports-for-set-target-port-groups-emulation.patch
new file mode 100644 (file)
index 0000000..5227c1d
--- /dev/null
@@ -0,0 +1,51 @@
+From 33395fb8a13731c7ef7b175dbf5a4d8a6738fe6c Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Thu, 23 Feb 2012 17:22:12 -0800
+Subject: target: Fix 16-bit target ports for SET TARGET PORT GROUPS emulation
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit 33395fb8a13731c7ef7b175dbf5a4d8a6738fe6c upstream.
+
+The old code did (MSB << 8) & 0xff, which always evaluates to 0.  Just use
+get_unaligned_be16() so we don't have to worry about whether our open-coded
+version is correct or not.
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_alua.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/target/target_core_alua.c
++++ b/drivers/target/target_core_alua.c
+@@ -30,6 +30,7 @@
+ #include <linux/configfs.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
++#include <asm/unaligned.h>
+ #include <target/target_core_base.h>
+ #include <target/target_core_device.h>
+@@ -238,8 +239,7 @@ int core_emulate_set_target_port_groups(
+                * changed.
+                */
+               if (primary) {
+-                      tg_pt_id = ((ptr[2] << 8) & 0xff);
+-                      tg_pt_id |= (ptr[3] & 0xff);
++                      tg_pt_id = get_unaligned_be16(ptr + 2);
+                       /*
+                        * Locate the matching target port group ID from
+                        * the global tg_pt_gp list
+@@ -280,8 +280,7 @@ int core_emulate_set_target_port_groups(
+                        * the Target Port in question for the the incoming
+                        * SET_TARGET_PORT_GROUPS op.
+                        */
+-                      rtpi = ((ptr[2] << 8) & 0xff);
+-                      rtpi |= (ptr[3] & 0xff);
++                      rtpi = get_unaligned_be16(ptr + 2);
+                       /*
+                        * Locate the matching relative target port identifer
+                        * for the struct se_device storage object.
diff --git a/queue-3.0/tcm_fc-fix-fc_exch-memory-leak-in-ft_send_resp_status.patch b/queue-3.0/tcm_fc-fix-fc_exch-memory-leak-in-ft_send_resp_status.patch
new file mode 100644 (file)
index 0000000..ee92bd7
--- /dev/null
@@ -0,0 +1,47 @@
+From 031ed4d565b31880a4136bb7366bc89f5b1dba7d Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Fri, 9 Mar 2012 23:45:38 -0800
+Subject: tcm_fc: Fix fc_exch memory leak in ft_send_resp_status
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit 031ed4d565b31880a4136bb7366bc89f5b1dba7d upstream.
+
+This patch fixes a bug in tcm_fc where fc_exch memory from fc_exch_mgr->ep_pool
+is currently being leaked by ft_send_resp_status() usage.  Following current
+code in ft_queue_status() response path, using lport->tt.seq_send() needs to be
+followed by a lport->tt.exch_done() in order to release fc_exch memory back into
+libfc_em kmem_cache.
+
+ft_send_resp_status() code is currently used in pre submit se_cmd ft_send_work()
+error exceptions, TM request setup exceptions, and main TM response callback
+path in ft_queue_tm_resp().  This bugfix addresses the leak in these cases.
+
+Cc: Mark D Rustad <mark.d.rustad@intel.com>
+Cc: Kiran Patil <kiran.patil@intel.com>
+Cc: Robert Love <robert.w.love@intel.com>
+Cc: Andy Grover <agrover@redhat.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/tcm_fc/tfc_cmd.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/target/tcm_fc/tfc_cmd.c
++++ b/drivers/target/tcm_fc/tfc_cmd.c
+@@ -371,10 +371,12 @@ static void ft_send_resp_status(struct f
+       fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
+       sp = fr_seq(fp);
+-      if (sp)
++      if (sp) {
+               lport->tt.seq_send(lport, sp, fp);
+-      else
++              lport->tt.exch_done(sp);
++      } else {
+               lport->tt.frame_send(lport, fp);
++      }
+ }
+ /*
diff --git a/queue-3.0/tcm_loop-set-residual-field-for-scsi-commands.patch b/queue-3.0/tcm_loop-set-residual-field-for-scsi-commands.patch
new file mode 100644 (file)
index 0000000..9529d83
--- /dev/null
@@ -0,0 +1,49 @@
+From 6cf3fa6918baab0c447f1206f1cef9166ad04864 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Tue, 14 Feb 2012 15:30:31 -0800
+Subject: tcm_loop: Set residual field for SCSI commands
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit 6cf3fa6918baab0c447f1206f1cef9166ad04864 upstream.
+
+If the target core signals an over- or under-run, tcm_loop should call
+scsi_set_resid() to tell the SCSI midlayer about the residual data length.
+
+The difference can be seen by doing something like
+
+    strace -eioctl sg_raw -r 1024 /dev/sda 8 0 0 0 1 0 > /dev/null
+
+and looking at the "resid=" part of the SG_IO ioctl -- after this patch,
+the field is correctly reported as 512.
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/loopback/tcm_loop.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/target/loopback/tcm_loop.c
++++ b/drivers/target/loopback/tcm_loop.c
+@@ -905,6 +905,9 @@ static int tcm_loop_queue_data_in(struct
+       sc->result = SAM_STAT_GOOD;
+       set_host_byte(sc, DID_OK);
++      if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
++          (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
++              scsi_set_resid(sc, se_cmd->residual_count);
+       sc->scsi_done(sc);
+       return 0;
+ }
+@@ -930,6 +933,9 @@ static int tcm_loop_queue_status(struct
+               sc->result = se_cmd->scsi_status;
+       set_host_byte(sc, DID_OK);
++      if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
++          (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
++              scsi_set_resid(sc, se_cmd->residual_count);
+       sc->scsi_done(sc);
+       return 0;
+ }
diff --git a/queue-3.0/udlfb-remove-sysfs-framebuffer-device-with-usb-.disconnect.patch b/queue-3.0/udlfb-remove-sysfs-framebuffer-device-with-usb-.disconnect.patch
new file mode 100644 (file)
index 0000000..71e46d0
--- /dev/null
@@ -0,0 +1,113 @@
+From ce880cb860f36694d2cdebfac9e6ae18176fe4c4 Mon Sep 17 00:00:00 2001
+From: Kay Sievers <kay.sievers@vrfy.org>
+Date: Sat, 28 Jan 2012 19:57:46 +0000
+Subject: udlfb: remove sysfs framebuffer device with USB .disconnect()
+
+From: Kay Sievers <kay.sievers@vrfy.org>
+
+commit ce880cb860f36694d2cdebfac9e6ae18176fe4c4 upstream.
+
+The USB graphics card driver delays the unregistering of the framebuffer
+device to a workqueue, which breaks the userspace visible remove uevent
+sequence. Recent userspace tools started to support USB graphics card
+hotplug out-of-the-box and rely on proper events sent by the kernel.
+
+The framebuffer device is a direct child of the USB interface which is
+removed immediately after the USB .disconnect() callback. But the fb device
+in /sys stays around until its final cleanup, at a time where all the parent
+devices have been removed already.
+
+To work around that, we remove the sysfs fb device directly in the USB
+.disconnect() callback and leave only the cleanup of the internal fb
+data to the delayed work.
+
+Before:
+ add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
+ add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
+ add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb0 (graphics)
+ remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
+ remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
+ remove   /2-1.2:1.0/graphics/fb0 (graphics)
+
+After:
+ add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
+ add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
+ add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics)
+ remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics)
+ remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
+ remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
+
+Tested-by: Bernie Thompson <bernie@plugable.com>
+Acked-by: Bernie Thompson <bernie@plugable.com>
+Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/fbmem.c |   18 +++++++++++++++++-
+ drivers/video/udlfb.c |    2 +-
+ include/linux/fb.h    |    1 +
+ 3 files changed, 19 insertions(+), 2 deletions(-)
+
+--- a/drivers/video/fbmem.c
++++ b/drivers/video/fbmem.c
+@@ -1651,6 +1651,7 @@ static int do_unregister_framebuffer(str
+       if (ret)
+               return -EINVAL;
++      unlink_framebuffer(fb_info);
+       if (fb_info->pixmap.addr &&
+           (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
+               kfree(fb_info->pixmap.addr);
+@@ -1658,7 +1659,6 @@ static int do_unregister_framebuffer(str
+       registered_fb[i] = NULL;
+       num_registered_fb--;
+       fb_cleanup_device(fb_info);
+-      device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+       event.info = fb_info;
+       fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+@@ -1667,6 +1667,22 @@ static int do_unregister_framebuffer(str
+       return 0;
+ }
++int unlink_framebuffer(struct fb_info *fb_info)
++{
++      int i;
++
++      i = fb_info->node;
++      if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
++              return -EINVAL;
++
++      if (fb_info->dev) {
++              device_destroy(fb_class, MKDEV(FB_MAJOR, i));
++              fb_info->dev = NULL;
++      }
++      return 0;
++}
++EXPORT_SYMBOL(unlink_framebuffer);
++
+ void remove_conflicting_framebuffers(struct apertures_struct *a,
+                                    const char *name, bool primary)
+ {
+--- a/drivers/video/udlfb.c
++++ b/drivers/video/udlfb.c
+@@ -1666,7 +1666,7 @@ static void dlfb_usb_disconnect(struct u
+       for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+               device_remove_file(info->dev, &fb_device_attrs[i]);
+       device_remove_bin_file(info->dev, &edid_attr);
+-
++      unlink_framebuffer(info);
+       usb_set_intfdata(interface, NULL);
+       /* if clients still have us open, will be freed on last close */
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -997,6 +997,7 @@ extern ssize_t fb_sys_write(struct fb_in
+ /* drivers/video/fbmem.c */
+ extern int register_framebuffer(struct fb_info *fb_info);
+ extern int unregister_framebuffer(struct fb_info *fb_info);
++extern int unlink_framebuffer(struct fb_info *fb_info);
+ extern void remove_conflicting_framebuffers(struct apertures_struct *a,
+                               const char *name, bool primary);
+ extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);