]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.7-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Jan 2013 09:58:01 +0000 (10:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Jan 2013 09:58:01 +0000 (10:58 +0100)
added patches:
ath9k_htc-fix-memory-leak.patch
dm-raid-fix-raid10-s-check-for-sufficient-redundancy.patch
mac80211-fix-ft-roaming.patch
mac80211-synchronize-scan-off-on-channel-and-ps-states.patch

queue-3.7/ath9k_htc-fix-memory-leak.patch [new file with mode: 0644]
queue-3.7/dm-raid-fix-raid10-s-check-for-sufficient-redundancy.patch [new file with mode: 0644]
queue-3.7/mac80211-fix-ft-roaming.patch [new file with mode: 0644]
queue-3.7/mac80211-synchronize-scan-off-on-channel-and-ps-states.patch [new file with mode: 0644]
queue-3.7/series

diff --git a/queue-3.7/ath9k_htc-fix-memory-leak.patch b/queue-3.7/ath9k_htc-fix-memory-leak.patch
new file mode 100644 (file)
index 0000000..5d601b4
--- /dev/null
@@ -0,0 +1,34 @@
+From 0981c3b24ef664f5611008a6e6d0622fac6d892b Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Wed, 9 Jan 2013 16:07:48 +0530
+Subject: ath9k_htc: Fix memory leak
+
+From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 0981c3b24ef664f5611008a6e6d0622fac6d892b upstream.
+
+SKBs that are allocated in the HTC layer do not have callbacks
+registered and hence ended up not being freed, Fix this by freeing
+them properly in the TX completion routine.
+
+Reported-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Tested-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/ath/ath9k/htc_hst.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
++++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
+@@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct ht
+                       endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
+                                                 skb, htc_hdr->endpoint_id,
+                                                 txok);
++              } else {
++                      kfree_skb(skb);
+               }
+       }
diff --git a/queue-3.7/dm-raid-fix-raid10-s-check-for-sufficient-redundancy.patch b/queue-3.7/dm-raid-fix-raid10-s-check-for-sufficient-redundancy.patch
new file mode 100644 (file)
index 0000000..9cec262
--- /dev/null
@@ -0,0 +1,240 @@
+From 55ebbb59c1c6eb1b040f62b8c4ae0b724de6e55a Mon Sep 17 00:00:00 2001
+From: Jonathan Brassow <jbrassow@redhat.com>
+Date: Tue, 22 Jan 2013 21:42:18 -0600
+Subject: DM-RAID: Fix RAID10's check for sufficient redundancy
+
+From: Jonathan Brassow <jbrassow@redhat.com>
+
+commit 55ebbb59c1c6eb1b040f62b8c4ae0b724de6e55a upstream.
+
+Before attempting to activate a RAID array, it is checked for sufficient
+redundancy.  That is, we make sure that there are not too many failed
+devices - or devices specified for rebuild - to undermine our ability to
+activate the array.  The current code performs this check twice - once to
+ensure there were not too many devices specified for rebuild by the user
+('validate_rebuild_devices') and again after possibly experiencing a failure
+to read the superblock ('analyse_superblocks').  Neither of these checks are
+sufficient.  The first check is done properly but with insufficient
+information about the possible failure state of the devices to make a good
+determination if the array can be activated.  The second check is simply
+done wrong in the case of RAID10 because it doesn't account for the
+independence of the stripes (i.e. mirror sets).  The solution is to use the
+properly written check ('validate_rebuild_devices'), but perform the check
+after the superblocks have been read and we know which devices have failed.
+This gives us one check instead of two and performs it in a location where
+it can be done right.
+
+Only RAID10 was affected and it was affected in the following ways:
+- the code did not properly catch the condition where a user specified
+  a device for rebuild that already had a failed device in the same mirror
+  set.  (This condition would, however, be caught at a deeper level in MD.)
+- the code triggers a false positive and denies activation when devices in
+  independent mirror sets have failed - counting the failures as though they
+  were all in the same set.
+
+The most likely place this error was introduced (or this patch should have
+been included) is in commit 4ec1e369 - first introduced in v3.7-rc1.
+Consequently this fix should also go in v3.7.y, however there is a
+small conflict on the .version in raid_target, so I'll submit a
+separate patch to -stable.
+
+Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/device-mapper/dm-raid.txt |    1 
+ drivers/md/dm-raid.c                    |  101 +++++++++++---------------------
+ 2 files changed, 38 insertions(+), 64 deletions(-)
+
+--- a/Documentation/device-mapper/dm-raid.txt
++++ b/Documentation/device-mapper/dm-raid.txt
+@@ -141,3 +141,4 @@ Version History
+ 1.2.0 Handle creation of arrays that contain failed devices.
+ 1.3.0 Added support for RAID 10
+ 1.3.1 Allow device replacement/rebuild for RAID 10
++1.3.2   Fix/improve redundancy checking for RAID10
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -338,24 +338,22 @@ static int validate_region_size(struct r
+ }
+ /*
+- * validate_rebuild_devices
++ * validate_raid_redundancy
+  * @rs
+  *
+- * Determine if the devices specified for rebuild can result in a valid
+- * usable array that is capable of rebuilding the given devices.
++ * Determine if there are enough devices in the array that haven't
++ * failed (or are being rebuilt) to form a usable array.
+  *
+  * Returns: 0 on success, -EINVAL on failure.
+  */
+-static int validate_rebuild_devices(struct raid_set *rs)
++static int validate_raid_redundancy(struct raid_set *rs)
+ {
+       unsigned i, rebuild_cnt = 0;
+       unsigned rebuilds_per_group, copies, d;
+-      if (!(rs->print_flags & DMPF_REBUILD))
+-              return 0;
+-
+       for (i = 0; i < rs->md.raid_disks; i++)
+-              if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
++              if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
++                  !rs->dev[i].rdev.sb_page)
+                       rebuild_cnt++;
+       switch (rs->raid_type->level) {
+@@ -391,27 +389,24 @@ static int validate_rebuild_devices(stru
+                *          A    A    B    B    C
+                *          C    D    D    E    E
+                */
+-              rebuilds_per_group = 0;
+               for (i = 0; i < rs->md.raid_disks * copies; i++) {
++                      if (!(i % copies))
++                              rebuilds_per_group = 0;
+                       d = i % rs->md.raid_disks;
+-                      if (!test_bit(In_sync, &rs->dev[d].rdev.flags) &&
++                      if ((!rs->dev[d].rdev.sb_page ||
++                           !test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
+                           (++rebuilds_per_group >= copies))
+                               goto too_many;
+-                      if (!((i + 1) % copies))
+-                              rebuilds_per_group = 0;
+               }
+               break;
+       default:
+-              DMERR("The rebuild parameter is not supported for %s",
+-                    rs->raid_type->name);
+-              rs->ti->error = "Rebuild not supported for this RAID type";
+-              return -EINVAL;
++              if (rebuild_cnt)
++                      return -EINVAL;
+       }
+       return 0;
+ too_many:
+-      rs->ti->error = "Too many rebuild devices specified";
+       return -EINVAL;
+ }
+@@ -662,9 +657,6 @@ static int parse_raid_params(struct raid
+       }
+       rs->md.dev_sectors = sectors_per_dev;
+-      if (validate_rebuild_devices(rs))
+-              return -EINVAL;
+-
+       /* Assume there are no metadata devices until the drives are parsed */
+       rs->md.persistent = 0;
+       rs->md.external = 1;
+@@ -993,28 +985,10 @@ static int super_validate(struct mddev *
+ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
+ {
+       int ret;
+-      unsigned redundancy = 0;
+       struct raid_dev *dev;
+       struct md_rdev *rdev, *tmp, *freshest;
+       struct mddev *mddev = &rs->md;
+-      switch (rs->raid_type->level) {
+-      case 1:
+-              redundancy = rs->md.raid_disks - 1;
+-              break;
+-      case 4:
+-      case 5:
+-      case 6:
+-              redundancy = rs->raid_type->parity_devs;
+-              break;
+-      case 10:
+-              redundancy = raid10_md_layout_to_copies(mddev->layout) - 1;
+-              break;
+-      default:
+-              ti->error = "Unknown RAID type";
+-              return -EINVAL;
+-      }
+-
+       freshest = NULL;
+       rdev_for_each_safe(rdev, tmp, mddev) {
+               /*
+@@ -1043,44 +1017,43 @@ static int analyse_superblocks(struct dm
+                       break;
+               default:
+                       dev = container_of(rdev, struct raid_dev, rdev);
+-                      if (redundancy--) {
+-                              if (dev->meta_dev)
+-                                      dm_put_device(ti, dev->meta_dev);
++                      if (dev->meta_dev)
++                              dm_put_device(ti, dev->meta_dev);
+-                              dev->meta_dev = NULL;
+-                              rdev->meta_bdev = NULL;
++                      dev->meta_dev = NULL;
++                      rdev->meta_bdev = NULL;
+-                              if (rdev->sb_page)
+-                                      put_page(rdev->sb_page);
++                      if (rdev->sb_page)
++                              put_page(rdev->sb_page);
+-                              rdev->sb_page = NULL;
++                      rdev->sb_page = NULL;
+-                              rdev->sb_loaded = 0;
++                      rdev->sb_loaded = 0;
+-                              /*
+-                               * We might be able to salvage the data device
+-                               * even though the meta device has failed.  For
+-                               * now, we behave as though '- -' had been
+-                               * set for this device in the table.
+-                               */
+-                              if (dev->data_dev)
+-                                      dm_put_device(ti, dev->data_dev);
+-
+-                              dev->data_dev = NULL;
+-                              rdev->bdev = NULL;
++                      /*
++                       * We might be able to salvage the data device
++                       * even though the meta device has failed.  For
++                       * now, we behave as though '- -' had been
++                       * set for this device in the table.
++                       */
++                      if (dev->data_dev)
++                              dm_put_device(ti, dev->data_dev);
+-                              list_del(&rdev->same_set);
++                      dev->data_dev = NULL;
++                      rdev->bdev = NULL;
+-                              continue;
+-                      }
+-                      ti->error = "Failed to load superblock";
+-                      return ret;
++                      list_del(&rdev->same_set);
+               }
+       }
+       if (!freshest)
+               return 0;
++      if (validate_raid_redundancy(rs)) {
++              rs->ti->error = "Insufficient redundancy to activate array";
++              return -EINVAL;
++      }
++
+       /*
+        * Validation of the freshest device provides the source of
+        * validation for the remaining devices.
+@@ -1430,7 +1403,7 @@ static void raid_resume(struct dm_target
+ static struct target_type raid_target = {
+       .name = "raid",
+-      .version = {1, 3, 1},
++      .version = {1, 3, 2},
+       .module = THIS_MODULE,
+       .ctr = raid_ctr,
+       .dtr = raid_dtr,
diff --git a/queue-3.7/mac80211-fix-ft-roaming.patch b/queue-3.7/mac80211-fix-ft-roaming.patch
new file mode 100644 (file)
index 0000000..23f11d3
--- /dev/null
@@ -0,0 +1,55 @@
+From 1626e0fa740dec8665a973cf2349405cdfeb46dc Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Fri, 11 Jan 2013 14:34:25 +0100
+Subject: mac80211: fix FT roaming
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 1626e0fa740dec8665a973cf2349405cdfeb46dc upstream.
+
+During FT roaming, wpa_supplicant attempts to set the
+key before association. This used to be rejected, but
+as a side effect of my commit 66e67e418908442389d3a9e
+("mac80211: redesign auth/assoc") the key was accepted
+causing hardware crypto to not be used for it as the
+station isn't added to the driver yet.
+
+It would be possible to accept the key and then add it
+to the driver when the station has been added. However,
+this may run into issues with drivers using the state-
+based station adding if they accept the key only after
+association like it used to be.
+
+For now, revert to the behaviour from before the auth
+and assoc change.
+
+Reported-by: Cédric Debarge <cedric.debarge@acksys.fr>
+Tested-by: Cédric Debarge <cedric.debarge@acksys.fr>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/cfg.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -164,7 +164,17 @@ static int ieee80211_add_key(struct wiph
+                       sta = sta_info_get(sdata, mac_addr);
+               else
+                       sta = sta_info_get_bss(sdata, mac_addr);
+-              if (!sta) {
++              /*
++               * The ASSOC test makes sure the driver is ready to
++               * receive the key. When wpa_supplicant has roamed
++               * using FT, it attempts to set the key before
++               * association has completed, this rejects that attempt
++               * so it will set the key again after assocation.
++               *
++               * TODO: accept the key if we have a station entry and
++               *       add it to the device after the station.
++               */
++              if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
+                       ieee80211_key_free(sdata->local, key);
+                       err = -ENOENT;
+                       goto out_unlock;
diff --git a/queue-3.7/mac80211-synchronize-scan-off-on-channel-and-ps-states.patch b/queue-3.7/mac80211-synchronize-scan-off-on-channel-and-ps-states.patch
new file mode 100644 (file)
index 0000000..bceb66b
--- /dev/null
@@ -0,0 +1,156 @@
+From aacde9ee45225f7e0b90960f479aef83c66bfdc0 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Thu, 20 Dec 2012 14:41:18 +0100
+Subject: mac80211: synchronize scan off/on-channel and PS states
+
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+
+commit aacde9ee45225f7e0b90960f479aef83c66bfdc0 upstream.
+
+Since:
+
+commit b23b025fe246f3acc2988eb6d400df34c27cb8ae
+Author: Ben Greear <greearb@candelatech.com>
+Date:   Fri Feb 4 11:54:17 2011 -0800
+
+    mac80211: Optimize scans on current operating channel.
+
+we do not disable PS while going back to operational channel (on
+ieee80211_scan_state_suspend) and deffer that until scan finish.
+But since we are allowed to send frames, we can send a frame to AP
+without PM bit set, so disable PS on AP side. Then when we switch
+to off-channel (in ieee80211_scan_state_resume) we do not enable PS.
+Hence we are off-channel with PS disabled, frames are not buffered
+by AP.
+
+To fix remove offchannel_ps_disable argument and always enable PS when
+going off-channel and disable it when going on-channel, like it was
+before.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+Tested-by: Seth Forshee <seth.forshee@canonical.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/ieee80211_i.h |    6 ++----
+ net/mac80211/offchannel.c  |   19 +++++++------------
+ net/mac80211/scan.c        |   15 +++++----------
+ 3 files changed, 14 insertions(+), 26 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1279,10 +1279,8 @@ int ieee80211_request_sched_scan_stop(st
+ void ieee80211_sched_scan_stopped_work(struct work_struct *work);
+ /* off-channel helpers */
+-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
+-                                  bool offchannel_ps_enable);
+-void ieee80211_offchannel_return(struct ieee80211_local *local,
+-                               bool offchannel_ps_disable);
++void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
++void ieee80211_offchannel_return(struct ieee80211_local *local);
+ void ieee80211_roc_setup(struct ieee80211_local *local);
+ void ieee80211_start_next_roc(struct ieee80211_local *local);
+ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -102,8 +102,7 @@ static void ieee80211_offchannel_ps_disa
+       ieee80211_sta_reset_conn_monitor(sdata);
+ }
+-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
+-                                  bool offchannel_ps_enable)
++void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
+ {
+       struct ieee80211_sub_if_data *sdata;
+@@ -131,8 +130,7 @@ void ieee80211_offchannel_stop_vifs(stru
+               if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
+                       netif_tx_stop_all_queues(sdata->dev);
+-                      if (offchannel_ps_enable &&
+-                          (sdata->vif.type == NL80211_IFTYPE_STATION) &&
++                      if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+                           sdata->u.mgd.associated)
+                               ieee80211_offchannel_ps_enable(sdata);
+               }
+@@ -140,8 +138,7 @@ void ieee80211_offchannel_stop_vifs(stru
+       mutex_unlock(&local->iflist_mtx);
+ }
+-void ieee80211_offchannel_return(struct ieee80211_local *local,
+-                               bool offchannel_ps_disable)
++void ieee80211_offchannel_return(struct ieee80211_local *local)
+ {
+       struct ieee80211_sub_if_data *sdata;
+@@ -157,11 +154,9 @@ void ieee80211_offchannel_return(struct
+                       continue;
+               /* Tell AP we're back */
+-              if (offchannel_ps_disable &&
+-                  sdata->vif.type == NL80211_IFTYPE_STATION) {
+-                      if (sdata->u.mgd.associated)
+-                              ieee80211_offchannel_ps_disable(sdata);
+-              }
++              if (sdata->vif.type == NL80211_IFTYPE_STATION &&
++                  sdata->u.mgd.associated)
++                      ieee80211_offchannel_ps_disable(sdata);
+               if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
+                       /*
+@@ -381,7 +376,7 @@ void ieee80211_sw_roc_work(struct work_s
+                       local->tmp_channel = NULL;
+                       ieee80211_hw_config(local, 0);
+-                      ieee80211_offchannel_return(local, true);
++                      ieee80211_offchannel_return(local);
+               }
+               ieee80211_recalc_idle(local);
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -310,7 +310,7 @@ static void __ieee80211_scan_completed(s
+       if (!was_hw_scan) {
+               ieee80211_configure_filter(local);
+               drv_sw_scan_complete(local);
+-              ieee80211_offchannel_return(local, true);
++              ieee80211_offchannel_return(local);
+       }
+       ieee80211_recalc_idle(local);
+@@ -355,7 +355,7 @@ static int ieee80211_start_sw_scan(struc
+       local->next_scan_state = SCAN_DECISION;
+       local->scan_channel_idx = 0;
+-      ieee80211_offchannel_stop_vifs(local, true);
++      ieee80211_offchannel_stop_vifs(local);
+       ieee80211_configure_filter(local);
+@@ -680,12 +680,8 @@ static void ieee80211_scan_state_suspend
+       local->scan_channel = NULL;
+       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+-      /*
+-       * Re-enable vifs and beaconing.  Leave PS
+-       * in off-channel state..will put that back
+-       * on-channel at the end of scanning.
+-       */
+-      ieee80211_offchannel_return(local, false);
++      /* disable PS */
++      ieee80211_offchannel_return(local);
+       *next_delay = HZ / 5;
+       /* afterwards, resume scan & go to next channel */
+@@ -695,8 +691,7 @@ static void ieee80211_scan_state_suspend
+ static void ieee80211_scan_state_resume(struct ieee80211_local *local,
+                                       unsigned long *next_delay)
+ {
+-      /* PS already is in off-channel mode */
+-      ieee80211_offchannel_stop_vifs(local, false);
++      ieee80211_offchannel_stop_vifs(local);
+       if (local->ops->flush) {
+               drv_flush(local, false);
index 1eebfd9fc3eee7eee8e6f203321afe0cdac0fc2d..2339f6046bfdb0a29ec81dd2a1088f1d737a415d 100644 (file)
@@ -28,3 +28,7 @@ mwifiex-fix-typo-in-pcie-adapter-null-check.patch
 iwlegacy-fix-ibss-cleanup.patch
 brcmsmac-increase-timer-reference-count-for-new-timers-only.patch
 brcmsmac-handle-packet-drop-during-transmit-correctly.patch
+dm-raid-fix-raid10-s-check-for-sufficient-redundancy.patch
+mac80211-synchronize-scan-off-on-channel-and-ps-states.patch
+mac80211-fix-ft-roaming.patch
+ath9k_htc-fix-memory-leak.patch