cfg80211/mac80211: apply station uAPSD parameters selectively

Currently, when hostapd sets the station as authorized
we also overwrite its uAPSD parameter. This obviously
leads to buggy behaviour (later, with my patches that
actually add uAPSD support). To fix this, only apply
those parameters if they were actually set in nl80211,
and to achieve that add a bitmap of things to apply.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 31d823a..34b8f26 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -424,6 +424,17 @@
 };
 
 /**
+ * enum station_parameters_apply_mask - station parameter values to apply
+ * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
+ *
+ * Not all station parameters have in-band "no change" signalling,
+ * for those that don't these flags will are used.
+ */
+enum station_parameters_apply_mask {
+	STATION_PARAM_APPLY_UAPSD = BIT(0),
+};
+
+/**
  * struct station_parameters - station parameters
  *
  * Used to change and create a new station.
@@ -450,6 +461,7 @@
 	u8 *supported_rates;
 	struct net_device *vlan;
 	u32 sta_flags_mask, sta_flags_set;
+	u32 sta_modify_mask;
 	int listen_interval;
 	u16 aid;
 	u8 supported_rates_len;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8fef3cd..13061eb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -714,8 +714,10 @@
 	}
 	spin_unlock_irqrestore(&sta->flaglock, flags);
 
-	sta->sta.uapsd_queues = params->uapsd_queues;
-	sta->sta.max_sp = params->max_sp;
+	if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
+		sta->sta.uapsd_queues = params->uapsd_queues;
+		sta->sta.max_sp = params->max_sp;
+	}
 
 	/*
 	 * cfg80211 validates this (1-2007) and allows setting the AID
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b850757..3799623 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2643,6 +2643,8 @@
 
 		if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
 			return -EINVAL;
+
+		params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
 	}
 
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&