forked from Minki/linux
mwifiex: add custom IE framework
1. support for setting custom IE from application hostapd etc. Custom IE addition using auto-indexing and Custom IE deletion using static indices (which are allocated during IE addition and stored in driver) are supported. 2. Separate file for handling IE related execution. Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Kiran Divekar <dkiran@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
e76268da22
commit
ede98bfa91
@ -30,6 +30,7 @@ mwifiex-y += join.o
|
||||
mwifiex-y += sta_ioctl.o
|
||||
mwifiex-y += sta_cmd.o
|
||||
mwifiex-y += uap_cmd.o
|
||||
mwifiex-y += ie.o
|
||||
mwifiex-y += sta_cmdresp.o
|
||||
mwifiex-y += sta_event.o
|
||||
mwifiex-y += sta_tx.o
|
||||
|
@ -94,6 +94,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
||||
#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF)))
|
||||
|
||||
#define UAP_BSS_PARAMS_I 0
|
||||
#define UAP_CUSTOM_IE_I 1
|
||||
#define MWIFIEX_AUTO_IDX_MASK 0xffff
|
||||
#define MWIFIEX_DELETE_MASK 0x0000
|
||||
|
||||
#define TLV_TYPE_UAP_SSID 0x0000
|
||||
|
||||
@ -1299,6 +1302,20 @@ struct host_cmd_ds_802_11_subsc_evt {
|
||||
__le16 events;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_ie {
|
||||
__le16 ie_index;
|
||||
__le16 mgmt_subtype_mask;
|
||||
__le16 ie_length;
|
||||
u8 ie_buffer[IEEE_MAX_IE_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define MAX_MGMT_IE_INDEX 16
|
||||
struct mwifiex_ie_list {
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_command {
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
|
149
drivers/net/wireless/mwifiex/ie.c
Normal file
149
drivers/net/wireless/mwifiex/ie.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Marvell Wireless LAN device driver: management IE handling- setting and
|
||||
* deleting IE.
|
||||
*
|
||||
* Copyright (C) 2012, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* This function checks if current IE index is used by any on other interface.
|
||||
* Return: -1: yes, current IE index is used by someone else.
|
||||
* 0: no, current IE index is NOT used by other interface.
|
||||
*/
|
||||
static int
|
||||
mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx)
|
||||
{
|
||||
int i;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_ie *ie;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
if (adapter->priv[i] != priv) {
|
||||
ie = &adapter->priv[i]->mgmt_ie[idx];
|
||||
if (ie->mgmt_subtype_mask && ie->ie_length)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get unused IE index. This index will be used for setting new IE */
|
||||
static int
|
||||
mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
|
||||
struct mwifiex_ie *ie, u16 *index)
|
||||
{
|
||||
u16 mask, len, i;
|
||||
|
||||
for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
|
||||
mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
|
||||
len = le16_to_cpu(priv->mgmt_ie[i].ie_length) +
|
||||
le16_to_cpu(ie->ie_length);
|
||||
|
||||
if (mask == MWIFIEX_AUTO_IDX_MASK)
|
||||
continue;
|
||||
|
||||
if (mask == subtype_mask) {
|
||||
if (len > IEEE_MAX_IE_SIZE)
|
||||
continue;
|
||||
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!priv->mgmt_ie[i].ie_length) {
|
||||
if (mwifiex_ie_index_used_by_other_intf(priv, i))
|
||||
continue;
|
||||
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This function prepares IE data buffer for command to be sent to FW */
|
||||
static int
|
||||
mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
|
||||
struct mwifiex_ie_list *ie_list)
|
||||
{
|
||||
u16 travel_len, index, mask;
|
||||
s16 input_len;
|
||||
struct mwifiex_ie *ie;
|
||||
u8 *tmp;
|
||||
|
||||
input_len = le16_to_cpu(ie_list->len);
|
||||
travel_len = sizeof(struct host_cmd_tlv);
|
||||
|
||||
ie_list->len = 0;
|
||||
|
||||
while (input_len > 0) {
|
||||
ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len);
|
||||
input_len -= le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE;
|
||||
travel_len += le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE;
|
||||
|
||||
index = le16_to_cpu(ie->ie_index);
|
||||
mask = le16_to_cpu(ie->mgmt_subtype_mask);
|
||||
|
||||
if (index == MWIFIEX_AUTO_IDX_MASK) {
|
||||
/* automatic addition */
|
||||
if (mwifiex_ie_get_autoidx(priv, mask, ie, &index))
|
||||
return -1;
|
||||
if (index == MWIFIEX_AUTO_IDX_MASK)
|
||||
return -1;
|
||||
|
||||
tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
|
||||
tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length);
|
||||
memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
|
||||
le16_add_cpu(&priv->mgmt_ie[index].ie_length,
|
||||
le16_to_cpu(ie->ie_length));
|
||||
priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
|
||||
priv->mgmt_ie[index].mgmt_subtype_mask =
|
||||
cpu_to_le16(mask);
|
||||
|
||||
ie->ie_index = cpu_to_le16(index);
|
||||
ie->ie_length = priv->mgmt_ie[index].ie_length;
|
||||
memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer,
|
||||
le16_to_cpu(priv->mgmt_ie[index].ie_length));
|
||||
} else {
|
||||
if (mask != MWIFIEX_DELETE_MASK)
|
||||
return -1;
|
||||
/*
|
||||
* Check if this index is being used on any
|
||||
* other interface.
|
||||
*/
|
||||
if (mwifiex_ie_index_used_by_other_intf(priv, index))
|
||||
return -1;
|
||||
|
||||
ie->ie_length = 0;
|
||||
memcpy(&priv->mgmt_ie[index], ie,
|
||||
sizeof(struct mwifiex_ie));
|
||||
}
|
||||
|
||||
le16_add_cpu(&ie_list->len,
|
||||
le16_to_cpu(priv->mgmt_ie[index].ie_length) +
|
||||
MWIFIEX_IE_HDR_SIZE);
|
||||
}
|
||||
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
|
||||
return mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
|
||||
HostCmd_ACT_GEN_SET,
|
||||
UAP_CUSTOM_IE_I, ie_list);
|
||||
|
||||
return 0;
|
||||
}
|
@ -279,6 +279,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
|
||||
memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
|
||||
adapter->arp_filter_size = 0;
|
||||
adapter->channel_type = NL80211_CHAN_HT20;
|
||||
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -299,6 +299,8 @@ struct mwifiex_ds_read_eeprom {
|
||||
|
||||
#define IEEE_MAX_IE_SIZE 256
|
||||
|
||||
#define MWIFIEX_IE_HDR_SIZE (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE)
|
||||
|
||||
struct mwifiex_ds_misc_gen_ie {
|
||||
u32 type;
|
||||
u32 len;
|
||||
|
@ -640,6 +640,8 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
|
||||
priv->current_key_index = 0;
|
||||
priv->media_connected = false;
|
||||
memset(&priv->nick_name, 0, sizeof(priv->nick_name));
|
||||
memset(priv->mgmt_ie, 0,
|
||||
sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
|
||||
priv->num_tx_timeout = 0;
|
||||
memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
|
||||
}
|
||||
|
@ -477,6 +477,7 @@ struct mwifiex_private {
|
||||
s32 cqm_rssi_thold;
|
||||
u32 cqm_rssi_hyst;
|
||||
u8 subsc_evt_rssi_state;
|
||||
struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
|
||||
};
|
||||
|
||||
enum mwifiex_ba_status {
|
||||
@ -680,6 +681,7 @@ struct mwifiex_adapter {
|
||||
spinlock_t queue_lock; /* lock for tx queues */
|
||||
struct completion fw_load;
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
u16 max_mgmt_ie_index;
|
||||
};
|
||||
|
||||
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
|
||||
|
@ -315,6 +315,26 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function parses custom IEs from IE list and prepares command buffer */
|
||||
static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
|
||||
{
|
||||
struct mwifiex_ie_list *ap_ie = cmd_buf;
|
||||
struct host_cmd_tlv *tlv_ie = (struct host_cmd_tlv *)tlv;
|
||||
|
||||
if (!ap_ie || !ap_ie->len || !ap_ie->ie_list)
|
||||
return -1;
|
||||
|
||||
*ie_size += le16_to_cpu(ap_ie->len) + sizeof(struct host_cmd_tlv);
|
||||
|
||||
tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
|
||||
tlv_ie->len = ap_ie->len;
|
||||
tlv += sizeof(struct host_cmd_tlv);
|
||||
|
||||
memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse AP config structure and prepare TLV based command structure
|
||||
* to be sent to FW for uAP configuration
|
||||
*/
|
||||
@ -323,7 +343,7 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
|
||||
u32 type, void *cmd_buf)
|
||||
{
|
||||
u8 *tlv;
|
||||
u16 cmd_size, param_size;
|
||||
u16 cmd_size, param_size, ie_size;
|
||||
struct host_cmd_ds_sys_config *sys_cfg;
|
||||
|
||||
cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
|
||||
@ -339,6 +359,12 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
|
||||
return -1;
|
||||
cmd->size = cpu_to_le16(param_size);
|
||||
break;
|
||||
case UAP_CUSTOM_IE_I:
|
||||
ie_size = cmd_size;
|
||||
if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
|
||||
return -1;
|
||||
cmd->size = cpu_to_le16(ie_size);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user