]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.1 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Nov 2011 20:29:56 +0000 (13:29 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Nov 2011 20:29:56 +0000 (13:29 -0700)
queue-3.1/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch [new file with mode: 0644]
queue-3.1/iwlagn-do-not-use-interruptible-waits.patch [new file with mode: 0644]
queue-3.1/jsm-remove-buggy-write-queue.patch [new file with mode: 0644]
queue-3.1/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch [new file with mode: 0644]
queue-3.1/omap-spi-fix-the-trying-to-free-nonexistent-resource-error.patch [new file with mode: 0644]
queue-3.1/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch [new file with mode: 0644]
queue-3.1/series
queue-3.1/um-fix-kmalloc-argument-order-in-um-vdso-vma.c.patch [new file with mode: 0644]
queue-3.1/um-fix-ubd-cow-size.patch [new file with mode: 0644]

diff --git a/queue-3.1/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch b/queue-3.1/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch
new file mode 100644 (file)
index 0000000..7cb1a7f
--- /dev/null
@@ -0,0 +1,105 @@
+From 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 14 Oct 2011 15:26:20 +0200
+Subject: ALSA: hda - Fix ADC input-amp handling for Cx20549 codec
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 upstream.
+
+It seems that Conexant CX20549 chip handle only a single input-amp even
+though the audio-input widget has multiple sources.  This has been never
+clear, and I implemented in the current way based on the debug information
+I got at the early time -- the device reacts individual input-amp values
+for different sources.  This is true for another Conexant codec, but it's
+not applied to CX20549 actually.
+
+This patch changes the auto-parser code to handle a single input-amp
+per audio-in widget for CX20549.  After applying this, you'll see only a
+single "Capture" volume control instead of separate "Mic" or "Line"
+captures when the device is set up to use a single ADC.
+
+We haven't tested 20551 and 20561 codecs yet.  If these show the similar
+behavior like 20549, they need to set spec->single_adc_amp=1, too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ sound/pci/hda/patch_conexant.c |   30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -137,6 +137,7 @@ struct conexant_spec {
+       unsigned int hp_laptop:1;
+       unsigned int asus:1;
+       unsigned int pin_eapd_ctrls:1;
++      unsigned int single_adc_amp:1;
+       unsigned int adc_switching:1;
+@@ -4256,6 +4257,8 @@ static int cx_auto_add_capture_volume(st
+               int idx = get_input_connection(codec, adc_nid, nid);
+               if (idx < 0)
+                       continue;
++              if (spec->single_adc_amp)
++                      idx = 0;
+               return cx_auto_add_volume_idx(codec, label, pfx,
+                                             cidx, adc_nid, HDA_INPUT, idx);
+       }
+@@ -4296,14 +4299,21 @@ static int cx_auto_build_input_controls(
+       struct hda_input_mux *imux = &spec->private_imux;
+       const char *prev_label;
+       int input_conn[HDA_MAX_NUM_INPUTS];
+-      int i, err, cidx;
++      int i, j, err, cidx;
+       int multi_connection;
++      if (!imux->num_items)
++              return 0;
++
+       multi_connection = 0;
+       for (i = 0; i < imux->num_items; i++) {
+               cidx = get_input_connection(codec, spec->imux_info[i].adc,
+                                           spec->imux_info[i].pin);
+-              input_conn[i] = (spec->imux_info[i].adc << 8) | cidx;
++              if (cidx < 0)
++                      continue;
++              input_conn[i] = spec->imux_info[i].adc;
++              if (!spec->single_adc_amp)
++                      input_conn[i] |= cidx << 8;
+               if (i > 0 && input_conn[i] != input_conn[0])
+                       multi_connection = 1;
+       }
+@@ -4332,6 +4342,15 @@ static int cx_auto_build_input_controls(
+                       err = cx_auto_add_capture_volume(codec, nid,
+                                                        "Capture", "", cidx);
+               } else {
++                      bool dup_found = false;
++                      for (j = 0; j < i; j++) {
++                              if (input_conn[j] == input_conn[i]) {
++                                      dup_found = true;
++                                      break;
++                              }
++                      }
++                      if (dup_found)
++                              continue;
+                       err = cx_auto_add_capture_volume(codec, nid,
+                                                        label, " Capture", cidx);
+               }
+@@ -4408,6 +4427,13 @@ static int patch_conexant_auto(struct hd
+               return -ENOMEM;
+       codec->spec = spec;
+       codec->pin_amp_workaround = 1;
++
++      switch (codec->vendor_id) {
++      case 0x14f15045:
++              spec->single_adc_amp = 1;
++              break;
++      }
++
+       err = cx_auto_search_adcs(codec);
+       if (err < 0)
+               return err;
diff --git a/queue-3.1/iwlagn-do-not-use-interruptible-waits.patch b/queue-3.1/iwlagn-do-not-use-interruptible-waits.patch
new file mode 100644 (file)
index 0000000..ce1fd36
--- /dev/null
@@ -0,0 +1,126 @@
+From effd4d9aece9184f526e6556786a94d335e38b71 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 15 Sep 2011 11:46:52 -0700
+Subject: iwlagn: do not use interruptible waits
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit effd4d9aece9184f526e6556786a94d335e38b71 upstream.
+
+Since the dawn of its time, iwlwifi has used
+interruptible waits to wait for synchronous
+commands and firmware loading.
+
+This leads to "interesting" bugs, because it
+can't actually handle the interruptions; for
+example when a command sending is interrupted
+it will assume the command completed fully,
+and then leave it pending, which leads to all
+kinds of trouble when the command finishes
+later.
+
+Since there's no easy way to gracefully deal
+with interruptions, fix the driver to not use
+interruptible waits.
+
+This at least fixes the error
+iwlagn 0000:02:00.0: Error: Response NULL in  'REPLY_SCAN_ABORT_CMD'
+
+I have seen in P2P testing, but it is likely
+that there are other errors caused by this.
+
+Cc: Stanislaw Gruszka <sgruszka@redhat.com>
+Cc: stable@kernel.org [2.6.24+]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+
+
+---
+ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c     |    9 ++-------
+ drivers/net/wireless/iwlwifi/iwl-core.c          |    4 ++--
+ drivers/net/wireless/iwlwifi/iwl-rx.c            |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c |    4 ++--
+ 5 files changed, 8 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+@@ -113,13 +113,8 @@ static int iwlagn_load_section(struct iw
+               FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
+       IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
+-      ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+-                                      priv->ucode_write_complete, 5 * HZ);
+-      if (ret == -ERESTARTSYS) {
+-              IWL_ERR(priv, "Could not load the %s uCode section due "
+-                      "to interrupt\n", name);
+-              return ret;
+-      }
++      ret = wait_event_timeout(priv->wait_command_queue,
++                               priv->ucode_write_complete, 5 * HZ);
+       if (!ret) {
+               IWL_ERR(priv, "Could not load the %s uCode section\n",
+                       name);
+--- a/drivers/net/wireless/iwlwifi/iwl-core.c
++++ b/drivers/net/wireless/iwlwifi/iwl-core.c
+@@ -867,7 +867,7 @@ void iwlagn_fw_error(struct iwl_priv *pr
+        * commands by clearing the ready bit */
+       clear_bit(STATUS_READY, &priv->status);
+-      wake_up_interruptible(&priv->wait_command_queue);
++      wake_up(&priv->wait_command_queue);
+       if (!ondemand) {
+               /*
+@@ -918,7 +918,7 @@ void iwl_irq_handle_error(struct iwl_pri
+                */
+               clear_bit(STATUS_READY, &priv->status);
+               clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+-              wake_up_interruptible(&priv->wait_command_queue);
++              wake_up(&priv->wait_command_queue);
+               IWL_ERR(priv, "RF is used by WiMAX\n");
+               return;
+       }
+--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
+@@ -561,7 +561,7 @@ static void iwl_rx_card_state_notif(stru
+               wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+                       test_bit(STATUS_RF_KILL_HW, &priv->status));
+       else
+-              wake_up_interruptible(&priv->wait_command_queue);
++              wake_up(&priv->wait_command_queue);
+ }
+ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+--- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
++++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
+@@ -671,7 +671,7 @@ void iwl_irq_tasklet(struct iwl_priv *pr
+               handled |= CSR_INT_BIT_FH_TX;
+               /* Wake up uCode load routine, now that load is complete */
+               priv->ucode_write_complete = 1;
+-              wake_up_interruptible(&priv->wait_command_queue);
++              wake_up(&priv->wait_command_queue);
+       }
+       if (inta & ~handled) {
+--- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
++++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
+@@ -790,7 +790,7 @@ void iwl_tx_cmd_complete(struct iwl_priv
+               clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+               IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
+                              get_cmd_string(cmd->hdr.cmd));
+-              wake_up_interruptible(&priv->wait_command_queue);
++              wake_up(&priv->wait_command_queue);
+       }
+       meta->flags = 0;
+@@ -957,7 +957,7 @@ static int iwl_send_cmd_sync(struct iwl_
+               return ret;
+       }
+-      ret = wait_event_interruptible_timeout(priv->wait_command_queue,
++      ret = wait_event_timeout(priv->wait_command_queue,
+                       !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+                       HOST_COMPLETE_TIMEOUT);
+       if (!ret) {
diff --git a/queue-3.1/jsm-remove-buggy-write-queue.patch b/queue-3.1/jsm-remove-buggy-write-queue.patch
new file mode 100644 (file)
index 0000000..580f7f2
--- /dev/null
@@ -0,0 +1,300 @@
+From 9d898966c4a07e4a5092215b5a2829d0ef02baa2 Mon Sep 17 00:00:00 2001
+From: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
+Date: Wed, 24 Aug 2011 13:14:22 -0300
+Subject: jsm: remove buggy write queue
+
+From: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
+
+commit 9d898966c4a07e4a5092215b5a2829d0ef02baa2 upstream.
+
+jsm uses a write queue that copies from uart_core circular buffer. This
+copying however has some bugs, like not wrapping the head counter. Since
+this write queue is also a circular buffer, the consumer function is
+ready to use the uart_core circular buffer directly.
+
+This buggy copying function was making some bytes be dropped when
+transmitting to a raw tty, doing something like this.
+
+[root@hostname ~]$ cat /dev/ttyn1 > cascardo/dump &
+[1] 2658
+[root@hostname ~]$ cat /proc/tty/drivers > /dev/ttyn0
+[root@hostname ~]$ cat /proc/tty/drivers
+/dev/tty             /dev/tty        5       0 system:/dev/tty
+/dev/console         /dev/console    5       1 system:console
+/dev/ptmx            /dev/ptmx       5       2 system
+/dev/vc/0            /dev/vc/0       4       0 system:vtmaster
+jsm                  /dev/ttyn     250 0-31 serial
+serial               /dev/ttyS       4 64-95 serial
+hvc                  /dev/hvc      229 0-7 system
+pty_slave            /dev/pts      136 0-1048575 pty:slave
+pty_master           /dev/ptm      128 0-1048575 pty:master
+unknown              /dev/tty        4 1-63 console
+[root@hostname ~]$ cat cascardo/dump
+/dev/tty             /dev/tty        5       0 system:/dev/tty
+/dev/console         /dev/console    5       1 system:console
+/dev/ptmx            /dev/ptmx       5       2 system
+/dev/vc/0            /dev/vc/0       4       0 system:vtmaste[root@hostname ~]$
+
+This patch drops the driver write queue entirely, using the circular
+buffer from uart_core only.
+
+Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/tty/serial/jsm/jsm.h        |    7 --
+ drivers/tty/serial/jsm/jsm_driver.c |    1 
+ drivers/tty/serial/jsm/jsm_neo.c    |   29 +++++------
+ drivers/tty/serial/jsm/jsm_tty.c    |   94 ++++--------------------------------
+ 4 files changed, 28 insertions(+), 103 deletions(-)
+
+--- a/drivers/tty/serial/jsm/jsm.h
++++ b/drivers/tty/serial/jsm/jsm.h
+@@ -183,10 +183,8 @@ struct jsm_board
+ /* Our Read/Error/Write queue sizes */
+ #define RQUEUEMASK    0x1FFF          /* 8 K - 1 */
+ #define EQUEUEMASK    0x1FFF          /* 8 K - 1 */
+-#define WQUEUEMASK    0x0FFF          /* 4 K - 1 */
+ #define RQUEUESIZE    (RQUEUEMASK + 1)
+ #define EQUEUESIZE    RQUEUESIZE
+-#define WQUEUESIZE    (WQUEUEMASK + 1)
+ /************************************************************************
+@@ -226,10 +224,6 @@ struct jsm_channel {
+       u16             ch_e_head;      /* Head location of the error queue */
+       u16             ch_e_tail;      /* Tail location of the error queue */
+-      u8              *ch_wqueue;     /* Our write queue buffer - malloc'ed */
+-      u16             ch_w_head;      /* Head location of the write queue */
+-      u16             ch_w_tail;      /* Tail location of the write queue */
+-
+       u64             ch_rxcount;     /* total of data received so far */
+       u64             ch_txcount;     /* total of data transmitted so far */
+@@ -378,7 +372,6 @@ extern int jsm_debug;
+  * Prototypes for non-static functions used in more than one module
+  *
+  *************************************************************************/
+-int jsm_tty_write(struct uart_port *port);
+ int jsm_tty_init(struct jsm_board *);
+ int jsm_uart_port_init(struct jsm_board *);
+ int jsm_remove_uart_port(struct jsm_board *);
+--- a/drivers/tty/serial/jsm/jsm_driver.c
++++ b/drivers/tty/serial/jsm/jsm_driver.c
+@@ -211,7 +211,6 @@ static void __devexit jsm_remove_one(str
+               if (brd->channels[i]) {
+                       kfree(brd->channels[i]->ch_rqueue);
+                       kfree(brd->channels[i]->ch_equeue);
+-                      kfree(brd->channels[i]->ch_wqueue);
+                       kfree(brd->channels[i]);
+               }
+       }
+--- a/drivers/tty/serial/jsm/jsm_neo.c
++++ b/drivers/tty/serial/jsm/jsm_neo.c
+@@ -496,12 +496,15 @@ static void neo_copy_data_from_queue_to_
+       int s;
+       int qlen;
+       u32 len_written = 0;
++      struct circ_buf *circ;
+       if (!ch)
+               return;
++      circ = &ch->uart_port.state->xmit;
++
+       /* No data to write to the UART */
+-      if (ch->ch_w_tail == ch->ch_w_head)
++      if (uart_circ_empty(circ))
+               return;
+       /* If port is "stopped", don't send any data to the UART */
+@@ -517,11 +520,10 @@ static void neo_copy_data_from_queue_to_
+               if (ch->ch_cached_lsr & UART_LSR_THRE) {
+                       ch->ch_cached_lsr &= ~(UART_LSR_THRE);
+-                      writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
++                      writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx);
+                       jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
+-                                      "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]);
+-                      ch->ch_w_tail++;
+-                      ch->ch_w_tail &= WQUEUEMASK;
++                                      "Tx data: %x\n", circ->buf[circ->head]);
++                      circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
+                       ch->ch_txcount++;
+               }
+               return;
+@@ -536,36 +538,36 @@ static void neo_copy_data_from_queue_to_
+       n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
+       /* cache head and tail of queue */
+-      head = ch->ch_w_head & WQUEUEMASK;
+-      tail = ch->ch_w_tail & WQUEUEMASK;
+-      qlen = (head - tail) & WQUEUEMASK;
++      head = circ->head & (UART_XMIT_SIZE - 1);
++      tail = circ->tail & (UART_XMIT_SIZE - 1);
++      qlen = uart_circ_chars_pending(circ);
+       /* Find minimum of the FIFO space, versus queue length */
+       n = min(n, qlen);
+       while (n > 0) {
+-              s = ((head >= tail) ? head : WQUEUESIZE) - tail;
++              s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail;
+               s = min(s, n);
+               if (s <= 0)
+                       break;
+-              memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
++              memcpy_toio(&ch->ch_neo_uart->txrxburst, circ->buf + tail, s);
+               /* Add and flip queue if needed */
+-              tail = (tail + s) & WQUEUEMASK;
++              tail = (tail + s) & (UART_XMIT_SIZE - 1);
+               n -= s;
+               ch->ch_txcount += s;
+               len_written += s;
+       }
+       /* Update the final tail */
+-      ch->ch_w_tail = tail & WQUEUEMASK;
++      circ->tail = tail & (UART_XMIT_SIZE - 1);
+       if (len_written >= ch->ch_t_tlevel)
+               ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+-      if (!jsm_tty_write(&ch->uart_port))
++      if (uart_circ_empty(circ))
+               uart_write_wakeup(&ch->uart_port);
+ }
+@@ -946,7 +948,6 @@ static void neo_param(struct jsm_channel
+       if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+               ch->ch_r_head = ch->ch_r_tail = 0;
+               ch->ch_e_head = ch->ch_e_tail = 0;
+-              ch->ch_w_head = ch->ch_w_tail = 0;
+               neo_flush_uart_write(ch);
+               neo_flush_uart_read(ch);
+--- a/drivers/tty/serial/jsm/jsm_tty.c
++++ b/drivers/tty/serial/jsm/jsm_tty.c
+@@ -118,6 +118,19 @@ static void jsm_tty_set_mctrl(struct uar
+       udelay(10);
+ }
++/*
++ * jsm_tty_write()
++ *
++ * Take data from the user or kernel and send it out to the FEP.
++ * In here exists all the Transparent Print magic as well.
++ */
++static void jsm_tty_write(struct uart_port *port)
++{
++      struct jsm_channel *channel;
++      channel = container_of(port, struct jsm_channel, uart_port);
++      channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
++}
++
+ static void jsm_tty_start_tx(struct uart_port *port)
+ {
+       struct jsm_channel *channel = (struct jsm_channel *)port;
+@@ -216,14 +229,6 @@ static int jsm_tty_open(struct uart_port
+                       return -ENOMEM;
+               }
+       }
+-      if (!channel->ch_wqueue) {
+-              channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL);
+-              if (!channel->ch_wqueue) {
+-                      jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+-                              "unable to allocate write queue buf");
+-                      return -ENOMEM;
+-              }
+-      }
+       channel->ch_flags &= ~(CH_OPENING);
+       /*
+@@ -237,7 +242,6 @@ static int jsm_tty_open(struct uart_port
+        */
+       channel->ch_r_head = channel->ch_r_tail = 0;
+       channel->ch_e_head = channel->ch_e_tail = 0;
+-      channel->ch_w_head = channel->ch_w_tail = 0;
+       brd->bd_ops->flush_uart_write(channel);
+       brd->bd_ops->flush_uart_read(channel);
+@@ -836,75 +840,3 @@ void jsm_check_queue_flow_control(struct
+               }
+       }
+ }
+-
+-/*
+- * jsm_tty_write()
+- *
+- * Take data from the user or kernel and send it out to the FEP.
+- * In here exists all the Transparent Print magic as well.
+- */
+-int jsm_tty_write(struct uart_port *port)
+-{
+-      int bufcount;
+-      int data_count = 0,data_count1 =0;
+-      u16 head;
+-      u16 tail;
+-      u16 tmask;
+-      u32 remain;
+-      int temp_tail = port->state->xmit.tail;
+-      struct jsm_channel *channel = (struct jsm_channel *)port;
+-
+-      tmask = WQUEUEMASK;
+-      head = (channel->ch_w_head) & tmask;
+-      tail = (channel->ch_w_tail) & tmask;
+-
+-      if ((bufcount = tail - head - 1) < 0)
+-              bufcount += WQUEUESIZE;
+-
+-      bufcount = min(bufcount, 56);
+-      remain = WQUEUESIZE - head;
+-
+-      data_count = 0;
+-      if (bufcount >= remain) {
+-              bufcount -= remain;
+-              while ((port->state->xmit.head != temp_tail) &&
+-              (data_count < remain)) {
+-                      channel->ch_wqueue[head++] =
+-                      port->state->xmit.buf[temp_tail];
+-
+-                      temp_tail++;
+-                      temp_tail &= (UART_XMIT_SIZE - 1);
+-                      data_count++;
+-              }
+-              if (data_count == remain) head = 0;
+-      }
+-
+-      data_count1 = 0;
+-      if (bufcount > 0) {
+-              remain = bufcount;
+-              while ((port->state->xmit.head != temp_tail) &&
+-                      (data_count1 < remain)) {
+-                      channel->ch_wqueue[head++] =
+-                              port->state->xmit.buf[temp_tail];
+-
+-                      temp_tail++;
+-                      temp_tail &= (UART_XMIT_SIZE - 1);
+-                      data_count1++;
+-
+-              }
+-      }
+-
+-      port->state->xmit.tail = temp_tail;
+-
+-      data_count += data_count1;
+-      if (data_count) {
+-              head &= tmask;
+-              channel->ch_w_head = head;
+-      }
+-
+-      if (data_count) {
+-              channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
+-      }
+-
+-      return data_count;
+-}
diff --git a/queue-3.1/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch b/queue-3.1/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch
new file mode 100644 (file)
index 0000000..ec093d8
--- /dev/null
@@ -0,0 +1,169 @@
+From f5252e009d5b87071a919221e4f6624184005368 Mon Sep 17 00:00:00 2001
+From: Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com>
+Date: Mon, 31 Oct 2011 17:08:13 -0700
+Subject: mm: avoid null pointer access in vm_struct via /proc/vmallocinfo
+
+From: Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com>
+
+commit f5252e009d5b87071a919221e4f6624184005368 upstream.
+
+The /proc/vmallocinfo shows information about vmalloc allocations in
+vmlist that is a linklist of vm_struct.  It, however, may access pages
+field of vm_struct where a page was not allocated.  This results in a null
+pointer access and leads to a kernel panic.
+
+Why this happens: In __vmalloc_node_range() called from vmalloc(), newly
+allocated vm_struct is added to vmlist at __get_vm_area_node() and then,
+some fields of vm_struct such as nr_pages and pages are set at
+__vmalloc_area_node().  In other words, it is added to vmlist before it is
+fully initialized.  At the same time, when the /proc/vmallocinfo is read,
+it accesses the pages field of vm_struct according to the nr_pages field
+at show_numa_info().  Thus, a null pointer access happens.
+
+The patch adds the newly allocated vm_struct to the vmlist *after* it is
+fully initialized.  So, it can avoid accessing the pages field with
+unallocated page when show_numa_info() is called.
+
+Signed-off-by: Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Namhyung Kim <namhyung@gmail.com>
+Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Cc: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/vmalloc.h |    1 
+ mm/vmalloc.c            |   65 +++++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 49 insertions(+), 17 deletions(-)
+
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -13,6 +13,7 @@ struct vm_area_struct;               /* vma defining
+ #define VM_MAP                0x00000004      /* vmap()ed pages */
+ #define VM_USERMAP    0x00000008      /* suitable for remap_vmalloc_range */
+ #define VM_VPAGES     0x00000010      /* buffer for pages was vmalloc'ed */
++#define VM_UNLIST     0x00000020      /* vm_struct is not listed in vmlist */
+ /* bits [20..32] reserved for arch specific ioremap internals */
+ /*
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -1253,18 +1253,22 @@ EXPORT_SYMBOL_GPL(map_vm_area);
+ DEFINE_RWLOCK(vmlist_lock);
+ struct vm_struct *vmlist;
+-static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
++static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
+                             unsigned long flags, void *caller)
+ {
+-      struct vm_struct *tmp, **p;
+-
+       vm->flags = flags;
+       vm->addr = (void *)va->va_start;
+       vm->size = va->va_end - va->va_start;
+       vm->caller = caller;
+       va->private = vm;
+       va->flags |= VM_VM_AREA;
++}
++
++static void insert_vmalloc_vmlist(struct vm_struct *vm)
++{
++      struct vm_struct *tmp, **p;
++      vm->flags &= ~VM_UNLIST;
+       write_lock(&vmlist_lock);
+       for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
+               if (tmp->addr >= vm->addr)
+@@ -1275,6 +1279,13 @@ static void insert_vmalloc_vm(struct vm_
+       write_unlock(&vmlist_lock);
+ }
++static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
++                            unsigned long flags, void *caller)
++{
++      setup_vmalloc_vm(vm, va, flags, caller);
++      insert_vmalloc_vmlist(vm);
++}
++
+ static struct vm_struct *__get_vm_area_node(unsigned long size,
+               unsigned long align, unsigned long flags, unsigned long start,
+               unsigned long end, int node, gfp_t gfp_mask, void *caller)
+@@ -1313,7 +1324,18 @@ static struct vm_struct *__get_vm_area_n
+               return NULL;
+       }
+-      insert_vmalloc_vm(area, va, flags, caller);
++      /*
++       * When this function is called from __vmalloc_node_range,
++       * we do not add vm_struct to vmlist here to avoid
++       * accessing uninitialized members of vm_struct such as
++       * pages and nr_pages fields. They will be set later.
++       * To distinguish it from others, we use a VM_UNLIST flag.
++       */
++      if (flags & VM_UNLIST)
++              setup_vmalloc_vm(area, va, flags, caller);
++      else
++              insert_vmalloc_vm(area, va, flags, caller);
++
+       return area;
+ }
+@@ -1381,17 +1403,20 @@ struct vm_struct *remove_vm_area(const v
+       va = find_vmap_area((unsigned long)addr);
+       if (va && va->flags & VM_VM_AREA) {
+               struct vm_struct *vm = va->private;
+-              struct vm_struct *tmp, **p;
+-              /*
+-               * remove from list and disallow access to this vm_struct
+-               * before unmap. (address range confliction is maintained by
+-               * vmap.)
+-               */
+-              write_lock(&vmlist_lock);
+-              for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
+-                      ;
+-              *p = tmp->next;
+-              write_unlock(&vmlist_lock);
++
++              if (!(vm->flags & VM_UNLIST)) {
++                      struct vm_struct *tmp, **p;
++                      /*
++                       * remove from list and disallow access to
++                       * this vm_struct before unmap. (address range
++                       * confliction is maintained by vmap.)
++                       */
++                      write_lock(&vmlist_lock);
++                      for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
++                              ;
++                      *p = tmp->next;
++                      write_unlock(&vmlist_lock);
++              }
+               vmap_debug_free_range(va->va_start, va->va_end);
+               free_unmap_vmap_area(va);
+@@ -1602,8 +1627,8 @@ void *__vmalloc_node_range(unsigned long
+       if (!size || (size >> PAGE_SHIFT) > totalram_pages)
+               return NULL;
+-      area = __get_vm_area_node(size, align, VM_ALLOC, start, end, node,
+-                                gfp_mask, caller);
++      area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNLIST,
++                                start, end, node, gfp_mask, caller);
+       if (!area)
+               return NULL;
+@@ -1611,6 +1636,12 @@ void *__vmalloc_node_range(unsigned long
+       addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+       /*
++       * In this function, newly allocated vm_struct is not added
++       * to vmlist at __get_vm_area_node(). so, it is added here.
++       */
++      insert_vmalloc_vmlist(area);
++
++      /*
+        * A ref_count = 3 is needed because the vm_struct and vmap_area
+        * structures allocated in the __get_vm_area_node() function contain
+        * references to the virtual address of the vmalloc'ed block.
diff --git a/queue-3.1/omap-spi-fix-the-trying-to-free-nonexistent-resource-error.patch b/queue-3.1/omap-spi-fix-the-trying-to-free-nonexistent-resource-error.patch
new file mode 100644 (file)
index 0000000..5b51774
--- /dev/null
@@ -0,0 +1,50 @@
+From 1458d160de3f1862aeaac57447ba96e7857ac52b Mon Sep 17 00:00:00 2001
+From: Shubhrajyoti D <shubhrajyoti@ti.com>
+Date: Mon, 24 Oct 2011 15:54:24 +0530
+Subject: OMAP: SPI: Fix the trying to free nonexistent resource error
+
+From: Shubhrajyoti D <shubhrajyoti@ti.com>
+
+commit 1458d160de3f1862aeaac57447ba96e7857ac52b upstream.
+
+Currently there is a request_mem_region(r->start, ..
+followed by r->start += pdata->regs_offset;
+
+And then in remove
+
+   r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   release_mem_region(r->start, resource_size(r));
+
+Here the offset addition is not taken care. Fix the code for the
+same.
+
+Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/spi/spi-omap2-mcspi.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/spi/spi-omap2-mcspi.c
++++ b/drivers/spi/spi-omap2-mcspi.c
+@@ -1116,15 +1116,16 @@ static int __init omap2_mcspi_probe(stru
+               status = -ENODEV;
+               goto err1;
+       }
++
++      r->start += pdata->regs_offset;
++      r->end += pdata->regs_offset;
++      mcspi->phys = r->start;
+       if (!request_mem_region(r->start, resource_size(r),
+                               dev_name(&pdev->dev))) {
+               status = -EBUSY;
+               goto err1;
+       }
+-      r->start += pdata->regs_offset;
+-      r->end += pdata->regs_offset;
+-      mcspi->phys = r->start;
+       mcspi->base = ioremap(r->start, resource_size(r));
+       if (!mcspi->base) {
+               dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
diff --git a/queue-3.1/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch b/queue-3.1/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch
new file mode 100644 (file)
index 0000000..3e25198
--- /dev/null
@@ -0,0 +1,133 @@
+From 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 Mon Sep 17 00:00:00 2001
+From: Andy Whitcroft <apw@canonical.com>
+Date: Wed, 2 Nov 2011 09:44:39 +0100
+Subject: readlinkat: ensure we return ENOENT for the empty pathname for normal lookups
+
+From: Andy Whitcroft <apw@canonical.com>
+
+commit 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 upstream.
+
+Since the commit below which added O_PATH support to the *at() calls, the
+error return for readlink/readlinkat for the empty pathname has switched
+from ENOENT to EINVAL:
+
+  commit 65cfc6722361570bfe255698d9cd4dccaf47570d
+  Author: Al Viro <viro@zeniv.linux.org.uk>
+  Date:   Sun Mar 13 15:56:26 2011 -0400
+
+    readlinkat(), fchownat() and fstatat() with empty relative pathnames
+
+This is both unexpected for userspace and makes readlink/readlinkat
+inconsistant with all other interfaces; and inconsistant with our stated
+return for these pathnames.
+
+As the readlinkat call does not have a flags parameter we cannot use the
+AT_EMPTY_PATH approach used in the other calls.  Therefore expose whether
+the original path is infact entry via a new user_path_at_empty() path
+lookup function.  Use this to determine whether to default to EINVAL or
+ENOENT for failures.
+
+Addresses http://bugs.launchpad.net/bugs/817187
+
+[akpm@linux-foundation.org: remove unused getname_flags()]
+Signed-off-by: Andy Whitcroft <apw@canonical.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namei.c            |   18 +++++++++++++-----
+ fs/stat.c             |    5 +++--
+ include/linux/namei.h |    1 +
+ 3 files changed, 17 insertions(+), 7 deletions(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -137,7 +137,7 @@ static int do_getname(const char __user
+       return retval;
+ }
+-static char *getname_flags(const char __user * filename, int flags)
++static char *getname_flags(const char __user *filename, int flags, int *empty)
+ {
+       char *tmp, *result;
+@@ -148,6 +148,8 @@ static char *getname_flags(const char __
+               result = tmp;
+               if (retval < 0) {
++                      if (retval == -ENOENT && empty)
++                              *empty = 1;
+                       if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
+                               __putname(tmp);
+                               result = ERR_PTR(retval);
+@@ -160,7 +162,7 @@ static char *getname_flags(const char __
+ char *getname(const char __user * filename)
+ {
+-      return getname_flags(filename, 0);
++      return getname_flags(filename, 0, 0);
+ }
+ #ifdef CONFIG_AUDITSYSCALL
+@@ -1798,11 +1800,11 @@ struct dentry *lookup_one_len(const char
+       return __lookup_hash(&this, base, NULL);
+ }
+-int user_path_at(int dfd, const char __user *name, unsigned flags,
+-               struct path *path)
++int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
++               struct path *path, int *empty)
+ {
+       struct nameidata nd;
+-      char *tmp = getname_flags(name, flags);
++      char *tmp = getname_flags(name, flags, empty);
+       int err = PTR_ERR(tmp);
+       if (!IS_ERR(tmp)) {
+@@ -1816,6 +1818,12 @@ int user_path_at(int dfd, const char __u
+       return err;
+ }
++int user_path_at(int dfd, const char __user *name, unsigned flags,
++               struct path *path)
++{
++      return user_path_at_empty(dfd, name, flags, path, 0);
++}
++
+ static int user_path_parent(int dfd, const char __user *path,
+                       struct nameidata *nd, char **name)
+ {
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -294,15 +294,16 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, co
+ {
+       struct path path;
+       int error;
++      int empty = 0;
+       if (bufsiz <= 0)
+               return -EINVAL;
+-      error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path);
++      error = user_path_at_empty(dfd, pathname, LOOKUP_EMPTY, &path, &empty);
+       if (!error) {
+               struct inode *inode = path.dentry->d_inode;
+-              error = -EINVAL;
++              error = empty ? -ENOENT : -EINVAL;
+               if (inode->i_op->readlink) {
+                       error = security_inode_readlink(path.dentry);
+                       if (!error) {
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -67,6 +67,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA
+ #define LOOKUP_EMPTY          0x4000
+ extern int user_path_at(int, const char __user *, unsigned, struct path *);
++extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
+ #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
+ #define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
index ff7d642d556a60072f7c91cc35dd7fd0f72a7a40..8b73f61433b7720ae90beba4a3cd5b5dd86ca7fa 100644 (file)
@@ -147,3 +147,11 @@ md-raid10-fix-bug-when-activating-a-hot-spare.patch
 plat-mxc-iomux-v3.h-implicitly-enable-pull-up-down-when-that-s-desired.patch
 arm-pxa-cm-x300-properly-set-bt_reset-pin.patch
 arm-mach-ux500-unlock-i-d-l2x0-caches-before-init.patch
+mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch
+alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch
+iwlagn-do-not-use-interruptible-waits.patch
+um-fix-ubd-cow-size.patch
+readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch
+um-fix-kmalloc-argument-order-in-um-vdso-vma.c.patch
+omap-spi-fix-the-trying-to-free-nonexistent-resource-error.patch
+jsm-remove-buggy-write-queue.patch
diff --git a/queue-3.1/um-fix-kmalloc-argument-order-in-um-vdso-vma.c.patch b/queue-3.1/um-fix-kmalloc-argument-order-in-um-vdso-vma.c.patch
new file mode 100644 (file)
index 0000000..25f04ad
--- /dev/null
@@ -0,0 +1,30 @@
+From 0d65ede0a605d6252acc5c8a9c536c4cd0211f3c Mon Sep 17 00:00:00 2001
+From: Dave Jones <davej@redhat.com>
+Date: Mon, 24 Oct 2011 18:15:32 -0400
+Subject: um: Fix kmalloc argument order in um/vdso/vma.c
+
+From: Dave Jones <davej@redhat.com>
+
+commit 0d65ede0a605d6252acc5c8a9c536c4cd0211f3c upstream.
+
+kmalloc size is 1st arg, not second.
+
+Signed-off-by: Dave Jones <davej@redhat.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/um/sys-x86_64/vdso/vma.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/um/sys-x86_64/vdso/vma.c
++++ b/arch/um/sys-x86_64/vdso/vma.c
+@@ -28,7 +28,7 @@ static int __init init_vdso(void)
+       um_vdso_addr = task_size - PAGE_SIZE;
+-      vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
++      vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
+       if (!vdsop)
+               goto oom;
diff --git a/queue-3.1/um-fix-ubd-cow-size.patch b/queue-3.1/um-fix-ubd-cow-size.patch
new file mode 100644 (file)
index 0000000..2d03c6b
--- /dev/null
@@ -0,0 +1,66 @@
+From 8535639810e578960233ad39def3ac2157b0c3ec Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Wed, 2 Nov 2011 13:17:27 +0100
+Subject: um: fix ubd cow size
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 8535639810e578960233ad39def3ac2157b0c3ec upstream.
+
+ubd_file_size() cannot use ubd_dev->cow.file because at this time
+ubd_dev->cow.file is not initialized.
+Therefore, ubd_file_size() will always report a wrong disk size when
+COW files are used.
+Reading from /dev/ubd* would crash the kernel.
+
+We have to read the correct disk size from the COW file's backing
+file.
+
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/um/drivers/ubd_kern.c |   31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -513,8 +513,37 @@ __uml_exitcall(kill_io_thread);
+ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
+ {
+       char *file;
++      int fd;
++      int err;
+-      file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
++      __u32 version;
++      __u32 align;
++      char *backing_file;
++      time_t mtime;
++      unsigned long long size;
++      int sector_size;
++      int bitmap_offset;
++
++      if (ubd_dev->file && ubd_dev->cow.file) {
++              file = ubd_dev->cow.file;
++
++              goto out;
++      }
++
++      fd = os_open_file(ubd_dev->file, global_openflags, 0);
++      if (fd < 0)
++              return fd;
++
++      err = read_cow_header(file_reader, &fd, &version, &backing_file, \
++              &mtime, &size, &sector_size, &align, &bitmap_offset);
++      os_close_file(fd);
++
++      if(err == -EINVAL)
++              file = ubd_dev->file;
++      else
++              file = backing_file;
++
++out:
+       return os_file_size(file, size_out);
+ }