]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.7-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 12:39:41 +0000 (04:39 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 12:39:41 +0000 (04:39 -0800)
added patches:
b43-fix-firmware-loading-when-driver-is-built-into-the-kernel.patch
iwlwifi-fix-pcie-interrupt-handle-return-value.patch
iwlwifi-fix-the-reclaimed-packet-tracking-upon-flush-queue.patch
mac80211-fix-ibss-scanning.patch
mac80211-fix-station-destruction-in-ap-mesh-modes.patch
mac80211-use-del_timer_sync-for-final-sta-cleanup-timer-deletion.patch
mwifiex-check-wait_event_interruptible-return-value.patch
radeon-kms-force-rn50-chip-to-always-report-connected-on-analog-output.patch
staging-comedi-comedi_test-fix-race-when-cancelling-command.patch
staging-comedi-fix-minimum-ao-period-for-ni-625x-and-ni-628x.patch
staging-comedi-kconfig-comedi_ni_at_a2150-should-select-comedi_fc.patch
staging-comedi-prevent-auto-unconfig-of-manually-configured-devices.patch
staging-r8712u-add-new-device-id.patch
staging-speakup-avoid-out-of-range-access-in-synth_add.patch
staging-speakup-avoid-out-of-range-access-in-synth_init.patch
staging-zram-factor-out-zram_decompress_page-function.patch
staging-zram-fix-invalid-memory-references-during-disk-write.patch

18 files changed:
queue-3.7/b43-fix-firmware-loading-when-driver-is-built-into-the-kernel.patch [new file with mode: 0644]
queue-3.7/iwlwifi-fix-pcie-interrupt-handle-return-value.patch [new file with mode: 0644]
queue-3.7/iwlwifi-fix-the-reclaimed-packet-tracking-upon-flush-queue.patch [new file with mode: 0644]
queue-3.7/mac80211-fix-ibss-scanning.patch [new file with mode: 0644]
queue-3.7/mac80211-fix-station-destruction-in-ap-mesh-modes.patch [new file with mode: 0644]
queue-3.7/mac80211-use-del_timer_sync-for-final-sta-cleanup-timer-deletion.patch [new file with mode: 0644]
queue-3.7/mwifiex-check-wait_event_interruptible-return-value.patch [new file with mode: 0644]
queue-3.7/radeon-kms-force-rn50-chip-to-always-report-connected-on-analog-output.patch [new file with mode: 0644]
queue-3.7/series
queue-3.7/staging-comedi-comedi_test-fix-race-when-cancelling-command.patch [new file with mode: 0644]
queue-3.7/staging-comedi-fix-minimum-ao-period-for-ni-625x-and-ni-628x.patch [new file with mode: 0644]
queue-3.7/staging-comedi-kconfig-comedi_ni_at_a2150-should-select-comedi_fc.patch [new file with mode: 0644]
queue-3.7/staging-comedi-prevent-auto-unconfig-of-manually-configured-devices.patch [new file with mode: 0644]
queue-3.7/staging-r8712u-add-new-device-id.patch [new file with mode: 0644]
queue-3.7/staging-speakup-avoid-out-of-range-access-in-synth_add.patch [new file with mode: 0644]
queue-3.7/staging-speakup-avoid-out-of-range-access-in-synth_init.patch [new file with mode: 0644]
queue-3.7/staging-zram-factor-out-zram_decompress_page-function.patch [new file with mode: 0644]
queue-3.7/staging-zram-fix-invalid-memory-references-during-disk-write.patch [new file with mode: 0644]

diff --git a/queue-3.7/b43-fix-firmware-loading-when-driver-is-built-into-the-kernel.patch b/queue-3.7/b43-fix-firmware-loading-when-driver-is-built-into-the-kernel.patch
new file mode 100644 (file)
index 0000000..4633920
--- /dev/null
@@ -0,0 +1,199 @@
+From 5e20a4b53094651d80f856ff55a916b999dbb57a Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Thu, 20 Dec 2012 15:55:01 -0600
+Subject: b43: Fix firmware loading when driver is built into the kernel
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit 5e20a4b53094651d80f856ff55a916b999dbb57a upstream.
+
+Recent versions of udev cause synchronous firmware loading from the
+probe routine to fail because the request to user space would time
+out. The original fix for b43 (commit 6b6fa58) moved the firmware
+load from the probe routine to a work queue, but it still used synchronous
+firmware loading. This method is OK when b43 is built as a module;
+however, it fails when the driver is compiled into the kernel.
+
+This version changes the code to load the initial firmware file
+using request_firmware_nowait(). A completion event is used to
+hold the work queue until that file is available. This driver
+reads several firmware files - the remainder can be read synchronously.
+On some test systems, the async read fails; however, a following synch
+read works, thus the async failure falls through to the sync try.
+
+Reported-and-Tested by: Felix Janda <felix.janda@posteo.de>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/b43/b43.h  |    5 +++
+ drivers/net/wireless/b43/main.c |   54 ++++++++++++++++++++++++++++++----------
+ drivers/net/wireless/b43/main.h |    5 +--
+ 3 files changed, 48 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -7,6 +7,7 @@
+ #include <linux/hw_random.h>
+ #include <linux/bcma/bcma.h>
+ #include <linux/ssb/ssb.h>
++#include <linux/completion.h>
+ #include <net/mac80211.h>
+ #include "debugfs.h"
+@@ -722,6 +723,10 @@ enum b43_firmware_file_type {
+ struct b43_request_fw_context {
+       /* The device we are requesting the fw for. */
+       struct b43_wldev *dev;
++      /* a completion event structure needed if this call is asynchronous */
++      struct completion fw_load_complete;
++      /* a pointer to the firmware object */
++      const struct firmware *blob;
+       /* The type of firmware to request. */
+       enum b43_firmware_file_type req_type;
+       /* Error messages for each firmware type. */
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct
+               b43warn(wl, text);
+ }
++static void b43_fw_cb(const struct firmware *firmware, void *context)
++{
++      struct b43_request_fw_context *ctx = context;
++
++      ctx->blob = firmware;
++      complete(&ctx->fw_load_complete);
++}
++
+ int b43_do_request_fw(struct b43_request_fw_context *ctx,
+                     const char *name,
+-                    struct b43_firmware_file *fw)
++                    struct b43_firmware_file *fw, bool async)
+ {
+-      const struct firmware *blob;
+       struct b43_fw_header *hdr;
+       u32 size;
+       int err;
+@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request
+               B43_WARN_ON(1);
+               return -ENOSYS;
+       }
+-      err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
++      if (async) {
++              /* do this part asynchronously */
++              init_completion(&ctx->fw_load_complete);
++              err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
++                                            ctx->dev->dev->dev, GFP_KERNEL,
++                                            ctx, b43_fw_cb);
++              if (err < 0) {
++                      pr_err("Unable to load firmware\n");
++                      return err;
++              }
++              /* stall here until fw ready */
++              wait_for_completion(&ctx->fw_load_complete);
++              if (ctx->blob)
++                      goto fw_ready;
++      /* On some ARM systems, the async request will fail, but the next sync
++       * request works. For this reason, we dall through here
++       */
++      }
++      err = request_firmware(&ctx->blob, ctx->fwname,
++                             ctx->dev->dev->dev);
+       if (err == -ENOENT) {
+               snprintf(ctx->errors[ctx->req_type],
+                        sizeof(ctx->errors[ctx->req_type]),
+-                       "Firmware file \"%s\" not found\n", ctx->fwname);
++                       "Firmware file \"%s\" not found\n",
++                       ctx->fwname);
+               return err;
+       } else if (err) {
+               snprintf(ctx->errors[ctx->req_type],
+@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request
+                        ctx->fwname, err);
+               return err;
+       }
+-      if (blob->size < sizeof(struct b43_fw_header))
++fw_ready:
++      if (ctx->blob->size < sizeof(struct b43_fw_header))
+               goto err_format;
+-      hdr = (struct b43_fw_header *)(blob->data);
++      hdr = (struct b43_fw_header *)(ctx->blob->data);
+       switch (hdr->type) {
+       case B43_FW_TYPE_UCODE:
+       case B43_FW_TYPE_PCM:
+               size = be32_to_cpu(hdr->size);
+-              if (size != blob->size - sizeof(struct b43_fw_header))
++              if (size != ctx->blob->size - sizeof(struct b43_fw_header))
+                       goto err_format;
+               /* fallthrough */
+       case B43_FW_TYPE_IV:
+@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request
+               goto err_format;
+       }
+-      fw->data = blob;
++      fw->data = ctx->blob;
+       fw->filename = name;
+       fw->type = ctx->req_type;
+@@ -2172,7 +2200,7 @@ err_format:
+       snprintf(ctx->errors[ctx->req_type],
+                sizeof(ctx->errors[ctx->req_type]),
+                "Firmware file \"%s\" format error.\n", ctx->fwname);
+-      release_firmware(blob);
++      release_firmware(ctx->blob);
+       return -EPROTO;
+ }
+@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43
+                       goto err_no_ucode;
+               }
+       }
+-      err = b43_do_request_fw(ctx, filename, &fw->ucode);
++      err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
+       if (err)
+               goto err_load;
+@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43
+       else
+               goto err_no_pcm;
+       fw->pcm_request_failed = false;
+-      err = b43_do_request_fw(ctx, filename, &fw->pcm);
++      err = b43_do_request_fw(ctx, filename, &fw->pcm, false);
+       if (err == -ENOENT) {
+               /* We did not find a PCM file? Not fatal, but
+                * core rev <= 10 must do without hwcrypto then. */
+@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43
+       default:
+               goto err_no_initvals;
+       }
+-      err = b43_do_request_fw(ctx, filename, &fw->initvals);
++      err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
+       if (err)
+               goto err_load;
+@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43
+       default:
+               goto err_no_initvals;
+       }
+-      err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
++      err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
+       if (err)
+               goto err_load;
+--- a/drivers/net/wireless/b43/main.h
++++ b/drivers/net/wireless/b43/main.h
+@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wl
+ struct b43_request_fw_context;
+-int b43_do_request_fw(struct b43_request_fw_context *ctx,
+-                    const char *name,
+-                    struct b43_firmware_file *fw);
++int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name,
++                    struct b43_firmware_file *fw, bool async);
+ void b43_do_release_fw(struct b43_firmware_file *fw);
+ #endif /* B43_MAIN_H_ */
diff --git a/queue-3.7/iwlwifi-fix-pcie-interrupt-handle-return-value.patch b/queue-3.7/iwlwifi-fix-pcie-interrupt-handle-return-value.patch
new file mode 100644 (file)
index 0000000..8fbffc6
--- /dev/null
@@ -0,0 +1,34 @@
+From 392d4cad7907f6cb4ffc85e135a01abfddc89027 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 27 Dec 2012 21:37:04 +0100
+Subject: iwlwifi: fix PCIe interrupt handle return value
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 392d4cad7907f6cb4ffc85e135a01abfddc89027 upstream.
+
+By accident, commit eb6476441bc2fecf6232a87d0313a85f8e3da7f4
+("iwlwifi: protect use_ict with irq_lock") changed the return
+value of the iwl_pcie_isr() function in case it handles an
+interrupt -- it now returns IRQ_NONE instead of IRQ_HANDLED.
+
+Put back the correct return value.
+
+Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/iwlwifi/pcie/rx.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
++++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
+@@ -971,6 +971,7 @@ static irqreturn_t iwl_isr(int irq, void
+       else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
+                !trans_pcie->inta)
+               iwl_enable_interrupts(trans);
++      return IRQ_HANDLED;
+ none:
+       /* re-enable interrupts here since we don't have anything to service. */
diff --git a/queue-3.7/iwlwifi-fix-the-reclaimed-packet-tracking-upon-flush-queue.patch b/queue-3.7/iwlwifi-fix-the-reclaimed-packet-tracking-upon-flush-queue.patch
new file mode 100644 (file)
index 0000000..093a6b4
--- /dev/null
@@ -0,0 +1,66 @@
+From f590dcec944552f9a4a61155810f3abd17d6465d Mon Sep 17 00:00:00 2001
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Date: Mon, 31 Dec 2012 09:26:10 +0200
+Subject: iwlwifi: fix the reclaimed packet tracking upon flush queue
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+commit f590dcec944552f9a4a61155810f3abd17d6465d upstream.
+
+There's a bug in the currently released firmware version,
+the sequence control in the Tx response isn't updated in
+all cases. Take it from the packet as a workaround.
+
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/iwlwifi/dvm/tx.c |   24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
+@@ -1154,13 +1154,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *
+                       next_reclaimed = ssn;
+               }
+-              if (tid != IWL_TID_NON_QOS) {
+-                      priv->tid_data[sta_id][tid].next_reclaimed =
+-                              next_reclaimed;
+-                      IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
+-                                                next_reclaimed);
+-              }
+-
+               iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);
+               iwlagn_check_ratid_empty(priv, sta_id, tid);
+@@ -1211,11 +1204,28 @@ int iwlagn_rx_reply_tx(struct iwl_priv *
+                       if (!is_agg)
+                               iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
++                      /*
++                       * W/A for FW bug - the seq_ctl isn't updated when the
++                       * queues are flushed. Fetch it from the packet itself
++                       */
++                      if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) {
++                              next_reclaimed = le16_to_cpu(hdr->seq_ctrl);
++                              next_reclaimed =
++                                      SEQ_TO_SN(next_reclaimed + 0x10);
++                      }
++
+                       is_offchannel_skb =
+                               (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
+                       freed++;
+               }
++              if (tid != IWL_TID_NON_QOS) {
++                      priv->tid_data[sta_id][tid].next_reclaimed =
++                              next_reclaimed;
++                      IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
++                                         next_reclaimed);
++              }
++
+               WARN_ON(!is_agg && freed != 1);
+               /*
diff --git a/queue-3.7/mac80211-fix-ibss-scanning.patch b/queue-3.7/mac80211-fix-ibss-scanning.patch
new file mode 100644 (file)
index 0000000..10023cd
--- /dev/null
@@ -0,0 +1,130 @@
+From 34bcf71502413f8903ade93746f2d0f04b937a78 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Tue, 11 Dec 2012 10:48:23 +0100
+Subject: mac80211: fix ibss scanning
+
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+
+commit 34bcf71502413f8903ade93746f2d0f04b937a78 upstream.
+
+Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this
+can trigger Microcode errors on iwlwifi and iwlegacy drivers.
+
+Also rename ieee80211_request_internal_scan() function since it is only
+used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss().
+
+This patch should address:
+https://bugzilla.redhat.com/show_bug.cgi?id=883414
+https://bugzilla.kernel.org/show_bug.cgi?id=49411
+
+Reported-by: Jesse Kahtava <jesse_kahtava@f-m.fm>
+Reported-by: Mikko Rapeli  <mikko.rapeli@iki.fi>
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/ibss.c        |    9 ++++-----
+ net/mac80211/ieee80211_i.h |    6 +++---
+ net/mac80211/scan.c        |   34 ++++++++++++++++++++++++----------
+ 3 files changed, 31 insertions(+), 18 deletions(-)
+
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(str
+       sdata_info(sdata,
+                  "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
+-      ieee80211_request_internal_scan(sdata,
+-                      ifibss->ssid, ifibss->ssid_len, NULL);
++      ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
++                                  NULL);
+ }
+ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
+@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(stru
+                                       IEEE80211_SCAN_INTERVAL)) {
+               sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
+-              ieee80211_request_internal_scan(sdata,
+-                              ifibss->ssid, ifibss->ssid_len,
+-                              ifibss->fixed_channel ? ifibss->channel : NULL);
++              ieee80211_request_ibss_scan(sdata, ifibss->ssid,
++                                          ifibss->ssid_len, chan);
+       } else {
+               int interval = IEEE80211_SCAN_INTERVAL;
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struc
+ /* scan/BSS handling */
+ void ieee80211_scan_work(struct work_struct *work);
+-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
+-                                  const u8 *ssid, u8 ssid_len,
+-                                  struct ieee80211_channel *chan);
++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
++                              const u8 *ssid, u8 ssid_len,
++                              struct ieee80211_channel *chan);
+ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
+                          struct cfg80211_scan_request *req);
+ void ieee80211_scan_cancel(struct ieee80211_local *local);
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80
+       return res;
+ }
+-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
+-                                  const u8 *ssid, u8 ssid_len,
+-                                  struct ieee80211_channel *chan)
++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
++                              const u8 *ssid, u8 ssid_len,
++                              struct ieee80211_channel *chan)
+ {
+       struct ieee80211_local *local = sdata->local;
+       int ret = -EBUSY;
+@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(stru
+       /* fill internal scan request */
+       if (!chan) {
+-              int i, nchan = 0;
++              int i, max_n;
++              int n_ch = 0;
+               for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+                       if (!local->hw.wiphy->bands[band])
+                               continue;
+-                      for (i = 0;
+-                           i < local->hw.wiphy->bands[band]->n_channels;
+-                           i++) {
+-                              local->int_scan_req->channels[nchan] =
++
++                      max_n = local->hw.wiphy->bands[band]->n_channels;
++                      for (i = 0; i < max_n; i++) {
++                              struct ieee80211_channel *tmp_ch =
+                                   &local->hw.wiphy->bands[band]->channels[i];
+-                              nchan++;
++
++                              if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS |
++                                                   IEEE80211_CHAN_DISABLED))
++                                      continue;
++
++                              local->int_scan_req->channels[n_ch] = tmp_ch;
++                              n_ch++;
+                       }
+               }
+-              local->int_scan_req->n_channels = nchan;
++              if (WARN_ON_ONCE(n_ch == 0))
++                      goto unlock;
++
++              local->int_scan_req->n_channels = n_ch;
+       } else {
++              if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS |
++                                              IEEE80211_CHAN_DISABLED)))
++                      goto unlock;
++
+               local->int_scan_req->channels[0] = chan;
+               local->int_scan_req->n_channels = 1;
+       }
diff --git a/queue-3.7/mac80211-fix-station-destruction-in-ap-mesh-modes.patch b/queue-3.7/mac80211-fix-station-destruction-in-ap-mesh-modes.patch
new file mode 100644 (file)
index 0000000..2a09256
--- /dev/null
@@ -0,0 +1,202 @@
+From 97f97b1f5fe0878b35c8e314f98591771696321b Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 13 Dec 2012 22:54:58 +0100
+Subject: mac80211: fix station destruction in AP/mesh modes
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 97f97b1f5fe0878b35c8e314f98591771696321b upstream.
+
+Unfortunately, commit b22cfcfcae5b, intended to speed up roaming
+by avoiding the synchronize_rcu() broke AP/mesh modes as it moved
+some code into that work item that will still call into the driver
+at a time where it's no longer expected to handle this: after the
+AP or mesh has been stopped.
+
+To fix this problem remove the per-station work struct, maintain a
+station cleanup list instead and flush this list when stations are
+flushed. To keep this patch smaller for stable, do this when the
+stations are flushed (sta_info_flush()). This unfortunately brings
+back the original roaming delay; I'll fix that again in a separate
+patch.
+
+Also, Ben reported that the original commit could sometimes (with
+many interfaces) cause long delays when an interface is set down,
+due to blocking on flush_workqueue(). Since we now maintain the
+cleanup list, this particular change of the original patch can be
+reverted.
+
+Reported-by: Ben Greear <greearb@candelatech.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/ieee80211_i.h |    4 ++++
+ net/mac80211/iface.c       |   28 ++++++++++++++++------------
+ net/mac80211/sta_info.c    |   44 ++++++++++++++++++++++++++++++++++++++++----
+ net/mac80211/sta_info.h    |    3 ++-
+ 4 files changed, 62 insertions(+), 17 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -730,6 +730,10 @@ struct ieee80211_sub_if_data {
+               u32 mntr_flags;
+       } u;
++      spinlock_t cleanup_stations_lock;
++      struct list_head cleanup_stations;
++      struct work_struct cleanup_stations_wk;
++
+ #ifdef CONFIG_MAC80211_DEBUGFS
+       struct {
+               struct dentry *dir;
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -793,20 +793,11 @@ static void ieee80211_do_stop(struct iee
+               flush_work(&sdata->work);
+               /*
+                * When we get here, the interface is marked down.
+-               * Call rcu_barrier() to wait both for the RX path
++               * Call synchronize_rcu() to wait for the RX path
+                * should it be using the interface and enqueuing
+-               * frames at this very time on another CPU, and
+-               * for the sta free call_rcu callbacks.
++               * frames at this very time on another CPU.
+                */
+-              rcu_barrier();
+-
+-              /*
+-               * free_sta_rcu() enqueues a work for the actual
+-               * sta cleanup, so we need to flush it while
+-               * sdata is still valid.
+-               */
+-              flush_workqueue(local->workqueue);
+-
++              synchronize_rcu();
+               skb_queue_purge(&sdata->skb_queue);
+               /*
+@@ -1432,6 +1423,15 @@ static void ieee80211_assign_perm_addr(s
+       mutex_unlock(&local->iflist_mtx);
+ }
++static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
++{
++      struct ieee80211_sub_if_data *sdata;
++
++      sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
++
++      ieee80211_cleanup_sdata_stas(sdata);
++}
++
+ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
+                    struct wireless_dev **new_wdev, enum nl80211_iftype type,
+                    struct vif_params *params)
+@@ -1507,6 +1507,10 @@ int ieee80211_if_add(struct ieee80211_lo
+       INIT_LIST_HEAD(&sdata->key_list);
++      spin_lock_init(&sdata->cleanup_stations_lock);
++      INIT_LIST_HEAD(&sdata->cleanup_stations);
++      INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
++
+       for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+               struct ieee80211_supported_band *sband;
+               sband = local->hw.wiphy->bands[i];
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee
+       return -ENOENT;
+ }
+-static void free_sta_work(struct work_struct *wk)
++static void cleanup_single_sta(struct sta_info *sta)
+ {
+-      struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk);
+       int ac, i;
+       struct tid_ampdu_tx *tid_tx;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+@@ -148,11 +147,35 @@ static void free_sta_work(struct work_st
+       sta_info_free(local, sta);
+ }
++void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata)
++{
++      struct sta_info *sta;
++
++      spin_lock_bh(&sdata->cleanup_stations_lock);
++      while (!list_empty(&sdata->cleanup_stations)) {
++              sta = list_first_entry(&sdata->cleanup_stations,
++                                     struct sta_info, list);
++              list_del(&sta->list);
++              spin_unlock_bh(&sdata->cleanup_stations_lock);
++
++              cleanup_single_sta(sta);
++
++              spin_lock_bh(&sdata->cleanup_stations_lock);
++      }
++
++      spin_unlock_bh(&sdata->cleanup_stations_lock);
++}
++
+ static void free_sta_rcu(struct rcu_head *h)
+ {
+       struct sta_info *sta = container_of(h, struct sta_info, rcu_head);
++      struct ieee80211_sub_if_data *sdata = sta->sdata;
+-      ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk);
++      spin_lock(&sdata->cleanup_stations_lock);
++      list_add_tail(&sta->list, &sdata->cleanup_stations);
++      spin_unlock(&sdata->cleanup_stations_lock);
++
++      ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk);
+ }
+ /* protected by RCU */
+@@ -305,7 +328,6 @@ struct sta_info *sta_info_alloc(struct i
+       spin_lock_init(&sta->lock);
+       INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
+-      INIT_WORK(&sta->free_sta_wk, free_sta_work);
+       INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
+       mutex_init(&sta->ampdu_mlme.mtx);
+@@ -877,6 +899,20 @@ int sta_info_flush(struct ieee80211_loca
+       }
+       mutex_unlock(&local->sta_mtx);
++      rcu_barrier();
++
++      if (sdata) {
++              ieee80211_cleanup_sdata_stas(sdata);
++              cancel_work_sync(&sdata->cleanup_stations_wk);
++      } else {
++              mutex_lock(&local->iflist_mtx);
++              list_for_each_entry(sdata, &local->interfaces, list) {
++                      ieee80211_cleanup_sdata_stas(sdata);
++                      cancel_work_sync(&sdata->cleanup_stations_wk);
++              }
++              mutex_unlock(&local->iflist_mtx);
++      }
++
+       return ret;
+ }
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -298,7 +298,6 @@ struct sta_info {
+       spinlock_t lock;
+       struct work_struct drv_unblock_wk;
+-      struct work_struct free_sta_wk;
+       u16 listen_interval;
+@@ -558,4 +557,6 @@ void ieee80211_sta_ps_deliver_wakeup(str
+ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
+ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
++void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata);
++
+ #endif /* STA_INFO_H */
diff --git a/queue-3.7/mac80211-use-del_timer_sync-for-final-sta-cleanup-timer-deletion.patch b/queue-3.7/mac80211-use-del_timer_sync-for-final-sta-cleanup-timer-deletion.patch
new file mode 100644 (file)
index 0000000..c429b06
--- /dev/null
@@ -0,0 +1,35 @@
+From a56f992cdabc63f56b4b142885deebebf936ff76 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 13 Dec 2012 23:08:52 +0100
+Subject: mac80211: use del_timer_sync for final sta cleanup timer deletion
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit a56f992cdabc63f56b4b142885deebebf936ff76 upstream.
+
+This is a very old bug, but there's nothing that prevents the
+timer from running while the module is being removed when we
+only do del_timer() instead of del_timer_sync().
+
+The timer should normally not be running at this point, but
+it's not clearly impossible (or we could just remove this.)
+
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/sta_info.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -870,7 +870,7 @@ void sta_info_init(struct ieee80211_loca
+ void sta_info_stop(struct ieee80211_local *local)
+ {
+-      del_timer(&local->sta_cleanup);
++      del_timer_sync(&local->sta_cleanup);
+       sta_info_flush(local, NULL);
+ }
diff --git a/queue-3.7/mwifiex-check-wait_event_interruptible-return-value.patch b/queue-3.7/mwifiex-check-wait_event_interruptible-return-value.patch
new file mode 100644 (file)
index 0000000..5c33ab1
--- /dev/null
@@ -0,0 +1,73 @@
+From 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 Mon Sep 17 00:00:00 2001
+From: Bing Zhao <bzhao@marvell.com>
+Date: Wed, 2 Jan 2013 16:07:35 -0800
+Subject: mwifiex: check wait_event_interruptible return value
+
+From: Bing Zhao <bzhao@marvell.com>
+
+commit 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 upstream.
+
+wait_event_interruptible function returns -ERESTARTSYS if it's
+interrupted by a signal. Driver should check the return value
+and handle this case properly.
+
+In mwifiex_wait_queue_complete() routine, as we are now checking
+wait_event_interruptible return value, the condition check is not
+required. Also, we have removed mwifiex_cancel_pending_ioctl()
+call to avoid a chance of sending second command to FW by other path
+as soon as we clear current command node. FW can not handle two
+commands simultaneously.
+
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/sta_ioctl.c |   21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
+@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifi
+  */
+ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
+ {
+-      bool cancel_flag = false;
+       int status;
+       struct cmd_ctrl_node *cmd_queued;
+@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct m
+       atomic_inc(&adapter->cmd_pending);
+       /* Wait for completion */
+-      wait_event_interruptible(adapter->cmd_wait_q.wait,
+-                               *(cmd_queued->condition));
+-      if (!*(cmd_queued->condition))
+-              cancel_flag = true;
+-
+-      if (cancel_flag) {
+-              mwifiex_cancel_pending_ioctl(adapter);
+-              dev_dbg(adapter->dev, "cmd cancel\n");
++      status = wait_event_interruptible(adapter->cmd_wait_q.wait,
++                                        *(cmd_queued->condition));
++      if (status) {
++              dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
++              return status;
+       }
+       status = adapter->cmd_wait_q.status;
+@@ -480,8 +476,11 @@ int mwifiex_enable_hs(struct mwifiex_ada
+               return false;
+       }
+-      wait_event_interruptible(adapter->hs_activate_wait_q,
+-                               adapter->hs_activate_wait_q_woken);
++      if (wait_event_interruptible(adapter->hs_activate_wait_q,
++                                   adapter->hs_activate_wait_q_woken)) {
++              dev_err(adapter->dev, "hs_activate_wait_q terminated\n");
++              return false;
++      }
+       return true;
+ }
diff --git a/queue-3.7/radeon-kms-force-rn50-chip-to-always-report-connected-on-analog-output.patch b/queue-3.7/radeon-kms-force-rn50-chip-to-always-report-connected-on-analog-output.patch
new file mode 100644 (file)
index 0000000..d4879f6
--- /dev/null
@@ -0,0 +1,38 @@
+From 51861d4eebc2ddc25c77084343d060fa79f6e291 Mon Sep 17 00:00:00 2001
+From: Jerome Glisse <jglisse@redhat.com>
+Date: Tue, 8 Jan 2013 18:41:01 -0500
+Subject: radeon/kms: force rn50 chip to always report connected on analog output
+
+From: Jerome Glisse <jglisse@redhat.com>
+
+commit 51861d4eebc2ddc25c77084343d060fa79f6e291 upstream.
+
+Those rn50 chip are often connected to console remoting hw and load
+detection often fails with those. Just don't try to load detect and
+report connect.
+
+Signed-off-by: Jerome Glisse <jglisse@redhat.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/radeon_legacy_encoders.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
++++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_
+       enum drm_connector_status found = connector_status_disconnected;
+       bool color = true;
++      /* just don't bother on RN50 those chip are often connected to remoting
++       * console hw and often we get failure to load detect those. So to make
++       * everyone happy report the encoder as always connected.
++       */
++      if (ASIC_IS_RN50(rdev)) {
++              return connector_status_connected;
++      }
++
+       /* save the regs we need */
+       vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+       crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
index 2ac8ad667c91138636a6be5c5c170c3baedc320a..3798ef542501670bf41be828d2be0ae991b8ba69 100644 (file)
@@ -137,3 +137,20 @@ revert-alsa-hda-shut-up-pins-at-power-saving-mode-with-conexnat-codecs.patch
 alsa-hda-disable-runtime-d3-for-intel-cpt-co.patch
 alsa-pxa27x-fix-ac97-cold-reset.patch
 alsa-pxa27x-fix-ac97-warm-reset.patch
+staging-comedi-prevent-auto-unconfig-of-manually-configured-devices.patch
+staging-comedi-fix-minimum-ao-period-for-ni-625x-and-ni-628x.patch
+staging-comedi-kconfig-comedi_ni_at_a2150-should-select-comedi_fc.patch
+staging-comedi-comedi_test-fix-race-when-cancelling-command.patch
+staging-r8712u-add-new-device-id.patch
+staging-speakup-avoid-out-of-range-access-in-synth_init.patch
+staging-speakup-avoid-out-of-range-access-in-synth_add.patch
+staging-zram-factor-out-zram_decompress_page-function.patch
+staging-zram-fix-invalid-memory-references-during-disk-write.patch
+radeon-kms-force-rn50-chip-to-always-report-connected-on-analog-output.patch
+iwlwifi-fix-pcie-interrupt-handle-return-value.patch
+iwlwifi-fix-the-reclaimed-packet-tracking-upon-flush-queue.patch
+mac80211-fix-ibss-scanning.patch
+mac80211-fix-station-destruction-in-ap-mesh-modes.patch
+mac80211-use-del_timer_sync-for-final-sta-cleanup-timer-deletion.patch
+mwifiex-check-wait_event_interruptible-return-value.patch
+b43-fix-firmware-loading-when-driver-is-built-into-the-kernel.patch
diff --git a/queue-3.7/staging-comedi-comedi_test-fix-race-when-cancelling-command.patch b/queue-3.7/staging-comedi-comedi_test-fix-race-when-cancelling-command.patch
new file mode 100644 (file)
index 0000000..87302f3
--- /dev/null
@@ -0,0 +1,45 @@
+From c0729eeefdcd76db338f635162bf0739fd2c5f6f Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Fri, 4 Jan 2013 11:33:21 +0000
+Subject: staging: comedi: comedi_test: fix race when cancelling command
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit c0729eeefdcd76db338f635162bf0739fd2c5f6f upstream.
+
+Éric Piel reported a kernel oops in the "comedi_test" module.  It was a
+NULL pointer dereference within `waveform_ai_interrupt()` (actually a
+timer function) that sometimes occurred when a running asynchronous
+command is cancelled (either by the `COMEDI_CANCEL` ioctl or by closing
+the device file).
+
+This seems to be a race between the caller of `waveform_ai_cancel()`
+which on return from that function goes and tears down the running
+command, and the timer function which uses the command.  In particular,
+`async->cmd.chanlist` gets freed (and the pointer set to NULL) by
+`do_become_nonbusy()` in "comedi_fops.c" but a previously scheduled
+`waveform_ai_interrupt()` timer function will dereference that pointer
+regardless, leading to the oops.
+
+Fix it by replacing the `del_timer()` call in `waveform_ai_cancel()`
+with `del_timer_sync()`.
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Reported-by: Ã‰ric Piel <piel@delmic.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/comedi_test.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -372,7 +372,7 @@ static int waveform_ai_cancel(struct com
+       struct waveform_private *devpriv = dev->private;
+       devpriv->timer_running = 0;
+-      del_timer(&devpriv->timer);
++      del_timer_sync(&devpriv->timer);
+       return 0;
+ }
diff --git a/queue-3.7/staging-comedi-fix-minimum-ao-period-for-ni-625x-and-ni-628x.patch b/queue-3.7/staging-comedi-fix-minimum-ao-period-for-ni-625x-and-ni-628x.patch
new file mode 100644 (file)
index 0000000..29416f7
--- /dev/null
@@ -0,0 +1,103 @@
+From 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 Mon Sep 17 00:00:00 2001
+From: Ã‰ric Piel <piel@delmic.com>
+Date: Wed, 19 Dec 2012 13:03:13 +0100
+Subject: staging: comedi: fix minimum AO period for NI 625x and NI 628x
+
+From: Ã‰ric Piel <piel@delmic.com>
+
+commit 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 upstream.
+
+The minimum period was set to 357 ns, while the divider for these boards is 50
+ns. This prevented to output at maximum speed as ni_ao_cmdtest() would return
+357 but would not accept it.
+
+Not sure why it was set to 357 ns (this was done before the git history,
+which starts 5 years ago). My guess is that it comes from reading the
+specification stating a 2.8 MHz rate (~ 357 ns). The latest
+specification states a 2.86 MHz rate (~ 350 ns), which makes a lot
+more sense.
+
+Tested on a pci-6251.
+
+Signed-off-by: Ã‰ric Piel <piel@delmic.com>
+Acked-By: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/ni_pcimio.c |   16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_625x_ao,
+        .reg_type = ni_reg_625x,
+        .ao_unipolar = 0,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 8,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_625x_ao,
+        .reg_type = ni_reg_625x,
+        .ao_unipolar = 0,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 8,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_625x_ao,
+        .reg_type = ni_reg_625x,
+        .ao_unipolar = 0,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 8,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_625x_ao,
+        .reg_type = ni_reg_625x,
+        .ao_unipolar = 0,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 32,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_625x_ao,
+        .reg_type = ni_reg_625x,
+        .ao_unipolar = 0,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 32,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_628x_ao,
+        .reg_type = ni_reg_628x,
+        .ao_unipolar = 1,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 8,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_628x_ao,
+        .reg_type = ni_reg_628x,
+        .ao_unipolar = 1,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 8,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_b
+        .ao_range_table = &range_ni_M_628x_ao,
+        .reg_type = ni_reg_628x,
+        .ao_unipolar = 1,
+-       .ao_speed = 357,
++       .ao_speed = 350,
+        .num_p0_dio_channels = 32,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
diff --git a/queue-3.7/staging-comedi-kconfig-comedi_ni_at_a2150-should-select-comedi_fc.patch b/queue-3.7/staging-comedi-kconfig-comedi_ni_at_a2150-should-select-comedi_fc.patch
new file mode 100644 (file)
index 0000000..d2b92b0
--- /dev/null
@@ -0,0 +1,30 @@
+From 34ffb33e09132401872fe79e95c30824ce194d23 Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Thu, 3 Jan 2013 12:15:26 +0000
+Subject: staging: comedi: Kconfig: COMEDI_NI_AT_A2150 should select COMEDI_FC
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 34ffb33e09132401872fe79e95c30824ce194d23 upstream.
+
+The 'ni_at_a2150' module links to `cfc_write_to_buffer` in the
+'comedi_fc' module, so selecting 'COMEDI_NI_AT_A2150' in the kernel config
+needs to also select 'COMEDI_FC'.
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/Kconfig |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/comedi/Kconfig
++++ b/drivers/staging/comedi/Kconfig
+@@ -444,6 +444,7 @@ config COMEDI_ADQ12B
+ config COMEDI_NI_AT_A2150
+       tristate "NI AT-A2150 ISA card support"
++      select COMEDI_FC
+       depends on VIRT_TO_BUS
+       ---help---
+         Enable support for National Instruments AT-A2150 cards
diff --git a/queue-3.7/staging-comedi-prevent-auto-unconfig-of-manually-configured-devices.patch b/queue-3.7/staging-comedi-prevent-auto-unconfig-of-manually-configured-devices.patch
new file mode 100644 (file)
index 0000000..e504053
--- /dev/null
@@ -0,0 +1,48 @@
+From 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Tue, 4 Dec 2012 15:59:55 +0000
+Subject: staging: comedi: prevent auto-unconfig of manually configured devices
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c upstream.
+
+When a low-level comedi driver auto-configures a device, a `struct
+comedi_dev_file_info` is allocated (as well as a `struct
+comedi_device`) by `comedi_alloc_board_minor()`.  A pointer to the
+hardware `struct device` is stored as a cookie in the `struct
+comedi_dev_file_info`.  When the low-level comedi driver
+auto-unconfigures the device, `comedi_auto_unconfig()` uses the cookie
+to find the `struct comedi_dev_file_info` so it can detach the comedi
+device from the driver, clean it up and free it.
+
+A problem arises if the user manually unconfigures and reconfigures the
+comedi device using the `COMEDI_DEVCONFIG` ioctl so that is no longer
+associated with the original hardware device.  The problem is that the
+cookie is not cleared, so that a call to `comedi_auto_unconfig()` from
+the low-level driver will still find it, detach it, clean it up and free
+it.
+
+Stop this problem occurring by always clearing the `hardware_device`
+cookie in the `struct comedi_dev_file_info` whenever the
+`COMEDI_DEVCONFIG` ioctl call is successful.
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/comedi_fops.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -1546,6 +1546,9 @@ static long comedi_unlocked_ioctl(struct
+       if (cmd == COMEDI_DEVCONFIG) {
+               rc = do_devconfig_ioctl(dev,
+                                       (struct comedi_devconfig __user *)arg);
++              if (rc == 0)
++                      /* Evade comedi_auto_unconfig(). */
++                      dev_file_info->hardware_device = NULL;
+               goto done;
+       }
diff --git a/queue-3.7/staging-r8712u-add-new-device-id.patch b/queue-3.7/staging-r8712u-add-new-device-id.patch
new file mode 100644 (file)
index 0000000..0a0bfde
--- /dev/null
@@ -0,0 +1,32 @@
+From da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Sat, 29 Dec 2012 11:36:53 -0600
+Subject: staging: r8712u: Add new device ID
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 upstream.
+
+The ISY IWL 1000 USB WLAN stick with USB ID 050d:11f1 is a clone of
+the Belkin F7D1101 V1 device.
+
+Reported-by: Thomas Hartmann <hartmann@ict.tuwien.ac.at>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Cc: Thomas Hartmann <hartmann@ict.tuwien.ac.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/rtl8712/usb_intf.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/rtl8712/usb_intf.c
++++ b/drivers/staging/rtl8712/usb_intf.c
+@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_
+       {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
+       /* Belkin */
+       {USB_DEVICE(0x050D, 0x945A)},
++      /* ISY IWL - Belkin clone */
++      {USB_DEVICE(0x050D, 0x11F1)},
+       /* Corega */
+       {USB_DEVICE(0x07AA, 0x0047)},
+       /* D-Link */
diff --git a/queue-3.7/staging-speakup-avoid-out-of-range-access-in-synth_add.patch b/queue-3.7/staging-speakup-avoid-out-of-range-access-in-synth_add.patch
new file mode 100644 (file)
index 0000000..26b556d
--- /dev/null
@@ -0,0 +1,30 @@
+From 6102c48bd421074a33e102f2ebda3724e8d275f9 Mon Sep 17 00:00:00 2001
+From: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Date: Mon, 7 Jan 2013 22:03:51 +0100
+Subject: staging: speakup: avoid out-of-range access in synth_add()
+
+From: Samuel Thibault <samuel.thibault@ens-lyon.org>
+
+commit 6102c48bd421074a33e102f2ebda3724e8d275f9 upstream.
+
+Check that array index is in-bounds before accessing the synths[] array.
+
+Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Cc: Nickolai Zeldovich <nickolai@csail.mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/speakup/synth.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/speakup/synth.c
++++ b/drivers/staging/speakup/synth.c
+@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth
+       int i;
+       int status = 0;
+       mutex_lock(&spk_mutex);
+-      for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
++      for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
+               /* synth_remove() is responsible for rotating the array down */
+               if (in_synth == synths[i]) {
+                       mutex_unlock(&spk_mutex);
diff --git a/queue-3.7/staging-speakup-avoid-out-of-range-access-in-synth_init.patch b/queue-3.7/staging-speakup-avoid-out-of-range-access-in-synth_init.patch
new file mode 100644 (file)
index 0000000..0cd3e61
--- /dev/null
@@ -0,0 +1,30 @@
+From ae428655b826f2755a8101b27beda42a275ef8ad Mon Sep 17 00:00:00 2001
+From: Nickolai Zeldovich <nickolai@csail.mit.edu>
+Date: Sat, 5 Jan 2013 14:17:45 -0500
+Subject: staging: speakup: avoid out-of-range access in synth_init()
+
+From: Nickolai Zeldovich <nickolai@csail.mit.edu>
+
+commit ae428655b826f2755a8101b27beda42a275ef8ad upstream.
+
+Check that array index is in-bounds before accessing the synths[] array.
+
+Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu>
+Cc: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/speakup/synth.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/speakup/synth.c
++++ b/drivers/staging/speakup/synth.c
+@@ -342,7 +342,7 @@ int synth_init(char *synth_name)
+       mutex_lock(&spk_mutex);
+       /* First, check if we already have it loaded. */
+-      for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
++      for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
+               if (strcmp(synths[i]->name, synth_name) == 0)
+                       synth = synths[i];
diff --git a/queue-3.7/staging-zram-factor-out-zram_decompress_page-function.patch b/queue-3.7/staging-zram-factor-out-zram_decompress_page-function.patch
new file mode 100644 (file)
index 0000000..044d0ea
--- /dev/null
@@ -0,0 +1,179 @@
+From 37b51fdddf64e7ba0971d070428655f8d6f36578 Mon Sep 17 00:00:00 2001
+From: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Date: Tue, 30 Oct 2012 22:40:23 +0300
+Subject: staging: zram: factor-out zram_decompress_page() function
+
+From: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+
+commit 37b51fdddf64e7ba0971d070428655f8d6f36578 upstream.
+
+zram_bvec_read() shared decompress functionality with zram_read_before_write() function.
+Factor-out and make commonly used zram_decompress_page() function, which also simplified
+error handling in zram_bvec_read().
+
+Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Reviewed-by: Nitin Gupta <ngupta@vflare.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c |  113 ++++++++++++++++------------------------
+ 1 file changed, 48 insertions(+), 65 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -183,62 +183,25 @@ static inline int is_partial_io(struct b
+       return bvec->bv_len != PAGE_SIZE;
+ }
+-static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+-                        u32 index, int offset, struct bio *bio)
++static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
+ {
+-      int ret;
+-      size_t clen;
+-      struct page *page;
+-      unsigned char *user_mem, *cmem, *uncmem = NULL;
+-
+-      page = bvec->bv_page;
+-
+-      if (zram_test_flag(zram, index, ZRAM_ZERO)) {
+-              handle_zero_page(bvec);
+-              return 0;
+-      }
++      int ret = LZO_E_OK;
++      size_t clen = PAGE_SIZE;
++      unsigned char *cmem;
++      unsigned long handle = zram->table[index].handle;
+-      /* Requested page is not present in compressed area */
+-      if (unlikely(!zram->table[index].handle)) {
+-              pr_debug("Read before write: sector=%lu, size=%u",
+-                       (ulong)(bio->bi_sector), bio->bi_size);
+-              handle_zero_page(bvec);
++      if (!handle || zram_test_flag(zram, index, ZRAM_ZERO)) {
++              memset(mem, 0, PAGE_SIZE);
+               return 0;
+       }
+-      if (is_partial_io(bvec)) {
+-              /* Use  a temporary buffer to decompress the page */
+-              uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-              if (!uncmem) {
+-                      pr_info("Error allocating temp memory!\n");
+-                      return -ENOMEM;
+-              }
+-      }
+-
+-      user_mem = kmap_atomic(page);
+-      if (!is_partial_io(bvec))
+-              uncmem = user_mem;
+-      clen = PAGE_SIZE;
+-
+-      cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
+-                              ZS_MM_RO);
+-
+-      if (zram->table[index].size == PAGE_SIZE) {
+-              memcpy(uncmem, cmem, PAGE_SIZE);
+-              ret = LZO_E_OK;
+-      } else {
++      cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
++      if (zram->table[index].size == PAGE_SIZE)
++              memcpy(mem, cmem, PAGE_SIZE);
++      else
+               ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+-                                  uncmem, &clen);
+-      }
+-
+-      if (is_partial_io(bvec)) {
+-              memcpy(user_mem + bvec->bv_offset, uncmem + offset,
+-                     bvec->bv_len);
+-              kfree(uncmem);
+-      }
+-
+-      zs_unmap_object(zram->mem_pool, zram->table[index].handle);
+-      kunmap_atomic(user_mem);
++                                              mem, &clen);
++      zs_unmap_object(zram->mem_pool, handle);
+       /* Should NEVER happen. Return bio error if it does. */
+       if (unlikely(ret != LZO_E_OK)) {
+@@ -247,36 +210,56 @@ static int zram_bvec_read(struct zram *z
+               return ret;
+       }
+-      flush_dcache_page(page);
+-
+       return 0;
+ }
+-static int zram_read_before_write(struct zram *zram, char *mem, u32 index)
++static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
++                        u32 index, int offset, struct bio *bio)
+ {
+       int ret;
+-      size_t clen = PAGE_SIZE;
+-      unsigned char *cmem;
+-      unsigned long handle = zram->table[index].handle;
++      struct page *page;
++      unsigned char *user_mem, *uncmem = NULL;
+-      if (zram_test_flag(zram, index, ZRAM_ZERO) || !handle) {
+-              memset(mem, 0, PAGE_SIZE);
++      page = bvec->bv_page;
++
++      if (unlikely(!zram->table[index].handle) ||
++                      zram_test_flag(zram, index, ZRAM_ZERO)) {
++              handle_zero_page(bvec);
+               return 0;
+       }
+-      cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
+-      ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+-                                  mem, &clen);
+-      zs_unmap_object(zram->mem_pool, handle);
++      user_mem = kmap_atomic(page);
++      if (is_partial_io(bvec))
++              /* Use  a temporary buffer to decompress the page */
++              uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
++      else
++              uncmem = user_mem;
++
++      if (!uncmem) {
++              pr_info("Unable to allocate temp memory\n");
++              ret = -ENOMEM;
++              goto out_cleanup;
++      }
++      ret = zram_decompress_page(zram, uncmem, index);
+       /* Should NEVER happen. Return bio error if it does. */
+       if (unlikely(ret != LZO_E_OK)) {
+               pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+               zram_stat64_inc(zram, &zram->stats.failed_reads);
+-              return ret;
++              goto out_cleanup;
+       }
+-      return 0;
++      if (is_partial_io(bvec))
++              memcpy(user_mem + bvec->bv_offset, uncmem + offset,
++                              bvec->bv_len);
++
++      flush_dcache_page(page);
++      ret = 0;
++out_cleanup:
++      kunmap_atomic(user_mem);
++      if (is_partial_io(bvec))
++              kfree(uncmem);
++      return ret;
+ }
+ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
+@@ -302,7 +285,7 @@ static int zram_bvec_write(struct zram *
+                       ret = -ENOMEM;
+                       goto out;
+               }
+-              ret = zram_read_before_write(zram, uncmem, index);
++              ret = zram_decompress_page(zram, uncmem, index);
+               if (ret) {
+                       kfree(uncmem);
+                       goto out;
diff --git a/queue-3.7/staging-zram-fix-invalid-memory-references-during-disk-write.patch b/queue-3.7/staging-zram-fix-invalid-memory-references-during-disk-write.patch
new file mode 100644 (file)
index 0000000..52b99e0
--- /dev/null
@@ -0,0 +1,129 @@
+From 397c60668aa5ae7130b5ad4e73870d7b8a787085 Mon Sep 17 00:00:00 2001
+From: Nitin Gupta <ngupta@vflare.org>
+Date: Wed, 2 Jan 2013 08:53:41 -0800
+Subject: staging: zram: fix invalid memory references during disk write
+
+From: Nitin Gupta <ngupta@vflare.org>
+
+commit 397c60668aa5ae7130b5ad4e73870d7b8a787085 upstream.
+
+Fixes a bug introduced by commit c8f2f0db1 ("zram: Fix handling
+of incompressible pages") which caused invalid memory references
+during disk write. Invalid references could occur in two cases:
+ - Incoming data expands on compression: In this case, reference was
+made to kunmap()'ed bio page.
+ - Partial (non PAGE_SIZE) write with incompressible data: In this
+case, reference was made to a kfree()'ed buffer.
+
+Fixes bug 50081:
+https://bugzilla.kernel.org/show_bug.cgi?id=50081
+
+Signed-off-by: Nitin Gupta <ngupta@vflare.org>
+Reported-by: Mihail Kasadjikov <hamer.mk@gmail.com>
+Reported-by: Tomas M <tomas@slax.org>
+Reviewed-by: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c |   39 ++++++++++++++++++++++++---------------
+ 1 file changed, 24 insertions(+), 15 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -265,7 +265,7 @@ out_cleanup:
+ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
+                          int offset)
+ {
+-      int ret;
++      int ret = 0;
+       size_t clen;
+       unsigned long handle;
+       struct page *page;
+@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram *
+                       goto out;
+               }
+               ret = zram_decompress_page(zram, uncmem, index);
+-              if (ret) {
+-                      kfree(uncmem);
++              if (ret)
+                       goto out;
+-              }
+       }
+       /*
+@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram *
+       user_mem = kmap_atomic(page);
+-      if (is_partial_io(bvec))
++      if (is_partial_io(bvec)) {
+               memcpy(uncmem + offset, user_mem + bvec->bv_offset,
+                      bvec->bv_len);
+-      else
++              kunmap_atomic(user_mem);
++              user_mem = NULL;
++      } else {
+               uncmem = user_mem;
++      }
+       if (page_zero_filled(uncmem)) {
+-              kunmap_atomic(user_mem);
+-              if (is_partial_io(bvec))
+-                      kfree(uncmem);
++              if (!is_partial_io(bvec))
++                      kunmap_atomic(user_mem);
+               zram_stat_inc(&zram->stats.pages_zero);
+               zram_set_flag(zram, index, ZRAM_ZERO);
+               ret = 0;
+@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram *
+       ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
+                              zram->compress_workmem);
+-      kunmap_atomic(user_mem);
+-      if (is_partial_io(bvec))
+-                      kfree(uncmem);
++      if (!is_partial_io(bvec)) {
++              kunmap_atomic(user_mem);
++              user_mem = NULL;
++              uncmem = NULL;
++      }
+       if (unlikely(ret != LZO_E_OK)) {
+               pr_err("Compression failed! err=%d\n", ret);
+@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram *
+       if (unlikely(clen > max_zpage_size)) {
+               zram_stat_inc(&zram->stats.bad_compress);
+-              src = uncmem;
+               clen = PAGE_SIZE;
++              src = NULL;
++              if (is_partial_io(bvec))
++                      src = uncmem;
+       }
+       handle = zs_malloc(zram->mem_pool, clen);
+@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram *
+       }
+       cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO);
++      if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
++              src = kmap_atomic(page);
+       memcpy(cmem, src, clen);
++      if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
++              kunmap_atomic(src);
+       zs_unmap_object(zram->mem_pool, handle);
+@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram *
+       if (clen <= PAGE_SIZE / 2)
+               zram_stat_inc(&zram->stats.good_compress);
+-      return 0;
+-
+ out:
++      if (is_partial_io(bvec))
++              kfree(uncmem);
++
+       if (ret)
+               zram_stat64_inc(zram, &zram->stats.failed_writes);
+       return ret;