A handful of fixes:
* disable AQL on most drivers, addressing the iwlwifi issues * fix double-free on network namespace changes * fix TID field in frames injected through monitor interfaces * fix ieee80211_calc_rx_airtime() * fix NULL pointer dereference in rfkill (and remove BUG_ON) -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl33THYACgkQB8qZga/f l8QSsw/+MW4NiXgjFNIaTfyPocFCLi45Efdizef3D+T2MsAD279DFILLFc4Q08Tt kL2CxOaD2lrrrPXTa++vkcaSBBQtgRRFvPQPycwoju9QkTuEQ31wFtXSzeCdSFmx vLVaY+gMvPjw6HejWqouPlm1hBaA0jqZOCjwq3IWj0spDR/FwJ0HwXSzzEhUs7FV 1097Q9i7kLDZjdMvUUVnKi8SyWPL8TMPfXxyGPOsSbMPG5QAYj3odfb7FtsZLYgD SwWafp6nroUfEDi3jk+QNEuJB4on6iAVEJxbltDQWqsBXO76CWVAezh9KqiDtzIt Ay2YtTyOUTZUTPR8lZnoiTvR0GLzeNybwT5BQ9COO1tCD4yB8y1/cpa8oJxv/YRB xekCcNMPDFqIwtrY4UKbTEuyCbf78uVO8cUYdlb4ZUUvLKFP2LiD63InyWAtvCdu N21mzausAUzy65j5AJ7IIut7iFrcNEQ2qQtQuECGEqmu9uqHD4S3e9MQYd6Qx429 uXdWbtyoqnYXMaEhF4Zy+DNz5vELNUkP0Lv9sJ6ihALQSXWXwkiz+p7+eYsdBdZy mJslJs+sYCgt0y46xzUfAcwvEdAOGkBeF91gCHSJ7q9g8UCrnZ4SN+OCx93YGnvW w1AQgZ7VW2aL4i8lnfu6bd86K04M/AbwdRn2OL6Ug4LmmFvHUT8= =tvTq -----END PGP SIGNATURE----- Merge tag 'mac80211-for-net-2019-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== A handful of fixes: * disable AQL on most drivers, addressing the iwlwifi issues * fix double-free on network namespace changes * fix TID field in frames injected through monitor interfaces * fix ieee80211_calc_rx_airtime() * fix NULL pointer dereference in rfkill (and remove BUG_ON) ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ad125c6c05
|
@ -8958,6 +8958,7 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL);
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) ||
|
||||
test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map))
|
||||
|
|
|
@ -5517,6 +5517,10 @@ enum nl80211_feature_flags {
|
|||
* with VLAN tagged frames and separate VLAN-specific netdevs added using
|
||||
* vconfig similarly to the Ethernet case.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL)
|
||||
* feature, which prevents bufferbloat by using the expected transmission
|
||||
* time to limit the amount of data buffered in the hardware.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
|
@ -5563,6 +5567,7 @@ enum nl80211_ext_feature_index {
|
|||
NL80211_EXT_FEATURE_STA_TX_PWR,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_VLAN_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_AQL,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
|
|
@ -442,7 +442,7 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
|||
return 0;
|
||||
|
||||
sband = hw->wiphy->bands[status->band];
|
||||
if (!sband || status->rate_idx > sband->n_bitrates)
|
||||
if (!sband || status->rate_idx >= sband->n_bitrates)
|
||||
return 0;
|
||||
|
||||
rate = &sband->bitrates[status->rate_idx];
|
||||
|
|
|
@ -201,8 +201,6 @@ static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
|
|||
char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
|
||||
u64 rx_airtime = 0, tx_airtime = 0;
|
||||
s64 deficit[IEEE80211_NUM_ACS];
|
||||
u32 q_depth[IEEE80211_NUM_ACS];
|
||||
u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
|
||||
ssize_t rv;
|
||||
int ac;
|
||||
|
||||
|
@ -214,22 +212,14 @@ static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
|
|||
rx_airtime += sta->airtime[ac].rx_airtime;
|
||||
tx_airtime += sta->airtime[ac].tx_airtime;
|
||||
deficit[ac] = sta->airtime[ac].deficit;
|
||||
q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
|
||||
q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
|
||||
spin_unlock_bh(&local->active_txq_lock[ac]);
|
||||
q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending);
|
||||
}
|
||||
|
||||
p += scnprintf(p, bufsz + buf - p,
|
||||
"RX: %llu us\nTX: %llu us\nWeight: %u\n"
|
||||
"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n"
|
||||
"Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
|
||||
"Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
|
||||
"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
|
||||
rx_airtime, tx_airtime, sta->airtime_weight,
|
||||
deficit[0], deficit[1], deficit[2], deficit[3],
|
||||
q_depth[0], q_depth[1], q_depth[2], q_depth[3],
|
||||
q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
|
||||
q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
|
||||
deficit[0], deficit[1], deficit[2], deficit[3]);
|
||||
|
||||
rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
|
||||
kfree(buf);
|
||||
|
@ -241,25 +231,7 @@ static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
|
|||
{
|
||||
struct sta_info *sta = file->private_data;
|
||||
struct ieee80211_local *local = sta->sdata->local;
|
||||
u32 ac, q_limit_l, q_limit_h;
|
||||
char _buf[100] = {}, *buf = _buf;
|
||||
|
||||
if (count > sizeof(_buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(buf, userbuf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buf[sizeof(_buf) - 1] = '\0';
|
||||
if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
|
||||
!= 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (ac >= IEEE80211_NUM_ACS)
|
||||
return -EINVAL;
|
||||
|
||||
sta->airtime[ac].aql_limit_low = q_limit_l;
|
||||
sta->airtime[ac].aql_limit_high = q_limit_h;
|
||||
int ac;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
spin_lock_bh(&local->active_txq_lock[ac]);
|
||||
|
@ -273,6 +245,70 @@ static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
|
|||
}
|
||||
STA_OPS_RW(airtime);
|
||||
|
||||
static ssize_t sta_aql_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct sta_info *sta = file->private_data;
|
||||
struct ieee80211_local *local = sta->sdata->local;
|
||||
size_t bufsz = 400;
|
||||
char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
|
||||
u32 q_depth[IEEE80211_NUM_ACS];
|
||||
u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
|
||||
ssize_t rv;
|
||||
int ac;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
spin_lock_bh(&local->active_txq_lock[ac]);
|
||||
q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
|
||||
q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
|
||||
spin_unlock_bh(&local->active_txq_lock[ac]);
|
||||
q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending);
|
||||
}
|
||||
|
||||
p += scnprintf(p, bufsz + buf - p,
|
||||
"Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
|
||||
"Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
|
||||
q_depth[0], q_depth[1], q_depth[2], q_depth[3],
|
||||
q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
|
||||
q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
|
||||
|
||||
rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
|
||||
kfree(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static ssize_t sta_aql_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct sta_info *sta = file->private_data;
|
||||
u32 ac, q_limit_l, q_limit_h;
|
||||
char _buf[100] = {}, *buf = _buf;
|
||||
|
||||
if (count > sizeof(_buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(buf, userbuf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buf[sizeof(_buf) - 1] = '\0';
|
||||
if (sscanf(buf, "limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
|
||||
!= 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (ac >= IEEE80211_NUM_ACS)
|
||||
return -EINVAL;
|
||||
|
||||
sta->airtime[ac].aql_limit_low = q_limit_l;
|
||||
sta->airtime[ac].aql_limit_high = q_limit_h;
|
||||
|
||||
return count;
|
||||
}
|
||||
STA_OPS_RW(aql);
|
||||
|
||||
|
||||
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
@ -996,6 +1032,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
|
|||
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
|
||||
DEBUGFS_ADD(airtime);
|
||||
|
||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_AQL))
|
||||
DEBUGFS_ADD(aql);
|
||||
|
||||
debugfs_create_xul("driver_buffered_tids", 0400, sta->debugfs_dir,
|
||||
&sta->driver_buffered_tids);
|
||||
|
||||
|
|
|
@ -672,9 +672,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
|||
IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
|
||||
}
|
||||
|
||||
local->airtime_flags = AIRTIME_USE_TX |
|
||||
AIRTIME_USE_RX |
|
||||
AIRTIME_USE_AQL;
|
||||
local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
|
||||
local->aql_threshold = IEEE80211_AQL_THRESHOLD;
|
||||
atomic_set(&local->aql_total_pending_airtime, 0);
|
||||
|
||||
|
|
|
@ -1916,6 +1916,9 @@ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
|
|||
{
|
||||
int tx_pending;
|
||||
|
||||
if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
|
||||
return;
|
||||
|
||||
if (!tx_completed) {
|
||||
if (sta)
|
||||
atomic_add(tx_airtime,
|
||||
|
|
|
@ -127,7 +127,6 @@ enum ieee80211_agg_stop_reason {
|
|||
/* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
|
||||
#define AIRTIME_USE_TX BIT(0)
|
||||
#define AIRTIME_USE_RX BIT(1)
|
||||
#define AIRTIME_USE_AQL BIT(2)
|
||||
|
||||
struct airtime_info {
|
||||
u64 rx_airtime;
|
||||
|
|
|
@ -2256,6 +2256,15 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
|||
payload[7]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize skb->priority for QoS frames. This is put in the TID field
|
||||
* of the frame before passing it to the driver.
|
||||
*/
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *p = ieee80211_get_qos_ctl(hdr);
|
||||
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
}
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
|
@ -3668,7 +3677,7 @@ begin:
|
|||
|
||||
IEEE80211_SKB_CB(skb)->control.vif = vif;
|
||||
|
||||
if (local->airtime_flags & AIRTIME_USE_AQL) {
|
||||
if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
|
||||
u32 airtime;
|
||||
|
||||
airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
|
||||
|
@ -3790,7 +3799,7 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
|
|||
struct sta_info *sta;
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
||||
if (!(local->airtime_flags & AIRTIME_USE_AQL))
|
||||
if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
|
||||
return true;
|
||||
|
||||
if (!txq->sta)
|
||||
|
|
|
@ -1002,10 +1002,13 @@ static void rfkill_sync_work(struct work_struct *work)
|
|||
int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
{
|
||||
static unsigned long rfkill_no;
|
||||
struct device *dev = &rfkill->dev;
|
||||
struct device *dev;
|
||||
int error;
|
||||
|
||||
BUG_ON(!rfkill);
|
||||
if (!rfkill)
|
||||
return -EINVAL;
|
||||
|
||||
dev = &rfkill->dev;
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
|
|
|
@ -1102,6 +1102,7 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
|
|||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
kzfree(wdev->wext.keys);
|
||||
wdev->wext.keys = NULL;
|
||||
#endif
|
||||
/* only initialized if we have a netdev */
|
||||
if (wdev->netdev)
|
||||
|
|
Loading…
Reference in New Issue