iwlwifi: mvm: support beacon IE injection

This is useful for automated tests.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Sara Sharon 2018-11-08 09:53:48 +02:00 committed by Luca Coelho
parent cee859fe9a
commit 138664a307
3 changed files with 128 additions and 11 deletions

View File

@ -1188,6 +1188,108 @@ out:
return ret ?: count;
}
static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
{
struct ieee80211_vif *vif;
struct iwl_mvm_vif *mvmvif;
struct sk_buff *beacon;
struct ieee80211_tx_info *info;
struct iwl_mac_beacon_cmd beacon_cmd = {};
u8 rate;
u16 flags;
int i;
len /= 2;
/* Element len should be represented by u8 */
if (len >= U8_MAX)
return -EINVAL;
if (!iwl_mvm_firmware_running(mvm))
return -EIO;
if (!iwl_mvm_has_new_tx_api(mvm) &&
!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
return -EINVAL;
rcu_read_lock();
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true);
if (!vif)
continue;
if (vif->type == NL80211_IFTYPE_AP)
break;
}
if (i == NUM_MAC_INDEX_DRIVER || !vif)
goto out_err;
mvm->hw->extra_beacon_tailroom = len;
beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
if (!beacon)
goto out_err;
if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
dev_kfree_skb(beacon);
goto out_err;
}
mvmvif = iwl_mvm_vif_from_mac80211(vif);
info = IEEE80211_SKB_CB(beacon);
rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
if (rate == IWL_FIRST_CCK_RATE)
flags |= IWL_MAC_BEACON_CCK;
beacon_cmd.flags = cpu_to_le16(flags);
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
&beacon_cmd.tim_size,
beacon->data, beacon->len);
mutex_lock(&mvm->mutex);
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
sizeof(beacon_cmd));
mutex_unlock(&mvm->mutex);
dev_kfree_skb(beacon);
rcu_read_unlock();
return 0;
out_err:
rcu_read_unlock();
return -EINVAL;
}
static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
mvm->hw->extra_beacon_tailroom = 0;
return ret ?: count;
}
static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
char *buf,
size_t count,
loff_t *ppos)
{
int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
mvm->hw->extra_beacon_tailroom = 0;
return ret ?: count;
}
static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@ -1806,6 +1908,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
@ -2007,6 +2111,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
#ifdef CONFIG_ACPI
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400);
#endif

View File

@ -811,9 +811,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
__le32 *tim_index, __le32 *tim_size,
u8 *beacon, u32 frame_size)
void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
__le32 *tim_index, __le32 *tim_size,
u8 *beacon, u32 frame_size)
{
u32 tim_idx;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
@ -853,8 +853,8 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
return ie - beacon;
}
static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
struct ieee80211_vif *vif)
u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
struct ieee80211_vif *vif)
{
u8 rate;
@ -904,9 +904,9 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
}
static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
struct sk_buff *beacon,
void *data, int len)
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
struct sk_buff *beacon,
void *data, int len)
{
struct iwl_host_cmd cmd = {
.id = BEACON_TEMPLATE_CMD,
@ -1009,9 +1009,9 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
sizeof(beacon_cmd));
}
static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct sk_buff *beacon)
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct sk_buff *beacon)
{
if (WARN_ON(!beacon))
return -EINVAL;

View File

@ -1693,6 +1693,17 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct sk_buff *beacon);
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
struct sk_buff *beacon,
void *data, int len);
u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
struct ieee80211_vif *vif);
void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
__le32 *tim_index, __le32 *tim_size,
u8 *beacon, u32 frame_size);
void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,