Commit 9bf13bee authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: mvm: include configured sniffer AID in radiotap

In order to make more sense out of the captured radiotap data e.g.
when the configured AID changes, add the currently configured AID
to the radiotap data as a vendor extension field.

This is made race-free by updating the included value from inside
the RX path (using a notification wait) for the command response
from the firmware, which thus means it's serialized with frame RX.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 81444538
......@@ -1682,11 +1682,33 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
return ret ?: count;
}
struct iwl_mvm_sniffer_apply {
struct iwl_mvm *mvm;
u16 aid;
};
static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_mvm_sniffer_apply *apply = data;
apply->mvm->cur_aid = cpu_to_le16(apply->aid);
return true;
}
static ssize_t
iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
size_t count, loff_t *ppos)
{
struct iwl_notification_wait wait;
struct iwl_he_monitor_cmd he_mon_cmd = {};
struct iwl_mvm_sniffer_apply apply = {
.mvm = mvm,
};
u16 wait_cmds[] = {
iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD, DATA_PATH_GROUP, 0),
};
u32 aid;
int ret;
......@@ -1702,10 +1724,30 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
he_mon_cmd.aid = cpu_to_le16(aid);
apply.aid = aid;
mutex_lock(&mvm->mutex);
/*
* Use the notification waiter to get our function triggered
* in sequence with other RX. This ensures that frames we get
* on the RX queue _before_ the new configuration is applied
* still have mvm->cur_aid pointing to the old AID, and that
* frames on the RX queue _after_ the firmware processed the
* new configuration (and sent the response, synchronously)
* get mvm->cur_aid correctly set to the new AID.
*/
iwl_init_notification_wait(&mvm->notif_wait, &wait,
wait_cmds, ARRAY_SIZE(wait_cmds),
iwl_mvm_sniffer_apply, &apply);
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD,
DATA_PATH_GROUP, 0), 0,
sizeof(he_mon_cmd), &he_mon_cmd);
/* no need to really wait, we already did anyway */
iwl_remove_notification(&mvm->notif_wait, &wait);
mutex_unlock(&mvm->mutex);
return ret ?: count;
......
......@@ -1167,6 +1167,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_stop_device(mvm);
mvm->cur_aid = 0;
mvm->scan_status = 0;
mvm->ps_disabled = false;
mvm->calibrating = false;
......
......@@ -1164,6 +1164,10 @@ struct iwl_mvm {
/* does a monitor vif exist (only one can exist hence bool) */
bool monitor_on;
/* sniffer data to include in radiotap */
__le16 cur_aid;
#ifdef CONFIG_ACPI
struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
......
......@@ -192,11 +192,40 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr,
}
}
static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
struct sk_buff *skb)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_vendor_radiotap *radiotap;
int size = sizeof(*radiotap) + sizeof(__le16);
if (!mvm->cur_aid)
return;
radiotap = skb_put(skb, size);
radiotap->align = 1;
/* Intel OUI */
radiotap->oui[0] = 0xf6;
radiotap->oui[1] = 0x54;
radiotap->oui[2] = 0x25;
/* radiotap sniffer config sub-namespace */
radiotap->subns = 1;
radiotap->present = 0x1;
radiotap->len = size - sizeof(*radiotap);
radiotap->pad = 0;
/* fill the data now */
memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
}
/* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
struct napi_struct *napi,
struct sk_buff *skb, int queue,
struct ieee80211_sta *sta)
struct ieee80211_sta *sta,
bool csi)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
......@@ -465,7 +494,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
while ((skb = __skb_dequeue(skb_list))) {
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
reorder_buf->queue,
sta);
sta, false);
reorder_buf->num_stored--;
}
}
......@@ -1304,6 +1333,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
.d4 = desc->phy_data4,
.info_type = IWL_RX_PHY_INFO_TYPE_NONE,
};
bool csi = false;
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
......@@ -1599,7 +1629,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
iwl_mvm_create_skb(skb, hdr, len, crypt_len, rxb);
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue,
sta, csi);
out:
rcu_read_unlock();
}
......@@ -1732,7 +1763,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
rx_status->rate_idx = rate;
}
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, false);
out:
rcu_read_unlock();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment