Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: Turn AQL into an NL80211_EXT_FEATURE

Instead of just having an airtime flag in debugfs, turn AQL into a proper
NL80211_EXT_FEATURE, so drivers can turn it on when they are ready, and so
we also expose the presence of the feature to userspace.

This also has the effect of flipping the default, so drivers have to opt in
to using AQL instead of getting it by default with TXQs. To keep
functionality the same as pre-patch, we set this feature for ath10k (which
is where it is needed the most).

While we're at it, split out the debugfs interface so AQL gets its own
per-station debugfs file instead of using the 'airtime' file.

[Johannes:]
This effectively disables AQL for iwlwifi, where it fixes a number of
issues:
* TSO in iwlwifi is causing underflows and associated warnings in AQL
* HE (802.11ax) rates aren't reported properly so at HE rates, AQL could
never have a valid estimate (it'd use 6 Mbps instead of up to 2400!)

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/r/20191212111437.224294-1-toke@redhat.com
Fixes: 3ace10f5b5ad ("mac80211: Implement Airtime-based Queue Limit (AQL)")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Toke Høiland-Jørgensen and committed by
Johannes Berg
911bde0f e548f749

+83 -37
+1
drivers/net/wireless/ath/ath10k/mac.c
··· 8958 8958 wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); 8959 8959 wiphy_ext_feature_set(ar->hw->wiphy, 8960 8960 NL80211_EXT_FEATURE_SET_SCAN_DWELL); 8961 + wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL); 8961 8962 8962 8963 if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) || 8963 8964 test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map))
+5
include/uapi/linux/nl80211.h
··· 5517 5517 * with VLAN tagged frames and separate VLAN-specific netdevs added using 5518 5518 * vconfig similarly to the Ethernet case. 5519 5519 * 5520 + * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL) 5521 + * feature, which prevents bufferbloat by using the expected transmission 5522 + * time to limit the amount of data buffered in the hardware. 5523 + * 5520 5524 * @NUM_NL80211_EXT_FEATURES: number of extended features. 5521 5525 * @MAX_NL80211_EXT_FEATURES: highest extended feature index. 5522 5526 */ ··· 5567 5563 NL80211_EXT_FEATURE_STA_TX_PWR, 5568 5564 NL80211_EXT_FEATURE_SAE_OFFLOAD, 5569 5565 NL80211_EXT_FEATURE_VLAN_OFFLOAD, 5566 + NL80211_EXT_FEATURE_AQL, 5570 5567 5571 5568 /* add new features before the definition below */ 5572 5569 NUM_NL80211_EXT_FEATURES,
+71 -31
net/mac80211/debugfs_sta.c
··· 201 201 char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf; 202 202 u64 rx_airtime = 0, tx_airtime = 0; 203 203 s64 deficit[IEEE80211_NUM_ACS]; 204 - u32 q_depth[IEEE80211_NUM_ACS]; 205 - u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS]; 206 204 ssize_t rv; 207 205 int ac; 208 206 ··· 212 214 rx_airtime += sta->airtime[ac].rx_airtime; 213 215 tx_airtime += sta->airtime[ac].tx_airtime; 214 216 deficit[ac] = sta->airtime[ac].deficit; 215 - q_limit_l[ac] = sta->airtime[ac].aql_limit_low; 216 - q_limit_h[ac] = sta->airtime[ac].aql_limit_high; 217 217 spin_unlock_bh(&local->active_txq_lock[ac]); 218 - q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending); 219 218 } 220 219 221 220 p += scnprintf(p, bufsz + buf - p, 222 221 "RX: %llu us\nTX: %llu us\nWeight: %u\n" 223 - "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n" 224 - "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n" 225 - "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n", 222 + "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n", 226 223 rx_airtime, tx_airtime, sta->airtime_weight, 227 - deficit[0], deficit[1], deficit[2], deficit[3], 228 - q_depth[0], q_depth[1], q_depth[2], q_depth[3], 229 - q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1], 230 - q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]), 224 + deficit[0], deficit[1], deficit[2], deficit[3]); 231 225 232 226 rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 233 227 kfree(buf); ··· 231 241 { 232 242 struct sta_info *sta = file->private_data; 233 243 struct ieee80211_local *local = sta->sdata->local; 234 - u32 ac, q_limit_l, q_limit_h; 235 - char _buf[100] = {}, *buf = _buf; 236 - 237 - if (count > sizeof(_buf)) 238 - return -EINVAL; 239 - 240 - if (copy_from_user(buf, userbuf, count)) 241 - return -EFAULT; 242 - 243 - buf[sizeof(_buf) - 1] = '\0'; 244 - if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h) 245 - != 3) 246 - return -EINVAL; 247 - 248 - if (ac >= IEEE80211_NUM_ACS) 249 - return -EINVAL; 250 - 251 - sta->airtime[ac].aql_limit_low = q_limit_l; 252 - sta->airtime[ac].aql_limit_high = q_limit_h; 244 + int ac; 253 245 254 246 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 255 247 spin_lock_bh(&local->active_txq_lock[ac]); ··· 244 272 return count; 245 273 } 246 274 STA_OPS_RW(airtime); 275 + 276 + static ssize_t sta_aql_read(struct file *file, char __user *userbuf, 277 + size_t count, loff_t *ppos) 278 + { 279 + struct sta_info *sta = file->private_data; 280 + struct ieee80211_local *local = sta->sdata->local; 281 + size_t bufsz = 400; 282 + char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf; 283 + u32 q_depth[IEEE80211_NUM_ACS]; 284 + u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS]; 285 + ssize_t rv; 286 + int ac; 287 + 288 + if (!buf) 289 + return -ENOMEM; 290 + 291 + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 292 + spin_lock_bh(&local->active_txq_lock[ac]); 293 + q_limit_l[ac] = sta->airtime[ac].aql_limit_low; 294 + q_limit_h[ac] = sta->airtime[ac].aql_limit_high; 295 + spin_unlock_bh(&local->active_txq_lock[ac]); 296 + q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending); 297 + } 298 + 299 + p += scnprintf(p, bufsz + buf - p, 300 + "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n" 301 + "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n", 302 + q_depth[0], q_depth[1], q_depth[2], q_depth[3], 303 + q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1], 304 + q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]), 305 + 306 + rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 307 + kfree(buf); 308 + return rv; 309 + } 310 + 311 + static ssize_t sta_aql_write(struct file *file, const char __user *userbuf, 312 + size_t count, loff_t *ppos) 313 + { 314 + struct sta_info *sta = file->private_data; 315 + u32 ac, q_limit_l, q_limit_h; 316 + char _buf[100] = {}, *buf = _buf; 317 + 318 + if (count > sizeof(_buf)) 319 + return -EINVAL; 320 + 321 + if (copy_from_user(buf, userbuf, count)) 322 + return -EFAULT; 323 + 324 + buf[sizeof(_buf) - 1] = '\0'; 325 + if (sscanf(buf, "limit %u %u %u", &ac, &q_limit_l, &q_limit_h) 326 + != 3) 327 + return -EINVAL; 328 + 329 + if (ac >= IEEE80211_NUM_ACS) 330 + return -EINVAL; 331 + 332 + sta->airtime[ac].aql_limit_low = q_limit_l; 333 + sta->airtime[ac].aql_limit_high = q_limit_h; 334 + 335 + return count; 336 + } 337 + STA_OPS_RW(aql); 338 + 247 339 248 340 static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, 249 341 size_t count, loff_t *ppos) ··· 1031 995 if (wiphy_ext_feature_isset(local->hw.wiphy, 1032 996 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) 1033 997 DEBUGFS_ADD(airtime); 998 + 999 + if (wiphy_ext_feature_isset(local->hw.wiphy, 1000 + NL80211_EXT_FEATURE_AQL)) 1001 + DEBUGFS_ADD(aql); 1034 1002 1035 1003 debugfs_create_xul("driver_buffered_tids", 0400, sta->debugfs_dir, 1036 1004 &sta->driver_buffered_tids);
+1 -3
net/mac80211/main.c
··· 672 672 IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H; 673 673 } 674 674 675 - local->airtime_flags = AIRTIME_USE_TX | 676 - AIRTIME_USE_RX | 677 - AIRTIME_USE_AQL; 675 + local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX; 678 676 local->aql_threshold = IEEE80211_AQL_THRESHOLD; 679 677 atomic_set(&local->aql_total_pending_airtime, 0); 680 678
+3
net/mac80211/sta_info.c
··· 1916 1916 { 1917 1917 int tx_pending; 1918 1918 1919 + if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) 1920 + return; 1921 + 1919 1922 if (!tx_completed) { 1920 1923 if (sta) 1921 1924 atomic_add(tx_airtime,
-1
net/mac80211/sta_info.h
··· 127 127 /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */ 128 128 #define AIRTIME_USE_TX BIT(0) 129 129 #define AIRTIME_USE_RX BIT(1) 130 - #define AIRTIME_USE_AQL BIT(2) 131 130 132 131 struct airtime_info { 133 132 u64 rx_airtime;
+2 -2
net/mac80211/tx.c
··· 3677 3677 3678 3678 IEEE80211_SKB_CB(skb)->control.vif = vif; 3679 3679 3680 - if (local->airtime_flags & AIRTIME_USE_AQL) { 3680 + if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { 3681 3681 u32 airtime; 3682 3682 3683 3683 airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, ··· 3799 3799 struct sta_info *sta; 3800 3800 struct ieee80211_local *local = hw_to_local(hw); 3801 3801 3802 - if (!(local->airtime_flags & AIRTIME_USE_AQL)) 3802 + if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) 3803 3803 return true; 3804 3804 3805 3805 if (!txq->sta)