* [PATCHv6 8/9] ath10k: Add new api to support TID specific configuration
From: Tamizh chelvam @ 2019-06-18 5:27 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1560835632-17405-1-git-send-email-tamizhr@codeaurora.org>
This patch add ops for set_tid_config to support TID
specific configuration. STA information along with the
TID config change mask to notify driver that which configuration
needs to be applied for this current command.
If the STA info not available in the command then the
configuration will be applied for all connected stations
in the vif. TID specific noack configuration requires
aggregation disabled and rate for the data TID packets
should be basic rates. So, if the TID already configured
with noack policy then driver will ignore the aggregation
or TX rate related configuration for the same data TID.
In TX rate configuration should be applied with highest
preamble configuration(HT rates should not be applied
for the station which supports vht rates).
Vif specific TID configuration will be applied for all
the connected stations except for the station which
already applied with the same configuration for the TID
through station specific command. Newly connecting stations
will be applied with vif TID configuration which will be stored
in ieee80211_vif.
Testing:
* Tested HW: QCA9888
* Tested FW: 10.4-3.5.1-00052
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/core.h | 6 +
drivers/net/wireless/ath/ath10k/mac.c | 633 ++++++++++++++++++++++++++++----
2 files changed, 559 insertions(+), 80 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index e35aae5..3d1b06a 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -82,6 +82,8 @@
/* Default Airtime weight multipler (Tuned for multiclient performance) */
#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4
+#define ATH10K_MAX_RETRY_COUNT 29
+
struct ath10k;
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -504,6 +506,7 @@ struct ath10k_sta {
#endif
/* Protected with ar->data_lock */
u32 peer_ps_state;
+ struct work_struct tid_config_wk;
};
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
@@ -571,6 +574,9 @@ struct ath10k_vif {
struct work_struct ap_csa_work;
struct delayed_work connection_loss_work;
struct cfg80211_bitrate_mask bitrate_mask;
+ u32 tid_conf_changed[IEEE80211_TID_MAX];
+
+ struct ieee80211_tid_config *tid_config;
};
struct ath10k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 9c703d2..0ce9720 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2930,6 +2930,59 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
cancel_delayed_work_sync(&arvif->connection_loss_work);
}
+static int ath10k_new_peer_tid_config(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ struct ath10k_vif *arvif)
+{
+ struct wmi_per_peer_per_tid_cfg_arg arg = {};
+ struct ieee80211_vif *vif = arvif->vif;
+ bool config_apply;
+ int ret, i;
+
+ for (i = 0; i < IEEE80211_TID_MAX; i++) {
+ config_apply = false;
+ if (vif->retry_long[i] || vif->ampdu[i] ||
+ vif->rate_code[i]) {
+ config_apply = true;
+ arg.tid = i;
+ arg.vdev_id = arvif->vdev_id;
+ arg.retry_count = vif->retry_long[i];
+ arg.aggr_control = vif->ampdu[i];
+ arg.rate_ctrl = vif->rate_ctrl[i];
+ arg.rcode_flags = vif->rate_code[i];
+ }
+
+ if (vif->noack[i]) {
+ arg.ack_policy = vif->noack[i];
+ arg.rate_ctrl =
+ WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE;
+ arg.aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
+ config_apply = true;
+ }
+
+ /* Assign default value(-1) to newly connected station.
+ * This is to identify station specific tid configuration not
+ * configured for the station.
+ */
+ sta->retry_long[i] = -1;
+ sta->noack[i] = -1;
+ sta->ampdu[i] = -1;
+
+ if (!config_apply)
+ continue;
+
+ ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
+ ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
+ if (ret) {
+ ath10k_warn(ar, "failed to set per tid retry/aggr config for sta %pM: %d\n",
+ sta->addr, ret);
+ return ret;
+ }
+ memset(&arg, 0, sizeof(arg));
+ }
+ return 0;
+}
+
static int ath10k_station_assoc(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -2995,7 +3048,10 @@ static int ath10k_station_assoc(struct ath10k *ar,
}
}
- return ret;
+ if (!test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map))
+ return ret;
+
+ return ath10k_new_peer_tid_config(ar, sta, arvif);
}
static int ath10k_station_disassoc(struct ath10k *ar,
@@ -6350,6 +6406,340 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif,
ar->num_stations--;
}
+struct ath10k_mac_iter_tid_conf_data {
+ struct ieee80211_vif *curr_vif;
+ struct ath10k *ar;
+};
+
+static bool
+ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ int num_rates = 0;
+ int i;
+
+ num_rates += hweight32(mask->control[band].legacy);
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
+ num_rates += hweight8(mask->control[band].ht_mcs[i]);
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
+ num_rates += hweight16(mask->control[band].vht_mcs[i]);
+
+ return num_rates == 1;
+}
+
+static int
+ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask,
+ u8 *rate, u8 *nss)
+{
+ int rate_idx;
+ int i;
+ u16 bitrate;
+ u8 preamble;
+ u8 hw_rate;
+
+ if (hweight32(mask->control[band].legacy) == 1) {
+ rate_idx = ffs(mask->control[band].legacy) - 1;
+
+ if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
+ rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
+
+ hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
+ bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
+
+ if (ath10k_mac_bitrate_is_cck(bitrate))
+ preamble = WMI_RATE_PREAMBLE_CCK;
+ else
+ preamble = WMI_RATE_PREAMBLE_OFDM;
+
+ *nss = 1;
+ *rate = preamble << 6 |
+ (*nss - 1) << 4 |
+ hw_rate << 0;
+
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
+ if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
+ *nss = i + 1;
+ *rate = WMI_RATE_PREAMBLE_HT << 6 |
+ (*nss - 1) << 4 |
+ (ffs(mask->control[band].ht_mcs[i]) - 1);
+
+ return 0;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
+ if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
+ *nss = i + 1;
+ *rate = WMI_RATE_PREAMBLE_VHT << 6 |
+ (*nss - 1) << 4 |
+ (ffs(mask->control[band].vht_mcs[i]) - 1);
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ u32 rate_ctrl_flag, u8 nss)
+{
+ if (nss > sta->rx_nss) {
+ ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
+ nss, sta->rx_nss);
+ return -EINVAL;
+ }
+
+ if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
+ if (!sta->vht_cap.vht_supported) {
+ ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
+ sta->addr);
+ return -EINVAL;
+ }
+ } else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
+ if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
+ ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
+ sta->addr);
+ return -EINVAL;
+ }
+ } else {
+ if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+ath10k_mac_tid_bitrate_config(struct ath10k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u32 *rate_ctrl_flag, u8 *rate_ctrl,
+ enum nl80211_tx_rate_setting txrate_type,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct cfg80211_chan_def def;
+ enum nl80211_band band;
+ u8 nss, rate;
+ int ret;
+
+ if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
+ return -EINVAL;
+
+ if (txrate_type == NL80211_TX_RATE_AUTOMATIC) {
+ *rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO;
+ *rate_ctrl_flag = 0;
+ return 0;
+ }
+
+ band = def.chan->band;
+
+ if (!ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask))
+ return -EINVAL;
+
+ ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
+ &rate, &nss);
+ if (ret) {
+ ath10k_warn(ar, "failed to get single rate: %d\n",
+ ret);
+ return ret;
+ }
+ *rate_ctrl_flag = rate;
+
+ if (sta && ath10k_mac_validate_rate_mask(ar, sta, *rate_ctrl_flag, nss))
+ return -EINVAL;
+
+ if (txrate_type == NL80211_TX_RATE_FIXED)
+ *rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE;
+ else
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+static void
+ath10k_mac_parse_tid_config(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ struct ieee80211_vif *vif,
+ struct ieee80211_tid_cfg *tid_conf,
+ struct wmi_per_peer_per_tid_cfg_arg *arg)
+{
+ u8 changed = tid_conf->tid_conf_mask;
+ int ret;
+
+ arg->tid = tid_conf->tid;
+
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ if (tid_conf->noack == NL80211_TID_CONFIG_ENABLE) {
+ arg->ack_policy = WMI_PEER_TID_CONFIG_NOACK;
+ arg->rate_ctrl =
+ WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE;
+ arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
+ } else {
+ arg->ack_policy = WMI_PEER_TID_CONFIG_ACK;
+ arg->rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO;
+ arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_ENABLE;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (tid_conf->retry_long == -1) {
+ if (vif->retry_long[arg->tid])
+ arg->retry_count = vif->retry_long[arg->tid];
+ else
+ arg->retry_count = ATH10K_MAX_RETRY_COUNT + 1;
+ } else {
+ /* firmware expects tx attempt value */
+ arg->retry_count = tid_conf->retry_long + 1;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (tid_conf->ampdu) {
+ arg->aggr_control = tid_conf->ampdu;
+ } else {
+ if (vif->ampdu[arg->tid])
+ arg->aggr_control = vif->ampdu[arg->tid];
+ else
+ arg->aggr_control =
+ WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ ret = ath10k_mac_tid_bitrate_config(ar, vif, sta,
+ &arg->rcode_flags,
+ &arg->rate_ctrl,
+ tid_conf->txrate_type,
+ tid_conf->mask);
+ if (ret) {
+ ath10k_warn(ar, "failed to configure bitrate mask %d\n",
+ ret);
+ arg->rcode_flags = 0;
+ arg->rate_ctrl = 0;
+ }
+ kfree(tid_conf->mask);
+ }
+}
+
+static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
+{
+ struct wmi_per_peer_per_tid_cfg_arg arg = {};
+ struct ieee80211_vif *vif;
+ struct ieee80211_sta *sta;
+ struct ath10k_sta *arsta;
+ struct ath10k_vif *arvif;
+ struct ath10k *ar;
+ bool config_apply;
+ int ret, i;
+ u8 changed;
+
+ arsta = container_of(wk, struct ath10k_sta, tid_config_wk);
+ sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
+ arvif = arsta->arvif;
+ vif = arvif->vif;
+ ar = arvif->ar;
+
+ mutex_lock(&ar->conf_mutex);
+
+ ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
+ for (i = 0; i < IEEE80211_TID_MAX; i++) {
+ config_apply = false;
+ changed = arvif->tid_conf_changed[i];
+
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ if (sta->noack[i] != -1) {
+ arg.ack_policy = 0;
+ } else {
+ config_apply = true;
+ arg.ack_policy = vif->noack[i];
+ arg.aggr_control = vif->ampdu[i];
+ arg.rate_ctrl = vif->rate_ctrl[i];
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (sta->retry_long[i] != -1 ||
+ sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.retry_count = 0;
+ } else {
+ arg.retry_count = vif->retry_long[i];
+ config_apply = true;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (sta->ampdu[i] != -1 ||
+ sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.aggr_control = 0;
+ } else {
+ arg.aggr_control = vif->ampdu[i];
+ config_apply = true;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ if (ath10k_mac_validate_rate_mask(ar, sta, vif->rate_code[i],
+ ATH10K_HW_NSS(vif->rate_code[i]))) {
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+
+ if (sta->rate_ctrl[i] >
+ WMI_TID_CONFIG_RATE_CONTROL_AUTO ||
+ sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ } else {
+ arg.rate_ctrl = vif->rate_ctrl[i];
+ arg.rcode_flags = vif->rate_code[i];
+ config_apply = true;
+ }
+ }
+
+ arg.tid = i;
+
+ if (config_apply) {
+ ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
+ if (ret)
+ ath10k_warn(ar, "failed to set per tid config for sta %pM: %d\n",
+ sta->addr, ret);
+ }
+
+ arg.ack_policy = 0;
+ arg.retry_count = 0;
+ arg.aggr_control = 0;
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+
+ mutex_unlock(&ar->conf_mutex);
+}
+
+static void ath10k_mac_vif_stations_tid_conf(void *data,
+ struct ieee80211_sta *sta)
+{
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ struct ath10k_mac_iter_tid_conf_data *iter_data = data;
+ struct ieee80211_vif *sta_vif = arsta->arvif->vif;
+
+ if (sta_vif != iter_data->curr_vif || !sta->wme)
+ return;
+
+ ieee80211_queue_work(iter_data->ar->hw, &arsta->tid_config_wk);
+}
+
static int ath10k_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -6369,6 +6759,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
arsta->arvif = arvif;
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);
+ INIT_WORK(&arsta->tid_config_wk, ath10k_sta_tid_cfg_wk);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
ath10k_mac_txq_init(sta->txq[i]);
@@ -6376,8 +6767,10 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
/* cancel must be done outside the mutex to avoid deadlock */
if ((old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST))
+ new_state == IEEE80211_STA_NOTEXIST)) {
cancel_work_sync(&arsta->update_wk);
+ cancel_work_sync(&arsta->tid_config_wk);
+ }
mutex_lock(&ar->conf_mutex);
@@ -7097,25 +7490,6 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
}
static bool
-ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask)
-{
- int num_rates = 0;
- int i;
-
- num_rates += hweight32(mask->control[band].legacy);
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
- num_rates += hweight8(mask->control[band].ht_mcs[i]);
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
- num_rates += hweight16(mask->control[band].vht_mcs[i]);
-
- return num_rates == 1;
-}
-
-static bool
ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
@@ -7164,65 +7538,6 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
return true;
}
-static int
-ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask,
- u8 *rate, u8 *nss)
-{
- int rate_idx;
- int i;
- u16 bitrate;
- u8 preamble;
- u8 hw_rate;
-
- if (hweight32(mask->control[band].legacy) == 1) {
- rate_idx = ffs(mask->control[band].legacy) - 1;
-
- if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
- rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
-
- hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
- bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
-
- if (ath10k_mac_bitrate_is_cck(bitrate))
- preamble = WMI_RATE_PREAMBLE_CCK;
- else
- preamble = WMI_RATE_PREAMBLE_OFDM;
-
- *nss = 1;
- *rate = preamble << 6 |
- (*nss - 1) << 4 |
- hw_rate << 0;
-
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
- if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
- *nss = i + 1;
- *rate = WMI_RATE_PREAMBLE_HT << 6 |
- (*nss - 1) << 4 |
- (ffs(mask->control[band].ht_mcs[i]) - 1);
-
- return 0;
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
- if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
- *nss = i + 1;
- *rate = WMI_RATE_PREAMBLE_VHT << 6 |
- (*nss - 1) << 4 |
- (ffs(mask->control[band].vht_mcs[i]) - 1);
-
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
u8 rate, u8 nss, u8 sgi, u8 ldpc)
{
@@ -7991,6 +8306,140 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
+static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tid_config *tid_config)
+{
+ struct ath10k *ar = hw->priv;
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
+ struct ath10k_mac_iter_tid_conf_data data = {};
+ struct wmi_per_peer_per_tid_cfg_arg arg = {};
+ int ret, i;
+ u8 changed;
+
+ mutex_lock(&ar->conf_mutex);
+ arg.vdev_id = arvif->vdev_id;
+
+ memset(arvif->tid_conf_changed, 0, sizeof(arvif->tid_conf_changed));
+
+ for (i = 0; i < tid_config->n_tid_conf; i++) {
+ if (tid_config->tid_conf[i].tid >= IEEE80211_TID_MAX)
+ continue;
+
+ ath10k_mac_parse_tid_config(ar, sta, vif,
+ &tid_config->tid_conf[i],
+ &arg);
+ changed = tid_config->tid_conf[i].tid_conf_mask;
+ if (sta) {
+ if (!sta->wme) {
+ ret = -ENOTSUPP;
+ goto exit;
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (sta->noack[arg.tid] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[arg.tid] == WMI_PEER_TID_CONFIG_NOACK)
+ arg.retry_count = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (sta->noack[arg.tid] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[arg.tid] == WMI_PEER_TID_CONFIG_NOACK)
+ arg.aggr_control = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ if (sta->noack[arg.tid] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[arg.tid] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+ }
+
+ ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
+ ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
+ if (ret)
+ goto exit;
+
+ /* Store the configured parameters in success case */
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ if (tid_config->tid_conf[i].noack ==
+ NL80211_TID_CONFIG_DEFAULT) {
+ sta->noack[arg.tid] = -1;
+ } else {
+ sta->noack[arg.tid] = arg.ack_policy;
+ }
+
+ arg.ack_policy = 0;
+ arg.aggr_control = 0;
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (tid_config->tid_conf[i].retry_long == -1) {
+ sta->retry_long[arg.tid] = -1;
+ } else {
+ sta->retry_long[arg.tid] = arg.retry_count;
+ }
+
+ arg.retry_count = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (tid_config->tid_conf[i].ampdu ==
+ NL80211_TID_CONFIG_DEFAULT) {
+ sta->ampdu[arg.tid] = -1;
+ } else {
+ sta->ampdu[arg.tid] = arg.aggr_control;
+ }
+
+ arg.aggr_control = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ sta->rate_ctrl[arg.tid] = arg.rate_ctrl;
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+ } else {
+ arvif->tid_conf_changed[arg.tid] |= changed;
+
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ vif->noack[arg.tid] = arg.ack_policy;
+ vif->ampdu[arg.tid] = arg.aggr_control;
+ vif->rate_ctrl[arg.tid] = arg.rate_ctrl;
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY)
+ vif->retry_long[arg.tid] = arg.retry_count;
+
+ if (changed & IEEE80211_TID_CONF_AMPDU)
+ vif->ampdu[arg.tid] = arg.aggr_control;
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ vif->rate_ctrl[arg.tid] = arg.rate_ctrl;
+ vif->rate_code[arg.tid] = arg.rcode_flags;
+ }
+ }
+ }
+
+ if (sta)
+ goto exit;
+
+ ret = 0;
+ data.curr_vif = vif;
+ data.ar = ar;
+
+ ieee80211_iterate_stations_atomic(hw, ath10k_mac_vif_stations_tid_conf,
+ &data);
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_mac_op_tx,
.wake_tx_queue = ath10k_mac_op_wake_tx_queue,
@@ -8033,6 +8482,7 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw,
.switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx,
.sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove,
.sta_statistics = ath10k_sta_statistics,
+ .set_tid_config = ath10k_mac_op_set_tid_config,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
@@ -8695,6 +9145,29 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+ if (test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) {
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK);
+ ar->hw->wiphy->max_data_retry_count = ATH10K_MAX_RETRY_COUNT;
+ ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT;
+ } else {
+ ar->ops->set_tid_config = NULL;
+ ar->hw->wiphy->flags &= ~WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT;
+ }
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 0/9] cfg80211/mac80211: Add support for TID specific configuration
From: Tamizh chelvam @ 2019-06-18 5:27 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
Add infrastructure to support per TID configurations like noack policy,
retry count, AMPDU control(disable/enable), RTSCTS control(enable/disable)
and TX rate mask configurations.
This will be useful for the driver which can supports data TID
specific configuration rather than phy level configurations.
Here NL80211_CMD_SET_TID_CONFIG added to support this operation by
accepting TID configuration.
This command can accept STA mac addreess to make the configuration
station specific rather than applying to all the connected stations
to the netdev.
And this nested command configuration can accept multiple number of
data TID specific configuration in a single command,
enum ieee80211_tid_conf_mask used to notify the driver that which
configuration got modified for the TID.
Tamizh chelvam (9):
nl80211: New netlink command for TID specific configuration
nl80211: Add new netlink attribute for TID speicific retry count
nl80211: Add netlink attribute for AMPDU aggregation enable/disable
nl80211: Add netlink attribute to enable/disable RTS_CTS
nl80211: Add netlink attribute to configure TID specific tx rate
mac80211: Add api to support configuring TID specific configuration
ath10k: Add wmi command support for station specific TID config
ath10k: Add new api to support TID specific configuration
ath10k: Add extended TID configuration support
v6:
* Addressed Johannes comments.
v5:
* Fixed possible memleak of 'tid_conf' in nl80211_set_tid_config.
v4:
* Fixed kbuild warnings.
v3:
* Modified "nl80211: Add netlink attribute to configure TID specific tx rate" patch
to accept multiple TX rate configuration at a time.
* Modified noack and ampdu variable data type to int in
"mac80211: Add api to support configuring TID specific configuration" patch to store
default configuration.
* Modified "ath10k: Add new api to support TID specific configuration" patch to handle
default values for noack and ampdu. And added sta pointer sanity check in
ath10k_mac_tid_bitrate_config function.
* Fixed "ath10k: Add extended TID configuration support" wmi command parameters
assigned part.
v2:
* Added support to accept multiple TID configuration
* Added support to configure TX rate and RTSCTS control
drivers/net/wireless/ath/ath10k/core.c | 4 +
drivers/net/wireless/ath/ath10k/core.h | 6 +
drivers/net/wireless/ath/ath10k/mac.c | 681 +++++++++++++++++++++++++----
drivers/net/wireless/ath/ath10k/wmi-ops.h | 19 +
drivers/net/wireless/ath/ath10k/wmi.c | 35 ++
drivers/net/wireless/ath/ath10k/wmi.h | 72 +++
include/net/cfg80211.h | 57 +++
include/net/mac80211.h | 38 ++
include/uapi/linux/nl80211.h | 188 ++++++++
net/mac80211/cfg.c | 28 ++
net/mac80211/driver-ops.h | 15 +
net/wireless/nl80211.c | 284 +++++++++++-
net/wireless/rdev-ops.h | 12 +
net/wireless/trace.h | 17 +
14 files changed, 1371 insertions(+), 85 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCHv6 9/9] ath10k: Add extended TID configuration support
From: Tamizh chelvam @ 2019-06-18 5:27 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1560835632-17405-1-git-send-email-tamizhr@codeaurora.org>
This patch extend TID configuration support to configure
RTS_CTS control and TX rate limit. Tx rate limit is
similar to auto rate but it will be limited to the user
configured rate mask rather than the station's highest
supported rate mask. Here ext_tid_cfg_bitmap added
to notify the target which extended configuration
parameter has modified(here RTS_CTS).
WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT service flag
introduced to advertise this support.
Testing:
* Tested HW: QCA9984
* Tested FW: 10.4-3.9.0.2-00021
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/core.c | 4 +++
drivers/net/wireless/ath/ath10k/mac.c | 48 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.c | 9 ++++--
drivers/net/wireless/ath/ath10k/wmi.h | 20 +++++++++++++
4 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index aff5856..5c021aa 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2636,6 +2636,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
val |= WMI_10_4_REPORT_AIRTIME;
+ if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ ar->wmi.svc_map))
+ val |= WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT;
+
status = ath10k_mac_ext_resource_config(ar, val);
if (status) {
ath10k_err(ar,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 0ce9720..79e5ec7 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2950,6 +2950,12 @@ static int ath10k_new_peer_tid_config(struct ath10k *ar,
arg.aggr_control = vif->ampdu[i];
arg.rate_ctrl = vif->rate_ctrl[i];
arg.rcode_flags = vif->rate_code[i];
+ if (vif->rtscts[i])
+ arg.ext_tid_cfg_bitmap =
+ WMI_EXT_TID_RTS_CTS_CONFIG;
+ else
+ arg.ext_tid_cfg_bitmap = 0;
+ arg.rtscts_ctrl = vif->rtscts[i];
}
if (vif->noack[i]) {
@@ -6560,6 +6566,10 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
if (txrate_type == NL80211_TX_RATE_FIXED)
*rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE;
+ else if (txrate_type == NL80211_TX_RATE_LIMITED &&
+ (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ ar->wmi.svc_map)))
+ *rate_ctrl = WMI_PEER_TID_CONFIG_RATE_UPPER_CAP;
else
return -EOPNOTSUPP;
return 0;
@@ -6628,6 +6638,14 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
}
kfree(tid_conf->mask);
}
+
+ if (changed & IEEE80211_TID_CONF_RTSCTS) {
+ if (tid_conf->rtscts)
+ arg->rtscts_ctrl = tid_conf->rtscts - 1;
+ else
+ arg->rtscts_ctrl = WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE;
+ arg->ext_tid_cfg_bitmap = WMI_EXT_TID_RTS_CTS_CONFIG;
+ }
}
static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
@@ -6708,6 +6726,18 @@ static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
}
}
+ if (changed & IEEE80211_TID_CONF_RTSCTS) {
+ if (sta->rtscts[i]) {
+ arg.rtscts_ctrl = 0;
+ arg.ext_tid_cfg_bitmap = 0;
+ } else {
+ arg.rtscts_ctrl = vif->rtscts[i] - 1;
+ arg.ext_tid_cfg_bitmap =
+ WMI_EXT_TID_RTS_CTS_CONFIG;
+ config_apply = true;
+ }
+ }
+
arg.tid = i;
if (config_apply) {
@@ -8403,6 +8433,13 @@ static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
arg.rate_ctrl = 0;
arg.rcode_flags = 0;
}
+
+ if (changed & IEEE80211_TID_CONF_RTSCTS) {
+ sta->rtscts[arg.tid] =
+ tid_config->tid_conf[i].rtscts;
+ arg.rtscts_ctrl = 0;
+ arg.ext_tid_cfg_bitmap = 0;
+ }
} else {
arvif->tid_conf_changed[arg.tid] |= changed;
@@ -8422,6 +8459,10 @@ static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
vif->rate_ctrl[arg.tid] = arg.rate_ctrl;
vif->rate_code[arg.tid] = arg.rcode_flags;
}
+
+ if (changed & IEEE80211_TID_CONF_RTSCTS)
+ vif->rtscts[arg.tid] =
+ tid_config->tid_conf[i].rtscts;
}
}
@@ -9168,6 +9209,13 @@ int ath10k_mac_register(struct ath10k *ar)
ar->ops->set_tid_config = NULL;
ar->hw->wiphy->flags &= ~WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT;
}
+
+ if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) {
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL);
+ }
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6b1c70d..544a621 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -8902,11 +8902,14 @@ static u32 ath10k_wmi_prepare_peer_qos(u8 uapsd_queues, u8 sp)
cmd->rate_control = cpu_to_le32(arg->rate_ctrl);
cmd->retry_count = cpu_to_le32(arg->retry_count);
cmd->rcode_flags = cpu_to_le32(arg->rcode_flags);
+ cmd->ext_tid_cfg_bitmap = cpu_to_le32(arg->ext_tid_cfg_bitmap);
+ cmd->rtscts_ctrl = cpu_to_le32(arg->rtscts_ctrl);
ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d mac_addr %pM\n",
- arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control, arg->rate_ctrl,
- arg->rcode_flags, arg->retry_count, arg->peer_macaddr.addr);
+ "wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d rtscts %d ext_tid_cfg_bitmap %d mac_addr %pM\n",
+ arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control,
+ arg->rate_ctrl, arg->rcode_flags, arg->retry_count, arg->rtscts_ctrl,
+ arg->ext_tid_cfg_bitmap, arg->peer_macaddr.addr);
return skb;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 41aaddf..cec3731 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -201,6 +201,7 @@ enum wmi_service {
WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
WMI_SERVICE_REPORT_AIRTIME,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
/* Remember to add the new value to wmi_service_name()! */
@@ -493,6 +494,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
SVCSTR(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT);
+ SVCSTR(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT);
case WMI_SERVICE_MAX:
return NULL;
@@ -822,6 +824,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_REPORT_AIRTIME, len);
SVCMAP(WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, len);
}
#undef SVCMAP
@@ -7188,6 +7192,16 @@ enum wmi_tid_rate_ctrl_conf {
WMI_TID_CONFIG_RATE_CONTROL_AUTO,
WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE,
WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE,
+ WMI_PEER_TID_CONFIG_RATE_UPPER_CAP,
+};
+
+enum wmi_tid_rtscts_control_conf {
+ WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE,
+ WMI_TID_CONFIG_RTSCTS_CONTROL_DISABLE,
+};
+
+enum wmi_ext_tid_config_map {
+ WMI_EXT_TID_RTS_CTS_CONFIG = BIT(0),
};
struct wmi_per_peer_per_tid_cfg_arg {
@@ -7199,6 +7213,8 @@ struct wmi_per_peer_per_tid_cfg_arg {
u8 rate_ctrl;
u32 retry_count;
u32 rcode_flags;
+ u32 ext_tid_cfg_bitmap;
+ u32 rtscts_ctrl;
};
struct wmi_peer_per_tid_cfg_cmd {
@@ -7214,6 +7230,10 @@ struct wmi_peer_per_tid_cfg_cmd {
__le32 rate_control;
__le32 rcode_flags;
__le32 retry_count;
+ /* See enum wmi_ext_tid_config_map */
+ __le32 ext_tid_cfg_bitmap;
+ /* see enum wmi_tid_rtscts_control_conf */
+ __le32 rtscts_ctrl;
} __packed;
enum wmi_txbf_conf {
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 3/9] nl80211: Add netlink attribute for AMPDU aggregation enable/disable
From: Tamizh chelvam @ 2019-06-18 5:27 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1560835632-17405-1-git-send-email-tamizhr@codeaurora.org>
Introduce NL80211_TID_ATTR_CONFIG_AMPDU_CTRL in nl80211_attr_tid_config
to accept TID specific AMPDU aggregation enable/disable configuration
through NL80211_CMD_SET_TID_CONFIG command. TID for which the
aggregation control configuration is to be applied is passed in
NL80211_TID_ATTR_CONFIG_TID attribute. When the user-space wants this
configuration peer specific rather than being applied for all the
connected stations, MAC address of the peer can be passed in
NL80211_ATTR_MAC attribute.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL and supporting per-STA data TID
ampdu configuration should advertise NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 3 +++
include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++++
net/wireless/nl80211.c | 25 +++++++++++++++++++++++++
3 files changed, 50 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 91bcb07..d2814e8 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -528,6 +528,7 @@ struct cfg80211_chan_def {
enum ieee80211_tid_conf_mask {
IEEE80211_TID_CONF_NOACK = BIT(0),
IEEE80211_TID_CONF_RETRY = BIT(1),
+ IEEE80211_TID_CONF_AMPDU = BIT(2),
};
/**
@@ -538,6 +539,7 @@ enum ieee80211_tid_conf_mask {
* @noack: noack configuration value for the TID
* @retry_long: retry count value
* @retry_short: retry count value
+ * @ampdu: Enable/Disable aggregation
*/
struct ieee80211_tid_cfg {
u8 tid;
@@ -545,6 +547,7 @@ struct ieee80211_tid_cfg {
u8 noack;
int retry_long;
int retry_short;
+ u8 ampdu;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index d30d7c9..465dbc6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4712,6 +4712,21 @@ enum nl80211_tid_config {
* the max value should be advertised by the driver through
* max_data_retry_count. when this attribute is not present, the driver
* would use the default configuration.
+ * @NL80211_TID_ATTR_CONFIG_AMPDU_CTRL: Enable/Disable aggregation for the TID
+ * specified in %%NL80211_TID_ATTR_CONFIG_TID. Its type is u8,
+ * if the peer MAC address is passed in %NL80211_ATTR_MAC, the aggregation
+ * configuration is applied
+ * to the data frame for the tid to that connected station.
+ * Station specific aggregation configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, this configuration
+ * should be treated as per-netdev configuration. This configuration will
+ * be cleared when the interface goes down and on the disconnection from a
+ * BSS. Driver supporting this feature should advertise
+ * NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL and supporting per station
+ * aggregation configuration should advertise
+ * NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL.
*/
enum nl80211_tid_attr_config {
__NL80211_TID_ATTR_INVALID,
@@ -4720,6 +4735,7 @@ enum nl80211_tid_attr_config {
NL80211_TID_ATTR_CONFIG_RETRY,
NL80211_TID_ATTR_CONFIG_RETRY_SHORT,
NL80211_TID_ATTR_CONFIG_RETRY_LONG,
+ NL80211_TID_ATTR_CONFIG_AMPDU_CTRL,
/* keep last */
__NL80211_TID_ATTR_CONFIG_AFTER_LAST,
@@ -5545,6 +5561,10 @@ enum nl80211_feature_flags {
* count functionality.
* @NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG: Driver supports STA specific
* data retry count functionality.
+ * @NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL: Driver supports TID specific
+ * aggregation control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL: Driver supports per STA
+ * specific TID aggregation control(enable/disable).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5595,6 +5615,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG,
NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG,
NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG,
+ NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL,
+ NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a21a4f4..a8982de 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -289,6 +289,8 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_TID_ATTR_CONFIG_RETRY] = { .type = NLA_FLAG },
[NL80211_TID_ATTR_CONFIG_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 0),
[NL80211_TID_ATTR_CONFIG_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 0),
+ [NL80211_TID_ATTR_CONFIG_AMPDU_CTRL] =
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
@@ -13661,6 +13663,29 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
}
}
+ if (attrs[NL80211_TID_ATTR_CONFIG_AMPDU_CTRL]) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL)) {
+ NL_SET_ERR_MSG_ATTR(extack,
+ attrs[NL80211_TID_ATTR_CONFIG_AMPDU_CTRL],
+ "TID specific configuration not "
+ "supported");
+ return -ENOTSUPP;
+ }
+
+ if (peer && !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL)) {
+ NL_SET_ERR_MSG_ATTR(extack,
+ attrs[NL80211_TID_ATTR_CONFIG_AMPDU_CTRL],
+ "peer specfic TID configuration not "
+ "supported");
+ return -ENOTSUPP;
+ }
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_AMPDU;
+ tid_conf->ampdu =
+ nla_get_u8(attrs[NL80211_TID_ATTR_CONFIG_AMPDU_CTRL]);
+ }
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 4/9] nl80211: Add netlink attribute to enable/disable RTS_CTS
From: Tamizh chelvam @ 2019-06-18 5:27 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1560835632-17405-1-git-send-email-tamizhr@codeaurora.org>
Introduce NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL in nl80211_attr_tid_config
to accept TID specific RTS_CTS enable/disable configuration
through NL80211_CMD_SET_TID_CONFIG command. TID for which the
RTS_CTS control configuration is to be applied is passed in
NL80211_TID_ATTR_CONFIG_TID attribute. When the user-space wants this
configuration peer specific rather than being applied for all the
connected stations, MAC address of the peer can be passed in
NL80211_ATTR_MAC attribute.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL and supporting per-STA data TID
RTS_CTS configuration should advertise NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 3 +++
include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++++
net/wireless/nl80211.c | 27 +++++++++++++++++++++++++++
3 files changed, 52 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d2814e8..1b875d8 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -529,6 +529,7 @@ enum ieee80211_tid_conf_mask {
IEEE80211_TID_CONF_NOACK = BIT(0),
IEEE80211_TID_CONF_RETRY = BIT(1),
IEEE80211_TID_CONF_AMPDU = BIT(2),
+ IEEE80211_TID_CONF_RTSCTS = BIT(3),
};
/**
@@ -540,6 +541,7 @@ enum ieee80211_tid_conf_mask {
* @retry_long: retry count value
* @retry_short: retry count value
* @ampdu: Enable/Disable aggregation
+ * @rtscts: Enable/Disable RTS/CTS
*/
struct ieee80211_tid_cfg {
u8 tid;
@@ -548,6 +550,7 @@ struct ieee80211_tid_cfg {
int retry_long;
int retry_short;
u8 ampdu;
+ u8 rtscts;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 465dbc6..df4e07d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4727,6 +4727,21 @@ enum nl80211_tid_config {
* NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL and supporting per station
* aggregation configuration should advertise
* NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL.
+ * @NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TID
+ * specified in %%NL80211_TID_ATTR_CONFIG_TID. It is u8 type, if the
+ * peer MAC address is passed in %NL80211_ATTR_MAC, then this
+ * configuration is applied to the data frame for the tid to that
+ * connected station.
+ * Station specific RTS_CTS configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, this configuration
+ * should be treated as per-netdev configuration. This configuration will
+ * be cleared when the interface goes down and on the disconnection from a
+ * BSS. Driver supporting this feature should advertise
+ * NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL and supporting per station
+ * RTS_CTS configuration should advertise
+ * NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL.
*/
enum nl80211_tid_attr_config {
__NL80211_TID_ATTR_INVALID,
@@ -4736,6 +4751,7 @@ enum nl80211_tid_attr_config {
NL80211_TID_ATTR_CONFIG_RETRY_SHORT,
NL80211_TID_ATTR_CONFIG_RETRY_LONG,
NL80211_TID_ATTR_CONFIG_AMPDU_CTRL,
+ NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL,
/* keep last */
__NL80211_TID_ATTR_CONFIG_AFTER_LAST,
@@ -5565,6 +5581,10 @@ enum nl80211_feature_flags {
* aggregation control(enable/disable).
* @NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL: Driver supports per STA
* specific TID aggregation control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL: Driver supports TID specific
+ * RTS_CTS control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL: Driver supports STA specific
+ * RTS_CTS control(enable/disable).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5617,6 +5637,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG,
NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL,
NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL,
+ NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL,
+ NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a8982de..370c483 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -291,6 +291,8 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_TID_ATTR_CONFIG_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 0),
[NL80211_TID_ATTR_CONFIG_AMPDU_CTRL] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
+ [NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL] =
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
@@ -13686,6 +13688,31 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
tid_conf->ampdu =
nla_get_u8(attrs[NL80211_TID_ATTR_CONFIG_AMPDU_CTRL]);
}
+
+ if (attrs[NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL]) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL)) {
+ NL_SET_ERR_MSG_ATTR(extack,
+ attrs[NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL],
+ "TID specific configuration not "
+ "supported");
+ return -ENOTSUPP;
+ }
+
+ if (peer && !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL)) {
+ NL_SET_ERR_MSG_ATTR(extack,
+ attrs[NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL],
+ "peer specfic TID configuration not "
+ "supported");
+ return -ENOTSUPP;
+ }
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_RTSCTS;
+ tid_conf->rtscts =
+ nla_get_u8(attrs[NL80211_TID_ATTR_CONFIG_RTSCTS_CTRL]);
+ }
+
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 6/9] mac80211: Add api to support configuring TID specific configuration
From: Tamizh chelvam @ 2019-06-18 5:27 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1560835632-17405-1-git-send-email-tamizhr@codeaurora.org>
Implement drv_set_tid_config api to allow TID specific
configuration. This per-TID configuration
will be applied for all the connected stations when MAC is NULL.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/mac80211.h | 38 ++++++++++++++++++++++++++++++++++++++
net/mac80211/cfg.c | 28 ++++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 15 +++++++++++++++
3 files changed, 81 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4411120..f97c755 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1563,6 +1563,8 @@ enum ieee80211_vif_flags {
IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
};
+#define IEEE80211_TID_MAX 8
+
/**
* struct ieee80211_vif - per-interface data
*
@@ -1600,6 +1602,13 @@ enum ieee80211_vif_flags {
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
* protected by fq->lock.
+ * @noack: per-TID noack policy.
+ * @retry_short: per-TID retry count.
+ * @retry_long: per-TID count.
+ * @ampdu: per-TID Aggregation-MPDU.
+ * @rate_ctrl: per-TID tx rate control type.
+ * @rate_code: per-TID tx rate code mask.
+ * @rtscts: per-TID RTSCTS policy.
*/
struct ieee80211_vif {
enum nl80211_iftype type;
@@ -1626,6 +1635,14 @@ struct ieee80211_vif {
bool txqs_stopped[IEEE80211_NUM_ACS];
+ int noack[IEEE80211_TID_MAX];
+ int retry_short[IEEE80211_TID_MAX];
+ int retry_long[IEEE80211_TID_MAX];
+ int ampdu[IEEE80211_TID_MAX];
+ u8 rate_ctrl[IEEE80211_TID_MAX];
+ u32 rate_code[IEEE80211_TID_MAX];
+ u8 rtscts[IEEE80211_TID_MAX];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -1960,6 +1977,12 @@ struct ieee80211_sta_txpwr {
* @max_tid_amsdu_len: Maximum A-MSDU size in bytes for this TID
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
* the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
+ * @noack: per-TID noack policy.
+ * @retry_short: per-TID retry count.
+ * @retry_long: per-TID count.
+ * @ampdu: per-TID Aggregation-MPDU.
+ * @rate_ctrl: per-TID tx rate control type.
+ * @rtscts: per-TID RTSCTS policy.
*/
struct ieee80211_sta {
u32 supp_rates[NUM_NL80211_BANDS];
@@ -2004,6 +2027,13 @@ struct ieee80211_sta {
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];
+ int noack[IEEE80211_TID_MAX];
+ int retry_short[IEEE80211_TID_MAX];
+ int retry_long[IEEE80211_TID_MAX];
+ int ampdu[IEEE80211_TID_MAX];
+ u8 rate_ctrl[IEEE80211_TID_MAX];
+ u8 rtscts[IEEE80211_TID_MAX];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -3743,6 +3773,10 @@ enum ieee80211_reconfig_type {
*
* @start_pmsr: start peer measurement (e.g. FTM) (this call can sleep)
* @abort_pmsr: abort peer measurement (this call can sleep)
+ * @set_tid_config: TID specific configurations will be applied for a particular
+ * station when @sta is non-NULL. When @sta is %NULL, then the configuration
+ * will be for all the connected clients in the vif.
+ * This callback may sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -4043,6 +4077,10 @@ struct ieee80211_ops {
struct cfg80211_pmsr_request *request);
void (*abort_pmsr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request);
+ int (*set_tid_config)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tid_config *tid_conf);
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fcf1dfc..55c08af 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3940,6 +3940,33 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
return drv_abort_pmsr(local, sdata, request);
}
+static int ieee80211_set_tid_config(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_tid_config *tid_conf)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct sta_info *sta;
+ int ret;
+
+ if (!sdata->local->ops->set_tid_config)
+ return -EOPNOTSUPP;
+
+ if (!tid_conf->peer)
+ return drv_set_tid_config(sdata->local, sdata, NULL, tid_conf);
+
+ mutex_lock(&sdata->local->sta_mtx);
+
+ sta = sta_info_get_bss(sdata, tid_conf->peer);
+ if (!sta) {
+ mutex_unlock(&sdata->local->sta_mtx);
+ return -ENOENT;
+ }
+
+ ret = drv_set_tid_config(sdata->local, sdata, &sta->sta, tid_conf);
+ mutex_unlock(&sdata->local->sta_mtx);
+ return ret;
+}
+
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -4038,4 +4065,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
.start_pmsr = ieee80211_start_pmsr,
.abort_pmsr = ieee80211_abort_pmsr,
.probe_mesh_link = ieee80211_probe_mesh_link,
+ .set_tid_config = ieee80211_set_tid_config,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index c2d8b54..d1ffca5 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1356,4 +1356,19 @@ static inline void drv_del_nan_func(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+static inline int drv_set_tid_config(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tid_config *tid_conf)
+{
+ int ret;
+
+ might_sleep();
+ ret = local->ops->set_tid_config(&local->hw, &sdata->vif, sta,
+ tid_conf);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
#endif /* __MAC80211_DRIVER_OPS */
--
1.7.9.5
^ permalink raw reply related
* Re: wpa_supplicant 2.8 fails in brcmf_cfg80211_set_pmk
From: Chi-Hsien Lin @ 2019-06-18 5:33 UTC (permalink / raw)
To: Marcel Holtmann
Cc: Stefan Wahren, Stanley Hsu, Arend van Spriel, Franky Lin,
Hante Meuleman, Wright Feng, linux-wireless@vger.kernel.org,
brcm80211-dev-list.pdl@broadcom.com, brcm80211-dev-list
In-Reply-To: <2AF2E0A7-23F0-4FFE-A658-4906FF546199@holtmann.org>
[-- Attachment #1: Type: text/plain, Size: 1302 bytes --]
On 06/17/2019 10:33, Marcel Holtmann wrote:
> Hi Chi-hsien,
>
>>>> i was able to reproduce an (maybe older issue) with 4-way handshake
>>>> offloading for 802.1X in the brcmfmac driver. My setup consists of
>>>> Raspberry Pi 3 B (current linux-next, arm64/defconfig) on STA side and a
>>>> Raspberry Pi 3 A+ (Linux 4.19) on AP side.
>>>
>>> Looks like Raspberry Pi isn't the only affected platform [3], [4].
>>>
>>> [3] - https://bugzilla.redhat.com/show_bug.cgi?id=1665608
>>> [4] - https://bugzilla.kernel.org/show_bug.cgi?id=202521
>>
>> Stefan,
>>
>> Could you please try the attached patch for your wpa_supplicant? We'll
>> upstream if it works for you.
>
> I hope that someone is also providing a kernel patch to fix the issue. Hacking around a kernel issue in userspace is not enough. Fix the root cause in the kernel.
Marcel,
This is a kernel warning for invalid application PMK set actions, so the
fix is to only set PMK to wifi driver when 4-way is offloaded. I think
Arend added the WARN_ON() intentionally to catch application misuse of
PMK setting.
You may also remove the warnings with the attached patch, but let's see
what Arend says first.
Arend,
Any comment?
Regards,
Chi-hsien Lin
>
> Regards
>
> Marcel
>
> .
>
[-- Attachment #2: 0001-brcmfmac-remove-WARN_ON-for-invalid-pmk-set.patch --]
[-- Type: text/plain, Size: 1896 bytes --]
From a54c0e7dcd815a5ef31bdbabe44792f2cedce0e3 Mon Sep 17 00:00:00 2001
From: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
Date: Mon, 17 Jun 2019 23:42:23 -0500
Subject: [PATCH] brcmfmac: remove WARN_ON() for invalid pmk set
2526ff21aa77c("brcmfmac: support 4-way handshake offloading for 802.1X")
added WARN_ON() to catch invalid PMK usage. Remove them and keep the
error return EINVAL.
Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index e9c8b21091a1..08b5fad38307 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1938,7 +1938,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
}
if (sme->crypto.psk) {
- if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
+ if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
err = -EINVAL;
goto done;
}
@@ -5173,7 +5173,7 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
/* expect using firmware supplicant for 1X */
ifp = netdev_priv(dev);
- if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
+ if (ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X)
return -EINVAL;
if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
@@ -5189,7 +5189,7 @@ static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
brcmf_dbg(TRACE, "enter\n");
ifp = netdev_priv(dev);
- if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
+ if (ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X)
return -EINVAL;
return brcmf_set_pmk(ifp, NULL, 0);
--
2.1.0
^ permalink raw reply related
* [PATCH V6 2/2] ath10k: add tx hw 802.11 encapusaltion offloading suppor
From: John Crispin @ 2019-06-18 6:28 UTC (permalink / raw)
To: Johannes Berg, Kalle Valo
Cc: ath10k, linux-wireless, Vasanthakumar Thiagarajan, John Crispin
In-Reply-To: <20190618062807.17158-1-john@phrozen.org>
From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
This patch adds support for ethernet rxtx mode to the driver. The feature
is enabled via a new module parameter. If enabled to driver will enable
the feature on a per vif basis if all other requirements were met.
Testing on a IPQ4019 based hardware shows a increase in TCP throughput
of ~20% when the feature is enabled.
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/wireless/ath/ath10k/core.c | 11 ++++
drivers/net/wireless/ath/ath10k/core.h | 3 +
drivers/net/wireless/ath/ath10k/htt_tx.c | 24 +++++---
drivers/net/wireless/ath/ath10k/mac.c | 70 +++++++++++++++++++-----
drivers/net/wireless/ath/ath10k/txrx.c | 11 +++-
5 files changed, 94 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index aff585658fc0..ac6e41f09f2a 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -30,6 +30,7 @@ static unsigned int ath10k_cryptmode_param;
static bool uart_print;
static bool skip_otp;
static bool rawmode;
+static bool ethernetmode;
unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |
BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);
@@ -41,6 +42,7 @@ module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644);
module_param(rawmode, bool, 0644);
module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
+module_param(ethernetmode, bool, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
@@ -48,6 +50,7 @@ MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
+MODULE_PARM_DESC(ethernetmode, "Use ethernet frame datapath");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
@@ -2939,6 +2942,14 @@ static void ath10k_core_register_work(struct work_struct *work)
/* peer stats are enabled by default */
set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
+ if (ethernetmode && rawmode) {
+ ath10k_err(ar, "ethernet and raw mode cannot co-exist\n");
+ status = -EINVAL;
+ goto err;
+ }
+
+ ar->ethernetmode = ethernetmode;
+
status = ath10k_core_probe_fw(ar);
if (status) {
ath10k_err(ar, "could not probe fw (%d)\n", status);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index e35aae5146f1..1bc463a39d6c 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -109,6 +109,7 @@ enum ath10k_skb_flags {
ATH10K_SKB_F_MGMT = BIT(3),
ATH10K_SKB_F_QOS = BIT(4),
ATH10K_SKB_F_RAW_TX = BIT(5),
+ ATH10K_SKB_F_HW_80211_ENCAP = BIT(6),
};
struct ath10k_skb_cb {
@@ -1190,6 +1191,8 @@ struct ath10k {
struct work_struct radar_confirmation_work;
struct ath10k_bus_params bus_param;
+ bool ethernetmode;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index d8e9cc0bb772..ae4c48b8b706 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1143,6 +1143,10 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
+ /* Firmware takes care of tid classification for ethernet format */
+ if (cb->flags & ATH10K_SKB_F_HW_80211_ENCAP)
+ return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
+
if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
return HTT_DATA_TX_EXT_TID_MGMT;
else if (cb->flags & ATH10K_SKB_F_QOS)
@@ -1351,15 +1355,17 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
txbuf_paddr = htt->txbuf.paddr +
(sizeof(struct ath10k_htt_txbuf_32) * msdu_id);
- if ((ieee80211_is_action(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control) ||
- ieee80211_is_disassoc(hdr->frame_control)) &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
- } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
- txmode == ATH10K_HW_TXRX_RAW &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
+ if ((ieee80211_is_action(hdr->frame_control) ||
+ ieee80211_is_deauth(hdr->frame_control) ||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
+ txmode == ATH10K_HW_TXRX_RAW &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+ }
}
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 9c703d287333..6918587951cb 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3386,12 +3386,16 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
struct sk_buff *skb)
{
const struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
__le16 fc = hdr->frame_control;
if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
return ATH10K_HW_TXRX_RAW;
+ if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+ return ATH10K_HW_TXRX_ETHERNET;
+
if (ieee80211_is_mgmt(fc))
return ATH10K_HW_TXRX_MGMT;
@@ -3544,6 +3548,15 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
ieee80211_is_data_qos(hdr->frame_control);
cb->flags = 0;
+ cb->vif = vif;
+ cb->txq = txq;
+ cb->airtime_est = airtime;
+
+ if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
+ cb->flags |= ATH10K_SKB_F_HW_80211_ENCAP;
+ return;
+ }
+
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
@@ -3562,10 +3575,6 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
cb->flags |= ATH10K_SKB_F_RAW_TX;
}
-
- cb->vif = vif;
- cb->txq = txq;
- cb->airtime_est = airtime;
}
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
@@ -3675,6 +3684,9 @@ static int ath10k_mac_tx(struct ath10k *ar,
const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
int ret;
+ if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+ goto skip_encap;
+
/* We should disable CCK RATE due to P2P */
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
@@ -3698,6 +3710,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
}
}
+skip_encap:
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
if (!ath10k_mac_tx_frm_has_freq(ar)) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
@@ -3747,6 +3760,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
int ret;
unsigned long time_left;
bool tmp_peer_created = false;
+ struct ieee80211_tx_info *info;
/* FW requirement: We must create a peer before FW will send out
* an offchannel frame. Otherwise the frame will be stuck and
@@ -3766,8 +3780,14 @@ void ath10k_offchan_tx_work(struct work_struct *work)
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
skb);
- hdr = (struct ieee80211_hdr *)skb->data;
- peer_addr = ieee80211_get_DA(hdr);
+ info = IEEE80211_SKB_CB(skb);
+
+ if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
+ peer_addr = skb->data;
+ } else {
+ hdr = (struct ieee80211_hdr *)skb->data;
+ peer_addr = ieee80211_get_DA(hdr);
+ }
spin_lock_bh(&ar->data_lock);
vdev_id = ar->scan.vdev_id;
@@ -4295,7 +4315,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif = info->control.vif;
struct ieee80211_sta *sta = control->sta;
struct ieee80211_txq *txq = NULL;
- struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ieee80211_hdr *hdr;
enum ath10k_hw_txrx_mode txmode;
enum ath10k_mac_tx_path txpath;
bool is_htt;
@@ -4326,14 +4346,20 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
return;
}
- ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp);
- if (ret) {
- ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n",
- ret);
- ath10k_htt_tx_dec_pending(htt);
- spin_unlock_bh(&ar->htt.tx_lock);
- ieee80211_free_txskb(ar->hw, skb);
- return;
+ if (is_mgmt) {
+ hdr = (struct ieee80211_hdr *)skb->data;
+ is_presp = ieee80211_is_probe_resp(hdr->frame_control);
+
+ ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt,
+ is_presp);
+ if (ret) {
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n",
+ ret);
+ ath10k_htt_tx_dec_pending(htt);
+ spin_unlock_bh(&ar->htt.tx_lock);
+ ieee80211_free_txskb(ar->hw, skb);
+ return;
+ }
}
spin_unlock_bh(&ar->htt.tx_lock);
}
@@ -5094,6 +5120,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
enum wmi_sta_powersave_param param;
+ int hw_encap = 0;
int ret = 0;
u32 value;
int bit;
@@ -5185,6 +5212,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
break;
}
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_AP:
+ hw_encap = 1;
+ break;
+ default:
+ break;
+ }
+ ieee80211_set_hw_80211_encap(vif, ar->ethernetmode & hw_encap);
+
/* Using vdev_id as queue number will make it very easy to do per-vif
* tx queue locking. This shouldn't wrap due to interface combinations
* but do a modulo for correctness sake and prevent using offchannel tx
@@ -8602,6 +8640,8 @@ int ath10k_mac_register(struct ath10k *ar)
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
+ if (ar->ethernetmode)
+ ieee80211_hw_set(ar->hw, SUPPORTS_80211_ENCAP);
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index c5818d28f55a..bad5e7335c0e 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -50,6 +50,8 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ath10k_skb_cb *skb_cb;
struct ath10k_txq *artxq;
struct sk_buff *msdu;
+ struct ieee80211_vif *vif;
+ u8 flags;
ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx completion msdu_id %u status %d\n",
@@ -78,6 +80,9 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
artxq->num_fw_queued--;
}
+ flags = skb_cb->flags;
+ vif = skb_cb->vif;
+
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
ath10k_htt_tx_dec_pending(htt);
if (htt->num_pending_tx == 0)
@@ -121,7 +126,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
info->status.is_valid_ack_signal = true;
}
- ieee80211_tx_status(htt->ar->hw, msdu);
+ if (flags & ATH10K_SKB_F_HW_80211_ENCAP)
+ ieee80211_tx_status_8023(htt->ar->hw, vif, msdu);
+ else
+ ieee80211_tx_status(htt->ar->hw, msdu);
+
/* we do not own the msdu anymore */
return 0;
--
2.20.1
^ permalink raw reply related
* [PATCH V6 0/2] mac80211: add 802.11 encapsulation offloading
From: John Crispin @ 2019-06-18 6:28 UTC (permalink / raw)
To: Johannes Berg, Kalle Valo; +Cc: ath10k, linux-wireless, John Crispin
This series picks up prior work from QCA. The patch is currently shipped
inside QSDK as part of the wlan-open package.
The series tries to address all feedback from the V2
-> https://patchwork.kernel.org/patch/9602585/
Changes in V3
* rebase on latest kernel
* various code style clean ups
* give some of the variables and functions more obvious names
* move the code that disables support for non-linear frames to the core
* disable monitor and tkip support
Changes in V4
* disable encap when TKIP is used instead of refusing TKIP
* use a flag inside tx_info instead of an extra element
* move 4addr detection into ieee80211_set_hw_80211_encap()
* ieee80211_tx_dequeue() was dropping out to early
Changes in V5
* implement comments from Johannes
Changes in V6
* the conditional masking out monitor support was inverse
Vasanthakumar Thiagarajan (2):
mac80211: add hw 80211 encapsulation offloading support
ath10k: add tx hw 802.11 encapusaltion offloading suppor
drivers/net/wireless/ath/ath10k/core.c | 11 ++
drivers/net/wireless/ath/ath10k/core.h | 3 +
drivers/net/wireless/ath/ath10k/htt_tx.c | 24 +--
drivers/net/wireless/ath/ath10k/mac.c | 70 +++++++--
drivers/net/wireless/ath/ath10k/txrx.c | 11 +-
include/net/mac80211.h | 25 +++
net/mac80211/cfg.c | 6 +
net/mac80211/debugfs.c | 1 +
net/mac80211/ieee80211_i.h | 10 ++
net/mac80211/iface.c | 84 ++++++++++
net/mac80211/key.c | 7 +
net/mac80211/main.c | 10 +-
net/mac80211/status.c | 79 ++++++++++
net/mac80211/tx.c | 187 ++++++++++++++++++++++-
14 files changed, 495 insertions(+), 33 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH V6 1/2] mac80211: add hw 80211 encapsulation offloading support
From: John Crispin @ 2019-06-18 6:28 UTC (permalink / raw)
To: Johannes Berg, Kalle Valo
Cc: ath10k, linux-wireless, Vasanthakumar Thiagarajan, John Crispin
In-Reply-To: <20190618062807.17158-1-john@phrozen.org>
From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
This patch adds a new transmit path for hardware that supports 802.11
encapsulation offloading. In those cases 802.3a frames get passed
directly to the driver allowing to hardware to handle the encapsulation.
Certain features wont work and the patch masks these out.
* monitor interfaces are not supported if any of the vif is in encap mode.
* amsdu/non-linear frames wont work in encap offloading mode.
* TKIP countermeasures cannot be triggered and hence those keys are not
accepted.
The patch defines a secondary netdev_ops struct that the device is assigned
to the device if 802.11 encap support is available and enabled. The driver
needs to enable the support on a per vif basis if it finds that all
pre-reqs are meet.
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
include/net/mac80211.h | 25 +++++
net/mac80211/cfg.c | 6 ++
net/mac80211/debugfs.c | 1 +
net/mac80211/ieee80211_i.h | 10 ++
net/mac80211/iface.c | 84 +++++++++++++++++
net/mac80211/key.c | 7 ++
net/mac80211/main.c | 10 +-
net/mac80211/status.c | 79 ++++++++++++++++
net/mac80211/tx.c | 187 ++++++++++++++++++++++++++++++++++++-
9 files changed, 401 insertions(+), 8 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1a93ca593c28..426b4f4d9020 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -827,6 +827,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTRL_AMSDU = BIT(3),
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP = BIT(5),
+ IEEE80211_TX_CTRL_HW_80211_ENCAP = BIT(6),
};
/*
@@ -2281,6 +2282,9 @@ struct ieee80211_txq {
* @IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT: The card/driver can't handle
* active Tx A-MPDU sessions with Extended Key IDs during rekey.
*
+ * @IEEE80211_HW_SUPPORTS_80211_ENCAP: Hardware/driver supports 802.11
+ * encap for data frames.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2334,6 +2338,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_EXT_KEY_ID_NATIVE,
IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT,
+ IEEE80211_HW_SUPPORTS_80211_ENCAP,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
@@ -4629,6 +4634,25 @@ static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw,
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct sk_buff *skb);
+/**
+ * ieee80211_tx_status_8023 - transmit status callback for 802.3 frame format
+ *
+ * Call this function for all transmitted data frames after their transmit
+ * completion. This callback should only be called for data frames which
+ * are are using driver's (or hardware's) offload capability of encap/decap
+ * 802.11 frames.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @vif: the interface for which the frame was transmitted
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb);
+
/**
* ieee80211_report_low_ack - report non-responding station
*
@@ -6384,4 +6408,5 @@ void ieee80211_nan_func_match(struct ieee80211_vif *vif,
struct cfg80211_nan_match_params *match,
gfp_t gfp);
+bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable);
#endif /* MAC80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8a6a38d74878..fb2588ec90a1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2424,11 +2424,17 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata;
int err;
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
ieee80211_check_fast_xmit_all(local);
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list)
+ ieee80211_set_hw_80211_encap(&sdata->vif, false);
+ mutex_unlock(&local->iflist_mtx);
+
err = drv_set_frag_threshold(local, wiphy->frag_threshold);
if (err) {
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 7c580010836e..69baf5d381ad 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -275,6 +275,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
FLAG(EXT_KEY_ID_NATIVE),
FLAG(NO_AMPDU_KEYBORDER_SUPPORT),
+ FLAG(SUPPORTS_80211_ENCAP),
#undef FLAG
};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 07da9e49db94..9e8474782a60 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -987,6 +987,8 @@ struct ieee80211_sub_if_data {
} debugfs;
#endif
+ bool hw_80211_encap;
+
/* must be last, dynamically sized area in this! */
struct ieee80211_vif vif;
};
@@ -1733,6 +1735,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct vif_params *params);
int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
enum nl80211_iftype type);
+bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local);
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
void ieee80211_remove_interfaces(struct ieee80211_local *local);
u32 ieee80211_idle_off(struct ieee80211_local *local);
@@ -1760,6 +1763,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct net_device *dev);
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev);
+netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+ struct net_device *dev);
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev,
u32 info_flags,
@@ -1940,6 +1945,11 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid,
enum nl80211_band band, u32 txdata_flags);
+/* sta_out needs to be checked for ERR_PTR() before using */
+int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb,
+ struct sta_info **sta_out);
+
static inline void
ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 410685d38c46..14a7c665afd0 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1176,6 +1176,89 @@ static const struct net_device_ops ieee80211_dataif_ops = {
.ndo_get_stats64 = ieee80211_get_stats64,
};
+static const struct net_device_ops ieee80211_dataif_8023_ops = {
+ .ndo_open = ieee80211_open,
+ .ndo_stop = ieee80211_stop,
+ .ndo_uninit = ieee80211_uninit,
+ .ndo_start_xmit = ieee80211_subif_start_xmit_8023,
+ .ndo_set_rx_mode = ieee80211_set_multicast_list,
+ .ndo_set_mac_address = ieee80211_change_mac,
+ .ndo_select_queue = ieee80211_netdev_select_queue,
+ .ndo_get_stats64 = ieee80211_get_stats64,
+};
+
+bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_key *key;
+
+ sdata_assert_lock(sdata);
+
+ if (!sdata->dev)
+ return 0;
+
+ if (enable == sdata->hw_80211_encap)
+ return enable;
+
+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_80211_ENCAP))
+ enable = 0;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ if (sdata->u.mgd.use_4addr)
+ enable = 0;
+ break;
+ case NL80211_IFTYPE_AP_VLAN:
+ if (sdata->wdev.use_4addr)
+ enable = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
+ (local->hw.wiphy->frag_threshold != (u32)-1))
+ enable = 0;
+
+ mutex_lock(&sdata->local->key_mtx);
+ list_for_each_entry(key, &sdata->key_list, list) {
+ if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
+ enable = 0;
+ }
+ mutex_unlock(&sdata->local->key_mtx);
+
+ if (enable) {
+ sdata->dev->netdev_ops = &ieee80211_dataif_8023_ops;
+ sdata->hw_80211_encap = true;
+ } else {
+ sdata->dev->netdev_ops = &ieee80211_dataif_ops;
+ sdata->hw_80211_encap = false;
+ }
+
+ return enable;
+}
+EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
+
+bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local)
+{
+ struct ieee80211_sub_if_data *sdata;
+ bool offloaded = false;
+ rcu_read_lock();
+
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (sdata->hw_80211_encap) {
+ offloaded = true;
+ break;
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+ rcu_read_unlock();
+
+ return offloaded;
+}
+
static u16 ieee80211_monitor_select_queue(struct net_device *dev,
struct sk_buff *skb,
struct net_device *sb_dev)
@@ -1408,6 +1491,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.idle = true;
sdata->noack_map = 0;
+ sdata->hw_80211_encap = false;
/* only monitor/p2p-device differ */
if (sdata->dev) {
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index faadfeea7127..4c9977770a45 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -179,6 +179,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
}
}
+ /* TKIP countermeasures wont work on encap offload mode */
+ if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
+ ieee80211_set_hw_80211_encap(&sdata->vif, false);
+
ret = drv_set_key(key->local, SET_KEY, sdata,
sta ? &sta->sta : NULL, &key->conf);
@@ -205,6 +209,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
key->conf.keyidx,
sta ? sta->sta.addr : bcast_addr, ret);
+ if (sdata->hw_80211_encap)
+ return -EINVAL;
+
out_unsupported:
switch (key->conf.cipher) {
case WLAN_CIPHER_SUITE_WEP40:
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1f11907dc528..c5096e24d81b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1000,9 +1000,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
}
- /* mac80211 always supports monitor */
- hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
- hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
+ if (ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)) {
+ /* mac80211 always supports monitor unless we do 802.11
+ * encapsulation offloading.
+ */
+ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+ hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
+ }
/* mac80211 doesn't support more than one IBSS interface right now */
for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 5b9952b1caf3..0c8858c01e36 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -1019,6 +1019,85 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_tx_rate_update);
+void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct sta_info *sta;
+ int retry_count;
+ int rates_idx;
+ bool acked;
+
+ if (WARN_ON(!ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)))
+ goto skip_stats_update;
+
+ sdata = vif_to_sdata(vif);
+
+ acked = info->flags & IEEE80211_TX_STAT_ACK;
+ rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+
+ rcu_read_lock();
+
+ if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
+ rcu_read_unlock();
+ goto counters_update;
+ }
+
+ if (!sta || IS_ERR(sta)) {
+ rcu_read_unlock();
+ goto counters_update;
+ }
+
+ if (!acked)
+ sta->status_stats.retry_failed++;
+
+ if (rates_idx != -1)
+ sta->tx_stats.last_rate = info->status.rates[rates_idx];
+
+ sta->status_stats.retry_count += retry_count;
+
+ if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
+ if (acked && vif->type == NL80211_IFTYPE_STATION)
+ ieee80211_sta_reset_conn_monitor(sdata);
+
+ sta->status_stats.last_ack = jiffies;
+ if (info->flags & IEEE80211_TX_STAT_ACK) {
+ if (sta->status_stats.lost_packets)
+ sta->status_stats.lost_packets = 0;
+
+ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
+ sta->status_stats.last_tdls_pkt_time = jiffies;
+ } else {
+ ieee80211_lost_packet(sta, info);
+ }
+ }
+
+ rcu_read_unlock();
+
+counters_update:
+ ieee80211_led_tx(local);
+
+ if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
+ !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
+ goto skip_stats_update;
+
+ I802_DEBUG_INC(local->dot11TransmittedFrameCount);
+ if (is_multicast_ether_addr(skb->data))
+ I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
+ if (retry_count > 0)
+ I802_DEBUG_INC(local->dot11RetryCount);
+ if (retry_count > 1)
+ I802_DEBUG_INC(local->dot11MultipleRetryCount);
+
+skip_stats_update:
+ ieee80211_report_used_skb(local, skb, false);
+ dev_kfree_skb(skb);
+}
+EXPORT_SYMBOL(ieee80211_tx_status_8023);
+
void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index dd220b977025..0d1f525c0b02 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1253,7 +1253,8 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
return NULL;
- if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
+ if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
+ unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
if ((!ieee80211_is_mgmt(hdr->frame_control) ||
ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
vif->type == NL80211_IFTYPE_STATION) &&
@@ -2358,9 +2359,9 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
}
-static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb,
- struct sta_info **sta_out)
+int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb,
+ struct sta_info **sta_out)
{
struct sta_info *sta;
@@ -2870,7 +2871,8 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
struct ieee80211_chanctx_conf *chanctx_conf;
__le16 fc;
- if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
+ if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) ||
+ sdata->hw_80211_encap)
return;
/* Locking here protects both the pointer itself, and against concurrent
@@ -3600,6 +3602,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
else
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+ if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+ goto encap_out;
+
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
struct sta_info *sta = container_of(txq->sta, struct sta_info,
sta);
@@ -3659,6 +3664,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
break;
}
+encap_out:
IEEE80211_SKB_CB(skb)->control.vif = vif;
return skb;
@@ -4030,6 +4036,167 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int led_len,
+ struct sta_info *sta,
+ bool txpending)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_tx_control control = {};
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_sta *pubsta = NULL;
+ unsigned long flags;
+ int q = info->hw_queue;
+
+ if (ieee80211_queue_skb(local, sdata, sta, skb))
+ return true;
+
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+
+ if (local->queue_stop_reasons[q] ||
+ (!txpending && !skb_queue_empty(&local->pending[q]))) {
+ if (txpending)
+ skb_queue_head(&local->pending[q], skb);
+ else
+ skb_queue_tail(&local->pending[q], skb);
+
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
+ return false;
+ }
+
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
+ if (sta && sta->uploaded)
+ pubsta = &sta->sta;
+
+ control.sta = pubsta;
+
+ drv_tx(local, &control, skb);
+
+ return true;
+}
+
+static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
+ struct net_device *dev, struct sta_info *sta,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ethhdr *ehdr = (struct ethhdr *)skb->data;
+ struct ieee80211_local *local = sdata->local;
+ bool authorized = false;
+ bool multicast;
+ bool tdls_peer;
+ unsigned char *ra = NULL;
+
+ if (IS_ERR(sta) || (sta && !sta->uploaded))
+ sta = NULL;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
+ if (tdls_peer)
+ ra = skb->data;
+ else
+ ra = sdata->u.mgd.bssid;
+ } else {
+ ra = ehdr->h_dest;
+ }
+
+ if (!ra)
+ goto out_free;
+ multicast = is_multicast_ether_addr(ra);
+
+ if (sta)
+ authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+
+ if (!multicast && !authorized &&
+ ((ehdr->h_proto != sdata->control_port_protocol) ||
+ !ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
+ goto out_free;
+
+ if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
+ !atomic_read(&sdata->u.ap.num_mcast_sta))
+ goto out_free;
+
+ if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
+ test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
+ goto out_free;
+
+ /* TODO: Handle frames requiring wifi tx status to be notified */
+
+ memset(info, 0, sizeof(*info));
+
+ if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
+ if (sdata->control_port_no_encrypt)
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+ }
+
+ if (multicast)
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
+
+ info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+
+ ieee80211_tx_stats(dev, skb->len);
+
+ if (sta) {
+ sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
+ sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
+ }
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata = container_of(sdata->bss,
+ struct ieee80211_sub_if_data, u.ap);
+
+ info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
+ info->control.vif = &sdata->vif;
+
+ ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
+
+ return;
+
+out_free:
+ kfree_skb(skb);
+}
+
+netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct sta_info *sta;
+
+ if (WARN_ON(!sdata->hw_80211_encap)) {
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (unlikely(skb->len < ETH_HLEN)) {
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (WARN_ON(dev->ieee80211_ptr->use_4addr)) {
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ rcu_read_lock();
+
+ if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
+ goto out_free;
+
+ ieee80211_8023_xmit(sdata, dev, sta, skb);
+
+ goto out;
+
+out_free:
+ kfree_skb(skb);
+out:
+ rcu_read_unlock();
+
+ return NETDEV_TX_OK;
+}
+
struct sk_buff *
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u32 info_flags)
@@ -4108,6 +4275,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
}
info->band = chanctx_conf->def.chan->band;
result = ieee80211_tx(sdata, NULL, skb, true, 0);
+ } else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
+ if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
+ dev_kfree_skb(skb);
+ return true;
+ }
+
+ if (IS_ERR(sta) || (sta && !sta->uploaded))
+ sta = NULL;
+
+ result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true);
} else {
struct sk_buff_head skbs;
--
2.20.1
^ permalink raw reply related
* [PATCH V3 2/2] mac80211: allow setting spatial reuse parameters from bss_conf
From: John Crispin @ 2019-06-18 6:19 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, John Crispin, Shashidhar Lakkavalli
In-Reply-To: <20190618061915.7102-1-john@phrozen.org>
Store the OBSS PD parameters inside bss_conf when bringing up an AP and/or
when a station connects to an AP. This allows the driver to configure the
HW accordingly.
Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
include/net/cfg80211.h | 15 +++++++++++++
include/net/mac80211.h | 4 ++++
include/uapi/linux/nl80211.h | 27 ++++++++++++++++++++++
net/mac80211/cfg.c | 5 ++++-
net/mac80211/he.c | 24 ++++++++++++++++++++
net/mac80211/ieee80211_i.h | 3 +++
net/mac80211/mlme.c | 1 +
net/wireless/nl80211.c | 43 ++++++++++++++++++++++++++++++++++++
8 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2d17e32eb438..49de2c69e63f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -249,6 +249,19 @@ struct ieee80211_rate {
u16 hw_value, hw_value_short;
};
+/**
+ * struct ieee80211_he_obss_pd - AP settings for spatial reuse
+ *
+ * @enable: is the feature enabled.
+ * @min_offset: minimal tx power offset an associated station shall use
+ * @max_offset: maximum tx power offset an associated station shall use
+ */
+struct ieee80211_he_obss_pd {
+ bool enable;
+ u32 min_offset;
+ u32 max_offset;
+};
+
/**
* struct ieee80211_sta_ht_cap - STA's HT capabilities
*
@@ -899,6 +912,7 @@ enum cfg80211_ap_settings_flags {
* @vht_required: stations must support VHT
* @twt_responder: Enable Target Wait Time
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
+ * @he_obss_pd: OBSS Packet Detection settings
*/
struct cfg80211_ap_settings {
struct cfg80211_chan_def chandef;
@@ -926,6 +940,7 @@ struct cfg80211_ap_settings {
bool ht_required, vht_required;
bool twt_responder;
u32 flags;
+ struct ieee80211_he_obss_pd he_obss_pd;
};
/**
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4411120e5a9a..1a93ca593c28 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -318,6 +318,7 @@ struct ieee80211_vif_chanctx_switch {
* @BSS_CHANGED_FTM_RESPONDER: fime timing reasurement request responder
* functionality changed for this BSS (AP mode).
* @BSS_CHANGED_TWT: TWT status changed
+ * @BSS_CHANGED_HE_OBSS_PD: OBSS Packet Detection status changed.
*
*/
enum ieee80211_bss_change {
@@ -349,6 +350,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_MCAST_RATE = 1<<25,
BSS_CHANGED_FTM_RESPONDER = 1<<26,
BSS_CHANGED_TWT = 1<<27,
+ BSS_CHANGED_HE_OBSS_PD = 1<<28,
/* when adding here, make sure to change ieee80211_reconfig */
};
@@ -603,6 +605,7 @@ struct ieee80211_ftm_responder_params {
* nontransmitted BSSIDs
* @profile_periodicity: the least number of beacon frames need to be received
* in order to discover all the nontransmitted BSSIDs in the set.
+ * @he_obss_pd: OBSS Packet Detection parameters.
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -664,6 +667,7 @@ struct ieee80211_bss_conf {
u8 bssid_indicator;
bool ema_ap;
u8 profile_periodicity;
+ struct ieee80211_he_obss_pd he_obss_pd;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8fc3a43cac75..68ee35cbd75e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2356,6 +2356,9 @@ enum nl80211_commands {
*
* @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support.
*
+ * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection
+ * functionality.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2813,6 +2816,8 @@ enum nl80211_attrs {
NL80211_ATTR_TWT_RESPONDER,
+ NL80211_ATTR_HE_OBSS_PD,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -6488,4 +6493,26 @@ enum nl80211_peer_measurement_ftm_resp {
NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1
};
+/**
+ * enum nl80211_he_spr - spatial reuse attributes
+ * @__NL80211_HE_OBSS_PD_ATTR_INVALID: Invalid
+ *
+ * @NL80211_ATTR_HE_OBSS_PD_MIN_OFFSET: the OBSS PD minimum tx power offset.
+ * @NL80211_ATTR_HE_OBSS_PD_MAX_OFFSET: the OBSS PD maximum tx power offset.
+ *
+ * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal
+ * @NL80211_HE_OBSS_PD_ATTR_MAX: highest spiatl reuse attribute.
+ */
+enum nl80211_he_spr_attributes {
+ __NL80211_HE_OBSS_PD_ATTR_INVALID,
+
+ NL80211_ATTR_HE_OBSS_PD_MIN_OFFSET,
+ NL80211_ATTR_HE_OBSS_PD_MAX_OFFSET,
+
+ /* keep last */
+ __NL80211_ATTR_HE_OBSS_PD_LAST,
+ NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_ATTR_HE_OBSS_PD_LAST - 1,
+};
+
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fcf1dfc3a1cc..8a6a38d74878 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -976,7 +976,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
BSS_CHANGED_SSID |
BSS_CHANGED_P2P_PS |
BSS_CHANGED_TXPOWER |
- BSS_CHANGED_TWT;
+ BSS_CHANGED_TWT |
+ BSS_CHANGED_HE_OBSS_PD;
int err;
int prev_beacon_int;
@@ -1047,6 +1048,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.enable_beacon = true;
sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
sdata->vif.bss_conf.twt_responder = params->twt_responder;
+ memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd,
+ sizeof(struct ieee80211_he_obss_pd));
sdata->vif.bss_conf.ssid_len = params->ssid_len;
if (params->ssid_len)
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index 769078ed5a12..5bb99bd3400c 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -53,3 +53,27 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
he_cap->has_he = true;
}
+
+void
+ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
+ const struct ieee80211_he_spr *he_spr_ie_elem)
+{
+ struct ieee80211_he_obss_pd *he_obss_pd =
+ &vif->bss_conf.he_obss_pd;
+ const u8 *data = he_spr_ie_elem->optional;
+
+ memset(he_obss_pd, 0, sizeof(*he_obss_pd));
+
+ if (!he_spr_ie_elem)
+ return;
+
+ if (he_spr_ie_elem->he_sr_control &
+ IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
+ data++;
+ if (he_spr_ie_elem->he_sr_control &
+ IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) {
+ he_obss_pd->max_offset = *data++;
+ he_obss_pd->min_offset = *data++;
+ he_obss_pd->enable = true;
+ }
+}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0ee5d82e6734..07da9e49db94 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1873,6 +1873,9 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband,
const u8 *he_cap_ie, u8 he_cap_len,
struct sta_info *sta);
+void
+ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
+ const struct ieee80211_he_spr *he_spr_ie_elem);
/* Spectrum management */
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b971b02d0d60..c5fee29ce03c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3373,6 +3373,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
if (elems.uora_element)
bss_conf->uora_ocw_range = elems.uora_element[0];
+ ieee80211_he_spr_ie_to_bss_conf(&sdata->vif, elems.he_spr);
/* TODO: OPEN: what happens if BSS color disable is set? */
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ff760ba83449..166bc66173f6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -574,6 +574,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
.len = SAE_PASSWORD_MAX_LEN },
[NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
+ [NL80211_ATTR_HE_OBSS_PD] = { .type = NLA_NESTED },
};
/* policy for the key attributes */
@@ -4348,6 +4349,40 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
return 0;
}
+static const struct nla_policy
+ he_spr_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
+ [NL80211_ATTR_HE_OBSS_PD_MIN_OFFSET] = { .type = NLA_U32 },
+ [NL80211_ATTR_HE_OBSS_PD_MAX_OFFSET] = { .type = NLA_U32 },
+};
+
+static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
+ struct ieee80211_he_obss_pd *he_obss_pd)
+{
+ struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
+ int err;
+
+ err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
+ he_spr_policy, NULL);
+ if (err)
+ return err;
+
+ if (!tb[NL80211_ATTR_HE_OBSS_PD_MIN_OFFSET] ||
+ !tb[NL80211_ATTR_HE_OBSS_PD_MAX_OFFSET])
+ return -EINVAL;
+
+ he_obss_pd->min_offset =
+ nla_get_u32(tb[NL80211_ATTR_HE_OBSS_PD_MIN_OFFSET]);
+ he_obss_pd->max_offset =
+ nla_get_u32(tb[NL80211_ATTR_HE_OBSS_PD_MAX_OFFSET]);
+
+ if (he_obss_pd->min_offset >= he_obss_pd->max_offset)
+ return -EINVAL;
+
+ he_obss_pd->enable = true;
+
+ return 0;
+}
+
static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
const u8 *rates)
{
@@ -4632,6 +4667,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.twt_responder =
nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
+ if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
+ err = nl80211_parse_he_obss_pd(
+ info->attrs[NL80211_ATTR_HE_OBSS_PD],
+ ¶ms.he_obss_pd);
+ if (err)
+ return err;
+ }
+
nl80211_calculate_ap_params(¶ms);
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
--
2.20.1
^ permalink raw reply related
* [PATCH V3 1/2] mac80211: HE: add Spatial Reuse IE parsing support
From: John Crispin @ 2019-06-18 6:19 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, John Crispin, Shashidhar Lakkavalli
In-Reply-To: <20190618061915.7102-1-john@phrozen.org>
Add support to mac80211 for parsing SPR IEs as per
P802.11ax_D4.0 section 9.4.2.241.
Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
include/linux/ieee80211.h | 49 ++++++++++++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/util.c | 4 ++++
3 files changed, 54 insertions(+)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 2dbefeffc43c..538d502902c0 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1628,6 +1628,18 @@ struct ieee80211_he_operation {
u8 optional[0];
} __packed;
+/**
+ * struct ieee80211_he_spr - HE spatial reuse element
+ *
+ * This structure is the "HE spatial reuse element" element as
+ * described in P802.11ax_D4.0 section 9.4.2.241
+ */
+struct ieee80211_he_spr {
+ u8 he_sr_control;
+ /* Optional 0 to 19 bytes: depends on @he_sr_control */
+ u8 optional[0];
+} __packed;
+
/**
* struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field
*
@@ -2066,6 +2078,42 @@ ieee80211_he_oper_size(const u8 *he_oper_ie)
return oper_len;
}
+/* HE Spatial Reuse defines */
+#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT 0x4
+#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT 0x8
+
+/*
+ * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size
+ * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the the byte
+ * after the ext ID byte. It is assumed that he_spr_ie has at least
+ * sizeof(struct ieee80211_he_spr) bytes, the caller must have validated
+ * this
+ * @return the actual size of the IE data (not including header), or 0 on error
+ */
+static inline u8
+ieee80211_he_spr_size(const u8 *he_spr_ie)
+{
+ struct ieee80211_he_spr *he_spr = (void *)he_spr_ie;
+ u8 spr_len = sizeof(struct ieee80211_he_spr);
+ u32 he_spr_params;
+
+ /* Make sure the input is not NULL */
+ if (!he_spr_ie)
+ return 0;
+
+ /* Calc required length */
+ he_spr_params = le32_to_cpu(he_spr->he_sr_control);
+ if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
+ spr_len++;
+ if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)
+ spr_len += 18;
+
+ /* Add the first byte (extension ID) to the total length */
+ spr_len++;
+
+ return spr_len;
+}
+
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
@@ -2488,6 +2536,7 @@ enum ieee80211_eid_ext {
WLAN_EID_EXT_HE_OPERATION = 36,
WLAN_EID_EXT_UORA = 37,
WLAN_EID_EXT_HE_MU_EDCA = 38,
+ WLAN_EID_EXT_HE_SPR = 39,
WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52,
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
WLAN_EID_EXT_NON_INHERITANCE = 56,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 073a8235ae1b..0ee5d82e6734 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1483,6 +1483,7 @@ struct ieee802_11_elems {
const struct ieee80211_meshconf_ie *mesh_config;
const u8 *he_cap;
const struct ieee80211_he_operation *he_operation;
+ const struct ieee80211_he_spr *he_spr;
const struct ieee80211_mu_edca_param_set *mu_edca_param_set;
const u8 *uora_element;
const u8 *mesh_id;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index cba4633cd6cf..34ce0ed67e59 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1236,6 +1236,10 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
elen == 3) {
elems->mbssid_config_ie = (void *)&pos[1];
+ } else if (pos[0] == WLAN_EID_EXT_HE_SPR &&
+ elen >= sizeof(*elems->he_spr) &&
+ elen >= ieee80211_he_spr_size(&pos[1])) {
+ elems->he_spr = (void *)&pos[1];
}
break;
default:
--
2.20.1
^ permalink raw reply related
* [PATCH V3 0/2] mac80211: HE: add SPR/OBSSPD support
From: John Crispin @ 2019-06-18 6:19 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, John Crispin
This series adds support for propagating the OBSS PD information from
assocs to a wireless driver.
Changes in V2
* always use bss_conf as per request from Johannes
Changes in V3
* remove reference to mac80211 inside comment
John Crispin (2):
mac80211: HE: add Spatial Reuse IE parsing support
mac80211: allow setting spatial reuse parameters from bss_conf
include/linux/ieee80211.h | 49 ++++++++++++++++++++++++++++++++++++
include/net/cfg80211.h | 15 +++++++++++
include/net/mac80211.h | 4 +++
include/uapi/linux/nl80211.h | 27 ++++++++++++++++++++
net/mac80211/cfg.c | 5 +++-
net/mac80211/he.c | 24 ++++++++++++++++++
net/mac80211/ieee80211_i.h | 4 +++
net/mac80211/mlme.c | 1 +
net/mac80211/util.c | 4 +++
net/wireless/nl80211.c | 43 +++++++++++++++++++++++++++++++
10 files changed, 175 insertions(+), 1 deletion(-)
--
2.20.1
^ permalink raw reply
* RE: [PATCH] ath10k: add mic bytes for pmf management packet
From: Wen Gong @ 2019-06-18 7:21 UTC (permalink / raw)
To: Ben Greear, Wen Gong, ath10k@lists.infradead.org
Cc: linux-wireless@vger.kernel.org
In-Reply-To: <136d04d4-671b-8dde-2abd-63070b07bd26@candelatech.com>
> -----Original Message-----
> From: ath10k <ath10k-bounces@lists.infradead.org> On Behalf Of Ben
> Greear
> Sent: Tuesday, June 18, 2019 12:04 AM
> To: Wen Gong <wgong@codeaurora.org>; ath10k@lists.infradead.org
> Cc: linux-wireless@vger.kernel.org
> Subject: [EXT] Re: [PATCH] ath10k: add mic bytes for pmf management
> packet
>
> I was looking at mac80211 code recently, and it seems some action
> frames are NOT supposed to be protected. I added my own helper
> method to my local ath10k. Maybe you want to use this?
>
>
> /* Copied from ieee80211_is_robust_mgmt_frame, but disable the check for
> has_protected
> * since we do tx hw crypt, and it won't actually be encrypted even when this
> flag is
> * set.
> */
> bool ieee80211_is_robust_mgmt_frame_tx(struct ieee80211_hdr *hdr)
> {
> if (ieee80211_is_disassoc(hdr->frame_control) ||
> ieee80211_is_deauth(hdr->frame_control))
> return true;
>
> if (ieee80211_is_action(hdr->frame_control)) {
> u8 *category;
>
> /*
> * Action frames, excluding Public Action frames, are Robust
> * Management Frames. However, if we are looking at a Protected
> * frame, skip the check since the data may be encrypted and
> * the frame has already been found to be a Robust Management
> * Frame (by the other end).
> */
> /*
> if (ieee80211_has_protected(hdr->frame_control))
> return true;
> */
> category = ((u8 *) hdr) + 24;
> return *category != WLAN_CATEGORY_PUBLIC &&
> *category != WLAN_CATEGORY_HT &&
> *category != WLAN_CATEGORY_WNM_UNPROTECTED &&
> *category != WLAN_CATEGORY_SELF_PROTECTED &&
> *category != WLAN_CATEGORY_UNPROT_DMG &&
> *category != WLAN_CATEGORY_VHT &&
> *category != WLAN_CATEGORY_VENDOR_SPECIFIC;
> }
>
> return false;
> }
>
> Thanks,
> Ben
>
> > +
> > data_len = msdu->len;
> >
> > switch (txmode) {
> >
>
>
Thanks Ben,
seems the ieee80211_is_robust_mgmt_frame_tx is not
match my change.
^ permalink raw reply
* Re: wpa_supplicant 2.8 fails in brcmf_cfg80211_set_pmk
From: Arend Van Spriel @ 2019-06-18 8:27 UTC (permalink / raw)
To: Chi-Hsien Lin, Marcel Holtmann
Cc: Stefan Wahren, Stanley Hsu, Franky Lin, Hante Meuleman,
Wright Feng, linux-wireless@vger.kernel.org,
brcm80211-dev-list.pdl@broadcom.com, brcm80211-dev-list,
Jouni Malinen
In-Reply-To: <d6bfe313-3aa7-82bb-dfac-25e6261dbf63@cypress.com>
+ Jouni
On 6/18/2019 7:33 AM, Chi-Hsien Lin wrote:
>
>
> On 06/17/2019 10:33, Marcel Holtmann wrote:
>> Hi Chi-hsien,
>>
>>>>> i was able to reproduce an (maybe older issue) with 4-way handshake
>>>>> offloading for 802.1X in the brcmfmac driver. My setup consists of
>>>>> Raspberry Pi 3 B (current linux-next, arm64/defconfig) on STA side and a
>>>>> Raspberry Pi 3 A+ (Linux 4.19) on AP side.
>>>>
>>>> Looks like Raspberry Pi isn't the only affected platform [3], [4].
>>>>
>>>> [3] - https://bugzilla.redhat.com/show_bug.cgi?id=1665608
>>>> [4] - https://bugzilla.kernel.org/show_bug.cgi?id=202521
>>>
>>> Stefan,
>>>
>>> Could you please try the attached patch for your wpa_supplicant? We'll
>>> upstream if it works for you.
>>
>> I hope that someone is also providing a kernel patch to fix the issue. Hacking around a kernel issue in userspace is not enough. Fix the root cause in the kernel.
>
> Marcel,
>
> This is a kernel warning for invalid application PMK set actions, so the
> fix is to only set PMK to wifi driver when 4-way is offloaded. I think
> Arend added the WARN_ON() intentionally to catch application misuse of
> PMK setting.
>
> You may also remove the warnings with the attached patch, but let's see
> what Arend says first.
>
>
> Arend,
>
> Any comment?
Hi Chi-Hsien, Marcel
From the kernel side I do not see an issue. In order to use 802.1X
offload the NL80211_ATTR_WANT_1X_4WAY_HS flag must be set in
NL80211_CMD_CONNECT. Otherwise, NL80211_CMD_SET_PMK is not accepted. The
only improvement would be to document this more clearly in the "WPA/WPA2
EAPOL handshake offload" DOC section in nl80211.h.
As for the wpa_supplicant behavior it seemed a good idea to reuse the
req_key_mgmt_offload parameter at the time, but it seems to bite each
other. Maybe it is better to have a separate flag like
'req_handshake_offload'. Jouni, any thoughts on this?
Regards,
Arend
^ permalink raw reply
* Re: [PATCH] rt2x00: fix rx queue hang
From: Stanislaw Gruszka @ 2019-06-18 9:34 UTC (permalink / raw)
To: Soeren Moch
Cc: Helmut Schaa, Kalle Valo, David S. Miller, linux-wireless, netdev,
linux-kernel, stable
In-Reply-To: <20190617094656.3952-1-smoch@web.de>
Hi
On Mon, Jun 17, 2019 at 11:46:56AM +0200, Soeren Moch wrote:
> Since commit ed194d136769 ("usb: core: remove local_irq_save() around
> ->complete() handler") the handlers rt2x00usb_interrupt_rxdone() and
> rt2x00usb_interrupt_txdone() are not running with interrupts disabled
> anymore. So these handlers are not guaranteed to run completely before
> workqueue processing starts. So only mark entries ready for workqueue
> processing after proper accounting in the dma done queue.
It was always the case on SMP machines that rt2x00usb_interrupt_{tx/rx}done
can run concurrently with rt2x00_work_{rx,tx}done, so I do not
understand how removing local_irq_save() around complete handler broke
things.
Have you reverted commit ed194d136769 and the revert does solve the problem ?
Between 4.19 and 4.20 we have some quite big changes in rt2x00 driver:
0240564430c0 rt2800: flush and txstatus rework for rt2800mmio
adf26a356f13 rt2x00: use different txstatus timeouts when flushing
5022efb50f62 rt2x00: do not check for txstatus timeout every time on tasklet
0b0d556e0ebb rt2800mmio: use txdone/txstatus routines from lib
5c656c71b1bf rt2800: move usb specific txdone/txstatus routines to rt2800lib
so I'm a bit afraid that one of those changes is real cause of
the issue not ed194d136769 .
> Note that rt2x00usb_work_rxdone() processes all available entries, not
> only such for which queue_work() was called.
>
> This fixes a regression on a RT5370 based wifi stick in AP mode, which
> suddenly stopped data transmission after some period of heavy load. Also
> stopping the hanging hostapd resulted in the error message "ieee80211
> phy0: rt2x00queue_flush_queue: Warning - Queue 14 failed to flush".
> Other operation modes are probably affected as well, this just was
> the used testcase.
Do you know what actually make the traffic stop,
TX queue hung or RX queue hung?
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> index 1b08b01db27b..9c102a501ee6 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> @@ -263,9 +263,9 @@ EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
>
> void rt2x00lib_dmadone(struct queue_entry *entry)
> {
> - set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
> clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
> rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
> + set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
Unfortunately I do not understand how this suppose to fix the problem,
could you elaborate more about this change?
Stanislaw
^ permalink raw reply
* [PATCH] mt76: fix sparse warnings: warning: dubious: x & !y
From: Lorenzo Bianconi @ 2019-06-18 10:02 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Fix following sparse warnings in mt7603/mac.c and mt76x02_mac.c
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c:113:17: warning: dubious: x & !y
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c:145:16: warning: dubious: x & !y
drivers/net/wireless/mediatek/mt76/mt7603/mac.c:730:9: warning: dubious: x & !y
drivers/net/wireless/mediatek/mt76/mt7603/mac.c:790:15: warning: dubious: x & !y
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 6 ++++--
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 7 +++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index ab5141701997..62e0a7f4716a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -709,6 +709,7 @@ int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
{
enum mt7603_cipher_type cipher;
u32 addr = mt7603_wtbl3_addr(wcid);
+ bool key_set = !!key;
u8 key_data[32];
int key_len = sizeof(key_data);
@@ -727,7 +728,7 @@ int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher);
if (key)
mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx);
- mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key);
+ mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, key_set);
return 0;
}
@@ -745,6 +746,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
struct ieee80211_vif *vif = info->control.vif;
struct mt76_queue *q = dev->mt76.q_tx[qid].q;
struct mt7603_vif *mvif;
+ bool key_set = !!key;
int wlan_idx;
int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
int tx_count = 8;
@@ -787,7 +789,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
FIELD_PREP(MT_TXD1_HDR_INFO, hdr_len / 2) |
FIELD_PREP(MT_TXD1_WLAN_IDX, wlan_idx) |
- FIELD_PREP(MT_TXD1_PROTECTED, !!key);
+ FIELD_PREP(MT_TXD1_PROTECTED, key_set);
txwi[1] = cpu_to_le32(val);
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 97621dbfd114..b3a35911deb1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -110,8 +110,10 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx,
memset(iv_data, 0, sizeof(iv_data));
if (key) {
+ bool pw_key = !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
+
mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE,
- !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
+ pw_key);
pn = atomic64_read(&key->tx_pn);
@@ -139,10 +141,11 @@ void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx,
u8 vif_idx, u8 *mac)
{
struct mt76_wcid_addr addr = {};
+ bool ext_id = !!(vif_idx & 8);
u32 attr;
attr = FIELD_PREP(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) |
- FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8));
+ FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, ext_id);
mt76_wr(dev, MT_WCID_ATTR(idx), attr);
--
2.21.0
^ permalink raw reply related
* Re: [PATCH V6 1/2] mac80211: add hw 80211 encapsulation offloading support
From: John Crispin @ 2019-06-18 10:07 UTC (permalink / raw)
To: Johannes Berg, Kalle Valo
Cc: ath10k, linux-wireless, Vasanthakumar Thiagarajan
In-Reply-To: <20190618062807.17158-2-john@phrozen.org>
Hi,
had a couple mails regarding this series and will change it so that when
a iface gets brought up it will check if there is already a monitor
interface and then not enable encap and when we bring up a monitor
interface, mak eit disable encap on all existing ifaces. That way we do
not loose the monitor feature. V7 coming shortly.
John
On 18/06/2019 08:28, John Crispin wrote:
> From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
>
> This patch adds a new transmit path for hardware that supports 802.11
> encapsulation offloading. In those cases 802.3a frames get passed
> directly to the driver allowing to hardware to handle the encapsulation.
>
> Certain features wont work and the patch masks these out.
> * monitor interfaces are not supported if any of the vif is in encap mode.
> * amsdu/non-linear frames wont work in encap offloading mode.
> * TKIP countermeasures cannot be triggered and hence those keys are not
> accepted.
>
> The patch defines a secondary netdev_ops struct that the device is assigned
> to the device if 802.11 encap support is available and enabled. The driver
> needs to enable the support on a per vif basis if it finds that all
> pre-reqs are meet.
>
> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
> Signed-off-by: John Crispin <john@phrozen.org>
> ---
> include/net/mac80211.h | 25 +++++
> net/mac80211/cfg.c | 6 ++
> net/mac80211/debugfs.c | 1 +
> net/mac80211/ieee80211_i.h | 10 ++
> net/mac80211/iface.c | 84 +++++++++++++++++
> net/mac80211/key.c | 7 ++
> net/mac80211/main.c | 10 +-
> net/mac80211/status.c | 79 ++++++++++++++++
> net/mac80211/tx.c | 187 ++++++++++++++++++++++++++++++++++++-
> 9 files changed, 401 insertions(+), 8 deletions(-)
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index 1a93ca593c28..426b4f4d9020 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -827,6 +827,7 @@ enum mac80211_tx_control_flags {
> IEEE80211_TX_CTRL_AMSDU = BIT(3),
> IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
> IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP = BIT(5),
> + IEEE80211_TX_CTRL_HW_80211_ENCAP = BIT(6),
> };
>
> /*
> @@ -2281,6 +2282,9 @@ struct ieee80211_txq {
> * @IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT: The card/driver can't handle
> * active Tx A-MPDU sessions with Extended Key IDs during rekey.
> *
> + * @IEEE80211_HW_SUPPORTS_80211_ENCAP: Hardware/driver supports 802.11
> + * encap for data frames.
> + *
> * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
> */
> enum ieee80211_hw_flags {
> @@ -2334,6 +2338,7 @@ enum ieee80211_hw_flags {
> IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
> IEEE80211_HW_EXT_KEY_ID_NATIVE,
> IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT,
> + IEEE80211_HW_SUPPORTS_80211_ENCAP,
>
> /* keep last, obviously */
> NUM_IEEE80211_HW_FLAGS
> @@ -4629,6 +4634,25 @@ static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw,
> void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
> struct sk_buff *skb);
>
> +/**
> + * ieee80211_tx_status_8023 - transmit status callback for 802.3 frame format
> + *
> + * Call this function for all transmitted data frames after their transmit
> + * completion. This callback should only be called for data frames which
> + * are are using driver's (or hardware's) offload capability of encap/decap
> + * 802.11 frames.
> + *
> + * This function may not be called in IRQ context. Calls to this function
> + * for a single hardware must be synchronized against each other.
> + *
> + * @hw: the hardware the frame was transmitted by
> + * @vif: the interface for which the frame was transmitted
> + * @skb: the frame that was transmitted, owned by mac80211 after this call
> + */
> +void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif,
> + struct sk_buff *skb);
> +
> /**
> * ieee80211_report_low_ack - report non-responding station
> *
> @@ -6384,4 +6408,5 @@ void ieee80211_nan_func_match(struct ieee80211_vif *vif,
> struct cfg80211_nan_match_params *match,
> gfp_t gfp);
>
> +bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable);
> #endif /* MAC80211_H */
> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index 8a6a38d74878..fb2588ec90a1 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -2424,11 +2424,17 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
> static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
> {
> struct ieee80211_local *local = wiphy_priv(wiphy);
> + struct ieee80211_sub_if_data *sdata;
> int err;
>
> if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
> ieee80211_check_fast_xmit_all(local);
>
> + mutex_lock(&local->iflist_mtx);
> + list_for_each_entry(sdata, &local->interfaces, list)
> + ieee80211_set_hw_80211_encap(&sdata->vif, false);
> + mutex_unlock(&local->iflist_mtx);
> +
> err = drv_set_frag_threshold(local, wiphy->frag_threshold);
>
> if (err) {
> diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
> index 7c580010836e..69baf5d381ad 100644
> --- a/net/mac80211/debugfs.c
> +++ b/net/mac80211/debugfs.c
> @@ -275,6 +275,7 @@ static const char *hw_flag_names[] = {
> FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
> FLAG(EXT_KEY_ID_NATIVE),
> FLAG(NO_AMPDU_KEYBORDER_SUPPORT),
> + FLAG(SUPPORTS_80211_ENCAP),
> #undef FLAG
> };
>
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 07da9e49db94..9e8474782a60 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -987,6 +987,8 @@ struct ieee80211_sub_if_data {
> } debugfs;
> #endif
>
> + bool hw_80211_encap;
> +
> /* must be last, dynamically sized area in this! */
> struct ieee80211_vif vif;
> };
> @@ -1733,6 +1735,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
> struct vif_params *params);
> int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
> enum nl80211_iftype type);
> +bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local);
> void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
> void ieee80211_remove_interfaces(struct ieee80211_local *local);
> u32 ieee80211_idle_off(struct ieee80211_local *local);
> @@ -1760,6 +1763,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
> struct net_device *dev);
> netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
> struct net_device *dev);
> +netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
> + struct net_device *dev);
> void __ieee80211_subif_start_xmit(struct sk_buff *skb,
> struct net_device *dev,
> u32 info_flags,
> @@ -1940,6 +1945,11 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
> struct sk_buff *skb, int tid,
> enum nl80211_band band, u32 txdata_flags);
>
> +/* sta_out needs to be checked for ERR_PTR() before using */
> +int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
> + struct sk_buff *skb,
> + struct sta_info **sta_out);
> +
> static inline void
> ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
> struct sk_buff *skb, int tid,
> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> index 410685d38c46..14a7c665afd0 100644
> --- a/net/mac80211/iface.c
> +++ b/net/mac80211/iface.c
> @@ -1176,6 +1176,89 @@ static const struct net_device_ops ieee80211_dataif_ops = {
> .ndo_get_stats64 = ieee80211_get_stats64,
> };
>
> +static const struct net_device_ops ieee80211_dataif_8023_ops = {
> + .ndo_open = ieee80211_open,
> + .ndo_stop = ieee80211_stop,
> + .ndo_uninit = ieee80211_uninit,
> + .ndo_start_xmit = ieee80211_subif_start_xmit_8023,
> + .ndo_set_rx_mode = ieee80211_set_multicast_list,
> + .ndo_set_mac_address = ieee80211_change_mac,
> + .ndo_select_queue = ieee80211_netdev_select_queue,
> + .ndo_get_stats64 = ieee80211_get_stats64,
> +};
> +
> +bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
> +{
> + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> + struct ieee80211_local *local = sdata->local;
> + struct ieee80211_key *key;
> +
> + sdata_assert_lock(sdata);
> +
> + if (!sdata->dev)
> + return 0;
> +
> + if (enable == sdata->hw_80211_encap)
> + return enable;
> +
> + if (!ieee80211_hw_check(&local->hw, SUPPORTS_80211_ENCAP))
> + enable = 0;
> +
> + switch (vif->type) {
> + case NL80211_IFTYPE_STATION:
> + if (sdata->u.mgd.use_4addr)
> + enable = 0;
> + break;
> + case NL80211_IFTYPE_AP_VLAN:
> + if (sdata->wdev.use_4addr)
> + enable = 0;
> + break;
> + default:
> + break;
> + }
> +
> + if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
> + (local->hw.wiphy->frag_threshold != (u32)-1))
> + enable = 0;
> +
> + mutex_lock(&sdata->local->key_mtx);
> + list_for_each_entry(key, &sdata->key_list, list) {
> + if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
> + enable = 0;
> + }
> + mutex_unlock(&sdata->local->key_mtx);
> +
> + if (enable) {
> + sdata->dev->netdev_ops = &ieee80211_dataif_8023_ops;
> + sdata->hw_80211_encap = true;
> + } else {
> + sdata->dev->netdev_ops = &ieee80211_dataif_ops;
> + sdata->hw_80211_encap = false;
> + }
> +
> + return enable;
> +}
> +EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
> +
> +bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local)
> +{
> + struct ieee80211_sub_if_data *sdata;
> + bool offloaded = false;
> + rcu_read_lock();
> +
> + mutex_lock(&local->iflist_mtx);
> + list_for_each_entry_rcu(sdata, &local->interfaces, list) {
> + if (sdata->hw_80211_encap) {
> + offloaded = true;
> + break;
> + }
> + }
> + mutex_unlock(&local->iflist_mtx);
> + rcu_read_unlock();
> +
> + return offloaded;
> +}
> +
> static u16 ieee80211_monitor_select_queue(struct net_device *dev,
> struct sk_buff *skb,
> struct net_device *sb_dev)
> @@ -1408,6 +1491,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
> sdata->vif.bss_conf.idle = true;
>
> sdata->noack_map = 0;
> + sdata->hw_80211_encap = false;
>
> /* only monitor/p2p-device differ */
> if (sdata->dev) {
> diff --git a/net/mac80211/key.c b/net/mac80211/key.c
> index faadfeea7127..4c9977770a45 100644
> --- a/net/mac80211/key.c
> +++ b/net/mac80211/key.c
> @@ -179,6 +179,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
> }
> }
>
> + /* TKIP countermeasures wont work on encap offload mode */
> + if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
> + ieee80211_set_hw_80211_encap(&sdata->vif, false);
> +
> ret = drv_set_key(key->local, SET_KEY, sdata,
> sta ? &sta->sta : NULL, &key->conf);
>
> @@ -205,6 +209,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
> key->conf.keyidx,
> sta ? sta->sta.addr : bcast_addr, ret);
>
> + if (sdata->hw_80211_encap)
> + return -EINVAL;
> +
> out_unsupported:
> switch (key->conf.cipher) {
> case WLAN_CIPHER_SUITE_WEP40:
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 1f11907dc528..c5096e24d81b 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -1000,9 +1000,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
> hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
> }
>
> - /* mac80211 always supports monitor */
> - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
> - hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
> + if (ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)) {
> + /* mac80211 always supports monitor unless we do 802.11
> + * encapsulation offloading.
> + */
> + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
> + hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
> + }
>
> /* mac80211 doesn't support more than one IBSS interface right now */
> for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
> diff --git a/net/mac80211/status.c b/net/mac80211/status.c
> index 5b9952b1caf3..0c8858c01e36 100644
> --- a/net/mac80211/status.c
> +++ b/net/mac80211/status.c
> @@ -1019,6 +1019,85 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
> }
> EXPORT_SYMBOL(ieee80211_tx_rate_update);
>
> +void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif,
> + struct sk_buff *skb)
> +{
> + struct ieee80211_local *local = hw_to_local(hw);
> + struct ieee80211_sub_if_data *sdata;
> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> + struct sta_info *sta;
> + int retry_count;
> + int rates_idx;
> + bool acked;
> +
> + if (WARN_ON(!ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)))
> + goto skip_stats_update;
> +
> + sdata = vif_to_sdata(vif);
> +
> + acked = info->flags & IEEE80211_TX_STAT_ACK;
> + rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
> +
> + rcu_read_lock();
> +
> + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
> + rcu_read_unlock();
> + goto counters_update;
> + }
> +
> + if (!sta || IS_ERR(sta)) {
> + rcu_read_unlock();
> + goto counters_update;
> + }
> +
> + if (!acked)
> + sta->status_stats.retry_failed++;
> +
> + if (rates_idx != -1)
> + sta->tx_stats.last_rate = info->status.rates[rates_idx];
> +
> + sta->status_stats.retry_count += retry_count;
> +
> + if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
> + if (acked && vif->type == NL80211_IFTYPE_STATION)
> + ieee80211_sta_reset_conn_monitor(sdata);
> +
> + sta->status_stats.last_ack = jiffies;
> + if (info->flags & IEEE80211_TX_STAT_ACK) {
> + if (sta->status_stats.lost_packets)
> + sta->status_stats.lost_packets = 0;
> +
> + if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
> + sta->status_stats.last_tdls_pkt_time = jiffies;
> + } else {
> + ieee80211_lost_packet(sta, info);
> + }
> + }
> +
> + rcu_read_unlock();
> +
> +counters_update:
> + ieee80211_led_tx(local);
> +
> + if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
> + !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
> + goto skip_stats_update;
> +
> + I802_DEBUG_INC(local->dot11TransmittedFrameCount);
> + if (is_multicast_ether_addr(skb->data))
> + I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
> + if (retry_count > 0)
> + I802_DEBUG_INC(local->dot11RetryCount);
> + if (retry_count > 1)
> + I802_DEBUG_INC(local->dot11MultipleRetryCount);
> +
> +skip_stats_update:
> + ieee80211_report_used_skb(local, skb, false);
> + dev_kfree_skb(skb);
> +}
> +EXPORT_SYMBOL(ieee80211_tx_status_8023);
> +
> void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
> {
> struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index dd220b977025..0d1f525c0b02 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -1253,7 +1253,8 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
> (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
> return NULL;
>
> - if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
> + if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
> + unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
> if ((!ieee80211_is_mgmt(hdr->frame_control) ||
> ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
> vif->type == NL80211_IFTYPE_STATION) &&
> @@ -2358,9 +2359,9 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
> skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
> }
>
> -static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
> - struct sk_buff *skb,
> - struct sta_info **sta_out)
> +int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
> + struct sk_buff *skb,
> + struct sta_info **sta_out)
> {
> struct sta_info *sta;
>
> @@ -2870,7 +2871,8 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
> struct ieee80211_chanctx_conf *chanctx_conf;
> __le16 fc;
>
> - if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
> + if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) ||
> + sdata->hw_80211_encap)
> return;
>
> /* Locking here protects both the pointer itself, and against concurrent
> @@ -3600,6 +3602,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
> else
> info->flags &= ~IEEE80211_TX_CTL_AMPDU;
>
> + if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
> + goto encap_out;
> +
> if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
> struct sta_info *sta = container_of(txq->sta, struct sta_info,
> sta);
> @@ -3659,6 +3664,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
> break;
> }
>
> +encap_out:
> IEEE80211_SKB_CB(skb)->control.vif = vif;
> return skb;
>
> @@ -4030,6 +4036,167 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
> return NETDEV_TX_OK;
> }
>
> +static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
> + struct sk_buff *skb, int led_len,
> + struct sta_info *sta,
> + bool txpending)
> +{
> + struct ieee80211_local *local = sdata->local;
> + struct ieee80211_tx_control control = {};
> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> + struct ieee80211_sta *pubsta = NULL;
> + unsigned long flags;
> + int q = info->hw_queue;
> +
> + if (ieee80211_queue_skb(local, sdata, sta, skb))
> + return true;
> +
> + spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
> +
> + if (local->queue_stop_reasons[q] ||
> + (!txpending && !skb_queue_empty(&local->pending[q]))) {
> + if (txpending)
> + skb_queue_head(&local->pending[q], skb);
> + else
> + skb_queue_tail(&local->pending[q], skb);
> +
> + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
> +
> + return false;
> + }
> +
> + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
> +
> + if (sta && sta->uploaded)
> + pubsta = &sta->sta;
> +
> + control.sta = pubsta;
> +
> + drv_tx(local, &control, skb);
> +
> + return true;
> +}
> +
> +static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
> + struct net_device *dev, struct sta_info *sta,
> + struct sk_buff *skb)
> +{
> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> + struct ethhdr *ehdr = (struct ethhdr *)skb->data;
> + struct ieee80211_local *local = sdata->local;
> + bool authorized = false;
> + bool multicast;
> + bool tdls_peer;
> + unsigned char *ra = NULL;
> +
> + if (IS_ERR(sta) || (sta && !sta->uploaded))
> + sta = NULL;
> +
> + if (sdata->vif.type == NL80211_IFTYPE_STATION) {
> + tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
> + if (tdls_peer)
> + ra = skb->data;
> + else
> + ra = sdata->u.mgd.bssid;
> + } else {
> + ra = ehdr->h_dest;
> + }
> +
> + if (!ra)
> + goto out_free;
> + multicast = is_multicast_ether_addr(ra);
> +
> + if (sta)
> + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +
> + if (!multicast && !authorized &&
> + ((ehdr->h_proto != sdata->control_port_protocol) ||
> + !ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
> + goto out_free;
> +
> + if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
> + !atomic_read(&sdata->u.ap.num_mcast_sta))
> + goto out_free;
> +
> + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
> + test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
> + goto out_free;
> +
> + /* TODO: Handle frames requiring wifi tx status to be notified */
> +
> + memset(info, 0, sizeof(*info));
> +
> + if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
> + if (sdata->control_port_no_encrypt)
> + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
> + info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
> + }
> +
> + if (multicast)
> + info->flags |= IEEE80211_TX_CTL_NO_ACK;
> +
> + info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
> +
> + ieee80211_tx_stats(dev, skb->len);
> +
> + if (sta) {
> + sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
> + sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
> + }
> +
> + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
> + sdata = container_of(sdata->bss,
> + struct ieee80211_sub_if_data, u.ap);
> +
> + info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
> + info->control.vif = &sdata->vif;
> +
> + ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
> +
> + return;
> +
> +out_free:
> + kfree_skb(skb);
> +}
> +
> +netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
> + struct net_device *dev)
> +{
> + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
> + struct sta_info *sta;
> +
> + if (WARN_ON(!sdata->hw_80211_encap)) {
> + kfree_skb(skb);
> + return NETDEV_TX_OK;
> + }
> +
> + if (unlikely(skb->len < ETH_HLEN)) {
> + kfree_skb(skb);
> + return NETDEV_TX_OK;
> + }
> +
> + if (WARN_ON(dev->ieee80211_ptr->use_4addr)) {
> + kfree_skb(skb);
> + return NETDEV_TX_OK;
> + }
> +
> + rcu_read_lock();
> +
> + if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
> + goto out_free;
> +
> + ieee80211_8023_xmit(sdata, dev, sta, skb);
> +
> + goto out;
> +
> +out_free:
> + kfree_skb(skb);
> +out:
> + rcu_read_unlock();
> +
> + return NETDEV_TX_OK;
> +}
> +
> struct sk_buff *
> ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
> struct sk_buff *skb, u32 info_flags)
> @@ -4108,6 +4275,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
> }
> info->band = chanctx_conf->def.chan->band;
> result = ieee80211_tx(sdata, NULL, skb, true, 0);
> + } else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
> + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
> + dev_kfree_skb(skb);
> + return true;
> + }
> +
> + if (IS_ERR(sta) || (sta && !sta->uploaded))
> + sta = NULL;
> +
> + result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true);
> } else {
> struct sk_buff_head skbs;
>
^ permalink raw reply
* Re: [PATCH] ath10k: remove mmc_hw_reset while hif power down
From: Nicolas Boichat @ 2019-06-18 10:39 UTC (permalink / raw)
To: Ulf Hansson
Cc: Kalle Valo, Wen Gong, Grant Grundler, Wen Gong,
linux-wireless@vger.kernel.org, ath10k@lists.infradead.org,
Claire Chang
In-Reply-To: <CAPDyKFrs1rO38yd-yQ50y2Oo1JE=R2hWM-5FWp=Ng_TM1df7ww@mail.gmail.com>
On Tue, May 28, 2019 at 9:46 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
[snip]
>
> In the end, it seems like this needs a more detailed debug study, to
> figure out what exactly happens during the re-initialization of the
> SDIO card, rather than just papering over the problem by removing the
> call to mmc_hw_reset() in the SDIO func driver. Hope this helps.
To close the loop on this, we fixed this on the platform by driving a
reset/enable pin during reset:
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1657506
(device tree for this device is not upstream yet).
The problem has to do with the fact that on re-init (without power
cycle or reset/enable pin cycling), the device still sets S18A=1 in
CMD5 response (that's incorrect, the device should set S18A=0 if it's
already using 1.8V), so the host tries to switch voltage using CMD11,
which fails, as the device is already in 1.8V mode (that's correct
according to the specs).
Thanks,
>
> Kind regards
> Uffe
^ permalink raw reply
* Re: [PATCH V4 22/28] PCI: tegra: Access endpoint config only if PCIe link is up
From: Thierry Reding @ 2019-06-18 10:49 UTC (permalink / raw)
To: Manikanta Maddireddy
Cc: Bjorn Helgaas, Lorenzo Pieralisi, robh+dt, mark.rutland,
jonathanh, vidyas, linux-tegra, linux-pci, devicetree, linux-pm,
Rafael J. Wysocki, Johannes Berg, linux-wireless
In-Reply-To: <a7e0472d-f4a7-ed63-836a-b5e8b1360645@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 12279 bytes --]
On Tue, Jun 18, 2019 at 11:06:44AM +0530, Manikanta Maddireddy wrote:
>
> On 18-Jun-19 1:00 AM, Bjorn Helgaas wrote:
> > [+cc Rafael, linux-pm, in case they have insights on how rfkill works]
> >
> > On Mon, Jun 17, 2019 at 01:47:45PM +0200, Thierry Reding wrote:
> >> On Mon, Jun 17, 2019 at 03:31:38PM +0530, Manikanta Maddireddy wrote:
> >>> On 13-Jun-19 9:12 PM, Thierry Reding wrote:
> >>>> On Thu, Jun 13, 2019 at 03:39:46PM +0100, Lorenzo Pieralisi wrote:
> >>>>> On Mon, Jun 10, 2019 at 10:08:16AM +0530, Manikanta Maddireddy wrote:
> >>>>>> On 04-Jun-19 7:40 PM, Manikanta Maddireddy wrote:
> >>>>>>> On 04-Jun-19 6:44 PM, Thierry Reding wrote:
> >>>>>>>> On Thu, May 16, 2019 at 11:23:01AM +0530, Manikanta Maddireddy wrote:
> >>>>>>>>> Few endpoints like Wi-Fi supports power on/off and to leverage that
> >>>>>>>>> root port must support hot-plug and hot-unplug. Tegra PCIe doesn't
> >>>>>>>>> support hot-plug and hot-unplug, however it supports endpoint power
> >>>>>>>>> on/off feature as follows,
> >>>>>>>>> - Power off sequence:
> >>>>>>>>> - Transition of PCIe link to L2
> >>>>>>>>> - Power off endpoint
> >>>>>>>>> - Leave root port in power up state with the link in L2
> >>>>>>>>> - Power on sequence:
> >>>>>>>>> - Power on endpoint
> >>>>>>>>> - Apply hot reset to get PCIe link up
> >>>>>>>>>
> >>>>>>>>> PCIe client driver stops accessing PCIe endpoint config and
> >>>>>>>>> BAR registers after endpoint is powered off. However,
> >>>>>>>>> software applications like x11 server or lspci can access
> >>>>>>>>> endpoint config registers in which case host controller
> >>>>>>>>> raises "response decoding" errors. To avoid this scenario,
> >>>>>>>>> add PCIe link up check in config read and write callback
> >>>>>>>>> functions before accessing endpoint config registers.
> >>>>>>>>> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> >>>>>>>>> ---
> >>>>>>>>> V4: No change
> >>>>>>>>>
> >>>>>>>>> V3: Update the commit log with explanation for the need of this patch
> >>>>>>>>>
> >>>>>>>>> V2: Change tegra_pcie_link_status() to tegra_pcie_link_up()
> >>>>>>>>>
> >>>>>>>>> drivers/pci/controller/pci-tegra.c | 38 ++++++++++++++++++++++++++++++
> >>>>>>>>> 1 file changed, 38 insertions(+)
> >>>>>>>> This still doesn't look right to me conceptually. If
> >>>>>>>> somebody wants to access the PCI devices after the kernel
> >>>>>>>> has powered them off, why can't we just power the devices
> >>>>>>>> back on so that we allow userspace to properly access the
> >>>>>>>> devices?
> >>>>>>> 1. WiFi devices provides power-off feature for power saving
> >>>>>>> in mobiles. When WiFi is turned off we shouldn't power on
> >>>>>>> the HW back without user turning it back on.
> >>>>>>> 2. When ever user process tries to access config space, it'll
> >>>>>>> end up in these functions. We cannot have is_powered_on check
> >>>>>>> in config read/write callbacks.
> >>>>>>> 3. WiFi power on/off is device specific feature, we shouldn't
> >>>>>>> handle it in PCI subsystem or host controller driver.
> >>>>>>>> Or if that's not what we want, shouldn't we add something to
> >>>>>>>> the core PCI infrastructure to let us deal with this? It
> >>>>>>>> seems like this is some general problem that would apply to
> >>>>>>>> every PCI device and host bridge driver. Having each driver
> >>>>>>>> implement this logic separately doesn't seem like a good
> >>>>>>>> idea to me.
> >>>>>>> This should be handled by hotplug feature, whenever endpoint
> >>>>>>> is powered-off/ removed from the slot, hot unplug event
> >>>>>>> should take care of it. Unfortunately Tegra PCIe doesn't
> >>>>>>> support hotplug feature.
> >>>>>> I thought about your comment in
> >>>>>> https://patchwork.ozlabs.org/patch/1084204/ again. What if I
> >>>>>> add link up check in tegra_pcie_isr() and make "response
> >>>>>> decoding error" as debug print? EP Config access will happen
> >>>>>> when link is down, but "Response decoding error" print comes
> >>>>>> only if debug log is enabled. This way we can avoid race
> >>>>>> issue in config accessors and we get prints when debug logs
> >>>>>> are enabled.
> >>>> The problem that Manikanta is trying to solve here occurs in
> >>>> this situation (Manikanta, correct me if I've got this wrong):
> >>>> on some setups, a WiFi module connected over PCI will toggle a
> >>>> power GPIO as part of runtime suspend. This effectively causes
> >>>> the module to disappear from the PCI bus (i.e. it can no longer
> >>>> be accessed until the power GPIO is toggled again).
> >>> GPIO is toggled as part of WiFi on/off, can be triggered from
> >>> network manager UI.
> >>>> This is fine from a kernel point of view because the kernel keeps track
> >>>> of what devices are suspended. However, userspace will occasionally try
> >>>> to read the configuration space access of all devices, and since it
> >>>> doesn't have any knowledge about the suspend state of these devices, it
> >>>> doesn't know which ones to leave alone. I think this happens when the
> >>>> X.Org server is running.
> >>> This is fine from a kernel point of view because PCI client driver
> >>> doesn't initiate any PCIe transaction until network interface
> >>> is up during WiFi on.
> >>>
> >>>> One thing that Manikanta and I had discussed was that perhaps
> >>>> the device should be hot-unplugged when it goes into this
> >>>> low-power state. However, we don't support hotplug on Tegra210
> >>>> where this is needed, so we'd need some sort of software-induced
> >>>> hot-unplug. However, this low power state is entered when the
> >>>> WiFi interface is taken down (i.e. ip link set dev <interface>
> >>>> down). If we were to remove the PCI device in that case, it
> >>>> means that the interface goes away completely, which is
> >>>> completely unexpected from a user's perspective. After all,
> >>>> taking a link down and up may be something that scripts are
> >>>> doing all the time. They'd fall over if after taking the
> >>>> interface down, the interface completely disappears.
> >>>> It's also not entirely clear to me how we get the device back
> >>>> onto the bus again after it is in low power. If we hot-unplug
> >>>> the device, then the driver will be unbound. Presumably the
> >>>> driver is what's controlling the power GPIO, so there won't be
> >>>> any entity that can be used to bring the chip back to life.
> >>>> Unless we deal with that power GPIO elsewhere (rfkill switch
> >>>> perhaps?).
> >>> Correct, rfkill switch should handle the GPIO.
> >>> Sequence will be,
> >>> - WiFi ON
> >>> - rfkill switch enables the WiFi GPIO
> >>> - Tegra PCIe receives hot plug event
> >>> - Tegra PCIe hot plug driver rescans PCI bus and enumerates the device
> >>> - PCI client driver is probed, which will create network interface
> >>> - WiFi OFF
> >>> - rfkill switch disables the WiFi GPIO
> >>> - Tegra PCIe receives hot unplug event
> >>> - Tegra PCIe hot plug driver removes PCI devices under the bus
> >>> - PCI client driver remove is executed, which will remove
> >>> network interface
> >>> We don't need current patch in this case because PCI device is not
> >>> present in the PCI hierarchy, so there cannot be EP config access
> >>> with link down. However Tegra doesn't support hot plug and unplug
> >>> events. I am not sure if we have any software based hot plug event
> >>> trigger.
> >>> I will drop current patch and pursue if above sequence can be
> >>> implemented for Tegra.
> >> I just recalled that we have these messages in the kernel log:
> >>
> >> # dmesg | grep tegra-pcie
> >> [ 1.055761] tegra-pcie 1003000.pcie: 4x1, 1x1 configuration
> >> [ 2.745764] tegra-pcie 1003000.pcie: 4x1, 1x1 configuration
> >> [ 2.753073] tegra-pcie 1003000.pcie: probing port 0, using 4 lanes
> >> [ 2.761334] tegra-pcie 1003000.pcie: Slot present pin change, signature: 00000008
> >> [ 3.177607] tegra-pcie 1003000.pcie: link 0 down, retrying
> >> [ 3.585605] tegra-pcie 1003000.pcie: link 0 down, retrying
> >> [ 3.993606] tegra-pcie 1003000.pcie: link 0 down, retrying
> >> [ 4.001214] tegra-pcie 1003000.pcie: link 0 down, ignoring
> >> [ 4.006733] tegra-pcie 1003000.pcie: probing port 1, using 1 lanes
> >> [ 4.015042] tegra-pcie 1003000.pcie: Slot present pin change, signature: 00000000
> >> [ 4.031177] tegra-pcie 1003000.pcie: PCI host bridge to bus 0000:00
> >>
> >> These "slot present pin change" message do look a lot like hotplug
> >> related messages. Could we perhaps use those to our advantage for this
> >> case? Do you see these when you run on the platform where WiFi is
> >> enabled/disabled using rfkill?
> >>
> >> Given that rfkill is completely decoupled from PCI, I don't see how we
> >> would trigger any software-based hotplug mechanism. Perhaps one thing
> >> that we could do is the equivalent of this:
> >>
> >> # echo 1 > /sys/bus/pci/rescan
> >>
> >> from some script that's perhaps tied to the rfkill somehow. I'm not sure
> >> if that's possible, or generic enough.
> > How does rfkill work? It sounds like it completely removes power from
> > the wifi device, putting it in D3cold. Is there any software
> > notification other than the "Slot present pin change" (which looks
> > like a Tegra-specific thing)?
> >
> > If the device is in D3cold, it won't respond to any PCI transactions,
> > and there's no standard PCI mechanism to wake it up. Probably the
> > cleanest way to handle this is to make it a hot-unplug.
> >
> > If this were an ACPI system, the rfkill might be visible as some sort
> > of ACPI power management event, and there might be a corresponding way
> > for software to bring the device back to D0 temporarily. That would
> > make lspci and X config reads work. But I don't think this system has
> > ACPI.
>
> "Slot present pin change" interrupt is triggered based on the programming
> of PRSNT_MAP bit field in PCIE2_RP_PRIV_MISC controller register and
> they are not triggered when EP is hot plugged/unplugged. Tegra PCIe
> controller doesn't have capability to detect EP hot plug and unplug.
> Consider that WiFi off equivalent to SW aware EP hot unplug event.
>
> The rfkill subsystem provides a generic interface for disabling any radio
> transmitter in the system. WiFi M.2 form factor cards provide W_DISABLE
> GPIO to control the radio transmitter and I have seen some cards provide
> control to turn off complete chip through this GPIO. Here we are talking
> about second case where device is put in D3cold state. This GPIO can be
> registered to rfkill subsystem and rfkill commands (like "rfkill unblock
> wifi") can be used to turn on radio transmitter during WiFi on.
Perhaps what we need here is some sort of mechanism to make rfkill and
the PCI host controller interoperate? I could imagine for example that
the PCI host controller would get a new "rfkill" property in device
tree that points at the rfkill device via phandle.
The driver could then get a reference to it using something like:
rfkill = rfkill_get(dev);
if (IS_ERR(rfkill)) {
...
}
and register for notification:
err = rfkill_subscribe(rfkill, callback);
if (err < 0) {
...
}
rfkill_unsubscribe() and rfkill_put() would then be used upon driver
unload to detach from the rfkill.
I noticed that there's an rfkill-gpio driver (net/rfkill/rfkill-gpio.c)
that already does pretty much everything that we need, except that it
doesn't support DT yet, but I suspect that that's pretty easy to add.
Johannes, any thoughts on this. In a nutshell what we're trying to solve
here is devices that get removed from/added to PCI based on an rfkill-
type of device. The difference to other implementations is that we have
no way of detecting when the device has gone away (PCI hotplug does not
work). So we'd need some software-triggered mechanism to let the PCI
host controller know when the device is presumably going away or being
added back, so that the PCI bus can be rescanned and the PCI device
removed or added at that point).
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v5 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle
From: Kalle Valo @ 2019-06-18 11:02 UTC (permalink / raw)
To: Ulf Hansson
Cc: Douglas Anderson, Adrian Hunter, Arend van Spriel,
brcm80211-dev-list.pdl, open list:ARM/Rockchip SoC..., Double Lo,
Brian Norris, linux-wireless, Naveen Gupta, Madhan Mohan R,
Matthias Kaehlcke, Wright Feng, Chi-Hsien Lin, netdev,
brcm80211-dev-list, YueHaibing, Allison Randal, Thomas Gleixner,
Hante Meuleman, Greg Kroah-Hartman, Niklas Söderlund,
Ritesh Harjani, Michael Trimarchi, Wolfram Sang, Franky Lin,
Ondrej Jirman, Jiong Wu, David S. Miller,
linux-mmc@vger.kernel.org, Linux Kernel Mailing List, Avri Altman
In-Reply-To: <CAPDyKFpaX6DSM_BjtghAHUf7qYCyEG+wMagXPUdgz3Eutovqfw@mail.gmail.com>
Ulf Hansson <ulf.hansson@linaro.org> writes:
> On Mon, 17 Jun 2019 at 19:57, Douglas Anderson <dianders@chromium.org> wrote:
>>
>> This series attempts to deal better with the expected transmission
>> errors related to the idle states (handled by the Always-On-Subsystem
>> or AOS) on the SDIO-based WiFi on rk3288-veyron-minnie,
>> rk3288-veyron-speedy, and rk3288-veyron-mickey.
>>
>> Some details about those errors can be found in
>> <https://crbug.com/960222>, but to summarize it here: if we try to
>> send the wakeup command to the WiFi card at the same time it has
>> decided to wake up itself then it will behave badly on the SDIO bus.
>> This can cause timeouts or CRC errors.
>>
>> When I tested on 4.19 and 4.20 these CRC errors can be seen to cause
>> re-tuning. Since I am currently developing on 4.19 this was the
>> original problem I attempted to solve.
>>
>> On mainline it turns out that you don't see the retuning errors but
>> you see tons of spam about timeouts trying to wakeup from sleep. I
>> tracked down the commit that was causing that and have partially
>> reverted it here. I have no real knowledge about Broadcom WiFi, but
>> the commit that was causing problems sounds (from the descriptioin) to
>> be a hack commit penalizing all Broadcom WiFi users because of a bug
>> in a Cypress SD controller. I will let others comment if this is
>> truly the case and, if so, what the right solution should be.
>>
>> For v3 of this series I have added 2 patches to the end of the series
>> to address errors that would show up on systems with these same SDIO
>> WiFi cards when used on controllers that do periodic retuning. These
>> systems need an extra fix to prevent the retuning from happening when
>> the card is asleep.
>>
>> I believe v5 of this series is all ready to go assuming Kalle Valo is
>> good with it. I've added after-the-cut notes to patches awaiting his
>> Ack and have added other tags collected so far.
>>
>> Changes in v5:
>> - Add missing sdio_retune_crc_enable() in comments (Ulf).
>> - /s/reneable/re-enable (Ulf).
>> - Remove leftover prototypes: mmc_expect_errors_begin() / end() (Ulf).
>> - Rewording of "sleep command" in commit message (Arend).
>>
>> Changes in v4:
>> - Moved to SDIO API only (Adrian, Ulf).
>> - Renamed to make it less generic, now retune_crc_disable (Ulf).
>> - Function header makes it clear host must be claimed (Ulf).
>> - No more WARN_ON (Ulf).
>> - Adjust to API rename (Adrian, Ulf).
>> - Moved retune hold/release to SDIO API (Adrian).
>> - Adjust to API rename (Adrian).
>>
>> Changes in v3:
>> - Took out the spinlock since I believe this is all in one context.
>> - Expect errors for all of brcmf_sdio_kso_control() (Adrian).
>> - ("mmc: core: Export mmc_retune_hold_now() mmc_retune_release()") new for v3.
>> - ("brcmfmac: sdio: Don't tune while the card is off") new for v3.
>>
>> Changes in v2:
>> - A full revert, not just a partial one (Arend). ...with explicit Cc.
>> - Updated commit message to clarify based on discussion of v1.
>>
>> Douglas Anderson (5):
>> Revert "brcmfmac: disable command decode in sdio_aos"
>> mmc: core: API to temporarily disable retuning for SDIO CRC errors
>> brcmfmac: sdio: Disable auto-tuning around commands expected to fail
>> mmc: core: Add sdio_retune_hold_now() and sdio_retune_release()
>> brcmfmac: sdio: Don't tune while the card is off
>>
>> drivers/mmc/core/core.c | 5 +-
>> drivers/mmc/core/sdio_io.c | 77 +++++++++++++++++++
>> .../broadcom/brcm80211/brcmfmac/sdio.c | 17 ++--
>> include/linux/mmc/host.h | 1 +
>> include/linux/mmc/sdio_func.h | 6 ++
>> 5 files changed, 99 insertions(+), 7 deletions(-)
>>
>> --
>> 2.22.0.410.gd8fdbe21b5-goog
>>
>
> Applied for fixes, thanks!
>
> Some minor changes:
> 1) Dropped the a few "commit notes", that was more related to version
> and practical information about the series.
> 2) Dropped fixes tags for patch 2->5, but instead put a stable tag
> targeted for v4.18+.
>
> Awaiting an ack from Kalle before sending the PR to Linus.
>
> Kalle, perhaps you prefer to pick patch 1, as it could go separate.
> Then please tell - and/or if there is anything else you want me to
> change.
TBH I haven't followed the thread (or patches) that closely :) So feel
free to take them and push them to Linus.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v5 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle
From: Ulf Hansson @ 2019-06-18 11:40 UTC (permalink / raw)
To: Kalle Valo
Cc: Douglas Anderson, Adrian Hunter, Arend van Spriel,
brcm80211-dev-list.pdl, open list:ARM/Rockchip SoC..., Double Lo,
Brian Norris, linux-wireless, Naveen Gupta, Madhan Mohan R,
Matthias Kaehlcke, Wright Feng, Chi-Hsien Lin, netdev,
brcm80211-dev-list, YueHaibing, Allison Randal, Thomas Gleixner,
Hante Meuleman, Greg Kroah-Hartman, Niklas Söderlund,
Ritesh Harjani, Michael Trimarchi, Wolfram Sang, Franky Lin,
Ondrej Jirman, Jiong Wu, David S. Miller,
linux-mmc@vger.kernel.org, Linux Kernel Mailing List, Avri Altman
In-Reply-To: <87v9x39mxf.fsf@kamboji.qca.qualcomm.com>
On Tue, 18 Jun 2019 at 13:02, Kalle Valo <kvalo@codeaurora.org> wrote:
>
> Ulf Hansson <ulf.hansson@linaro.org> writes:
>
> > On Mon, 17 Jun 2019 at 19:57, Douglas Anderson <dianders@chromium.org> wrote:
> >>
> >> This series attempts to deal better with the expected transmission
> >> errors related to the idle states (handled by the Always-On-Subsystem
> >> or AOS) on the SDIO-based WiFi on rk3288-veyron-minnie,
> >> rk3288-veyron-speedy, and rk3288-veyron-mickey.
> >>
> >> Some details about those errors can be found in
> >> <https://crbug.com/960222>, but to summarize it here: if we try to
> >> send the wakeup command to the WiFi card at the same time it has
> >> decided to wake up itself then it will behave badly on the SDIO bus.
> >> This can cause timeouts or CRC errors.
> >>
> >> When I tested on 4.19 and 4.20 these CRC errors can be seen to cause
> >> re-tuning. Since I am currently developing on 4.19 this was the
> >> original problem I attempted to solve.
> >>
> >> On mainline it turns out that you don't see the retuning errors but
> >> you see tons of spam about timeouts trying to wakeup from sleep. I
> >> tracked down the commit that was causing that and have partially
> >> reverted it here. I have no real knowledge about Broadcom WiFi, but
> >> the commit that was causing problems sounds (from the descriptioin) to
> >> be a hack commit penalizing all Broadcom WiFi users because of a bug
> >> in a Cypress SD controller. I will let others comment if this is
> >> truly the case and, if so, what the right solution should be.
> >>
> >> For v3 of this series I have added 2 patches to the end of the series
> >> to address errors that would show up on systems with these same SDIO
> >> WiFi cards when used on controllers that do periodic retuning. These
> >> systems need an extra fix to prevent the retuning from happening when
> >> the card is asleep.
> >>
> >> I believe v5 of this series is all ready to go assuming Kalle Valo is
> >> good with it. I've added after-the-cut notes to patches awaiting his
> >> Ack and have added other tags collected so far.
> >>
> >> Changes in v5:
> >> - Add missing sdio_retune_crc_enable() in comments (Ulf).
> >> - /s/reneable/re-enable (Ulf).
> >> - Remove leftover prototypes: mmc_expect_errors_begin() / end() (Ulf).
> >> - Rewording of "sleep command" in commit message (Arend).
> >>
> >> Changes in v4:
> >> - Moved to SDIO API only (Adrian, Ulf).
> >> - Renamed to make it less generic, now retune_crc_disable (Ulf).
> >> - Function header makes it clear host must be claimed (Ulf).
> >> - No more WARN_ON (Ulf).
> >> - Adjust to API rename (Adrian, Ulf).
> >> - Moved retune hold/release to SDIO API (Adrian).
> >> - Adjust to API rename (Adrian).
> >>
> >> Changes in v3:
> >> - Took out the spinlock since I believe this is all in one context.
> >> - Expect errors for all of brcmf_sdio_kso_control() (Adrian).
> >> - ("mmc: core: Export mmc_retune_hold_now() mmc_retune_release()") new for v3.
> >> - ("brcmfmac: sdio: Don't tune while the card is off") new for v3.
> >>
> >> Changes in v2:
> >> - A full revert, not just a partial one (Arend). ...with explicit Cc.
> >> - Updated commit message to clarify based on discussion of v1.
> >>
> >> Douglas Anderson (5):
> >> Revert "brcmfmac: disable command decode in sdio_aos"
> >> mmc: core: API to temporarily disable retuning for SDIO CRC errors
> >> brcmfmac: sdio: Disable auto-tuning around commands expected to fail
> >> mmc: core: Add sdio_retune_hold_now() and sdio_retune_release()
> >> brcmfmac: sdio: Don't tune while the card is off
> >>
> >> drivers/mmc/core/core.c | 5 +-
> >> drivers/mmc/core/sdio_io.c | 77 +++++++++++++++++++
> >> .../broadcom/brcm80211/brcmfmac/sdio.c | 17 ++--
> >> include/linux/mmc/host.h | 1 +
> >> include/linux/mmc/sdio_func.h | 6 ++
> >> 5 files changed, 99 insertions(+), 7 deletions(-)
> >>
> >> --
> >> 2.22.0.410.gd8fdbe21b5-goog
> >>
> >
> > Applied for fixes, thanks!
> >
> > Some minor changes:
> > 1) Dropped the a few "commit notes", that was more related to version
> > and practical information about the series.
> > 2) Dropped fixes tags for patch 2->5, but instead put a stable tag
> > targeted for v4.18+.
> >
> > Awaiting an ack from Kalle before sending the PR to Linus.
> >
> > Kalle, perhaps you prefer to pick patch 1, as it could go separate.
> > Then please tell - and/or if there is anything else you want me to
> > change.
>
> TBH I haven't followed the thread (or patches) that closely :) So feel
> free to take them and push them to Linus.
>
I take that as an ack and will add your tag for it, thanks!
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH v5 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle
From: Kalle Valo @ 2019-06-18 11:47 UTC (permalink / raw)
To: Ulf Hansson
Cc: Douglas Anderson, Adrian Hunter, Arend van Spriel,
brcm80211-dev-list.pdl, open list:ARM/Rockchip SoC..., Double Lo,
Brian Norris, linux-wireless, Naveen Gupta, Madhan Mohan R,
Matthias Kaehlcke, Wright Feng, Chi-Hsien Lin, netdev,
brcm80211-dev-list, YueHaibing, Allison Randal, Thomas Gleixner,
Hante Meuleman, Greg Kroah-Hartman, Niklas Söderlund,
Ritesh Harjani, Michael Trimarchi, Wolfram Sang, Franky Lin,
Ondrej Jirman, Jiong Wu, David S. Miller,
linux-mmc@vger.kernel.org, Linux Kernel Mailing List, Avri Altman
In-Reply-To: <CAPDyKFoE0+KNBT5j3_VpJKcztghVa-eFJhy8887bZcUk8bfN2Q@mail.gmail.com>
Ulf Hansson <ulf.hansson@linaro.org> writes:
> On Tue, 18 Jun 2019 at 13:02, Kalle Valo <kvalo@codeaurora.org> wrote:
>
> Ulf Hansson <ulf.hansson@linaro.org> writes:
>
> > On Mon, 17 Jun 2019 at 19:57, Douglas Anderson
> <dianders@chromium.org> wrote:
> >>
> >> This series attempts to deal better with the expected
> transmission
> >> errors related to the idle states (handled by the
> Always-On-Subsystem
> >> or AOS) on the SDIO-based WiFi on rk3288-veyron-minnie,
> >> rk3288-veyron-speedy, and rk3288-veyron-mickey.
> >>
> >> Some details about those errors can be found in
> >> <https://crbug.com/960222>, but to summarize it here: if we try
> to
> >> send the wakeup command to the WiFi card at the same time it
> has
> >> decided to wake up itself then it will behave badly on the SDIO
> bus.
> >> This can cause timeouts or CRC errors.
> >>
> >> When I tested on 4.19 and 4.20 these CRC errors can be seen to
> cause
> >> re-tuning. Since I am currently developing on 4.19 this was the
> >> original problem I attempted to solve.
> >>
> >> On mainline it turns out that you don't see the retuning errors
> but
> >> you see tons of spam about timeouts trying to wakeup from
> sleep. I
> >> tracked down the commit that was causing that and have
> partially
> >> reverted it here. I have no real knowledge about Broadcom WiFi,
> but
> >> the commit that was causing problems sounds (from the
> descriptioin) to
> >> be a hack commit penalizing all Broadcom WiFi users because of
> a bug
> >> in a Cypress SD controller. I will let others comment if this
> is
> >> truly the case and, if so, what the right solution should be.
> >>
> >> For v3 of this series I have added 2 patches to the end of the
> series
> >> to address errors that would show up on systems with these same
> SDIO
> >> WiFi cards when used on controllers that do periodic retuning.
> These
> >> systems need an extra fix to prevent the retuning from
> happening when
> >> the card is asleep.
> >>
> >> I believe v5 of this series is all ready to go assuming Kalle
> Valo is
> >> good with it. I've added after-the-cut notes to patches
> awaiting his
> >> Ack and have added other tags collected so far.
> >>
> >> Changes in v5:
> >> - Add missing sdio_retune_crc_enable() in comments (Ulf).
> >> - /s/reneable/re-enable (Ulf).
> >> - Remove leftover prototypes: mmc_expect_errors_begin() / end()
> (Ulf).
> >> - Rewording of "sleep command" in commit message (Arend).
> >>
> >> Changes in v4:
> >> - Moved to SDIO API only (Adrian, Ulf).
> >> - Renamed to make it less generic, now retune_crc_disable
> (Ulf).
> >> - Function header makes it clear host must be claimed (Ulf).
> >> - No more WARN_ON (Ulf).
> >> - Adjust to API rename (Adrian, Ulf).
> >> - Moved retune hold/release to SDIO API (Adrian).
> >> - Adjust to API rename (Adrian).
> >>
> >> Changes in v3:
> >> - Took out the spinlock since I believe this is all in one
> context.
> >> - Expect errors for all of brcmf_sdio_kso_control() (Adrian).
> >> - ("mmc: core: Export mmc_retune_hold_now() mmc_retune_release
> ()") new for v3.
> >> - ("brcmfmac: sdio: Don't tune while the card is off") new for
> v3.
> >>
> >> Changes in v2:
> >> - A full revert, not just a partial one (Arend). ...with
> explicit Cc.
> >> - Updated commit message to clarify based on discussion of v1.
> >>
> >> Douglas Anderson (5):
> >> Revert "brcmfmac: disable command decode in sdio_aos"
> >> mmc: core: API to temporarily disable retuning for SDIO CRC
> errors
> >> brcmfmac: sdio: Disable auto-tuning around commands expected to
> fail
> >> mmc: core: Add sdio_retune_hold_now() and sdio_retune_release()
> >> brcmfmac: sdio: Don't tune while the card is off
> >>
> >> drivers/mmc/core/core.c | 5 +-
> >> drivers/mmc/core/sdio_io.c | 77 +++++++++++++++++++
> >> .../broadcom/brcm80211/brcmfmac/sdio.c | 17 ++--
> >> include/linux/mmc/host.h | 1 +
> >> include/linux/mmc/sdio_func.h | 6 ++
> >> 5 files changed, 99 insertions(+), 7 deletions(-)
> >>
> >> --
> >> 2.22.0.410.gd8fdbe21b5-goog
> >>
> >
> > Applied for fixes, thanks!
> >
> > Some minor changes:
> > 1) Dropped the a few "commit notes", that was more related to
> version
> > and practical information about the series.
> > 2) Dropped fixes tags for patch 2->5, but instead put a stable
> tag
> > targeted for v4.18+.
> >
> > Awaiting an ack from Kalle before sending the PR to Linus.
> >
> > Kalle, perhaps you prefer to pick patch 1, as it could go
> separate.
> > Then please tell - and/or if there is anything else you want me
> to
> > change.
>
> TBH I haven't followed the thread (or patches) that closely :) So
> feel
> free to take them and push them to Linus.
>
>
> I take that as an ack and will add your tag for it, thanks!
Yes, it was an ack :) I forgot to add:
Acked-by: Kalle Valo <kvalo@codeaurora.org>
BTW, your previous mail was in HTML so most likely it didn't reach the
list.
--
Kalle Valo
^ permalink raw reply
* [PATCH v2] mmc: core: Prevent processing SDIO IRQs when the card is suspended
From: Ulf Hansson @ 2019-06-18 12:05 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson, Douglas Anderson
Cc: Adrian Hunter, Brian Norris, Shawn Lin, Guenter Roeck,
Heiko Stuebner, Kalle Valo, linux-wireless, stable
Processing of SDIO IRQs must obviously be prevented while the card is
system suspended, otherwise we may end up trying to communicate with an
uninitialized SDIO card.
Reports throughout the years shows that this is not only a theoretical
problem, but a real issue. So, let's finally fix this problem, by keeping
track of the state for the card and bail out before processing the SDIO
IRQ, in case the card is suspended.
Cc: stable@vger.kernel.org
Reported-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
Changes in v2:
- Respect error code in mmc_sdio_suspend(), pointed out by Doug.
---
drivers/mmc/core/sdio.c | 13 ++++++++++++-
drivers/mmc/core/sdio_irq.c | 4 ++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index d1aa1c7577bb..712a7742765e 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -937,6 +937,10 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
*/
static int mmc_sdio_suspend(struct mmc_host *host)
{
+ /* Prevent processing of SDIO IRQs in suspended state. */
+ mmc_card_set_suspended(host->card);
+ cancel_delayed_work_sync(&host->sdio_irq_work);
+
mmc_claim_host(host);
if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host))
@@ -985,13 +989,20 @@ static int mmc_sdio_resume(struct mmc_host *host)
err = sdio_enable_4bit_bus(host->card);
}
- if (!err && host->sdio_irqs) {
+ if (err)
+ goto out;
+
+ /* Allow SDIO IRQs to be processed again. */
+ mmc_card_clr_suspended(host->card);
+
+ if (host->sdio_irqs) {
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread);
else if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 1);
}
+out:
mmc_release_host(host);
host->pm_flags &= ~MMC_PM_KEEP_POWER;
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 931e6226c0b3..9f54a259a1b3 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -34,6 +34,10 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
unsigned char pending;
struct sdio_func *func;
+ /* Don't process SDIO IRQs if the card is suspended. */
+ if (mmc_card_suspended(card))
+ return 0;
+
/*
* Optimization, if there is only 1 function interrupt registered
* and we know an IRQ was signaled then call irq handler directly.
--
2.17.1
^ permalink raw reply related
* Re: [PATCH] mt76: fix sparse warnings: warning: dubious: x & !y
From: Kalle Valo @ 2019-06-18 12:08 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: nbd, lorenzo.bianconi, linux-wireless
In-Reply-To: <d8a003eda05150fb21842d7755fe8081b86cf6df.1560851052.git.lorenzo@kernel.org>
Lorenzo Bianconi <lorenzo@kernel.org> writes:
> Fix following sparse warnings in mt7603/mac.c and mt76x02_mac.c
>
> drivers/net/wireless/mediatek/mt76/mt76x02_mac.c:113:17: warning: dubious: x & !y
> drivers/net/wireless/mediatek/mt76/mt76x02_mac.c:145:16: warning: dubious: x & !y
> drivers/net/wireless/mediatek/mt76/mt7603/mac.c:730:9: warning: dubious: x & !y
> drivers/net/wireless/mediatek/mt76/mt7603/mac.c:790:15: warning: dubious: x & !y
>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 6 ++++--
> drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 7 +++++--
> 2 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
> index ab5141701997..62e0a7f4716a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
> @@ -709,6 +709,7 @@ int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
> {
> enum mt7603_cipher_type cipher;
> u32 addr = mt7603_wtbl3_addr(wcid);
> + bool key_set = !!key;
> u8 key_data[32];
> int key_len = sizeof(key_data);
>
> @@ -727,7 +728,7 @@ int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
> mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher);
> if (key)
> mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx);
> - mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key);
> + mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, key_set);
I'm not seeing you really _fixing_ anything here, you are just working
around a sparse warning by adding an extra variable. I'm having a hard
time to see the benefit from that, it's just an unnecessary variable.
FWIW I had similar warnings in ath11k, I decided to ignore those. But
anyone has suggestions how to solve it better, please do let me know.
--
Kalle Valo
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox