Search Linux Wireless

Re: [PATCH v4 1/1] wifi: mwifiex: added code to support host mlme.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello David,

For the next v5 please be sure to properly thread the series as
git-send-email would normally do (if you are going to have a cover
letter) or even better just add the changelog after the commit
message (separated with ---).


On Tue, Aug 15, 2023 at 07:09:25AM +0000, David Lin wrote:
> 1. For station mode first.
> 2. This feature is a must for WPA3.
> 3. Firmware key api version 2 is needed for this feature.
> 4. The code is only enabled and tested with IW416.
> 5. This feature is disabled for other chips.

I believe that this commit message should be rewritten, at least to me
this was confusing to read at first.

Maybe something like that?

```
wifi: mwifiex: add MLME support

Add host based MLME support for station mode to enable WPA3
functionalities.

This feature requires a firmware with key API major version 2 and is
currently enabled and tested only for IW416.
```

Was this patch tested to be wholly working with WPA3 or you expect
follow up patches for proper enabling WPA3 support?


> Signed-off-by: David Lin <yu-hao.lin@xxxxxxx>
> ---
>  .../net/wireless/marvell/mwifiex/cfg80211.c   | 327 ++++++++++++++++++
>  drivers/net/wireless/marvell/mwifiex/cmdevt.c |  14 +-
>  drivers/net/wireless/marvell/mwifiex/decl.h   |  12 +
>  drivers/net/wireless/marvell/mwifiex/fw.h     |  15 +
>  drivers/net/wireless/marvell/mwifiex/init.c   |   3 +
>  drivers/net/wireless/marvell/mwifiex/join.c   |  64 +++-
>  drivers/net/wireless/marvell/mwifiex/main.h   |  10 +
>  drivers/net/wireless/marvell/mwifiex/scan.c   |   6 +
>  drivers/net/wireless/marvell/mwifiex/sdio.c   |  13 +
>  drivers/net/wireless/marvell/mwifiex/sdio.h   |   2 +
>  .../net/wireless/marvell/mwifiex/sta_event.c  |  18 +-
>  .../net/wireless/marvell/mwifiex/sta_ioctl.c  |   3 +-
>  drivers/net/wireless/marvell/mwifiex/sta_tx.c |  10 +-
>  .../net/wireless/marvell/mwifiex/uap_cmd.c    |  26 ++
>  drivers/net/wireless/marvell/mwifiex/util.c   |  73 ++++
>  15 files changed, 583 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> index ba4e29713a8c..605952ee0aa9 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> @@ -57,6 +57,31 @@ ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {
>  	.beacon_int_infra_match = true,
>  };
>  
> +struct mwifiex_ieee80211_mgmt {
What's the reasoning for having this in cfg80211.c?
Am I wrong or most of this binary structures are defined in fw.h?

> +	__le16 frame_control;
> +	__le16 duration;
> +	u8 da[ETH_ALEN];
> +	u8 sa[ETH_ALEN];
> +	u8 bssid[ETH_ALEN];
> +	__le16 seq_ctrl;
> +	u8 addr4[ETH_ALEN];
> +	union {
> +		struct {
> +			__le16 auth_alg;
> +			__le16 auth_transaction;
> +			__le16 status_code;
> +			/* possibly followed by Challenge text */
> +			u8 variable[];
> +		} __packed auth;
> +		struct {
> +			__le16 capab_info;
> +			__le16 listen_interval;
> +			/* followed by SSID and Supported rates */
> +			u8 variable[];
> +		} __packed assoc_req;
> +	} u;
> +} __pack;

__packed

>  /*
>   * This function maps the nl802.11 channel type into driver channel type.
>   *
> @@ -268,6 +293,8 @@ mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
>  
>  	if (mask != priv->mgmt_frame_mask) {
>  		priv->mgmt_frame_mask = mask;
> +		if (priv->host_mlme_reg)
> +			priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;
>  		mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
>  				 HostCmd_ACT_GEN_SET, 0,
>  				 &priv->mgmt_frame_mask, false);
> @@ -848,6 +875,7 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
>  	struct mwifiex_adapter *adapter = priv->adapter;
>  	unsigned long flags;
>  
> +	priv->host_mlme_reg = false;
>  	priv->mgmt_frame_mask = 0;
>  	if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
>  			     HostCmd_ACT_GEN_SET, 0,
> @@ -4201,6 +4229,292 @@ mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
>  	return ret;
>  }
>  
> +static int
> +mwifiex_cfg80211_authenticate(struct wiphy *wiphy,
> +			      struct net_device *dev,
> +			      struct cfg80211_auth_request *req)
> +{
> +	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
> +	struct mwifiex_adapter *adapter = priv->adapter;
> +	struct sk_buff *skb;
> +	u16 pkt_len, auth_alg;
> +	int ret;
> +	struct mwifiex_ieee80211_mgmt *mgmt;
> +	struct mwifiex_txinfo *tx_info;
> +	u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
> +	u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
> +	u8 trans = 1, status_code = 0;
> +	u8 *varptr;
> +
> +	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
> +		mwifiex_dbg(priv->adapter, ERROR, "Interface role is AP\n");
> +		return -EFAULT;
> +	}
> +
> +	if (priv->wdev.iftype != NL80211_IFTYPE_STATION) {
> +		mwifiex_dbg(priv->adapter, ERROR,
> +			    "Interface type is not correct (type %d)\n",
> +			    priv->wdev.iftype);
> +		return -EINVAL;
> +	}
> +
> +	if (priv->auth_alg != WLAN_AUTH_SAE &&
> +	    (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {
> +		mwifiex_dbg(priv->adapter, ERROR, "Pending auth on going\n");
> +		return -EBUSY;
> +	}
> +
> +	if (!priv->host_mlme_reg) {
> +		priv->host_mlme_reg = true;
> +		priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;
> +		mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
> +				 HostCmd_ACT_GEN_SET, 0,
> +				 &priv->mgmt_frame_mask, false);
> +	}
> +
> +	switch (req->auth_type) {
> +	case NL80211_AUTHTYPE_OPEN_SYSTEM:
> +		auth_alg = WLAN_AUTH_OPEN;
> +		break;
> +	case NL80211_AUTHTYPE_SHARED_KEY:
> +		auth_alg = WLAN_AUTH_SHARED_KEY;
> +		break;
> +	case NL80211_AUTHTYPE_FT:
> +		auth_alg = WLAN_AUTH_FT;
> +		break;
> +	case NL80211_AUTHTYPE_NETWORK_EAP:
> +		auth_alg = WLAN_AUTH_LEAP;
> +		break;
> +	case NL80211_AUTHTYPE_SAE:
> +		auth_alg = WLAN_AUTH_SAE;
> +		break;
> +	default:
> +		mwifiex_dbg(priv->adapter, ERROR,
> +			    "unsupported auth type=%d\n", req->auth_type);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	if (!priv->auth_flag) {
> +		ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET,
> +						 req->bss->channel,
> +						 AUTH_TX_DEFAULT_WAIT_TIME);
> +
> +		if (!ret) {
> +			priv->roc_cfg.cookie = get_random_u32() | 1;
> +			priv->roc_cfg.chan = *req->bss->channel;
> +		}
> +	}
> +
> +	priv->sec_info.authentication_mode = auth_alg;
> +
> +	mwifiex_cancel_scan(adapter);
> +
> +	pkt_len = (u16)req->ie_len + req->auth_data_len +
> +		     MWIFIEX_MGMT_HEADER_LEN + MWIFIEX_AUTH_BODY_LEN;
> +	if (req->auth_data_len >= 4)
> +		pkt_len -= 4;
> +
> +	skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
> +			    MWIFIEX_MGMT_FRAME_HEADER_SIZE +
> +			    pkt_len + sizeof(pkt_len));
> +	if (!skb) {
> +		mwifiex_dbg(priv->adapter, ERROR,
> +			    "allocate skb failed for management frame\n");
> +		return -ENOMEM;
> +	}
> +
> +	tx_info = MWIFIEX_SKB_TXCB(skb);
> +	memset(tx_info, 0, sizeof(*tx_info));
> +	tx_info->bss_num = priv->bss_num;
> +	tx_info->bss_type = priv->bss_type;
> +	tx_info->pkt_len = pkt_len;
> +
> +	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
> +		    MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
> +	memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
> +	memcpy(skb_push(skb, sizeof(tx_control)),
> +	       &tx_control, sizeof(tx_control));
> +	memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
> +
> +	mgmt = (struct mwifiex_ieee80211_mgmt *)skb_put(skb, pkt_len);
> +	memset(mgmt, 0, pkt_len);
> +	mgmt->frame_control =
> +		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
> +	memcpy(mgmt->da, req->bss->bssid, ETH_ALEN);
> +	memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
> +	memcpy(mgmt->bssid, req->bss->bssid, ETH_ALEN);
> +	memcpy(mgmt->addr4, addr, ETH_ALEN);
> +
> +	if (req->auth_data_len >= 4) {
> +		if (req->auth_type == NL80211_AUTHTYPE_SAE) {
> +			__le16 *pos = (__le16 *)req->auth_data;
> +
> +			trans = le16_to_cpu(pos[0]);
> +			status_code = le16_to_cpu(pos[1]);
> +		}
> +		memcpy((u8 *)(&mgmt->u.auth.variable), req->auth_data + 4,
> +		       req->auth_data_len - 4);
> +		varptr = (u8 *)&mgmt->u.auth.variable +
> +			 (req->auth_data_len - 4);
> +	}
> +
> +	mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
> +	mgmt->u.auth.auth_transaction = trans;
> +	mgmt->u.auth.status_code = status_code;
> +
> +	if (req->ie && req->ie_len) {
> +		if (!varptr)
> +			varptr = (u8 *)&mgmt->u.auth.variable;
> +		memcpy((u8 *)varptr, req->ie, req->ie_len);
> +	}
> +
> +	priv->auth_flag = HOST_MLME_AUTH_PENDING;
> +	priv->auth_alg = auth_alg;
> +
> +	skb->priority = WMM_HIGHEST_PRIORITY;
> +	__net_timestamp(skb);
> +
> +	mwifiex_dbg(priv->adapter, MSG,
> +		    "auth: send authentication to %pM\n", req->bss->bssid);
> +
> +	mwifiex_queue_tx_pkt(priv, skb);
> +
> +	return 0;
> +}
> +
> +static int
> +mwifiex_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
> +			   struct cfg80211_assoc_request *req)
> +{
> +	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
> +	struct mwifiex_adapter *adapter = priv->adapter;
> +	int ret;
> +	struct cfg80211_ssid req_ssid;
> +	const u8 *ssid_ie;
> +	struct cfg80211_rx_assoc_resp assoc_resp = {
> +		.uapsd_queues = -1,
> +	};
> +
> +	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
> +		mwifiex_dbg(adapter, ERROR,
> +			    "%s: reject infra assoc request in non-STA role\n",
> +			    dev->name);
> +		return -EINVAL;
> +	}
> +
> +	if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
> +	    test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
> +		mwifiex_dbg(adapter, ERROR,
> +			    "%s: Ignore association.\t"
> +			    "Card removed or FW in bad state\n",
> +			    dev->name);
> +		return -EFAULT;
> +	}
> +
> +	if (priv->auth_alg == WLAN_AUTH_SAE)
> +		priv->auth_flag = HOST_MLME_AUTH_DONE;
> +
> +	if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE))
> +		return -EBUSY;
> +
> +	if (!mwifiex_stop_bg_scan(priv))
> +		cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);
> +
> +	memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
> +	rcu_read_lock();
> +	ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
> +
> +	if (!ssid_ie)
> +		goto ssid_err;
> +
> +	req_ssid.ssid_len = ssid_ie[1];
> +	if (req_ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
> +		mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
> +		goto ssid_err;
> +	}
> +
> +	memcpy(req_ssid.ssid, ssid_ie + 2, req_ssid.ssid_len);
> +	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
> +		mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
> +		goto ssid_err;
> +	}
> +	rcu_read_unlock();
> +
> +	/* As this is new association, clear locally stored
> +	 * keys and security related flags
> +	 */
> +	priv->sec_info.wpa_enabled = false;
> +	priv->sec_info.wpa2_enabled = false;
> +	priv->wep_key_curr_index = 0;
> +	priv->sec_info.encryption_mode = 0;
> +	priv->sec_info.is_authtype_auto = 0;
> +	ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
> +
> +	if (req->crypto.n_ciphers_pairwise)
> +		priv->sec_info.encryption_mode =
> +			req->crypto.ciphers_pairwise[0];
> +
> +	if (req->crypto.cipher_group)
> +		priv->sec_info.encryption_mode = req->crypto.cipher_group;
> +
> +	if (req->ie)
> +		ret = mwifiex_set_gen_ie(priv, req->ie, req->ie_len);
> +
> +	memcpy(priv->cfg_bssid, req->bss->bssid, ETH_ALEN);
> +
> +	mwifiex_dbg(priv->adapter, MSG,
> +		    "assoc: send association to %pM\n", req->bss->bssid);
> +
> +	cfg80211_ref_bss(priv->adapter->wiphy, req->bss);
> +
> +	ret = mwifiex_bss_start(priv, req->bss, &req_ssid);
> +
> +	if (!ret) {
> +		assoc_resp.links[0].bss = priv->attempted_bss_desc->bss;
> +		assoc_resp.buf = priv->assoc_rsp_buf;
> +		assoc_resp.len = priv->assoc_rsp_size;
> +		cfg80211_rx_assoc_resp(priv->netdev,
> +				       &assoc_resp);
> +	} else {
> +		priv->auth_flag = 0;
> +		priv->auth_alg = 0xFFFF;
worth a define? you have it multiple times.

> +		eth_zero_addr(priv->cfg_bssid);
> +	}
> +
> +	cfg80211_put_bss(priv->adapter->wiphy, req->bss);
> +
> +	return 0;
> +
> +ssid_err:
> +
> +	rcu_read_unlock();
> +	return -EFAULT;
> +}
> +
> +static int
> +mwifiex_cfg80211_deauthenticate(struct wiphy *wiphy,
> +				struct net_device *dev,
> +				struct cfg80211_deauth_request *req)
> +{
> +	return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);
> +}
> +
> +static int
> +mwifiex_cfg80211_disassociate(struct wiphy *wiphy,
> +			      struct net_device *dev,
> +			      struct cfg80211_disassoc_request *req)
> +{
> +	return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);
> +}
> +
> +static int
> +mwifiex_cfg80211_probe_client(struct wiphy *wiphy,
> +			      struct net_device *dev, const u8 *peer,
> +			      u64 *cookie)
> +{
> +	return -1;
> +}
> +
>  /* station cfg80211 operations */
>  static struct cfg80211_ops mwifiex_cfg80211_ops = {
>  	.add_virtual_intf = mwifiex_add_virtual_intf,
> @@ -4346,6 +4660,16 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
>  			    "%s: creating new wiphy\n", __func__);
>  		return -ENOMEM;
>  	}
> +	if (adapter->host_mlme) {
I think this variable should be renamed to host_mlme_enabled or
mlme_enabled, not sure what's the best.

> +		mwifiex_cfg80211_ops.auth = mwifiex_cfg80211_authenticate;
> +		mwifiex_cfg80211_ops.assoc = mwifiex_cfg80211_associate;
> +		mwifiex_cfg80211_ops.deauth = mwifiex_cfg80211_deauthenticate;
> +		mwifiex_cfg80211_ops.disassoc = mwifiex_cfg80211_disassociate;
> +		mwifiex_cfg80211_ops.disconnect = NULL;
> +		mwifiex_cfg80211_ops.connect = NULL;
> +		mwifiex_cfg80211_ops.probe_client =
> +			mwifiex_cfg80211_probe_client;
do you need defining this to a function that just return -1? Is this
required?

> +	}
>  	wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
>  	wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
>  	wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
> @@ -4427,6 +4751,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
>  			   NL80211_FEATURE_LOW_PRIORITY_SCAN |
>  			   NL80211_FEATURE_NEED_OBSS_SCAN;
>  
> +	if (adapter->host_mlme)
> +		wiphy->features |= NL80211_FEATURE_SAE;
> +
>  	if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
>  		wiphy->features |= NL80211_FEATURE_HT_IBSS;
>  
> diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> index 3756aa247e77..311af5f40c3e 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> @@ -654,7 +654,7 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
>  	if (ret) {
>  		mwifiex_dbg(adapter, ERROR,
>  			    "PREP_CMD: cmd %#x preparation failed\n",
> -			cmd_no);
> +			    cmd_no);
unrelated change

>  		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
>  		return -1;
>  	}
> @@ -1477,6 +1477,17 @@ int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
>  	return 0;
>  }
>  
> +static void mwifiex_check_key_api_ver(struct mwifiex_adapter *adapter)
> +{
> +	if (adapter->host_mlme) {
> +		if (adapter->key_api_major_ver != KEY_API_VER_MAJOR_V2)
> +			adapter->host_mlme = false;
> +		mwifiex_dbg(adapter, MSG, "host_mlme: %s, key_api: %d\n",
> +			    adapter->host_mlme ? "enable" : "disable",
> +			    adapter->key_api_major_ver);
> +	}
> +}
> +
>  /*
>   * This function handles the command response of get hardware
>   * specifications.
> @@ -1586,6 +1597,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
>  						    "key_api v%d.%d\n",
>  						    adapter->key_api_major_ver,
>  						    adapter->key_api_minor_ver);
> +					mwifiex_check_key_api_ver(adapter);
for other functionalities you have everything at the end of
mwifiex_ret_get_hw_spec()

why not doing the same here? Just do the check in a similar way as done
for scan_chan_gap_enabled.



>  					break;
>  				case FW_API_VER_ID:
>  					adapter->fw_api_ver =
> diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h
> index 88648c062713..385b5119f2ee 100644
> --- a/drivers/net/wireless/marvell/mwifiex/decl.h
> +++ b/drivers/net/wireless/marvell/mwifiex/decl.h
> @@ -24,6 +24,18 @@
>  #define MWIFIEX_RX_HEADROOM	    64
>  #define MAX_TXPD_SZ		    32
>  #define INTF_HDR_ALIGN		     4
> +/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl + addr4 */
> +#define MWIFIEX_MGMT_HEADER_LEN   (2 + 2 + 6 + 6 + 6 + 2 + 6)
> +/* 6   = auth_alg + auth_transaction + auth_status */
> +#define MWIFIEX_AUTH_BODY_LEN     6

those comments and magic number are quite confusing, in other part of
the code (just a few lines after), proper defines are used. Maybe doing
the same here would help and we could get rid of the comment?

> +
> +#define HOST_MLME_AUTH_PENDING    BIT(0)
> +#define HOST_MLME_AUTH_DONE       BIT(1)
> +
> +#define HOST_MLME_MGMT_MASK       (BIT(IEEE80211_STYPE_AUTH >> 4) | \
> +				   BIT(IEEE80211_STYPE_DEAUTH >> 4) | \
> +				   BIT(IEEE80211_STYPE_DISASSOC >> 4))
> +#define AUTH_TX_DEFAULT_WAIT_TIME 2400
>  
>  #define MWIFIEX_MIN_DATA_HEADER_LEN (MWIFIEX_DMA_ALIGN_SZ + INTF_HDR_ALIGN + \
>  				     MAX_TXPD_SZ)
> diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
> index f2168fac95ed..5e6bda38f22c 100644
> --- a/drivers/net/wireless/marvell/mwifiex/fw.h
> +++ b/drivers/net/wireless/marvell/mwifiex/fw.h
> @@ -209,6 +209,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
>  #define TLV_TYPE_RANDOM_MAC         (PROPRIETARY_TLV_BASE_ID + 236)
>  #define TLV_TYPE_CHAN_ATTR_CFG      (PROPRIETARY_TLV_BASE_ID + 237)
>  #define TLV_TYPE_MAX_CONN           (PROPRIETARY_TLV_BASE_ID + 279)
> +#define TLV_TYPE_HOST_MLME          (PROPRIETARY_TLV_BASE_ID + 307)
> +#define TLV_TYPE_SAE_PWE_MODE       (PROPRIETARY_TLV_BASE_ID + 339)
> +
>  
>  #define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
>  
> @@ -802,6 +805,11 @@ struct mwifiex_ie_types_ssid_param_set {
>  	u8 ssid[];
>  } __packed;
>  
> +struct mwifiex_ie_types_host_mlme {
> +	struct mwifiex_ie_types_header header;
> +	u8 host_mlme;
> +} __packed;
> +
>  struct mwifiex_ie_types_num_probes {
>  	struct mwifiex_ie_types_header header;
>  	__le16 num_probes;
> @@ -905,6 +913,13 @@ struct mwifiex_ie_types_tdls_idle_timeout {
>  	__le16 value;
>  } __packed;
>  
> +#define MWIFIEX_AUTHTYPE_SAE 6
> +
> +struct mwifiex_ie_types_sae_pwe_mode {
> +	struct mwifiex_ie_types_header header;
> +	u8 pwe[];
> +} __packed;
> +
>  struct mwifiex_ie_types_rsn_param_set {
>  	struct mwifiex_ie_types_header header;
>  	u8 rsn_ie[];
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index 7dddb4b5dea1..ca23be8d3ac3 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -81,6 +81,9 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
>  	priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
>  	priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
>  
> +	priv->auth_flag = 0;
> +	priv->auth_alg = 0xFFFF;
> +
>  	priv->sec_info.wep_enabled = 0;
>  	priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
>  	priv->sec_info.encryption_mode = 0;
> diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c
> index a6e254a1185c..ef7cc40c3ba4 100644
> --- a/drivers/net/wireless/marvell/mwifiex/join.c
> +++ b/drivers/net/wireless/marvell/mwifiex/join.c
> @@ -382,7 +382,9 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
>  	struct mwifiex_ie_types_ss_param_set *ss_tlv;
>  	struct mwifiex_ie_types_rates_param_set *rates_tlv;
>  	struct mwifiex_ie_types_auth_type *auth_tlv;
> +	struct mwifiex_ie_types_sae_pwe_mode *sae_pwe_tlv;
>  	struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
> +	struct mwifiex_ie_types_host_mlme *host_mlme_tlv;
>  	u8 rates[MWIFIEX_SUPPORTED_RATES];
>  	u32 rates_size;
>  	u16 tmp_cap;
> @@ -448,7 +450,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
>  	mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n",
>  		    rates_size);
>  
> -	/* Add the Authentication type to be used for Auth frames */
> +	/* Add the Authentication type */
>  	auth_tlv = (struct mwifiex_ie_types_auth_type *) pos;
>  	auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
>  	auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type));
> @@ -460,6 +462,24 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
>  
>  	pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len);
>  
> +	if (priv->sec_info.authentication_mode == WLAN_AUTH_SAE) {
> +		auth_tlv->auth_type = cpu_to_le16(MWIFIEX_AUTHTYPE_SAE);
> +		if (bss_desc->bcn_rsnx_ie &&
> +		    bss_desc->bcn_rsnx_ie->ieee_hdr.len &&
> +		    (bss_desc->bcn_rsnx_ie->data[0] &
> +		    WLAN_RSNX_CAPA_SAE_H2E)) {
> +			sae_pwe_tlv =
> +				(struct mwifiex_ie_types_sae_pwe_mode *)pos;
> +			sae_pwe_tlv->header.type =
> +				cpu_to_le16(TLV_TYPE_SAE_PWE_MODE);
> +			sae_pwe_tlv->header.len =
> +				cpu_to_le16(sizeof(sae_pwe_tlv->pwe[0]));
> +			sae_pwe_tlv->pwe[0] = bss_desc->bcn_rsnx_ie->data[0];
> +			pos += sizeof(sae_pwe_tlv->header) +
> +				sizeof(sae_pwe_tlv->pwe[0]);
> +		}
> +	}
> +
>  	if (IS_SUPPORT_MULTI_BANDS(priv->adapter) &&
>  	    !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
>  	    (!bss_desc->disable_11n) &&
> @@ -491,6 +511,16 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
>  			sizeof(struct mwifiex_chan_scan_param_set);
>  	}
>  
> +	if (priv->adapter->host_mlme) {
> +		host_mlme_tlv = (struct mwifiex_ie_types_host_mlme *)pos;
> +		host_mlme_tlv->header.type = cpu_to_le16(TLV_TYPE_HOST_MLME);
> +		host_mlme_tlv->header.len =
> +			cpu_to_le16(sizeof(host_mlme_tlv->host_mlme));
> +		host_mlme_tlv->host_mlme = 1;
> +		pos += sizeof(host_mlme_tlv->header) +
> +			sizeof(host_mlme_tlv->host_mlme);
> +	}
> +
>  	if (!priv->wps.session_enable) {
>  		if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
>  			rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
> @@ -634,6 +664,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
>  	u16 cap_info, status_code, aid;
>  	const u8 *ie_ptr;
>  	struct ieee80211_ht_operation *assoc_resp_ht_oper;
> +	struct ieee80211_mgmt *hdr;
>  
>  	if (!priv->attempted_bss_desc) {
>  		mwifiex_dbg(priv->adapter, ERROR,
> @@ -641,7 +672,19 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
>  		goto done;
>  	}
>  
> -	assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;
> +	if (adapter->host_mlme) {
> +		hdr = (struct ieee80211_mgmt *)&resp->params;
> +		if (!memcmp(hdr->bssid,
> +			    priv->attempted_bss_desc->mac_address,
> +			    ETH_ALEN))
> +			assoc_rsp = (struct ieee_types_assoc_rsp *)
> +				&hdr->u.assoc_resp;
> +		else
> +			assoc_rsp =
> +				(struct ieee_types_assoc_rsp *)&resp->params;
> +	} else {
> +		assoc_rsp = (struct ieee_types_assoc_rsp *)&resp->params;
> +	}
>  
>  	cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap);
>  	status_code = le16_to_cpu(assoc_rsp->status_code);
> @@ -778,7 +821,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
>  
>  	priv->adapter->dbg.num_cmd_assoc_success++;
>  
> -	mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n");
> +	mwifiex_dbg(priv->adapter, MSG, "assoc: associated with %pM\n",
> +		    priv->attempted_bss_desc->mac_address);
>  
>  	/* Add the ra_list here for infra mode as there will be only 1 ra
>  	   always */
> @@ -1491,6 +1535,20 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
>  	if (!priv->media_connected)
>  		return 0;
>  
> +	if (priv->adapter->host_mlme) {
> +		priv->auth_flag = 0;
> +		priv->auth_alg = 0xFFFF;
> +		priv->host_mlme_reg = false;
> +		priv->mgmt_frame_mask = 0;
> +		if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
> +				     HostCmd_ACT_GEN_SET, 0,
> +				     &priv->mgmt_frame_mask, false)) {
> +			mwifiex_dbg(priv->adapter, ERROR,
> +				    "could not unregister mgmt frame rx\n");
> +			return -1;
> +		}
> +	}
> +
>  	switch (priv->bss_mode) {
>  	case NL80211_IFTYPE_STATION:
>  	case NL80211_IFTYPE_P2P_CLIENT:
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
> index b95886e1413e..6d0b9fcfe07c 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -384,6 +384,7 @@ struct ieee_types_aid {
>  
>  struct mwifiex_bssdescriptor {
>  	u8 mac_address[ETH_ALEN];
> +	struct cfg80211_bss *bss;
>  	struct cfg80211_ssid ssid;
>  	u32 privacy;
>  	s32 rssi;
> @@ -426,6 +427,8 @@ struct mwifiex_bssdescriptor {
>  	u16 wpa_offset;
>  	struct ieee_types_generic *bcn_rsn_ie;
>  	u16 rsn_offset;
> +	struct ieee_types_generic *bcn_rsnx_ie;
> +	u16 rsnx_offset;
>  	struct ieee_types_generic *bcn_wapi_ie;
>  	u16 wapi_offset;
>  	u8 *beacon_buf;
> @@ -536,6 +539,8 @@ struct mwifiex_private {
>  	u8 bss_priority;
>  	u8 bss_num;
>  	u8 bss_started;
> +	u8 auth_flag;
> +	u16 auth_alg;
>  	u8 frame_type;
>  	u8 curr_addr[ETH_ALEN];
>  	u8 media_connected;
> @@ -658,6 +663,7 @@ struct mwifiex_private {
>  	u16 gen_idx;
>  	u8 ap_11n_enabled;
>  	u8 ap_11ac_enabled;
> +	bool host_mlme_reg;
>  	u32 mgmt_frame_mask;
>  	struct mwifiex_roc_cfg roc_cfg;
>  	bool scan_aborting;
> @@ -1012,6 +1018,7 @@ struct mwifiex_adapter {
>  	bool is_up;
>  
>  	bool ext_scan;
> +	bool host_mlme;
>  	u8 fw_api_ver;
>  	u8 key_api_major_ver, key_api_minor_ver;
>  	u8 max_p2p_conn, max_sta_conn;
> @@ -1077,6 +1084,9 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
>  int mwifiex_uap_recv_packet(struct mwifiex_private *priv,
>  			    struct sk_buff *skb);
>  
> +void mwifiex_host_mlme_disconnect(struct mwifiex_private *priv,
> +				  u16 reason_code, u8 *sa);
> +
Remove? Not used

>  int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
>  				struct sk_buff *skb);
>  
> diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
> index 644b1e134b01..27eb9a073666 100644
> --- a/drivers/net/wireless/marvell/mwifiex/scan.c
> +++ b/drivers/net/wireless/marvell/mwifiex/scan.c
> @@ -1388,6 +1388,12 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
>  			bss_entry->rsn_offset = (u16) (current_ptr -
>  							bss_entry->beacon_buf);
>  			break;
> +		case WLAN_EID_RSNX:
> +			bss_entry->bcn_rsnx_ie =
> +				(struct ieee_types_generic *)current_ptr;
> +			bss_entry->rsnx_offset =
> +				(u16)(current_ptr - bss_entry->beacon_buf);
> +			break;
>  		case WLAN_EID_BSS_AC_ACCESS_DELAY:
>  			bss_entry->bcn_wapi_ie =
>  				(struct ieee_types_generic *) current_ptr;
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
> index a24bd40dd41a..6ba0339ccc65 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> @@ -331,6 +331,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
>  	.can_dump_fw = false,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = false,
> +	.host_mlme = false,
what about the PCIe devices? nothing needed there?

>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
> @@ -346,6 +347,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
>  	.can_dump_fw = false,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
> @@ -361,6 +363,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
>  	.can_dump_fw = false,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
> @@ -376,6 +379,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
>  	.can_dump_fw = true,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8977 = {
> @@ -392,6 +396,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8977 = {
>  	.fw_dump_enh = true,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8978 = {
> @@ -408,6 +413,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8978 = {
>  	.fw_dump_enh = true,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = true,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
> @@ -425,6 +431,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
>  	.fw_dump_enh = true,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
> @@ -440,6 +447,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
>  	.can_dump_fw = false,
>  	.can_auto_tdls = true,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8987 = {
> @@ -456,6 +464,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8987 = {
>  	.fw_dump_enh = true,
>  	.can_auto_tdls = true,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = {
> @@ -471,6 +480,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = {
>  	.can_dump_fw = false,
>  	.can_auto_tdls = false,
>  	.can_ext_scan = true,
> +	.host_mlme = false,
>  };
>  
>  static struct memory_type_mapping generic_mem_type_map[] = {
> @@ -563,6 +573,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
>  		card->fw_dump_enh = data->fw_dump_enh;
>  		card->can_auto_tdls = data->can_auto_tdls;
>  		card->can_ext_scan = data->can_ext_scan;
> +		card->host_mlme = data->host_mlme;
>  		INIT_WORK(&card->work, mwifiex_sdio_work);
>  	}
>  
> @@ -2493,6 +2504,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
>  		adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
>  	}
>  
> +	adapter->host_mlme = card->host_mlme;
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
> index ae94c172310f..d2da8c45a9be 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.h
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
> @@ -258,6 +258,7 @@ struct sdio_mmc_card {
>  	bool fw_dump_enh;
>  	bool can_auto_tdls;
>  	bool can_ext_scan;
> +	bool host_mlme;
>  
>  	struct mwifiex_sdio_mpa_tx mpa_tx;
>  	struct mwifiex_sdio_mpa_rx mpa_rx;
> @@ -281,6 +282,7 @@ struct mwifiex_sdio_device {
>  	bool fw_dump_enh;
>  	bool can_auto_tdls;
>  	bool can_ext_scan;
> +	bool host_mlme;
>  };
>  
>  /*
> diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
> index df9cdd10a494..69426ddd9c3a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
> @@ -135,6 +135,9 @@ void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code,
>  
>  	priv->media_connected = false;
>  
> +	priv->auth_flag = 0;
> +	priv->auth_alg = 0xFFFF;
> +
>  	priv->scan_block = false;
>  	priv->port_open = false;
>  
> @@ -999,10 +1002,17 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
>  	case EVENT_REMAIN_ON_CHAN_EXPIRED:
>  		mwifiex_dbg(adapter, EVENT,
>  			    "event: Remain on channel expired\n");
> -		cfg80211_remain_on_channel_expired(&priv->wdev,
> -						   priv->roc_cfg.cookie,
> -						   &priv->roc_cfg.chan,
> -						   GFP_ATOMIC);
> +
> +		if (adapter->host_mlme &&
> +		    (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {
> +			priv->auth_flag = 0;
> +			priv->auth_alg = 0xFFFF;
> +		} else {
> +			cfg80211_remain_on_channel_expired(&priv->wdev,
> +							   priv->roc_cfg.cookie,
> +							   &priv->roc_cfg.chan,
> +							   GFP_ATOMIC);
> +		}
>  
>  		memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
>  
> diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
> index a2ad2b53f016..046541713318 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
> @@ -136,6 +136,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
>  	const struct cfg80211_bss_ies *ies;
>  
>  	rcu_read_lock();
> +	bss_desc->bss = bss;
>  	ies = rcu_dereference(bss->ies);
>  	beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
>  	beacon_ie_len = ies->len;
> @@ -339,7 +340,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
>  			ret = mwifiex_associate(priv, bss_desc);
>  		}
>  
> -		if (bss)
> +		if (bss && !priv->adapter->host_mlme)
>  			cfg80211_put_bss(priv->adapter->wiphy, bss);
>  	} else {
>  		/* Adhoc mode */
> diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
> index 13c0e67ededf..6aed6a334d15 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
> @@ -36,7 +36,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
>  	struct txpd *local_tx_pd;
>  	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
>  	unsigned int pad;
> -	u16 pkt_type, pkt_offset;
> +	u16 pkt_type, pkt_length, pkt_offset;
>  	int hroom = adapter->intf_hdr_len;
>  
>  	if (!skb->len) {
> @@ -58,9 +58,11 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
>  	memset(local_tx_pd, 0, sizeof(struct txpd));
>  	local_tx_pd->bss_num = priv->bss_num;
>  	local_tx_pd->bss_type = priv->bss_type;
> -	local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len -
> -						       (sizeof(struct txpd) +
> -							pad)));
> +
> +	pkt_length = (u16)(skb->len - (sizeof(struct txpd) + pad));
> +	if (pkt_type == PKT_TYPE_MGMT)
> +		pkt_length -= MWIFIEX_MGMT_FRAME_HEADER_SIZE;
> +	local_tx_pd->tx_pkt_length = cpu_to_le16(pkt_length);
>  
>  	local_tx_pd->priority = (u8) skb->priority;
>  	local_tx_pd->pkt_delay_2ms =
> diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
> index e78a201cd150..eb0b8016d43d 100644
> --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
> +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
> @@ -743,6 +743,29 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
>  	return 0;
>  }
>  
> +/* This function prepares AP start up command with or without host MLME
> + */
> +static int mwifiex_cmd_uap_bss_start(struct mwifiex_private *priv,
> +				     struct host_cmd_ds_command *cmd)
> +{
> +	struct mwifiex_ie_types_host_mlme *tlv;
> +
> +	cmd->command = cpu_to_le16(HostCmd_CMD_UAP_BSS_START);
> +	cmd->size = S_DS_GEN;
> +
> +	if (priv->adapter->host_mlme) {
> +		tlv = (struct mwifiex_ie_types_host_mlme *)((u8 *)cmd + cmd->size);
> +		tlv->header.type = cpu_to_le16(TLV_TYPE_HOST_MLME);
> +		tlv->header.len = cpu_to_le16(sizeof(tlv->host_mlme));
> +		tlv->host_mlme = 1;
> +		cmd->size += sizeof(struct mwifiex_ie_types_host_mlme);
> +	}
> +
> +	cmd->size = cpu_to_le16(cmd->size);
> +
> +	return 0;
> +}
> +
>  /* This function prepares AP specific deauth command with mac supplied in
>   * function parameter.
>   */
> @@ -777,6 +800,9 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
>  			return -1;
>  		break;
>  	case HostCmd_CMD_UAP_BSS_START:
> +		if (mwifiex_cmd_uap_bss_start(priv, cmd))
> +			return -1;
> +		break;
>  	case HostCmd_CMD_UAP_BSS_STOP:
>  	case HOST_CMD_APCMD_SYS_RESET:
>  	case HOST_CMD_APCMD_STA_LIST:
> diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c
> index 745b1d925b21..bd9bf2888485 100644
> --- a/drivers/net/wireless/marvell/mwifiex/util.c
> +++ b/drivers/net/wireless/marvell/mwifiex/util.c
> @@ -370,6 +370,46 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
>  
>  	return 0;
>  }
> +
> +/* This function sends deauth packet to the kernel. */
> +void mwifiex_host_mlme_disconnect(struct mwifiex_private *priv,
> +				  u16 reason_code, u8 *sa)
Not used? Remove the whole function.

>  /*
>   * This function processes the received management packet and send it
>   * to the kernel.
> @@ -417,6 +457,39 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
>  	pkt_len -= ETH_ALEN;
>  	rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
>  
> +	if (priv->host_mlme_reg &&
> +	    (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) &&
> +	    (ieee80211_is_auth(ieee_hdr->frame_control) ||
> +	     ieee80211_is_deauth(ieee_hdr->frame_control) ||
> +	     ieee80211_is_disassoc(ieee_hdr->frame_control))) {
> +		if (ieee80211_is_auth(ieee_hdr->frame_control)) {
> +			if (priv->auth_flag & HOST_MLME_AUTH_PENDING) {
> +				if (priv->auth_alg != WLAN_AUTH_SAE) {
> +					priv->auth_flag &=
> +						~HOST_MLME_AUTH_PENDING;
> +					priv->auth_flag |=
> +						HOST_MLME_AUTH_DONE;
> +				}
> +			} else {
> +				return 0;
> +			}
> +
> +			mwifiex_dbg(priv->adapter, MSG,
> +				    "auth: receive authentication from %pM\n",
> +				    ieee_hdr->addr3);
> +		} else {
> +			if (!priv->wdev.connected)
> +				return 0;
> +
> +			if (ieee80211_is_deauth(ieee_hdr->frame_control)) {
> +				priv->auth_flag = 0;
> +				priv->auth_alg = 0xFFFF;
> +			}
> +		}
> +
> +		cfg80211_rx_mlme_mgmt(priv->netdev, skb->data, pkt_len);
> +	}
> +
>  	cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
>  			 CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len,
>  			 0);
> -- 
> 2.25.1
> 





[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux