From patchwork Fri Jul 28 06:18:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lin X-Patchwork-Id: 13331227 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FAAEC0015E for ; Fri, 28 Jul 2023 06:19:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233497AbjG1GTU (ORCPT ); Fri, 28 Jul 2023 02:19:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231896AbjG1GTO (ORCPT ); Fri, 28 Jul 2023 02:19:14 -0400 Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-db3eur04on2040.outbound.protection.outlook.com [40.107.6.40]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 160663C03 for ; Thu, 27 Jul 2023 23:18:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=XlXh6zahtmoFJ/r7gu+sYu/TrZzgjpRnx697dlqZ13mfKZ1BOlJZh5gGH6QEa9+vezJBwj8U/xUoderdz2lUmMZ3k/QNxXkaBLoOkYQNudE9o79+O25oKs4IjjioQ/dVybPdeYIfpBhqtIMV3FIDaXv+zDCHc4M5/kj3tqWnDs9zv+NJz4O54heGQBTW5pQkhemp+79as2tk6qzMw7DbY5yFXB/EGSnZ1miSts7fV4mo2RHKHlNeNO/TzUaOpJDJtle8oQjKHKsWBeebPx2Oo7XfG/xmeCZpgVk6faZ3eT0lenjn1mWeSnf+rJGlVYJRXVMxZkpm4YTLcJowE1apwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=FDFctxYQjnCtgsJr2xBHKGzNrLkxn0thB7DQuKW/fDw=; b=eg8dibJ+4SmaQ8InYuU1GqhD9OVkz9E8QG8Rz11wXTRoxwaKG9plkENVxe+n/Azh++yQTo6t1SPgLCjKcxNu4HprtObr/bjVlWV6oeqGLEtS1asDpOhkGW2GN9j7zKbqHWQyQKNImmXu06F7eUOjp5l+DUw4xYX+1nNYvmAAiY8ZG3ema2KwC6CmdO2xbQVSF7sqpkczHW4CD11gAAc9Njf8Y6LNoVdxWUIQkIfIPOzQl2mQYhFBX8YfnjTnI8SNS3OoY+wg1ePtbwoMGRyNX5IDudONC59yfX32AaIVpIURTCmvYTWhU9Xs6MJRyYa+qtvbeVUzPRWv/ptN3O73ZQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=FDFctxYQjnCtgsJr2xBHKGzNrLkxn0thB7DQuKW/fDw=; b=qzxyj8StOJi9l5VrVQyL3YL04BTRBd/weeYCrgEfcri8GRAFxq9EOSf8KDS0IDamQVb4+W8kj6D8ScG3he+Snc0T5+OKJ2VjIpN/rmyHCNQ3hZTPN7Fdp70t1rKCd5DGeUr+/ukfKHgDp8IdaiJpFIoDg5kMQ1MYOQSjrD7U8TY= Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB8480.eurprd04.prod.outlook.com (2603:10a6:10:2c6::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6631.29; Fri, 28 Jul 2023 06:18:09 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::693d:8782:eae1:2460]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::693d:8782:eae1:2460%4]) with mapi id 15.20.6631.026; Fri, 28 Jul 2023 06:18:09 +0000 From: David Lin To: "linux-wireless@vger.kernel.org" CC: Sharvari Harisangam , David Lin , Pete Hsieh Subject: [PATCH] wifi: mwifiex: added code to support host mlme. Thread-Topic: [PATCH] wifi: mwifiex: added code to support host mlme. Thread-Index: AdnBG0VbUku3Gob0RoOlmlRWbISqeA== Date: Fri, 28 Jul 2023 06:18:09 +0000 Message-ID: Accept-Language: zh-TW, en-US Content-Language: zh-TW X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: PA4PR04MB9638:EE_|DB9PR04MB8480:EE_ x-ms-office365-filtering-correlation-id: 6a299d11-4a48-4431-b663-08db8f3269f0 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 9qFmLphKrC47cMyjIygVeSmEfB8ESqZkyakthCzUQGNmxY6yc7b2nkzIt37YUfHfmF3IJs+u3nlnzXeikHYKzbMDjMYbRSGSGTwaGpSIXWdXRfUYUj1p3Xc+f8hqr5UCI4oLYsSkHiV+jkeUhfGkXtZhyerUnJAecPnYf8+OOUA1SeLo2f3yDkJ/wMhW1o6cjMTKZPcSrG8vu13G8f+eJK+oBQjlimBjDXSxrQ5Jnc42jEPJ66FJf+myS5YimimWbkrnhrMAh3ke+/sBbtR952O89Oy58aZ0MIJr2bXu1HP2Xl33T92r1VycYOIH200tT6eh37hpdKTPpNdqRIEBlTvuF+px1VBuaUnJfc5222DiZJOgkrkcYsL41lW5XyHVtim3EL988C3PSmJDXUftlFSEWR9CARk3LKSkyBMkDfAfa8Wa5yQ/qPJMcKPZQ64I7YP7VWkW+Pd+uUgb//awqZL1O9ENVstKzWuvunmGAaH43rlu/FH8MPItLnKtzsgYN/7YL82k16DjZ/kYcAumVMqSvS0xplZtTM4ARhREKskwD9ZBOtDA5oGGugZfioAS4f3sK6a7+4aM2bL6YaaUOuILEkAg3TTue3wKBk31b/PI6GCiuPLP2R2NeXuDeBrb x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PA4PR04MB9638.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(376002)(346002)(396003)(39860400002)(366004)(136003)(451199021)(316002)(6506007)(8936002)(26005)(41300700001)(66899021)(8676002)(55016003)(33656002)(54906003)(6916009)(122000001)(66446008)(64756008)(76116006)(66556008)(478600001)(4326008)(66476007)(9686003)(66946007)(7696005)(71200400001)(38100700002)(30864003)(2906002)(38070700005)(83380400001)(86362001)(52536014)(186003)(5660300002)(559001)(579004);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: khxSr7aHsdX6cqvYQ3IlVA36UcER+4Vs/VS4N3In2fSt3KfsfschVGjQsqd+Ic715OhdUi+EJoEvcTnzyIPwWB8kOBcAVN+p/T+qLBKkNrpuR7gYcuEX54N8Q9ctS+Xmk/RZjvCPbaulHhKKnwmBipcBXLcS8IIIzUvNB9zQpYAka5kfj3vmM6bl7UHmuv+jJeNmfTrSBJDSNYHHbkkI3lr6RIsCrqA0BnKw7Ma6SJ1Z/tsAviicUTBedQAG4C245IEwOLDAJcrFFxMjXekOTR61z6ENFaxsQd7U010jGh0cWajnxWVvRfn1GUvGaeogOiiVwyq/HcCg+VM56QGwgojU6+BZBZ/KSTbWr63R6QsJvBKX8tzEXA/PWvtqernfMDzEqCVX4h4ngUChefbgZje+yssdgTvWBH0/1bwHb8mLIkajNe2faVWWIGnV7l3hw+/RDcyj6EbnM3dVs/LrwqYeaRtQscV4KHBEyWvjmCajZwmsVSzuMYusQByV4aWmB5TqN1HAEEMb+3ZjxdWkB/nADfP/rmRxfgeM2WkCZOhEZ4DnsTBGFvLOIhnJsWoo6V8kXl4vOfRc/nl21HEc1/jCKm0CHS/OwuXUGLlsNzX/QMtQZtk3qXHqGYMR8GchuxuZ9V7ya5E05PkczR2ltX7u/htoUdmd8M264+T5nktY1bGyM0END7IhCMKDnc7MBGShGEKsudd4KZWYBcZWAuzljDIdEAaEl4egx79WJIGC62ykZ8iL8OIVa6jayeFsPUwoCKJFX4AUnvuFyn584ddOoS1ksWrPHBUwQskHikmNEOYkUrzsmFlJ6RMJWV3naKCdxGHQ6F8JluK3gkg7Z4WLYt2FbLz9tK/boe1FaPsquI3APrfXf7xaQPsReN4Jb+5YaC4G00tW8FNEFQkDqsjPEQH8hk8PBa+DlePW6NJwIG8Necvqem4SAB7MFPebYj/XmXiKb+3YgtoYPi2/9yjyh+JUmbeziGZOzP4+INKXVJUXvaW5URFefXUhakb12DpiBsbPDRZy2OhrwDDwL7pbanO8jpElnLpn88N0xBZXDZ/olXwtOgQCknsCZjcrdT1IGtCGacB1H0P0QXwqGSIS6E7VR/l7+lR0p120c7LsJd6zKd14lZbGxTnoJtcltkD8VmHKgiM8bhPWm2wzujSEwo+JVN8I/ukTZjRY/QAvW/UOholev87oDxM74e4Sutj79BGxZ1lQHnRq7ERWRo5t6T4YChwapwuCiEGO29bBHVc+cVCPSR3prtRBMOAmkvC12ey0/r5c122xNFIpwD4Fd/widHqU0XjrvQD4/2ar2wB2lcpF9WuYNGEJT+IA5AWsdPFS+eKlSbOiy8GzvTCkWw/9+roxfnRiY7hkJSwCng6ve4H4IdOo6rTpbEvJCsC2Nd3ZTkm5rOBO0hzUY6rhq2IsUktOyQNn1UM+nNy3wap2ToIZNBKAHqT83nspCGKtfSo0nNuin7Vk19tGYTMEEPfNTO/BsSYkBHVkaMe5UqGb2MzvngSD00FsJsb2Sowez+1UK6geaD4m9eGFsC/2clzgbz0UoVvhVrU1RFaKa3ipx3WXuImjxXBtA3xb MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6a299d11-4a48-4431-b663-08db8f3269f0 X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Jul 2023 06:18:09.1514 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 7H9pzCR06A1HlaC73QFKKRQK7AWEGgYA6nleyDjdsMAKoScVB0eFeoeMyOQxvIVgqy/4zzeRbpRrro3tukrwUA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB8480 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org 1. For station mode first. 2. This feature is a must for WPA3. 3. The code is tested with IW416. There is no guarantee for other chips. Signed-off-by: David Lin --- .../net/wireless/marvell/mwifiex/cfg80211.c | 327 +++++++++++++++++- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 +- 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 | 65 +++- drivers/net/wireless/marvell/mwifiex/main.c | 4 + drivers/net/wireless/marvell/mwifiex/main.h | 10 + drivers/net/wireless/marvell/mwifiex/scan.c | 6 + .../net/wireless/marvell/mwifiex/sta_event.c | 17 +- .../net/wireless/marvell/mwifiex/sta_ioctl.c | 1 + drivers/net/wireless/marvell/mwifiex/sta_tx.c | 10 +- .../net/wireless/marvell/mwifiex/uap_cmd.c | 25 ++ drivers/net/wireless/marvell/mwifiex/util.c | 74 ++++ 14 files changed, 558 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 813d1cbebe19..619c1746ce67 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 { + __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; + /* * 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; + 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 (host_mlme) { + 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; + } wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; wiphy->mgmt_stypes = mwifiex_mgmt_stypes; @@ -4424,7 +4748,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER | NL80211_FEATURE_LOW_PRIORITY_SCAN | - NL80211_FEATURE_NEED_OBSS_SCAN; + NL80211_FEATURE_NEED_OBSS_SCAN | + 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..1db437cc96b8 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); mwifiex_insert_cmd_to_free_q(adapter, cmd_node); return -1; } 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 + +#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..e2827e25ec38 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[1]; +} __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..56bb1a1146d9 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] & + (0x01 << 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)); + sae_pwe_tlv->pwe[0] = bss_desc->bcn_rsnx_ie->data[0]; + pos += sizeof(sae_pwe_tlv->header) + + sizeof(sae_pwe_tlv->pwe); + } + } + if (IS_SUPPORT_MULTI_BANDS(priv->adapter) && !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && (!bss_desc->disable_11n) && @@ -491,6 +511,17 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, sizeof(struct mwifiex_chan_scan_param_set); } + if (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 = sizeof(host_mlme_tlv->host_mlme); + host_mlme_tlv->host_mlme = 1; + pos += sizeof(host_mlme_tlv->header) + + host_mlme_tlv->header.len; + host_mlme_tlv->header.len = + cpu_to_le16(host_mlme_tlv->header.len); + } + 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 +665,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 +673,19 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, goto done; } - assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; + if (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 +822,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 +1536,20 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) if (!priv->media_connected) return 0; + if (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.c b/drivers/net/wireless/marvell/mwifiex/main.c index 1cd9d20cca16..39bf4fd13899 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -28,6 +28,10 @@ module_param(driver_mode, ushort, 0); MODULE_PARM_DESC(driver_mode, "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7"); +bool host_mlme; +module_param(host_mlme, bool, 0); +MODULE_PARM_DESC(host_mlme, "Host MLME support enable:1, disable:0"); + bool mfg_mode; module_param(mfg_mode, bool, 0); MODULE_PARM_DESC(mfg_mode, "manufacturing mode enable:1, disable:0"); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index b95886e1413e..b88761b170a1 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -49,6 +49,7 @@ #include "sdio.h" extern const char driver_version[]; +extern bool host_mlme; extern bool mfg_mode; extern bool aggr_ctrl; @@ -384,6 +385,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 +428,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 +540,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 +664,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; @@ -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); + 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/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index df9cdd10a494..51009f20e942 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,16 @@ 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 (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..2bea5bc627f1 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; 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..f0ac8f144198 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c @@ -743,6 +743,28 @@ 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 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 (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 +799,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(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 94c2d219835d..79b4f666a9b4 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) +{ + u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 frame_buf[100]; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)frame_buf; + + memset(frame_buf, 0, sizeof(frame_buf)); + mgmt->frame_control = (__force __le16)IEEE80211_STYPE_DEAUTH; + mgmt->duration = 0; + mgmt->seq_ctrl = 0; + mgmt->u.deauth.reason_code = (__force __le16)reason_code; + + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { + memcpy(mgmt->da, broadcast_addr, ETH_ALEN); + memcpy(mgmt->sa, + priv->curr_bss_params.bss_descriptor.mac_address, + ETH_ALEN); + memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN); + priv->auth_flag = 0; + priv->auth_alg = 0xFFFF; + } else { + memcpy(mgmt->da, priv->curr_addr, ETH_ALEN); + memcpy(mgmt->sa, sa, ETH_ALEN); + memcpy(mgmt->bssid, priv->curr_addr, ETH_ALEN); + } + + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) { + mutex_lock(&priv->wdev.mtx); + cfg80211_rx_mlme_mgmt(priv->netdev, frame_buf, 26); + mutex_unlock(&priv->wdev.mtx); + } else { + cfg80211_rx_mgmt(&priv->wdev, + priv->bss_chandef.chan->center_freq, + 0, frame_buf, 26, 0); + } +} + /* * This function processes the received management packet and send it * to the kernel. @@ -405,6 +445,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, pkt_len, rx_pd)) return -1; } + /* Remove address4 */ memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), skb->data + sizeof(struct ieee80211_hdr), @@ -413,6 +454,39 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, pkt_len -= ETH_ALEN + sizeof(pkt_len); 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);