From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2052.outbound.protection.outlook.com [40.107.8.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B4AF016C869; Fri, 21 Jun 2024 07:52:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956360; cv=fail; b=FfHzm/qz8m9kKk9oU4i5Wt4o7H3+5+myOqXKedyBC9mGcOudopQWgCgk9QynVgQV5BAwfnboS1pMlDCqPlRmkZeEIYp/uJHbxpIomM54mdBYlpClt7RNKpY0rLYDFVOCOF9tGWQm1rPDe3w9ElKXlWEmWv/S1r0XklMuTMJwNxU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956360; c=relaxed/simple; bh=/CqqwbsuFNyN9I/zT1ZQ3O+fAGUOKJIFD3bPUT+sX8w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=VZkIOfWoyBoAaPqUX52X9vWIPOySh09NTtlP52JFRe583ms7X5RYtXdcTaEw9ZYl3s+O0YeIOO8fYXu1u66wsTmg0aZNRu0WSDWme+vaXLpQZnP/8+Viy7bxmgSKUIwDMIeWA6V7P5/I3mPYsah9xE/1JUmi0HBXSAzX6r3Bp6M= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=SD7bYNxt; arc=fail smtp.client-ip=40.107.8.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="SD7bYNxt" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=F4esDpauijT7HHdqZt2Q1bTW+8+I7ExqTWFQvVd0VGKPN5/dts5yz+ALsQBBMK3TSKCrF1X6861jJzCtok/FG7FZs2mjCmiU9uweWATTnMkz0fTSEiBUekG33oLhaPG+Y3d3na4FlNn3ok4ifoSa30+y1OGMz5G/5nOkrac4rlNS2wIRKbAvKdWyY5V10ekmkqbMpyHfSrlulU+gsZnv0tqlyzb2MXGvIhEfV/dmiOkecWbayNZ6xTw8TWfhqw+NkTC7ori+w/gEOPNdn6+2PoxHNT1/7okJveSTvqDqUfAW4Xb56T3BiQpQP/v48rEW/tlRpPayBa4G449KjOGHng== 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=xynYrVUvjJKWmvUnozM32d3mC1JgZR6wFOtGF2B/a4Y=; b=Dc0RVQoJn6J3BX09DDaTlJ34J2hA4N45eIfkn5c8QMNUg+/YfgEaR17+LQ/vd21cn/2es/9+A+uyeZUCnemMJd0StDugIciFCUlK7LO77z8Xz1nao/tMSWY2M/V0J8hpXI/09Ao5WK3mtrkcycezW2NLFkdm3oBawQZpn7suEcKDvyYWP9qsSzc24NPCHa19neuMXXssZ5KwRRAc1vUe4cW1vlKpacojRIK8VudTbCup88AhF1wrEKpdH314zQubh5/sIXLVlx+LZTBmV66gygpPf7rN63SI7l6UBW9658uTwBvpdyiKNp13Sv25TQqDMXkhi/ykRCOB9+CppwgNXg== 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=xynYrVUvjJKWmvUnozM32d3mC1JgZR6wFOtGF2B/a4Y=; b=SD7bYNxtklyehatbxT6/rvMfpJZwwCi8vvcI4Zibc0UNUJ2gARpIreVvZI+R1KhTZeOzNoOqhtiwB3+tnVYCflBjymvhGWU/qhebg34KukYq2TljBO0JHRJceFiPoVQEQVvEfmzf3Ywcx2lso8+5KAZV2PU9gZwZ2LorZsbZqAI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:34 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:34 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 01/43] wifi: nxpwifi: add 11ac.c Date: Fri, 21 Jun 2024 15:51:26 +0800 Message-Id: <20240621075208.513497-2-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: 6ea7208d-399f-48a8-6e1d-08dc91c71c76 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?Me9liTswT8+Pjy3txlFHKCR03wakUOZHXJoGk+E0HblAoPLaZ9RZnlPSgAlg?= =?us-ascii?Q?GnSfei/jIh3gj6G9TQN6iOFbHXHryDV9jcnmyQgGZmtYv1uHqoM4x5Pxo/gK?= =?us-ascii?Q?b8gDGXWhcuY8Q+EL0Wz8JTtdSipfpw9NxPJ4vZK7YgyGZoQghZatq9B3xAEF?= =?us-ascii?Q?Px+rPID+suNBGaBUmeTPEZuM7XPUdGqvA+9mXDKCbYniJV2Br6ndMa6FVRia?= =?us-ascii?Q?T+w2nexB650StQlbaI8icjFbmN0aNirwmDeMS8sS+3Md6AdmLmHIyCYo6wrr?= =?us-ascii?Q?TexVi//Cc/hQ0RuiBz5fu7Modgs5Ntffw19QcgUzOltv0vxLPHZFe9j5rLOb?= =?us-ascii?Q?UlpwLPTTqmawY7UIMbicrNp9o2WIfTvN9Dljc96jnxk4KYrqC3RJBdwEPqxC?= =?us-ascii?Q?immJ49FB+6+8NnuToi+l7/IJOrbMu2+th5cCSWP31qMxnEgdqq1EithDJhdt?= =?us-ascii?Q?OhhUVYUhFAqwa6cYVHg8slvgMnKQI6X75JjdNUlJYyr9d5swpYBpMYuYlIkb?= =?us-ascii?Q?G+ozCDl9PH9GnAmUmSWSrhn71S8T1IuKg/puYZmqe9EHX4ERz8BIycqA194x?= =?us-ascii?Q?dk2/pzNQZXRn0+pRRNkwwcoX69y76swDFkH+hGN700X3p8zq5p9Jc3yVVGQf?= =?us-ascii?Q?qY1A31xwO+yxZ82cwHXUQCaU3A91w2LKChwRvcTWusTQDLh1gTHBZAqmYCqZ?= =?us-ascii?Q?GVgzOEn2FUjHQLreXU1h44uHkk0aCHprsvGoX379CHdPlvVCQEwYYDkMIVsI?= =?us-ascii?Q?tQ31z1gtNuh2T9rB5x9ewwNHyCuYOaSrbY8rEj6Vn1tAQkTrayPdyYTAYKf2?= =?us-ascii?Q?r9UixCPdX2q+H1YMOFmIuIxJEIpZXI+Pyz/ALLKlBLZSzoytHWC512Ft9RXP?= =?us-ascii?Q?vRtRMZf+jMkYh/u3DJpF/5xaZjA6rfhdZeYOfhKo8LHXMeua+Ufkjda6zWfJ?= =?us-ascii?Q?Q3IFcbrm3grFWNnf0vHHFz5l9RiV9JIplmr2gqyklqGDDiNyxs4wvfiQUTwm?= =?us-ascii?Q?XScY8mFvcOygPM0jTqO32TD1Kpgo1Tlf3+3ELhdsca5IDDFrLRIAkLJM9NW8?= =?us-ascii?Q?LLIjPHNph1a/SHQmFIQCoVypxs9MFVF8hgqg/ScRzCIhZ6ikml9rcoicQ3vP?= =?us-ascii?Q?8UPHETyYm6h3HiazPFD1iuYCWlD7KWu9B5f+sEt6SotOxBOTX9jncRtulHsT?= =?us-ascii?Q?b4eh0Z3VdT7WTuG4gpuSTBls10mYnsG7ENGS9mx7K6SjYkNP3OSNu7u7PMD/?= =?us-ascii?Q?MMspWqaPsTd1s1NCzRoRez9NvDqkeBegCgTax2Z87wH3ImSjODJmBLSWdB1k?= =?us-ascii?Q?8ofxMIHFf17fbFqbx28hKBdtd/qzrEEM94D+2iunG6m9p2cyRCdP7+R/MzoC?= =?us-ascii?Q?MaNcGSI=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?JxLmUSIIwhhF54N9x/5ggsdEjE9FvFdpk1DeuFDbbaikPVOo/05iwPw2y8Pm?= =?us-ascii?Q?VAQuUsazI+5qA2SC6R6BtqckcEMci+Oa2P6ocEMu0z9H1ZrGvZGew47QfBHs?= =?us-ascii?Q?Z41VX7gF+2B8JZ74dAJ/Y6+Iz5Soc6Jd9rntsYFl2P9OSG6E0MPzef9jtVvX?= =?us-ascii?Q?/evoBOJaEx8FajkA6cj1vIEppPux76NhvVEb/2b5spm2a1zcxF/SpVXuxlNc?= =?us-ascii?Q?nfE0QpmjixbjjgcL47EkafTIvA/zr+pkPv3/PHblECglWwaGCLJ7Oqh077fj?= =?us-ascii?Q?3gLR9d4FbYSrdeDEmqzMFeIUagzfsFXaI1KwtxljQsSuWYaww3sfRrM2TQHz?= =?us-ascii?Q?MLlWUM5WcKqvjkhPPquw9XWYCU5EOUPTt/M3a4mf0HiQDncA3eqp8ZQ5jvO5?= =?us-ascii?Q?SsDKQTv/MG4GeqnpsyrnCT1r1IPASrTlXxVeFZB/Sz3J+lZoeP7Ti1R/4S0r?= =?us-ascii?Q?OakZVZjcA22uj/dpHBV8BdH/zYGRRJq4HfwQ1DUFdwcjbXI+JZr9U7hP736p?= =?us-ascii?Q?Yz02O4uEzvRC5peaNTOnB+Jys9XAcYJDpf1JySAtfLXaRG+Apdr59JLvRMb/?= =?us-ascii?Q?vNLSNS4AQvp7cUj3C4ckezmg25KMX2jEknJ/iuvCely9952NMrEDR6C33sLi?= =?us-ascii?Q?LA3b+tw0DqXPOfq5nBiFkuvsjWrLCuBtnYWBnjlWQOEREAmCCzsdjVXZyI0v?= =?us-ascii?Q?g6zLcL5vRqpNCzkqh8UrB/fMueTo4W3DzmX6MSNrJe6Y12ZsZR9i0fOjmMQH?= =?us-ascii?Q?yb5/zACLcuyI3H74kPQJb0ErqLh3BLj9hS7Dfkq01CoKeQN7at36Uyzo96wv?= =?us-ascii?Q?rHfhbC4/kODybWGnAkygCaFz5IWlQQ29QmE49iMfZIGUOo+fkx/ty87wu+sm?= =?us-ascii?Q?RYvL+++yCLx0yhLFwv+w2HpxlsnlPIFDyhy5m3bnTtuyXGUv7gvQyM137WjQ?= =?us-ascii?Q?T8YGK9OkbVfTBzZqm9eqX5gI4b7w9CPILSx/eKGX4XqVwcefvHFNwXIf3u/W?= =?us-ascii?Q?8h5peewkJxyrklKetgCw0dYK5CmiNHSZE3kMVxxQ3BsiazJMvWXzah2JRhSa?= =?us-ascii?Q?PJnz6WcLjx2Pbdy3Z5GfDlMBKsA//kXcoVgBpAo9cQumNZeYx5WJcY+Er6Sh?= =?us-ascii?Q?oAqiVPwBG9lLSK9GlommJqrLOWfm4YKt7xKW+zs6xHqufvre4OqGDD6e58r/?= =?us-ascii?Q?F+EgljOdbVTJEZG7EcCsjFtfgGaqjm43Jn1QY4R9KMZ4w01lyD0oTXk8KhQu?= =?us-ascii?Q?sY/vZGO4ZEcVL1RS9w+HAxe3ll//8Fk9WEe7oHfzS/IVmAgWs5QkXZt2QR+p?= =?us-ascii?Q?iFv2PGkIlzHoYavM/yzhgbY+Rnm8v2+iH4yp/v+SfLIChw9lKsajJu2Js77L?= =?us-ascii?Q?u4pBes/tQO1GviqMGrEv1Y0inXgohqX2SnDkHGQwgaKCxw3zcUmt3hZPZyd6?= =?us-ascii?Q?zZBfNCgqspj58UIZctHvE4KA/ox+6hxdxZ5iSVsRfBzzUtj9UQLGvYWP4KUZ?= =?us-ascii?Q?alzkOZzjc7jOu/6ffb8BimmTv0CHtJJ0sqZDAtgF3X3oJdT82t7ee4tkVv6r?= =?us-ascii?Q?SFtvkMxjo1QwDYNGHQY14rcM6JlzTAZMXcxL9kcq?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6ea7208d-399f-48a8-6e1d-08dc91c71c76 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:34.8390 (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: kYh04AYBsLp0r7vn7M1SJDQadyzl/7wNM0SJY17l2r8R/s2pr87HtxotVX97M7mLOSnbKh5MWu3burh7b/XL3g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11ac.c | 366 ++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11ac.c diff --git a/drivers/net/wireless/nxp/nxpwifi/11ac.c b/drivers/net/wireless= /nxp/nxpwifi/11ac.c new file mode 100644 index 000000000000..3e14ee602cdc --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11ac.c @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: 802.11ac + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "fw.h" +#include "main.h" +#include "11ac.h" + +/* Tables of the MCS map to the highest data rate (in Mbps) supported + * for long GI. + */ +static const u16 max_rate_lgi_80MHZ[8][3] =3D { + {0x124, 0x15F, 0x186}, /* NSS =3D 1 */ + {0x249, 0x2BE, 0x30C}, /* NSS =3D 2 */ + {0x36D, 0x41D, 0x492}, /* NSS =3D 3 */ + {0x492, 0x57C, 0x618}, /* NSS =3D 4 */ + {0x5B6, 0x6DB, 0x79E}, /* NSS =3D 5 */ + {0x6DB, 0x83A, 0x0}, /* NSS =3D 6 */ + {0x7FF, 0x999, 0xAAA}, /* NSS =3D 7 */ + {0x924, 0xAF8, 0xC30} /* NSS =3D 8 */ +}; + +static const u16 max_rate_lgi_160MHZ[8][3] =3D { + {0x249, 0x2BE, 0x30C}, /* NSS =3D 1 */ + {0x492, 0x57C, 0x618}, /* NSS =3D 2 */ + {0x6DB, 0x83A, 0x0}, /* NSS =3D 3 */ + {0x924, 0xAF8, 0xC30}, /* NSS =3D 4 */ + {0xB6D, 0xDB6, 0xF3C}, /* NSS =3D 5 */ + {0xDB6, 0x1074, 0x1248}, /* NSS =3D 6 */ + {0xFFF, 0x1332, 0x1554}, /* NSS =3D 7 */ + {0x1248, 0x15F0, 0x1860} /* NSS =3D 8 */ +}; + +/* This function converts the 2-bit MCS map to the highest long GI + * VHT data rate. + */ +static u16 +nxpwifi_convert_mcsmap_to_maxrate(struct nxpwifi_private *priv, + u8 bands, u16 mcs_map) +{ + u8 i, nss, mcs; + u16 max_rate =3D 0; + u32 usr_vht_cap_info =3D 0; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (bands & BAND_AAC) + usr_vht_cap_info =3D adapter->usr_dot_11ac_dev_cap_a; + else + usr_vht_cap_info =3D adapter->usr_dot_11ac_dev_cap_bg; + + /* find the max NSS supported */ + nss =3D 1; + for (i =3D 1; i <=3D 8; i++) { + mcs =3D GET_VHTNSSMCS(mcs_map, i); + if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED) + nss =3D i; + } + mcs =3D GET_VHTNSSMCS(mcs_map, nss); + + /* if mcs is 3, nss must be 1 (NSS =3D 1). Default mcs to MCS 0~9 */ + if (mcs =3D=3D IEEE80211_VHT_MCS_NOT_SUPPORTED) + mcs =3D IEEE80211_VHT_MCS_SUPPORT_0_9; + + if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) { + /* support 160 MHz */ + max_rate =3D max_rate_lgi_160MHZ[nss - 1][mcs]; + if (!max_rate) + /* MCS9 is not supported in NSS6 */ + max_rate =3D max_rate_lgi_160MHZ[nss - 1][mcs - 1]; + } else { + max_rate =3D max_rate_lgi_80MHZ[nss - 1][mcs]; + if (!max_rate) + /* MCS9 is not supported in NSS3 */ + max_rate =3D max_rate_lgi_80MHZ[nss - 1][mcs - 1]; + } + + return max_rate; +} + +static void +nxpwifi_fill_vht_cap_info(struct nxpwifi_private *priv, + struct ieee80211_vht_cap *vht_cap, u8 bands) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (bands & BAND_A) + vht_cap->vht_cap_info =3D + cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a); + else + vht_cap->vht_cap_info =3D + cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg); +} + +void nxpwifi_fill_vht_cap_tlv(struct nxpwifi_private *priv, + struct ieee80211_vht_cap *vht_cap, u8 bands) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 mcs_map_user, mcs_map_resp, mcs_map_result; + u16 mcs_user, mcs_resp, nss, tmp; + + /* Fill VHT cap info */ + nxpwifi_fill_vht_cap_info(priv, vht_cap, bands); + + /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */ + mcs_map_user =3D GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support); + mcs_map_resp =3D le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map); + mcs_map_result =3D 0; + + for (nss =3D 1; nss <=3D 8; nss++) { + mcs_user =3D GET_VHTNSSMCS(mcs_map_user, nss); + mcs_resp =3D GET_VHTNSSMCS(mcs_map_resp, nss); + + if (mcs_user =3D=3D IEEE80211_VHT_MCS_NOT_SUPPORTED || + mcs_resp =3D=3D IEEE80211_VHT_MCS_NOT_SUPPORTED) + SET_VHTNSSMCS(mcs_map_result, nss, + IEEE80211_VHT_MCS_NOT_SUPPORTED); + else + SET_VHTNSSMCS(mcs_map_result, nss, + min(mcs_user, mcs_resp)); + } + + vht_cap->supp_mcs.rx_mcs_map =3D cpu_to_le16(mcs_map_result); + + tmp =3D nxpwifi_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); + vht_cap->supp_mcs.rx_highest =3D cpu_to_le16(tmp); + + /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */ + mcs_map_user =3D GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support); + mcs_map_resp =3D le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map); + mcs_map_result =3D 0; + + for (nss =3D 1; nss <=3D 8; nss++) { + mcs_user =3D GET_VHTNSSMCS(mcs_map_user, nss); + mcs_resp =3D GET_VHTNSSMCS(mcs_map_resp, nss); + if (mcs_user =3D=3D IEEE80211_VHT_MCS_NOT_SUPPORTED || + mcs_resp =3D=3D IEEE80211_VHT_MCS_NOT_SUPPORTED) + SET_VHTNSSMCS(mcs_map_result, nss, + IEEE80211_VHT_MCS_NOT_SUPPORTED); + else + SET_VHTNSSMCS(mcs_map_result, nss, + min(mcs_user, mcs_resp)); + } + + vht_cap->supp_mcs.tx_mcs_map =3D cpu_to_le16(mcs_map_result); + + tmp =3D nxpwifi_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); + vht_cap->supp_mcs.tx_highest =3D cpu_to_le16(tmp); +} + +int nxpwifi_cmd_append_11ac_tlv(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc, + u8 **buffer) +{ + struct nxpwifi_ie_types_vhtcap *vht_cap; + struct nxpwifi_ie_types_oper_mode_ntf *oper_ntf; + struct ieee_types_oper_mode_ntf *ieee_oper_ntf; + struct nxpwifi_ie_types_vht_oper *vht_op; + struct nxpwifi_adapter *adapter =3D priv->adapter; + u8 supp_chwd_set; + u32 usr_vht_cap_info; + int ret_len =3D 0; + + if (bss_desc->bss_band & BAND_A) + usr_vht_cap_info =3D adapter->usr_dot_11ac_dev_cap_a; + else + usr_vht_cap_info =3D adapter->usr_dot_11ac_dev_cap_bg; + + /* VHT Capabilities IE */ + if (bss_desc->bcn_vht_cap) { + vht_cap =3D (struct nxpwifi_ie_types_vhtcap *)*buffer; + memset(vht_cap, 0, sizeof(*vht_cap)); + vht_cap->header.type =3D cpu_to_le16(WLAN_EID_VHT_CAPABILITY); + vht_cap->header.len =3D + cpu_to_le16(sizeof(struct ieee80211_vht_cap)); + memcpy((u8 *)vht_cap + sizeof(struct nxpwifi_ie_types_header), + (u8 *)bss_desc->bcn_vht_cap, + le16_to_cpu(vht_cap->header.len)); + + nxpwifi_fill_vht_cap_tlv(priv, &vht_cap->vht_cap, + bss_desc->bss_band); + *buffer +=3D sizeof(*vht_cap); + ret_len +=3D sizeof(*vht_cap); + } + + /* VHT Operation IE */ + if (bss_desc->bcn_vht_oper) { + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION) { + vht_op =3D (struct nxpwifi_ie_types_vht_oper *)*buffer; + memset(vht_op, 0, sizeof(*vht_op)); + vht_op->header.type =3D + cpu_to_le16(WLAN_EID_VHT_OPERATION); + vht_op->header.len =3D cpu_to_le16(sizeof(*vht_op) - + sizeof(struct nxpwifi_ie_types_header)); + memcpy((u8 *)vht_op + + sizeof(struct nxpwifi_ie_types_header), + (u8 *)bss_desc->bcn_vht_oper, + le16_to_cpu(vht_op->header.len)); + + /* negotiate the channel width and central freq + * and keep the central freq as the peer suggests + */ + supp_chwd_set =3D GET_VHTCAP_CHWDSET(usr_vht_cap_info); + + switch (supp_chwd_set) { + case 0: + vht_op->chan_width =3D + min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ, + bss_desc->bcn_vht_oper->chan_width); + break; + case 1: + vht_op->chan_width =3D + min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ, + bss_desc->bcn_vht_oper->chan_width); + break; + case 2: + vht_op->chan_width =3D + min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ, + bss_desc->bcn_vht_oper->chan_width); + break; + default: + vht_op->chan_width =3D + IEEE80211_VHT_CHANWIDTH_USE_HT; + break; + } + + *buffer +=3D sizeof(*vht_op); + ret_len +=3D sizeof(*vht_op); + } + } + + /* Operating Mode Notification IE */ + if (bss_desc->oper_mode) { + ieee_oper_ntf =3D bss_desc->oper_mode; + oper_ntf =3D (void *)*buffer; + memset(oper_ntf, 0, sizeof(*oper_ntf)); + oper_ntf->header.type =3D cpu_to_le16(WLAN_EID_OPMODE_NOTIF); + oper_ntf->header.len =3D cpu_to_le16(sizeof(u8)); + oper_ntf->oper_mode =3D ieee_oper_ntf->oper_mode; + *buffer +=3D sizeof(*oper_ntf); + ret_len +=3D sizeof(*oper_ntf); + } + + return ret_len; +} + +int nxpwifi_cmd_11ac_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, u16 cmd_action, + struct nxpwifi_11ac_vht_cfg *cfg) +{ + struct host_cmd_11ac_vht_cfg *vhtcfg =3D &cmd->params.vht_cfg; + + cmd->command =3D cpu_to_le16(HOST_CMD_11AC_CFG); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) + + S_DS_GEN); + vhtcfg->action =3D cpu_to_le16(cmd_action); + vhtcfg->band_config =3D cfg->band_config; + vhtcfg->misc_config =3D cfg->misc_config; + vhtcfg->cap_info =3D cpu_to_le32(cfg->cap_info); + vhtcfg->mcs_tx_set =3D cpu_to_le32(cfg->mcs_tx_set); + vhtcfg->mcs_rx_set =3D cpu_to_le32(cfg->mcs_rx_set); + + return 0; +} + +/* This function initializes the BlockACK setup information for given + * nxpwifi_private structure for 11ac enabled networks. + */ +void nxpwifi_set_11ac_ba_params(struct nxpwifi_private *priv) +{ + priv->add_ba_param.timeout =3D NXPWIFI_DEFAULT_BLOCK_ACK_TIMEOUT; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + priv->add_ba_param.tx_win_size =3D + NXPWIFI_11AC_UAP_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size =3D + NXPWIFI_11AC_UAP_AMPDU_DEF_RXWINSIZE; + } else { + priv->add_ba_param.tx_win_size =3D + NXPWIFI_11AC_STA_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size =3D + NXPWIFI_11AC_STA_AMPDU_DEF_RXWINSIZE; + } +} + +bool nxpwifi_is_bss_in_11ac_mode(struct nxpwifi_private *priv) +{ + struct nxpwifi_bssdescriptor *bss_desc; + struct ieee80211_vht_operation *vht_oper; + + bss_desc =3D &priv->curr_bss_params.bss_descriptor; + vht_oper =3D bss_desc->bcn_vht_oper; + + if (!bss_desc->bcn_vht_cap || !vht_oper) + return false; + + if (vht_oper->chan_width =3D=3D IEEE80211_VHT_CHANWIDTH_USE_HT) + return false; + + return true; +} + +u8 nxpwifi_get_center_freq_index(struct nxpwifi_private *priv, u8 band, + u32 pri_chan, u8 chan_bw) +{ + u8 center_freq_idx =3D 0; + + if (band & BAND_AAC) { + switch (pri_chan) { + case 36: + case 40: + case 44: + case 48: + if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_80MHZ) + center_freq_idx =3D 42; + break; + case 52: + case 56: + case 60: + case 64: + if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_80MHZ) + center_freq_idx =3D 58; + else if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_160MHZ) + center_freq_idx =3D 50; + break; + case 100: + case 104: + case 108: + case 112: + if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_80MHZ) + center_freq_idx =3D 106; + break; + case 116: + case 120: + case 124: + case 128: + if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_80MHZ) + center_freq_idx =3D 122; + else if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_160MHZ) + center_freq_idx =3D 114; + break; + case 132: + case 136: + case 140: + case 144: + if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_80MHZ) + center_freq_idx =3D 138; + break; + case 149: + case 153: + case 157: + case 161: + if (chan_bw =3D=3D IEEE80211_VHT_CHANWIDTH_80MHZ) + center_freq_idx =3D 155; + break; + default: + center_freq_idx =3D 42; + } + } + + return center_freq_idx; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2052.outbound.protection.outlook.com [40.107.8.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 33FAE16D335; Fri, 21 Jun 2024 07:52:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956363; cv=fail; b=QtorzSFsGLmZ/FlaOSUuM9bcxWGkqvehLAQKmzquc9RZD9g5xyaxFLwecbT2sa1vgoS13ofJmPpdnfi1Ik6tW418osbSp5n9NsRt21ar5lbeB85oxXaLZDlYm/bM5VdSwi147sNabo0zUUxzLfpN8oX7f7gW23pO9mVrkXx39iI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956363; c=relaxed/simple; bh=29/7PCObOYigLkRDRhX7GqvssKztbaGrAiheJJycaiQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=GmGY7ofcqR29CreERBqQA/nixcnQnmxCFMnrVqS9dS+iTD68TNPRTIf0HAE5DC8rg2r60Xyu7en7yowCr3M2latpjHwWhU3PVL2r6u8X5aqW7ccz8vLgKVuInnNvjgAMWqQIe5A/KSQ/WIxOZXq27CrOxgMMWw/e1AtCAXz3nHU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=im9gqVh6; arc=fail smtp.client-ip=40.107.8.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="im9gqVh6" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NrKW96uW8q6iBpqWMFCTabeII9sJ002vg390YnSuYIaBL95antDguMWbR5nXP59ioBRZqj6FqipYblqwf5vCi5n99tW42xuVzn8VARfERzdQ+8fURA1dtS7clVTmhQox+iYZfaceZ1xUzGAKrTrKP50SI3f6vk0qGdl1RtDBuC+zDAJPlieqeGxBj9DvUE2GhV7tz965frFQupe6Q+pBaEW5i44/gQ/4kl3IFAG93vgAMyLgl30xwuPHgJWr3ZUgVE99Yycq5F6HBRputn+wHuBNQ6aYtZmTCNrvtOraLDYZfZT+iOWI5GGJPP9LmzTh1QsRZN4fk5wt2kqgqU0IZw== 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=Mi5r2ML+Cj4fQ/fCi0gFAN5/9NwlsrP2l0VP/bNbYlo=; b=AFnfvjeOynOLIGsUhM55FYU2FAPaI9iL2Uj+VmrcvbG4NiELrgNOzKAkMKhKKJHz2pmxOaUpBQxZXgyrjoV8Txw0KsjPYz7ZQBJKhtihMg3H3h05+ifB8zt5aDWE4itrenlHEmFiyQfPVS/rGwbT4jV/qB+1+gLh3elZ9yEnDOdXMV7fd9EO2oJ+YMM14zbsHWzFzhZbeGkQTSCxw7NuaBHQ7gPg//RY5XHIPT9JuVWBZhP+HcT2iwT15aohw/04CJJRQugKMk6L1b7e8QFR3uwI+s52fp2XSmQYHotGfvI0VmpMBxIDRjfC6zkHGEOPZHMYntpszklGqR0Z2k8fxA== 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=Mi5r2ML+Cj4fQ/fCi0gFAN5/9NwlsrP2l0VP/bNbYlo=; b=im9gqVh6rKAtvikOLn22/N+Ro5GPgQUz79UJYoMuspbpxMNxSKCvLNTWLBo8gdOHImG+dbV5k1Q/pmqYNJS3+XArJ3vChVNx+6DYXJ8eh0dfkWHIpWsHZMpzZaXo8l3X5zWI8B3XFoELSsBz131S6e4w8nUR+gZCTggiJ8Pg/+U= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:37 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:37 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 02/43] wifi: nxpwifi: add 11ac.h Date: Fri, 21 Jun 2024 15:51:27 +0800 Message-Id: <20240621075208.513497-3-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: e421670b-9532-4e09-b4d8-08dc91c71e6b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?kuwqiN6+/ET38/GUrWQZWynmfwww5+D2I+VJOxnnYUURmElaM1vt8QiaXVxW?= =?us-ascii?Q?N4Uw0bhZ6P7dyyzt8KP1HD7OrrNlXVm2IfSzojnoLGs7URoCNzrepgCju81g?= =?us-ascii?Q?roncha+HX7wyVKh/q1lkgGEtDDuhADBNaezyZ7qTGG3W/bJ/jtPG+i9oOQUG?= =?us-ascii?Q?ZpHfoopGSmt3aJBv9zfXd4ckMBooq3GHSM09aGwygaCyspzBp9+Eoyl4Wcd1?= =?us-ascii?Q?tZVkOaaAiP5RjoZ3fsxvA74K316KfNyRKHvBclcf+koFNa3GJR2zaIOYtPkk?= =?us-ascii?Q?rLiE/JQBhIUEjWxyj0LlQb6KjUPc98lVnc2iWts+M8UA81w5PVbnA2mvqzDg?= =?us-ascii?Q?whzxer3P5dIGjjSem01+JEumWQpowlOdsIo6ljHCLCFTWnEh77SfF2DhhPQe?= =?us-ascii?Q?9r3gGznDDun7vexMPsOqYBlka9LV8BGgHu1C6aBrbrKukHJrjJlQyXI4JZDC?= =?us-ascii?Q?XZ34ndh7ar558JtmgdfE7ebjskAJij7Kxc2E1mIKZgpT/yOOVAW+IiRSELQh?= =?us-ascii?Q?9diJqEVjloL+/3hu4moBJvXN0B8S5VmqJZz1kXZUSxzyI5dvhBsQGp85ztCN?= =?us-ascii?Q?tW3lNkuTYfgd0JfoOugCDfLQV7LG371xG8mxy+eCZfc079dcpbA0r5EVUsY9?= =?us-ascii?Q?7FR787Q6KdckTYVkDDo6GNNBfCnuK2JrYifMIkBxJ/vhukfIsDJBM+YniuVf?= =?us-ascii?Q?7MUdGfCh0T0cwCZnLSfis6ao771WcW19ZekAuFmvy4oxDVzUezdW+0XiFEAi?= =?us-ascii?Q?ox/lTnied8RSckth6inB+ldhHJYCT48KZ966qZiJp7qjarCk8Lgj0QVkT2Kb?= =?us-ascii?Q?m4vFAq51ulEh0HU82kt79ESyywwL8/5NiXJJFm0hIc3XTFzRhGjWr9majc6g?= =?us-ascii?Q?OHTaM65jpR1GAU578vcz68kKGHrXWeanxroJcdFTPetm5wGZXMkoH0rU5qJE?= =?us-ascii?Q?ESN5PT2u6ZX3RZzaIfqzK0dpfF3OGxM3t9LJ3ESP+RZoB1E2GP8elsPLboBa?= =?us-ascii?Q?lua5W93qBrx3JwWACyQaZ7mbKJIDiGnmsu2RhdAa98UhBohA1FQCQXWlRibW?= =?us-ascii?Q?1xyelBUvHaCJtYtf6Zq0mxzps1xTCVdAq6f0PD7ONBjfLFT3mZeZ9fvv/HjU?= =?us-ascii?Q?f98fdawIcmmSp1TsH/r0ur1yVMaTcqFQvmG3CLdAexOK2uvfC0JIsLQ8GqdB?= =?us-ascii?Q?SiMSNDZKJTdySBc6NBKRe/mVBNACmv0W6kh2nvRfnaJetird+uptXK19m5f+?= =?us-ascii?Q?Av9WYSkNkj3LP+JdsXObQAp6/vtaB26LkYZ4J5oSdL4gnwW7RzsC41JP1LgO?= =?us-ascii?Q?pe0rqufompIZ4fjUw7GpYuIdRghk21JRVc7hJDnHzTuqM5dHdithWcNtgAop?= =?us-ascii?Q?C3FHuDo=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?zN//NQPhVLVPiSw0opgt/ewYIDkn7dpCzbXao4tk656lrwJatt6/BPqQnt3R?= =?us-ascii?Q?dfk47MUKXjZuHW9CrVkGpI6sRJkLN8kL8IKh1DGUnDnuFHuFq4PUErdmeumd?= =?us-ascii?Q?3dnw8ZqK1RmtM2AUM5Fzalz8Je1/zXa7FQCAkF7Oq+cV9u9lQvzEfdB79bR0?= =?us-ascii?Q?CjNE1o0S0z4QA00IM4BsTuLuIVbel2RFSPJvMLB6A0EhtGguBqjPkKM4TVzL?= =?us-ascii?Q?KzHMM0NypmGO01SRAnFY0Iu5F0wN2ziZxFYNTtPQX3WT2jvaMxioXbJqCoH9?= =?us-ascii?Q?v1Sxc/32eBjIDP6/cV6sB3f+eL9cZ5fB8kw8BH0o3dUao6HaQbjptvqL9Buk?= =?us-ascii?Q?mXnXsummKDsQUt+Wnl4rJ6OBhSmJnCaqkShdJLw54wfH1/zzTqYucsp8egAM?= =?us-ascii?Q?gpinPJ8fM8KCTQ21KBwI5xpZZp64AnaW5+OgW5RkYA5yKtaLwcBBQFFiEFP1?= =?us-ascii?Q?Lqs3wzXQiA3SWWJOFWZ3qXg8qk0zXukUCqz7lLr3Q40nTl9EArOvl+gbU8zH?= =?us-ascii?Q?z8TExcVzAw/qJwIyhmw3/SJW0TjPfx5Lxjj7re1BJlIzT/T2eq4ayefT+4/w?= =?us-ascii?Q?eXH9yM003uUafJ11STrzaIs3MPNKqhJlJz5etZYnyU/cTNO6MI6D/Rw/wXoV?= =?us-ascii?Q?rqdFLJO1NelLr+sU+85eju3CJjgFBF+J4IECzPDNakXNbeStpJEdv/NDepwI?= =?us-ascii?Q?vEuu2Wj0bgKIJWUJB6qRip0JBkSbs2RBK5fDuDch/hT9xWtzynneBFBEW0j4?= =?us-ascii?Q?GQgxs6gmh2WFBRrxnyix15I97i7fiBWFjtNQigok9rlkLlW4H5PcdyIHw+R7?= =?us-ascii?Q?hkbj+2GJplOlyHKRM/AxPOnDcdvL38TDOGjR1YMPLwTQAa2ujbmr9Oq8RxQK?= =?us-ascii?Q?cxfweaUy4vFEGpHgYAbegcdU6xF25ITLQRD43L1jyydid07QsdNPDhXqe/bq?= =?us-ascii?Q?8toiP1JpmMxV/ZE9laBzeAiNyIN5M2sPf806zkDT10wUBMzvlWUKh8RBOgHQ?= =?us-ascii?Q?6PPEuVvnWZrpOqX+LBI3MKfC+TlLar3f2eJTQuDF8ZkewFkWE8Zyw0anWaWj?= =?us-ascii?Q?fdxpkndg+12uwj7pyalq58xzeXImwjpQ0n52sv0yC1Y3w5CjOzf5NWm2KDZl?= =?us-ascii?Q?jdhWPjW2u0aaYc80kPyBsNwEtEyQJIB9MfqPt8oOyC4Q8KDm8Zw2OfLrcGWG?= =?us-ascii?Q?649suseabxA0/f+8d1Raf5kCI5eLROU/kTeDiLyuFfPN/tcrvpk5MBu/IYa5?= =?us-ascii?Q?QHIMlUjWc+gRykEEkDlDiEXlODqp76YPkFBiA9X9EYqWbOo84nJR73xEd7cW?= =?us-ascii?Q?m1NuqEunjcZ7fMkDUDUrGa3vi9P7lDRu+3g950hRFNOf9IeDiDd/eMISjh7M?= =?us-ascii?Q?O2XfLIiwCYG3XmfYV1wGBPUIokmvYxOiRvB6Z6+1tnnRJH4kPk7zv2KprpnG?= =?us-ascii?Q?y1KayIvbmgSYOVnzWPl63DHJDlJ2Ad9h8/F+Y9+j4TmKX/lz2aq4tOs3zSvI?= =?us-ascii?Q?pQOtYUMGMS58rVvgqS1NudUc6m76+G9ntn3v9NkfEbNVtBLJz6WE49hDStWD?= =?us-ascii?Q?JC9bRK6STE3upiMfJk7Wsok+pkzzPU+8Q0rtr5Jc?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: e421670b-9532-4e09-b4d8-08dc91c71e6b X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:37.8312 (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: CXzOCehMKs8QFzTfFlpEFgq+aoNTO+HY3B1mWa54u2bLTj+MqLuISmK1b+DaoPSBO7rydmQ+UIUE5B9LzuXMvg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11ac.h | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11ac.h diff --git a/drivers/net/wireless/nxp/nxpwifi/11ac.h b/drivers/net/wireless= /nxp/nxpwifi/11ac.h new file mode 100644 index 000000000000..b060de17a18e --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11ac.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: 802.11ac + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_11AC_H_ +#define _NXPWIFI_11AC_H_ + +#define VHT_CFG_2GHZ BIT(0) +#define VHT_CFG_5GHZ BIT(1) + +enum vht_cfg_misc_config { + VHT_CAP_TX_OPERATION =3D 1, + VHT_CAP_ASSOCIATION, + VHT_CAP_UAP_ONLY +}; + +#define DEFAULT_VHT_MCS_SET 0xfffe +#define DISABLE_VHT_MCS_SET 0xffff + +#define VHT_BW_80_160_80P80 BIT(2) + +int nxpwifi_cmd_append_11ac_tlv(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc, + u8 **buffer); +int nxpwifi_cmd_11ac_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, u16 cmd_action, + struct nxpwifi_11ac_vht_cfg *cfg); +void nxpwifi_fill_vht_cap_tlv(struct nxpwifi_private *priv, + struct ieee80211_vht_cap *vht_cap, u8 bands); +#endif /* _NXPWIFI_11AC_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2045.outbound.protection.outlook.com [40.107.21.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03F8D16D9A5; Fri, 21 Jun 2024 07:52:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.45 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956366; cv=fail; b=TP3a03UgmQ8TKdFcpIz3/+CRrQmV96T16dQJwEOUl1zOxa+YYYztNiuDcs6xbfLrPJRWk6tEyhHlGbVFC+wZ+GPdoHVzpN2mFy3xCGO1ggiWj/k904TdCKfGHV/FWzCWbDEDhABQzc9MMgQ8XKACt7KphTHeGTJGQCR5oBhMTmA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956366; c=relaxed/simple; bh=LLzkHu0h9E9YdY7PJfgq5nNTslIulLjkOHOJ2hAXBcA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=hQw9taqAmLXFxsf2ORkLXALK1seM+GtSmRVcg2I6giHFQx2GoIsrk8S2ivivhOLkKejQksRoY2pXqIKAA4KlMhLv483lRC5NjWg8+fMhtRfiyBIQ12ShATK1fSoAZtAUEhQa8kA7ufWal4lyOadJlJ80gqiF5lwZuP+hC3Y2BUU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=O+ishUq1; arc=fail smtp.client-ip=40.107.21.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="O+ishUq1" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=IwP79VBmXWxV1fkMSBlpgi+wSkTT1DFTRZ81fUiIjvGEBlDfU2AJ3BRNGP7JhzXecCtcBGzYLp+W4JgtszplmjBbusskWqhfYa3gYGc74CGzXn0ezrqgHhFg6tSPDvpoQzu/U0Ei4xNTJWz0JKK36T2MQMs/BsFdAoaapGlgAhrOArhttMT0eKtkZubktoC4crgylBfFWfGdlhEfbqt+lrldzBvvawLgQByghkebxmnz2V9U/2Zuiyl9i+s4umvMbzJ3Spbtezcf9YI+U1vk5ljuwWcZESMeNWE0TMHBuxkOaAyOnJ4kgi0gcDMc1I1ObSoFmb2QUq11bKB0OkWMAg== 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=HafID6muxkDGDhFzNj2vFIwIKuvfQPQRcrZ2D1BQu78=; b=BmkT/I5XCGS12g+H/qFjwhMhlOSIJopGPnPUcHdJsH0BdseLZH3Cvik/IMC0ZmJT9AFnn5GDMpnku0j9IIQ4BCpepgfW2MD4KWNyfX/J2mCzqWHXLkt3QPY2hJIiTXoa09d2116dkcdUTemb5UHIYio6R73yy19sQMtclfW8YDtpZefdxC+Emi9B13d2wWnvhcnwH3EssfhOMyrKbIyyo7fo4T5Wan3CuOjKP55CERXt5swWQ4sGFssOaxAxCzHFXWzthY1Rgp9PJiM/Gh0nLweACmRooLx9yHiH+Zl9yceD5g12+VlxrVip+rQsjxblWCJCG2/sCFuhc+4ddwqWAQ== 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=HafID6muxkDGDhFzNj2vFIwIKuvfQPQRcrZ2D1BQu78=; b=O+ishUq13Y2IcWeD/gWd5obWrTkv+RM62t0L/9ImM7+pNP6M0AfVtmniqR9dbKEBCUuMHBCshdA9RpozXXKaWVfJU/JyP7EOaN7G14mCdTRzCeWrAtHbGu38Ajk0eJzfYN5yIeut0HipxuEt5yH2qADcBmn3+xvPwlK+TP2XhLo= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:41 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:40 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 03/43] wifi: nxpwifi: add 11h.c Date: Fri, 21 Jun 2024 15:51:28 +0800 Message-Id: <20240621075208.513497-4-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 48effe7f-fe0c-4caa-6cdb-08dc91c7203e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?l23u21YEdfQd6XBELvu9AaSqBCqn3fKuLokWPDM1V8t1mdQVJHC+NHKY/WAi?= =?us-ascii?Q?O7vExmij4o/jT6wAlBzfTTfkFxZkccIomRVwB88bJmzHRbgAvVjBrn73PbvM?= =?us-ascii?Q?7RLeHuI5mNN1hsCTxAEMn0i87hEUtfrK7dJZ64G4lPpJgvkihSl+Acalw68E?= =?us-ascii?Q?SPEfL9b1Q/Oy4/CRK83Uga6a6nP/rEbBv3KhhHIowdKf2sLH6KruPrm1DVno?= =?us-ascii?Q?8KkF2oI+vSW4j/t32GxDQATEf52R8oslGsRFMDlrtlDt2s+aLvyViwj4sYin?= =?us-ascii?Q?WVxmTYFzDFCgsV0GooS+GMBIjXzBFypgh9jhfxD/shpV/WFTbuBQAQofDlLQ?= =?us-ascii?Q?fhAuLEa1kd46/q6OfvS+8NWCQWj3ikU4kvQgPEmuKPlt/PYBB9BC8XQ86MVA?= =?us-ascii?Q?WeM1SxuxXz5BLL0XhBgtTJ3RJgyrmDFjKidZbIxYYsudDmCz4Uw9MlMtT4n+?= =?us-ascii?Q?aK7PSIXzNW09bX/RAxY6lqfMTEPzq6Lls+nWf//DzFp5J5Gu2aVbUIV9FVHC?= =?us-ascii?Q?p5xlXECCcSBtoIDd0Z9PUpxDgz47+xJSZBaKh5exbm5MHlEcVTVZVkEaviXj?= =?us-ascii?Q?L//eVxTukTz3RC6Ig8wP2SmIxxnbB4SbU7WZC2v4vnQXnbOvMiT1bgc1E96f?= =?us-ascii?Q?bNQprGDA+WD/W0AtvpPUxRFV9cI3aGsVOE8zcosoLcSOYRrdwgw+NlqGjjqX?= =?us-ascii?Q?xMSMOFd47et87Vb/IBR/FLFmbydAEvQGp5Hj83JbsGdHVY1qn46X/cuB/Bp8?= =?us-ascii?Q?A5xkOtjEzl4j+iltFsA7o5Wr0W7xw1MlWJuT4JvT8F6+RDt4WevFc8Z0qjQD?= =?us-ascii?Q?sxAxTG4rGbACLlr9C/Pgev5yhKyiqwX2cMry8zRiCvjcEpwBf2FLbhchwQdT?= =?us-ascii?Q?HTwD3Q1Bvj9FfDr0DwGh27xHnVrte5RpKLZDlsaovZwWslwPWhZPXyYS7FCS?= =?us-ascii?Q?kjbrbdOQoaMNee8745TJmoiVKO9ID1ErZZ/3/UA408t+6BTrpA6+QgR0SZ6V?= =?us-ascii?Q?MeiVK0ZLNgkUJw/sKf+lXEjTd4c6ErlkCex4yDA5R7g2ChWT43qdwjqf+HvA?= =?us-ascii?Q?y3SWhx2JyrwENeT9iFsxCS8Sv83Ux0EAzpFS9Lz4deUHP4Hwk7lax2OiIuC5?= =?us-ascii?Q?62dMMnOOrFKaYy8im8mSSUnSPy25/4eBpWxkkYdCo9REnl8wSzJ7XwXVOFbR?= =?us-ascii?Q?9bsBGbCzi2aQZyadW1tV7n6mGhaKw/JKCGI1rIx61T8/wuV30n+sdAGCbgUf?= =?us-ascii?Q?Om5dqz2PUKxeMXqqEcLJwRsvZQ+e2DxdiD3qoNuHx4oV0sak3hKLsfrtO/qg?= =?us-ascii?Q?6cRIBLfyGRs1w1DzujMNkPILnT7a7Tip5CxCTdd2u7/k6gtOY5ABEKgB2Fpo?= =?us-ascii?Q?5czy1dU=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?b4RJtbNr+5qqaXrozDxfyTxixtWcgUgkbmclPs9jqK2l5GIjMxrRfptNmwP0?= =?us-ascii?Q?lgIC/JI40cdM3AI/lf/rRCVa0HZX6wqX+AyaMsNTj/JgcvLzf40Jl+KpJv8x?= =?us-ascii?Q?uTq9AA904Fx8TZPdnSw487VTMoXoq5ki8gt0D3tdfincUvVTN+sdYw1E4Mms?= =?us-ascii?Q?aBgTCr76BwwIQm4bHAc7lTHT70pDEiNZPnttdrm8faDSGAvxHl6QuP3dISMk?= =?us-ascii?Q?baECqAmKz5fqNFhwpX6bAoyi1dQUYrDumJXNf5GVeQq5b3M8PCLa21IAlIoT?= =?us-ascii?Q?alPz88cgFZQgniW29DhfZ9Cuc9YpZV8ij3a+vYY2pHei/SjsNIa2i4dIN6Ye?= =?us-ascii?Q?rjZG97K+Zaf60+o/m4jQWhDpTw/FoTZ96w3UovodUvLgqlvlPHmzX7DxxA4r?= =?us-ascii?Q?RTAVTjjbKGzBZjgI7fkIx58owwjdvhZ/qhMoaqZs39dD1KCwRsPNq0A5mvND?= =?us-ascii?Q?joOO8bNDItTXIMDw3EMze/rO7BSqM3qgU7mMjHsJzAhDnMmSlh8UjH3n2e4h?= =?us-ascii?Q?SU3kOpVVjWOQuqWC3xzZ0r0t4W0Qvd7mNp2YfC/ntGH76cvPOCrhbICFoUC7?= =?us-ascii?Q?Gfm51JEeji14PRF9XLesZJCjxhanQwTf3Nrm9BA7nSm/dY8396WCcjBW24rv?= =?us-ascii?Q?urSp5NiFiVXJ4FRHjjP9o0zcHwa4N2A6MszwFczF6gJv/ZGI2S2PJLB4PfIf?= =?us-ascii?Q?5wf1yg6iZE19qflgMx2MllvU2BtMIQc6zyg5fe9jCOhyqBLG5v+OMM3vjYrX?= =?us-ascii?Q?KbMm6gx6DLfDJstYCJ2U3EOijqutjC9KunpG0Wkqanzl/iOQMpezki0mE1Ur?= =?us-ascii?Q?EVdD/kU2Dl2XynfJ93+ZHk0qbWFHhAgTAL59QeGhdOpamtZpzhFVfnTT5DIh?= =?us-ascii?Q?ohsCOu0Ke/KcSR+3MaLe9urKPWFoVB4/HkI2HUFuHJ732dt/HtCwPC5C+Idn?= =?us-ascii?Q?/oX7wrAuPjuNnrsv5v6gQm5NbaYNholNMwjWLJY5vIw3SvY8WAET+oxr5Nv3?= =?us-ascii?Q?7zRNOXjrZX3cmPp5sB9BGDtIUhfcIZbQUYcvfforF1quc8O6l828WATVgfP0?= =?us-ascii?Q?BIisP04DmpQ9eenLZo5JKOndwLFvp+ps9qCSzFdU6Q/n8Sf7mmnjY8b8qan6?= =?us-ascii?Q?7uKkBEEyKx5W5MJI1p3zs6D2J0We9dzmITzBTM7iRD5wMe+QtClPJaKjheYq?= =?us-ascii?Q?INzQ1EN/sZKuORQ9RgFffAbEncThipti+kq8iFaS4BP//rKP1vPQ0uaE1/ZV?= =?us-ascii?Q?n/1gkwlfb7kmCgSWMpP4lPtnAWebhwnMnoiaVK6KOp8NI4JqjbioYT5PH1Vs?= =?us-ascii?Q?kKzBptnG0evgooSluJ9RK0EAdXO9clI7rGkR/cf9Jn29ZtfXYUEGYVz9AyRI?= =?us-ascii?Q?NYXL5L0kn+TqEV7NcNEsnatNH7nVe0yOLDVccLyPG3sD4Yiw1sjhUFc3FNy1?= =?us-ascii?Q?nPFRH8vvG2SitFFKSjUskUSDXovKAf8WwNYVkQokvSAO5qTlafp7PRsnVJkr?= =?us-ascii?Q?Yi/q03IIKeV79xqkn4NPCap6YBHYNl34BJ08U8Y5nYvG55dAaOPaIM8+Kqnw?= =?us-ascii?Q?vtZyTsXxusILTvrOFAKpOHXd4pnl9xF8TMkL6xFb?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 48effe7f-fe0c-4caa-6cdb-08dc91c7203e X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:40.8900 (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: SW4dS6IdpjcEnuCt7mwjthBgn8e+5R2HH8FvuIOBOZ1ptcQ3wXrnTBAQhcpowXzopDkfkB/UsVBcqxDaYYTVwg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11h.c | 432 +++++++++++++++++++++++++ 1 file changed, 432 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11h.c diff --git a/drivers/net/wireless/nxp/nxpwifi/11h.c b/drivers/net/wireless/= nxp/nxpwifi/11h.c new file mode 100644 index 000000000000..4bd21e1686e6 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11h.c @@ -0,0 +1,432 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: 802.11h + * + * Copyright 2011-2024 NXP + */ + +#include "main.h" +#include "cmdevt.h" +#include "fw.h" +#include "cfg80211.h" + +void nxpwifi_init_11h_params(struct nxpwifi_private *priv) +{ + priv->state_11h.is_11h_enabled =3D true; + priv->state_11h.is_11h_active =3D false; +} + +inline int nxpwifi_is_11h_active(struct nxpwifi_private *priv) +{ + return priv->state_11h.is_11h_active; +} + +/* This function appends 11h info to a buffer while joining an + * infrastructure BSS + */ +static void +nxpwifi_11h_process_infra_join(struct nxpwifi_private *priv, u8 **buffer, + struct nxpwifi_bssdescriptor *bss_desc) +{ + struct nxpwifi_ie_types_header *ie_header; + struct nxpwifi_ie_types_pwr_capability *cap; + struct nxpwifi_ie_types_local_pwr_constraint *constraint; + struct ieee80211_supported_band *sband; + u8 radio_type; + int i; + + if (!buffer || !(*buffer)) + return; + + radio_type =3D nxpwifi_band_to_radio_type((u8)bss_desc->bss_band); + sband =3D priv->wdev.wiphy->bands[radio_type]; + + cap =3D (struct nxpwifi_ie_types_pwr_capability *)*buffer; + cap->header.type =3D cpu_to_le16(WLAN_EID_PWR_CAPABILITY); + cap->header.len =3D cpu_to_le16(2); + cap->min_pwr =3D 0; + cap->max_pwr =3D 0; + *buffer +=3D sizeof(*cap); + + constraint =3D (struct nxpwifi_ie_types_local_pwr_constraint *)*buffer; + constraint->header.type =3D cpu_to_le16(WLAN_EID_PWR_CONSTRAINT); + constraint->header.len =3D cpu_to_le16(2); + constraint->chan =3D bss_desc->channel; + constraint->constraint =3D bss_desc->local_constraint; + *buffer +=3D sizeof(*constraint); + + ie_header =3D (struct nxpwifi_ie_types_header *)*buffer; + ie_header->type =3D cpu_to_le16(TLV_TYPE_PASSTHROUGH); + ie_header->len =3D cpu_to_le16(2 * sband->n_channels + 2); + *buffer +=3D sizeof(*ie_header); + *(*buffer)++ =3D WLAN_EID_SUPPORTED_CHANNELS; + *(*buffer)++ =3D 2 * sband->n_channels; + for (i =3D 0; i < sband->n_channels; i++) { + u32 center_freq; + + center_freq =3D sband->channels[i].center_freq; + *(*buffer)++ =3D ieee80211_frequency_to_channel(center_freq); + *(*buffer)++ =3D 1; /* one channel in the subband */ + } +} + +/* Enable or disable the 11h extensions in the firmware */ +int nxpwifi_11h_activate(struct nxpwifi_private *priv, bool flag) +{ + u32 enable =3D flag; + + /* enable master mode radar detection on AP interface */ + if ((GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) && enable) + enable |=3D NXPWIFI_MASTER_RADAR_DET_MASK; + + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_SET, DOT11H_I, &enable, true); +} + +/* This functions processes TLV buffer for a pending BSS Join command. + * + * Activate 11h functionality in the firmware if the spectrum management + * capability bit is found in the network we are joining. Also, necessary + * TLVs are set based on requested network's 11h capability. + */ +void nxpwifi_11h_process_join(struct nxpwifi_private *priv, u8 **buffer, + struct nxpwifi_bssdescriptor *bss_desc) +{ + if (bss_desc->sensed_11h) { + /* Activate 11h functions in firmware, turns on capability + * bit + */ + nxpwifi_11h_activate(priv, true); + priv->state_11h.is_11h_active =3D true; + bss_desc->cap_info_bitmap |=3D WLAN_CAPABILITY_SPECTRUM_MGMT; + nxpwifi_11h_process_infra_join(priv, buffer, bss_desc); + } else { + /* Deactivate 11h functions in the firmware */ + nxpwifi_11h_activate(priv, false); + priv->state_11h.is_11h_active =3D false; + bss_desc->cap_info_bitmap &=3D ~WLAN_CAPABILITY_SPECTRUM_MGMT; + } +} + +/* This is DFS CAC work queue function. + * This delayed work emits CAC finished event for cfg80211 if + * CAC was started earlier. + */ +void nxpwifi_dfs_cac_work_queue(struct work_struct *work) +{ + struct cfg80211_chan_def chandef; + struct delayed_work *delayed_work =3D to_delayed_work(work); + struct nxpwifi_private *priv =3D + container_of(delayed_work, struct nxpwifi_private, + dfs_cac_work); + + chandef =3D priv->dfs_chandef; + if (priv->wdev.cac_started) { + nxpwifi_dbg(priv->adapter, MSG, + "CAC timer finished; No radar detected\n"); + cfg80211_cac_event(priv->netdev, &chandef, + NL80211_RADAR_CAC_FINISHED, + GFP_KERNEL); + } +} + +static u8 nxpwifi_get_channel_2_offset(int chan) +{ + u8 chan2_offset =3D SEC_CHAN_NONE; + + switch (chan) { + case 36: + case 44: + case 52: + case 60: + case 100: + case 108: + case 116: + case 124: + case 132: + case 140: + case 149: + case 157: + case 165: + case 173: + chan2_offset =3D SEC_CHAN_ABOVE; + break; + case 40: + case 48: + case 56: + case 64: + case 104: + case 112: + case 120: + case 128: + case 136: + case 144: + case 153: + case 161: + case 169: + case 177: + chan2_offset =3D SEC_CHAN_BELOW; + break; + } + + return chan2_offset; +} + +static void nxpwifi_convert_chan_to_band_cfg(u8 *band_cfg, + struct cfg80211_chan_def *chan_def) +{ + u8 chan_band, chan_width, chan2_offset; + + switch (chan_def->chan->band) { + case NL80211_BAND_2GHZ: + chan_band =3D BAND_2GHZ; + break; + case NL80211_BAND_5GHZ: + chan_band =3D BAND_5GHZ; + break; + default: + break; + } + + switch (chan_def->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + chan_width =3D CHAN_BW_20MHZ; + break; + case NL80211_CHAN_WIDTH_40: + chan_width =3D CHAN_BW_40MHZ; + if (chan_def->center_freq1 > chan_def->chan->center_freq) + chan2_offset =3D SEC_CHAN_ABOVE; + else + chan2_offset =3D SEC_CHAN_BELOW; + break; + case NL80211_CHAN_WIDTH_80: + chan2_offset =3D + nxpwifi_get_channel_2_offset(chan_def->chan->hw_value); + chan_width =3D CHAN_BW_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + case NL80211_CHAN_WIDTH_160: + default: + break; + } + + *band_cfg =3D ((chan2_offset << BAND_CFG_CHAN2_SHIFT_BIT) & + BAND_CFG_CHAN2_OFFSET_MASK) | + ((chan_width << BAND_CFG_CHAN_WIDTH_SHIFT_BIT) & + BAND_CFG_CHAN_WIDTH_MASK) | + ((chan_band << BAND_CFG_CHAN_BAND_SHIFT_BIT) & + BAND_CFG_CHAN_BAND_MASK); +} + +/* This function prepares channel report request command to FW for + * starting radar detection. + */ +int nxpwifi_cmd_issue_chan_report_request(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_chan_rpt_req *cr_req =3D &cmd->params.chan_rpt_req; + struct nxpwifi_radar_params *radar_params =3D (void *)data_buf; + u16 size; + + cmd->command =3D cpu_to_le16(HOST_CMD_CHAN_REPORT_REQUEST); + size =3D S_DS_GEN; + + cr_req->chan_desc.start_freq =3D cpu_to_le16(NXPWIFI_A_BAND_START_FREQ); + nxpwifi_convert_chan_to_band_cfg(&cr_req->chan_desc.band_cfg, + radar_params->chandef); + cr_req->chan_desc.chan_num =3D radar_params->chandef->chan->hw_value; + cr_req->msec_dwell_time =3D cpu_to_le32(radar_params->cac_time_ms); + size +=3D sizeof(*cr_req); + + if (radar_params->cac_time_ms) { + struct nxpwifi_ie_types_chan_rpt_data *rpt; + + rpt =3D (struct nxpwifi_ie_types_chan_rpt_data *)((u8 *)cmd + size); + rpt->header.type =3D cpu_to_le16(TLV_TYPE_CHANRPT_11H_BASIC); + rpt->header.len =3D cpu_to_le16(sizeof(u8)); + rpt->meas_rpt_map =3D 1 << MEAS_RPT_MAP_RADAR_SHIFT_BIT; + size +=3D sizeof(*rpt); + + nxpwifi_dbg(priv->adapter, MSG, + "11h: issuing DFS Radar check for channel=3D%d\n", + radar_params->chandef->chan->hw_value); + } else { + nxpwifi_dbg(priv->adapter, MSG, "cancelling CAC\n"); + } + + cmd->size =3D cpu_to_le16(size); + + return 0; +} + +int nxpwifi_stop_radar_detection(struct nxpwifi_private *priv, + struct cfg80211_chan_def *chandef) +{ + struct nxpwifi_radar_params radar_params; + + memset(&radar_params, 0, sizeof(struct nxpwifi_radar_params)); + radar_params.chandef =3D chandef; + radar_params.cac_time_ms =3D 0; + + return nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REPORT_REQUEST, + HOST_ACT_GEN_SET, 0, &radar_params, true); +} + +/* This function is to abort ongoing CAC upon stopping AP operations + * or during unload. + */ +void nxpwifi_abort_cac(struct nxpwifi_private *priv) +{ + if (priv->wdev.cac_started) { + if (nxpwifi_stop_radar_detection(priv, &priv->dfs_chandef)) + nxpwifi_dbg(priv->adapter, ERROR, + "failed to stop CAC in FW\n"); + nxpwifi_dbg(priv->adapter, MSG, + "Aborting delayed work for CAC.\n"); + cancel_delayed_work_sync(&priv->dfs_cac_work); + cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); + } +} + +/* This function handles channel report event from FW during CAC period. + * If radar is detected during CAC, driver indicates the same to cfg80211 + * and also cancels ongoing delayed work. + */ +int nxpwifi_11h_handle_chanrpt_ready(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct host_cmd_ds_chan_rpt_event *rpt_event; + struct nxpwifi_ie_types_chan_rpt_data *rpt; + u16 event_len, tlv_len; + + rpt_event =3D (void *)(skb->data + sizeof(u32)); + event_len =3D skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event) + + sizeof(u32)); + + if (le32_to_cpu(rpt_event->result) !=3D HOST_RESULT_OK) { + nxpwifi_dbg(priv->adapter, ERROR, + "Error in channel report event\n"); + return -1; + } + + while (event_len >=3D sizeof(struct nxpwifi_ie_types_header)) { + rpt =3D (void *)&rpt_event->tlvbuf; + tlv_len =3D le16_to_cpu(rpt->header.len); + + switch (le16_to_cpu(rpt->header.type)) { + case TLV_TYPE_CHANRPT_11H_BASIC: + if (rpt->meas_rpt_map & MEAS_RPT_MAP_RADAR_MASK) { + nxpwifi_dbg(priv->adapter, MSG, + "RADAR Detected on channel %d!\n", + priv->dfs_chandef.chan->hw_value); + cancel_delayed_work_sync(&priv->dfs_cac_work); + cfg80211_cac_event(priv->netdev, + &priv->dfs_chandef, + NL80211_RADAR_CAC_ABORTED, + GFP_KERNEL); + cfg80211_radar_event(priv->adapter->wiphy, + &priv->dfs_chandef, + GFP_KERNEL); + } + break; + default: + break; + } + + event_len -=3D (tlv_len + sizeof(rpt->header)); + } + + return 0; +} + +/* Handler for radar detected event from FW.*/ +int nxpwifi_11h_handle_radar_detected(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_radar_det_event *rdr_event; + + rdr_event =3D (void *)(skb->data + sizeof(u32)); + + nxpwifi_dbg(priv->adapter, MSG, + "radar detected; indicating kernel\n"); + if (priv->wdev.cac_started) { + if (nxpwifi_stop_radar_detection(priv, &priv->dfs_chandef)) + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to stop CAC in FW\n"); + cancel_delayed_work_sync(&priv->dfs_cac_work); + cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); + } + cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef, + GFP_KERNEL); + nxpwifi_dbg(priv->adapter, MSG, "regdomain: %d\n", + rdr_event->reg_domain); + nxpwifi_dbg(priv->adapter, MSG, "radar detection type: %d\n", + rdr_event->det_type); + + return 0; +} + +/* This is work queue function for channel switch handling. + * This function takes care of updating new channel definitin to + * bss config structure, restart AP and indicate channel switch success + * to cfg80211. + */ +void nxpwifi_dfs_chan_sw_work_queue(struct work_struct *work) +{ + struct nxpwifi_uap_bss_param *bss_cfg; + struct delayed_work *delayed_work =3D to_delayed_work(work); + struct nxpwifi_private *priv =3D container_of(delayed_work, + struct nxpwifi_private, + dfs_chan_sw_work); + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (nxpwifi_del_mgmt_ies(priv)) + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to delete mgmt IEs!\n"); + + bss_cfg =3D &priv->bss_cfg; + if (!bss_cfg->beacon_period) { + nxpwifi_dbg(adapter, ERROR, + "channel switch: AP already stopped\n"); + return; + } + + if (nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_STOP, + HOST_ACT_GEN_SET, 0, NULL, true)) { + nxpwifi_dbg(adapter, ERROR, + "channel switch: Failed to stop the BSS\n"); + return; + } + + if (nxpwifi_cfg80211_change_beacon_data(adapter->wiphy, priv->netdev, + &priv->beacon_after)) { + nxpwifi_dbg(adapter, ERROR, + "channel switch: Failed to set beacon\n"); + return; + } + + nxpwifi_uap_set_channel(priv, bss_cfg, priv->dfs_chandef); + + if (nxpwifi_config_start_uap(priv, bss_cfg)) { + nxpwifi_dbg(adapter, ERROR, + "Failed to start AP after channel switch\n"); + return; + } + + nxpwifi_dbg(adapter, MSG, + "indicating channel switch completion to kernel\n"); + wiphy_lock(priv->wdev.wiphy); + cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0); + wiphy_unlock(priv->wdev.wiphy); + + if (priv->uap_stop_tx) { + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + nxpwifi_wake_up_net_dev_queue(priv->netdev, adapter); + priv->uap_stop_tx =3D false; + } +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2045.outbound.protection.outlook.com [40.107.21.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B32B216D9D2; Fri, 21 Jun 2024 07:52:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.45 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956369; cv=fail; b=lQ7H2Dbyl59sTLXqdw4eyKuAcf6h0ngWk2DGXCLIUXNo0kj/mdGaejhb8Y5vQJ/tRxUjXpVvAj1vEmNOaXjZIWyOB7FmCfcYIRRhODb6inn3pkhYi/jDd5gyGi1GcdYnzWCqVk7DefRybAL+XJChV1X1bke+hwCp44CnVJY0v5E= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956369; c=relaxed/simple; bh=6RZarGx0ac+AyKPisDSefWR9U63H2PaXoFIouV4D2U8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=GlQSrOddqDYVSh6mSCALrlxxgm+yDvK4HA9UXJxk8YkVc1NlHIasNIeWwbW8Cx6OH9rY4MQPckIuR/rf3ub1oMuCcz1skIdTVCOhmks1eqnMBxfhoN0Bvn2hG7+ykXto7RExEE5slp+KL+Xnan6wflQzBxVtnudaof7IgAHxHNE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=OUOD3ZKh; arc=fail smtp.client-ip=40.107.21.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="OUOD3ZKh" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lRZWIzKGQdOzN432Wbrp0JYBDkH7wF4e4Nx9s8j8G26ptHqPLQBk90GVhHyxpex5+GGf4sON0lgGy+4UW01YAyDYd+3oEAyDQTSxDJBp6/h2G8pvaAmUdgx2sj8YlG6ozzg/XcvJij9Xl/Pg7pWb8YjSVMIal/1RVLii8C3iLEPsx1y03bTDzGQgs4M338hAohCgqtAVm8/URRz4CqnCM2eci6Grsy44eo2UY4C/ZsRfSYzsi6ctbnEkFT2K+8L6f8rlL+HsIav66fefoVfZVjrNQLoPBpnpBphCgX0pSKlWhrKxeko+MYoNCCS2u8f4cppHBbFlTDanetJFkN7BNw== 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=TPyQ3+F5mqca036GLWj2FtjCHg1aWCq/qapY2jDNlX0=; b=VnwGEw7RWfMBsrTUH0TqBeTU2yNLZeeaZRBpg/l8GtZxMSEVMpPNxWkJf6PNZhFVMORXQV7bB2meNoXcOd66nADmgNog0vyuWyk4uB3Xb6B5jp1uxUj+jZtvdsk6H/z/7qhtxmMJbryKmdydyNvchUQ415EYq1+mISl9bYGghwBEbFZ6dCqrfUv6hpZNAf0M7Gz5aQmkshgpK7E+sdQvW6x3MrsjZtasuzcglzdYonkfkDYOcNvhewNaZ8yDGfBhHIkKHX1ajmlQShLsd9w6cWd8GdmGmSjGiIcY19uJbVqKgVs3/T5tZQiqHDfLVBO+q9DEQ3Sz6qp68rItfz/CEA== 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=TPyQ3+F5mqca036GLWj2FtjCHg1aWCq/qapY2jDNlX0=; b=OUOD3ZKhf1zp1qZBY2JogVsQw9ty+J0YLeyBq4ZKV00D2DRumlxqOu0ny/jblaQQc+FsLqivqWimJ+CqE1o2z7OiSjtJSTyezofCccc1eyTqkLA+FCxBwLetjrJlNHbpzc7+CIwWxCowFu2PhQl9XAsrxFYjAgeK59HRYEya3bw= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:45 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:45 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 04/43] wifi: nxpwifi: add 11n.c Date: Fri, 21 Jun 2024 15:51:29 +0800 Message-Id: <20240621075208.513497-5-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 39e8e84f-1991-4802-18f6-08dc91c7224b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?E1hbOmztGHaOxOEx/fdpoGg/+iOucYoxEsXJCyinKePq3UI9GoqHKSSgaRSM?= =?us-ascii?Q?PWKBm6Jgn6gvA3bxS4//CA7B1lKhHvAKZNtzkPFw2AA87kimAkenNVIiEfkW?= =?us-ascii?Q?T+SfN3a/MK2HiaT/U7TPQwuPRH+V/Ew5M/kuSIvGhuFSpza5fPpCO9rR0ffp?= =?us-ascii?Q?DNbgq07nWY9CMIJ6pbGdFIwkXEnSAjZwvKwFi5xuISEc5NOQQEDhgb0NJ30P?= =?us-ascii?Q?cNk9y8qCw/W/bHeEnogB8Ep83mJxaLPEDfmDdOFuYOvQrIaGiy7yOFX837KS?= =?us-ascii?Q?CE6BBdLgIhshawAoB2KtOtsDv7WUd59Hmcqn8DOUHhSmMIRmVEbecM8Z4NVJ?= =?us-ascii?Q?cyvBalwgtx21HsxuuXFHgbXMNCsIH27D89Q1fO+EpNwVgC/ZbywDutHLjpE+?= =?us-ascii?Q?A+yg/9w+ZLHx3u2naLL2Jk73xKvXiigE9f4d25w41nkdxYUkx3iDoYFcnhOy?= =?us-ascii?Q?ifJiZF4U1qD/pyaXf5QruxfSpP5UoBXNm00AnOO2i74GkJE+o1+xCaxxKZgy?= =?us-ascii?Q?n1gWAI1qa6CKiY2ugoZtk6w25amgDtXWvlUBH5Cbyyk2wVZURjGZy9NAWNFF?= =?us-ascii?Q?3RqCpC3Rc5aG4l5/TxD9uyNAcusgonTuTd2mjqt4zARTAQGrgbmB14I86ejw?= =?us-ascii?Q?PbnheUai/8Fw9vmIek3Rj/2K2YQQF8aCLib0yOsxYxuwmHAPxPe1QWyFTT6u?= =?us-ascii?Q?95sW1UWVU3jmveSXnfGJmNuzIYz/X5oPnarEdLdspoUsnc0f/bhRHwyIRTrS?= =?us-ascii?Q?OUClRpF1tM8lCZs+sTj1Xjvw+6E386Z4hZ70s0jMbI9kgPNn8SmMAZxfC4ex?= =?us-ascii?Q?AsS1muRlRPe+kPjstk0l08tSNKK9b90cJkOuC5UdPFRkEQDxqVZgCCefmS0X?= =?us-ascii?Q?FtuyGYAV3yaiQMpo9a2+GejAhR2ZfnLrkseslZS5DEA+XnmPESho+Q2S3HhM?= =?us-ascii?Q?Pt6r1M8o8oJ031S1rN5pyXw9X5eB+3kuqou3+eNImWCARazbmPN2ltJu+sGt?= =?us-ascii?Q?bSwZttWKvaFUIdugOeGVD8hIsj3aDftTOlPGSjYm+ZiJ0OS7GLKLADCnT45c?= =?us-ascii?Q?lOP/wb70+dX2OHtSyJUKiIAlE3/yiDCGSkX0S1k0LZdaqebm8mKClgmR0IP2?= =?us-ascii?Q?tJYdkggaNkPeITIU/FY+M3QnyW4FWTrHBeK8/Vu54y5T8tieNDsCWh7FU32k?= =?us-ascii?Q?+W02kIjCuyrj5ej3zr9BJnL58tW/1Ql1VPYIYlaA52eeE6ozBJQaS76KDGXR?= =?us-ascii?Q?xpMUfmy1Js8cTrmxzW2RZxC09myf6xLybqWXyRxYkPYlrZ9hkxfuS7eB/ma1?= =?us-ascii?Q?qEIPcpeN+XAH+1P4QeKao1PTxm1RmbKoEz48/avnNTra44ih6hcheQByAabl?= =?us-ascii?Q?qCMy2oQ=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?XiALGpBSxLvEj/LzObbAiYDZHjDt3r1zuFD202Fv0Ix/El015oZptbktghVK?= =?us-ascii?Q?34peOVMpmQUawSJr1Zt0xmQOIkK8pKg4AMniEHV3RaqBhs0mhFovPWl2eVCp?= =?us-ascii?Q?asGjXZAn1M5lUiBfFmlHUZ8Y55J2aXHVxwLzZT7vutaMvP6hoNcjf+fQ3Hmy?= =?us-ascii?Q?ngyfXgDYM7cSUTKz4R1fFgg49yD7XExS4VXGuyaMMC2rkNbLq17h06RxJ6qI?= =?us-ascii?Q?I9kurYe1bMiNofp41Fyb4I8y8W2SoMGzbo3eBR8JThER9DElgTF0+81TvGrS?= =?us-ascii?Q?nHXkcHK7jzuaEl0xDCBXXxtYZ4n6yJqWqlCJ9qDfiPygv2e19/VZrkkbcbBz?= =?us-ascii?Q?HSj25+6uGaMyDpE5ICtD6+d6V3ZVeoDCa77B7vJ+TVxw2h/15ap742X9h5V7?= =?us-ascii?Q?CngCRnVG/r0hsdxu8pWpgqcoJqRtUsbkEbi8Om9ehv45g7BB5T5XItRkmMCl?= =?us-ascii?Q?fGOTvlmO/lukMMjn84yFeCRW5rhMgtCVLvnF12p641pQ+JshYCGEq65pQVYy?= =?us-ascii?Q?k1AQiklNIsLY6YznH3aOjVeAXrPuEUY1G236KsaCCT7GT0KR2zCfd8I6kkY4?= =?us-ascii?Q?DqLQ9CN8FSyDj606dRH6q0Vy2enQMw4BZD9ys3f3Oudzo348cIVM/auOTK/h?= =?us-ascii?Q?z+NF4YB0kEuKvm3sxl9J/pY5yuX6M5zq/+hYU40v9QHrAxE16/afzmClEsLR?= =?us-ascii?Q?b7YHFLrOoxCbykr3VOgVSM05sDNWUj/3GDgFkTghyqNnk5ZiYHmDiBpoJxuh?= =?us-ascii?Q?NBlQRDBgjlMeM7+AgBS1gFayrsOfdEnbrPLTbqKFbd5lp5ZM1Ps564cdQMiV?= =?us-ascii?Q?tEJneWnzhIyeLpljhoDZA3+Ts/pWiAOoRbkfPPcpYa6VV1c86+V5Zxr/1GBc?= =?us-ascii?Q?KTfFxd1FoYAGESayi6QQnQRGQCpi7FCHSUYQJXRyNmL6hUmS4+aQK2a5pFRD?= =?us-ascii?Q?kdqMb3VvB3s8E3noK1Rc02u8t88njnhF2alvIbGv+hLPeh11tV82gHgoYKjl?= =?us-ascii?Q?JZW3zq4bb6xRir4bKtJq6wnNtTpYLigqhQJM7lkAhXDskg4VPdrwcxyHk9v0?= =?us-ascii?Q?8pGshMNYVhFDtDvpEr8UH96HCRCDYNeFMJWVfj8OGEwM0i3Ut0Zn+mY4Wa7L?= =?us-ascii?Q?ucRjmreibXsWh0kDXLk6qRqmWtv9bI2ykjE/ZTI5HFDWcDsdnhNjmq0wtWjH?= =?us-ascii?Q?pEHgnl7SwGWCh4giFhRaToqQB1UKaa6rwYciJjL3a1m29smx0ev4AlXYmpv5?= =?us-ascii?Q?8WI9rKuh07d36PfsEshLf03tj3WYFLDIFuU+8ylvY/0wI9kPkXnBiMcEPjr0?= =?us-ascii?Q?K9wAo5YkCTR+ZcdpTdBHx5NeFCKGTVq7f1+jinbETUaiFR4fPNpnw2KAuqpa?= =?us-ascii?Q?RC8XjzSiBCviDci1v8lutqmApfPEoJHsu1dggfS/h2BZ41o42ARsjF8nUvqP?= =?us-ascii?Q?fD1SDtt4C7lZh8elBwEdNdop7wzZFvDECZw+7W5k2RSWx2QB9DMBrR+N7akW?= =?us-ascii?Q?CFZgRcd3IWtWBRkWwO63+4e9Q8XQTPYXOcT5E6dcoHK48IpOdTx6XNh4hqeZ?= =?us-ascii?Q?AVpTRQChtmL1ioo4ObgXVV24eNIzb+1jf9f7X52a?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 39e8e84f-1991-4802-18f6-08dc91c7224b X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:45.0414 (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: wWRv1wqU5BzQNeRztleqXKwKa5/O13gkxmo9bPm7iQyC1UPc7nD+7Ss530eLGmFXYM3nIAvPzQgk1BJIqB3pjQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11n.c | 851 +++++++++++++++++++++++++ 1 file changed, 851 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11n.c diff --git a/drivers/net/wireless/nxp/nxpwifi/11n.c b/drivers/net/wireless/= nxp/nxpwifi/11n.c new file mode 100644 index 000000000000..76f01fa6387f --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n.c @@ -0,0 +1,851 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: 802.11n + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" + +/* Fills HT capability information field, AMPDU Parameters field, HT exten= ded + * capability field, and supported MCS set fields. + * + * HT capability information field, AMPDU Parameters field, supported MCS = set + * fields are retrieved from cfg80211 stack + * + * RD responder bit to set to clear in the extended capability header. + */ +int nxpwifi_fill_cap_info(struct nxpwifi_private *priv, u8 radio_type, + struct ieee80211_ht_cap *ht_cap) +{ + u16 ht_cap_info; + u16 bcn_ht_cap =3D le16_to_cpu(ht_cap->cap_info); + u16 ht_ext_cap =3D le16_to_cpu(ht_cap->extended_ht_cap_info); + struct ieee80211_supported_band *sband =3D + priv->wdev.wiphy->bands[radio_type]; + + if (WARN_ON_ONCE(!sband)) { + nxpwifi_dbg(priv->adapter, ERROR, "Invalid radio type!\n"); + return -EINVAL; + } + + ht_cap->ampdu_params_info =3D + (sband->ht_cap.ampdu_factor & + IEEE80211_HT_AMPDU_PARM_FACTOR) | + ((sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & + IEEE80211_HT_AMPDU_PARM_DENSITY); + + memcpy((u8 *)&ht_cap->mcs, &sband->ht_cap.mcs, + sizeof(sband->ht_cap.mcs)); + + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION || + (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && + priv->adapter->sec_chan_offset !=3D IEEE80211_HT_PARAM_CHA_SEC_NONE)) + /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ + SETHT_MCS32(ht_cap->mcs.rx_mask); + + /* Clear RD responder bit */ + ht_ext_cap &=3D ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; + + ht_cap_info =3D sband->ht_cap.cap; + if (bcn_ht_cap) { + if (!(bcn_ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + ht_cap_info &=3D ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + if (!(bcn_ht_cap & IEEE80211_HT_CAP_SGI_40)) + ht_cap_info &=3D ~IEEE80211_HT_CAP_SGI_40; + if (!(bcn_ht_cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) + ht_cap_info &=3D ~IEEE80211_HT_CAP_40MHZ_INTOLERANT; + } + ht_cap->cap_info =3D cpu_to_le16(ht_cap_info); + ht_cap->extended_ht_cap_info =3D cpu_to_le16(ht_ext_cap); + + if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap)) + ht_cap->tx_BF_cap_info =3D cpu_to_le32(NXPWIFI_DEF_11N_TX_BF_CAP); + + return 0; +} + +/* This function returns the pointer to an entry in BA Stream + * table which matches the requested BA status. + */ +static struct nxpwifi_tx_ba_stream_tbl * +nxpwifi_get_ba_status(struct nxpwifi_private *priv, + enum nxpwifi_ba_status ba_status) +{ + struct nxpwifi_tx_ba_stream_tbl *tx_ba_tsr_tbl; + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (tx_ba_tsr_tbl->ba_status =3D=3D ba_status) { + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + return tx_ba_tsr_tbl; + } + } + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + return NULL; +} + +/* This function handles the command response of delete a block + * ack request. + * + * The function checks the response success status and takes action + * accordingly (send an add BA request in case of success, or recreate + * the deleted stream in case of failure, if the add BA was also + * initiated by us). + */ +int nxpwifi_ret_11n_delba(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + int tid; + struct nxpwifi_tx_ba_stream_tbl *tx_ba_tbl; + struct host_cmd_ds_11n_delba *del_ba =3D &resp->params.del_ba; + u16 del_ba_param_set =3D le16_to_cpu(del_ba->del_ba_param_set); + + tid =3D del_ba_param_set >> DELBA_TID_POS; + if (del_ba->del_result =3D=3D BA_RESULT_SUCCESS) { + nxpwifi_del_ba_tbl(priv, tid, del_ba->peer_mac_addr, + TYPE_DELBA_SENT, + INITIATOR_BIT(del_ba_param_set)); + + tx_ba_tbl =3D nxpwifi_get_ba_status(priv, BA_SETUP_INPROGRESS); + if (tx_ba_tbl) + nxpwifi_send_addba(priv, tx_ba_tbl->tid, + tx_ba_tbl->ra); + } else { /* + * In case of failure, recreate the deleted stream in case + * we initiated the DELBA + */ + if (!INITIATOR_BIT(del_ba_param_set)) + return 0; + + nxpwifi_create_ba_tbl(priv, del_ba->peer_mac_addr, tid, + BA_SETUP_INPROGRESS); + + tx_ba_tbl =3D nxpwifi_get_ba_status(priv, BA_SETUP_INPROGRESS); + + if (tx_ba_tbl) + nxpwifi_del_ba_tbl(priv, tx_ba_tbl->tid, tx_ba_tbl->ra, + TYPE_DELBA_SENT, true); + } + + return 0; +} + +/* This function handles the command response of add a block + * ack request. + * + * Handling includes changing the header fields to CPU formats, checking + * the response success status and taking actions accordingly (delete the + * BA stream table in case of failure). + */ +int nxpwifi_ret_11n_addba_req(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + int tid, tid_down; + struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =3D &resp->params.add_ba_rsp; + struct nxpwifi_tx_ba_stream_tbl *tx_ba_tbl; + struct nxpwifi_ra_list_tbl *ra_list; + u16 block_ack_param_set =3D le16_to_cpu(add_ba_rsp->block_ack_param_set); + + add_ba_rsp->ssn =3D cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) + & SSN_MASK); + + tid =3D (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + + tid_down =3D nxpwifi_wmm_downgrade_tid(priv, tid); + ra_list =3D nxpwifi_wmm_get_ralist_node(priv, tid_down, + add_ba_rsp->peer_mac_addr); + if (le16_to_cpu(add_ba_rsp->status_code) !=3D BA_RESULT_SUCCESS) { + if (ra_list) { + ra_list->ba_status =3D BA_SETUP_NONE; + ra_list->amsdu_in_ampdu =3D false; + } + nxpwifi_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, + TYPE_DELBA_SENT, true); + if (add_ba_rsp->add_rsp_result !=3D BA_RESULT_TIMEOUT) + priv->aggr_prio_tbl[tid].ampdu_ap =3D + BA_STREAM_NOT_ALLOWED; + return 0; + } + + tx_ba_tbl =3D nxpwifi_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr); + if (tx_ba_tbl) { + nxpwifi_dbg(priv->adapter, EVENT, "info: BA stream complete\n"); + tx_ba_tbl->ba_status =3D BA_SETUP_COMPLETE; + if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && + priv->add_ba_param.tx_amsdu && + priv->aggr_prio_tbl[tid].amsdu !=3D BA_STREAM_NOT_ALLOWED) + tx_ba_tbl->amsdu =3D true; + else + tx_ba_tbl->amsdu =3D false; + if (ra_list) { + ra_list->amsdu_in_ampdu =3D tx_ba_tbl->amsdu; + ra_list->ba_status =3D BA_SETUP_COMPLETE; + } + } else { + nxpwifi_dbg(priv->adapter, ERROR, "BA stream not created\n"); + } + + return 0; +} + +/* This function prepares command of reconfigure Tx buffer. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting Tx buffer size (for SET only) + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_recfg_tx_buf(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, int cmd_action, + u16 *buf_size) +{ + struct host_cmd_ds_txbuf_cfg *tx_buf =3D &cmd->params.tx_buf; + u16 action =3D (u16)cmd_action; + + cmd->command =3D cpu_to_le16(HOST_CMD_RECONFIGURE_TX_BUFF); + cmd->size =3D + cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN); + tx_buf->action =3D cpu_to_le16(action); + switch (action) { + case HOST_ACT_GEN_SET: + nxpwifi_dbg(priv->adapter, CMD, + "cmd: set tx_buf=3D%d\n", *buf_size); + tx_buf->buff_size =3D cpu_to_le16(*buf_size); + break; + case HOST_ACT_GEN_GET: + default: + tx_buf->buff_size =3D 0; + break; + } + return 0; +} + +/* This function prepares command of AMSDU aggregation control. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting AMSDU control parameters (for SET only) + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, + int cmd_action, + struct nxpwifi_ds_11n_amsdu_aggr_ctrl *aa_ctrl) +{ + struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =3D + &cmd->params.amsdu_aggr_ctrl; + u16 action =3D (u16)cmd_action; + + cmd->command =3D cpu_to_le16(HOST_CMD_AMSDU_AGGR_CTRL); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl) + + S_DS_GEN); + amsdu_ctrl->action =3D cpu_to_le16(action); + switch (action) { + case HOST_ACT_GEN_SET: + amsdu_ctrl->enable =3D cpu_to_le16(aa_ctrl->enable); + amsdu_ctrl->curr_buf_size =3D 0; + break; + case HOST_ACT_GEN_GET: + default: + amsdu_ctrl->curr_buf_size =3D 0; + break; + } + return 0; +} + +/* This function prepares 11n configuration command. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting HT Tx capability and HT Tx information fields + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_11n_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, u16 cmd_action, + struct nxpwifi_ds_11n_tx_cfg *txcfg) +{ + struct host_cmd_ds_11n_cfg *htcfg =3D &cmd->params.htcfg; + + cmd->command =3D cpu_to_le16(HOST_CMD_11N_CFG); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN); + htcfg->action =3D cpu_to_le16(cmd_action); + htcfg->ht_tx_cap =3D cpu_to_le16(txcfg->tx_htcap); + htcfg->ht_tx_info =3D cpu_to_le16(txcfg->tx_htinfo); + + if (priv->adapter->is_hw_11ac_capable) + htcfg->misc_config =3D cpu_to_le16(txcfg->misc_config); + + return 0; +} + +/* This function appends an 11n TLV to a buffer. + * + * Buffer allocation is responsibility of the calling + * function. No size validation is made here. + * + * The function fills up the following sections, if applicable - + * - HT capability IE + * - HT information IE (with channel list) + * - 20/40 BSS Coexistence IE + * - HT Extended Capabilities IE + */ +int +nxpwifi_cmd_append_11n_tlv(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc, + u8 **buffer) +{ + struct nxpwifi_ie_types_htcap *ht_cap; + struct nxpwifi_ie_types_chan_list_param_set *chan_list; + struct nxpwifi_ie_types_2040bssco *bss_co_2040; + struct nxpwifi_ie_types_extcap *ext_cap; + int ret_len =3D 0; + struct ieee80211_supported_band *sband; + struct ieee_types_header *hdr; + u8 radio_type; + + if (!buffer || !*buffer) + return ret_len; + + radio_type =3D nxpwifi_band_to_radio_type((u8)bss_desc->bss_band); + sband =3D priv->wdev.wiphy->bands[radio_type]; + + if (bss_desc->bcn_ht_cap) { + ht_cap =3D (struct nxpwifi_ie_types_htcap *)*buffer; + memset(ht_cap, 0, sizeof(struct nxpwifi_ie_types_htcap)); + ht_cap->header.type =3D cpu_to_le16(WLAN_EID_HT_CAPABILITY); + ht_cap->header.len =3D + cpu_to_le16(sizeof(struct ieee80211_ht_cap)); + memcpy((u8 *)ht_cap + sizeof(struct nxpwifi_ie_types_header), + (u8 *)bss_desc->bcn_ht_cap, + le16_to_cpu(ht_cap->header.len)); + + nxpwifi_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); + /* Update HT40 capability from current channel information */ + if (bss_desc->bcn_ht_oper) { + u8 ht_param =3D bss_desc->bcn_ht_oper->ht_param; + u8 radio =3D + nxpwifi_band_to_radio_type(bss_desc->bss_band); + int freq =3D + ieee80211_channel_to_frequency(bss_desc->channel, + radio); + struct ieee80211_channel *chan =3D + ieee80211_get_channel(priv->adapter->wiphy, freq); + + switch (ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) { + ht_cap->ht_cap.cap_info &=3D + cpu_to_le16 + (~IEEE80211_HT_CAP_SUP_WIDTH_20_40); + ht_cap->ht_cap.cap_info &=3D + cpu_to_le16(~IEEE80211_HT_CAP_SGI_40); + } + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) { + ht_cap->ht_cap.cap_info &=3D + cpu_to_le16 + (~IEEE80211_HT_CAP_SUP_WIDTH_20_40); + ht_cap->ht_cap.cap_info &=3D + cpu_to_le16(~IEEE80211_HT_CAP_SGI_40); + } + break; + } + } + + *buffer +=3D sizeof(struct nxpwifi_ie_types_htcap); + ret_len +=3D sizeof(struct nxpwifi_ie_types_htcap); + } + + if (bss_desc->bcn_ht_oper) { + chan_list =3D + (struct nxpwifi_ie_types_chan_list_param_set *)*buffer; + memset(chan_list, 0, struct_size(chan_list, chan_scan_param, 1)); + chan_list->header.type =3D cpu_to_le16(TLV_TYPE_CHANLIST); + chan_list->header.len =3D + cpu_to_le16(sizeof(struct nxpwifi_chan_scan_param_set)); + chan_list->chan_scan_param[0].chan_number =3D + bss_desc->bcn_ht_oper->primary_chan; + chan_list->chan_scan_param[0].radio_type =3D + nxpwifi_band_to_radio_type((u8)bss_desc->bss_band); + + if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && + bss_desc->bcn_ht_oper->ht_param & + IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) + SET_SECONDARYCHAN + (chan_list->chan_scan_param[0].radio_type, + (bss_desc->bcn_ht_oper->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); + + *buffer +=3D struct_size(chan_list, chan_scan_param, 1); + ret_len +=3D struct_size(chan_list, chan_scan_param, 1); + } + + if (bss_desc->bcn_bss_co_2040) { + bss_co_2040 =3D (struct nxpwifi_ie_types_2040bssco *)*buffer; + memset(bss_co_2040, 0, + sizeof(struct nxpwifi_ie_types_2040bssco)); + bss_co_2040->header.type =3D cpu_to_le16(WLAN_EID_BSS_COEX_2040); + bss_co_2040->header.len =3D + cpu_to_le16(sizeof(bss_co_2040->bss_co_2040)); + + memcpy((u8 *)bss_co_2040 + + sizeof(struct nxpwifi_ie_types_header), + bss_desc->bcn_bss_co_2040 + + sizeof(struct ieee_types_header), + le16_to_cpu(bss_co_2040->header.len)); + + *buffer +=3D sizeof(struct nxpwifi_ie_types_2040bssco); + ret_len +=3D sizeof(struct nxpwifi_ie_types_2040bssco); + } + + if (bss_desc->bcn_ext_cap) { + hdr =3D (void *)bss_desc->bcn_ext_cap; + ext_cap =3D (struct nxpwifi_ie_types_extcap *)*buffer; + memset(ext_cap, 0, sizeof(struct nxpwifi_ie_types_extcap)); + ext_cap->header.type =3D cpu_to_le16(WLAN_EID_EXT_CAPABILITY); + ext_cap->header.len =3D cpu_to_le16(hdr->len); + + memcpy((u8 *)ext_cap->ext_capab, + bss_desc->bcn_ext_cap + sizeof(struct ieee_types_header), + le16_to_cpu(ext_cap->header.len)); + + if (hdr->len > 3 && + ext_cap->ext_capab[3] & WLAN_EXT_CAPA4_INTERWORKING_ENABLED) + priv->hs2_enabled =3D true; + else + priv->hs2_enabled =3D false; + + *buffer +=3D sizeof(struct nxpwifi_ie_types_extcap) + hdr->len; + ret_len +=3D sizeof(struct nxpwifi_ie_types_extcap) + hdr->len; + } + + return ret_len; +} + +/* This function checks if the given pointer is valid entry of + * Tx BA Stream table. + */ +static int +nxpwifi_is_tx_ba_stream_ptr_valid(struct nxpwifi_private *priv, + struct nxpwifi_tx_ba_stream_tbl *tx_tbl_ptr) +{ + struct nxpwifi_tx_ba_stream_tbl *tx_ba_tsr_tbl; + + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (tx_ba_tsr_tbl =3D=3D tx_tbl_ptr) + return true; + } + + return false; +} + +/* This function deletes the given entry in Tx BA Stream table. + * + * The function also performs a validity check on the supplied + * pointer before trying to delete. + */ +void +nxpwifi_11n_delete_tx_ba_stream_tbl_entry(struct nxpwifi_private *priv, + struct nxpwifi_tx_ba_stream_tbl *tbl) +{ + if (!tbl && nxpwifi_is_tx_ba_stream_ptr_valid(priv, tbl)) + return; + + nxpwifi_dbg(priv->adapter, INFO, + "info: tx_ba_tsr_tbl %p\n", tbl); + + list_del(&tbl->list); + + kfree(tbl); +} + +/* This function deletes all the entries in Tx BA Stream table. + */ +void nxpwifi_11n_delete_all_tx_ba_stream_tbl(struct nxpwifi_private *priv) +{ + int i; + struct nxpwifi_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node; + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_for_each_entry_safe(del_tbl_ptr, tmp_node, + &priv->tx_ba_stream_tbl_ptr, list) + nxpwifi_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr); + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + + INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); + + for (i =3D 0; i < MAX_NUM_TID; ++i) + priv->aggr_prio_tbl[i].ampdu_ap =3D + priv->aggr_prio_tbl[i].ampdu_user; +} + +/* This function returns the pointer to an entry in BA Stream + * table which matches the given RA/TID pair. + */ +struct nxpwifi_tx_ba_stream_tbl * +nxpwifi_get_ba_tbl(struct nxpwifi_private *priv, int tid, u8 *ra) +{ + struct nxpwifi_tx_ba_stream_tbl *tx_ba_tsr_tbl; + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (ether_addr_equal_unaligned(tx_ba_tsr_tbl->ra, ra) && + tx_ba_tsr_tbl->tid =3D=3D tid) { + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + return tx_ba_tsr_tbl; + } + } + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + return NULL; +} + +/* This function creates an entry in Tx BA stream table for the + * given RA/TID pair. + */ +void nxpwifi_create_ba_tbl(struct nxpwifi_private *priv, u8 *ra, int tid, + enum nxpwifi_ba_status ba_status) +{ + struct nxpwifi_tx_ba_stream_tbl *new_node; + struct nxpwifi_ra_list_tbl *ra_list; + int tid_down; + + if (!nxpwifi_get_ba_tbl(priv, tid, ra)) { + new_node =3D kzalloc(sizeof(*new_node), GFP_ATOMIC); + if (!new_node) + return; + + tid_down =3D nxpwifi_wmm_downgrade_tid(priv, tid); + ra_list =3D nxpwifi_wmm_get_ralist_node(priv, tid_down, ra); + if (ra_list) { + ra_list->ba_status =3D ba_status; + ra_list->amsdu_in_ampdu =3D false; + } + INIT_LIST_HEAD(&new_node->list); + + new_node->tid =3D tid; + new_node->ba_status =3D ba_status; + memcpy(new_node->ra, ra, ETH_ALEN); + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr); + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + } +} + +/* This function sends an add BA request to the given TID/RA pair. + */ +int nxpwifi_send_addba(struct nxpwifi_private *priv, int tid, u8 *peer_mac) +{ + struct host_cmd_ds_11n_addba_req add_ba_req; + u32 tx_win_size =3D priv->add_ba_param.tx_win_size; + static u8 dialog_tok; + int ret; + u16 block_ack_param_set; + + nxpwifi_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid); + + memset(&add_ba_req, 0, sizeof(add_ba_req)); + + block_ack_param_set =3D (u16)((tid << BLOCKACKPARAM_TID_POS) | + tx_win_size << BLOCKACKPARAM_WINSIZE_POS | + IMMEDIATE_BLOCK_ACK); + + /* enable AMSDU inside AMPDU */ + if (priv->add_ba_param.tx_amsdu && + priv->aggr_prio_tbl[tid].amsdu !=3D BA_STREAM_NOT_ALLOWED) + block_ack_param_set |=3D BLOCKACKPARAM_AMSDU_SUPP_MASK; + + add_ba_req.block_ack_param_set =3D cpu_to_le16(block_ack_param_set); + add_ba_req.block_ack_tmo =3D cpu_to_le16((u16)priv->add_ba_param.timeout); + + ++dialog_tok; + + if (dialog_tok =3D=3D 0) + dialog_tok =3D 1; + + add_ba_req.dialog_token =3D dialog_tok; + memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); + + /* We don't wait for the response of this command */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_11N_ADDBA_REQ, + 0, 0, &add_ba_req, false); + + return ret; +} + +/* This function sends a delete BA request to the given TID/RA pair. + */ +int nxpwifi_send_delba(struct nxpwifi_private *priv, int tid, u8 *peer_mac, + int initiator) +{ + struct host_cmd_ds_11n_delba delba; + int ret; + u16 del_ba_param_set; + + memset(&delba, 0, sizeof(delba)); + + del_ba_param_set =3D tid << DELBA_TID_POS; + + if (initiator) + del_ba_param_set |=3D IEEE80211_DELBA_PARAM_INITIATOR_MASK; + else + del_ba_param_set &=3D ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; + + delba.del_ba_param_set =3D cpu_to_le16(del_ba_param_set); + memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); + + /* We don't wait for the response of this command */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_11N_DELBA, + HOST_ACT_GEN_SET, 0, &delba, false); + + return ret; +} + +/* This function sends delba to specific tid + */ +void nxpwifi_11n_delba(struct nxpwifi_private *priv, int tid) +{ + struct nxpwifi_rx_reorder_tbl *rx_reor_tbl_ptr; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) { + if (rx_reor_tbl_ptr->tid =3D=3D tid) { + dev_dbg(priv->adapter->dev, + "Send delba to tid=3D%d, %pM\n", + tid, rx_reor_tbl_ptr->ta); + nxpwifi_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0); + goto exit; + } + } +exit: + spin_unlock_bh(&priv->rx_reorder_tbl_lock); +} + +/* This function handles the command response of a delete BA request. + */ +void nxpwifi_11n_delete_ba_stream(struct nxpwifi_private *priv, u8 *del_ba) +{ + struct host_cmd_ds_11n_delba *cmd_del_ba =3D + (struct host_cmd_ds_11n_delba *)del_ba; + u16 del_ba_param_set =3D le16_to_cpu(cmd_del_ba->del_ba_param_set); + int tid; + + tid =3D del_ba_param_set >> DELBA_TID_POS; + + nxpwifi_del_ba_tbl(priv, tid, cmd_del_ba->peer_mac_addr, + TYPE_DELBA_RECEIVE, INITIATOR_BIT(del_ba_param_set)); +} + +/* This function retrieves the Rx reordering table. + */ +int nxpwifi_get_rx_reorder_tbl(struct nxpwifi_private *priv, + struct nxpwifi_ds_rx_reorder_tbl *buf) +{ + int i; + struct nxpwifi_ds_rx_reorder_tbl *rx_reo_tbl =3D buf; + struct nxpwifi_rx_reorder_tbl *rx_reorder_tbl_ptr; + int count =3D 0; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr, + list) { + rx_reo_tbl->tid =3D (u16)rx_reorder_tbl_ptr->tid; + memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN); + rx_reo_tbl->start_win =3D rx_reorder_tbl_ptr->start_win; + rx_reo_tbl->win_size =3D rx_reorder_tbl_ptr->win_size; + for (i =3D 0; i < rx_reorder_tbl_ptr->win_size; ++i) { + if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) + rx_reo_tbl->buffer[i] =3D true; + else + rx_reo_tbl->buffer[i] =3D false; + } + rx_reo_tbl++; + count++; + + if (count >=3D NXPWIFI_MAX_RX_BASTREAM_SUPPORTED) + break; + } + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + return count; +} + +/* This function retrieves the Tx BA stream table. + */ +int nxpwifi_get_tx_ba_stream_tbl(struct nxpwifi_private *priv, + struct nxpwifi_ds_tx_ba_stream_tbl *buf) +{ + struct nxpwifi_tx_ba_stream_tbl *tx_ba_tsr_tbl; + struct nxpwifi_ds_tx_ba_stream_tbl *rx_reo_tbl =3D buf; + int count =3D 0; + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + rx_reo_tbl->tid =3D (u16)tx_ba_tsr_tbl->tid; + nxpwifi_dbg(priv->adapter, DATA, "data: %s tid=3D%d\n", + __func__, rx_reo_tbl->tid); + memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); + rx_reo_tbl->amsdu =3D tx_ba_tsr_tbl->amsdu; + rx_reo_tbl++; + count++; + if (count >=3D NXPWIFI_MAX_TX_BASTREAM_SUPPORTED) + break; + } + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + + return count; +} + +/* This function retrieves the entry for specific tx BA stream table by RA= and + * deletes it. + */ +void nxpwifi_del_tx_ba_stream_tbl_by_ra(struct nxpwifi_private *priv, u8 *= ra) +{ + struct nxpwifi_tx_ba_stream_tbl *tbl, *tmp; + + if (!ra) + return; + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) + if (!memcmp(tbl->ra, ra, ETH_ALEN)) + nxpwifi_11n_delete_tx_ba_stream_tbl_entry(priv, tbl); + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); +} + +/* This function initializes the BlockACK setup information for given + * nxpwifi_private structure. + */ +void nxpwifi_set_ba_params(struct nxpwifi_private *priv) +{ + priv->add_ba_param.timeout =3D NXPWIFI_DEFAULT_BLOCK_ACK_TIMEOUT; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + priv->add_ba_param.tx_win_size =3D + NXPWIFI_UAP_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size =3D + NXPWIFI_UAP_AMPDU_DEF_RXWINSIZE; + } else { + priv->add_ba_param.tx_win_size =3D + NXPWIFI_STA_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size =3D + NXPWIFI_STA_AMPDU_DEF_RXWINSIZE; + } + + priv->add_ba_param.tx_amsdu =3D true; + priv->add_ba_param.rx_amsdu =3D true; +} + +u8 nxpwifi_get_sec_chan_offset(int chan) +{ + u8 sec_offset; + + switch (chan) { + case 36: + case 44: + case 52: + case 60: + case 100: + case 108: + case 116: + case 124: + case 132: + case 140: + case 149: + case 157: + sec_offset =3D IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + break; + case 40: + case 48: + case 56: + case 64: + case 104: + case 112: + case 120: + case 128: + case 136: + case 144: + case 153: + case 161: + sec_offset =3D IEEE80211_HT_PARAM_CHA_SEC_BELOW; + break; + case 165: + default: + sec_offset =3D IEEE80211_HT_PARAM_CHA_SEC_NONE; + break; + } + + return sec_offset; +} + +/* This function will send DELBA to entries in the priv's + * Tx BA stream table + */ +static void +nxpwifi_send_delba_txbastream_tbl(struct nxpwifi_private *priv, u8 tid) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr; + + list_for_each_entry(tx_ba_stream_tbl_ptr, + &priv->tx_ba_stream_tbl_ptr, list) { + if (tx_ba_stream_tbl_ptr->ba_status =3D=3D BA_SETUP_COMPLETE) { + if (tid =3D=3D tx_ba_stream_tbl_ptr->tid) { + dev_dbg(adapter->dev, + "Tx:Send delba to tid=3D%d, %pM\n", tid, + tx_ba_stream_tbl_ptr->ra); + nxpwifi_send_delba(priv, + tx_ba_stream_tbl_ptr->tid, + tx_ba_stream_tbl_ptr->ra, 1); + return; + } + } + } +} + +/* This function updates all the tx_win_size + */ +void nxpwifi_update_ampdu_txwinsize(struct nxpwifi_adapter *adapter) +{ + u8 i, j; + u32 tx_win_size; + struct nxpwifi_private *priv; + + for (i =3D 0; i < adapter->priv_num; i++) { + if (!adapter->priv[i]) + continue; + priv =3D adapter->priv[i]; + tx_win_size =3D priv->add_ba_param.tx_win_size; + + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_STA) + priv->add_ba_param.tx_win_size =3D + NXPWIFI_STA_AMPDU_DEF_TXWINSIZE; + + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_UAP) + priv->add_ba_param.tx_win_size =3D + NXPWIFI_UAP_AMPDU_DEF_TXWINSIZE; + + if (adapter->coex_win_size) { + if (adapter->coex_tx_win_size) + priv->add_ba_param.tx_win_size =3D + adapter->coex_tx_win_size; + } + + if (tx_win_size !=3D priv->add_ba_param.tx_win_size) { + if (!priv->media_connected) + continue; + for (j =3D 0; j < MAX_NUM_TID; j++) + nxpwifi_send_delba_txbastream_tbl(priv, j); + } + } +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2086.outbound.protection.outlook.com [40.107.21.86]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4956516D31E; Fri, 21 Jun 2024 07:52:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.86 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956373; cv=fail; b=X68jBBQoA/EWPU6FGWcZYUs+g8/ST1L0cX3L5Z8pHkax59+prPSgM+6tjRz2ojD+CRHXWIMFfJagidRAnvbV9mrp2UIuwvKzxcTrJ5gbGXlQiSfrCsOvG2z7csYVIOccEn8hIv9PfgrCniBbQLXswClp2nG9GmtGTZYqgccjVes= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956373; c=relaxed/simple; bh=+s2RwZ3XGIcjdkAqdrgZINYg9aP/PcbWlRDNiRANEhQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=lqeE+Vj9JgnpPdEPQXXCCg2oyFGnh9v5IbPVzCpYprYabygbUtQOllg21mYR76uu9+FEWgZfPO6TVGcTI58T66t0euYWPWtxn6uvCDbMOIJ+gXm1kIJEupp+bOPw5pwHogXhXI61DlOULs0uEfI+NuLFD390DAQE5UIWeQE3BNE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=CPO+hxdK; arc=fail smtp.client-ip=40.107.21.86 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="CPO+hxdK" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=l88q11UDDjmU3+wZxXdO/22mSwN30bx1umdjgItHpHCQh93ydYYf4awoOdaWhQDn4PXsXLDQ63CmGdx3Sh0Zvn2/yWWUTjjMKf0XiJvHbygUHTsZNXqOXjfXf2homv8BJAN5x1UdCT1CVJZC0MvJ7nfn3TxwoqVSAlY9F4gIbnlQgDme/PC9KDZjxz3CVRvrSD9G8o4fZJbcxj7WoO0IthJ2CEXocE6ED9L7D1GmK0Ue+CaS45h8KxobVkMjE1L8s5M/oHP6tSNklZL4RCp5AXBqFv928uHi83+Y8qSeV6nJBt1AVpPRCsTYU1wqPMh9TcezyW0UwWfF++375NurCQ== 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=xKRQr41pWma60HDhQhSWeHxcJvU7O3Psl5qZsePcfwc=; b=e8LC4/24mR5MdFc6j/7pkLhoixAFyz1LwM/iHAi2wfVdX/u3VDvF/IcfDhwTXdVblcVfi9oX9sVPwQfR/yjtk2jHwgrZhiCH5hKG3c2EduNkckcu22GeAuvtyE+AkykLgYz67k6gSRdZG1Dcj2vNAFxUAIHwTCmYMs9XQtaiLTH/bxHu6gSRVeBBLelgSaTur9RonAlF4iwFvDp/AqZSaO8cZTJ6Nx0lBuEX0snMuLsj5kT+xpxAC5ezORFIb21tHdwW4y5eMSVfnkNavn6GofIYziFgNH/Ifk3ELv0jEsigUI35ykgoiMDhTjv42/W258L4Yf2m/1qu67QJwcwzQQ== 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=xKRQr41pWma60HDhQhSWeHxcJvU7O3Psl5qZsePcfwc=; b=CPO+hxdKk6NAyArdLRxyedDaRB5wiPu2f9SRJbMLDUoS6FlpXxRIGd0AMwvUuMsVI0Ycz8BsYxR0qdSYJW5z7LbebmTlDVU6/gH+FzyeH15Y0GYmgvt5/6AbfxddLnOQxVBs8Nzc6QGrea1XaNNcZw2wtU7CC23vQNiz0gNxV0Q= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:48 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:48 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 05/43] wifi: nxpwifi: add 11n.h Date: Fri, 21 Jun 2024 15:51:30 +0800 Message-Id: <20240621075208.513497-6-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 300c1ff5-7799-4392-b512-08dc91c724be X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?/AiZw0YeAUEFeuQgHla1Folxmi/lyL7YGd3dWLw7ihY1/ITqsEssN+A6+SZ0?= =?us-ascii?Q?bZu3IkVSfihuwnutxKksYlnM/4RM6acItmPX6L+v4XQGXv8nXlR3nxjlp8IS?= =?us-ascii?Q?2LdHqRkMYnpU75zV3hd2ocPfDcDqbQVFHlqmAOalIy7WTWelFnkLZa8oGj5/?= =?us-ascii?Q?G3ZzaZOhmCEv04LCQY0vjUOwKXMOzx2e6JGVA/gtmf3ZxIOzrYHKeacnSt7x?= =?us-ascii?Q?283FNq0ONTd5uLtGSq7TxVstsZzs/JjO5oo3t9fy9y5ppwMUYSsEjphra4l0?= =?us-ascii?Q?WFul3pRE1HlC3UTGvPfIynP86uG28qsT7Gg8pxCtj8evFXseYAPxR2nWLFSJ?= =?us-ascii?Q?pmqkvJ7Psbquro4fSwGPqApD4Dq3N/1JSORdFNJ12SpFI/NblFMP9Y5qSzbn?= =?us-ascii?Q?Fx4Yl0asY79Owjn3TTNBAYAMqVvoR9E4ESPyH74/LJIDCih6GMFdiDEpSTJW?= =?us-ascii?Q?hARwX1y0GviMHaPLUGLTE0ezxh1PSQKlIDoOpd1qNZolZSQfjpjc7o/KBmeR?= =?us-ascii?Q?CyzRek1s6iI6PNnhTGSBabnnH0oL9vdS0N0k1PMD0bZdDbXDM9fOmQI5SNNW?= =?us-ascii?Q?BRsxuWJOaKAL1eHGyslOiC1TZRmIsoL31VFXtqbTtWuZm/sldsA+MYitGQgj?= =?us-ascii?Q?JzjYfZXM8j9zubBFWTjp9qYdb8kgMuk86PptwPg+gVP1k2RmWFsy7c13OUaG?= =?us-ascii?Q?fQjkNjjtiXF/AnTGa7IFgcRmPPfY8GG+Z/DGxxBFobQded6KRdtwa6K2H3km?= =?us-ascii?Q?0OQLlFfi61P9n0PcD+WwnaIB27X0a+rNd5IY1mBJq723QEemm4LHLNQuA3Tn?= =?us-ascii?Q?J/06AUPQ2xlBSEaaWzWrtB28ijD8U7MH2KoD3NpAVj+yVG8WMVE6zDkCmSor?= =?us-ascii?Q?kzqwC2lzmzXD7pG/TUY//WZxXOKRzv0UQm2XgjMtFwJGhlfsiOf34cIUep3g?= =?us-ascii?Q?xJF+E35zp2LJe7Ri4q7gTr76QS0/v0LMkuxme9jVnTbxI5Fq/Aept/BHgf5i?= =?us-ascii?Q?S5pMjZBPpub1zGBQx5IQRPMc1dWF3EXf6PEQTms1uR3d6Ncey5XryjVWQxb3?= =?us-ascii?Q?ZloyTI7V3qv88Oih9xmWW2Bc5LFlL2zz54muPPMSpJCuw5raMqNwEEHlumBl?= =?us-ascii?Q?88QkwrQqdJww+JlYNI7AMRikq2mKWOEyT0Pyir3uo1RG5rqBA7lxuBFd0ykd?= =?us-ascii?Q?A3OIDIgMQ8zqZjLsdqxc3p7zB2UaAVInvdpLOI4xbiifZTzFN/pXa96ZM4o4?= =?us-ascii?Q?+L/9wCslmXrlNScBcnzkbkc3fvWSxUzNf8r5TUyiZuSt6feiu0qMJFP28Xee?= =?us-ascii?Q?9nZEDv8r+i7NBx1yvtajHQ/JkMs2P+8kUV6+GXvT08jSw0trZ/xBdpSU/v+/?= =?us-ascii?Q?i9WXEVM=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?WP8lrubR2YCiq7Xlk1NMHr6IxNpM/nlv0igeJMOaKnKbcfhryibvxev8iJR+?= =?us-ascii?Q?RK1buTLq9yz+gjoe8aVY8LebzybF0xOpnCfhZMbqM6RCeH1epM8UFSUXv++q?= =?us-ascii?Q?v7haO4hFFcLRkVqkbZpU1M2UlzhPNiyZOu8gU0n9HMPFyOt2Ro0cl59jBKoB?= =?us-ascii?Q?Bl5GPbARioKoSC5H25jKjiX3+WKZW3EdH3+k0Ca6Gv0dgSkOpuyU0UskgRMS?= =?us-ascii?Q?JfnHsiwtcqKdS3BKMq6+Z4wSkQKD4O0R911Kvn/Y0QVlUkg2GuxzuvXeura0?= =?us-ascii?Q?+SE7KtiKtqGmjp+k0qZUj4STndp34z1Wkl0wNSqZ5zRntAd+lb8BEbdsGUSH?= =?us-ascii?Q?9nQT5a4IkLDAYxrUoRPTDL6pXGjBPkSBdSK4/Q45IIwbhPs8rk2oTT3jP4qT?= =?us-ascii?Q?VJh1XpZCqXyqZwRI6zKSpnmEUMoaA3XVHBf59IfC9B/9Z8tXiaqWoj/HU8Eq?= =?us-ascii?Q?W0KV0CR73zEZ2kvqFyZmkqn5bqtErLykDbySFxZ1/z1vBlBHbcIWqnEENMpX?= =?us-ascii?Q?JQ7brTyjGF/M0N42b9XSKzLHmpSm8sydu0Li2jgb9aFs+k7Mcsyp88Ylc44F?= =?us-ascii?Q?aLaFtUZhivtK35/nvcVDbuGQ8vmT6wBAvtWmHru3offo46b140PrFJzoH+QO?= =?us-ascii?Q?gsOwOKnjXZC5TdZvzG6TQmATuXhS1ycEoEXiDtzNZCbv6U/1lMo4LiyZcvEX?= =?us-ascii?Q?gdLKOuWVVcW6CKLPcjjBK8g/Hq3gv+DCGQbiIYNRUqwyLhiahwJ7+yVA2EcW?= =?us-ascii?Q?8KJHkgoVRUBeDJBQMA0SPe4VT7TOWwBVpnvMwX+PrgmuELa4ftCb9scYt0n2?= =?us-ascii?Q?n5XZXpL6gK6l8+9gp1USIVFznMpAbXo7IBMSyQrlx19DnJ3HSStsMrWrxcJA?= =?us-ascii?Q?xEI4F1rBi4FwNRN+QhZkVCifAPhbUkAA8kPSafVX6OT8UWpqD/VDmMN2G0KE?= =?us-ascii?Q?7H+LmxQJ8Gt+/3bXdzqsQKMBzj0Iznc89xbyLoUGXMC1wa/1Uy8VxjfE3F6s?= =?us-ascii?Q?ynQgmY4Vm6NtIel1CCg/XLncMDCSCzS+CDEq+wPJV57yJVItD3fEdRELEWLd?= =?us-ascii?Q?d4is+K87YU91GlKlOcfoD8LETQolWlgRv+Ll0lyftnKIInz2ydU2RU8zs7xZ?= =?us-ascii?Q?ggDsllaZtW/LtzQqLazCpJe2vL9mpvj1vrsQVv0/qKEr2VcvM60GhhohyBgg?= =?us-ascii?Q?P/Qkdu7/PFVIO8v46s4DHqVHsR2lYsvzPcLeH9Q6bZ4mVZIf05LS2+kja2GV?= =?us-ascii?Q?j4mwirtN/PIGLrrxcotND0Q7/vRfNwkeXSfgJUzFZCzlc1cYH21N6cTNxZVj?= =?us-ascii?Q?EYcpgUbewuTETvN8DrXryJMSou/cZmmWtHRHyWQaanpifVpZCE6rzeIQ6X1Z?= =?us-ascii?Q?Thju44WxLQXN1E0uRwsBRp1O71B6Wl016RwJarfZDXu7AsaqKA2JNs1XLMmM?= =?us-ascii?Q?GtBZgAkSO6VmYfshidnKDiVzeJcg1C08eOD/eVfdba+4VrcNBwuzvp+Dd1WI?= =?us-ascii?Q?rKJ9rv+EZh0ek/MiGFCzGWp534G0tZW9ZvZot82Vc1P5BYvnaBRDETanAUm+?= =?us-ascii?Q?mHpK1FFLcLLH+jRI60AJOcAkYgTatfgj7xfV4nIt?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 300c1ff5-7799-4392-b512-08dc91c724be X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:48.4406 (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: C/t1w2YkyDkiV2/UTaDuIPgmUwrap2U98gkpbpBqYWA7Q9S8wvcS7iYFiKVMTMeyMpFDrQTK/6MNfsntgDdfhQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11n.h | 163 +++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11n.h diff --git a/drivers/net/wireless/nxp/nxpwifi/11n.h b/drivers/net/wireless/= nxp/nxpwifi/11n.h new file mode 100644 index 000000000000..9d983aea3a39 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: 802.11n + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_11N_H_ +#define _NXPWIFI_11N_H_ + +#include "11n_aggr.h" +#include "11n_rxreorder.h" +#include "wmm.h" + +int nxpwifi_ret_11n_delba(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp); +int nxpwifi_ret_11n_addba_req(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp); +int nxpwifi_cmd_11n_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, u16 cmd_action, + struct nxpwifi_ds_11n_tx_cfg *txcfg); +int nxpwifi_cmd_append_11n_tlv(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc, + u8 **buffer); +int nxpwifi_fill_cap_info(struct nxpwifi_private *priv, u8 radio_type, + struct ieee80211_ht_cap *ht_cap); +int nxpwifi_set_get_11n_htcap_cfg(struct nxpwifi_private *priv, + u16 action, int *htcap_cfg); +void nxpwifi_11n_delete_tx_ba_stream_tbl_entry(struct nxpwifi_private *pri= v, + struct nxpwifi_tx_ba_stream_tbl + *tx_tbl); +void nxpwifi_11n_delete_all_tx_ba_stream_tbl(struct nxpwifi_private *priv); +struct nxpwifi_tx_ba_stream_tbl *nxpwifi_get_ba_tbl(struct nxpwifi_private + *priv, int tid, u8 *ra); +void nxpwifi_create_ba_tbl(struct nxpwifi_private *priv, u8 *ra, int tid, + enum nxpwifi_ba_status ba_status); +int nxpwifi_send_addba(struct nxpwifi_private *priv, int tid, u8 *peer_mac= ); +int nxpwifi_send_delba(struct nxpwifi_private *priv, int tid, u8 *peer_mac, + int initiator); +void nxpwifi_11n_delete_ba_stream(struct nxpwifi_private *priv, u8 *del_ba= ); +int nxpwifi_get_rx_reorder_tbl(struct nxpwifi_private *priv, + struct nxpwifi_ds_rx_reorder_tbl *buf); +int nxpwifi_get_tx_ba_stream_tbl(struct nxpwifi_private *priv, + struct nxpwifi_ds_tx_ba_stream_tbl *buf); +int nxpwifi_cmd_recfg_tx_buf(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + int cmd_action, u16 *buf_size); +int nxpwifi_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, + int cmd_action, + struct nxpwifi_ds_11n_amsdu_aggr_ctrl *aa_ctrl); +void nxpwifi_del_tx_ba_stream_tbl_by_ra(struct nxpwifi_private *priv, u8 *= ra); +u8 nxpwifi_get_sec_chan_offset(int chan); + +static inline u8 +nxpwifi_is_station_ampdu_allowed(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr, int tid) +{ + struct nxpwifi_sta_node *node =3D nxpwifi_get_sta_entry(priv, ptr->ra); + + if (unlikely(!node)) + return false; + + return (node->ampdu_sta[tid] !=3D BA_STREAM_NOT_ALLOWED) ? true : false; +} + +/* This function checks whether AMPDU is allowed or not for a particular T= ID. */ +static inline u8 +nxpwifi_is_ampdu_allowed(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr, int tid) +{ + u8 ret; + + if (is_broadcast_ether_addr(ptr->ra)) + return false; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) + ret =3D nxpwifi_is_station_ampdu_allowed(priv, ptr, tid); + else + ret =3D (priv->aggr_prio_tbl[tid].ampdu_ap !=3D + BA_STREAM_NOT_ALLOWED) ? true : false; + + return ret; +} + +/* This function checks whether AMSDU is allowed or not for a particular T= ID. + */ +static inline u8 +nxpwifi_is_amsdu_allowed(struct nxpwifi_private *priv, int tid) +{ + return (((priv->aggr_prio_tbl[tid].amsdu !=3D BA_STREAM_NOT_ALLOWED) && + (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03))) + ? true : false); +} + +/* This function checks whether a space is available for new BA stream or = not. + */ +static inline u8 +nxpwifi_space_avail_for_new_ba_stream(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + u8 i; + size_t ba_stream_num =3D 0, ba_stream_max; + + ba_stream_max =3D NXPWIFI_MAX_TX_BASTREAM_SUPPORTED; + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv) + ba_stream_num +=3D + list_count_nodes(&priv->tx_ba_stream_tbl_ptr); + } + + if (adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) { + ba_stream_max =3D + GETSUPP_TXBASTREAMS(adapter->hw_dot_11n_dev_cap); + if (!ba_stream_max) + ba_stream_max =3D NXPWIFI_MAX_TX_BASTREAM_SUPPORTED; + } + + return ((ba_stream_num < ba_stream_max) ? true : false); +} + +/* This function finds the correct Tx BA stream to delete. + * + * Upon successfully locating, both the TID and the RA are returned. + */ +static inline u8 +nxpwifi_find_stream_to_delete(struct nxpwifi_private *priv, int ptr_tid, + int *ptid, u8 *ra) +{ + int tid; + u8 ret =3D false; + struct nxpwifi_tx_ba_stream_tbl *tx_tbl; + + tid =3D priv->aggr_prio_tbl[ptr_tid].ampdu_user; + + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) { + tid =3D priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user; + *ptid =3D tx_tbl->tid; + memcpy(ra, tx_tbl->ra, ETH_ALEN); + ret =3D true; + } + } + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + + return ret; +} + +/* This function checks whether associated station is 11n enabled + */ +static inline int nxpwifi_is_sta_11n_enabled(struct nxpwifi_private *priv, + struct nxpwifi_sta_node *node) +{ + if (!node || (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP && + !priv->ap_11n_enabled)) + return 0; + + return node->is_11n_enabled; +} + +#endif /* !_NXPWIFI_11N_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2086.outbound.protection.outlook.com [40.107.21.86]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9DA9416E860; Fri, 21 Jun 2024 07:52:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.86 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956375; cv=fail; b=gLww6+JapNvBM9oI+uE6fzlAeMIv/1VpLBZL6+cGlTVJQWyjXLEPN+mRD2s++xa5OV0n+yLL2dodsXZWklPusfYoIbJdVdWBb7xIF9lNuiuB3yVUbS8SzXvryejsLpoosECRBeLbjIt0fVAdhPnXH5FpV+cBVH0bMocg2Twb6yg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956375; c=relaxed/simple; bh=r1L2c9vNy66MsrKECVNUDrtoSILyX+MMq5u6iBxSQdA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=uwmI24Zw8NjdPDQCG4zilJNwmlNEAdchXhtMqMngEZozrnQpbn5dxQ6IbKectzm5+R9RwlR7opUTQtesQVBX1Pr3Rn52DJKI/VM2YauEY5UgjJsA0ToQ5dr1308dLdFBppGFay0hhJ0yKS/BDOPgkQqvxt1MpqP3pebkGF78EVM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=ndGhfD+F; arc=fail smtp.client-ip=40.107.21.86 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="ndGhfD+F" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ChXlmllEBp+hXu9UbeUg2+4yZL5WJDSAAg6S7WZhKR+36yOPHm52gYRIvVLVy3cY06cTRwFlMDNa6+V/a9s7K9TvHoG+K9/V+Tni5S3Yt2JyMe7J5qLRd/gH2uWe1+HoqVsv8/THIRcENoLmofBSktenbbo5mQ5hu3yMgZA7WpMA2IsNFpwgr59mOJpYYYOoZmqi9FOHsgAlM491CaBwrSUhBu8LaX6Ly2vYIMipcwA0trnRblKJDsZ5Kvx66khy8CtZ/GwYkIEdGeZPnKdjYxoWbjJQQXY9yjLvENyrwKmhI7LLoQ64vmlqUGYeDA293FAX9cg0pfoozOfGiNQ3Lg== 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=ib1CEuU7lxRC8Q/V8J2N0pkm+C8PhVLSZwHXyMNkC5I=; b=QJq6Eg0lm6N+maiDCaWvP+M6P9L+g2EE+GF/rrnYXxyLFehTDy6uI0F8k8FOPFss1Pq4bIa4qdpfz5u7J//a3sIVW4/fkxmVQAmr9MbBNaeBhF8bMeBIre2lE+boKIfsl0iuciQJknZ9CPU8VoFdSZ3M22mI4qABO/nTF7Rwxog4D5omj4AIjUyn6eKwXklzBmAz0aNuHeaN6dGNEWGwO/0mjv2XNwsnHqWi0nVeowC0sf2xIWOmrClSXhQOFiibMhssrECELtvlUypQb8r7hYEAYXY0TF7oi67Eu/VZ0ZciufBM93LRXHK1TKbB6Lwux3KEr56RmgOGWP/D1pacaA== 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=ib1CEuU7lxRC8Q/V8J2N0pkm+C8PhVLSZwHXyMNkC5I=; b=ndGhfD+Frqcnh9ChAFLmLk/fVV0a84FafVyqyrerZ78ZxCrgghAJnMnes+iCsbZW+JOs/LDyPAsUn66CYc3KqVtCQsh0estoQIEfeLfFBtDi9rb8CyWNte3hG7hyANV51w40R3oMSmUY80jljJdnv4yp5caacYVKNsWuu7biO48= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:52 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:51 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 06/43] wifi: nxpwifi: add 11n_aggr.c Date: Fri, 21 Jun 2024 15:51:31 +0800 Message-Id: <20240621075208.513497-7-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 8cddec74-d5f3-4c05-6d77-08dc91c726ce X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?iIKuzU08pVqnKQmqDvjsa8bl5UHTrC58Xty8vR9lPFOVNXz+zsWwQuL6yoPA?= =?us-ascii?Q?pAdSuaxSnV5L3AbuwPohJgAsVAo4zYlMQLfLCp+qO5YDobNpzqUi6T7zQkGu?= =?us-ascii?Q?RUz/AK+PbCqzFHdWCE+BY+CYYZ+2eDIMBWlLgzmDSWom9ovrkq2yrqNCtiyp?= =?us-ascii?Q?zk6Sh5T8OWFviAfXbG5g9Y7AGpASlCEaFJy4/FwA91cfT+HwjWRD/fpJ4Q9M?= =?us-ascii?Q?9YOtSE/52F+0aeJGlhlgqT3L0NKxe4GZ+exdQjKzduGonS01zHeRL6TtF579?= =?us-ascii?Q?7Vn+xByQzWfhMORvSlVyOKi6UMdj2BM4L32+QV4zNXAkY8RMHBEbmw6xLB2c?= =?us-ascii?Q?URcHwO6l3j9hDCWQuQ5qFccDlvlWbOfCTeoqQv2aCehrFytgXE+WSGyCPb+j?= =?us-ascii?Q?kWeDhOqx9mXIUqGKVhXnaqJi/eCBCMI/e8H9+d5uLbLPJMFjcg757XkuHEFa?= =?us-ascii?Q?KfIGOdXlJXr3P4aFBdMyih2WPfNyYPq5sHBCtzSVDua6JcIU03PzLTv920P9?= =?us-ascii?Q?LHz/1VSYRPgZGTMe3vvy4I8PcPOe/Q9XprcS/RRsqdLY6xtVuV+VwPFDu96c?= =?us-ascii?Q?/Ofa5pFDJstvhTf5UibgY5nA4xDs2HFi8x+93G4Klp+zdgxwuGBuiUJdfkuI?= =?us-ascii?Q?HwcP4UXipz7RfBuGNn7Aq8E9+OC2Fn+pcE68klItvpvZy7/q3TW/M0gTqhYz?= =?us-ascii?Q?k+YibmcQ1TGZFvnVTSjazLyuY7aCwVhEl1qBBZZ3ilWQ10zN12r3x2ulQpxC?= =?us-ascii?Q?XzZHg3OYqlDZ1ajZHWMC01haro+LERy6oQIaFHjizqRDxZVSqrva8706Q/Bx?= =?us-ascii?Q?xrcaopWnM2PXqcGgHCUFSBEPf/PY/p+XmBNzNxDlpULx1byPZQT4atJjiZVr?= =?us-ascii?Q?s83dnZIK4U/38XFPJ/Wf8Iz0OaCqzkWU+9VADVNihCgq6fAnNLrCmus+T/T6?= =?us-ascii?Q?7ERXRj3WWoIIv0+dtY3UGz6lnn5NH0Ykn81pbfGyi+Dn8sY0QxF75cmI8t79?= =?us-ascii?Q?vOb35M7PFHFZlbKotfe7kuz+PfwiWTf2UAbNzmKOIL+xAqVbUj4A1l5LlaIB?= =?us-ascii?Q?kzY9pdPULd3fcpUz2s8mEmjfUApfl4tTwfaffOQbg6UG61YliLr2nb++ROsv?= =?us-ascii?Q?iunb5srOJ7qB3aSGKoXQj0WgCu36wZ94S1UCWJjxxNWt6RG38bAgbp0vC8yD?= =?us-ascii?Q?birTIDzOvaC9wC5kcojQlZwbPejGfCKxTlpOZGw6v/C1UABMM4sA4rP3IFfD?= =?us-ascii?Q?ddMBSy9Z3csI+Nw6bSZasFlk7yGnCyxKhAOTDcFg4nDm3mwHnQkoLk7XIhFO?= =?us-ascii?Q?l+OSlq10MZOT53RyteRscASDw7OVkAUq1W+hvOpY5x46Qfkji2f/NCu5lz21?= =?us-ascii?Q?3139PRY=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?k7toiuvts+L0gzjMlQtig14U0b8K+LMgPOzVO5ko9OXU04IdP+CtbFmN0eXA?= =?us-ascii?Q?YziSEFtqUKJ0lKLPNw9sLOZDb1SPvb8z2Qk00wmDJNp2v2ThjKC+dQ1g1tAp?= =?us-ascii?Q?hzO0g/V049Va4Axx9gBGtabVFkT4w5A6QhkE/s5jm1/unMZk2JQ9Mcms0Cau?= =?us-ascii?Q?DqA/rWtbq9sEDSjiB3J7UxLQJkT8A+TaV89ymrRJNhq8gKKwnFwh2384gh8h?= =?us-ascii?Q?Xz+1dZiqynaBsNABLkVTiY2e0SbBVg4jnkeQ9volz4f4+sTLJzaPPPKqxykU?= =?us-ascii?Q?JJHiCVR2Fqqo1wLGOOsb6zNFw9C0xvj4oCiKdoBmNcUvHcVk+SMTcs7fssLo?= =?us-ascii?Q?GJyX0YmOs2p1fVQYrUkuUiD1kIHotxtAADuBFOtdke2zRw4ei5gDAkFel6fn?= =?us-ascii?Q?96XDzS8PX0MhXJzbsxag2KdilZdJdrTvHsdu8+THJ52gb9OtYDRhpXzKXIp7?= =?us-ascii?Q?MG96db74mLVJlDCRJfPpz/Gcwbe+c0LO4CshHr9Pv0Lc0rp5ChyIE5avlml8?= =?us-ascii?Q?04sHq7De4fw1+LH/4iaJtGGWjrcIxhcCMZdg6fXY4EFKCnzAhI8HmL4ZwS75?= =?us-ascii?Q?Z+mkCsuCN02fjtm2ow3hL7o+3ri5oAp/H69yG9fgUAqVR7GhzQPdmQ68J1dh?= =?us-ascii?Q?3yoDWbmV/x8Efwiug0ozXpkM31/fg072qlJAMjIqNMJ+iAHQmvwSQOAXZRLo?= =?us-ascii?Q?61UZk2bdTVjt/VDzk4QJ5kA7oO0J7IV7BAV/25yhbGkKXa9q+5UfGP4wCKld?= =?us-ascii?Q?pKwdORzo4SsPdcIRvMorUfpK4l42uFtNguu7DAhTN2H+S7PTnqOl6Zct/iLX?= =?us-ascii?Q?XObnRiY/t2oWVl5U9jUqBCpqEb2WpwlripbHCAVV0/HZFLV9fOZVQZBcn6iZ?= =?us-ascii?Q?XUAhSPB7dmBt+cbDrIfqO9EWdcVhOR20dzSR9CA2IqEeLtD8d6csiHpFxnTs?= =?us-ascii?Q?EVrFRkUF+tOlH9niL02yuR7AD7GguxSHQTLmdnOftjJYoeQLTaHeEQC9eLHi?= =?us-ascii?Q?CsYKqbCMUS2nFtur1+jvb55WUxN25jwBeDr3OwhRLGDCBm2KRApwu3lsH7f6?= =?us-ascii?Q?WkacxDCMpY3xJPTDUcDtd1fYvpPbIzBZ8Lm9A/vx0Am0yjEdcrGOfjFevFXP?= =?us-ascii?Q?m+XszK0aW7j2QElgKdn/MxyyF2wFUKLzgMQNnpSmTByLgSrK7m1lIgs3Zu/W?= =?us-ascii?Q?48G8jG12NYpdzBZxxPBBPFimxZDGxChnbAj8AJsQjwIGTFbhvHWNhydfaaod?= =?us-ascii?Q?LMgDba6q5VJL0FLTeG8KpTSWVMtGiR6r1y1GaNO3rHcS/O0zz9GoEmRBI/cW?= =?us-ascii?Q?Xd5CLimKsdrPEF9rR+VvHkVBpslZEfDjFu4+n9ARn3cw0sV4X/QLudo8Q1Hf?= =?us-ascii?Q?ctErn5sMpl2SjPWXzTRcvTZ39YNrEa+YqafcPATc82cZn7gAfbX2eOQEzc6q?= =?us-ascii?Q?TWkYBRJeAAKV15MgC2vPJ3m2OfC8YvEAMulgSv4dbHYWkmD+advuWgQk/LOK?= =?us-ascii?Q?twq229yCigqhWkX1xvd59LRmR9lObKC2DYkehQZOVcs09L7RvOqdeamO41s0?= =?us-ascii?Q?kMSF0QiXE2D8bu7IDwEUw/Ik7/SXm8iNpOlcnKAk?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8cddec74-d5f3-4c05-6d77-08dc91c726ce X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:51.9043 (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: mjgMfnmLSZJQ3cEaRWr3VBB7I3EakK3Wt7EoFxt6N728Fi0JXiCiVkirZma3MMKuMbn3kxtcpkJyCb4X2BJeUQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11n_aggr.c | 278 ++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11n_aggr.c diff --git a/drivers/net/wireless/nxp/nxpwifi/11n_aggr.c b/drivers/net/wire= less/nxp/nxpwifi/11n_aggr.c new file mode 100644 index 000000000000..0169c8d910a4 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n_aggr.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: 802.11n Aggregation + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" +#include "11n_aggr.h" + +/* Creates an AMSDU subframe for aggregation into one AMSDU packet. + * + * The resultant AMSDU subframe format is - + * + * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ + * | DA | SA | Length | SNAP header | MSDU | + * | data[0..5] | data[6..11] | | | data[14..] | + * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ + * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes--> + * + * This function also computes the amount of padding required to make the + * buffer length multiple of 4 bytes. + * + * Data =3D> |DA|SA|SNAP-TYPE|........ .| + * MSDU =3D> |DA|SA|Length|SNAP|...... ..| + */ +static int +nxpwifi_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, + struct sk_buff *skb_src, int *pad) + +{ + int dt_offset; + struct rfc_1042_hdr snap =3D { + 0xaa, /* LLC DSAP */ + 0xaa, /* LLC SSAP */ + 0x03, /* LLC CTRL */ + {0x00, 0x00, 0x00}, /* SNAP OUI */ + 0x0000 /* SNAP type */ + /* This field will be overwritten + * later with ethertype + */ + }; + struct tx_packet_hdr *tx_header; + + tx_header =3D skb_put(skb_aggr, sizeof(*tx_header)); + + /* Copy DA and SA */ + dt_offset =3D 2 * ETH_ALEN; + memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset); + + /* Copy SNAP header */ + snap.snap_type =3D ((struct ethhdr *)skb_src->data)->h_proto; + + dt_offset +=3D sizeof(__be16); + + memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr)); + + skb_pull(skb_src, dt_offset); + + /* Update Length field */ + tx_header->eth803_hdr.h_proto =3D htons(skb_src->len + LLC_SNAP_LEN); + + /* Add payload */ + skb_put_data(skb_aggr, skb_src->data, skb_src->len); + + /* Add padding for new MSDU to start from 4 byte boundary */ + *pad =3D (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4; + + return skb_aggr->len + *pad; +} + +/* Adds TxPD to AMSDU header. + * + * Each AMSDU packet will contain one TxPD at the beginning, + * followed by multiple AMSDU subframes. + */ +static void +nxpwifi_11n_form_amsdu_txpd(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct txpd *local_tx_pd; + + skb_push(skb, sizeof(*local_tx_pd)); + + local_tx_pd =3D (struct txpd *)skb->data; + memset(local_tx_pd, 0, sizeof(struct txpd)); + + /* Original priority has been overwritten */ + local_tx_pd->priority =3D (u8)skb->priority; + local_tx_pd->pkt_delay_2ms =3D + nxpwifi_wmm_compute_drv_pkt_delay(priv, skb); + local_tx_pd->bss_num =3D priv->bss_num; + local_tx_pd->bss_type =3D priv->bss_type; + /* Always zero as the data is followed by struct txpd */ + local_tx_pd->tx_pkt_offset =3D cpu_to_le16(sizeof(struct txpd)); + local_tx_pd->tx_pkt_type =3D cpu_to_le16(PKT_TYPE_AMSDU); + local_tx_pd->tx_pkt_length =3D cpu_to_le16(skb->len - + sizeof(*local_tx_pd)); + + if (local_tx_pd->tx_control =3D=3D 0) + /* TxCtrl set by user or default */ + local_tx_pd->tx_control =3D cpu_to_le32(priv->pkt_tx_ctrl); + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA && + priv->adapter->pps_uapsd_mode) { + if (nxpwifi_check_last_packet_indication(priv)) { + priv->adapter->tx_lock_flag =3D true; + local_tx_pd->flags =3D + NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET; + } + } +} + +/* Create aggregated packet. + * + * This function creates an aggregated MSDU packet, by combining buffers + * from the RA list. Each individual buffer is encapsulated as an AMSDU + * subframe and all such subframes are concatenated together to form the + * AMSDU packet. + * + * A TxPD is also added to the front of the resultant AMSDU packets for + * transmission. The resultant packets format is - + * + * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+ + * | TxPD |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame| + * | | 1 | 2 | .. | n | + * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+ + */ +int +nxpwifi_11n_aggregate_pkt(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *pra_list, + int ptrindex) + __releases(&priv->wmm.ra_list_spinlock) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct sk_buff *skb_aggr, *skb_src; + struct nxpwifi_txinfo *tx_info_aggr, *tx_info_src; + int pad =3D 0, aggr_num =3D 0, ret; + struct nxpwifi_tx_param tx_param; + struct txpd *ptx_pd =3D NULL; + int headroom =3D adapter->intf_hdr_len; + + skb_src =3D skb_peek(&pra_list->skb_head); + if (!skb_src) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + return 0; + } + + tx_info_src =3D NXPWIFI_SKB_TXCB(skb_src); + skb_aggr =3D nxpwifi_alloc_dma_align_buf(adapter->tx_buf_size, + GFP_ATOMIC); + if (!skb_aggr) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + return -1; + } + + /* skb_aggr->data already 64 byte align, just reserve bus interface + * header and txpd. + */ + skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); + tx_info_aggr =3D NXPWIFI_SKB_TXCB(skb_aggr); + + memset(tx_info_aggr, 0, sizeof(*tx_info_aggr)); + tx_info_aggr->bss_type =3D tx_info_src->bss_type; + tx_info_aggr->bss_num =3D tx_info_src->bss_num; + + tx_info_aggr->flags |=3D NXPWIFI_BUF_FLAG_AGGR_PKT; + skb_aggr->priority =3D skb_src->priority; + skb_aggr->tstamp =3D skb_src->tstamp; + + do { + /* Check if AMSDU can accommodate this MSDU */ + if ((skb_aggr->len + skb_src->len + LLC_SNAP_LEN) > + adapter->tx_buf_size) + break; + + skb_src =3D skb_dequeue(&pra_list->skb_head); + pra_list->total_pkt_count--; + atomic_dec(&priv->wmm.tx_pkts_queued); + aggr_num++; + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); + + nxpwifi_write_data_complete(adapter, skb_src, 0, 0); + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + if (!nxpwifi_is_ralist_valid(priv, pra_list, ptrindex)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + return -1; + } + + if (skb_tailroom(skb_aggr) < pad) { + pad =3D 0; + break; + } + skb_put(skb_aggr, pad); + + skb_src =3D skb_peek(&pra_list->skb_head); + + } while (skb_src); + + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + + /* Last AMSDU packet does not need padding */ + skb_trim(skb_aggr, skb_aggr->len - pad); + + /* Form AMSDU */ + nxpwifi_11n_form_amsdu_txpd(priv, skb_aggr); + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) + ptx_pd =3D (struct txpd *)skb_aggr->data; + + skb_push(skb_aggr, headroom); + tx_info_aggr->aggr_num =3D aggr_num * 2; + if (adapter->data_sent || adapter->tx_lock_flag) { + atomic_add(aggr_num * 2, &adapter->tx_queued); + skb_queue_tail(&adapter->tx_data_q, skb_aggr); + return 0; + } + + if (skb_src) + tx_param.next_pkt_len =3D skb_src->len + sizeof(struct txpd); + else + tx_param.next_pkt_len =3D 0; + + ret =3D adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_DATA, + skb_aggr, &tx_param); + + switch (ret) { + case -EBUSY: + spin_lock_bh(&priv->wmm.ra_list_spinlock); + if (!nxpwifi_is_ralist_valid(priv, pra_list, ptrindex)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_write_data_complete(adapter, skb_aggr, 1, -1); + return -1; + } + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA && + adapter->pps_uapsd_mode && adapter->tx_lock_flag) { + priv->adapter->tx_lock_flag =3D false; + if (ptx_pd) + ptx_pd->flags =3D 0; + } + + skb_queue_tail(&pra_list->skb_head, skb_aggr); + + pra_list->total_pkt_count++; + + atomic_inc(&priv->wmm.tx_pkts_queued); + + tx_info_aggr->flags |=3D NXPWIFI_BUF_FLAG_REQUEUED_PKT; + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); + break; + case -1: + nxpwifi_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n", + __func__, ret); + adapter->dbg.num_tx_host_to_card_failure++; + nxpwifi_write_data_complete(adapter, skb_aggr, 1, ret); + return 0; + case -EINPROGRESS: + break; + case 0: + nxpwifi_write_data_complete(adapter, skb_aggr, 1, ret); + break; + default: + break; + } + if (ret !=3D -EBUSY) + nxpwifi_rotate_priolists(priv, pra_list, ptrindex); + + return 0; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2052.outbound.protection.outlook.com [40.107.21.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B26516EB78; Fri, 21 Jun 2024 07:52:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956380; cv=fail; b=ObmMvGJGfn/+YeLGtShj8fTcmOFke7avmia2Knp5t6AD8PUnkz2cnrJKBacANbwVvK2993td4V+oyOTTZd65hC/MaffEc4RmznSA0R9Yx/P4rb2qRo8f4mQpjg0Rhkds4wf5iTBYE7VEn0Eellr4v/xePzZBlh7Uuv2OVsbPO/Q= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956380; c=relaxed/simple; bh=mFwmBSvJLZ7f6jOt6OcpAXbxX3cuiCfiiuaDCO2V7bs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=KM1ctF96jjtT/vPxNETY0XSL0wfxRZm8upyIec6HrMcO5PaDHAdvRSO5/ZA8cQ4XrMdTaOUsIOORo101sj5nMUCiyoauvLJr206Rx1A61TYbuwjdShFEE6CxNl+D5b9lZseyw+wMwSebcMGrYSSROMEfnc2vODZgsgreWk+J/dQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=Tbu4V/JC; arc=fail smtp.client-ip=40.107.21.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="Tbu4V/JC" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=eJi/bmxhfGzN3ytAIEOz1hFS1IqVtBQk0JxVtMoI3b285j06Ssqdjmxo6aaFFf1DOBs0HYjNJoVfChGVIldDhHBRMyzksWICJTrVwWX64neu7XdEjEwcoJfiShxaFVjNzeNSkuLLskKED97MjWxQn0BaIDGlhKJ/efmx6o7wcL5CosYxBfNa+sORdA6r94YaWgLG/2U8Qe/clf9qdhIEtkdWimlj6sfIS+YhAu0xp+zUsL1i6B6R7+NRJs4FEl9HUcUtXHZ1uuvvyCRAGw2bxYM9CnPebB0i7HDZi63nmfWOFs4U4JXX9OT5AUfdPpGFMMMTnsjDLL5pzYQVchlihQ== 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=vTC0Du6ORTJMxynMG2wa9WJHDamonh41INI58D+OQvw=; b=atTuXzaX2UW6LDTx3jyYe+o4gURDIDkrvixwyhwO5CCTiGBCHt4tBOIu391H3jDwLzKAAQPGdpYh5Av+qd/lHUXdO4GWpSzYi/dZ20ODlYWjkMhnCdEbGkTFRef40CXULjsa2hc81TdyAQt2bMyVOuc3pOVCBqhovQmsxnOqU58lLjE/++47jVC9mrPJoRfSaul7kcANUD1B1LBnFo9hhl1N497N1yDXm9UdCwcXy4QFQqdYcCBJG4ZV3zJjNd+rh0b2CFo+qOQVh1F4BrTxOLHw8fxekazsMqrAjRiimRahLeZwdEG619Mhdyz0SDZyn3uOIo7fOHRG9o5AU6xutw== 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=vTC0Du6ORTJMxynMG2wa9WJHDamonh41INI58D+OQvw=; b=Tbu4V/JCLXJtyXIQEVUZpgJP4UBWzZVcrZ0ulaFdj42e7mmeAcHw3b89q6wo8sDZccdJdTsrtNuUp8YhElOxpv2GwBpzZCX/gAuwl+kDN+DugISJFQgHALYj0br9uhbqVeG9RECHigJARBLA/nj0T94ucamHxCh8VW9y3Kw1aRo= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:55 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:55 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 07/43] wifi: nxpwifi: add 11n_aggr.h Date: Fri, 21 Jun 2024 15:51:32 +0800 Message-Id: <20240621075208.513497-8-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 34a767eb-da12-489b-deb6-08dc91c728d9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?pZnU5lUPdihh85N6TsKgXbdaLpl5/9gZ/uaOKJFaUY3GeOxNmwNuiZSNatmg?= =?us-ascii?Q?1om57/vr9tTBr3U4rV3k2jwvxS8Q7+rPjyBcNEz7DSrpVF9k9cN4mfB7qxl9?= =?us-ascii?Q?0933n/qF7fdYXVgyMDieeoTGpkhRvHR2QH3QyoejH86RlLVehJHeWqtWhSwx?= =?us-ascii?Q?SA3NmS5PLzsqS98cPecuLIXGdESHNC3AdbUOXIMOWUu56Yzj2nsodkDwIBx5?= =?us-ascii?Q?owPwZ/4/UjD/2rkDTy51IKaPhPMBcTUVY5pITM4ZXgPNZetG13kO+Y8w4Odx?= =?us-ascii?Q?/PcFqXPvn8FCTbS8HZ1kv1hIHR2L7ejYNSUHclqE5Ph5jkOeSZVeZaewPEeQ?= =?us-ascii?Q?5UhEMDJ+uIjK/xnnSr49yQduG8jnIkNt1snUvA6Z0lWTRUpZee7tDIeTevfX?= =?us-ascii?Q?GesFghdIT1Z6qHyb9nAqC+0WgGnkAwXQTTV8pjPtyXU6jV9JNgYAIlSdLOQb?= =?us-ascii?Q?SZWY/SePgD5F1lc7pXgqVEaRjjQTLoBeMMt5dIqkZ9qbduZCK0225ic6zI5h?= =?us-ascii?Q?V2KCPerS1whNAwNqyYu5tRkSz1y5bQ7059L/G69j/SLNYF8m3cjcuxabjovP?= =?us-ascii?Q?5t6vjBHDWSnzsTrF8VUQ7x1qzTG4/NkM0gRLKP/db1Y5xfoRifnWKZoZcXlR?= =?us-ascii?Q?ucVy87qGv/cdHogbIcIAYotBwPThCgL3TIlrasLHwmZLsAz4ZOMrwDWYUahA?= =?us-ascii?Q?+B80XtXbw+X3jlZEffYjcmEW5pqEi05STSgu6RE61ghNtfTWkWCjwQ0asl43?= =?us-ascii?Q?KkU4uEhrUE8aOb3UcuYQJTJ6CY2+GMqUlKHvV3YReSX1a1p4MgPZtj5wO7hc?= =?us-ascii?Q?y+MJtrzUcd+fpinQ07GMDgA+MIiz1D2dtOHeR/xbubD1FKSQqs6Gp+F2jhVC?= =?us-ascii?Q?hUG1maruvv+kE01z+2p59A7J+1rHvJ4XsuA68/aIP8omOWcMNdfPZP3t7xuF?= =?us-ascii?Q?USDkFTqRodZNpPGI6oN75O1qNcIZz904xWf/d8Z1W/sAIaPfLtL3gWhqEtQo?= =?us-ascii?Q?YBW77l/fCRnmlmc3FoydKzl9RQ9Xbhx/G24tVyh00nJAJByGQeItxK6mNOJG?= =?us-ascii?Q?bBo/IuYdGrSiuMfKSvFAxs14CVqL24j3n+PsaAkqKuQIqTUjIgI20WwUbIaz?= =?us-ascii?Q?XDnaWBbRGj43qdlbDsXSMcKDlTd/B7P5LDz0TRzhRD9ZyiJQC+AeiPEyARs9?= =?us-ascii?Q?kHCWB8+WGJOTWK7tPBOZZrlI7ezZQcWtJ52wqkRepZn1rLrTbbbNriIAu7gv?= =?us-ascii?Q?WKhn+Con0y7qWPHEnLbnRzEGzgKtbAfxG93B5RogtVYVfXJ5R/pb5UAUtm0M?= =?us-ascii?Q?NTpqxxKdPAA8lTwoFEogEjiWpEnSjFy7yNOXFLR56QfTnGIhYXf/va4LgKbk?= =?us-ascii?Q?v8i1CMw=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?jwIsEacNDDjOrQ7+xJqPrnz4NEGB/A4eJmsJjmyE5/VKk1BYjXB32vKu7ZEd?= =?us-ascii?Q?Jc2JxtgIZDMhE9gR1DZiPa+26o3wf8dI/A4++OHzhDXsaJrtUN3bmbP0NtMj?= =?us-ascii?Q?4D0y/XKJSKIxsSrYTLAA6JuoCToXKBSX1cHax2eeM7w/0niP9vQLm2MnZY1y?= =?us-ascii?Q?Ei3Skkf2EBXnoNJ7BCAqEub0iJT7fAkcGa84Qb5YVuxdAfdBeW6cYIcvBNjs?= =?us-ascii?Q?pqzXO+u6d+PsC810wln2SuOsccU4KauI85V/4Hi7nFxh0WNN1JtDnapsrD12?= =?us-ascii?Q?Zh2S9qg4vrQPbqQwGPhyf3bkul/QdrqMTunvliG7iF+iQB/y7AZuSyj2wQug?= =?us-ascii?Q?FgzhpKWgSTdXSJI0EDyZgxtPaqeNLSMAs8yJFI+uwdZhYplU+L48fFwkuFe6?= =?us-ascii?Q?1RUw2vw/oYa9iPsC1FR+vi6Dzmdzg18ok8N/nCza1do3n3zbyZT5CnDSAPl2?= =?us-ascii?Q?LaqtOVMHqLOt8mZn023JgmnDLeN+/6hXUkwf764mDoprDknJAAcvwV5ssXfZ?= =?us-ascii?Q?GbIFR793exk1re4/WLsKzFZWf2nHpwZOOAksCWhmhvo4/7QJT2MVfJB1RjiE?= =?us-ascii?Q?npjuwWQu7+WiqNDGBom4a8PwI8hgIRN4narcRxBbtbPaav8jlXDzszLPVUIK?= =?us-ascii?Q?Wx174F/imuw8Wahuz5LmX2CDtOjWqNuMYtNwIVSuOrz+DaF7VTBoc2jT8LwP?= =?us-ascii?Q?LDS1uEj9J2xrChNbtr8uk3DY6udDk4PuomGsEqP5OYR3EJSvWtPO0EhUtsQy?= =?us-ascii?Q?h0CvRqoLNIqtuSnY7PR+yiCn6uByT14jtxm2qLNciW1mp+K1TSJn/CLRVhy0?= =?us-ascii?Q?u8f3OYkGWAMxd4dGB5yvi1/AsqU1UIPKFu3Kvq62FsO7BZstDdkGSlO7daNc?= =?us-ascii?Q?RDlpE/3s0LovpJ6u4Kp36TJ62vFVcG8uAR7tGeis0ZiPxm168WG8QuO6eQ+w?= =?us-ascii?Q?xorhUZN0P5dDqMCaVwP/UcENj8xx7sK9K+Y3jMr0yc8vDYdGf4bEu4hL/Qxl?= =?us-ascii?Q?X9sYnJ93YiFDOmBvCOUcfh84Xjvl6G484N7zEh2Dgri+6fzQXDtQJ1D1a4V5?= =?us-ascii?Q?Frl/BdCI4JtGWHn5ar/nfWLrb6iaEAeoNjW+rFVnVeTArpC8b7UikXEglHzq?= =?us-ascii?Q?iwCHliANT8zxwQhRDwf+BQSGkqwhw0cJsDk7s+qCdRjAjTLyPtOUxGIUDVSC?= =?us-ascii?Q?pscp+zIkLUdiRiL/9dKgA+E6ngK4/kwOsgLpSguCKPZP0rI12TQxRqoK+jL3?= =?us-ascii?Q?fxIxlBgyNWXl3EQAKGy6VMyxGEi5j3Lecp8P2tpABsYuvs3lRySks53fuiPj?= =?us-ascii?Q?z55TbZK5wtmVR//c9YSGLSDPX7vXYxibWYNL9KxpEi/We5HgfIZOLshXFiA3?= =?us-ascii?Q?opYR351AU7uhEjfYsg5FaynB9ycmudkb1/vYPPAN3L/JFE4iGxKytxoN0L1C?= =?us-ascii?Q?+nmsKpR8xxkoeu7ey/Lk0KmZNjZGdxwUs+VijlnwxngTz3yK09H8i96OHjNt?= =?us-ascii?Q?wfBOOwp33LOOT3lISxitJzYVmV9gTv5rDtQYBtfueLzMnQY65RrcaNtAnj3s?= =?us-ascii?Q?Mwq3oeI1kDzuS+j2XcdbXwjnN+dWhL5M/gLB/056?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 34a767eb-da12-489b-deb6-08dc91c728d9 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:55.3183 (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: uaRMNjBWt3w0JDjTIS1YK2U04Wt/gowbZFyECq86mu9Wzv4j9oHeLL+KrPKDQNQCgUl7FxyEdWMwmFtoNDnJLA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/11n_aggr.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11n_aggr.h diff --git a/drivers/net/wireless/nxp/nxpwifi/11n_aggr.h b/drivers/net/wire= less/nxp/nxpwifi/11n_aggr.h new file mode 100644 index 000000000000..be9f0f8f4e48 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n_aggr.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: 802.11n Aggregation + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_11N_AGGR_H_ +#define _NXPWIFI_11N_AGGR_H_ + +#define PKT_TYPE_AMSDU 0xE6 +#define MIN_NUM_AMSDU 2 + +int nxpwifi_11n_deaggregate_pkt(struct nxpwifi_private *priv, + struct sk_buff *skb); +int nxpwifi_11n_aggregate_pkt(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr, + int ptr_index) + __releases(&priv->wmm.ra_list_spinlock); + +#endif /* !_NXPWIFI_11N_AGGR_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on2040.outbound.protection.outlook.com [40.107.14.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA8A416EC0A; Fri, 21 Jun 2024 07:53:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.14.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956386; cv=fail; b=RPANKhhvgxvcyZSb43x12zgD59QR26Mz2PTSWCu0ugfs79uuBbm9o4RUZDu9/rktloFL6MmExj7nGTPSTwGZ9CFs9w1HzwsMptHgvP0YP12KnkztPu7KSSbhukUeodfXZPlJSFCKXBUtBRIMYve7Y4pgBxsiFRxrhiG5btJcGb0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956386; c=relaxed/simple; bh=oeA7LJLYKQE+Z0d8djSWISwJbziMN1SjpgnuFMUvxKU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=VDLyN6IEc2LTl68/2k7vnEL6I+uqLF1lb28UfmD7THtszI3XwwYnettGMcwIxjj94gVNjVMH/UE4852R8ITpm8+N2qnmUtSnB+JkF9+E+2G9WMPG6bYppKR1lCsNvvsGjVDk0kDc5oNaEIl516KEfsSAhAEr0+ASS+l11CXADHk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=j0H9aq/x; arc=fail smtp.client-ip=40.107.14.40 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="j0H9aq/x" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bZ0nd7NfuWTP6A3lcqpduo55aswZXUtdaVu4ATLXC92VMtKBHB3aF4v1CnX4PNemRDImA2lvcZYBiTDEtgNpql94G3RrvPoHaAJoHjaoNAdQxUfWak/5JcIrjAwTsYKaz4niBq38cub96u5fihLqIVZZ6fX0OsPs87ZO4D0C8k/HsrLYh9FmSllWcBjSgZOcK15TFd1fK3VsVKNNDhvtKk4BlI5Pjswjz4QTw5fJhHpoYkReh/rZmXH38cE2WlY92AjzGyEmAQ8fqMMMk7EHnbFt5hwxnwA8fcVXkGVQhT/JjsKWs7QezdAskWBdFNZJxX6lzv7hqIxEthHBj79UWQ== 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=QCuDEjBJYICiI2qFyFPOB3rD/eWQwt1l8bCybjVAO6w=; b=mK7BzaUpihuOve1kAuiSuJRyeIPvnmy1v2rb9f1mKVTIL6Hhgk8q5IkC1xi03dCA0wn8csHTJ8mRt1LhHP7QqDXUVG3hZSWXYCRoiz0x2T9AjeGhQQ5SdZaEEzj90nBZi7oqx6D0e+vQwWw7AN9EMliDYps/zgJjI/BPANlF3jHGSN83IcTmTHxC5RuZ5tAlKmwuxBLdhSgL283rf3fSo/1vaAd1qJSTiP4VzpOy5ZHyvDFlqtPU7akZb4Sfn1ml/i4KqNtcutqoaS2C+ACBC1Q7lepKZLl6azoUrVszhTyiCCqdylslefO/g63S1kCc8saj67+oZNVlDgalUfMGyA== 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=QCuDEjBJYICiI2qFyFPOB3rD/eWQwt1l8bCybjVAO6w=; b=j0H9aq/xDELs7NBJsTGN4XCPeXmBr+CQIMU9PsoBVMvU3Ip3mVOkOcxkLhj3dEn9oIZkp98hwD8jyF9urojUD8wVUdLkRI5hN7EEfXvGR6OwD3cSvEYg3efinc+0aANGBuqOvZsU97w9r17UY2q39HjA/urY/362S+M4hXBLqFE= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:52:59 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:52:59 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 08/43] wifi: nxpwifi: add 11n_rxreorder.c Date: Fri, 21 Jun 2024 15:51:33 +0800 Message-Id: <20240621075208.513497-9-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: cce7e190-4839-4eef-a0fe-08dc91c72a9c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?nFVhPjrIDIR4U6YeDDr2wALpmvlXrUMYorA4+g5uFC77UpvYTVa39n2Xrk+e?= =?us-ascii?Q?YUpCmUVsJ1g+Xuptfr/6SCSjaA5RiPWVBuV0fa+x7FhU93eQJTaHw352/ECI?= =?us-ascii?Q?fxPhwMXQ/LA5ddbivNa4VAWDlYZfGTFsx4ivSB16W4SrLj/7Un/B9j5rISm6?= =?us-ascii?Q?CNm2hGY2uaKKFfPqNLCpUrncWghlAXwnJ6XgIc5B4xyLNskXg1TbQgSfsr2e?= =?us-ascii?Q?jdyDTq5AltZkkk2jwz9vIDXClUoSWS/qnMBtSlY1kyvvKTOq04in3ICrNWRQ?= =?us-ascii?Q?e2A7Gs4YTr35HUHBe7Tk7YyJXuziLwPqNeh4rh+f8z9zfADvqFzTlOMU6Vk1?= =?us-ascii?Q?jrBszJrTzfE9PsUzvuUdChq+nEXyxIJvxXzmzzvGfkVauuTrBB3cOtrxBTJO?= =?us-ascii?Q?ShNpdknW26zvo/01u+v2EKOh4AC3XkfVPJlFdOPJP5aGWZB8TE4I6CE6zlmT?= =?us-ascii?Q?kvpOKnH6sS9wc34eNCJGBXagEnOjKZoz5nWI774FSR00kav0hwRJME8CmQA7?= =?us-ascii?Q?dvkyPB9rQEd/7jzHhc+5s8828B/jw+byrB17Ez1QI95E3qcjGs9AWwFsmw9p?= =?us-ascii?Q?X66wOeYdPPMvVdl0xt4XyfxBDjWViceVGaKXW7zLQ8fwzjh44MKwqzj5AaP7?= =?us-ascii?Q?cF5jzOkYGy3GON8lqQJbuy1nzWE7L3ZJfMuADLzrFgNYuG+dna3wtwn3cZTs?= =?us-ascii?Q?QKYx9r29VDEZTdvA9XZ4Q6hbsV501adu11fkcMKFEqn/jt3HLOKkwZ6CULM6?= =?us-ascii?Q?a90VgiKNzrb42T4e5lnDFCihulXTsrRwzYgy8ut9yh3OmWLfFZqHi++lziAp?= =?us-ascii?Q?qqyu6Kxu6w+1IlMEtSlEOuv0PahGIRrh5TNtBY0yCwHdyQ2+o1kbjIpJHd7c?= =?us-ascii?Q?T5mQcWX4yl9ofhQF2l/EGo80m88mUjPM7wh26oSZeW9ymWaSaLsW2kY8gdfL?= =?us-ascii?Q?hgNiSzNvXPEsajhXW1FW/IvJM5mar4tXmr4l2xTpzdNDg+oE9mGD3N6Bearo?= =?us-ascii?Q?3D2g2XJR2/9rxXXexnciloIU1CtC9z0cM9OxBzDzcH2c6c23Yd4wcLhRp7q3?= =?us-ascii?Q?amc6nrgzHE0kh7BgPListBNGQQe8+Y6sIO78Jqahe42v86amJgNNdE9GN49/?= =?us-ascii?Q?63S4NgCCfRZS30RtliHHMY8dgFLGC8oF4Xdt5Ao9H9eclk+q87WuVZVZGuHf?= =?us-ascii?Q?NYb9IrVUvleSTGoUDNaIu8gVVbzyf7EgY02etTEvKCkOdefmE8D84iEebZUv?= =?us-ascii?Q?oxQcfczgiaxQJ1WY1UcsmgjSftTgAzbJTG6JYVkUmtoAAsLsNj0XvW7B8TpZ?= =?us-ascii?Q?2CONrCQpb3ZMGi/Ef6sEpekbaHHDQKNTVyq5QurZaNMDhfnK4207qW+lZsYN?= =?us-ascii?Q?3qYtfxY=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?fxKc/YBLCM61qZej7r2b0zYJryzELtKCWzmqq07fS8x7tEReJ8YrqJwNDS3t?= =?us-ascii?Q?U0jxrbtORtx+Wg52nKNocOf4uP93mBISTY9rMIlvLNPprbhh3RJNszQYM0I2?= =?us-ascii?Q?WGYfFAELJmj+nwo1zg3VuE99fGGlnge9RQ79MniEOSkz2RIKiL3aERVRTZMC?= =?us-ascii?Q?3+p1jdorBYyEQRAU2LLH/smvd7FXGol4lSYBlyjW6CrtI3UZrffgnmbxqGOu?= =?us-ascii?Q?bMyxEShe8AqTct6eo9cY4iSkT/NQ0vkSrGqZJ31EK6QbO+xu+Tw1DmKrZXR9?= =?us-ascii?Q?0zLR7kg9s/VP/eHOYPfNnRrqYxjTl5AMf9qMVbPykJOjq1mcHpey4DTQM2nr?= =?us-ascii?Q?zb6EyGNRzgUmm7n4kbcicoRuO/1/5EA/SkFPSKHwBVRn5xYyMQQH6dg9r8eI?= =?us-ascii?Q?Ta/HM42Gpy4+czGFz8kcnM+/NWEQ+CAjjZuNb6mIts9YMLGd9H9cLlk1VmIh?= =?us-ascii?Q?ZxqdQHTNDdOrTKrEWOB4SpfFNz8bRq1K3BndFZE6NQGkLdsYk+D6A9rqW/6m?= =?us-ascii?Q?UTLYknNKdhVGCA9D/XSUjYOf234DSknbE1d+mcHNADY8TVUU3FdlD008iuZx?= =?us-ascii?Q?t3DvSVuNlIzdFuWdANBMTKMdPPUTn+AMz1Cs9Yt/PWJtnuf3JLFS29Nzp8/t?= =?us-ascii?Q?8RsHjw63CqpL9IkGqav9BBRciDQoZ5Xr9E6maeaXXm6NdDOyAO/nv54ImtlO?= =?us-ascii?Q?JitaqBsPwqEWtcNsQm+SNfzxv8pzhZ95izBpiZwwIQA18xH9sZMQJaT0dSh3?= =?us-ascii?Q?lmYiyMW6a57nZb4Hjbe0RYUGeF82hpiGmo8a5L38oPm0l79F/Wri02lLW2mU?= =?us-ascii?Q?w2Mcn6tYb/rb1pbKejNyk1Dhiv04ZwOLibd9fdyBN1WEuDrxIXqHjTTp3h6l?= =?us-ascii?Q?W8IRmECyDgFRwRat3ykIWGG1EXz8/klNtStX3dNH8zO5pBE7O5GZL/yzodwb?= =?us-ascii?Q?7MjTNVlsT+VraOHQ5IwTecobRXc6fA4nf7oKuNcSNz/mqanRlrRMbKx49Add?= =?us-ascii?Q?u5flvnD7imAMBYRAkGmO0XiSo9eGG0d9y3J+A6P/VBlXTrWPtBKW63UIPFDB?= =?us-ascii?Q?SCMbEJjOiGQCqdCcwzKCL01X+8hvcxIQOuV+1dqjBnQMMv/8tJejFV2dfp8t?= =?us-ascii?Q?VDrpt6Qaiw/Cm4N8qmoFtofuBewlR6o/DX9ND3ILWfKBeJdPX2lVKkZOn5cc?= =?us-ascii?Q?h+BgXJKvOlYiwNeQpYzzWal+Xp9GZ7o7vsnvqfD9XgPVoMTHASyLzukMvRmr?= =?us-ascii?Q?Xu/gQvGhym7Kau0jyD5Udh9ZV7EXYS+sMActCds6F99b0gNnMQgBSeCpOjjv?= =?us-ascii?Q?vbACal5tbkg4I0bSJnnhb3EPHtcnmyvWyXI1sdXyeSzVTQWAcLL0P2Djcjf/?= =?us-ascii?Q?r5sKAbSv3hO9K+KmryB446+fA7QOnTNBtg5D9uhnbsJHllDVjT4rCGPLj71u?= =?us-ascii?Q?q2SqBC4KJarchvTsd1a4JemiaI5vHVtIWbZT/tdSORiduy6G26767GQyUdUk?= =?us-ascii?Q?aMNYr5LwHHcuIXqHNHiwrliYxHG5TXm0D3LU5xs+rhPU0reNsgTDcWMVG15v?= =?us-ascii?Q?asPEf6fs1GtYJGRYr/tznR4RKx0hdq3HLMmIbvFw?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: cce7e190-4839-4eef-a0fe-08dc91c72a9c X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:52:59.4530 (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: NUMIosdPW8qRZtnu4GiQp2iDqQdi+VRKUVz/xFo2WZ5gM5xBbbP9iNl/+Zumb3bWCmbUd7cs8bV5AcfQYvn7zg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- .../net/wireless/nxp/nxpwifi/11n_rxreorder.c | 928 ++++++++++++++++++ 1 file changed, 928 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c diff --git a/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c b/drivers/net= /wireless/nxp/nxpwifi/11n_rxreorder.c new file mode 100644 index 000000000000..20faab3d6994 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c @@ -0,0 +1,928 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: 802.11n RX Re-ordering + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" +#include "11n_rxreorder.h" + +/* This function will dispatch amsdu packet and forward it to kernel/upper + * layer. + */ +static int nxpwifi_11n_dispatch_amsdu_pkt(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct rxpd *local_rx_pd =3D (struct rxpd *)(skb->data); + int ret; + + if (le16_to_cpu(local_rx_pd->rx_pkt_type) =3D=3D PKT_TYPE_AMSDU) { + struct sk_buff_head list; + struct sk_buff *rx_skb; + + __skb_queue_head_init(&list); + + skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset)); + skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); + + ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, + priv->wdev.iftype, 0, NULL, NULL, false); + + while (!skb_queue_empty(&list)) { + struct rx_packet_hdr *rx_hdr; + + rx_skb =3D __skb_dequeue(&list); + rx_hdr =3D (struct rx_packet_hdr *)rx_skb->data; + + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP) + ret =3D nxpwifi_uap_recv_packet(priv, rx_skb); + else + ret =3D nxpwifi_recv_packet(priv, rx_skb); + if (ret =3D=3D -1) + nxpwifi_dbg(priv->adapter, ERROR, + "Rx of A-MSDU failed"); + } + return 0; + } + + return -1; +} + +/* This function will process the rx packet and forward it to kernel/upper + * layer. + */ +static int nxpwifi_11n_dispatch_pkt(struct nxpwifi_private *priv, + struct sk_buff *payload) +{ + int ret; + + if (!payload) { + nxpwifi_dbg(priv->adapter, INFO, "info: fw drop data\n"); + return 0; + } + + ret =3D nxpwifi_11n_dispatch_amsdu_pkt(priv, payload); + if (!ret) + return 0; + + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP) + return nxpwifi_handle_uap_rx_forward(priv, payload); + + return nxpwifi_process_rx_packet(priv, payload); +} + +/* This function dispatches all packets in the Rx reorder table until the + * start window. + * + * There could be holes in the buffer, which are skipped by the function. + * Since the buffer is linear, the function uses rotation to simulate + * circular buffer. + */ +static void +nxpwifi_11n_dispatch_pkt_until_start_win(struct nxpwifi_private *priv, + struct nxpwifi_rx_reorder_tbl *tbl, + int start_win) +{ + struct sk_buff_head list; + struct sk_buff *skb; + int pkt_to_send, i; + + __skb_queue_head_init(&list); + spin_lock_bh(&priv->rx_reorder_tbl_lock); + + pkt_to_send =3D (start_win > tbl->start_win) ? + min((start_win - tbl->start_win), tbl->win_size) : + tbl->win_size; + + for (i =3D 0; i < pkt_to_send; ++i) { + if (tbl->rx_reorder_ptr[i]) { + skb =3D tbl->rx_reorder_ptr[i]; + __skb_queue_tail(&list, skb); + tbl->rx_reorder_ptr[i] =3D NULL; + } + } + + /* We don't have a circular buffer, hence use rotation to simulate + * circular buffer + */ + for (i =3D 0; i < tbl->win_size - pkt_to_send; ++i) { + tbl->rx_reorder_ptr[i] =3D tbl->rx_reorder_ptr[pkt_to_send + i]; + tbl->rx_reorder_ptr[pkt_to_send + i] =3D NULL; + } + + tbl->start_win =3D start_win; + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + while ((skb =3D __skb_dequeue(&list))) + nxpwifi_11n_dispatch_pkt(priv, skb); +} + +/* This function dispatches all packets in the Rx reorder table until + * a hole is found. + * + * The start window is adjusted automatically when a hole is located. + * Since the buffer is linear, the function uses rotation to simulate + * circular buffer. + */ +static void +nxpwifi_11n_scan_and_dispatch(struct nxpwifi_private *priv, + struct nxpwifi_rx_reorder_tbl *tbl) +{ + struct sk_buff_head list; + struct sk_buff *skb; + int i, j, xchg; + + __skb_queue_head_init(&list); + spin_lock_bh(&priv->rx_reorder_tbl_lock); + + for (i =3D 0; i < tbl->win_size; ++i) { + if (!tbl->rx_reorder_ptr[i]) + break; + skb =3D tbl->rx_reorder_ptr[i]; + __skb_queue_tail(&list, skb); + tbl->rx_reorder_ptr[i] =3D NULL; + } + + /* We don't have a circular buffer, hence use rotation to simulate + * circular buffer + */ + if (i > 0) { + xchg =3D tbl->win_size - i; + for (j =3D 0; j < xchg; ++j) { + tbl->rx_reorder_ptr[j] =3D tbl->rx_reorder_ptr[i + j]; + tbl->rx_reorder_ptr[i + j] =3D NULL; + } + } + tbl->start_win =3D (tbl->start_win + i) & (MAX_TID_VALUE - 1); + + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + while ((skb =3D __skb_dequeue(&list))) + nxpwifi_11n_dispatch_pkt(priv, skb); +} + +/* This function deletes the Rx reorder table and frees the memory. + * + * The function stops the associated timer and dispatches all the + * pending packets in the Rx reorder table before deletion. + */ +static void +nxpwifi_del_rx_reorder_entry(struct nxpwifi_private *priv, + struct nxpwifi_rx_reorder_tbl *tbl) +{ + int start_win; + + if (!tbl) + return; + + spin_lock_bh(&priv->adapter->rx_proc_lock); + priv->adapter->rx_locked =3D true; + if (priv->adapter->rx_processing) { + spin_unlock_bh(&priv->adapter->rx_proc_lock); + flush_workqueue(priv->adapter->rx_workqueue); + } else { + spin_unlock_bh(&priv->adapter->rx_proc_lock); + } + + start_win =3D (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1); + nxpwifi_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); + + del_timer_sync(&tbl->timer_context.timer); + tbl->timer_context.timer_is_set =3D false; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_del(&tbl->list); + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + kfree(tbl->rx_reorder_ptr); + kfree(tbl); + + spin_lock_bh(&priv->adapter->rx_proc_lock); + priv->adapter->rx_locked =3D false; + spin_unlock_bh(&priv->adapter->rx_proc_lock); +} + +/* This function returns the pointer to an entry in Rx reordering + * table which matches the given TA/TID pair. + */ +struct nxpwifi_rx_reorder_tbl * +nxpwifi_11n_get_rx_reorder_tbl(struct nxpwifi_private *priv, int tid, u8 *= ta) +{ + struct nxpwifi_rx_reorder_tbl *tbl; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) { + if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid =3D=3D tid) { + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + return tbl; + } + } + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + return NULL; +} + +/* This function retrieves the pointer to an entry in Rx reordering + * table which matches the given TA and deletes it. + */ +void nxpwifi_11n_del_rx_reorder_tbl_by_ta(struct nxpwifi_private *priv, u8= *ta) +{ + struct nxpwifi_rx_reorder_tbl *tbl, *tmp; + + if (!ta) + return; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) { + if (!memcmp(tbl->ta, ta, ETH_ALEN)) { + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + nxpwifi_del_rx_reorder_entry(priv, tbl); + spin_lock_bh(&priv->rx_reorder_tbl_lock); + } + } + spin_unlock_bh(&priv->rx_reorder_tbl_lock); +} + +/* This function finds the last sequence number used in the packets + * buffered in Rx reordering table. + */ +static int +nxpwifi_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx) +{ + struct nxpwifi_rx_reorder_tbl *rx_reorder_tbl_ptr =3D ctx->ptr; + struct nxpwifi_private *priv =3D ctx->priv; + int i; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + for (i =3D rx_reorder_tbl_ptr->win_size - 1; i >=3D 0; --i) { + if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) { + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + return i; + } + } + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + return -1; +} + +/* This function flushes all the packets in Rx reordering table. + * + * The function checks if any packets are currently buffered in the + * table or not. In case there are packets available, it dispatches + * them and then dumps the Rx reordering table. + */ +static void +nxpwifi_flush_data(struct timer_list *t) +{ + struct reorder_tmr_cnxt *ctx =3D + from_timer(ctx, t, timer); + int start_win, seq_num; + + ctx->timer_is_set =3D false; + seq_num =3D nxpwifi_11n_find_last_seq_num(ctx); + + if (seq_num < 0) + return; + + nxpwifi_dbg(ctx->priv->adapter, INFO, "info: flush data %d\n", seq_num); + start_win =3D (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1); + nxpwifi_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr, + start_win); +} + +/* This function creates an entry in Rx reordering table for the + * given TA/TID. + * + * The function also initializes the entry with sequence number, window + * size as well as initializes the timer. + * + * If the received TA/TID pair is already present, all the packets are + * dispatched and the window size is moved until the SSN. + */ +static void +nxpwifi_11n_create_rx_reorder_tbl(struct nxpwifi_private *priv, u8 *ta, + int tid, int win_size, int seq_num) +{ + int i; + struct nxpwifi_rx_reorder_tbl *tbl, *new_node; + u16 last_seq =3D 0; + struct nxpwifi_sta_node *node; + + /* If we get a TID, ta pair which is already present dispatch all + * the packets and move the window size until the ssn + */ + tbl =3D nxpwifi_11n_get_rx_reorder_tbl(priv, tid, ta); + if (tbl) { + nxpwifi_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num); + return; + } + /* if !tbl then create one */ + new_node =3D kzalloc(sizeof(*new_node), GFP_KERNEL); + if (!new_node) + return; + + INIT_LIST_HEAD(&new_node->list); + new_node->tid =3D tid; + memcpy(new_node->ta, ta, ETH_ALEN); + new_node->start_win =3D seq_num; + new_node->init_win =3D seq_num; + new_node->flags =3D 0; + + spin_lock_bh(&priv->sta_list_spinlock); + if (nxpwifi_queuing_ra_based(priv)) { + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP) { + node =3D nxpwifi_get_sta_entry(priv, ta); + if (node) + last_seq =3D node->rx_seq[tid]; + } + } else { + node =3D nxpwifi_get_sta_entry(priv, ta); + if (node) + last_seq =3D node->rx_seq[tid]; + else + last_seq =3D priv->rx_seq[tid]; + } + spin_unlock_bh(&priv->sta_list_spinlock); + + nxpwifi_dbg(priv->adapter, INFO, + "info: last_seq=3D%d start_win=3D%d\n", + last_seq, new_node->start_win); + + if (last_seq !=3D NXPWIFI_DEF_11N_RX_SEQ_NUM && + last_seq >=3D new_node->start_win) { + new_node->start_win =3D last_seq + 1; + new_node->flags |=3D RXREOR_INIT_WINDOW_SHIFT; + } + + new_node->win_size =3D win_size; + + new_node->rx_reorder_ptr =3D kcalloc(win_size, sizeof(void *), + GFP_KERNEL); + if (!new_node->rx_reorder_ptr) { + kfree(new_node); + nxpwifi_dbg(priv->adapter, ERROR, + "%s: failed to alloc reorder_ptr\n", __func__); + return; + } + + new_node->timer_context.ptr =3D new_node; + new_node->timer_context.priv =3D priv; + new_node->timer_context.timer_is_set =3D false; + + timer_setup(&new_node->timer_context.timer, nxpwifi_flush_data, 0); + + for (i =3D 0; i < win_size; ++i) + new_node->rx_reorder_ptr[i] =3D NULL; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr); + spin_unlock_bh(&priv->rx_reorder_tbl_lock); +} + +static void +nxpwifi_11n_rxreorder_timer_restart(struct nxpwifi_rx_reorder_tbl *tbl) +{ + u32 min_flush_time; + + if (tbl->win_size >=3D NXPWIFI_BA_WIN_SIZE_32) + min_flush_time =3D MIN_FLUSH_TIMER_15_MS; + else + min_flush_time =3D MIN_FLUSH_TIMER_MS; + + mod_timer(&tbl->timer_context.timer, + jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size)); + + tbl->timer_context.timer_is_set =3D true; +} + +/* This function prepares command for adding a BA request. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting add BA request buffer + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_= buf) +{ + struct host_cmd_ds_11n_addba_req *add_ba_req =3D &cmd->params.add_ba_req; + + cmd->command =3D cpu_to_le16(HOST_CMD_11N_ADDBA_REQ); + cmd->size =3D cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN); + memcpy(add_ba_req, data_buf, sizeof(*add_ba_req)); + + return 0; +} + +/* This function prepares command for adding a BA response. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting add BA response buffer + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_11n_addba_rsp_gen(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + struct host_cmd_ds_11n_addba_req + *cmd_addba_req) +{ + struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =3D &cmd->params.add_ba_rsp; + u32 rx_win_size =3D priv->add_ba_param.rx_win_size; + u8 tid; + int win_size; + u16 block_ack_param_set; + + cmd->command =3D cpu_to_le16(HOST_CMD_11N_ADDBA_RSP); + cmd->size =3D cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); + + memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr, + ETH_ALEN); + add_ba_rsp->dialog_token =3D cmd_addba_req->dialog_token; + add_ba_rsp->block_ack_tmo =3D cmd_addba_req->block_ack_tmo; + add_ba_rsp->ssn =3D cmd_addba_req->ssn; + + block_ack_param_set =3D le16_to_cpu(cmd_addba_req->block_ack_param_set); + tid =3D (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + add_ba_rsp->status_code =3D cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); + block_ack_param_set &=3D ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; + + /* If we don't support AMSDU inside AMPDU, reset the bit */ + if (!priv->add_ba_param.rx_amsdu || + priv->aggr_prio_tbl[tid].amsdu =3D=3D BA_STREAM_NOT_ALLOWED) + block_ack_param_set &=3D ~BLOCKACKPARAM_AMSDU_SUPP_MASK; + block_ack_param_set |=3D rx_win_size << BLOCKACKPARAM_WINSIZE_POS; + add_ba_rsp->block_ack_param_set =3D cpu_to_le16(block_ack_param_set); + win_size =3D (le16_to_cpu(add_ba_rsp->block_ack_param_set) + & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) + >> BLOCKACKPARAM_WINSIZE_POS; + cmd_addba_req->block_ack_param_set =3D cpu_to_le16(block_ack_param_set); + + nxpwifi_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr, + tid, win_size, + le16_to_cpu(cmd_addba_req->ssn)); + return 0; +} + +/* This function prepares command for deleting a BA request. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting del BA request buffer + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf) +{ + struct host_cmd_ds_11n_delba *del_ba =3D &cmd->params.del_ba; + + cmd->command =3D cpu_to_le16(HOST_CMD_11N_DELBA); + cmd->size =3D cpu_to_le16(sizeof(*del_ba) + S_DS_GEN); + memcpy(del_ba, data_buf, sizeof(*del_ba)); + + return 0; +} + +/* This function identifies if Rx reordering is needed for a received pack= et. + * + * In case reordering is required, the function will do the reordering + * before sending it to kernel. + * + * The Rx reorder table is checked first with the received TID/TA pair. If + * not found, the received packet is dispatched immediately. But if found, + * the packet is reordered and all the packets in the updated Rx reordering + * table is dispatched until a hole is found. + * + * For sequence number less than the starting window, the packet is droppe= d. + */ +int nxpwifi_11n_rx_reorder_pkt(struct nxpwifi_private *priv, + u16 seq_num, u16 tid, + u8 *ta, u8 pkt_type, void *payload) +{ + struct nxpwifi_rx_reorder_tbl *tbl; + int prev_start_win, start_win, end_win, win_size; + u16 pkt_index; + bool init_window_shift =3D false; + int ret =3D 0; + + tbl =3D nxpwifi_11n_get_rx_reorder_tbl(priv, tid, ta); + if (!tbl) { + if (pkt_type !=3D PKT_TYPE_BAR) + nxpwifi_11n_dispatch_pkt(priv, payload); + return ret; + } + + if (pkt_type =3D=3D PKT_TYPE_AMSDU && !tbl->amsdu) { + nxpwifi_11n_dispatch_pkt(priv, payload); + return ret; + } + + start_win =3D tbl->start_win; + prev_start_win =3D start_win; + win_size =3D tbl->win_size; + end_win =3D ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); + if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) { + init_window_shift =3D true; + tbl->flags &=3D ~RXREOR_INIT_WINDOW_SHIFT; + } + + if (tbl->flags & RXREOR_FORCE_NO_DROP) { + nxpwifi_dbg(priv->adapter, INFO, + "RXREOR_FORCE_NO_DROP when HS is activated\n"); + tbl->flags &=3D ~RXREOR_FORCE_NO_DROP; + } else if (init_window_shift && seq_num < start_win && + seq_num >=3D tbl->init_win) { + nxpwifi_dbg(priv->adapter, INFO, + "Sender TID sequence number reset %d->%d for SSN %d\n", + start_win, seq_num, tbl->init_win); + start_win =3D seq_num; + tbl->start_win =3D start_win; + end_win =3D ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); + } else { + /* If seq_num is less then starting win then ignore and drop + * the packet + */ + if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { + if (seq_num >=3D ((start_win + TWOPOW11) & + (MAX_TID_VALUE - 1)) && + seq_num < start_win) { + ret =3D -1; + goto done; + } + } else if ((seq_num < start_win) || + (seq_num >=3D (start_win + TWOPOW11))) { + ret =3D -1; + goto done; + } + } + + /* If this packet is a BAR we adjust seq_num as + * WinStart =3D seq_num + */ + if (pkt_type =3D=3D PKT_TYPE_BAR) + seq_num =3D ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); + + if ((end_win < start_win && + seq_num < start_win && seq_num > end_win) || + (end_win > start_win && (seq_num > end_win || + seq_num < start_win))) { + end_win =3D seq_num; + if (((end_win - win_size) + 1) >=3D 0) + start_win =3D (end_win - win_size) + 1; + else + start_win =3D (MAX_TID_VALUE - (win_size - end_win)) + 1; + nxpwifi_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); + } + + if (pkt_type !=3D PKT_TYPE_BAR) { + if (seq_num >=3D start_win) + pkt_index =3D seq_num - start_win; + else + pkt_index =3D (seq_num + MAX_TID_VALUE) - start_win; + + if (tbl->rx_reorder_ptr[pkt_index]) { + ret =3D -1; + goto done; + } + + tbl->rx_reorder_ptr[pkt_index] =3D payload; + } + + /* Dispatch all packets sequentially from start_win until a + * hole is found and adjust the start_win appropriately + */ + nxpwifi_11n_scan_and_dispatch(priv, tbl); + +done: + if (!tbl->timer_context.timer_is_set || + prev_start_win !=3D tbl->start_win) + nxpwifi_11n_rxreorder_timer_restart(tbl); + return ret; +} + +/* This function deletes an entry for a given TID/TA pair. + * + * The TID/TA are taken from del BA event body. + */ +void +nxpwifi_del_ba_tbl(struct nxpwifi_private *priv, int tid, u8 *peer_mac, + u8 type, int initiator) +{ + struct nxpwifi_rx_reorder_tbl *tbl; + struct nxpwifi_tx_ba_stream_tbl *ptx_tbl; + struct nxpwifi_ra_list_tbl *ra_list; + u8 cleanup_rx_reorder_tbl; + int tid_down; + + if (type =3D=3D TYPE_DELBA_RECEIVE) + cleanup_rx_reorder_tbl =3D (initiator) ? true : false; + else + cleanup_rx_reorder_tbl =3D (initiator) ? false : true; + + nxpwifi_dbg(priv->adapter, EVENT, "event: DELBA: %pM tid=3D%d initiator= =3D%d\n", + peer_mac, tid, initiator); + + if (cleanup_rx_reorder_tbl) { + tbl =3D nxpwifi_11n_get_rx_reorder_tbl(priv, tid, peer_mac); + if (!tbl) { + nxpwifi_dbg(priv->adapter, EVENT, + "event: TID, TA not found in table\n"); + return; + } + nxpwifi_del_rx_reorder_entry(priv, tbl); + } else { + ptx_tbl =3D nxpwifi_get_ba_tbl(priv, tid, peer_mac); + if (!ptx_tbl) { + nxpwifi_dbg(priv->adapter, EVENT, + "event: TID, RA not found in table\n"); + return; + } + + tid_down =3D nxpwifi_wmm_downgrade_tid(priv, tid); + ra_list =3D nxpwifi_wmm_get_ralist_node(priv, tid_down, peer_mac); + if (ra_list) { + ra_list->amsdu_in_ampdu =3D false; + ra_list->ba_status =3D BA_SETUP_NONE; + } + spin_lock_bh(&priv->tx_ba_stream_tbl_lock); + nxpwifi_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); + spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); + } +} + +/* This function handles the command response of an add BA response. + * + * Handling includes changing the header fields into CPU format and + * creating the stream, provided the add BA is accepted. + */ +int nxpwifi_ret_11n_addba_resp(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =3D &resp->params.add_ba_rsp; + int tid, win_size; + struct nxpwifi_rx_reorder_tbl *tbl; + u16 block_ack_param_set; + + block_ack_param_set =3D le16_to_cpu(add_ba_rsp->block_ack_param_set); + + tid =3D (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + /* Check if we had rejected the ADDBA, if yes then do not create + * the stream + */ + if (le16_to_cpu(add_ba_rsp->status_code) !=3D BA_RESULT_SUCCESS) { + nxpwifi_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=3D%d)\n", + add_ba_rsp->peer_mac_addr, tid); + + tbl =3D nxpwifi_11n_get_rx_reorder_tbl(priv, tid, + add_ba_rsp->peer_mac_addr); + if (tbl) + nxpwifi_del_rx_reorder_entry(priv, tbl); + + return 0; + } + + win_size =3D (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) + >> BLOCKACKPARAM_WINSIZE_POS; + + tbl =3D nxpwifi_11n_get_rx_reorder_tbl(priv, tid, + add_ba_rsp->peer_mac_addr); + if (tbl) { + if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && + priv->add_ba_param.rx_amsdu && + priv->aggr_prio_tbl[tid].amsdu !=3D BA_STREAM_NOT_ALLOWED) + tbl->amsdu =3D true; + else + tbl->amsdu =3D false; + } + + nxpwifi_dbg(priv->adapter, CMD, + "cmd: ADDBA RSP: %pM tid=3D%d ssn=3D%d win_size=3D%d\n", + add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size); + + return 0; +} + +/* This function handles BA stream timeout event by preparing and sending + * a command to the firmware. + */ +void nxpwifi_11n_ba_stream_timeout(struct nxpwifi_private *priv, + struct host_cmd_ds_11n_batimeout *event) +{ + struct host_cmd_ds_11n_delba delba; + + memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba)); + memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN); + + delba.del_ba_param_set |=3D + cpu_to_le16((u16)event->tid << DELBA_TID_POS); + delba.del_ba_param_set |=3D + cpu_to_le16((u16)event->origninator << DELBA_INITIATOR_POS); + delba.reason_code =3D cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); + nxpwifi_send_cmd(priv, HOST_CMD_11N_DELBA, 0, 0, &delba, false); +} + +/* This function cleans up the Rx reorder table by deleting all the entries + * and re-initializing. + */ +void nxpwifi_11n_cleanup_reorder_tbl(struct nxpwifi_private *priv) +{ + struct nxpwifi_rx_reorder_tbl *del_tbl_ptr, *tmp_node; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_for_each_entry_safe(del_tbl_ptr, tmp_node, + &priv->rx_reorder_tbl_ptr, list) { + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + nxpwifi_del_rx_reorder_entry(priv, del_tbl_ptr); + spin_lock_bh(&priv->rx_reorder_tbl_lock); + } + INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + + nxpwifi_reset_11n_rx_seq_num(priv); +} + +/* This function updates all rx_reorder_tbl's flags. + */ +void nxpwifi_update_rxreor_flags(struct nxpwifi_adapter *adapter, u8 flags) +{ + struct nxpwifi_private *priv; + struct nxpwifi_rx_reorder_tbl *tbl; + int i; + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (!priv) + continue; + + spin_lock_bh(&priv->rx_reorder_tbl_lock); + list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) + tbl->flags =3D flags; + spin_unlock_bh(&priv->rx_reorder_tbl_lock); + } +} + +/* This function update all the rx_win_size based on coex flag + */ +static void nxpwifi_update_ampdu_rxwinsize(struct nxpwifi_adapter *adapter, + bool coex_flag) +{ + u8 i; + u32 rx_win_size; + struct nxpwifi_private *priv; + + dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag); + + for (i =3D 0; i < adapter->priv_num; i++) { + if (!adapter->priv[i]) + continue; + priv =3D adapter->priv[i]; + rx_win_size =3D priv->add_ba_param.rx_win_size; + if (coex_flag) { + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_STA) + priv->add_ba_param.rx_win_size =3D + NXPWIFI_STA_COEX_AMPDU_DEF_RXWINSIZE; + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_UAP) + priv->add_ba_param.rx_win_size =3D + NXPWIFI_UAP_COEX_AMPDU_DEF_RXWINSIZE; + } else { + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_STA) + priv->add_ba_param.rx_win_size =3D + NXPWIFI_STA_AMPDU_DEF_RXWINSIZE; + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_UAP) + priv->add_ba_param.rx_win_size =3D + NXPWIFI_UAP_AMPDU_DEF_RXWINSIZE; + } + + if (adapter->coex_win_size && adapter->coex_rx_win_size) + priv->add_ba_param.rx_win_size =3D + adapter->coex_rx_win_size; + + if (rx_win_size !=3D priv->add_ba_param.rx_win_size) { + if (!priv->media_connected) + continue; + for (i =3D 0; i < MAX_NUM_TID; i++) + nxpwifi_11n_delba(priv, i); + } + } +} + +/* This function check coex for RX BA + */ +void nxpwifi_coex_ampdu_rxwinsize(struct nxpwifi_adapter *adapter) +{ + u8 i; + struct nxpwifi_private *priv; + u8 count =3D 0; + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv =3D adapter->priv[i]; + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) { + if (priv->media_connected) + count++; + } + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + if (priv->bss_started) + count++; + } + } + if (count >=3D NXPWIFI_BSS_COEX_COUNT) + break; + } + if (count >=3D NXPWIFI_BSS_COEX_COUNT) + nxpwifi_update_ampdu_rxwinsize(adapter, true); + else + nxpwifi_update_ampdu_rxwinsize(adapter, false); +} + +/* This function handles rxba_sync event + */ +void nxpwifi_11n_rxba_sync_event(struct nxpwifi_private *priv, + u8 *event_buf, u16 len) +{ + struct nxpwifi_ie_types_rxba_sync *tlv_rxba =3D (void *)event_buf; + u16 tlv_type, tlv_len; + struct nxpwifi_rx_reorder_tbl *rx_reor_tbl_ptr; + u8 i, j; + u16 seq_num, tlv_seq_num, tlv_bitmap_len; + int tlv_buf_left =3D len; + int ret; + u8 *tmp; + + nxpwifi_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", + event_buf, len); + while (tlv_buf_left > sizeof(*tlv_rxba)) { + tlv_type =3D le16_to_cpu(tlv_rxba->header.type); + tlv_len =3D le16_to_cpu(tlv_rxba->header.len); + if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) { + nxpwifi_dbg(priv->adapter, WARN, + "TLV size (%zu) overflows event_buf buf_left=3D%d\n", + size_add(sizeof(tlv_rxba->header), tlv_len), + tlv_buf_left); + return; + } + + if (tlv_type !=3D TLV_TYPE_RXBA_SYNC) { + nxpwifi_dbg(priv->adapter, ERROR, + "Wrong TLV id=3D0x%x\n", tlv_type); + return; + } + + tlv_seq_num =3D le16_to_cpu(tlv_rxba->seq_num); + tlv_bitmap_len =3D le16_to_cpu(tlv_rxba->bitmap_len); + if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { + nxpwifi_dbg(priv->adapter, WARN, + "TLV size (%zu) overflows event_buf buf_left=3D%d\n", + size_add(sizeof(*tlv_rxba), tlv_bitmap_len), + tlv_buf_left); + return; + } + + nxpwifi_dbg(priv->adapter, INFO, + "%pM tid=3D%d seq_num=3D%d bitmap_len=3D%d\n", + tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, + tlv_bitmap_len); + + rx_reor_tbl_ptr =3D + nxpwifi_11n_get_rx_reorder_tbl(priv, tlv_rxba->tid, + tlv_rxba->mac); + if (!rx_reor_tbl_ptr) { + nxpwifi_dbg(priv->adapter, ERROR, + "Can not find rx_reorder_tbl!"); + return; + } + + for (i =3D 0; i < tlv_bitmap_len; i++) { + for (j =3D 0 ; j < 8; j++) { + if (tlv_rxba->bitmap[i] & (1 << j)) { + seq_num =3D (MAX_TID_VALUE - 1) & + (tlv_seq_num + i * 8 + j); + + nxpwifi_dbg(priv->adapter, ERROR, + "drop packet,seq=3D%d\n", + seq_num); + + ret =3D nxpwifi_11n_rx_reorder_pkt + (priv, seq_num, tlv_rxba->tid, + tlv_rxba->mac, 0, NULL); + + if (ret) + nxpwifi_dbg(priv->adapter, + ERROR, + "Fail to drop packet"); + } + } + } + + tlv_buf_left -=3D (sizeof(tlv_rxba->header) + tlv_len); + tmp =3D (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; + tlv_rxba =3D (struct nxpwifi_ie_types_rxba_sync *)tmp; + } +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on2040.outbound.protection.outlook.com [40.107.14.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 267C216D4F1; Fri, 21 Jun 2024 07:53:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.14.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956389; cv=fail; b=IxNH9rE9acwL/A98BQP4HNPVEydgnIC3uNqZlWahWmQqorUOTCpnX9wk+j4NNrZgZp6Q19Dv9sy7MqubSHlUVwmjAiYrla7yoGkMPO1LaXJJfi6CbI5cSZwasgKhXm4bFfMgp5mq5rmNCKmejWBbqP7wGAFzrUOKn1iO6N0TYQc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956389; c=relaxed/simple; bh=tz4DGMMNSo4TPmxoDzXcyXduJhbSew6/kiAaMBufKN0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=qMpYLdZf7of6k4O6A+BhFfc0NGSspW/WAko06EoD3Q/c4qvhldSBUBIbzkIR7RpB4Sg9ylve823kWszQnusDa9XzKc29Z776BtIqEFjreZoU1VgU+1Bk3OfrHslSn4qXp9PASzeZSpq6M+z7nyZUBI4NtpLS7RDpNg5PiYIwilw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=WnTseNM1; arc=fail smtp.client-ip=40.107.14.40 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="WnTseNM1" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=guINo3TtX/0tOio0nVXyAjH0CPKHXzqfNkj9GycqCBrf1qhANKW1qG+U+uclMUdFfz3zTcXdZwf39aw4uZYZj/MhlCmPu3szse9fNVPOUiuhx4PsPIeiSLCtduOAB1CNsdD0OBccixNfPy32ov6NXH8puHiKNMF+eDQtcr7VEpEYEa7Ez/jbPWd7jr+1YBs8cgSXnRqXIbk+BXIftLxBLTT3ZHOw4jz+wwGSIVWW3Be44FxEoAB1YOE18TYnrL+iDxLZhRUXkpQvZ1YMXUlU+wVb7kbDaGjFZSe9SMGlNVd5qHJ/lipV/IzNyAJHXNoaxurDet4RTp0fecntsAXx1Q== 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=6/SyoI9cRkq2Kyo0xPSJ0d2ojtuvkST/zzCy665dN/0=; b=CZ7m47O8RM7X1XxrfhW6mN8YfuyqcWhoxz7zybT4Y5euz7YPjshSHY8iPx6Emr0PcFl8k86cnTnH51lC0xrK6r3GHmRgCWgyvu6IZB0EmxvC4clX16qbwJ+Qctpq1Sl9cK/i6FPZypi00ssJpo6gTzRuen5c/Rq3VBTfWek258IgTIqa1EigAXuPFaUCaQmJDDOS99YqR9XA3AUg2FpGB4NXfSGszi/8L6zjOvs55YZ6pQZKWBKQNMzixJD7GhY1q3B5Xcrn1jl2tPKMyEtJPEQaohHaOu9/7yepEi8ay8uFGZNa5r+B99XkdsLX6BJyEOAXQNeyy8rnvs+aNWRVQA== 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=6/SyoI9cRkq2Kyo0xPSJ0d2ojtuvkST/zzCy665dN/0=; b=WnTseNM1VSpGcyUrBHnnDIfDZck1EoTO07o6t++P1rcSZG2CbokeGUrEw/MTF3ENon20LCM6rN0MRXmyDTRUfmHwEEoo4qO/ss9MykmJWkr2HF9gVu5D0gMFiwSbPiF0ghr94DvMKmEqAbttIQI4iBlSLEWgOeMHpv++uKgKr3A= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:02 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:02 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 09/43] wifi: nxpwifi: add 11n_rxreorder.h Date: Fri, 21 Jun 2024 15:51:34 +0800 Message-Id: <20240621075208.513497-10-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 05371deb-261b-46a4-ac90-08dc91c72d0e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?UU4zvWuY7918vYvAbGrp4SbyzlIMbcK2gpaXNwEVIQESPjXVPEND7KSYRz5z?= =?us-ascii?Q?i/9CFcKgmqBohwam0nrdFflj71kjE0ATsf8CShpwHI2sc5tVA/1l7073CYeB?= =?us-ascii?Q?cDj+W5yrSeD4e5bdF/4qCY1wTVcMoVWSmeeId+bIat389zZ+Kuzf4jkgdM84?= =?us-ascii?Q?rXQk6mto2WNEmqxCioXZNkFKJ0PYrsxrwJ3FCX9PVrXWhlUieTs95TG3FXQe?= =?us-ascii?Q?toEkWXhx9B72V+l53pI/k1/Oap/iFp1hWfWL4c3awtZHfTPN6y+NHBi39ilK?= =?us-ascii?Q?2M0s0KBQOzGaTzZNZ5j1TiYfdf0b4qX8BlNRBM+BECEJNajczBm6H2GOR/wV?= =?us-ascii?Q?2tZpQGrFdyRbj5ky1q7Bm0HDS3cVuLKfSRq5T08uxTdD1DXA8ytipnHlhCTs?= =?us-ascii?Q?GxAs0yTaya4dbztUxtOy9vK7cp61ZhpmYdBxWcsDy0M6BZXkv2A6ibLuqfbs?= =?us-ascii?Q?QbCCf2O6LfDbZmu9dwBSVHDVN+io3ptvmR9m1Uo54z4nCyiGj0CXv8Kq2xU5?= =?us-ascii?Q?dbe92+IGST4O232as09bZ0GRWAgKCEq4ccfCe75PvddSpmiEn64/Bs0oj+DX?= =?us-ascii?Q?sUjcpTGicRd34C1nw5GHTeurlQMEnPmIPyeDFGmdR14wakkgBwjC7PFU0pKJ?= =?us-ascii?Q?feLZQgp1z2jnT5+lEUSw7nl5f4rfncX3/mmtRQSdV5nz75SoK9aqE1/1umQR?= =?us-ascii?Q?fp2l9Whnjv5czJfrp2dK7OZ5rRe3o1ih77fEanLrYyEgG0Ux3tMnasYRdv2T?= =?us-ascii?Q?GWPVIpv6sohUk8Mx98RH5H1hRNT9hxuhce0FgqHCOxKKcNNHwm41j4j2zEqI?= =?us-ascii?Q?5ENgDsyp/2yL7IG9jTOt8u+Xg4LsHwp3z9j4cJghImmGzqLa2AM4CFrYhNOK?= =?us-ascii?Q?AIddA+GZlFuUeBwdWnrqIUJ+N6iCz1AK8T0LzeMWxX7FdilD64oWxGB3Q1mb?= =?us-ascii?Q?aoK/94h3t3SimumaEyxM9z4vNXvxmMd3OdNy23gur/pH/M3iJNBDXoQOV0Ai?= =?us-ascii?Q?2y5Jpv/QDODBfegAw6h4FMj8t+0bjNcIuwT+xunIOo0U4TAR0Kvz8aQejKq2?= =?us-ascii?Q?lJf0lsq2OpSIJA5F0zVEy2J/RxXiRa+wq3CNdNM7kX/CeLxTI0CtYjer6Owm?= =?us-ascii?Q?+BH+OQ0GTfVV9Zo/NIt2gSSVJes+W2EjV5dNpIRZg7zj2+J39Z1knROAgdNL?= =?us-ascii?Q?E1xinH3v8MZcXKE1HjnXrru2fm3mtwVxvsCm/qTEnB9yrID0zwDETOVeI9k1?= =?us-ascii?Q?d3EP/YAZLR8ZFTJsuAM4FU21rggNKXJvO+QvjtNduPnVUHbadnNi2AOiQYGj?= =?us-ascii?Q?VT+sq9/TshUEU5lwCydEpqwmaTvnniszGPbRKC4HhxsHZFWIgPVc7vUxIurx?= =?us-ascii?Q?/9rMPpo=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?BhtSAnXi4TODGxKzlEw+XGmp9/HZxvjRSPpDogdmuHHedV+J415UaBS9J608?= =?us-ascii?Q?FWyFmKXJl9srmMjpoKwmskmYoB3/cudMlUyH6/nZXxo5/EnXF0vS/SEfTxpi?= =?us-ascii?Q?t34zRGW/854kRXJs8hn+5MIvZBRLgzDrp0xeD6U226mO/v+JrLwcEK+By98N?= =?us-ascii?Q?SV/IRpyZcB2FWd4wM05oi9pudNGAr43XTlA87kGAI7rY7pUiVgUKvjkgCbVJ?= =?us-ascii?Q?srcRvFdZJMJENoi7y+YWYQkOnP5b9bEEaffTFGFUVorUuWH0/8Xucb4hxTIH?= =?us-ascii?Q?hNwRQoXOqjQOMuNZ8YiMw057Stt3Qr2u/3hpR8N+SD2qPrxUbN7VRrpjqG17?= =?us-ascii?Q?nLZm8ClA0JX3Ui7tliiMo4AK5F44gQvEus+qx90WdybLxGWVcQM62RIdYXU6?= =?us-ascii?Q?2GK9tXpA3S/8xoqBYVSCmBm3n31BuRvhoHgK4gGO+kyRLlbhpjB7e/pqyKW5?= =?us-ascii?Q?nX7IdZNgUPhc+ZMnrT3x2XQhSbpQRf4kqwDCcng4N39Ix8PdhcnvYeHuLLE6?= =?us-ascii?Q?LlAWN4yTJyy2mDzRLgUrKhvynr3hktYMqXcgLLx4S264Zm92LhLq6/txO3+b?= =?us-ascii?Q?8xod7LdhoLhOwO+K/9nnboDqktjLIfLZAJRGW32a13OrVGQbOG9OxfWfTDrq?= =?us-ascii?Q?cSzkJrSkHn/h1tg+tuB/i9ubckTnN4SBiV++SqKjqrHnbz2KhrLvYOgj4j4E?= =?us-ascii?Q?jLSAZsZZyGWvzHzLMvnt2GyePn0sTIzgNm88omm88GkRIdXxJv5f/1T1Qk9w?= =?us-ascii?Q?ELyWUVOdJOm+UoGZImyFk8qM+s8+mzC3lCCHfbUj/XMpMYn35864SMJTdYp2?= =?us-ascii?Q?DIjMRrzGnOoF8Tg9FatyUq1ci3+uEQiVEhQuD+5XXcUWKgaYDsceaQjP64Ks?= =?us-ascii?Q?Rm3Ev35LJLNLD9K4UayQFt5yy9pDKVmFnW9oVIk4VSJc1mbSk9UesJakZ3KR?= =?us-ascii?Q?L2sJnpm5QHpxJ1zxH+A69ASoI4+wxP+NZv7kUqMW7Hcj2g+r4kXsZKiYRTlW?= =?us-ascii?Q?hB+GFHEMgX3OavlnBt0UuWr/rYUB2MQ9y8wtBkVuL8mY6m2QCfLjCCnMM7Qk?= =?us-ascii?Q?sYS0wAnQ49o0TweezIA9LRkDWGZrwJWuH6igzXAX1AXnsj9Nvu9RqDLuAGcw?= =?us-ascii?Q?y90MtzezaHSMzNjB+WYXQjGTJo+xtCGY0QihGzkrAAtq3c7LH0tgV5BZNkkI?= =?us-ascii?Q?QsnRSFkrApRp5z/+2Ro2UWI435GvOEPswdA/vTbDmuXx1ccI4xOY5iS3Lqy0?= =?us-ascii?Q?r/3HNJUYOcP8RIAE8f/wnCdT+jPBdPG6NTv+QAEY8UxxxTfzzTruc+vTR7pO?= =?us-ascii?Q?NonlN1gMpIq/cxIfA2mBQWRb+C5+S0yUaQliIx80Rw3ll08N10RDB+7pV9TX?= =?us-ascii?Q?NTsP0SigOFDxdKxHqtOmTxcLBJpbJKI/kxmrRuPyHBP7E2hCjLlcv6h/Hpwg?= =?us-ascii?Q?6oquFeyZVIf1CZIHNrPDuBON6sTZqDnH99GJFhn7aBEziPAEVUBvpUI0Ih05?= =?us-ascii?Q?WfRFWsvVzvsKg9Ihww7NtYTBX8KZ4N2vzhkV8DGL68MHI7qo9Bc2WPY5aLGD?= =?us-ascii?Q?gZtdAXZV+P4UOUJcKH8/XjbDtiO3eCBRSIypylq5?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 05371deb-261b-46a4-ac90-08dc91c72d0e X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:02.3753 (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: 0M78blKWX0EvTsD/uDlbghv1sy6Zi5O8w0cSO5aiYyE0cmX+VfQsDuOfiAtSMS+faFa+aRMw4EmjDjppHKlaRg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- .../net/wireless/nxp/nxpwifi/11n_rxreorder.h | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.h diff --git a/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.h b/drivers/net= /wireless/nxp/nxpwifi/11n_rxreorder.h new file mode 100644 index 000000000000..9b5dd4899f0e --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: 802.11n RX Re-ordering + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_11N_RXREORDER_H_ +#define _NXPWIFI_11N_RXREORDER_H_ + +#define MIN_FLUSH_TIMER_MS 50 +#define MIN_FLUSH_TIMER_15_MS 15 +#define NXPWIFI_BA_WIN_SIZE_32 32 + +#define PKT_TYPE_BAR 0xE7 +#define MAX_TID_VALUE (2 << 11) +#define TWOPOW11 (2 << 10) + +#define BLOCKACKPARAM_TID_POS 2 +#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1 +#define BLOCKACKPARAM_WINSIZE_POS 6 +#define DELBA_TID_POS 12 +#define DELBA_INITIATOR_POS 11 +#define TYPE_DELBA_SENT 1 +#define TYPE_DELBA_RECEIVE 2 +#define IMMEDIATE_BLOCK_ACK 0x2 + +#define ADDBA_RSP_STATUS_ACCEPT 0 + +#define NXPWIFI_DEF_11N_RX_SEQ_NUM 0xffff +#define BA_SETUP_MAX_PACKET_THRESHOLD 16 +#define BA_SETUP_PACKET_OFFSET 16 + +enum nxpwifi_rxreor_flags { + RXREOR_FORCE_NO_DROP =3D 1 << 0, + RXREOR_INIT_WINDOW_SHIFT =3D 1 << 1, +}; + +static inline void nxpwifi_reset_11n_rx_seq_num(struct nxpwifi_private *pr= iv) +{ + memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq)); +} + +int nxpwifi_11n_rx_reorder_pkt(struct nxpwifi_private *, + u16 seqNum, + u16 tid, u8 *ta, + u8 pkttype, void *payload); +void nxpwifi_del_ba_tbl(struct nxpwifi_private *priv, int tid, + u8 *peer_mac, u8 type, int initiator); +void nxpwifi_11n_ba_stream_timeout(struct nxpwifi_private *priv, + struct host_cmd_ds_11n_batimeout *event); +int nxpwifi_ret_11n_addba_resp(struct nxpwifi_private *priv, + struct host_cmd_ds_command + *resp); +int nxpwifi_cmd_11n_delba(struct host_cmd_ds_command *cmd, + void *data_buf); +int nxpwifi_cmd_11n_addba_rsp_gen(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + struct host_cmd_ds_11n_addba_req + *cmd_addba_req); +int nxpwifi_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, + void *data_buf); +void nxpwifi_11n_cleanup_reorder_tbl(struct nxpwifi_private *priv); +struct nxpwifi_rx_reorder_tbl * +nxpwifi_11n_get_rxreorder_tbl(struct nxpwifi_private *priv, int tid, u8 *t= a); +struct nxpwifi_rx_reorder_tbl * +nxpwifi_11n_get_rx_reorder_tbl(struct nxpwifi_private *priv, int tid, u8 *= ta); +void nxpwifi_11n_del_rx_reorder_tbl_by_ta(struct nxpwifi_private *priv, u8= *ta); +void nxpwifi_update_rxreor_flags(struct nxpwifi_adapter *adapter, u8 flags= ); +void nxpwifi_11n_rxba_sync_event(struct nxpwifi_private *priv, + u8 *event_buf, u16 len); +#endif /* _NXPWIFI_11N_RXREORDER_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2080.outbound.protection.outlook.com [40.107.21.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6CEB16F0EC; Fri, 21 Jun 2024 07:53:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.80 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956398; cv=fail; b=hRI7AH1xxIVvr/rLNi4LAq4yqPDhUnxkAAHYgWnIH0OahVuz1+yfemkfHN3m9z5f4qNXr9ovHNZlHJsfVrVGEN83DpwuPJMo7EHxHL35snmyvHmu8uX/NjxL/om1K0XKnGXkA2MFsqKUnBLgLwYYCgEZdp042NeWSTo04upzfo0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956398; c=relaxed/simple; bh=aLURCCEKCxRZ++zcSqBL2TVIRjVQBUGD2wQ4aEOr+MQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=QQGGfyvbqjU/U0qoLjq4WM8l1S/g6gGuqyxWNi8lyVCFBS/jn7Os56L4lSw2P1XqEngEglURu3GBDMqCrYEFKubb+JVw8XYizMT+86VWJk0w/dnPb/TTWPcbstCg83oUUovtjrgTvVWezpTetqAhB2OcQpBZ18yqrDKIBjZfQRU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=WfVxvOvc; arc=fail smtp.client-ip=40.107.21.80 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="WfVxvOvc" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=W1qZyp4G1LF2xJVcpD4zzC0Jt2aD7/NfRo5cpJTFKNU+bUEFY6daDI9Mfsguemd9c6YByJ1jGCaDOCyu6RO0stKqUE0nnIPgGNRN4RbQN+5Kacp6X3ApF2jkukCcsc/Qx1U+su6yp18j9muJXvXdKMqleLooNiUKLnFTxFHMiZf++J9lSy1hOuU/DdWUnFH15CfaN3eme3+8IJoqR4JgAwmNhLWLCPNgnw/Yame45zuKGe14sHzsVwmzpojXdRxH7+ATQqyrfgstUvuJftiLQ8qFa6FKvaKBSIRqq7O/vopxx7g5p3A9dcJkBPqLMyKyog4iauf9gLVcgLaDiWJE6Q== 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=KMf2WmQ+uGTUkEwDQUNBDnLJO0yZRjNWDkfg5Lb6OaI=; b=kiPFzvbW58m02sRdOxQ5GFoALQyF/+T55Ffg5bUg4GrfZnoYJN5b3NusbDgpL5BqIZf+0SWOreDNQSyPVhHMxXxHhoZA4mrcVEPBvjb3Tn25JVGc4rDKn73t0c1zqMixNe+QicxHZcjNDvXCAamyc7dpcJSP1HPHIvqYpc85jVjnY4rGCaqnrvuA7jKKnrr4K5HJ0r/RCy7mCUKfbHH3WA6fFzZ5h9Aqz46sY/9H59hCUYTPumd6L35YXMg4rZeTOpk2BghNsRnsjDRzlfeiWZbgKMX0SyKXVdZ0QX1NPQITFyyyVApFDukzQRjUxH8LSOm4WCR5qs5HhJrp2y4T7Q== 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=KMf2WmQ+uGTUkEwDQUNBDnLJO0yZRjNWDkfg5Lb6OaI=; b=WfVxvOvciPxvwubL41JGUo3IFzAqyAH8DljW73iwJ2hEr+oh1ziq6Rb4XEU6lj9wGmX076CknVhDGaJLw3v0DLGggv2APM48MnRsZ3OGuUQsbarWBl6H++dNSwMAg+lDLH+RcxxQaSgO1idjZdAwljW1YBJa/n1SwfvqnJ66qK0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by DB9PR04MB9789.eurprd04.prod.outlook.com (2603:10a6:10:4ed::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:08 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:08 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 10/43] wifi: nxpwifi: add cfg80211.c Date: Fri, 21 Jun 2024 15:51:35 +0800 Message-Id: <20240621075208.513497-11-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|DB9PR04MB9789:EE_ X-MS-Office365-Filtering-Correlation-Id: 1a835b9f-9272-4220-8f67-08dc91c72ed4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|4022899006|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?k7fQIipyPL4nqjoxU7LJNuYKmwDt0XQH2kyJT0ULUWbpu4vWQ65DsqAyFTOp?= =?us-ascii?Q?G6gXAYuDDQAJA7T0FXF/TC3x2V0cYamIX0RB0pwMFeSkZ4WuWcspjAjzPW6O?= =?us-ascii?Q?4oahPumVZStJPfWceK2pboNbe2fDwf5sF613m0kNbT5+v4wZ8oi8fsEa6m2b?= =?us-ascii?Q?QlyBV5IukX5CRoBQtnsPvJi34NhPETfPkKBt8RTFYtSW77i+8ki+mHa1yOza?= =?us-ascii?Q?NT1K3ifrbmCj3z9X/BHWWKGUEvM87Cx2alaXsm1oWj6nVCNRVboCVQfVUucd?= =?us-ascii?Q?ahc0vaQkxXljpOgz2yNrkbbzNvqsrRe9GldiQQAFj25xHor3MdaEYyFc5qdh?= =?us-ascii?Q?H1cOdJnL8kROupGTdQmgw9NG9JuLpNqeip+R2+2TC9INGHmHFDltAa0l83P0?= =?us-ascii?Q?yDTXkGVsEMm3v8pqKZPyS0/OvJeNkzPm+G7tKVoOk2aV6yMapmu2BXKK9IiG?= =?us-ascii?Q?bT5MkjA2k92Xb/K+RIWxW8KBB8A/FcFMLnOCqjHQYLBmlxKBf2im7VcBwlrd?= =?us-ascii?Q?buDJ1Q3R6US5g2lapR9TM7NnSyl950VlxBDwTyoLYpsxu56AadagETcED1/W?= =?us-ascii?Q?zGGgdgnDelpF/vMN989pCeOD5TBxBqshYxIBOF+4gtCQO6bdXv8ZtoK3uz6V?= =?us-ascii?Q?fNYKxZFeIsKBzrKu93Vbs3bCF3GX477Q9rlWv5APi6TXX55agUDyU91A3IGH?= =?us-ascii?Q?0HAbQH3AdJVhXX6fH78Ycd7Mish85HLB75dyPHkDij6G0+q7KmQhsWc9QBah?= =?us-ascii?Q?Iwg3xKmKGTrw38I7AFlGeNMHa/ZYhynozqL8ZlYG/eWzBnCnSjv6ie93P+RR?= =?us-ascii?Q?+vojB77m2J1foOye7Pr4CHASLtQeneO2/UNXG2+zXeVKL+v+iQYSeBTJXCcl?= =?us-ascii?Q?0ufjnrVDZEbeHGUWmPiZgYaggib7HGzd2/DHt3BWa1lVihW4DCb2trdh2NiK?= =?us-ascii?Q?Y30w4xc+dx1DW7mDfMITmy+UjZhdN899nf9/CpgYfjPu8A2Xf/dLSgEsPAnI?= =?us-ascii?Q?86ugOCUXVhk8sWKm3Y61fxuSO2CgtwYJ+bGV0i0TX/rwC1wVcl4Ky3gGZtA8?= =?us-ascii?Q?/mzoyqzZuMx1NIKtuUftvo/zVqAtKYbpbp1vap6yP5Qoj49A2hgjoyx1yg4d?= =?us-ascii?Q?baQrPO5aeKlodFjkHY+X97Irv8Zm/CDBJpBNlsnsXZvk/LeZMXXLW/3y3G0X?= =?us-ascii?Q?vot/XKWTMcHKliyRfhKvx+BZ7/U7jJ0RYtbprH0C0VXF5Jp1kLhOSdw22bkA?= =?us-ascii?Q?8AF/hW8j93R0o8gkUwoRwUgb1lm9i+3udd5G6MYrMm5JMIrdBocTh22xNspc?= =?us-ascii?Q?0uMRw4yz5TI9I1ctXPeTl3+gv1BlZ1VmANY+ayhDkS9+zMYWRcoM2V407OHi?= =?us-ascii?Q?b/VgZ/k=3D?= 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:(13230037)(1800799021)(4022899006)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?R4/HFkhgXwszlrj29PFfkGDU6BPeCmEOzYvmhU8UrKPP5db7w+fODHtIbJyU?= =?us-ascii?Q?3YHrRY7g9cVPIoZIetFwhv91aDD28uQPP8rpOMM7IxBG2goG36gkVkD83vWd?= =?us-ascii?Q?7EMppct7WyAOgtj2zzyQf2Ig4ZnJv0jLWB7gTSW3WLck5gjh7o2L/2WkOxc5?= =?us-ascii?Q?zxC2CWID07Ikgit1eluRbAQQkZxd/zpd4P6EsxkLGHxye0jGpD4ZG70twiRI?= =?us-ascii?Q?44YKvO99VX0Bdj4NNpcZuy2kB9svhzB9CvnnJcv+RJkd6wJ8kPvyYmwY/cvN?= =?us-ascii?Q?/GqQBKSLlLVqNIkbPrYkdSRDqwV3xWDBLquc+pv/+q8HzjpYHlt1U0rupfAv?= =?us-ascii?Q?EtLJl9IO2qE+pmtzUeuUzjpHP/obOop6XvGAFVpalxb7fZxvTFkIwkWrQDCK?= =?us-ascii?Q?J4PYU3nG93S6TyrNGxYXyNnIX+0NI5D+uyGUiUZAWAMalCZz4GIcPOZKCHiV?= =?us-ascii?Q?0AiVbF3yFdaipwxakmBB06usuVWnQKJrOwls2vjUcqaYUKWS0kqWtlRx3wtb?= =?us-ascii?Q?tDJpO/ZGwWuBok4fb1butHq7a/d6BsLSz/GmywQY8/iUkQU3iZeLqNZ+tRbA?= =?us-ascii?Q?xX1dgE+4nnD9bPuYh085rRq4pe5fyM3JlrwHrV+yKoc8/VnWCny9GGqsz76J?= =?us-ascii?Q?k0KBlBI8KxON3RtjYbsufjbrP8u5SdWcJ+1tsvryF8WkN4GVnFn4rFDDDYZy?= =?us-ascii?Q?1qKvm/vQfIxybZ+KsS/1Zj+VCxsIW55nQoXfFRMk+sPpSVLlLhhuqqub41EQ?= =?us-ascii?Q?yUv0yqNLHUQYb8173KMKwQO9hN1fR7VbntNckIGIcCxo7sTnqvV724YyCboV?= =?us-ascii?Q?NCbbh82XgYh+OwPS4vHuN4ej/7ZtUUSsu3SheU4Ks0LJ83Nj8FdW15Bdol+D?= =?us-ascii?Q?M3X3xz64H3dpTGJAjYeuOvKcTjgZNL+6DJYQz5+72ogkbI0cflyw5vJD/eqb?= =?us-ascii?Q?qe0FpMDtJnJFwMPDXCs7Y42K+WcGIAz3sSNY6VrSoGZP2ue9eMkJsPxX54LG?= =?us-ascii?Q?50joojn2e0RbXKtUDDxyXuUNFLrLX39MNCnxDW263z3dIYz3hz+wDTKlhsv8?= =?us-ascii?Q?xEs2Ru3cx7LRC1ZUn4lA7XTxyT5lnPkwMZnNIqvxVdjdNBPreLhgIP7cA2zj?= =?us-ascii?Q?Q6b1gBRxrNJ7rS224ptVjUNr1fbBhaOXqeVXX3HB+OEp3fOk8mbL7QmyD5VJ?= =?us-ascii?Q?7Km31TXjD/+FrI2Ck9/epCGQM5GlUnNz7sfmGiPmVRiqxL+HceyiZfHgtcEq?= =?us-ascii?Q?3nh731e5KtNm0kuhg34Zy8FY5liRcxhMn3+6yfC0MgTCPX3YcI0zQ0D1lMO3?= =?us-ascii?Q?hpNFkS9lW5R/my5LiNxSPJtoszUsB4v8GJpvkOPp7EuREw3fpbpYGd78sywh?= =?us-ascii?Q?kzkcp3cXSjX9jSsMW6fxGUB2PldsP699lu2LiBHudVuPrfJ3nYtc1JifDhWn?= =?us-ascii?Q?n6j22OI2jhl57mzsSp3WAKRAJzqXWZch+hkGNfqA+oXegCTe8Qqyeh7Tpnpb?= =?us-ascii?Q?AXpxVSJfzWRl0xmXM7QKnHwTBeiNowDfhIwS1TLmGOj1rUrCEcSsZ0DuBTC1?= =?us-ascii?Q?cw1pjze1TbxKWhb/Y+VPhUh3Bhv+eZFTFv/OChD6?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1a835b9f-9272-4220-8f67-08dc91c72ed4 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:08.2610 (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: stoeMaIRMRl5FWVoV58/PGLkqk4vBSajoFLktgOmks708qMcRFMga6DQPMBQ3ZbPCpSSVM/bCH3BfHEQuijBUA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR04MB9789 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/cfg80211.c | 3773 +++++++++++++++++++ 1 file changed, 3773 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/cfg80211.c diff --git a/drivers/net/wireless/nxp/nxpwifi/cfg80211.c b/drivers/net/wire= less/nxp/nxpwifi/cfg80211.c new file mode 100644 index 000000000000..7a2b72484923 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/cfg80211.c @@ -0,0 +1,3773 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: CFG80211 + * + * Copyright 2011-2024 NXP + */ + +#include "cfg80211.h" +#include "main.h" +#include "cmdevt.h" +#include "11n.h" +#include "wmm.h" + +static const struct ieee80211_iface_limit nxpwifi_ap_sta_limits[] =3D { + { + .max =3D NXPWIFI_MAX_BSS_NUM, + .types =3D BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP), + }, +}; + +static const struct ieee80211_iface_combination +nxpwifi_iface_comb_ap_sta =3D { + .limits =3D nxpwifi_ap_sta_limits, + .num_different_channels =3D 1, + .n_limits =3D ARRAY_SIZE(nxpwifi_ap_sta_limits), + .max_interfaces =3D NXPWIFI_MAX_BSS_NUM, + .beacon_int_infra_match =3D true, + .radar_detect_widths =3D BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40), +}; + +static const struct ieee80211_iface_combination +nxpwifi_iface_comb_ap_sta_vht =3D { + .limits =3D nxpwifi_ap_sta_limits, + .num_different_channels =3D 1, + .n_limits =3D ARRAY_SIZE(nxpwifi_ap_sta_limits), + .max_interfaces =3D NXPWIFI_MAX_BSS_NUM, + .beacon_int_infra_match =3D true, + .radar_detect_widths =3D BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), +}; + +/* This function maps the nl802.11 channel type into driver channel type. + * + * The mapping is as follows - + * NL80211_CHAN_NO_HT -> IEEE80211_HT_PARAM_CHA_SEC_NONE + * NL80211_CHAN_HT20 -> IEEE80211_HT_PARAM_CHA_SEC_NONE + * NL80211_CHAN_HT40PLUS -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE + * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW + * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE + */ +u8 nxpwifi_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_typ= e) +{ + switch (chan_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + return IEEE80211_HT_PARAM_CHA_SEC_NONE; + case NL80211_CHAN_HT40PLUS: + return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + case NL80211_CHAN_HT40MINUS: + return IEEE80211_HT_PARAM_CHA_SEC_BELOW; + default: + return IEEE80211_HT_PARAM_CHA_SEC_NONE; + } +} + +/* This function maps IEEE HT secondary channel type to NL80211 channel ty= pe + */ +u8 nxpwifi_get_chan_type(struct nxpwifi_private *priv) +{ + struct nxpwifi_channel_band channel_band; + int ret; + + ret =3D nxpwifi_get_chan_info(priv, &channel_band); + + if (!ret) { + switch (channel_band.band_config.chan_width) { + case CHAN_BW_20MHZ: + if (IS_11N_ENABLED(priv)) + return NL80211_CHAN_HT20; + else + return NL80211_CHAN_NO_HT; + case CHAN_BW_40MHZ: + if (channel_band.band_config.chan2_offset =3D=3D + SEC_CHAN_ABOVE) + return NL80211_CHAN_HT40PLUS; + else + return NL80211_CHAN_HT40MINUS; + default: + return NL80211_CHAN_HT20; + } + } + + return NL80211_CHAN_HT20; +} + +/* This function retrieves the private structure from kernel wiphy structu= re. + */ +static void *nxpwifi_cfg80211_get_adapter(struct wiphy *wiphy) +{ + return (void *)(*(unsigned long *)wiphy_priv(wiphy)); +} + +/* CFG802.11 operation handler to delete a network key. + */ +static int +nxpwifi_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, + int link_id, u8 key_index, bool pairwise, + const u8 *mac_addr) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(netdev); + static const u8 bc_mac[] =3D {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const u8 *peer_mac =3D pairwise ? mac_addr : bc_mac; + + if (nxpwifi_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) { + nxpwifi_dbg(priv->adapter, ERROR, "deleting the crypto keys\n"); + return -EFAULT; + } + + nxpwifi_dbg(priv->adapter, INFO, "info: crypto keys deleted\n"); + return 0; +} + +/* This function forms an skb for management frame. + */ +static int +nxpwifi_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) +{ + u8 addr[ETH_ALEN] =3D {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + u16 pkt_len; + u32 tx_control =3D 0, pkt_type =3D PKT_TYPE_MGMT; + + pkt_len =3D len + ETH_ALEN; + + skb_reserve(skb, NXPWIFI_MIN_DATA_HEADER_LEN + + NXPWIFI_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)); + + /* Add packet data and address4 */ + skb_put_data(skb, buf, sizeof(struct ieee80211_hdr_3addr)); + skb_put_data(skb, addr, ETH_ALEN); + skb_put_data(skb, buf + sizeof(struct ieee80211_hdr_3addr), + len - sizeof(struct ieee80211_hdr_3addr)); + + skb->priority =3D LOW_PRIO_TID; + __net_timestamp(skb); + + return 0; +} + +/* CFG802.11 operation handler to transmit a management frame. + */ +static int +nxpwifi_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie) +{ + const u8 *buf =3D params->buf; + size_t len =3D params->len; + struct sk_buff *skb; + u16 pkt_len; + const struct ieee80211_mgmt *mgmt; + struct nxpwifi_txinfo *tx_info; + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + + if (!buf || !len) { + nxpwifi_dbg(priv->adapter, ERROR, "invalid buffer and length\n"); + return -EFAULT; + } + + mgmt =3D (const struct ieee80211_mgmt *)buf; + if (GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_STA && + ieee80211_is_probe_resp(mgmt->frame_control)) { + /* Since we support offload probe resp, we need to skip probe + * resp in AP or GO mode + */ + nxpwifi_dbg(priv->adapter, INFO, + "info: skip to send probe resp in AP or GO mode\n"); + return 0; + } + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + if (ieee80211_is_auth(mgmt->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "auth: send auth to %pM\n", mgmt->da); + if (ieee80211_is_deauth(mgmt->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "auth: send deauth to %pM\n", mgmt->da); + if (ieee80211_is_disassoc(mgmt->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "assoc: send disassoc to %pM\n", mgmt->da); + if (ieee80211_is_assoc_resp(mgmt->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "assoc: send assoc resp to %pM\n", + mgmt->da); + if (ieee80211_is_reassoc_resp(mgmt->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "assoc: send reassoc resp to %pM\n", + mgmt->da); + } + + pkt_len =3D len + ETH_ALEN; + skb =3D dev_alloc_skb(NXPWIFI_MIN_DATA_HEADER_LEN + + NXPWIFI_MGMT_FRAME_HEADER_SIZE + + pkt_len + sizeof(pkt_len)); + + if (!skb) { + nxpwifi_dbg(priv->adapter, ERROR, + "allocate skb failed for management frame\n"); + return -ENOMEM; + } + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num =3D priv->bss_num; + tx_info->bss_type =3D priv->bss_type; + tx_info->pkt_len =3D pkt_len; + + nxpwifi_form_mgmt_frame(skb, buf, len); + *cookie =3D get_random_u32() | 1; + + if (ieee80211_is_action(mgmt->frame_control)) + skb =3D nxpwifi_clone_skb_for_tx_status(priv, + skb, + NXPWIFI_BUF_FLAG_ACTION_TX_STATUS, cookie); + else + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, + GFP_ATOMIC); + + nxpwifi_queue_tx_pkt(priv, skb); + + nxpwifi_dbg(priv->adapter, INFO, "info: management frame transmitted\n"); + return 0; +} + +/* CFG802.11 operation handler to register a mgmt frame. + */ +static void +nxpwifi_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct mgmt_frame_regs *upd) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + u32 mask =3D upd->interface_stypes; + + if (mask !=3D priv->mgmt_frame_mask) { + priv->mgmt_frame_mask =3D mask; + if (priv->host_mlme_reg && + GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_UAP) + priv->mgmt_frame_mask |=3D HOST_MLME_MGMT_MASK; + nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, + HOST_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false); + nxpwifi_dbg(priv->adapter, INFO, "info: mgmt frame registered\n"); + } +} + +/* CFG802.11 operation handler to remain on channel. + */ +static int +nxpwifi_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + int ret; + + if (!chan || !cookie) { + nxpwifi_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n"); + return -EINVAL; + } + + if (priv->roc_cfg.cookie) { + nxpwifi_dbg(priv->adapter, INFO, + "info: ongoing ROC, cookie =3D 0x%llx\n", + priv->roc_cfg.cookie); + return -EBUSY; + } + + ret =3D nxpwifi_remain_on_chan_cfg(priv, HOST_ACT_GEN_SET, chan, + duration); + + if (!ret) { + *cookie =3D get_random_u32() | 1; + priv->roc_cfg.cookie =3D *cookie; + priv->roc_cfg.chan =3D *chan; + + cfg80211_ready_on_channel(wdev, *cookie, chan, + duration, GFP_ATOMIC); + + nxpwifi_dbg(priv->adapter, INFO, + "info: ROC, cookie =3D 0x%llx\n", *cookie); + } + + return ret; +} + +/* CFG802.11 operation handler to cancel remain on channel. + */ +static int +nxpwifi_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + int ret; + + if (cookie !=3D priv->roc_cfg.cookie) + return -ENOENT; + + ret =3D nxpwifi_remain_on_chan_cfg(priv, HOST_ACT_GEN_REMOVE, + &priv->roc_cfg.chan, 0); + + if (!ret) { + cfg80211_remain_on_channel_expired(wdev, cookie, + &priv->roc_cfg.chan, + GFP_ATOMIC); + + memset(&priv->roc_cfg, 0, sizeof(struct nxpwifi_roc_cfg)); + + nxpwifi_dbg(priv->adapter, INFO, + "info: cancel ROC, cookie =3D 0x%llx\n", cookie); + } + + return ret; +} + +/* CFG802.11 operation handler to set Tx power. + */ +static int +nxpwifi_cfg80211_set_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, + int mbm) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv; + struct nxpwifi_power_cfg power_cfg; + int dbm =3D MBM_TO_DBM(mbm); + + switch (type) { + case NL80211_TX_POWER_FIXED: + power_cfg.is_power_auto =3D 0; + power_cfg.is_power_fixed =3D 1; + power_cfg.power_level =3D dbm; + break; + case NL80211_TX_POWER_LIMITED: + power_cfg.is_power_auto =3D 0; + power_cfg.is_power_fixed =3D 0; + power_cfg.power_level =3D dbm; + break; + case NL80211_TX_POWER_AUTOMATIC: + power_cfg.is_power_auto =3D 1; + break; + } + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + return nxpwifi_set_tx_power(priv, &power_cfg); +} + +/* CFG802.11 operation handler to get Tx power. + */ +static int +nxpwifi_cfg80211_get_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv =3D nxpwifi_get_priv(adapter, + NXPWIFI_BSS_ROLE_ANY); + int ret =3D nxpwifi_send_cmd(priv, HOST_CMD_RF_TX_PWR, + HOST_ACT_GEN_GET, 0, NULL, true); + + if (ret < 0) + return ret; + + /* tx_power_level is set in HOST_CMD_RF_TX_PWR command handler */ + *dbm =3D priv->tx_power_level; + + return 0; +} + +/* CFG802.11 operation handler to set Power Save option. + * + * The timeout value, if provided, is currently ignored. + */ +static int +nxpwifi_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, int timeout) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + u32 ps_mode; + + if (timeout) + nxpwifi_dbg(priv->adapter, INFO, + "info: ignore timeout value for IEEE Power Save\n"); + + ps_mode =3D enabled; + + return nxpwifi_drv_set_power(priv, &ps_mode); +} + +/* CFG802.11 operation handler to set the default network key. + */ +static int +nxpwifi_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *n= etdev, + int link_id, u8 key_index, bool unicast, + bool multicast) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(netdev); + + /* Return if WEP key not configured */ + if (!priv->sec_info.wep_enabled) + return 0; + + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_UAP) { + priv->wep_key_curr_index =3D key_index; + } else if (nxpwifi_set_encode(priv, NULL, NULL, 0, key_index, + NULL, 0)) { + nxpwifi_dbg(priv->adapter, ERROR, "set default Tx key index\n"); + return -EFAULT; + } + + return 0; +} + +/* CFG802.11 operation handler to add a network key. + */ +static int +nxpwifi_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, + int link_id, u8 key_index, bool pairwise, + const u8 *mac_addr, struct key_params *params) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(netdev); + struct nxpwifi_wep_key *wep_key; + static const u8 bc_mac[] =3D {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const u8 *peer_mac =3D pairwise ? mac_addr : bc_mac; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP && + (params->cipher =3D=3D WLAN_CIPHER_SUITE_WEP40 || + params->cipher =3D=3D WLAN_CIPHER_SUITE_WEP104)) { + if (params->key && params->key_len) { + wep_key =3D &priv->wep_key[key_index]; + memset(wep_key, 0, sizeof(struct nxpwifi_wep_key)); + memcpy(wep_key->key_material, params->key, + params->key_len); + wep_key->key_index =3D key_index; + wep_key->key_length =3D params->key_len; + priv->sec_info.wep_enabled =3D 1; + } + return 0; + } + + if (nxpwifi_set_encode(priv, params, params->key, params->key_len, + key_index, peer_mac, 0)) { + nxpwifi_dbg(priv->adapter, ERROR, "crypto keys added\n"); + return -EFAULT; + } + + return 0; +} + +/* CFG802.11 operation handler to set default mgmt key. + */ +static int +nxpwifi_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *netdev, + int link_id, + u8 key_index) +{ + return 0; +} + +/* This function sends domain information to the firmware. + * + * The following information are passed to the firmware - + * - Country codes + * - Sub bands (first channel, number of channels, maximum Tx power) + */ +int nxpwifi_send_domain_info_cmd_fw(struct wiphy *wiphy) +{ + u8 no_of_triplet =3D 0; + struct ieee80211_country_ie_triplet *t; + u8 no_of_parsed_chan =3D 0; + u8 first_chan =3D 0, next_chan =3D 0, max_pwr =3D 0; + u8 i, flag =3D 0; + enum nl80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv; + struct nxpwifi_802_11d_domain_reg *domain_info =3D &adapter->domain_reg; + + /* Set country code */ + domain_info->country_code[0] =3D adapter->country_code[0]; + domain_info->country_code[1] =3D adapter->country_code[1]; + domain_info->country_code[2] =3D ' '; + + band =3D nxpwifi_band_to_radio_type(adapter->config_bands); + if (!wiphy->bands[band]) { + nxpwifi_dbg(adapter, ERROR, + "11D: setting domain info in FW\n"); + return -1; + } + + sband =3D wiphy->bands[band]; + + for (i =3D 0; i < sband->n_channels ; i++) { + ch =3D &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (!flag) { + flag =3D 1; + first_chan =3D (u32)ch->hw_value; + next_chan =3D first_chan; + max_pwr =3D ch->max_power; + no_of_parsed_chan =3D 1; + continue; + } + + if (ch->hw_value =3D=3D next_chan + 1 && + ch->max_power =3D=3D max_pwr) { + next_chan++; + no_of_parsed_chan++; + } else { + t =3D &domain_info->triplet[no_of_triplet]; + t->chans.first_channel =3D first_chan; + t->chans.num_channels =3D no_of_parsed_chan; + t->chans.max_power =3D max_pwr; + no_of_triplet++; + first_chan =3D (u32)ch->hw_value; + next_chan =3D first_chan; + max_pwr =3D ch->max_power; + no_of_parsed_chan =3D 1; + } + } + + if (flag) { + t =3D &domain_info->triplet[no_of_triplet]; + t->chans.first_channel =3D first_chan; + t->chans.num_channels =3D no_of_parsed_chan; + t->chans.max_power =3D max_pwr; + no_of_triplet++; + } + + domain_info->no_of_triplet =3D no_of_triplet; + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + if (nxpwifi_send_cmd(priv, HOST_CMD_802_11D_DOMAIN_INFO, + HOST_ACT_GEN_SET, 0, NULL, false)) { + nxpwifi_dbg(adapter, INFO, + "11D: setting domain info in FW\n"); + return -1; + } + + return 0; +} + +static void nxpwifi_reg_apply_radar_flags(struct wiphy *wiphy) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + unsigned int i; + + if (!wiphy->bands[NL80211_BAND_5GHZ]) + return; + sband =3D wiphy->bands[NL80211_BAND_5GHZ]; + + for (i =3D 0; i < sband->n_channels; i++) { + chan =3D &sband->channels[i]; + if ((!(chan->flags & IEEE80211_CHAN_DISABLED)) && + (chan->flags & IEEE80211_CHAN_RADAR)) + chan->flags |=3D IEEE80211_CHAN_NO_IR; + } +} + +/* CFG802.11 regulatory domain callback function. + * + * This function is called when the regulatory domain is changed due to the + * following reasons - + * - Set by driver + * - Set by system core + * - Set by user + * - Set bt Country IE + */ +static void nxpwifi_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv =3D nxpwifi_get_priv(adapter, + NXPWIFI_BSS_ROLE_ANY); + nxpwifi_dbg(adapter, INFO, + "info: cfg80211 regulatory domain callback for %c%c\n", + request->alpha2[0], request->alpha2[1]); + nxpwifi_reg_apply_radar_flags(wiphy); + + switch (request->initiator) { + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + break; + default: + nxpwifi_dbg(adapter, ERROR, + "unknown regdom initiator: %d\n", + request->initiator); + return; + } + + /* Don't send world or same regdom info to firmware */ + if (strncmp(request->alpha2, "00", 2) && + strncmp(request->alpha2, adapter->country_code, + sizeof(request->alpha2))) { + memcpy(adapter->country_code, request->alpha2, + sizeof(request->alpha2)); + nxpwifi_send_domain_info_cmd_fw(wiphy); + nxpwifi_dnld_txpwr_table(priv); + } +} + +/* This function sets the fragmentation threshold. + * + * The fragmentation threshold value must lie between NXPWIFI_FRAG_MIN_VAL= UE + * and NXPWIFI_FRAG_MAX_VALUE. + */ +static int +nxpwifi_set_frag(struct nxpwifi_private *priv, u32 frag_thr) +{ + if (frag_thr < NXPWIFI_FRAG_MIN_VALUE || + frag_thr > NXPWIFI_FRAG_MAX_VALUE) + frag_thr =3D NXPWIFI_FRAG_MAX_VALUE; + + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_SET, FRAG_THRESH_I, + &frag_thr, true); +} + +/* This function sets the RTS threshold. + * + * The rts value must lie between NXPWIFI_RTS_MIN_VALUE + * and NXPWIFI_RTS_MAX_VALUE. + */ +static int +nxpwifi_set_rts(struct nxpwifi_private *priv, u32 rts_thr) +{ + if (rts_thr < NXPWIFI_RTS_MIN_VALUE || rts_thr > NXPWIFI_RTS_MAX_VALUE) + rts_thr =3D NXPWIFI_RTS_MAX_VALUE; + + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_SET, RTS_THRESH_I, + &rts_thr, true); +} + +/* CFG802.11 operation handler to set wiphy parameters. + * + * This function can be used to set the RTS threshold and the + * Fragmentation threshold of the driver. + */ +static int +nxpwifi_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv; + struct nxpwifi_uap_bss_param *bss_cfg; + int ret; + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + switch (priv->bss_role) { + case NXPWIFI_BSS_ROLE_UAP: + if (priv->bss_started) + return 0; + + bss_cfg =3D kzalloc(sizeof(*bss_cfg), GFP_KERNEL); + if (!bss_cfg) + return -ENOMEM; + + nxpwifi_set_sys_config_invalid_data(bss_cfg); + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + bss_cfg->rts_threshold =3D wiphy->rts_threshold; + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + bss_cfg->frag_threshold =3D wiphy->frag_threshold; + if (changed & WIPHY_PARAM_RETRY_LONG) + bss_cfg->retry_limit =3D wiphy->retry_long; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_UAP_SYS_CONFIG, + HOST_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg, + false); + + kfree(bss_cfg); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "Failed to set wiphy phy params\n"); + return ret; + } + break; + + case NXPWIFI_BSS_ROLE_STA: + if (priv->media_connected) + return 0; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + ret =3D nxpwifi_set_rts(priv, + wiphy->rts_threshold); + if (ret) + return ret; + } + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + ret =3D nxpwifi_set_frag(priv, + wiphy->frag_threshold); + if (ret) + return ret; + } + break; + } + + return 0; +} + +static int nxpwifi_deinit_priv_params(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + unsigned long flags; + + priv->host_mlme_reg =3D false; + priv->mgmt_frame_mask =3D 0; + if (nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, + HOST_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false)) { + nxpwifi_dbg(adapter, ERROR, + "could not unregister mgmt frame rx\n"); + return -1; + } + + nxpwifi_deauthenticate(priv, NULL); + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + adapter->main_locked =3D true; + if (adapter->nxpwifi_processing) { + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + flush_workqueue(adapter->workqueue); + } else { + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + } + + spin_lock_bh(&adapter->rx_proc_lock); + adapter->rx_locked =3D true; + if (adapter->rx_processing) { + spin_unlock_bh(&adapter->rx_proc_lock); + flush_workqueue(adapter->rx_workqueue); + } else { + spin_unlock_bh(&adapter->rx_proc_lock); + } + + nxpwifi_free_priv(priv); + priv->wdev.iftype =3D NL80211_IFTYPE_UNSPECIFIED; + priv->bss_mode =3D NL80211_IFTYPE_UNSPECIFIED; + priv->sec_info.authentication_mode =3D NL80211_AUTHTYPE_OPEN_SYSTEM; + + return 0; +} + +static int +nxpwifi_init_new_priv_params(struct nxpwifi_private *priv, + struct net_device *dev, + enum nl80211_iftype type) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + unsigned long flags; + + nxpwifi_init_priv(priv); + + priv->bss_mode =3D type; + priv->wdev.iftype =3D type; + + nxpwifi_init_priv_params(priv, priv->netdev); + priv->bss_started =3D 0; + + switch (type) { + case NL80211_IFTYPE_STATION: + priv->bss_role =3D NXPWIFI_BSS_ROLE_STA; + priv->bss_type =3D NXPWIFI_BSS_TYPE_STA; + break; + case NL80211_IFTYPE_AP: + priv->bss_role =3D NXPWIFI_BSS_ROLE_UAP; + priv->bss_type =3D NXPWIFI_BSS_TYPE_UAP; + break; + default: + nxpwifi_dbg(adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); + return -EOPNOTSUPP; + } + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + adapter->main_locked =3D false; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + + spin_lock_bh(&adapter->rx_proc_lock); + adapter->rx_locked =3D false; + spin_unlock_bh(&adapter->rx_proc_lock); + + nxpwifi_set_mac_address(priv, dev, false, NULL); + + return 0; +} + +static bool +is_vif_type_change_allowed(struct nxpwifi_adapter *adapter, + enum nl80211_iftype old_iftype, + enum nl80211_iftype new_iftype) +{ + switch (old_iftype) { + case NL80211_IFTYPE_STATION: + switch (new_iftype) { + case NL80211_IFTYPE_AP: + return adapter->curr_iface_comb.uap_intf !=3D + adapter->iface_limit.uap_intf; + default: + return false; + } + + case NL80211_IFTYPE_AP: + switch (new_iftype) { + case NL80211_IFTYPE_STATION: + return adapter->curr_iface_comb.sta_intf !=3D + adapter->iface_limit.sta_intf; + default: + return false; + } + + default: + break; + } + + return false; +} + +static void +update_vif_type_counter(struct nxpwifi_adapter *adapter, + enum nl80211_iftype iftype, + int change) +{ + switch (iftype) { + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_STATION: + adapter->curr_iface_comb.sta_intf +=3D change; + break; + case NL80211_IFTYPE_AP: + adapter->curr_iface_comb.uap_intf +=3D change; + break; + default: + nxpwifi_dbg(adapter, ERROR, + "%s: Unsupported iftype passed: %d\n", + __func__, iftype); + break; + } +} + +static int +nxpwifi_change_vif_to_sta(struct net_device *dev, + enum nl80211_iftype curr_iftype, + enum nl80211_iftype type, + struct vif_params *params) +{ + struct nxpwifi_private *priv; + struct nxpwifi_adapter *adapter; + + priv =3D nxpwifi_netdev_get_priv(dev); + + if (!priv) + return -1; + + adapter =3D priv->adapter; + + nxpwifi_dbg(adapter, INFO, + "%s: changing role to station\n", dev->name); + + if (nxpwifi_deinit_priv_params(priv)) + return -1; + if (nxpwifi_init_new_priv_params(priv, dev, type)) + return -1; + + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, 1); + dev->ieee80211_ptr->iftype =3D type; + + if (nxpwifi_send_cmd(priv, HOST_CMD_SET_BSS_MODE, + HOST_ACT_GEN_SET, 0, NULL, true)) + return -1; + if (nxpwifi_sta_init_cmd(priv, false, false)) + return -1; + + return 0; +} + +static int +nxpwifi_change_vif_to_ap(struct net_device *dev, + enum nl80211_iftype curr_iftype, + enum nl80211_iftype type, + struct vif_params *params) +{ + struct nxpwifi_private *priv; + struct nxpwifi_adapter *adapter; + + priv =3D nxpwifi_netdev_get_priv(dev); + + if (!priv) + return -1; + + adapter =3D priv->adapter; + + nxpwifi_dbg(adapter, INFO, + "%s: changing role to AP\n", dev->name); + + if (nxpwifi_deinit_priv_params(priv)) + return -1; + if (nxpwifi_init_new_priv_params(priv, dev, type)) + return -1; + + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, 1); + dev->ieee80211_ptr->iftype =3D type; + + if (nxpwifi_send_cmd(priv, HOST_CMD_SET_BSS_MODE, + HOST_ACT_GEN_SET, 0, NULL, true)) + return -1; + if (nxpwifi_sta_init_cmd(priv, false, false)) + return -1; + + return 0; +} + +/* CFG802.11 operation handler to change interface type. + */ +static int +nxpwifi_cfg80211_change_virtual_intf(struct wiphy *wiphy, + struct net_device *dev, + enum nl80211_iftype type, + struct vif_params *params) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + enum nl80211_iftype curr_iftype =3D dev->ieee80211_ptr->iftype; + + if (priv->scan_request) { + nxpwifi_dbg(priv->adapter, ERROR, + "change virtual interface: scan in process\n"); + return -EBUSY; + } + + if (type =3D=3D NL80211_IFTYPE_UNSPECIFIED) { + nxpwifi_dbg(priv->adapter, INFO, + "%s: no new type specified, keeping old type %d\n", + dev->name, curr_iftype); + return 0; + } + + if (curr_iftype =3D=3D type) { + nxpwifi_dbg(priv->adapter, INFO, + "%s: interface already is of type %d\n", + dev->name, curr_iftype); + return 0; + } + + if (!is_vif_type_change_allowed(priv->adapter, curr_iftype, type)) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: change from type %d to %d is not allowed\n", + dev->name, curr_iftype, type); + return -EOPNOTSUPP; + } + + switch (curr_iftype) { + case NL80211_IFTYPE_STATION: + switch (type) { + case NL80211_IFTYPE_AP: + return nxpwifi_change_vif_to_ap(dev, curr_iftype, type, + params); + default: + goto errnotsupp; + } + + case NL80211_IFTYPE_AP: + switch (type) { + case NL80211_IFTYPE_STATION: + return nxpwifi_change_vif_to_sta(dev, curr_iftype, + type, params); + break; + default: + goto errnotsupp; + } + + default: + goto errnotsupp; + } + + return 0; + +errnotsupp: + nxpwifi_dbg(priv->adapter, ERROR, + "unsupported interface type transition: %d to %d\n", + curr_iftype, type); + return -EOPNOTSUPP; +} + +static void +nxpwifi_parse_htinfo(struct nxpwifi_private *priv, u8 rateinfo, u8 htinfo, + struct rate_info *rate) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (adapter->is_hw_11ac_capable) { + /* bit[1-0]: 00=3DLG 01=3DHT 10=3DVHT */ + if (htinfo & BIT(0)) { + /* HT */ + rate->mcs =3D rateinfo; + rate->flags |=3D RATE_INFO_FLAGS_MCS; + } + if (htinfo & BIT(1)) { + /* VHT */ + rate->mcs =3D rateinfo & 0x0F; + rate->flags |=3D RATE_INFO_FLAGS_VHT_MCS; + } + + if (htinfo & (BIT(1) | BIT(0))) { + /* HT or VHT */ + switch (htinfo & (BIT(3) | BIT(2))) { + case 0: + rate->bw =3D RATE_INFO_BW_20; + break; + case (BIT(2)): + rate->bw =3D RATE_INFO_BW_40; + break; + case (BIT(3)): + rate->bw =3D RATE_INFO_BW_80; + break; + case (BIT(3) | BIT(2)): + rate->bw =3D RATE_INFO_BW_160; + break; + } + + if (htinfo & BIT(4)) + rate->flags |=3D RATE_INFO_FLAGS_SHORT_GI; + + if ((rateinfo >> 4) =3D=3D 1) + rate->nss =3D 2; + else + rate->nss =3D 1; + } + } else { + /* Bit 0 in htinfo indicates that current rate is 11n. Valid + * MCS index values for us are 0 to 15. + */ + if ((htinfo & BIT(0)) && rateinfo < 16) { + rate->mcs =3D rateinfo; + rate->flags |=3D RATE_INFO_FLAGS_MCS; + rate->bw =3D RATE_INFO_BW_20; + if (htinfo & BIT(1)) + rate->bw =3D RATE_INFO_BW_40; + if (htinfo & BIT(2)) + rate->flags |=3D RATE_INFO_FLAGS_SHORT_GI; + } + } + + /* Decode legacy rates for non-HT. */ + if (!(htinfo & (BIT(0) | BIT(1)))) { + /* Bitrates in multiples of 100kb/s. */ + static const int legacy_rates[] =3D { + [0] =3D 10, + [1] =3D 20, + [2] =3D 55, + [3] =3D 110, + [4] =3D 60, /* NXPWIFI_RATE_INDEX_OFDM0 */ + [5] =3D 60, + [6] =3D 90, + [7] =3D 120, + [8] =3D 180, + [9] =3D 240, + [10] =3D 360, + [11] =3D 480, + [12] =3D 540, + }; + if (rateinfo < ARRAY_SIZE(legacy_rates)) + rate->legacy =3D legacy_rates[rateinfo]; + } +} + +/* This function dumps the station information on a buffer. + * + * The following information are shown - + * - Total bytes transmitted + * - Total bytes received + * - Total packets transmitted + * - Total packets received + * - Signal quality level + * - Transmission rate + */ +static int +nxpwifi_dump_station_info(struct nxpwifi_private *priv, + struct nxpwifi_sta_node *node, + struct station_info *sinfo) +{ + u32 rate; + + sinfo->filled =3D BIT_ULL(NL80211_STA_INFO_RX_BYTES) | + BIT_ULL(NL80211_STA_INFO_TX_BYTES) | + BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | + BIT_ULL(NL80211_STA_INFO_TX_PACKETS) | + BIT_ULL(NL80211_STA_INFO_TX_BITRATE) | + BIT_ULL(NL80211_STA_INFO_SIGNAL) | + BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + if (!node) + return -ENOENT; + + sinfo->filled |=3D BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) | + BIT_ULL(NL80211_STA_INFO_TX_FAILED); + sinfo->inactive_time =3D + jiffies_to_msecs(jiffies - node->stats.last_rx); + + sinfo->signal =3D node->stats.rssi; + sinfo->signal_avg =3D node->stats.rssi; + sinfo->rx_bytes =3D node->stats.rx_bytes; + sinfo->tx_bytes =3D node->stats.tx_bytes; + sinfo->rx_packets =3D node->stats.rx_packets; + sinfo->tx_packets =3D node->stats.tx_packets; + sinfo->tx_failed =3D node->stats.tx_failed; + + nxpwifi_parse_htinfo(priv, priv->tx_rate, + node->stats.last_tx_htinfo, + &sinfo->txrate); + sinfo->txrate.legacy =3D node->stats.last_tx_rate * 5; + + return 0; + } + + /* Get signal information from the firmware */ + if (nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO, + HOST_ACT_GEN_GET, 0, NULL, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "failed to get signal information\n"); + return -EFAULT; + } + + if (nxpwifi_drv_get_data_rate(priv, &rate)) { + nxpwifi_dbg(priv->adapter, ERROR, + "getting data rate error\n"); + return -EFAULT; + } + + /* Get DTIM period information from firmware */ + nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_GET, DTIM_PERIOD_I, + &priv->dtim_period, true); + + nxpwifi_parse_htinfo(priv, priv->tx_rate, priv->tx_htinfo, + &sinfo->txrate); + + sinfo->signal_avg =3D priv->bcn_rssi_avg; + sinfo->rx_bytes =3D priv->stats.rx_bytes; + sinfo->tx_bytes =3D priv->stats.tx_bytes; + sinfo->rx_packets =3D priv->stats.rx_packets; + sinfo->tx_packets =3D priv->stats.tx_packets; + sinfo->signal =3D priv->bcn_rssi_avg; + /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ + sinfo->txrate.legacy =3D rate * 5; + + sinfo->filled |=3D BIT(NL80211_STA_INFO_RX_BITRATE); + nxpwifi_parse_htinfo(priv, priv->rxpd_rate, priv->rxpd_htinfo, + &sinfo->rxrate); + + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION) { + sinfo->filled |=3D BIT_ULL(NL80211_STA_INFO_BSS_PARAM); + sinfo->bss_param.flags =3D 0; + if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap & + WLAN_CAPABILITY_SHORT_PREAMBLE) + sinfo->bss_param.flags |=3D + BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap & + WLAN_CAPABILITY_SHORT_SLOT_TIME) + sinfo->bss_param.flags |=3D + BSS_PARAM_FLAGS_SHORT_SLOT_TIME; + sinfo->bss_param.dtim_period =3D priv->dtim_period; + sinfo->bss_param.beacon_interval =3D + priv->curr_bss_params.bss_descriptor.beacon_period; + } + + return 0; +} + +/* CFG802.11 operation handler to get station information. + * + * This function only works in connected mode, and dumps the + * requested station information, if available. + */ +static int +nxpwifi_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac, struct station_info *sinfo) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + if (!priv->media_connected) + return -ENOENT; + if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) + return -ENOENT; + + return nxpwifi_dump_station_info(priv, NULL, sinfo); +} + +/* CFG802.11 operation handler to dump station information. + */ +static int +nxpwifi_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_sta_node *node; + int i; + + if ((GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) && + priv->media_connected && idx =3D=3D 0) { + ether_addr_copy(mac, priv->cfg_bssid); + return nxpwifi_dump_station_info(priv, NULL, sinfo); + } else if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + nxpwifi_send_cmd(priv, HOST_CMD_APCMD_STA_LIST, + HOST_ACT_GEN_GET, 0, NULL, true); + + i =3D 0; + list_for_each_entry(node, &priv->sta_list, list) { + if (i++ !=3D idx) + continue; + ether_addr_copy(mac, node->mac_addr); + return nxpwifi_dump_station_info(priv, node, sinfo); + } + } + + return -ENOENT; +} + +static int +nxpwifi_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, + int idx, struct survey_info *survey) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_chan_stats *pchan_stats =3D priv->adapter->chan_stats; + enum nl80211_band band; + u8 chan_num; + + nxpwifi_dbg(priv->adapter, DUMP, "dump_survey idx=3D%d\n", idx); + + memset(survey, 0, sizeof(struct survey_info)); + + if ((GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) && + priv->media_connected && idx =3D=3D 0) { + u8 curr_bss_band =3D priv->curr_bss_params.band; + u32 chan =3D priv->curr_bss_params.bss_descriptor.channel; + + band =3D nxpwifi_band_to_radio_type(curr_bss_band); + survey->channel =3D ieee80211_get_channel + (wiphy, + ieee80211_channel_to_frequency(chan, band)); + + if (priv->bcn_nf_last) { + survey->filled =3D SURVEY_INFO_NOISE_DBM; + survey->noise =3D priv->bcn_nf_last; + } + return 0; + } + + if (idx >=3D priv->adapter->num_in_chan_stats) + return -ENOENT; + + if (!pchan_stats[idx].cca_scan_dur) + return 0; + + band =3D pchan_stats[idx].bandcfg; + chan_num =3D pchan_stats[idx].chan_num; + survey->channel =3D ieee80211_get_channel + (wiphy, + ieee80211_channel_to_frequency(chan_num, band)); + survey->filled =3D SURVEY_INFO_NOISE_DBM | + SURVEY_INFO_TIME | + SURVEY_INFO_TIME_BUSY; + survey->noise =3D pchan_stats[idx].noise; + survey->time =3D pchan_stats[idx].cca_scan_dur; + survey->time_busy =3D pchan_stats[idx].cca_busy_dur; + + return 0; +} + +/* Supported rates to be advertised to the cfg80211 */ +static struct ieee80211_rate nxpwifi_rates[] =3D { + {.bitrate =3D 10, .hw_value =3D 2, }, + {.bitrate =3D 20, .hw_value =3D 4, }, + {.bitrate =3D 55, .hw_value =3D 11, }, + {.bitrate =3D 110, .hw_value =3D 22, }, + {.bitrate =3D 60, .hw_value =3D 12, }, + {.bitrate =3D 90, .hw_value =3D 18, }, + {.bitrate =3D 120, .hw_value =3D 24, }, + {.bitrate =3D 180, .hw_value =3D 36, }, + {.bitrate =3D 240, .hw_value =3D 48, }, + {.bitrate =3D 360, .hw_value =3D 72, }, + {.bitrate =3D 480, .hw_value =3D 96, }, + {.bitrate =3D 540, .hw_value =3D 108, }, +}; + +/* Channel definitions to be advertised to cfg80211 */ +static struct ieee80211_channel nxpwifi_channels_2ghz[] =3D { + {.center_freq =3D 2412, .hw_value =3D 1, }, + {.center_freq =3D 2417, .hw_value =3D 2, }, + {.center_freq =3D 2422, .hw_value =3D 3, }, + {.center_freq =3D 2427, .hw_value =3D 4, }, + {.center_freq =3D 2432, .hw_value =3D 5, }, + {.center_freq =3D 2437, .hw_value =3D 6, }, + {.center_freq =3D 2442, .hw_value =3D 7, }, + {.center_freq =3D 2447, .hw_value =3D 8, }, + {.center_freq =3D 2452, .hw_value =3D 9, }, + {.center_freq =3D 2457, .hw_value =3D 10, }, + {.center_freq =3D 2462, .hw_value =3D 11, }, + {.center_freq =3D 2467, .hw_value =3D 12, }, + {.center_freq =3D 2472, .hw_value =3D 13, }, + {.center_freq =3D 2484, .hw_value =3D 14, }, +}; + +static struct ieee80211_supported_band nxpwifi_band_2ghz =3D { + .channels =3D nxpwifi_channels_2ghz, + .n_channels =3D ARRAY_SIZE(nxpwifi_channels_2ghz), + .bitrates =3D nxpwifi_rates, + .n_bitrates =3D ARRAY_SIZE(nxpwifi_rates), +}; + +static struct ieee80211_channel nxpwifi_channels_5ghz[] =3D { + {.center_freq =3D 5040, .hw_value =3D 8, }, + {.center_freq =3D 5060, .hw_value =3D 12, }, + {.center_freq =3D 5080, .hw_value =3D 16, }, + {.center_freq =3D 5170, .hw_value =3D 34, }, + {.center_freq =3D 5190, .hw_value =3D 38, }, + {.center_freq =3D 5210, .hw_value =3D 42, }, + {.center_freq =3D 5230, .hw_value =3D 46, }, + {.center_freq =3D 5180, .hw_value =3D 36, }, + {.center_freq =3D 5200, .hw_value =3D 40, }, + {.center_freq =3D 5220, .hw_value =3D 44, }, + {.center_freq =3D 5240, .hw_value =3D 48, }, + {.center_freq =3D 5260, .hw_value =3D 52, }, + {.center_freq =3D 5280, .hw_value =3D 56, }, + {.center_freq =3D 5300, .hw_value =3D 60, }, + {.center_freq =3D 5320, .hw_value =3D 64, }, + {.center_freq =3D 5500, .hw_value =3D 100, }, + {.center_freq =3D 5520, .hw_value =3D 104, }, + {.center_freq =3D 5540, .hw_value =3D 108, }, + {.center_freq =3D 5560, .hw_value =3D 112, }, + {.center_freq =3D 5580, .hw_value =3D 116, }, + {.center_freq =3D 5600, .hw_value =3D 120, }, + {.center_freq =3D 5620, .hw_value =3D 124, }, + {.center_freq =3D 5640, .hw_value =3D 128, }, + {.center_freq =3D 5660, .hw_value =3D 132, }, + {.center_freq =3D 5680, .hw_value =3D 136, }, + {.center_freq =3D 5700, .hw_value =3D 140, }, + {.center_freq =3D 5745, .hw_value =3D 149, }, + {.center_freq =3D 5765, .hw_value =3D 153, }, + {.center_freq =3D 5785, .hw_value =3D 157, }, + {.center_freq =3D 5805, .hw_value =3D 161, }, + {.center_freq =3D 5825, .hw_value =3D 165, }, +}; + +static struct ieee80211_supported_band nxpwifi_band_5ghz =3D { + .channels =3D nxpwifi_channels_5ghz, + .n_channels =3D ARRAY_SIZE(nxpwifi_channels_5ghz), + .bitrates =3D nxpwifi_rates + 4, + .n_bitrates =3D ARRAY_SIZE(nxpwifi_rates) - 4, +}; + +/* Supported crypto cipher suits to be advertised to cfg80211 */ +static const u32 nxpwifi_cipher_suites[] =3D { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_SMS4, + WLAN_CIPHER_SUITE_AES_CMAC, +}; + +/* Supported mgmt frame types to be advertised to cfg80211 */ +static const struct ieee80211_txrx_stypes +nxpwifi_mgmt_stypes[NUM_NL80211_IFTYPES] =3D { + [NL80211_IFTYPE_STATION] =3D { + .tx =3D BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx =3D BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + }, + [NL80211_IFTYPE_AP] =3D { + .tx =3D 0xffff, + .rx =3D BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4), + }, +}; + +/* CFG802.11 operation handler for setting bit rates. + * + * Function configures data rates to firmware using bitrate mask + * provided by cfg80211. + */ +static int +nxpwifi_cfg80211_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + unsigned int link_id, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; + enum nl80211_band band; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (!priv->media_connected) { + nxpwifi_dbg(adapter, ERROR, + "Can not set Tx data rate in disconnected state\n"); + return -EINVAL; + } + + band =3D nxpwifi_band_to_radio_type(priv->curr_bss_params.band); + + memset(bitmap_rates, 0, sizeof(bitmap_rates)); + + /* Fill HR/DSSS rates. */ + if (band =3D=3D NL80211_BAND_2GHZ) + bitmap_rates[0] =3D mask->control[band].legacy & 0x000f; + + /* Fill OFDM rates */ + if (band =3D=3D NL80211_BAND_2GHZ) + bitmap_rates[1] =3D (mask->control[band].legacy & 0x0ff0) >> 4; + else + bitmap_rates[1] =3D mask->control[band].legacy; + + /* Fill HT MCS rates */ + bitmap_rates[2] =3D mask->control[band].ht_mcs[0]; + if (adapter->hw_dev_mcs_support =3D=3D HT_STREAM_2X2) + bitmap_rates[2] |=3D mask->control[band].ht_mcs[1] << 8; + + /* Fill VHT MCS rates */ + if (adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) { + bitmap_rates[10] =3D mask->control[band].vht_mcs[0]; + if (adapter->hw_dev_mcs_support =3D=3D HT_STREAM_2X2) + bitmap_rates[11] =3D mask->control[band].vht_mcs[1]; + } + + return nxpwifi_send_cmd(priv, HOST_CMD_TX_RATE_CFG, + HOST_ACT_GEN_SET, 0, bitmap_rates, true); +} + +/* CFG802.11 operation handler for connection quality monitoring. + * + * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI + * events to FW. + */ +static int nxpwifi_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, + s32 rssi_thold, u32 rssi_hyst) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_ds_misc_subsc_evt subsc_evt; + + priv->cqm_rssi_thold =3D rssi_thold; + priv->cqm_rssi_hyst =3D rssi_hyst; + + memset(&subsc_evt, 0x00, sizeof(struct nxpwifi_ds_misc_subsc_evt)); + subsc_evt.events =3D BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; + + /* Subscribe/unsubscribe low and high rssi events */ + if (rssi_thold && rssi_hyst) { + subsc_evt.action =3D HOST_ACT_BITWISE_SET; + subsc_evt.bcn_l_rssi_cfg.abs_value =3D abs(rssi_thold); + subsc_evt.bcn_h_rssi_cfg.abs_value =3D abs(rssi_thold); + subsc_evt.bcn_l_rssi_cfg.evt_freq =3D 1; + subsc_evt.bcn_h_rssi_cfg.evt_freq =3D 1; + return nxpwifi_send_cmd(priv, + HOST_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, &subsc_evt, true); + } else { + subsc_evt.action =3D HOST_ACT_BITWISE_CLR; + return nxpwifi_send_cmd(priv, + HOST_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, &subsc_evt, true); + } + + return 0; +} + +int nxpwifi_cfg80211_change_beacon_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *data) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_cancel_scan(adapter); + + if (GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_UAP) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: bss_type mismatched\n", __func__); + return -EINVAL; + } + + if (nxpwifi_set_mgmt_ies(priv, data)) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: setting mgmt ies failed\n", __func__); + return -EFAULT; + } + + return 0; +} + +/* cfg80211 operation handler for change_beacon. + * Function retrieves and sets modified management IEs to FW. + */ +static int nxpwifi_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_update *params) +{ + int ret; + + ret =3D nxpwifi_cfg80211_change_beacon_data(wiphy, dev, ¶ms->beacon); + + return ret; +} + +/* cfg80211 operation handler for del_station. + * Function deauthenticates station which value is provided in mac paramet= er. + * If mac is NULL/broadcast, all stations in associated station list are + * deauthenticated. If bss is not started or there are no stations in + * associated stations list, no action is taken. + */ +static int +nxpwifi_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, + struct station_del_parameters *params) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_sta_node *sta_node; + u8 deauth_mac[ETH_ALEN]; + + if (!priv->bss_started && priv->wdev.cac_started) { + nxpwifi_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__); + nxpwifi_abort_cac(priv); + } + + if (list_empty(&priv->sta_list) || !priv->bss_started) + return 0; + + if (!params->mac || is_broadcast_ether_addr(params->mac)) + return 0; + + nxpwifi_dbg(priv->adapter, INFO, "%s: mac address %pM\n", + __func__, params->mac); + + eth_zero_addr(deauth_mac); + + spin_lock_bh(&priv->sta_list_spinlock); + sta_node =3D nxpwifi_get_sta_entry(priv, params->mac); + if (sta_node) + ether_addr_copy(deauth_mac, params->mac); + spin_unlock_bh(&priv->sta_list_spinlock); + + if (is_valid_ether_addr(deauth_mac)) { + if (nxpwifi_send_cmd(priv, HOST_CMD_UAP_STA_DEAUTH, + HOST_ACT_GEN_SET, 0, + deauth_mac, true)) + return -1; + } + + return 0; +} + +static int +nxpwifi_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv =3D nxpwifi_get_priv(adapter, + NXPWIFI_BSS_ROLE_ANY); + struct nxpwifi_ds_ant_cfg ant_cfg; + + if (!tx_ant || !rx_ant) + return -EOPNOTSUPP; + + if (adapter->hw_dev_mcs_support !=3D HT_STREAM_2X2) { + /* Not a MIMO chip. User should provide specific antenna number + * for Tx/Rx path or enable all antennas for diversity + */ + if (tx_ant !=3D rx_ant) + return -EOPNOTSUPP; + + if ((tx_ant & (tx_ant - 1)) && + (tx_ant !=3D BIT(adapter->number_of_antenna) - 1)) + return -EOPNOTSUPP; + + if ((tx_ant =3D=3D BIT(adapter->number_of_antenna) - 1) && + priv->adapter->number_of_antenna > 1) { + tx_ant =3D RF_ANTENNA_AUTO; + rx_ant =3D RF_ANTENNA_AUTO; + } + } else { + struct ieee80211_sta_ht_cap *ht_info; + int rx_mcs_supp; + enum nl80211_band band; + + if ((tx_ant =3D=3D 0x1 && rx_ant =3D=3D 0x1)) { + adapter->user_dev_mcs_support =3D HT_STREAM_1X1; + if (adapter->is_hw_11ac_capable) + adapter->usr_dot_11ac_mcs_support =3D + NXPWIFI_11AC_MCS_MAP_1X1; + } else { + adapter->user_dev_mcs_support =3D HT_STREAM_2X2; + if (adapter->is_hw_11ac_capable) + adapter->usr_dot_11ac_mcs_support =3D + NXPWIFI_11AC_MCS_MAP_2X2; + } + + for (band =3D 0; band < NUM_NL80211_BANDS; band++) { + if (!adapter->wiphy->bands[band]) + continue; + + ht_info =3D &adapter->wiphy->bands[band]->ht_cap; + rx_mcs_supp =3D + GET_RXMCSSUPP(adapter->user_dev_mcs_support); + memset(&ht_info->mcs, 0, adapter->number_of_antenna); + memset(&ht_info->mcs, 0xff, rx_mcs_supp); + } + } + + ant_cfg.tx_ant =3D tx_ant; + ant_cfg.rx_ant =3D rx_ant; + + return nxpwifi_send_cmd(priv, HOST_CMD_RF_ANTENNA, + HOST_ACT_GEN_SET, 0, &ant_cfg, true); +} + +static int +nxpwifi_cfg80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv =3D nxpwifi_get_priv(adapter, + NXPWIFI_BSS_ROLE_ANY); + nxpwifi_send_cmd(priv, HOST_CMD_RF_ANTENNA, + HOST_ACT_GEN_GET, 0, NULL, true); + + *tx_ant =3D priv->tx_ant; + *rx_ant =3D priv->rx_ant; + + return 0; +} + +/* cfg80211 operation handler for stop ap. + * Function stops BSS running at uAP interface. + */ +static int nxpwifi_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device= *dev, + unsigned int link_id) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + nxpwifi_abort_cac(priv); + + if (nxpwifi_del_mgmt_ies(priv)) + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to delete mgmt IEs!\n"); + + priv->ap_11n_enabled =3D 0; + memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg)); + + if (nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_STOP, + HOST_ACT_GEN_SET, 0, NULL, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to stop the BSS\n"); + return -1; + } + + if (nxpwifi_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, + HOST_ACT_GEN_SET, 0, NULL, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to reset BSS\n"); + return -1; + } + + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + nxpwifi_stop_net_dev_queue(priv->netdev, priv->adapter); + + return 0; +} + +/* cfg80211 operation handler for start_ap. + * Function sets beacon period, DTIM period, SSID and security into + * AP config structure. + * AP is configured with these settings and BSS is started. + */ +static int nxpwifi_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *params) +{ + struct nxpwifi_uap_bss_param *bss_cfg; + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_private *tmp_priv; + int i; + struct nxpwifi_current_bss_params *bss_params; + enum nl80211_band band; + int freq; + + if (GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_UAP) + return -1; + + for (i =3D 0; i < NXPWIFI_MAX_BSS_NUM; i++) { + tmp_priv =3D adapter->priv[i]; + if (tmp_priv =3D=3D priv) + continue; + if (GET_BSS_ROLE(tmp_priv) =3D=3D NXPWIFI_BSS_ROLE_STA && + tmp_priv->media_connected) { + bss_params =3D &tmp_priv->curr_bss_params; + band =3D nxpwifi_band_to_radio_type(bss_params->band); + freq =3D ieee80211_channel_to_frequency + (bss_params->bss_descriptor.channel, band); + if (!ieee80211_channel_equal + (params->chandef.chan, + ieee80211_get_channel(wiphy, freq))) { + nxpwifi_dbg + (priv->adapter, MSG, + "AP and STA must operate on same channel\n"); + return -EOPNOTSUPP; + } + } + } + + bss_cfg =3D kzalloc(sizeof(*bss_cfg), GFP_KERNEL); + if (!bss_cfg) + return -ENOMEM; + + nxpwifi_set_sys_config_invalid_data(bss_cfg); + + memcpy(bss_cfg->mac_addr, priv->curr_addr, ETH_ALEN); + + if (params->beacon_interval) + bss_cfg->beacon_period =3D params->beacon_interval; + if (params->dtim_period) + bss_cfg->dtim_period =3D params->dtim_period; + + if (params->ssid && params->ssid_len) { + memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); + bss_cfg->ssid.ssid_len =3D params->ssid_len; + } + if (params->inactivity_timeout > 0) { + /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ + bss_cfg->sta_ao_timer =3D 10 * params->inactivity_timeout; + bss_cfg->ps_sta_ao_timer =3D 10 * params->inactivity_timeout; + } + + switch (params->hidden_ssid) { + case NL80211_HIDDEN_SSID_NOT_IN_USE: + bss_cfg->bcast_ssid_ctl =3D 1; + break; + case NL80211_HIDDEN_SSID_ZERO_LEN: + bss_cfg->bcast_ssid_ctl =3D 0; + break; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + bss_cfg->bcast_ssid_ctl =3D 2; + break; + default: + kfree(bss_cfg); + return -EINVAL; + } + + nxpwifi_uap_set_channel(priv, bss_cfg, params->chandef); + nxpwifi_set_uap_rates(bss_cfg, params); + + if (nxpwifi_set_secure_params(priv, bss_cfg, params)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to parse security parameters!\n"); + goto out; + } + + nxpwifi_set_ht_params(priv, bss_cfg, params); + + if (priv->adapter->is_hw_11ac_capable) { + nxpwifi_set_vht_params(priv, bss_cfg, params); + nxpwifi_set_vht_width(priv, params->chandef.width, + priv->ap_11ac_enabled); + } + + if (priv->ap_11ac_enabled) + nxpwifi_set_11ac_ba_params(priv); + else + nxpwifi_set_ba_params(priv); + + nxpwifi_set_wmm_params(priv, bss_cfg, params); + + if (nxpwifi_is_11h_active(priv)) + nxpwifi_set_tpc_params(priv, bss_cfg, params); + + if (nxpwifi_is_11h_active(priv) && + !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, + priv->bss_mode)) { + nxpwifi_dbg(priv->adapter, INFO, + "Disable 11h extensions in FW\n"); + if (nxpwifi_11h_activate(priv, false)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to disable 11h extensions!!"); + goto out; + } + priv->state_11h.is_11h_active =3D false; + } + + nxpwifi_config_uap_11d(priv, ¶ms->beacon); + + if (nxpwifi_config_start_uap(priv, bss_cfg)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to start AP\n"); + goto out; + } + + if (nxpwifi_set_mgmt_ies(priv, ¶ms->beacon)) + goto out; + + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + nxpwifi_wake_up_net_dev_queue(priv->netdev, priv->adapter); + + memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); + kfree(bss_cfg); + return 0; + +out: + kfree(bss_cfg); + return -1; +} + +/* CFG802.11 operation handler for scan request. + * + * This function issues a scan request to the firmware based upon + * the user specified scan configuration. On successful completion, + * it also informs the results. + */ +static int +nxpwifi_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct net_device *dev =3D request->wdev->netdev; + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + int i, offset, ret; + struct ieee80211_channel *chan; + struct ieee_types_header *ie; + struct nxpwifi_user_scan_cfg *user_scan_cfg; + u8 mac_addr[ETH_ALEN]; + + nxpwifi_dbg(priv->adapter, CMD, + "info: received scan request on %s\n", dev->name); + + /* Block scan request if scan operation or scan cleanup when interface + * is disabled is in process + */ + if (priv->scan_request || priv->scan_aborting) { + nxpwifi_dbg(priv->adapter, WARN, + "cmd: Scan already in process..\n"); + return -EBUSY; + } + + if (!priv->wdev.connected && priv->scan_block) + priv->scan_block =3D false; + + if (!nxpwifi_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); + + user_scan_cfg =3D kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); + if (!user_scan_cfg) + return -ENOMEM; + + priv->scan_request =3D request; + + if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { + get_random_mask_addr(mac_addr, request->mac_addr, + request->mac_addr_mask); + ether_addr_copy(request->mac_addr, mac_addr); + ether_addr_copy(user_scan_cfg->random_mac, mac_addr); + } + + user_scan_cfg->num_ssids =3D request->n_ssids; + user_scan_cfg->ssid_list =3D request->ssids; + + if (request->ie && request->ie_len) { + offset =3D 0; + for (i =3D 0; i < NXPWIFI_MAX_VSIE_NUM; i++) { + if (priv->vs_ie[i].mask !=3D NXPWIFI_VSIE_MASK_CLEAR) + continue; + priv->vs_ie[i].mask =3D NXPWIFI_VSIE_MASK_SCAN; + ie =3D (struct ieee_types_header *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); + offset +=3D sizeof(*ie) + ie->len; + + if (offset >=3D request->ie_len) + break; + } + } + + for (i =3D 0; i < min_t(u32, request->n_channels, + NXPWIFI_USER_SCAN_CHAN_MAX); i++) { + chan =3D request->channels[i]; + user_scan_cfg->chan_list[i].chan_number =3D chan->hw_value; + user_scan_cfg->chan_list[i].radio_type =3D chan->band; + + if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids) + user_scan_cfg->chan_list[i].scan_type =3D + NXPWIFI_SCAN_TYPE_PASSIVE; + else + user_scan_cfg->chan_list[i].scan_type =3D + NXPWIFI_SCAN_TYPE_ACTIVE; + + user_scan_cfg->chan_list[i].scan_time =3D 0; + } + + if (priv->adapter->scan_chan_gap_enabled && + nxpwifi_is_any_intf_active(priv)) + user_scan_cfg->scan_chan_gap =3D + priv->adapter->scan_chan_gap_time; + + ret =3D nxpwifi_scan_networks(priv, user_scan_cfg); + kfree(user_scan_cfg); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "scan failed: %d\n", ret); + priv->scan_aborting =3D false; + priv->scan_request =3D NULL; + return ret; + } + + if (request->ie && request->ie_len) { + for (i =3D 0; i < NXPWIFI_MAX_VSIE_NUM; i++) { + if (priv->vs_ie[i].mask =3D=3D NXPWIFI_VSIE_MASK_SCAN) { + priv->vs_ie[i].mask =3D NXPWIFI_VSIE_MASK_CLEAR; + memset(&priv->vs_ie[i].ie, 0, + NXPWIFI_MAX_VSIE_LEN); + } + } + } + return 0; +} + +/* CFG802.11 operation handler for sched_scan_start. + * + * This function issues a bgscan config request to the firmware based upon + * the user specified sched_scan configuration. On successful completion, + * firmware will generate BGSCAN_REPORT event, driver should issue bgscan + * query command to get sched_scan results from firmware. + */ +static int +nxpwifi_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + int i, offset; + struct ieee80211_channel *chan; + struct nxpwifi_bg_scan_cfg *bgscan_cfg; + struct ieee_types_header *ie; + + if (!request || (!request->n_ssids && !request->n_match_sets)) { + wiphy_err(wiphy, "%s : Invalid Sched_scan parameters", + __func__); + return -EINVAL; + } + + wiphy_info(wiphy, "sched_scan start : n_ssids=3D%d n_match_sets=3D%d ", + request->n_ssids, request->n_match_sets); + wiphy_info(wiphy, "n_channels=3D%d interval=3D%d ie_len=3D%d\n", + request->n_channels, request->scan_plans->interval, + (int)request->ie_len); + + bgscan_cfg =3D kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL); + if (!bgscan_cfg) + return -ENOMEM; + + if (priv->scan_request || priv->scan_aborting) + bgscan_cfg->start_later =3D true; + + bgscan_cfg->num_ssids =3D request->n_match_sets; + bgscan_cfg->ssid_list =3D request->match_sets; + + if (request->ie && request->ie_len) { + offset =3D 0; + for (i =3D 0; i < NXPWIFI_MAX_VSIE_NUM; i++) { + if (priv->vs_ie[i].mask !=3D NXPWIFI_VSIE_MASK_CLEAR) + continue; + priv->vs_ie[i].mask =3D NXPWIFI_VSIE_MASK_BGSCAN; + ie =3D (struct ieee_types_header *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); + offset +=3D sizeof(*ie) + ie->len; + + if (offset >=3D request->ie_len) + break; + } + } + + for (i =3D 0; i < min_t(u32, request->n_channels, + NXPWIFI_BG_SCAN_CHAN_MAX); i++) { + chan =3D request->channels[i]; + bgscan_cfg->chan_list[i].chan_number =3D chan->hw_value; + bgscan_cfg->chan_list[i].radio_type =3D chan->band; + + if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids) + bgscan_cfg->chan_list[i].scan_type =3D + NXPWIFI_SCAN_TYPE_PASSIVE; + else + bgscan_cfg->chan_list[i].scan_type =3D + NXPWIFI_SCAN_TYPE_ACTIVE; + + bgscan_cfg->chan_list[i].scan_time =3D 0; + } + + bgscan_cfg->chan_per_scan =3D min_t(u32, request->n_channels, + NXPWIFI_BG_SCAN_CHAN_MAX); + + /* Use at least 15 second for per scan cycle */ + bgscan_cfg->scan_interval =3D (request->scan_plans->interval > + NXPWIFI_BGSCAN_INTERVAL) ? + request->scan_plans->interval : + NXPWIFI_BGSCAN_INTERVAL; + + bgscan_cfg->repeat_count =3D NXPWIFI_BGSCAN_REPEAT_COUNT; + bgscan_cfg->report_condition =3D NXPWIFI_BGSCAN_SSID_MATCH | + NXPWIFI_BGSCAN_WAIT_ALL_CHAN_DONE; + bgscan_cfg->bss_type =3D NXPWIFI_BSS_MODE_INFRA; + bgscan_cfg->action =3D NXPWIFI_BGSCAN_ACT_SET; + bgscan_cfg->enable =3D true; + if (request->min_rssi_thold !=3D NL80211_SCAN_RSSI_THOLD_OFF) { + bgscan_cfg->report_condition |=3D NXPWIFI_BGSCAN_SSID_RSSI_MATCH; + bgscan_cfg->rssi_threshold =3D request->min_rssi_thold; + } + + if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_CONFIG, + HOST_ACT_GEN_SET, 0, bgscan_cfg, true)) { + kfree(bgscan_cfg); + return -EFAULT; + } + + priv->sched_scanning =3D true; + + kfree(bgscan_cfg); + return 0; +} + +/* CFG802.11 operation handler for sched_scan_stop. + * + * This function issues a bgscan config command to disable + * previous bgscan configuration in the firmware + */ +static int nxpwifi_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev, u64 reqid) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + wiphy_info(wiphy, "sched scan stop!"); + nxpwifi_stop_bg_scan(priv); + + return 0; +} + +static void nxpwifi_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, + struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + vht_info->vht_supported =3D true; + + vht_info->cap =3D adapter->hw_dot_11ac_dev_cap; + /* Update MCS support for VHT */ + vht_info->vht_mcs.rx_mcs_map =3D + cpu_to_le16(adapter->hw_dot_11ac_mcs_support & 0xFFFF); + vht_info->vht_mcs.rx_highest =3D 0; + vht_info->vht_mcs.tx_mcs_map =3D + cpu_to_le16(adapter->hw_dot_11ac_mcs_support >> 16); + vht_info->vht_mcs.tx_highest =3D 0; +} + +/* This function sets up the CFG802.11 specific HT capability fields + * with default values. + * + * The following default values are set - + * - HT Supported =3D True + * - Maximum AMPDU length factor =3D IEEE80211_HT_MAX_AMPDU_64K + * - Minimum AMPDU spacing =3D IEEE80211_HT_MPDU_DENSITY_NONE + * - HT Capabilities supported by firmware + * - MCS information, Rx mask =3D 0xff + * - MCD information, Tx parameters =3D IEEE80211_HT_MCS_TX_DEFINED (= 0x01) + */ +static void +nxpwifi_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, + struct nxpwifi_private *priv) +{ + int rx_mcs_supp; + struct ieee80211_mcs_info mcs_set; + u8 *mcs =3D (u8 *)&mcs_set; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + ht_info->ht_supported =3D true; + ht_info->ampdu_factor =3D IEEE80211_HT_MAX_AMPDU_64K; + ht_info->ampdu_density =3D IEEE80211_HT_MPDU_DENSITY_NONE; + + memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); + + /* Fill HT capability information */ + if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_SUP_WIDTH_20_40; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_SGI_20; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_SGI_20; + + if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_SGI_40; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_SGI_40; + + if (adapter->user_dev_mcs_support =3D=3D HT_STREAM_2X2) + ht_info->cap |=3D 2 << IEEE80211_HT_CAP_RX_STBC_SHIFT; + else + ht_info->cap |=3D 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; + + if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_TX_STBC; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_TX_STBC; + + if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_GRN_FLD; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_GRN_FLD; + + if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_40MHZ_INTOLERANT; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_40MHZ_INTOLERANT; + + if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |=3D IEEE80211_HT_CAP_LDPC_CODING; + else + ht_info->cap &=3D ~IEEE80211_HT_CAP_LDPC_CODING; + + ht_info->cap &=3D ~IEEE80211_HT_CAP_MAX_AMSDU; + ht_info->cap |=3D IEEE80211_HT_CAP_SM_PS; + + rx_mcs_supp =3D GET_RXMCSSUPP(adapter->user_dev_mcs_support); + /* Set MCS for 1x1/2x2 */ + memset(mcs, 0xff, rx_mcs_supp); + /* Clear all the other values */ + memset(&mcs[rx_mcs_supp], 0, + sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION || + ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) + /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ + SETHT_MCS32(mcs_set.rx_mask); + + memcpy((u8 *)&ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info)); + + ht_info->mcs.tx_params =3D IEEE80211_HT_MCS_TX_DEFINED; +} + +/* create a new virtual interface with the given name and name assign type + */ +struct wireless_dev *nxpwifi_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv; + struct net_device *dev; + void *mdev_priv; + int ret; + + if (!adapter) + return ERR_PTR(-EFAULT); + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_STATION: + if (adapter->curr_iface_comb.sta_intf =3D=3D + adapter->iface_limit.sta_intf) { + nxpwifi_dbg(adapter, ERROR, + "cannot create multiple sta ifaces\n"); + return ERR_PTR(-EINVAL); + } + + priv =3D nxpwifi_get_unused_priv_by_bss_type + (adapter, NXPWIFI_BSS_TYPE_STA); + if (!priv) { + nxpwifi_dbg(adapter, ERROR, + "could not get free private struct\n"); + return ERR_PTR(-EFAULT); + } + + priv->wdev.wiphy =3D wiphy; + priv->wdev.iftype =3D NL80211_IFTYPE_STATION; + + if (type =3D=3D NL80211_IFTYPE_UNSPECIFIED) + priv->bss_mode =3D NL80211_IFTYPE_STATION; + else + priv->bss_mode =3D type; + + priv->bss_type =3D NXPWIFI_BSS_TYPE_STA; + priv->frame_type =3D NXPWIFI_DATA_FRAME_TYPE_ETH_II; + priv->bss_priority =3D 0; + priv->bss_role =3D NXPWIFI_BSS_ROLE_STA; + + break; + case NL80211_IFTYPE_AP: + if (adapter->curr_iface_comb.uap_intf =3D=3D + adapter->iface_limit.uap_intf) { + nxpwifi_dbg(adapter, ERROR, + "cannot create multiple AP ifaces\n"); + return ERR_PTR(-EINVAL); + } + + priv =3D nxpwifi_get_unused_priv_by_bss_type + (adapter, NXPWIFI_BSS_TYPE_UAP); + if (!priv) { + nxpwifi_dbg(adapter, ERROR, + "could not get free private struct\n"); + return ERR_PTR(-EFAULT); + } + + priv->wdev.wiphy =3D wiphy; + priv->wdev.iftype =3D NL80211_IFTYPE_AP; + + priv->bss_type =3D NXPWIFI_BSS_TYPE_UAP; + priv->frame_type =3D NXPWIFI_DATA_FRAME_TYPE_ETH_II; + priv->bss_priority =3D 0; + priv->bss_role =3D NXPWIFI_BSS_ROLE_UAP; + priv->bss_started =3D 0; + priv->bss_mode =3D type; + + break; + default: + nxpwifi_dbg(adapter, ERROR, "type not supported\n"); + return ERR_PTR(-EINVAL); + } + + dev =3D alloc_netdev_mqs(sizeof(struct nxpwifi_private *), name, + name_assign_type, ether_setup, + IEEE80211_NUM_ACS, 1); + if (!dev) { + nxpwifi_dbg(adapter, ERROR, + "no memory available for netdevice\n"); + ret =3D -ENOMEM; + goto err_alloc_netdev; + } + + nxpwifi_init_priv_params(priv, dev); + + priv->netdev =3D dev; + + nxpwifi_set_mac_address(priv, dev, false, NULL); + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_SET_BSS_MODE, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) + goto err_set_bss_mode; + + ret =3D nxpwifi_sta_init_cmd(priv, false, false); + if (ret) + goto err_sta_init; + + nxpwifi_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv); + if (adapter->is_hw_11ac_capable) + nxpwifi_setup_vht_caps + (&wiphy->bands[NL80211_BAND_2GHZ]->vht_cap, priv); + + if (adapter->config_bands & BAND_A) + nxpwifi_setup_ht_caps + (&wiphy->bands[NL80211_BAND_5GHZ]->ht_cap, priv); + + if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable) + nxpwifi_setup_vht_caps + (&wiphy->bands[NL80211_BAND_5GHZ]->vht_cap, priv); + + dev_net_set(dev, wiphy_net(wiphy)); + dev->ieee80211_ptr =3D &priv->wdev; + dev->ieee80211_ptr->iftype =3D priv->bss_mode; + SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); + + dev->flags |=3D IFF_BROADCAST | IFF_MULTICAST; + dev->watchdog_timeo =3D NXPWIFI_DEFAULT_WATCHDOG_TIMEOUT; + dev->needed_headroom =3D NXPWIFI_MIN_DATA_HEADER_LEN; + dev->ethtool_ops =3D &nxpwifi_ethtool_ops; + + mdev_priv =3D netdev_priv(dev); + *((unsigned long *)mdev_priv) =3D (unsigned long)priv; + + SET_NETDEV_DEV(dev, adapter->dev); + + priv->dfs_cac_workqueue =3D alloc_workqueue("NXPWIFI_DFS_CAC%s", + WQ_HIGHPRI | + WQ_MEM_RECLAIM | + WQ_UNBOUND, 0, name); + if (!priv->dfs_cac_workqueue) { + nxpwifi_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n"); + ret =3D -ENOMEM; + goto err_alloc_cac; + } + + INIT_DELAYED_WORK(&priv->dfs_cac_work, nxpwifi_dfs_cac_work_queue); + + priv->dfs_chan_sw_workqueue =3D alloc_workqueue("NXPWIFI_DFS_CHSW%s", + WQ_HIGHPRI | WQ_UNBOUND | + WQ_MEM_RECLAIM, 0, name); + if (!priv->dfs_chan_sw_workqueue) { + nxpwifi_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n"); + ret =3D -ENOMEM; + goto err_alloc_chsw; + } + + INIT_DELAYED_WORK(&priv->dfs_chan_sw_work, + nxpwifi_dfs_chan_sw_work_queue); + + mutex_init(&priv->async_mutex); + + /* Register network device */ + if (cfg80211_register_netdevice(dev)) { + nxpwifi_dbg(adapter, ERROR, "cannot register network device\n"); + ret =3D -EFAULT; + goto err_reg_netdev; + } + + nxpwifi_dbg(adapter, INFO, + "info: %s: NXP 802.11 Adapter\n", dev->name); + +#ifdef CONFIG_DEBUG_FS + nxpwifi_dev_debugfs_init(priv); +#endif + + update_vif_type_counter(adapter, type, 1); + + return &priv->wdev; + +err_reg_netdev: + destroy_workqueue(priv->dfs_chan_sw_workqueue); + priv->dfs_chan_sw_workqueue =3D NULL; +err_alloc_chsw: + destroy_workqueue(priv->dfs_cac_workqueue); + priv->dfs_cac_workqueue =3D NULL; +err_alloc_cac: + free_netdev(dev); + priv->netdev =3D NULL; +err_sta_init: +err_set_bss_mode: +err_alloc_netdev: + memset(&priv->wdev, 0, sizeof(priv->wdev)); + priv->wdev.iftype =3D NL80211_IFTYPE_UNSPECIFIED; + priv->bss_mode =3D NL80211_IFTYPE_UNSPECIFIED; + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(nxpwifi_add_virtual_intf); + +/* del_virtual_intf: remove the virtual interface determined by dev + */ +int nxpwifi_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wde= v) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct sk_buff *skb, *tmp; + +#ifdef CONFIG_DEBUG_FS + nxpwifi_dev_debugfs_remove(priv); +#endif + + if (priv->sched_scanning) + priv->sched_scanning =3D false; + + nxpwifi_stop_net_dev_queue(priv->netdev, adapter); + + skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) { + skb_unlink(skb, &priv->bypass_txq); + nxpwifi_write_data_complete(priv->adapter, skb, 0, -1); + } + + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + + if (wdev->netdev->reg_state =3D=3D NETREG_REGISTERED) + cfg80211_unregister_netdevice(wdev->netdev); + + if (priv->dfs_cac_workqueue) { + destroy_workqueue(priv->dfs_cac_workqueue); + priv->dfs_cac_workqueue =3D NULL; + } + + if (priv->dfs_chan_sw_workqueue) { + destroy_workqueue(priv->dfs_chan_sw_workqueue); + priv->dfs_chan_sw_workqueue =3D NULL; + } + /* Clear the priv in adapter */ + priv->netdev =3D NULL; + + update_vif_type_counter(adapter, priv->bss_mode, -1); + + priv->bss_mode =3D NL80211_IFTYPE_UNSPECIFIED; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA || + GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) + kfree(priv->hist_data); + + return 0; +} +EXPORT_SYMBOL_GPL(nxpwifi_del_virtual_intf); + +static bool +nxpwifi_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_se= q, + u8 max_byte_seq) +{ + int j, k, valid_byte_cnt =3D 0; + bool dont_care_byte =3D false; + + for (j =3D 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { + for (k =3D 0; k < 8; k++) { + if (pat->mask[j] & 1 << k) { + memcpy(byte_seq + valid_byte_cnt, + &pat->pattern[j * 8 + k], 1); + valid_byte_cnt++; + if (dont_care_byte) + return false; + } else { + if (valid_byte_cnt) + dont_care_byte =3D true; + } + + /* wildcard bytes record as the offset + * before the valid byte + */ + if (!valid_byte_cnt && !dont_care_byte) + pat->pkt_offset++; + + if (valid_byte_cnt > max_byte_seq) + return false; + } + } + + byte_seq[max_byte_seq] =3D valid_byte_cnt; + + return true; +} + +#ifdef CONFIG_PM +static void nxpwifi_set_auto_arp_mef_entry(struct nxpwifi_private *priv, + struct nxpwifi_mef_entry *mef_entry) +{ + int i, filt_num =3D 0, num_ipv4 =3D 0; + struct in_device *in_dev; + struct in_ifaddr *ifa; + __be32 ips[NXPWIFI_MAX_SUPPORTED_IPADDR]; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + mef_entry->mode =3D MEF_MODE_HOST_SLEEP; + mef_entry->action =3D MEF_ACTION_AUTO_ARP; + + /* Enable ARP offload feature */ + memset(ips, 0, sizeof(ips)); + for (i =3D 0; i < NXPWIFI_MAX_BSS_NUM; i++) { + if (adapter->priv[i]->netdev) { + in_dev =3D __in_dev_get_rtnl(adapter->priv[i]->netdev); + if (!in_dev) + continue; + ifa =3D rtnl_dereference(in_dev->ifa_list); + if (!ifa || !ifa->ifa_local) + continue; + ips[i] =3D ifa->ifa_local; + num_ipv4++; + } + } + + for (i =3D 0; i < num_ipv4; i++) { + if (!ips[i]) + continue; + mef_entry->filter[filt_num].repeat =3D 1; + memcpy(mef_entry->filter[filt_num].byte_seq, + (u8 *)&ips[i], sizeof(ips[i])); + mef_entry->filter[filt_num].byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D + sizeof(ips[i]); + mef_entry->filter[filt_num].offset =3D 46; + mef_entry->filter[filt_num].filt_type =3D TYPE_EQ; + if (filt_num) { + mef_entry->filter[filt_num].filt_action =3D + TYPE_OR; + } + filt_num++; + } + + mef_entry->filter[filt_num].repeat =3D 1; + mef_entry->filter[filt_num].byte_seq[0] =3D 0x08; + mef_entry->filter[filt_num].byte_seq[1] =3D 0x06; + mef_entry->filter[filt_num].byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D 2; + mef_entry->filter[filt_num].offset =3D 20; + mef_entry->filter[filt_num].filt_type =3D TYPE_EQ; + mef_entry->filter[filt_num].filt_action =3D TYPE_AND; +} + +static int nxpwifi_set_wowlan_mef_entry(struct nxpwifi_private *priv, + struct nxpwifi_ds_mef_cfg *mef_cfg, + struct nxpwifi_mef_entry *mef_entry, + struct cfg80211_wowlan *wowlan) +{ + int i, filt_num =3D 0, ret =3D 0; + bool first_pat =3D true; + u8 byte_seq[NXPWIFI_MEF_MAX_BYTESEQ + 1]; + static const u8 ipv4_mc_mac[] =3D {0x33, 0x33}; + static const u8 ipv6_mc_mac[] =3D {0x01, 0x00, 0x5e}; + + mef_entry->mode =3D MEF_MODE_HOST_SLEEP; + mef_entry->action =3D MEF_ACTION_ALLOW_AND_WAKEUP_HOST; + + for (i =3D 0; i < wowlan->n_patterns; i++) { + memset(byte_seq, 0, sizeof(byte_seq)); + if (!nxpwifi_is_pattern_supported + (&wowlan->patterns[i], byte_seq, + NXPWIFI_MEF_MAX_BYTESEQ)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Pattern not supported\n"); + return -EOPNOTSUPP; + } + + if (!wowlan->patterns[i].pkt_offset) { + if (is_unicast_ether_addr(byte_seq) && + byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D=3D 1) { + mef_cfg->criteria |=3D NXPWIFI_CRITERIA_UNICAST; + continue; + } else if (is_broadcast_ether_addr(byte_seq)) { + mef_cfg->criteria |=3D NXPWIFI_CRITERIA_BROADCAST; + continue; + } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && + (byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D=3D 2)) || + (!memcmp(byte_seq, ipv6_mc_mac, 3) && + (byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D=3D 3))) { + mef_cfg->criteria |=3D NXPWIFI_CRITERIA_MULTICAST; + continue; + } + } + mef_entry->filter[filt_num].repeat =3D 1; + mef_entry->filter[filt_num].offset =3D + wowlan->patterns[i].pkt_offset; + memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, + sizeof(byte_seq)); + mef_entry->filter[filt_num].filt_type =3D TYPE_EQ; + + if (first_pat) { + first_pat =3D false; + nxpwifi_dbg(priv->adapter, INFO, "Wake on patterns\n"); + } else { + mef_entry->filter[filt_num].filt_action =3D TYPE_AND; + } + + filt_num++; + } + + if (wowlan->magic_pkt) { + mef_cfg->criteria |=3D NXPWIFI_CRITERIA_UNICAST; + mef_entry->filter[filt_num].repeat =3D 16; + memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, + ETH_ALEN); + mef_entry->filter[filt_num].byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D + ETH_ALEN; + mef_entry->filter[filt_num].offset =3D 28; + mef_entry->filter[filt_num].filt_type =3D TYPE_EQ; + if (filt_num) + mef_entry->filter[filt_num].filt_action =3D TYPE_OR; + + filt_num++; + mef_entry->filter[filt_num].repeat =3D 16; + memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, + ETH_ALEN); + mef_entry->filter[filt_num].byte_seq[NXPWIFI_MEF_MAX_BYTESEQ] =3D + ETH_ALEN; + mef_entry->filter[filt_num].offset =3D 56; + mef_entry->filter[filt_num].filt_type =3D TYPE_EQ; + mef_entry->filter[filt_num].filt_action =3D TYPE_OR; + nxpwifi_dbg(priv->adapter, INFO, "Wake on magic packet\n"); + } + return ret; +} + +static int nxpwifi_set_mef_filter(struct nxpwifi_private *priv, + struct cfg80211_wowlan *wowlan) +{ + int ret =3D 0, num_entries =3D 1; + struct nxpwifi_ds_mef_cfg mef_cfg; + struct nxpwifi_mef_entry *mef_entry; + + if (wowlan->n_patterns || wowlan->magic_pkt) + num_entries++; + + mef_entry =3D kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL); + if (!mef_entry) + return -ENOMEM; + + memset(&mef_cfg, 0, sizeof(mef_cfg)); + mef_cfg.criteria |=3D NXPWIFI_CRITERIA_BROADCAST | + NXPWIFI_CRITERIA_UNICAST; + mef_cfg.num_entries =3D num_entries; + mef_cfg.mef_entry =3D mef_entry; + + nxpwifi_set_auto_arp_mef_entry(priv, &mef_entry[0]); + + if (wowlan->n_patterns || wowlan->magic_pkt) { + ret =3D nxpwifi_set_wowlan_mef_entry(priv, &mef_cfg, + &mef_entry[1], wowlan); + if (ret) + goto err; + } + + if (!mef_cfg.criteria) + mef_cfg.criteria =3D NXPWIFI_CRITERIA_BROADCAST | + NXPWIFI_CRITERIA_UNICAST | + NXPWIFI_CRITERIA_MULTICAST; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MEF_CFG, HOST_ACT_GEN_SET, 0, + &mef_cfg, true); + +err: + kfree(mef_entry); + return ret; +} + +static int nxpwifi_cfg80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wowlan) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_ds_hs_cfg hs_cfg; + int i, ret =3D 0, retry_num =3D 10; + struct nxpwifi_private *priv; + struct nxpwifi_private *sta_priv =3D + nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA); + + sta_priv->scan_aborting =3D true; + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + nxpwifi_abort_cac(priv); + } + + nxpwifi_cancel_all_pending_cmd(adapter); + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv && priv->netdev) + netif_device_detach(priv->netdev); + } + + for (i =3D 0; i < retry_num; i++) { + if (!nxpwifi_wmm_lists_empty(adapter) || + !nxpwifi_bypass_txlist_empty(adapter) || + !skb_queue_empty(&adapter->tx_data_q)) + usleep_range(10000, 15000); + else + break; + } + + if (!wowlan) { + nxpwifi_dbg(adapter, INFO, + "None of the WOWLAN triggers enabled\n"); + ret =3D 0; + goto done; + } + + if (!sta_priv->media_connected && !wowlan->nd_config) { + nxpwifi_dbg(adapter, ERROR, + "Can not configure WOWLAN in disconnected state\n"); + ret =3D 0; + goto done; + } + + ret =3D nxpwifi_set_mef_filter(sta_priv, wowlan); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "Failed to set MEF filter\n"); + goto done; + } + + memset(&hs_cfg, 0, sizeof(hs_cfg)); + hs_cfg.conditions =3D le32_to_cpu(adapter->hs_cfg.conditions); + + if (wowlan->nd_config) { + nxpwifi_dbg(adapter, INFO, "Wake on net detect\n"); + hs_cfg.conditions |=3D HS_CFG_COND_MAC_EVENT; + nxpwifi_cfg80211_sched_scan_start(wiphy, sta_priv->netdev, + wowlan->nd_config); + } + + if (wowlan->disconnect) { + hs_cfg.conditions |=3D HS_CFG_COND_MAC_EVENT; + nxpwifi_dbg(sta_priv->adapter, INFO, "Wake on device disconnect\n"); + } + + hs_cfg.is_invoke_hostcmd =3D false; + hs_cfg.gpio =3D adapter->hs_cfg.gpio; + hs_cfg.gap =3D adapter->hs_cfg.gap; + ret =3D nxpwifi_set_hs_params(sta_priv, HOST_ACT_GEN_SET, + NXPWIFI_SYNC_CMD, &hs_cfg); + if (ret) + nxpwifi_dbg(adapter, ERROR, "Failed to set HS params\n"); + +done: + sta_priv->scan_aborting =3D false; + return ret; +} + +static int nxpwifi_cfg80211_resume(struct wiphy *wiphy) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + struct nxpwifi_private *priv; + struct nxpwifi_ds_wakeup_reason wakeup_reason; + struct cfg80211_wowlan_wakeup wakeup_report; + int i; + bool report_wakeup_reason =3D true; + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv && priv->netdev) + netif_device_attach(priv->netdev); + } + + if (!wiphy->wowlan_config) + goto done; + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA); + nxpwifi_get_wakeup_reason(priv, HOST_ACT_GEN_GET, NXPWIFI_SYNC_CMD, + &wakeup_reason); + memset(&wakeup_report, 0, sizeof(struct cfg80211_wowlan_wakeup)); + + wakeup_report.pattern_idx =3D -1; + + switch (wakeup_reason.hs_wakeup_reason) { + case NO_HSWAKEUP_REASON: + break; + case BCAST_DATA_MATCHED: + break; + case MCAST_DATA_MATCHED: + break; + case UCAST_DATA_MATCHED: + break; + case MASKTABLE_EVENT_MATCHED: + break; + case NON_MASKABLE_EVENT_MATCHED: + if (wiphy->wowlan_config->disconnect) + wakeup_report.disconnect =3D true; + if (wiphy->wowlan_config->nd_config) + wakeup_report.net_detect =3D adapter->nd_info; + break; + case NON_MASKABLE_CONDITION_MATCHED: + break; + case MAGIC_PATTERN_MATCHED: + if (wiphy->wowlan_config->magic_pkt) + wakeup_report.magic_pkt =3D true; + if (wiphy->wowlan_config->n_patterns) + wakeup_report.pattern_idx =3D 1; + break; + case GTK_REKEY_FAILURE: + if (wiphy->wowlan_config->gtk_rekey_failure) + wakeup_report.gtk_rekey_failure =3D true; + break; + default: + report_wakeup_reason =3D false; + break; + } + + if (report_wakeup_reason) + cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, + GFP_KERNEL); + +done: + if (adapter->nd_info) { + for (i =3D 0 ; i < adapter->nd_info->n_matches ; i++) + kfree(adapter->nd_info->matches[i]); + kfree(adapter->nd_info); + adapter->nd_info =3D NULL; + } + + return 0; +} + +static void nxpwifi_cfg80211_set_wakeup(struct wiphy *wiphy, + bool enabled) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + + device_set_wakeup_enable(adapter->dev, enabled); +} +#endif + +static int nxpwifi_get_coalesce_pkt_type(u8 *byte_seq) +{ + static const u8 ipv4_mc_mac[] =3D {0x33, 0x33}; + static const u8 ipv6_mc_mac[] =3D {0x01, 0x00, 0x5e}; + static const u8 bc_mac[] =3D {0xff, 0xff, 0xff, 0xff}; + + if ((byte_seq[0] & 0x01) && + byte_seq[NXPWIFI_COALESCE_MAX_BYTESEQ] =3D=3D 1) + return PACKET_TYPE_UNICAST; + else if (!memcmp(byte_seq, bc_mac, 4)) + return PACKET_TYPE_BROADCAST; + else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && + byte_seq[NXPWIFI_COALESCE_MAX_BYTESEQ] =3D=3D 2) || + (!memcmp(byte_seq, ipv6_mc_mac, 3) && + byte_seq[NXPWIFI_COALESCE_MAX_BYTESEQ] =3D=3D 3)) + return PACKET_TYPE_MULTICAST; + + return 0; +} + +static int +nxpwifi_fill_coalesce_rule_info(struct nxpwifi_private *priv, + struct cfg80211_coalesce_rules *crule, + struct nxpwifi_coalesce_rule *mrule) +{ + u8 byte_seq[NXPWIFI_COALESCE_MAX_BYTESEQ + 1]; + struct filt_field_param *param; + int i; + + mrule->max_coalescing_delay =3D crule->delay; + + param =3D mrule->params; + + for (i =3D 0; i < crule->n_patterns; i++) { + memset(byte_seq, 0, sizeof(byte_seq)); + if (!nxpwifi_is_pattern_supported(&crule->patterns[i], + byte_seq, + NXPWIFI_COALESCE_MAX_BYTESEQ)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Pattern not supported\n"); + return -EOPNOTSUPP; + } + + if (!crule->patterns[i].pkt_offset) { + u8 pkt_type; + + pkt_type =3D nxpwifi_get_coalesce_pkt_type(byte_seq); + if (pkt_type && mrule->pkt_type) { + nxpwifi_dbg(priv->adapter, ERROR, + "Multiple packet types not allowed\n"); + return -EOPNOTSUPP; + } else if (pkt_type) { + mrule->pkt_type =3D pkt_type; + continue; + } + } + + if (crule->condition =3D=3D NL80211_COALESCE_CONDITION_MATCH) + param->operation =3D RECV_FILTER_MATCH_TYPE_EQ; + else + param->operation =3D RECV_FILTER_MATCH_TYPE_NE; + + param->operand_len =3D byte_seq[NXPWIFI_COALESCE_MAX_BYTESEQ]; + memcpy(param->operand_byte_stream, byte_seq, + param->operand_len); + param->offset =3D crule->patterns[i].pkt_offset; + param++; + + mrule->num_of_fields++; + } + + if (!mrule->pkt_type) { + nxpwifi_dbg(priv->adapter, ERROR, + "Packet type can not be determined\n"); + return -EOPNOTSUPP; + } + + return 0; +} + +static int nxpwifi_cfg80211_set_coalesce(struct wiphy *wiphy, + struct cfg80211_coalesce *coalesce) +{ + struct nxpwifi_adapter *adapter =3D nxpwifi_cfg80211_get_adapter(wiphy); + int i, ret; + struct nxpwifi_ds_coalesce_cfg coalesce_cfg; + struct nxpwifi_private *priv =3D + nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA); + + memset(&coalesce_cfg, 0, sizeof(coalesce_cfg)); + if (!coalesce) { + nxpwifi_dbg(adapter, WARN, + "Disable coalesce and reset all previous rules\n"); + return nxpwifi_send_cmd(priv, HOST_CMD_COALESCE_CFG, + HOST_ACT_GEN_SET, 0, + &coalesce_cfg, true); + } + + coalesce_cfg.num_of_rules =3D coalesce->n_rules; + for (i =3D 0; i < coalesce->n_rules; i++) { + ret =3D nxpwifi_fill_coalesce_rule_info(priv, &coalesce->rules[i], + &coalesce_cfg.rule[i]); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "Recheck the patterns provided for rule %d\n", + i + 1); + return ret; + } + } + + return nxpwifi_send_cmd(priv, HOST_CMD_COALESCE_CFG, + HOST_ACT_GEN_SET, 0, &coalesce_cfg, true); +} + +static int +nxpwifi_cfg80211_uap_add_station(struct nxpwifi_private *priv, const u8 *m= ac, + struct station_parameters *params) +{ + struct nxpwifi_sta_info add_sta; + int ret; + + memcpy(add_sta.peer_mac, mac, ETH_ALEN); + add_sta.params =3D params; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_ADD_NEW_STATION, + HOST_ACT_ADD_STA, 0, (void *)&add_sta, true); + + if (!ret) { + struct station_info *sinfo =3D NULL; + + sinfo =3D kzalloc(sizeof(*sinfo), GFP_KERNEL); + + if (sinfo) { + cfg80211_new_sta(priv->netdev, mac, sinfo, GFP_KERNEL); + kfree(sinfo); + } + } + + return ret; +} + +static int +nxpwifi_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac, struct station_parameters *params) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + int ret =3D -EOPNOTSUPP; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) + ret =3D nxpwifi_cfg80211_uap_add_station(priv, mac, params); + + return ret; +} + +static int +nxpwifi_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *de= v, + struct cfg80211_csa_settings *params) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + int chsw_msec; + + if (priv->adapter->scan_processing) { + nxpwifi_dbg(priv->adapter, ERROR, + "radar detection: scan in process...\n"); + return -EBUSY; + } + + if (priv->wdev.cac_started) + return -EBUSY; + + if (cfg80211_chandef_identical(¶ms->chandef, + &priv->dfs_chandef)) + return -EINVAL; + + if (params->block_tx) { + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + nxpwifi_stop_net_dev_queue(priv->netdev, priv->adapter); + priv->uap_stop_tx =3D true; + } + + if (nxpwifi_del_mgmt_ies(priv)) + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to delete mgmt IEs!\n"); + + if (nxpwifi_set_mgmt_ies(priv, ¶ms->beacon_csa)) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: setting mgmt ies failed\n", __func__); + return -EFAULT; + } + + memcpy(&priv->dfs_chandef, ¶ms->chandef, sizeof(priv->dfs_chandef)); + memcpy(&priv->beacon_after, ¶ms->beacon_after, + sizeof(priv->beacon_after)); + + chsw_msec =3D max(params->count * priv->bss_cfg.beacon_period, 100); + queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work, + msecs_to_jiffies(chsw_msec)); + return 0; +} + +static int nxpwifi_cfg80211_get_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + unsigned int link_id, + struct cfg80211_chan_def *chandef) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + struct nxpwifi_bssdescriptor *curr_bss; + struct ieee80211_channel *chan; + enum nl80211_channel_type chan_type; + enum nl80211_band band; + int freq; + int ret =3D -ENODATA; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP && + cfg80211_chandef_valid(&priv->bss_chandef)) { + *chandef =3D priv->bss_chandef; + ret =3D 0; + } else if (priv->media_connected) { + curr_bss =3D &priv->curr_bss_params.bss_descriptor; + band =3D nxpwifi_band_to_radio_type(priv->curr_bss_params.band); + freq =3D ieee80211_channel_to_frequency(curr_bss->channel, band); + chan =3D ieee80211_get_channel(wiphy, freq); + + if (priv->ht_param_present) { + chan_type =3D nxpwifi_get_chan_type(priv); + cfg80211_chandef_create(chandef, chan, chan_type); + } else { + cfg80211_chandef_create(chandef, chan, + NL80211_CHAN_NO_HT); + } + ret =3D 0; + } + + return ret; +} + +#ifdef CONFIG_NL80211_TESTMODE + +enum nxpwifi_tm_attr { + __NXPWIFI_TM_ATTR_INVALID =3D 0, + NXPWIFI_TM_ATTR_CMD =3D 1, + NXPWIFI_TM_ATTR_DATA =3D 2, + + /* keep last */ + __NXPWIFI_TM_ATTR_AFTER_LAST, + NXPWIFI_TM_ATTR_MAX =3D __NXPWIFI_TM_ATTR_AFTER_LAST - 1, +}; + +static const struct nla_policy nxpwifi_tm_policy[NXPWIFI_TM_ATTR_MAX + 1] = =3D { + [NXPWIFI_TM_ATTR_CMD] =3D { .type =3D NLA_U32 }, + [NXPWIFI_TM_ATTR_DATA] =3D { .type =3D NLA_BINARY, + .len =3D NXPWIFI_SIZE_OF_CMD_BUFFER }, +}; + +enum nxpwifi_tm_command { + NXPWIFI_TM_CMD_HOSTCMD =3D 0, +}; + +static int nxpwifi_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, + void *data, int len) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(wdev->netdev); + struct nxpwifi_ds_misc_cmd *hostcmd; + struct nlattr *tb[NXPWIFI_TM_ATTR_MAX + 1]; + struct sk_buff *skb; + int err; + + if (!priv) + return -EINVAL; + + err =3D nla_parse_deprecated(tb, NXPWIFI_TM_ATTR_MAX, data, len, + nxpwifi_tm_policy, NULL); + if (err) + return err; + + if (!tb[NXPWIFI_TM_ATTR_CMD]) + return -EINVAL; + + switch (nla_get_u32(tb[NXPWIFI_TM_ATTR_CMD])) { + case NXPWIFI_TM_CMD_HOSTCMD: + if (!tb[NXPWIFI_TM_ATTR_DATA]) + return -EINVAL; + + hostcmd =3D kzalloc(sizeof(*hostcmd), GFP_KERNEL); + if (!hostcmd) + return -ENOMEM; + + hostcmd->len =3D nla_len(tb[NXPWIFI_TM_ATTR_DATA]); + memcpy(hostcmd->cmd, nla_data(tb[NXPWIFI_TM_ATTR_DATA]), + hostcmd->len); + + if (nxpwifi_send_cmd(priv, 0, 0, 0, hostcmd, true)) { + dev_err(priv->adapter->dev, "Failed to process hostcmd\n"); + kfree(hostcmd); + return -EFAULT; + } + + /* process hostcmd response*/ + skb =3D cfg80211_testmode_alloc_reply_skb(wiphy, hostcmd->len); + if (!skb) { + kfree(hostcmd); + return -ENOMEM; + } + err =3D nla_put(skb, NXPWIFI_TM_ATTR_DATA, + hostcmd->len, hostcmd->cmd); + if (err) { + kfree(hostcmd); + kfree_skb(skb); + return -EMSGSIZE; + } + + err =3D cfg80211_testmode_reply(skb); + kfree(hostcmd); + return err; + default: + return -EOPNOTSUPP; + } +} +#endif + +static int +nxpwifi_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + u32 cac_time_ms) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_radar_params radar_params; + + if (priv->adapter->scan_processing) { + nxpwifi_dbg(priv->adapter, ERROR, + "radar detection: scan already in process...\n"); + return -EBUSY; + } + + if (!nxpwifi_is_11h_active(priv)) { + nxpwifi_dbg(priv->adapter, INFO, + "Enable 11h extensions in FW\n"); + if (nxpwifi_11h_activate(priv, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to activate 11h extensions!!"); + return -1; + } + priv->state_11h.is_11h_active =3D true; + } + + memset(&radar_params, 0, sizeof(struct nxpwifi_radar_params)); + radar_params.chandef =3D chandef; + radar_params.cac_time_ms =3D cac_time_ms; + + memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef)); + + if (nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REPORT_REQUEST, + HOST_ACT_GEN_SET, 0, &radar_params, true)) + return -1; + + queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work, + msecs_to_jiffies(cac_time_ms)); + return 0; +} + +static int +nxpwifi_cfg80211_change_station(struct wiphy *wiphy, struct net_device *de= v, + const u8 *mac, + struct station_parameters *params) +{ + return 0; +} + +static int +nxpwifi_cfg80211_authenticate(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_auth_request *req) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_private *tmp_priv; + int i; + struct sk_buff *skb; + u16 pkt_len, auth_alg; + int ret; + struct nxpwifi_ieee80211_mgmt *mgmt; + struct nxpwifi_txinfo *tx_info; + u32 tx_control =3D 0, pkt_type =3D PKT_TYPE_MGMT; + u8 trans =3D 1, status_code =3D 0; + u8 *varptr; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + nxpwifi_dbg(priv->adapter, ERROR, "Interface role is AP\n"); + return -EFAULT; + } + + if (priv->wdev.iftype !=3D NL80211_IFTYPE_STATION) { + nxpwifi_dbg(priv->adapter, ERROR, + "Interface type is not correct (type %d)\n", + priv->wdev.iftype); + return -EINVAL; + } + + for (i =3D 0; i < NXPWIFI_MAX_BSS_NUM; i++) { + tmp_priv =3D adapter->priv[i]; + if (tmp_priv =3D=3D priv) + continue; + if (GET_BSS_ROLE(tmp_priv) =3D=3D NXPWIFI_BSS_ROLE_UAP && + netif_carrier_ok(tmp_priv->netdev) && + cfg80211_chandef_valid(&tmp_priv->bss_chandef)) { + if (!ieee80211_channel_equal + (req->bss->channel, tmp_priv->bss_chandef.chan)) { + nxpwifi_dbg + (priv->adapter, MSG, + "STA and AP must operate on same channel\n"); + return -EOPNOTSUPP; + } + } + } + + if (priv->auth_alg !=3D WLAN_AUTH_SAE && + (priv->auth_flag & HOST_MLME_AUTH_PENDING)) { + nxpwifi_dbg(priv->adapter, ERROR, "Pending auth on going\n"); + return -EBUSY; + } + + if (!priv->host_mlme_reg) { + priv->host_mlme_reg =3D true; + priv->mgmt_frame_mask |=3D HOST_MLME_MGMT_MASK; + nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, + HOST_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false); + } + + switch (req->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + auth_alg =3D WLAN_AUTH_OPEN; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + auth_alg =3D WLAN_AUTH_SHARED_KEY; + break; + case NL80211_AUTHTYPE_FT: + auth_alg =3D WLAN_AUTH_FT; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + auth_alg =3D WLAN_AUTH_LEAP; + break; + case NL80211_AUTHTYPE_SAE: + auth_alg =3D WLAN_AUTH_SAE; + break; + default: + nxpwifi_dbg(priv->adapter, ERROR, + "unsupported auth type=3D%d\n", req->auth_type); + return -EOPNOTSUPP; + } + + if (!priv->auth_flag) { + ret =3D nxpwifi_remain_on_chan_cfg(priv, HOST_ACT_GEN_SET, + req->bss->channel, + AUTH_TX_DEFAULT_WAIT_TIME); + + if (!ret) { + priv->roc_cfg.cookie =3D get_random_u32() | 1; + priv->roc_cfg.chan =3D *req->bss->channel; + } else { + return -EFAULT; + } + } + + priv->sec_info.authentication_mode =3D auth_alg; + + nxpwifi_cancel_scan(adapter); + + pkt_len =3D (u16)req->ie_len + req->auth_data_len + + NXPWIFI_MGMT_HEADER_LEN + NXPWIFI_AUTH_BODY_LEN; + if (req->auth_data_len >=3D 4) + pkt_len -=3D 4; + + skb =3D dev_alloc_skb(NXPWIFI_MIN_DATA_HEADER_LEN + + NXPWIFI_MGMT_FRAME_HEADER_SIZE + + pkt_len + sizeof(pkt_len)); + if (!skb) { + nxpwifi_dbg(priv->adapter, ERROR, + "allocate skb failed for management frame\n"); + return -ENOMEM; + } + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num =3D priv->bss_num; + tx_info->bss_type =3D priv->bss_type; + tx_info->pkt_len =3D pkt_len; + + skb_reserve(skb, NXPWIFI_MIN_DATA_HEADER_LEN + + NXPWIFI_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 =3D (struct nxpwifi_ieee80211_mgmt *)skb_put(skb, pkt_len); + memset(mgmt, 0, pkt_len); + mgmt->frame_control =3D + 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); + eth_broadcast_addr(mgmt->addr4); + + if (req->auth_data_len >=3D 4) { + if (req->auth_type =3D=3D NL80211_AUTHTYPE_SAE) { + __le16 *pos =3D (__le16 *)req->auth_data; + + trans =3D le16_to_cpu(pos[0]); + status_code =3D le16_to_cpu(pos[1]); + } + memcpy((u8 *)(&mgmt->auth.variable), req->auth_data + 4, + req->auth_data_len - 4); + varptr =3D (u8 *)&mgmt->auth.variable + + (req->auth_data_len - 4); + } + + mgmt->auth.auth_alg =3D cpu_to_le16(auth_alg); + mgmt->auth.auth_transaction =3D cpu_to_le16(trans); + mgmt->auth.status_code =3D cpu_to_le16(status_code); + + if (req->ie && req->ie_len) { + if (!varptr) + varptr =3D (u8 *)&mgmt->auth.variable; + memcpy((u8 *)varptr, req->ie, req->ie_len); + } + + priv->auth_flag =3D HOST_MLME_AUTH_PENDING; + priv->auth_alg =3D auth_alg; + + skb->priority =3D WMM_HIGHEST_PRIORITY; + __net_timestamp(skb); + + nxpwifi_dbg(priv->adapter, MSG, + "auth: send authentication to %pM\n", req->bss->bssid); + + nxpwifi_queue_tx_pkt(priv, skb); + + return 0; +} + +static int +nxpwifi_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_assoc_request *req) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + struct cfg80211_ssid req_ssid; + const u8 *ssid_ie; + + if (GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_STA) { + nxpwifi_dbg(adapter, ERROR, + "%s: reject infra assoc request in non-STA role\n", + dev->name); + return -EINVAL; + } + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags) || + test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "%s: Ignore association.\t" + "Card removed or FW in bad state\n", + dev->name); + return -EFAULT; + } + + if (priv->auth_alg =3D=3D WLAN_AUTH_SAE) + priv->auth_flag =3D HOST_MLME_AUTH_DONE; + + if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE)) + return -EBUSY; + + if (priv->roc_cfg.cookie) { + ret =3D nxpwifi_remain_on_chan_cfg(priv, HOST_ACT_GEN_REMOVE, + &priv->roc_cfg.chan, 0); + if (!ret) + memset(&priv->roc_cfg, 0, + sizeof(struct nxpwifi_roc_cfg)); + else + return -EFAULT; + } + + if (!nxpwifi_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 =3D ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); + + if (!ssid_ie) + goto ssid_err; + + req_ssid.ssid_len =3D ssid_ie[1]; + if (req_ssid.ssid_len > IEEE80211_MAX_SSID_LEN) { + nxpwifi_dbg(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) { + nxpwifi_dbg(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 =3D false; + priv->sec_info.wpa2_enabled =3D false; + priv->wep_key_curr_index =3D 0; + priv->sec_info.encryption_mode =3D 0; + priv->sec_info.is_authtype_auto =3D 0; + ret =3D nxpwifi_set_encode(priv, NULL, NULL, 0, 0, NULL, 1); + + if (req->crypto.n_ciphers_pairwise) + priv->sec_info.encryption_mode =3D + req->crypto.ciphers_pairwise[0]; + + if (req->crypto.cipher_group) + priv->sec_info.encryption_mode =3D req->crypto.cipher_group; + + if (req->ie) + ret =3D nxpwifi_set_gen_ie(priv, req->ie, req->ie_len); + + memcpy(priv->cfg_bssid, req->bss->bssid, ETH_ALEN); + + nxpwifi_dbg(adapter, MSG, + "assoc: send association to %pM\n", req->bss->bssid); + + cfg80211_ref_bss(adapter->wiphy, req->bss); + + ret =3D nxpwifi_bss_start(priv, req->bss, &req_ssid); + + if (ret) { + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + eth_zero_addr(priv->cfg_bssid); + } + + if (priv->assoc_rsp_size) { + priv->req_bss =3D req->bss; + adapter->assoc_resp_received =3D true; + queue_work(adapter->host_mlme_workqueue, + &adapter->host_mlme_work); + } + + cfg80211_put_bss(priv->adapter->wiphy, req->bss); + + return 0; + +ssid_err: + + rcu_read_unlock(); + return -EFAULT; +} + +static int +nxpwifi_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + if (!nxpwifi_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); + + if (nxpwifi_deauthenticate(priv, NULL)) + return -EFAULT; + + eth_zero_addr(priv->cfg_bssid); + priv->hs2_enabled =3D false; + + return 0; +} + +static int +nxpwifi_cfg80211_deauthenticate(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req) +{ + return nxpwifi_cfg80211_disconnect(wiphy, dev, req->reason_code); +} + +static int +nxpwifi_cfg80211_disassociate(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req) +{ + return nxpwifi_cfg80211_disconnect(wiphy, dev, req->reason_code); +} + +static int +nxpwifi_cfg80211_probe_client(struct wiphy *wiphy, + struct net_device *dev, const u8 *peer, + u64 *cookie) +{ + return -EOPNOTSUPP; +} + +/* station cfg80211 operations */ +static struct cfg80211_ops nxpwifi_cfg80211_ops =3D { + .add_virtual_intf =3D nxpwifi_add_virtual_intf, + .del_virtual_intf =3D nxpwifi_del_virtual_intf, + .change_virtual_intf =3D nxpwifi_cfg80211_change_virtual_intf, + .scan =3D nxpwifi_cfg80211_scan, + .auth =3D nxpwifi_cfg80211_authenticate, + .assoc =3D nxpwifi_cfg80211_associate, + .deauth =3D nxpwifi_cfg80211_deauthenticate, + .disassoc =3D nxpwifi_cfg80211_disassociate, + .probe_client =3D nxpwifi_cfg80211_probe_client, + .get_station =3D nxpwifi_cfg80211_get_station, + .dump_station =3D nxpwifi_cfg80211_dump_station, + .dump_survey =3D nxpwifi_cfg80211_dump_survey, + .set_wiphy_params =3D nxpwifi_cfg80211_set_wiphy_params, + .add_key =3D nxpwifi_cfg80211_add_key, + .del_key =3D nxpwifi_cfg80211_del_key, + .set_default_mgmt_key =3D nxpwifi_cfg80211_set_default_mgmt_key, + .mgmt_tx =3D nxpwifi_cfg80211_mgmt_tx, + .update_mgmt_frame_registrations =3D + nxpwifi_cfg80211_update_mgmt_frame_registrations, + .remain_on_channel =3D nxpwifi_cfg80211_remain_on_channel, + .cancel_remain_on_channel =3D nxpwifi_cfg80211_cancel_remain_on_channel, + .set_default_key =3D nxpwifi_cfg80211_set_default_key, + .set_power_mgmt =3D nxpwifi_cfg80211_set_power_mgmt, + .set_tx_power =3D nxpwifi_cfg80211_set_tx_power, + .get_tx_power =3D nxpwifi_cfg80211_get_tx_power, + .set_bitrate_mask =3D nxpwifi_cfg80211_set_bitrate_mask, + .start_ap =3D nxpwifi_cfg80211_start_ap, + .stop_ap =3D nxpwifi_cfg80211_stop_ap, + .change_beacon =3D nxpwifi_cfg80211_change_beacon, + .set_cqm_rssi_config =3D nxpwifi_cfg80211_set_cqm_rssi_config, + .set_antenna =3D nxpwifi_cfg80211_set_antenna, + .get_antenna =3D nxpwifi_cfg80211_get_antenna, + .del_station =3D nxpwifi_cfg80211_del_station, + .sched_scan_start =3D nxpwifi_cfg80211_sched_scan_start, + .sched_scan_stop =3D nxpwifi_cfg80211_sched_scan_stop, + .change_station =3D nxpwifi_cfg80211_change_station, +#ifdef CONFIG_PM + .suspend =3D nxpwifi_cfg80211_suspend, + .resume =3D nxpwifi_cfg80211_resume, + .set_wakeup =3D nxpwifi_cfg80211_set_wakeup, +#endif + .set_coalesce =3D nxpwifi_cfg80211_set_coalesce, + .add_station =3D nxpwifi_cfg80211_add_station, + CFG80211_TESTMODE_CMD(nxpwifi_tm_cmd) + .get_channel =3D nxpwifi_cfg80211_get_channel, + .start_radar_detection =3D nxpwifi_cfg80211_start_radar_detection, + .channel_switch =3D nxpwifi_cfg80211_channel_switch, +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support nxpwifi_wowlan_support =3D { + .flags =3D WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_NET_DETECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE, + .n_patterns =3D NXPWIFI_MEF_MAX_FILTERS, + .pattern_min_len =3D 1, + .pattern_max_len =3D NXPWIFI_MAX_PATTERN_LEN, + .max_pkt_offset =3D NXPWIFI_MAX_OFFSET_LEN, + .max_nd_match_sets =3D NXPWIFI_MAX_ND_MATCH_SETS, +}; + +static const struct wiphy_wowlan_support nxpwifi_wowlan_support_no_gtk =3D= { + .flags =3D WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_NET_DETECT, + .n_patterns =3D NXPWIFI_MEF_MAX_FILTERS, + .pattern_min_len =3D 1, + .pattern_max_len =3D NXPWIFI_MAX_PATTERN_LEN, + .max_pkt_offset =3D NXPWIFI_MAX_OFFSET_LEN, + .max_nd_match_sets =3D NXPWIFI_MAX_ND_MATCH_SETS, +}; +#endif + +static const struct wiphy_coalesce_support nxpwifi_coalesce_support =3D { + .n_rules =3D NXPWIFI_COALESCE_MAX_RULES, + .max_delay =3D NXPWIFI_MAX_COALESCING_DELAY, + .n_patterns =3D NXPWIFI_COALESCE_MAX_FILTERS, + .pattern_min_len =3D 1, + .pattern_max_len =3D NXPWIFI_MAX_PATTERN_LEN, + .max_pkt_offset =3D NXPWIFI_MAX_OFFSET_LEN, +}; + +int nxpwifi_init_channel_scan_gap(struct nxpwifi_adapter *adapter) +{ + u32 n_channels_bg, n_channels_a =3D 0; + + n_channels_bg =3D nxpwifi_band_2ghz.n_channels; + + if (adapter->config_bands & BAND_A) + n_channels_a =3D nxpwifi_band_5ghz.n_channels; + + /* allocate twice the number total channels, since the driver issues an + * additional active scan request for hidden SSIDs on passive channels. + */ + adapter->num_in_chan_stats =3D 2 * (n_channels_bg + n_channels_a); + adapter->chan_stats =3D vmalloc(array_size(sizeof(*adapter->chan_stats), + adapter->num_in_chan_stats)); + + if (!adapter->chan_stats) + return -ENOMEM; + + return 0; +} + +/* This function registers the device with CFG802.11 subsystem. + * + * The function creates the wireless device/wiphy, populates it with + * default parameters and handler function pointers, and finally + * registers the device. + */ + +int nxpwifi_register_cfg80211(struct nxpwifi_adapter *adapter) +{ + int ret; + void *wdev_priv; + struct wiphy *wiphy; + struct nxpwifi_private *priv =3D adapter->priv[NXPWIFI_BSS_TYPE_STA]; + u8 *country_code; + u32 thr, retry; + + /* create a new wiphy for use with cfg80211 */ + wiphy =3D wiphy_new(&nxpwifi_cfg80211_ops, + sizeof(struct nxpwifi_adapter *)); + if (!wiphy) { + nxpwifi_dbg(adapter, ERROR, + "%s: creating new wiphy\n", __func__); + return -ENOMEM; + } + + wiphy->max_scan_ssids =3D NXPWIFI_MAX_SSID_LIST_LENGTH; + wiphy->max_scan_ie_len =3D NXPWIFI_MAX_VSIE_LEN; + + wiphy->mgmt_stypes =3D nxpwifi_mgmt_stypes; + wiphy->max_remain_on_channel_duration =3D 5000; + wiphy->interface_modes =3D BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP); + + wiphy->bands[NL80211_BAND_2GHZ] =3D &nxpwifi_band_2ghz; + if (adapter->config_bands & BAND_A) + wiphy->bands[NL80211_BAND_5GHZ] =3D &nxpwifi_band_5ghz; + else + wiphy->bands[NL80211_BAND_5GHZ] =3D NULL; + + if (adapter->is_hw_11ac_capable) + wiphy->iface_combinations =3D &nxpwifi_iface_comb_ap_sta_vht; + else + wiphy->iface_combinations =3D &nxpwifi_iface_comb_ap_sta; + wiphy->n_iface_combinations =3D 1; + + wiphy->max_ap_assoc_sta =3D adapter->max_sta_conn; + + /* Initialize cipher suits */ + wiphy->cipher_suites =3D nxpwifi_cipher_suites; + wiphy->n_cipher_suites =3D ARRAY_SIZE(nxpwifi_cipher_suites); + + if (adapter->regd) { + wiphy->regulatory_flags |=3D REGULATORY_CUSTOM_REG | + REGULATORY_DISABLE_BEACON_HINTS | + REGULATORY_COUNTRY_IE_IGNORE; + wiphy_apply_custom_regulatory(wiphy, adapter->regd); + } + + ether_addr_copy(wiphy->perm_addr, adapter->perm_addr); + wiphy->signal_type =3D CFG80211_SIGNAL_TYPE_MBM; + wiphy->flags |=3D WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | + WIPHY_FLAG_AP_UAPSD | + WIPHY_FLAG_REPORTS_OBSS | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_NETNS_OK | + WIPHY_FLAG_PS_ON_BY_DEFAULT; + wiphy->max_num_csa_counters =3D NXPWIFI_MAX_CSA_COUNTERS; + +#ifdef CONFIG_PM + if (ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info)) + wiphy->wowlan =3D &nxpwifi_wowlan_support; + else + wiphy->wowlan =3D &nxpwifi_wowlan_support_no_gtk; +#endif + + wiphy->coalesce =3D &nxpwifi_coalesce_support; + + wiphy->probe_resp_offload =3D NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; + + wiphy->max_sched_scan_reqs =3D 1; + wiphy->max_sched_scan_ssids =3D NXPWIFI_MAX_SSID_LIST_LENGTH; + wiphy->max_sched_scan_ie_len =3D NXPWIFI_MAX_VSIE_LEN; + wiphy->max_match_sets =3D NXPWIFI_MAX_SSID_LIST_LENGTH; + + wiphy->available_antennas_tx =3D BIT(adapter->number_of_antenna) - 1; + wiphy->available_antennas_rx =3D BIT(adapter->number_of_antenna) - 1; + + wiphy->features |=3D NL80211_FEATURE_SAE | + NL80211_FEATURE_INACTIVITY_TIMER | + NL80211_FEATURE_LOW_PRIORITY_SCAN | + NL80211_FEATURE_NEED_OBSS_SCAN; + + if (ISSUPP_RANDOM_MAC(adapter->fw_cap_info)) + wiphy->features |=3D NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | + NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | + NL80211_FEATURE_ND_RANDOM_MAC_ADDR; + + if (adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) + wiphy->features |=3D NL80211_FEATURE_SK_TX_STATUS; + + /* Reserve space for nxpwifi specific private data for BSS */ + wiphy->bss_priv_size =3D sizeof(struct nxpwifi_bss_priv); + + wiphy->reg_notifier =3D nxpwifi_reg_notifier; + + /* Set struct nxpwifi_adapter pointer in wiphy_priv */ + wdev_priv =3D wiphy_priv(wiphy); + *(unsigned long *)wdev_priv =3D (unsigned long)adapter; + + set_wiphy_dev(wiphy, priv->adapter->dev); + + ret =3D wiphy_register(wiphy); + if (ret < 0) { + nxpwifi_dbg(adapter, ERROR, + "%s: wiphy_register failed: %d\n", __func__, ret); + wiphy_free(wiphy); + return ret; + } + + if (!adapter->regd) { + if (adapter->region_code =3D=3D 0x00) { + nxpwifi_dbg(adapter, WARN, + "Ignore world regulatory domain\n"); + } else { + wiphy->regulatory_flags |=3D + REGULATORY_DISABLE_BEACON_HINTS | + REGULATORY_COUNTRY_IE_IGNORE; + country_code =3D + nxpwifi_11d_code_2_region(adapter->region_code); + if (country_code && + regulatory_hint(wiphy, country_code)) + nxpwifi_dbg(priv->adapter, ERROR, + "regulatory_hint() failed\n"); + } + } + + nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_GET, FRAG_THRESH_I, &thr, true); + wiphy->frag_threshold =3D thr; + nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_GET, RTS_THRESH_I, &thr, true); + wiphy->rts_threshold =3D thr; + nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true); + wiphy->retry_short =3D (u8)retry; + nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true); + wiphy->retry_long =3D (u8)retry; + + adapter->wiphy =3D wiphy; + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2068.outbound.protection.outlook.com [40.107.8.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC2C516F0F9; Fri, 21 Jun 2024 07:53:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956395; cv=fail; b=oPwSqmtbEw7lkaYlwcTVkCrtSftmOMjM9ZFcXk82OWn7YEpDsXVtewtRxui3N/5CnM+67oafs47NF8C/4PJZfwYTpPo3DGvRc6COVHzZCum+aug6T57N1AzECqx3M6griL0uq1ussqEjlrAR2E/bGlrWyI9AQj/qlUWLNQD030I= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956395; c=relaxed/simple; bh=3dplxlyXW1Zxy4YiHEztF/HjtUnRFoQ00VkskttUzp0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=oolwbWEkUh48fBftZOn8+mR9rORipqhNA5IjLGlZTQUj8jTtfgUoKf30zezo+swqfBO0ozU6qmQYoh6gTvImEVMnbpkC0CAzUydkoAe09uPcSWDJNGQqEucJCD86GwekR3lpl2vwDOEzBuCBPKFzROPOEesA9O5RSQoI8Ff76tw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=UkAwWe33; arc=fail smtp.client-ip=40.107.8.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="UkAwWe33" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=cO1HvPKybj4Lhm1QLuYtD5874AQRE/zsMzOX6D8s9+LHd/rVMsSZRTF6qkID6ICly3YsT/N3S/cWZLtNqxI7Doi2FsqkWHwXzlMU4RANPPJgXAj2bzWU5T9pIuCPDJgoY2HKF2UKym9q1dAuzGjgF6xseY7IHTC6lr7BRQQ/JjCEPWlOVwfhinjxgciw6ZXnjrp13r7uCFaV1ikgjUgG18Oe+AXgICl5enzU9fMUZc7mxfeVzlYE+EPL3WnYVFA4kyL6qW3KY1WWJy/H/coaNWK7csqsryA+bG+lRTAh9/QBOWihK5glL6BCybnF1v+QIj5uA+MtBg731bYQmz5KNA== 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=kO0oyfsuJoweQWi578zh5DQ2EF8aGbVqEv8amPR9EFw=; b=WeU+LL6bqrp6xqlisHjNYzjQzW5jd7rlKrpLigbHJqSaZy43LnBR92rSjvr9zkmS3zb4IiJNG3ohTK4CtnlTO2LqHSwbWGU21SDaYQL2CZEiW76OfCpDcOQlG7O3ENoFnSf+PdsiwF2hppq/WzsdPXM1G9XYZX2pttOe/tr5o+qiId39JUMfLnRXKXY6RVCSQlF7MGajhp7bzfpTt8Gi3HcOQzAXtNWwYlPYi3QTa4NiPJRTOZlbKDGtA36E1Vjox+J2pDll2uf7JwfqPGYyXq9jGYXvDY14caw9YebJMYeYQduuU0Z0frL/ipdlzAGqeYV/fsKVbvY+V3u+ofBmgQ== 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=kO0oyfsuJoweQWi578zh5DQ2EF8aGbVqEv8amPR9EFw=; b=UkAwWe33AQnQVDtpUx5UMy+zN9nB1qtku+j5cZpKauOPYMeZIqjsZcGjd0AicXdT5blnZpQF9qAMYIFksNs/LQ1YPI8lkO1Ep1JyFsSj43IsQGy6mUIk0jYD53twghT6vdK0qMU5shxxVwi0VUN4j9RXpHZfH9iCCrPoamX8WjY= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:11 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:11 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 11/43] wifi: nxpwifi: add cfg80211.h Date: Fri, 21 Jun 2024 15:51:36 +0800 Message-Id: <20240621075208.513497-12-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: 6090dcfa-c2e5-4d66-f139-08dc91c73259 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?gIscUlDGZRQ81VjOpuF1qa+VI3WljGnyhbRXiwbNbyP7KN47lAnWoIXk0s1d?= =?us-ascii?Q?brm/bK5JYXnRLVsOCYWvWpQTmkiWjCxNEADypEx3z4uw9aiWqMYpTOm4wM8Z?= =?us-ascii?Q?s81dFmiQ3rK/U/Kd4+kekLzoNbwgYNqpQ6az6lJKNYX1/PesLx83K6Lj2oPs?= =?us-ascii?Q?ba4f2XkZ3Uj8mcgxGh4KiTowdzWh2+YbYNodhvxvolFXNZlea2m20zrJiMFW?= =?us-ascii?Q?b1QCer2ZJKfMX7ut1fysIGZZvkekAeXbBSBlz7YI6xnYkHIGuH9cmNxU6Ld3?= =?us-ascii?Q?8lE2ns0JaB2d7amgeESyKqmWsFQA+7ODaJlwMuQE5FRRZ9Y7UiBFFLPERaaC?= =?us-ascii?Q?wiA7tyKohVTD9CnRGyvgO4My/f8IYfBar4gmRRVBlyP8C2Yt3ulubM04Kg0r?= =?us-ascii?Q?f6Y7gOFLdO/xJBa4L6JBFjdrGsFp60121tS6ldRp64XmizkEor/08Lo0lURd?= =?us-ascii?Q?Ta4lIK56Td5grrYtvfJHh1fLvJICg1/5S2kfVkZZK1AGR1n1pyoOFX4EvBhV?= =?us-ascii?Q?4R/gt7FBtFNo5Amr6LKq1IgDAfcObrj/jbGArRWgDpMzUVQM7qGQOkoG/ckX?= =?us-ascii?Q?Ur8xUgJ3HezKgbuWeHva71XzqaJETeSWo/04cWmuBx2Hf/KJikYDEhjJcul1?= =?us-ascii?Q?+aNAZO1LDrxCeIeR6SUdojXl+uBSdsN2jqGVU2mRKtBDAuA6LnU3AMkY5UGP?= =?us-ascii?Q?5BQMmVXwR+sJekGSpi0mKPRTR5akcd6J5KSNjsO6LsEI5Tq89gagLnxiA535?= =?us-ascii?Q?gIgC8iGPVbep+XNObLVdSmRFSzrHIUaeNode9YgVSLRGGQLtCpUrd9knq0ng?= =?us-ascii?Q?40wQ1ZJwqrc1KYV/mKn7J57L5cvBWPG7HWsQlKHAch4R9SHa6U8Cj4iE2hu+?= =?us-ascii?Q?7fnPfmCbAbMAh5uBoFXPdkf7tMXvN0VPuHu1UYN7nkXAHanwVnfOwrr0Bo2s?= =?us-ascii?Q?zcmOAhiN0Fbqc5X8S98mrr1bQ6bdaq1BZ/G7gp22doBiGTQGKLf5P9cruSPb?= =?us-ascii?Q?4vYalpZKWt2KVN7DD+rXXRaLf/W2HOGO5p3KAjOt4AlDb7oPiv8mjcituTWz?= =?us-ascii?Q?GYn3QIA0r0IDQNNEHDOzmfA1/19gr16Pt98Gofigo8xkJ2Ht9IcNcr/735IG?= =?us-ascii?Q?XRJCnKDG081Ylui7edXdOdhZGFOc51tFLdoA/smJK/bZ1+3TsH5WDWXZRu2D?= =?us-ascii?Q?gNVnFx3YNZLDQQwqW+VtHcpC552tbr1xjRfUPF4PaRH+m/fkh2azbuB5VEd0?= =?us-ascii?Q?xxk7EyMtofKJal0kpPV/Dhlqz9FkKzxq7W+eyfqGgMq3jO027K9jZayYN95e?= =?us-ascii?Q?pbPhLcry3AO0e84yH4DrK9d9vaTQTGmnrTbhv1Vv1fc6ZIm/jsHS1btoaVOb?= =?us-ascii?Q?5kbLWXU=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?L5hY2wsE3StsnZkYjDHbMYD5uQFkjyWQG0YbTweoYDYlW2C5p+HpMNeZaQpL?= =?us-ascii?Q?NNQTe+AszuO4307TNAq377yqM/J0v0NPWzpDSN+XS0dWh7Bx5fN5cpNqmJY9?= =?us-ascii?Q?fXInB6Svey5nf7JvyFKwgTxLVm0PdE1MXdrUCTkGiIqcGYxsZPfsJrVCqTAa?= =?us-ascii?Q?IGDD6Et4D+c/a6fzv3GE8d9eV4lXch+vEeB65s4aAKsDBUp5XoHEIpEztIn+?= =?us-ascii?Q?LltJF7A7ajYIFDAep/tAhDzO19G9ER5nCJfuylVtgTAUXIojDoJQhRpnBq6l?= =?us-ascii?Q?6on5eQJqBa2qwKoZn5n3Xbst3FWXzV8sLiq6XyZ1telNp1Qp8hxJ6kfcyU7g?= =?us-ascii?Q?v8cStNYUBov6yMTXkg+SiaW4f1gjH9Pei4kCbH8jlyBQX8ZG5eoije9i3Tqu?= =?us-ascii?Q?eBtnvimqTVUoo+GvRZVXuSxV/SpGbVCbyPTIRB3oFsvYwnXF5ejaJbmXWbAw?= =?us-ascii?Q?speyKSOP83ZDvvrrx05Ibgmc2Ca8AjcwX0OFVcpnvZk3YsB8dXjjicznqL+6?= =?us-ascii?Q?FdnKanlEmy6cXOFYEgVGP56HxtM6fJGtyocUeuLw8e/MlPOafHdlpqrURxBc?= =?us-ascii?Q?a11IaIjNgFea7wZ7+g7B1gBT8frSpdMqmdP4e82HC5QIuEsMTYNB2Bx0PxpQ?= =?us-ascii?Q?/S0uIqj3yzgXkPgtTs84LiV98q5wqrkc5zWXpxxdiRvtd84rQmPBhSoDeWGQ?= =?us-ascii?Q?ipAaBT2jO6SCFivF74BWP9BcOpK1h8ABvfhECauDG5hxbVldbf0BR06W2TeT?= =?us-ascii?Q?zotZdJElmlc/eesa2kZlVMwp6l9Gz5sbLiFZa7uTkT5G3EpLrWdmTzFiWzJq?= =?us-ascii?Q?lWw2pTShYTXO1DDXVrtpMEMGfwvXMFQ41nk1gvYr3cUHjbbpCho8bPQpbG2q?= =?us-ascii?Q?VugvyriwGDy1gb0O4bxkMk2kl8PCHByEIqO/9V+kpF6dO5MBT2Pl56dOAhbK?= =?us-ascii?Q?xGvCv/iEbjaYjS4P2QT0YJYuCMuEWAWTbctkFdEPYHw/9P5Z/IKFAhvpP61Z?= =?us-ascii?Q?JuQXp1c0okmx3Q9SUo0WWgt8dEo3ixf9Vdfqx3oYhbowEkuxTjK+7slQjS6+?= =?us-ascii?Q?x6yolHsiZ8eD+zSABOAc1iMARzbcSKxz5maJ8WnS6k5jYx+TGyGHoFp0cGs/?= =?us-ascii?Q?Ih6WAoba8CwVe6bSic83RfwYq9YgMQOeEIL/ZUDggdPE8HOvWc664/gCx+P0?= =?us-ascii?Q?oUar7YHs7yWcvjEaYqS2EmK/cvvjVDZfnTJmT+Eq+mWbYKlJ1pt2zR6L2nQy?= =?us-ascii?Q?zvGePe2nIwtQ5fKrLzetXgO7H5JNh3dtwmt3Jogrq0f48w9k8PUL8SNWe2No?= =?us-ascii?Q?N0D3QjRMAK5yMt8f6D9ojsNope8rWjK8OX3cN88Rj2fbQyD3EFBo/a+jcr6Y?= =?us-ascii?Q?BiRCE3wvL4u4KAnDUaDcpV0MXxMwgvDsTLQRyjhvw2N25iIBrYFwsjWmO7EG?= =?us-ascii?Q?lYjuvYWBqq83asKqaffkobyIS6O7dAUdHT4DNKKJi+pkt5DjmezoDkmYJVgN?= =?us-ascii?Q?Bz0J+yIrWMcgCu5Xa1y3cckSTmVmjTY1hPMZm56jU5whidMd6oibfyzJ1KdT?= =?us-ascii?Q?QEr72XrMKhBhgApjp2eD4X+7KmVwl3o0D7dw46qg?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6090dcfa-c2e5-4d66-f139-08dc91c73259 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:11.2284 (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: zkRIHgbgwhK9Nan4K+jZlUptqwP6vrTZVeC3DOP6FVwS97c7+iJDrM4FCwbFMbWOGDkXNMoKyPK8LO3CRzodbw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/cfg80211.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/cfg80211.h diff --git a/drivers/net/wireless/nxp/nxpwifi/cfg80211.h b/drivers/net/wire= less/nxp/nxpwifi/cfg80211.h new file mode 100644 index 000000000000..086ec9ca4cc9 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/cfg80211.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: CFG80211 + * + * Copyright 2011-2024 NXP + */ + +#ifndef __NXPWIFI_CFG80211__ +#define __NXPWIFI_CFG80211__ + +#include "main.h" + +int nxpwifi_register_cfg80211(struct nxpwifi_adapter *adapter); + +int nxpwifi_cfg80211_change_beacon_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *data); + +#endif --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2068.outbound.protection.outlook.com [40.107.8.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E601016F269; Fri, 21 Jun 2024 07:53:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956398; cv=fail; b=EcCzHvw/5mZmHInszWJNX2mjj30whl0otn7rULP5SJ3twtI7iWIhR9ak3LK8N3BMaU0RgyV3CFfHnkU6DZOPwyfCEo9GTc01cVRrFzTAnYKC5TVnazWiLLF9d8hjwSbDtJgGTF2zTl7YVh1p7W2w13frqu4AaIoeRVpOC4ePlWg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956398; c=relaxed/simple; bh=uEpY8cDKF0IEOBKttlAGcwDVWN/AfVZM4YwiyAE3Se8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=R8nsNnwjxvGP+D+FU7qU6T6TCKc8EtebB7wMeDhJDflWwCdqDjVK5iDFASZce7xJ/UivJzRXmvw+guJpFPsTg7+GWHo8mB45FrJl/5E3wJGARhzhUuv027fQcvILcz9HGNk3qdmOjI+qLbZYkHIRJeY7kli+Kr2+5Cue5ZCzHdA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=Vbzp8wIl; arc=fail smtp.client-ip=40.107.8.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="Vbzp8wIl" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fdu8PME5SNxNfVJk9X6a/aWXd5KxTVnTjY1GXTUt5yCVBL9TZ6PnLRwbb9FLa5hBWwNoe+tL85EfztoIOgKtUcrhk/SbryDv9nlKlELYtdNvWgOo15S9fRj5munVtbmF+vg8SJ5W2szpGTUJtKvxi/4mgt24G30zQDX422+kfOcAg5M8JUWnM42VhYdePAfFnPcusQ/P9UHkuVOqv4N+wNiHQ8aEGUggsv5L5N9sDuuIgqasBSNPmDyw8Tv8nK9m+hvUl8FrczUQ93w+cl3di2m4JfFPp3bYJGeNXhmPMA+9LA4SeQ/0DTJsI/nbldb1h1STTHdWT7S2gQQogAfX8w== 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=0GU6nIhsdc9DdTeK08hBh9rOdAUEaagjd8/3z87/I9w=; b=WFvbsMTIOIwayEIIjZRwQqKOVFPlJ2VcF6VHi8euFX6QqmHqNzRmY9mkjW0pMmyWmgsu54lP4kgTGP/CIeknvNvxatSzmARaPC3PkB2Dptx9Qm2vNDQ3FW/DdHu7YRZE0tnds27b15VmUcc0yzRvMae59GbkNJoZBJrnFxZWVgd4g7JJf/DmsKl567o7/ZJaraE2Fl/i7aS+PXXn6XDXVk0IBH125f7embJ0zzhMrNdmWZ4HYVLcsOAEb1epicJzlZQOhxGPMVxa+ygGkRxrcw6+JGRUn81Lfv7flERdkO9qGP9cTTmLQn74HfaNm5/suOxcYY6TqL56wKlF97E9MQ== 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=0GU6nIhsdc9DdTeK08hBh9rOdAUEaagjd8/3z87/I9w=; b=Vbzp8wIlR+HFZlsjecYBGRBQAEgG/tTJelazmfw/m+LYZjcrBTXYEppEpamtZtztCOQuJ5EOCgGBfPrlLtMzeEwWF3WKhQX9Py0BkW9y5/cpyI/Hp/jHYgr4QPhxGjwjva/9U41DHLayVMyJpIDhwAo8s4Mplf9gisP0symr694= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:14 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:14 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 12/43] wifi: nxpwifi: add cfp.c Date: Fri, 21 Jun 2024 15:51:37 +0800 Message-Id: <20240621075208.513497-13-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: 30a6f778-bd9c-4d42-52ef-08dc91c73415 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?a5tl6gOEhIK38lxLQ2WltU0qnCOlZsTQZ8bXL8yCyfMk3Y4+ZAPFMcag5o0n?= =?us-ascii?Q?/Owm4LezNOzDgYvBcHlZFA1ya7NQowrNQKykcejkRa4EB9zS0v0SznGwzHLR?= =?us-ascii?Q?LuKrA8bSMVYcF1WR/JJO3rLOyQSXvqUI/Gu7Bo0Hpnmskv6PWiDZI/n/w9se?= =?us-ascii?Q?H7tJOyQrsVieg7zZ1/0THpypIN/MKMZ9slmFpdYa6utpLAAq1fsf1eMI2EMV?= =?us-ascii?Q?bNCfqReCqq6fV57FwdrY2po41QZRhsR3WT65JURJP7tctAHl2vwX9JYBOlul?= =?us-ascii?Q?iqWGnUYjxaTk7qXfSc5p2YjR7TWeFmRoReUPDeJ4eZ51bnmHtO16VMkb6I5e?= =?us-ascii?Q?942TCfRa5vw2Go57HjRiVSqsqQCZiL9AVc7amFEhiA68LxL0xWU5NlpunHWA?= =?us-ascii?Q?/qbNA6qHd68pCv5b9F6mBpXSKwTOkAQwWIPTGr1eIEm3R3vBHXSw2j4xybS7?= =?us-ascii?Q?kUa0qe+w8gtZcEVFOMUy4KNcQtnCX3Rk8nyV3fJYr7XhoEaxEa+5T7UMMojM?= =?us-ascii?Q?8pz5iyf2uM4KjjWphHYrKG978AyErpkUDB6pUoDXIIQyvYJldaKFAX7f/Vmn?= =?us-ascii?Q?P0Dhg09uGAncADtf5O92APx2GoHtjOdczMpGGrqrHtIH8lQYVH+jeBJQTEa9?= =?us-ascii?Q?7a44ZbEafFYj1kWzqUn10nr4+O+I2Bvduh07v5fFi6+vdzAd5KooNFHt1+CC?= =?us-ascii?Q?2QTVhAk3YsZ3ahDB4UGHrmW5YBgntbIJ4SOwbtoFk4Kp/Mb2Vl8oIoayR0Mw?= =?us-ascii?Q?QrsZhJiA8/5VY4ZmhzSOK6Wu68xOI0ZZlEHgNa+zhKpbeCDH5eXQy++LPBrL?= =?us-ascii?Q?0M67+L878a1KIF/o2kifLxVn/sIjHRdFOxtjw+MMoBEvPhe9uQPxcI2D7DNZ?= =?us-ascii?Q?AtlvZMyxqJt973fIwxd8oOxbwIjCSaVGUDZ5P58h6pXD0y+4P08Yk34K4Dbv?= =?us-ascii?Q?iyYOjW/2UlNS112tLjMotVDqzcukuN4sL+khNU1f7h3ZlvemWxK1URnKgUPT?= =?us-ascii?Q?qgC3JGSqg1Hj5txJuAZMOnD3XjJj7NEGkXXy74Z9u7Qo0lsrcftZN+w0gbcL?= =?us-ascii?Q?uYZDF1UDJZ2xAhYVWjXBZUIjyYEUqX7EHiiNcNsTb/6WVXtIND7Bjqcdfazq?= =?us-ascii?Q?H2gMPqGZds0g3ctMOCVJRCx2NmfO0LcSeXxAAn3nvi+JbmKwKeQ/kk0er0Da?= =?us-ascii?Q?QSLYCeF0YpHRYJ5eRSztmNh7gmMQZmPnN+n26d3iRJH076uRu489YQBBCvpL?= =?us-ascii?Q?jNru0ycg15xtUAry5PKB2+xggt+DMRJwtcE8Y0OzmDib5ywJgRpdv2Q8zdJm?= =?us-ascii?Q?ad1CpD3DbExiM3ulcfYAUWix1t7WVQ/ns7AFQdcQbCHOtXC6M1CzuQBTxfqz?= =?us-ascii?Q?U9eKS2c=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?YHekFwP7ddtvymjXoikNox4DU91Dl0C3WJP0TLlCUCtZ0giF05HYWdcuf0La?= =?us-ascii?Q?rMHB63EeJmafdc8blW3c1HnCZ1lFHTnl/6Zyr1Bw1tzQjhkS8bH3v4FOmDsX?= =?us-ascii?Q?FMACeZplLFrBjVg39PYDWeRa1rvwK0wobwPONS3decIutSLUFDJlK/SzFAP5?= =?us-ascii?Q?8yMkKqdx7R7vxOvV+2d++Pu9sk/FLAipp6j5Xlo5QSIFs2oZggjjXwNDfK2s?= =?us-ascii?Q?5z9GIzgYm11HD29qMNmEVRprXse9PUdug5qAFXSnDICfIt2e64qBIPFPhqn9?= =?us-ascii?Q?xNDCueste/Of7OrBDXEtbYyCMCDffdIfoZGj6dYXYpsM1HL8BC8A5tdvhS5l?= =?us-ascii?Q?Tgz7ta57JMJ8MHwdvfVfzk7eEf3VjClPaXGJAlcsw+HeRPxaVg1V/EYqRpwm?= =?us-ascii?Q?O/wlkSoO84wc75/SqyPqRBiP0hI39ZK5HlxNVxZKX4bnfSCwwUEPcNBZvfnC?= =?us-ascii?Q?X94NNoXbiQkfPuq7IIQYTZp+BOZkVBzYQHBAeHGI7uJDJU8pPRUzekQxr5CO?= =?us-ascii?Q?ZMhAfrfmwy1pFHHIBCmkBfczIS/IBZrjK3T6NssyaCPIldH6Z4A/nWQuAS7v?= =?us-ascii?Q?w7w2SBPn4W8X8V0/WrsnMAQAJBFCx0gDrjUz92szXPdkhDDF04SjaDNcqiO8?= =?us-ascii?Q?XiUvs6M5Zm526f2J/8n5fUYpjqsN+wlbaGKAv9O/6x/fDjpaZdnQUQAyKjGD?= =?us-ascii?Q?v5PTlxDHVUBq/Wyqhi+5hl+2H48cXBh13/1qwm24D+9oT6mqYo3DReUmjRlI?= =?us-ascii?Q?Y2yng+PO/m5gUOUyi3sVdDSDvhpKXhHRF4uubvd30BmX86xTIQXCr+yYoUif?= =?us-ascii?Q?mmgD78OCLjpimDkq0ucYlJ0UDLJEZWWIJvQdTIUXg5pWK0GiHM9dCSff6rg+?= =?us-ascii?Q?9n+93hzWpgrci2EdMBFUE/jD77VE21+AiBy5TE0K7gEccTH9UUEpp1P76/Qg?= =?us-ascii?Q?gIvZKJIviSQ5/79IHEl+eHWzBZQ3QkVluGcDzsRye3TclM4mi8NVvhHHYU9x?= =?us-ascii?Q?LdecYwpPbd/DVfiq+E/uWy6+6txuvrHd+yyi2xj227KbD1WuAGKqF70m6PSj?= =?us-ascii?Q?9A5VxkUL+jJAbNx+3XgDjqYzdCuUdaP4t2z3rQyVTXsRIAmMfgSqlXWHNjQn?= =?us-ascii?Q?MuIEbrKNPrE7pVvkJw6j5X26drnH8RPOc5f+ItmmWOPJFBHKqtK2S9dadm9r?= =?us-ascii?Q?uwZ8LGTDufZNzGS40qaZXzJzP4/nJLreQzOfTgisigZRHJpGIaMDWcPMAHo3?= =?us-ascii?Q?Rx/VwLjwC1Dii7QJYvCv20xHJOJmVyKP5t0i/GDjIRdtCWEm1QjZR6JMR+Ri?= =?us-ascii?Q?NrPr3on8B5/nB7f3a9fgBnnj6Mv1fHm1ot8uNJBNpcY6Wyqevd4hfo+pZbBV?= =?us-ascii?Q?3Itaw/eSNcOsyiUDrzuR4kLIQvsoMXjbLYxaswvKObzzLC6WgsMMdRQGyS7K?= =?us-ascii?Q?2Dxmh+wP8Os/Y6aDZbEQM2tgpEdzidxOFRzsl1rqgzNPMHe1eff9WFMH+Ufx?= =?us-ascii?Q?D5056ItQyLWNCob1ljrhnSkBq/VsXsuADZfFhvoGwamXRr7GKHiasztvmmnR?= =?us-ascii?Q?xoGEA8CE+RDC1HGWY3JiExMkWn6KNtSiXlE0ca4K?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 30a6f778-bd9c-4d42-52ef-08dc91c73415 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:14.1645 (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: d/GV2acD0GSxaEbWg4GSpSSneltpMc4DvTiByJ+K/EjN6lbGPsKmApYAX4QUX5SConOa8mga++Wv7c4V13+WiA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/cfp.c | 484 +++++++++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/cfp.c diff --git a/drivers/net/wireless/nxp/nxpwifi/cfp.c b/drivers/net/wireless/= nxp/nxpwifi/cfp.c new file mode 100644 index 000000000000..4fcd2add9b66 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/cfp.c @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: Channel, Frequency and Power + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cfg80211.h" + +/* 100mW */ +#define NXPWIFI_TX_PWR_DEFAULT 20 +/* 100mW */ +#define NXPWIFI_TX_PWR_US_DEFAULT 20 +/* 50mW */ +#define NXPWIFI_TX_PWR_JP_DEFAULT 16 +/* 100mW */ +#define NXPWIFI_TX_PWR_FR_100MW 20 +/* 10mW */ +#define NXPWIFI_TX_PWR_FR_10MW 10 +/* 100mW */ +#define NXPWIFI_TX_PWR_EMEA_DEFAULT 20 + +static u8 supported_rates_a[A_SUPPORTED_RATES] =3D { 0x0c, 0x12, 0x18, 0x2= 4, + 0xb0, 0x48, 0x60, 0x6c, 0 }; +static u16 nxpwifi_data_rates[NXPWIFI_SUPPORTED_RATES_EXT] =3D { 0x02, 0x0= 4, + 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, + 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, + 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, + 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, + 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 }; + +static u8 supported_rates_b[B_SUPPORTED_RATES] =3D { 0x02, 0x04, 0x0b, 0x1= 6, 0 }; + +static u8 supported_rates_g[G_SUPPORTED_RATES] =3D { 0x0c, 0x12, 0x18, 0x2= 4, + 0x30, 0x48, 0x60, 0x6c, 0 }; + +static u8 supported_rates_bg[BG_SUPPORTED_RATES] =3D { 0x02, 0x04, 0x0b, 0= x0c, + 0x12, 0x16, 0x18, 0x24, 0x30, 0x48, + 0x60, 0x6c, 0 }; + +u16 region_code_index[NXPWIFI_MAX_REGION_CODE] =3D { 0x00, 0x10, 0x20, 0x3= 0, + 0x31, 0x32, 0x40, 0x41, 0x50 }; + +static u8 supported_rates_n[N_SUPPORTED_RATES] =3D { 0x02, 0x04, 0 }; + +/* For every mcs_rate line, the first 8 bytes are for stream 1x1, + * and all 16 bytes are for stream 2x2. + */ +static const u16 mcs_rate[4][16] =3D { + /* LGI 40M */ + { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, + 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, + + /* SGI 40M */ + { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, + 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, + + /* LGI 20M */ + { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, + 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, + + /* SGI 20M */ + { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, + 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } +}; + +/* AC rates */ +static const u16 ac_mcs_rate_nss1[8][10] =3D { + /* LG 160M */ + { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, + 0x492, 0x57C, 0x618 }, + + /* SG 160M */ + { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, + 0x514, 0x618, 0x6C6 }, + + /* LG 80M */ + { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, + 0x249, 0x2BE, 0x30C }, + + /* SG 80M */ + { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, + 0x28A, 0x30C, 0x363 }, + + /* LG 40M */ + { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, + 0x10E, 0x144, 0x168 }, + + /* SG 40M */ + { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, + 0x12C, 0x168, 0x190 }, + + /* LG 20M */ + { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 }, + + /* SG 20M */ + { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 }, +}; + +/* NSS2 note: the value in the table is 2 multiplier of the actual rate */ +static const u16 ac_mcs_rate_nss2[8][10] =3D { + /* LG 160M */ + { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, + 0x924, 0xAF8, 0xC30 }, + + /* SG 160M */ + { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, + 0xA28, 0xC30, 0xD8B }, + + /* LG 80M */ + { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, + 0x492, 0x57C, 0x618 }, + + /* SG 80M */ + { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, + 0x514, 0x618, 0x6C6 }, + + /* LG 40M */ + { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, + 0x21C, 0x288, 0x2D0 }, + + /* SG 40M */ + { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, + 0x258, 0x2D0, 0x320 }, + + /* LG 20M */ + { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, + 0x138, 0x00 }, + + /* SG 20M */ + { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, + 0x15B, 0x00 }, +}; + +struct region_code_mapping { + u8 code; + u8 region[IEEE80211_COUNTRY_STRING_LEN]; +}; + +static struct region_code_mapping region_code_mapping_t[] =3D { + { 0x10, "US " }, /* US FCC */ + { 0x20, "CA " }, /* IC Canada */ + { 0x30, "FR " }, /* France */ + { 0x31, "ES " }, /* Spain */ + { 0x32, "FR " }, /* France */ + { 0x40, "JP " }, /* Japan */ + { 0x41, "JP " }, /* Japan */ + { 0x50, "CN " }, /* China */ +}; + +/* This function converts integer code to region string */ +u8 *nxpwifi_11d_code_2_region(u8 code) +{ + u8 i; + + /* Look for code in mapping table */ + for (i =3D 0; i < ARRAY_SIZE(region_code_mapping_t); i++) + if (region_code_mapping_t[i].code =3D=3D code) + return region_code_mapping_t[i].region; + + return NULL; +} + +/* This function maps an index in supported rates table into + * the corresponding data rate. + */ +u32 nxpwifi_index_to_acs_data_rate(struct nxpwifi_private *priv, + u8 index, u8 ht_info) +{ + u32 rate =3D 0; + u8 mcs_index =3D 0; + u8 bw =3D 0; + u8 gi =3D 0; + + if ((ht_info & 0x3) =3D=3D NXPWIFI_RATE_FORMAT_VHT) { + mcs_index =3D min(index & 0xF, 9); + + /* 20M: bw=3D0, 40M: bw=3D1, 80M: bw=3D2, 160M: bw=3D3 */ + bw =3D (ht_info & 0xC) >> 2; + + /* LGI: gi =3D0, SGI: gi =3D 1 */ + gi =3D (ht_info & 0x10) >> 4; + + if ((index >> 4) =3D=3D 1) /* NSS =3D 2 */ + rate =3D ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index]; + else /* NSS =3D 1 */ + rate =3D ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index]; + } else if ((ht_info & 0x3) =3D=3D NXPWIFI_RATE_FORMAT_HT) { + /* 20M: bw=3D0, 40M: bw=3D1 */ + bw =3D (ht_info & 0xC) >> 2; + + /* LGI: gi =3D0, SGI: gi =3D 1 */ + gi =3D (ht_info & 0x10) >> 4; + + if (index =3D=3D NXPWIFI_RATE_BITMAP_MCS0) { + if (gi =3D=3D 1) + rate =3D 0x0D; /* MCS 32 SGI rate */ + else + rate =3D 0x0C; /* MCS 32 LGI rate */ + } else if (index < 16) { + if (bw =3D=3D 1 || bw =3D=3D 0) + rate =3D mcs_rate[2 * (1 - bw) + gi][index]; + else + rate =3D nxpwifi_data_rates[0]; + } else { + rate =3D nxpwifi_data_rates[0]; + } + } else { + /* 11n non-HT rates */ + if (index >=3D NXPWIFI_SUPPORTED_RATES_EXT) + index =3D 0; + rate =3D nxpwifi_data_rates[index]; + } + + return rate; +} + +/* This function maps an index in supported rates table into + * the corresponding data rate. + */ +u32 nxpwifi_index_to_data_rate(struct nxpwifi_private *priv, + u8 index, u8 ht_info) +{ + u32 mcs_num_supp =3D + (priv->adapter->user_dev_mcs_support =3D=3D HT_STREAM_2X2) ? 16 : 8; + u32 rate; + + if (priv->adapter->is_hw_11ac_capable) + return nxpwifi_index_to_acs_data_rate(priv, index, ht_info); + + if (ht_info & BIT(0)) { + if (index =3D=3D NXPWIFI_RATE_BITMAP_MCS0) { + if (ht_info & BIT(2)) + rate =3D 0x0D; /* MCS 32 SGI rate */ + else + rate =3D 0x0C; /* MCS 32 LGI rate */ + } else if (index < mcs_num_supp) { + if (ht_info & BIT(1)) { + if (ht_info & BIT(2)) + /* SGI, 40M */ + rate =3D mcs_rate[1][index]; + else + /* LGI, 40M */ + rate =3D mcs_rate[0][index]; + } else { + if (ht_info & BIT(2)) + /* SGI, 20M */ + rate =3D mcs_rate[3][index]; + else + /* LGI, 20M */ + rate =3D mcs_rate[2][index]; + } + } else { + rate =3D nxpwifi_data_rates[0]; + } + } else { + if (index >=3D NXPWIFI_SUPPORTED_RATES_EXT) + index =3D 0; + rate =3D nxpwifi_data_rates[index]; + } + return rate; +} + +/* This function returns the current active data rates. + * + * The result may vary depending upon connection status. + */ +u32 nxpwifi_get_active_data_rates(struct nxpwifi_private *priv, u8 *rates) +{ + if (!priv->media_connected) + return nxpwifi_get_supported_rates(priv, rates); + else + return nxpwifi_copy_rates(rates, 0, + priv->curr_bss_params.data_rates, + priv->curr_bss_params.num_of_rates); +} + +/* This function locates the Channel-Frequency-Power triplet based upon + * band and channel/frequency parameters. + */ +struct nxpwifi_chan_freq_power * +nxpwifi_get_cfp(struct nxpwifi_private *priv, u8 band, u16 channel, u32 fr= eq) +{ + struct nxpwifi_chan_freq_power *cfp =3D NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch =3D NULL; + int i; + + if (!channel && !freq) + return cfp; + + if (nxpwifi_band_to_radio_type(band) =3D=3D HOST_SCAN_RADIO_TYPE_BG) + sband =3D priv->wdev.wiphy->bands[NL80211_BAND_2GHZ]; + else + sband =3D priv->wdev.wiphy->bands[NL80211_BAND_5GHZ]; + + if (!sband) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: cannot find cfp by band %d\n", + __func__, band); + return cfp; + } + + for (i =3D 0; i < sband->n_channels; i++) { + ch =3D &sband->channels[i]; + + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (freq) { + if (ch->center_freq =3D=3D freq) + break; + } else { + /* find by valid channel*/ + if (ch->hw_value =3D=3D channel || + channel =3D=3D FIRST_VALID_CHANNEL) + break; + } + } + if (i =3D=3D sband->n_channels) { + nxpwifi_dbg(priv->adapter, WARN, + "%s: cannot find cfp by band %d\t" + "& channel=3D%d freq=3D%d\n", + __func__, band, channel, freq); + } else { + if (!ch) + return cfp; + + priv->cfp.channel =3D ch->hw_value; + priv->cfp.freq =3D ch->center_freq; + priv->cfp.max_tx_power =3D ch->max_power; + cfp =3D &priv->cfp; + } + + return cfp; +} + +/* This function checks if the data rate is set to auto. + */ +u8 +nxpwifi_is_rate_auto(struct nxpwifi_private *priv) +{ + u32 i; + int rate_num =3D 0; + + for (i =3D 0; i < ARRAY_SIZE(priv->bitmap_rates); i++) + if (priv->bitmap_rates[i]) + rate_num++; + + if (rate_num > 1) + return true; + else + return false; +} + +/* This function gets the supported data rates from bitmask inside + * cfg80211_scan_request. + */ +u32 nxpwifi_get_rates_from_cfg80211(struct nxpwifi_private *priv, + u8 *rates, u8 radio_type) +{ + struct wiphy *wiphy =3D priv->adapter->wiphy; + struct cfg80211_scan_request *request =3D priv->scan_request; + u32 num_rates, rate_mask; + struct ieee80211_supported_band *sband; + int i; + + if (radio_type) { + sband =3D wiphy->bands[NL80211_BAND_5GHZ]; + if (WARN_ON_ONCE(!sband)) + return 0; + rate_mask =3D request->rates[NL80211_BAND_5GHZ]; + } else { + sband =3D wiphy->bands[NL80211_BAND_2GHZ]; + if (WARN_ON_ONCE(!sband)) + return 0; + rate_mask =3D request->rates[NL80211_BAND_2GHZ]; + } + + num_rates =3D 0; + for (i =3D 0; i < sband->n_bitrates; i++) { + if ((BIT(i) & rate_mask) =3D=3D 0) + continue; /* skip rate */ + rates[num_rates++] =3D (u8)(sband->bitrates[i].bitrate / 5); + } + + return num_rates; +} + +/* This function gets the supported data rates. The function works in + * both Ad-Hoc and infra mode by printing the band and returning the + * data rates. + */ +u32 nxpwifi_get_supported_rates(struct nxpwifi_private *priv, u8 *rates) +{ + u32 k =3D 0; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION) { + switch (adapter->config_bands) { + case BAND_B: + nxpwifi_dbg(adapter, INFO, "info: infra band=3D%d\t" + "supported_rates_b\n", + adapter->config_bands); + k =3D nxpwifi_copy_rates(rates, k, supported_rates_b, + sizeof(supported_rates_b)); + break; + case BAND_G: + case BAND_G | BAND_GN: + nxpwifi_dbg(adapter, INFO, "info: infra band=3D%d\t" + "supported_rates_g\n", + adapter->config_bands); + k =3D nxpwifi_copy_rates(rates, k, supported_rates_g, + sizeof(supported_rates_g)); + break; + case BAND_B | BAND_G: + case BAND_A | BAND_B | BAND_G: + case BAND_A | BAND_B: + case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: + case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: + case BAND_B | BAND_G | BAND_GN: + nxpwifi_dbg(adapter, INFO, "info: infra band=3D%d\t" + "supported_rates_bg\n", + adapter->config_bands); + k =3D nxpwifi_copy_rates(rates, k, supported_rates_bg, + sizeof(supported_rates_bg)); + break; + case BAND_A: + case BAND_A | BAND_G: + nxpwifi_dbg(adapter, INFO, "info: infra band=3D%d\t" + "supported_rates_a\n", + adapter->config_bands); + k =3D nxpwifi_copy_rates(rates, k, supported_rates_a, + sizeof(supported_rates_a)); + break; + case BAND_AN: + case BAND_A | BAND_AN: + case BAND_A | BAND_AN | BAND_AAC: + case BAND_A | BAND_G | BAND_AN | BAND_GN: + case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC: + nxpwifi_dbg(adapter, INFO, "info: infra band=3D%d\t" + "supported_rates_a\n", + adapter->config_bands); + k =3D nxpwifi_copy_rates(rates, k, supported_rates_a, + sizeof(supported_rates_a)); + break; + case BAND_GN: + nxpwifi_dbg(adapter, INFO, "info: infra band=3D%d\t" + "supported_rates_n\n", + adapter->config_bands); + k =3D nxpwifi_copy_rates(rates, k, supported_rates_n, + sizeof(supported_rates_n)); + break; + } + } + + return k; +} + +u8 nxpwifi_adjust_data_rate(struct nxpwifi_private *priv, + u8 rx_rate, u8 rate_info) +{ + u8 rate_index =3D 0; + + /* HT40 */ + if ((rate_info & BIT(0)) && (rate_info & BIT(1))) + rate_index =3D NXPWIFI_RATE_INDEX_MCS0 + + NXPWIFI_BW20_MCS_NUM + rx_rate; + else if (rate_info & BIT(0)) /* HT20 */ + rate_index =3D NXPWIFI_RATE_INDEX_MCS0 + rx_rate; + else + rate_index =3D (rx_rate > NXPWIFI_RATE_INDEX_OFDM0) ? + rx_rate - 1 : rx_rate; + + if (rate_index >=3D NXPWIFI_MAX_AC_RX_RATES) + rate_index =3D NXPWIFI_MAX_AC_RX_RATES - 1; + + return rate_index; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2088.outbound.protection.outlook.com [40.107.8.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 56F5916F83A; Fri, 21 Jun 2024 07:53:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.88 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956404; cv=fail; b=UiHMUVaFezlZVYfxrxo2La0NtblcOYqGr9HCYu/s9QI1kjd87KpKz73yq4sULsINixtoS7jaZJ2HWk62ZdXXiqu/gPN07p/gOuSmNn5kBasTH9ntJ3cgXUq+gni2m3mrlT2PoE9XRP7DtsMbT81LlCK0YDnbPGaN9ooJP7PA1qU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956404; c=relaxed/simple; bh=nYIXh+KV3afaE+npdoiFIm7rfdWDtKxn1knZXX3/1Hw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=q2ZaH5gPWCa1hLpEc/gDf2LT5pk+L3Z1IS62zbdEf1vPw2V69w1cNi6WWMiGHSQvQpclJwzBt5UqwXgG/VH8UsPPihGpWTEMqZl619QM1UMAFUwJKsECszjB0b4TLdEQwPlfMZcNN7f8P78aZUrqplUn2ScDoLh7be6GfYefAPg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=k0chNcNk; arc=fail smtp.client-ip=40.107.8.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="k0chNcNk" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RWg/sb9i8WAQuoJPdGOtehBeEt550c1rLNqGJgzKIOtrU6veSx+YuFBfNDFw5wBwIeTn0kRMJFOX+gOuc5MsZ528fqghGo88jehDVfNQWm/giloQ32TVex4TPWCIKPSvYFZ6o7XoEvGPDNrq02AecjVVFKVgMnPmnNnKIV7/f7zKhWgW71UGSOoCazxm1GUvLMkbrBhhKFCF3DJg3LVtIYaJGdxIwsFULYx6UrluvpCt8nl35bUCacyBBeJR9S9RDpyEadm7qr2J7MS6TAS9oYx1cYLgDatMc9e2B95YOmhqAAcEmkEX4jQfmnHI6txIQDi3sXcnsKEUIQEJpbHWbw== 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=agxeHZK2Yp1egKAbGyZVuezTi7XhfygTMg6OVAxThxQ=; b=C2LYd5sNUgAUOkmY2JfQwBAq/aR0TcOO0qG4974OvNbARoeYjt5PQUoSfMYBToR6+0LDDhz4RPeYNR03BDlhY4MQhIb9tLgEM90HW/b47vgenaOVf9hcoMIJk2Mt/8UY7rNGykxhq0hznrFRXIi8d/ItFkY3hXFFQdFUBOQ3ZNixsh7hgLt5anHuFa/oiATNJpPdBXqTf+5ZFOT9NeNh9GNyDdfGw8Sr5hkbKu9XDwVOVynCu0GCjnPauXu/VTZeO6QO9Qg3ndEtojNThaFUo1G02Meb0Q1CWpDEhUoZYEVDaRc2kAukdRqbdtdZAcAtaiyQYZg/jGjdZpP7GZHwMg== 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=agxeHZK2Yp1egKAbGyZVuezTi7XhfygTMg6OVAxThxQ=; b=k0chNcNkgQz2LOV4oCQDgrA+snvkhyp9B12FA111HVCzO2TZq0OWo3LBs1a+WzdVf8lACFkRWY6ieiLBo8C0IpeQNdxkclUB+BG1ZV+MhFGuM49uzAXB7iKiBfbURTZw5Nsh3GXHKJV0rscBa6DRvg/YmRUjXhbfNg/qXpTAjw8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:18 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:18 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 13/43] wifi: nxpwifi: add cmdevt.c Date: Fri, 21 Jun 2024 15:51:38 +0800 Message-Id: <20240621075208.513497-14-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: b974e882-89cc-4884-d98f-08dc91c73600 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?dv7XZ31gJVo0XoKUUT8LT2l1V/HYv/uHd014L68ePRvz9OoZ9eNE+UotG6bJ?= =?us-ascii?Q?bmAGB/o/RoXw38k114sddIWi/BFCALFPaEi83mf6IuAbSrJzJyMB9mKgpAOM?= =?us-ascii?Q?DRgGCVZ9pmbYsOcMKjGj3GbdAyti8//DdV1+TKM6DwdfpmKpow6B/K896uti?= =?us-ascii?Q?HrTUrQQgRWUYmPw1vS+0TehgiRKLjmDQRL9Auf+l2j+vdTQCnQqC33g9vU1c?= =?us-ascii?Q?JT+OYCEywZeOuhdjHTMZoAZ7dI9WXYdelwHywHkFBFmfStSQGPNHZlPfNbPv?= =?us-ascii?Q?pSSD/qbC3/cqMyUt3Lw5UV5MZ1wMUEx+Y5QK8zMAaRWguBgq372tqKOxgvqM?= =?us-ascii?Q?Ne6QqsagCM1Gm1M/Bynu6TeE3rDD4g33WQxhIo8vNCcTkLFMJeMTzy2SJxaQ?= =?us-ascii?Q?MXSHdfBxAHJRdkq5K14+oxp7aIkkff7pfaO7Rt05i0hmsodKW9QmVrSPUZQs?= =?us-ascii?Q?IEnALq6IPNRHWEX8vOHcL4trTJe20wJcWYygn1o2Z17TWNkbuxb0YOQENIt9?= =?us-ascii?Q?DEqEdc1FltqptfNC0KKq/Ot2NE2AmBZ5KdZBn25Wup/BFP4X92xvGkpWUFNd?= =?us-ascii?Q?DCEuNMa2Q3yzLXbIQEs7PoaxocCdGsdOXT9l3wzQOlw3CRWcUynv54gMoP+q?= =?us-ascii?Q?WBDFOahQW4crfIdaLqhDyBl0JUXVwTfbVPzepLYY5t+dgtxI2IKx3+CoJk56?= =?us-ascii?Q?oggb52aibpyT2yHFFAuwfHcba6ww7bgQt4gBmZInW7HYK+LzKMRXlJFVj+uF?= =?us-ascii?Q?BPg+WlLRZ69KaBkY9vziiFYfclK4+YAvSonlPTK2A0esfGGV1OHCBu+kUIiT?= =?us-ascii?Q?OtOGigV3HfwblCISiHdvUZVQypuR607T9XIAJsa1FD8oVU6mpLtGixcVANKh?= =?us-ascii?Q?Sk3a5Pnhatufl17gYvAUGwXrxUjgFJdUxGwY1ippYzpQJNhqbikyB3MoKttG?= =?us-ascii?Q?yeF5Ubaoqbrmk63rALLtT7rGs+9EgEEpmpwTmqI7niD6oZ0ppyJL+7MKxpyZ?= =?us-ascii?Q?VRReZydvBka4MsGKA3WnkdUrUB/4XaJMvnCLItVBlmoHc+ju7+hhJNQmiZhb?= =?us-ascii?Q?6OUVXHTAlTOmYfjH4uwtitfjjS2VZ6XX5VBVpMPD40ei70hHiTPzTypPLF0U?= =?us-ascii?Q?Vznk97HZMd7n1LEgLLCfxl8A1D1qbMrs0Qba1R/gK2fyPkpH4MzHUhqg3PcS?= =?us-ascii?Q?/ZQ/obuM/5PmZ/xPZa3elPE8NAgVHlEBBccvYEgqx7z2I7UACscQG9It4ym+?= =?us-ascii?Q?C9kMimt6Z2u8NAdosNy41QaJKq+nkZ3a+79yV50xElnBd3iZuYx3LM7HVOR4?= =?us-ascii?Q?LKfaV0PxZsAiugz141K02oVeX913OHbQ1jdAFd/MRCel05v+0at5hh0LvAzl?= =?us-ascii?Q?l83Mlxo=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?ZJLBsu2+9CCGbIoy8UcvQcqsq++oOT3gLqyy8q357QQhatTEjfDjHF5nlrFp?= =?us-ascii?Q?e8vPs51PuIXQoscGW9Vr0xQsAyHtZpHNyv6cHsosbosmw/IfDw3389MnRRGc?= =?us-ascii?Q?/574M2l7rfBfyK5XNOMPpXlxObpAsW5QdvnBL6U0/NPadNrwr5yjrXAZOgNK?= =?us-ascii?Q?d/oo4p3dMBnvBu7Xn3unQYqvUWtnLfJ/AFj6AV2p5KB1pS/HNz7jZEqka9ez?= =?us-ascii?Q?DxkPMvoAb08er9Voah2RTq3JnydJ++ySm32kykG/hofbBMympLTd7PlZ9eT/?= =?us-ascii?Q?+Sb1hk6hjuZpWoJIImY4ikMKZnHcQXcuFoG9fb2e3rnGbUt3pziDfDeWtEZu?= =?us-ascii?Q?1RGYS0/CE3OW76w/0ngYF8HKsE13Dq8o6qeHp4Odq+rQeZM4Ghv9nvDXfm4N?= =?us-ascii?Q?S+AzrRg852u6AdWeMdkH9kxdZBrL1sBN8RyYLlGbUN1xDUs1dDnF+QwAhf67?= =?us-ascii?Q?rNXzjR11oNZabtZRp87WiNoxqtBqgZTh2bZ3mgzzmMmLMevAAIKw18Zn5VXf?= =?us-ascii?Q?kYRLyI4tzIF5gIVX+tMizgskV55jS+RqBrV9A++/lQlEVuDJ9Rz+9WkRmTG1?= =?us-ascii?Q?Jik03tB3rz5+wMQDy2FpKDWP3h0n+NmFpI5M4S/czPugocnW1hLIr4HNybM+?= =?us-ascii?Q?r/12NdhYWU6q6/xQ2VsiWIqUkpBzOMe1rc4MEnih17or9tWfBAJtJ3wNt43u?= =?us-ascii?Q?TTED8ZbS2m3cpofGphcTYfDJGo2K47V67vkWifbYhaXNTrqfJiVhZ2K3BcoH?= =?us-ascii?Q?HLxlI77l96R2MTEOvE4J3C1AtHl9ndB31JIY6RcSXL/l+QzHSlOiQ7ZutbJe?= =?us-ascii?Q?2CTgGCsHshu8S4nPztC6CYdfiVQsqFiv32eAZtpt9C5pF4iKfB/BCfu4/YAI?= =?us-ascii?Q?n9+gCxAwhsKS2o6ZyLJdTWEEDXd3BEalzwts418lc3mNY3EgBA97gnOU1B9U?= =?us-ascii?Q?KAUpfrnUjpre7NU9yyNtbe9ztH5lGAvPlQ7jaZBcUeXyKwV8PAVuEUARVoIa?= =?us-ascii?Q?FkOf+vR2VeWtDZOs8rUu3K8IQDxyiaKBW4EjvxW6hs3bSZruHdK2R1I5bgaK?= =?us-ascii?Q?HQMNNhT1suOcmWb6ehABunQp1+F/uTR9ldFupTrLeDylo+jjj6n00hNXb4/N?= =?us-ascii?Q?5gz5nz0EXv5Gve1DWz7tLvpkWIyxZCZ7ooR/t+gD1JyKLhhc8lXZRAaVp3rE?= =?us-ascii?Q?tLzvNuMdmc78eSTAtVcl/ZLgBCwwaaR31bcNyK8OjkO31DyqgshpreqvrYPS?= =?us-ascii?Q?MntPNRjc/lOt2OD4iUWTua9Scsplv/2F3ZsN97YLGHKK7YdirnrgKDF2431+?= =?us-ascii?Q?T8lfTlDoQcyak1G8iYXpZ81Djmp4V9UJoecVi9KJ5T0Dxl6W5ol0daS6y/kZ?= =?us-ascii?Q?JFvXMOf/2JTCOIpblkLWWNAuBGLgQ/y0oEynOdyeWvkv6QYaL0dypRIwihp5?= =?us-ascii?Q?mKUb8kt7UjMHcsZliYKAR+ybzxCDMXM6uLiC+yh1EoGSS+Mnod+Sj0wyKTaA?= =?us-ascii?Q?7K18LZWSyGlHICPcQtgJIr6v/fgnFEd1CaKgHe+HVDWjmkBPp38bxEv5IMN5?= =?us-ascii?Q?L+snvm2wIhP0V7UdfWQZxGeVsaO16J27JQE7AXCW?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: b974e882-89cc-4884-d98f-08dc91c73600 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:18.0955 (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: KP7BjGxK/uBvlXdd4uArGLOGuwEaU3a93XPxdV2QE/snvHfErLZWLzHOIdjERgNREundYp1U/bdT334KJxayog== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/cmdevt.c | 1285 +++++++++++++++++++++ 1 file changed, 1285 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/cmdevt.c diff --git a/drivers/net/wireless/nxp/nxpwifi/cmdevt.c b/drivers/net/wirele= ss/nxp/nxpwifi/cmdevt.c new file mode 100644 index 000000000000..fd05a1ecd127 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/cmdevt.c @@ -0,0 +1,1285 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: commands and events + * + * Copyright 2011-2024 NXP + */ + +#include +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" + +static void nxpwifi_cancel_pending_ioctl(struct nxpwifi_adapter *adapter); + +/* This function initializes a command node. + * + * The actual allocation of the node is not done by this function. It only + * initiates a node by filling it with default parameters. Similarly, + * allocation of the different buffers used (IOCTL buffer, data buffer) are + * not done by this function either. + */ +static void +nxpwifi_init_cmd_node(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node, + u32 cmd_no, void *data_buf, bool sync) +{ + cmd_node->priv =3D priv; + cmd_node->cmd_no =3D cmd_no; + + if (sync) { + cmd_node->wait_q_enabled =3D true; + cmd_node->cmd_wait_q_woken =3D false; + cmd_node->condition =3D &cmd_node->cmd_wait_q_woken; + } + cmd_node->data_buf =3D data_buf; + cmd_node->cmd_skb =3D cmd_node->skb; + cmd_node->cmd_resp =3D NULL; +} + +/* This function returns a command node from the free queue depending upon + * availability. + */ +static struct cmd_ctrl_node * +nxpwifi_get_cmd_node(struct nxpwifi_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node; + + spin_lock_bh(&adapter->cmd_free_q_lock); + if (list_empty(&adapter->cmd_free_q)) { + nxpwifi_dbg(adapter, ERROR, + "GET_CMD_NODE: cmd node not available\n"); + spin_unlock_bh(&adapter->cmd_free_q_lock); + return NULL; + } + cmd_node =3D list_first_entry(&adapter->cmd_free_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_bh(&adapter->cmd_free_q_lock); + + return cmd_node; +} + +/* This function cleans up a command node. + * + * The function resets the fields including the buffer pointers. + * This function does not try to free the buffers. They must be + * freed before calling this function. + * + * This function will however call the receive completion callback + * in case a response buffer is still available before resetting + * the pointer. + */ +static void +nxpwifi_clean_cmd_node(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + cmd_node->cmd_no =3D 0; + cmd_node->cmd_flag =3D 0; + cmd_node->data_buf =3D NULL; + cmd_node->wait_q_enabled =3D false; + + if (cmd_node->cmd_skb) + skb_trim(cmd_node->cmd_skb, 0); + + if (cmd_node->resp_skb) { + adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb); + cmd_node->resp_skb =3D NULL; + } +} + +/* This function returns a command to the command free queue. + * + * The function also calls the completion callback if required, before + * cleaning the command node and re-inserting it into the free queue. + */ +static void +nxpwifi_insert_cmd_to_free_q(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + if (!cmd_node) + return; + + if (cmd_node->wait_q_enabled) + nxpwifi_complete_cmd(adapter, cmd_node); + /* Clean the node */ + nxpwifi_clean_cmd_node(adapter, cmd_node); + + /* Insert node into cmd_free_q */ + spin_lock_bh(&adapter->cmd_free_q_lock); + list_add_tail(&cmd_node->list, &adapter->cmd_free_q); + spin_unlock_bh(&adapter->cmd_free_q_lock); +} + +/* This function reuses a command node. */ +void nxpwifi_recycle_cmd_node(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + struct host_cmd_ds_command *host_cmd =3D (void *)cmd_node->cmd_skb->data; + + nxpwifi_insert_cmd_to_free_q(adapter, cmd_node); + + atomic_dec(&adapter->cmd_pending); + nxpwifi_dbg(adapter, CMD, + "cmd: FREE_CMD: cmd=3D%#x, cmd_pending=3D%d\n", + le16_to_cpu(host_cmd->command), + atomic_read(&adapter->cmd_pending)); +} + +/* This function sends a host command to the firmware. + * + * The function copies the host command into the driver command + * buffer, which will be transferred to the firmware later by the + * main thread. + */ +static int nxpwifi_cmd_host_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node) +{ + struct host_cmd_ds_command *cmd; + struct nxpwifi_ds_misc_cmd *pcmd_ptr; + + cmd =3D (struct host_cmd_ds_command *)cmd_node->skb->data; + pcmd_ptr =3D (struct nxpwifi_ds_misc_cmd *)cmd_node->data_buf; + + /* Copy the HOST command to command buffer */ + memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len); + nxpwifi_dbg(priv->adapter, CMD, + "cmd: host cmd size =3D %d\n", pcmd_ptr->len); + return 0; +} + +/* This function downloads a command to the firmware. + * + * The function performs sanity tests, sets the command sequence + * number and size, converts the header fields to CPU format before + * sending. Afterwards, it logs the command ID and action for debugging + * and sets up the command timeout timer. + */ +static int nxpwifi_dnld_cmd_to_fw(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + struct host_cmd_ds_command *host_cmd; + u16 cmd_code; + u16 cmd_size; + + if (!adapter || !cmd_node) + return -1; + + host_cmd =3D (struct host_cmd_ds_command *)(cmd_node->cmd_skb->data); + + /* Sanity test */ + if (host_cmd->size =3D=3D 0) { + nxpwifi_dbg(adapter, ERROR, + "DNLD_CMD: host_cmd is null\t" + "or cmd size is 0, not sending\n"); + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status =3D -1; + nxpwifi_recycle_cmd_node(adapter, cmd_node); + return -1; + } + + cmd_code =3D le16_to_cpu(host_cmd->command); + cmd_node->cmd_no =3D cmd_code; + cmd_size =3D le16_to_cpu(host_cmd->size); + + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_RESET && + cmd_code !=3D HOST_CMD_FUNC_SHUTDOWN && + cmd_code !=3D HOST_CMD_FUNC_INIT) { + nxpwifi_dbg(adapter, ERROR, + "DNLD_CMD: FW in reset state, ignore cmd %#x\n", + cmd_code); + nxpwifi_recycle_cmd_node(adapter, cmd_node); + queue_work(adapter->workqueue, &adapter->main_work); + return -1; + } + + /* Set command sequence number */ + adapter->seq_num++; + host_cmd->seq_num =3D cpu_to_le16(HOST_SET_SEQ_NO_BSS_INFO + (adapter->seq_num, + cmd_node->priv->bss_num, + cmd_node->priv->bss_type)); + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->curr_cmd =3D cmd_node; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + /* Adjust skb length */ + if (cmd_node->cmd_skb->len > cmd_size) + /* cmd_size is less than sizeof(struct host_cmd_ds_command). + * Trim off the unused portion. + */ + skb_trim(cmd_node->cmd_skb, cmd_size); + else if (cmd_node->cmd_skb->len < cmd_size) + /* cmd_size is larger than sizeof(struct host_cmd_ds_command) + * because we have appended custom IE TLV. Increase skb length + * accordingly. + */ + skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); + + nxpwifi_dbg(adapter, CMD, + "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", + cmd_code, + get_unaligned_le16((u8 *)host_cmd + S_DS_GEN), + cmd_size, le16_to_cpu(host_cmd->seq_num)); + nxpwifi_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size); + + skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len); + ret =3D adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_CMD, + cmd_node->cmd_skb, NULL); + skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len); + + if (ret =3D=3D -1) { + nxpwifi_dbg(adapter, ERROR, + "DNLD_CMD: host to card failed\n"); + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status =3D -1; + nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->curr_cmd =3D NULL; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + adapter->dbg.num_cmd_host_to_card_failure++; + return -1; + } + + /* Save the last command id and action to debug log */ + adapter->dbg.last_cmd_index =3D + (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; + adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] =3D cmd_code; + adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =3D + get_unaligned_le16((u8 *)host_cmd + S_DS_GEN); + + /* Setup the timer after transmit command, except that specific + * command might not have command response. + */ + if (cmd_code !=3D HOST_CMD_FW_DUMP_EVENT) + mod_timer(&adapter->cmd_timer, + jiffies + msecs_to_jiffies(NXPWIFI_TIMER_10S)); + + /* Clear BSS_NO_BITS from HOST */ + cmd_code &=3D HOST_CMD_ID_MASK; + + return 0; +} + +/* This function downloads a sleep confirm command to the firmware. + * + * The function performs sanity tests, sets the command sequence + * number and size, converts the header fields to CPU format before + * sending. + * + * No responses are needed for sleep confirm command. + */ +static int nxpwifi_dnld_sleep_confirm_cmd(struct nxpwifi_adapter *adapter) +{ + int ret; + struct nxpwifi_private *priv; + struct nxpwifi_opt_sleep_confirm *sleep_cfm_buf =3D + (struct nxpwifi_opt_sleep_confirm *) + adapter->sleep_cfm->data; + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + adapter->seq_num++; + sleep_cfm_buf->seq_num =3D + cpu_to_le16(HOST_SET_SEQ_NO_BSS_INFO + (adapter->seq_num, priv->bss_num, + priv->bss_type)); + + nxpwifi_dbg(adapter, CMD, + "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", + le16_to_cpu(sleep_cfm_buf->command), + le16_to_cpu(sleep_cfm_buf->action), + le16_to_cpu(sleep_cfm_buf->size), + le16_to_cpu(sleep_cfm_buf->seq_num)); + nxpwifi_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf, + le16_to_cpu(sleep_cfm_buf->size)); + + skb_push(adapter->sleep_cfm, adapter->intf_hdr_len); + ret =3D adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_CMD, + adapter->sleep_cfm, NULL); + skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len); + + if (ret =3D=3D -1) { + nxpwifi_dbg(adapter, ERROR, "SLEEP_CFM: failed\n"); + adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; + return -1; + } + + if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) + /* Response is not needed for sleep confirm command */ + adapter->ps_state =3D PS_STATE_SLEEP; + else + adapter->ps_state =3D PS_STATE_SLEEP_CFM; + + if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && + (test_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags) && + !adapter->sleep_period.period)) { + adapter->pm_wakeup_card_req =3D true; + nxpwifi_hs_activated_event(nxpwifi_get_priv + (adapter, NXPWIFI_BSS_ROLE_ANY), true); + } + + return ret; +} + +/* This function allocates the command buffers and links them to + * the command free queue. + * + * The driver uses a pre allocated number of command buffers, which + * are created at driver initializations and freed at driver cleanup. + * Every command needs to obtain a command buffer from this pool before + * it can be issued. The command free queue lists the command buffers + * currently free to use, while the command pending queue lists the + * command buffers already in use and awaiting handling. Command buffers + * are returned to the free queue after use. + */ +int nxpwifi_alloc_cmd_buffer(struct nxpwifi_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_array; + u32 i; + + /* Allocate and initialize struct cmd_ctrl_node */ + cmd_array =3D kcalloc(NXPWIFI_NUM_OF_CMD_BUFFER, + sizeof(struct cmd_ctrl_node), GFP_KERNEL); + if (!cmd_array) + return -ENOMEM; + + adapter->cmd_pool =3D cmd_array; + + /* Allocate and initialize command buffers */ + for (i =3D 0; i < NXPWIFI_NUM_OF_CMD_BUFFER; i++) { + cmd_array[i].skb =3D dev_alloc_skb(NXPWIFI_SIZE_OF_CMD_BUFFER); + if (!cmd_array[i].skb) + return -ENOMEM; + } + + for (i =3D 0; i < NXPWIFI_NUM_OF_CMD_BUFFER; i++) + nxpwifi_insert_cmd_to_free_q(adapter, &cmd_array[i]); + + return 0; +} + +/* This function frees the command buffers. + * + * The function calls the completion callback for all the command + * buffers that still have response buffers associated with them. + */ +void nxpwifi_free_cmd_buffer(struct nxpwifi_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_array; + u32 i; + + /* Need to check if cmd pool is allocated or not */ + if (!adapter->cmd_pool) { + nxpwifi_dbg(adapter, FATAL, + "info: FREE_CMD_BUF: cmd_pool is null\n"); + return; + } + + cmd_array =3D adapter->cmd_pool; + + /* Release shared memory buffers */ + for (i =3D 0; i < NXPWIFI_NUM_OF_CMD_BUFFER; i++) { + if (cmd_array[i].skb) { + nxpwifi_dbg(adapter, CMD, + "cmd: free cmd buffer %d\n", i); + dev_kfree_skb_any(cmd_array[i].skb); + } + if (!cmd_array[i].resp_skb) + continue; + + dev_kfree_skb_any(cmd_array[i].resp_skb); + } + /* Release struct cmd_ctrl_node */ + if (adapter->cmd_pool) { + nxpwifi_dbg(adapter, CMD, + "cmd: free cmd pool\n"); + kfree(adapter->cmd_pool); + adapter->cmd_pool =3D NULL; + } +} + +/* This function handles events generated by firmware. + * + * Event body of events received from firmware are not used (though they a= re + * saved), only the event ID is used. Some events are re-invoked by + * the driver, with a new event body. + * + * After processing, the function calls the completion callback + * for cleanup. + */ +int nxpwifi_process_event(struct nxpwifi_adapter *adapter) +{ + int ret, i; + struct nxpwifi_private *priv =3D + nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + struct sk_buff *skb =3D adapter->event_skb; + u32 eventcause; + struct nxpwifi_rxinfo *rx_info; + + if ((adapter->event_cause & EVENT_ID_MASK) =3D=3D EVENT_RADAR_DETECTED) { + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv && nxpwifi_is_11h_active(priv)) { + adapter->event_cause |=3D + ((priv->bss_num & 0xff) << 16) | + ((priv->bss_type & 0xff) << 24); + break; + } + } + } + + eventcause =3D adapter->event_cause; + + /* Save the last event to debug log */ + adapter->dbg.last_event_index =3D + (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; + adapter->dbg.last_event[adapter->dbg.last_event_index] =3D + (u16)eventcause; + + /* Get BSS number and corresponding priv */ + priv =3D nxpwifi_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), + EVENT_GET_BSS_TYPE(eventcause)); + if (!priv) + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + /* Clear BSS_NO_BITS from event */ + eventcause &=3D EVENT_ID_MASK; + adapter->event_cause =3D eventcause; + + if (skb) { + rx_info =3D NXPWIFI_SKB_RXCB(skb); + memset(rx_info, 0, sizeof(*rx_info)); + rx_info->bss_num =3D priv->bss_num; + rx_info->bss_type =3D priv->bss_type; + nxpwifi_dbg_dump(adapter, EVT_D, "Event Buf:", + skb->data, skb->len); + } + + nxpwifi_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause); + + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP) + ret =3D nxpwifi_process_uap_event(priv); + else + ret =3D nxpwifi_process_sta_event(priv); + + adapter->event_cause =3D 0; + adapter->event_skb =3D NULL; + adapter->if_ops.event_complete(adapter, skb); + + return ret; +} + +/* This function prepares a command and send it to the firmware. + * + * Preparation includes - + * - Sanity tests to make sure the card is still present or the FW + * is not reset + * - Getting a new command node from the command free queue + * - Initializing the command node for default parameters + * - Fill up the non-default parameters and buffer pointers + * - Add the command to pending queue + */ +int nxpwifi_send_cmd(struct nxpwifi_private *priv, u16 cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync) +{ + int ret; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct cmd_ctrl_node *cmd_node; + + if (!adapter) { + pr_err("PREP_CMD: adapter is NULL\n"); + return -1; + } + + if (test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: device in suspended state\n"); + return -1; + } + + if (test_bit(NXPWIFI_IS_HS_ENABLING, &adapter->work_flags) && + cmd_no !=3D HOST_CMD_802_11_HS_CFG_ENH) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: host entering sleep state\n"); + return -1; + } + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: card is removed\n"); + return -1; + } + + if (test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: FW is in bad state\n"); + return -1; + } + + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_RESET) { + if (cmd_no !=3D HOST_CMD_FUNC_INIT) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: FW in reset state\n"); + return -1; + } + } + + if (priv->adapter->hs_activated_manually && + cmd_no !=3D HOST_CMD_802_11_HS_CFG_ENH) { + nxpwifi_cancel_hs(priv, NXPWIFI_ASYNC_CMD); + priv->adapter->hs_activated_manually =3D false; + } + + /* Get a new command node */ + cmd_node =3D nxpwifi_get_cmd_node(adapter); + + if (!cmd_node) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: no free cmd node\n"); + return -1; + } + + /* Initialize the command node */ + nxpwifi_init_cmd_node(priv, cmd_node, cmd_no, data_buf, sync); + + if (!cmd_node->cmd_skb) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: no free cmd buf\n"); + return -1; + } + + skb_put_zero(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)); + + /* Prepare command */ + if (cmd_no) { + switch (cmd_no) { + case HOST_CMD_UAP_SYS_CONFIG: + case HOST_CMD_UAP_BSS_START: + case HOST_CMD_UAP_BSS_STOP: + case HOST_CMD_UAP_STA_DEAUTH: + case HOST_CMD_APCMD_SYS_RESET: + case HOST_CMD_APCMD_STA_LIST: + case HOST_CMD_CHAN_REPORT_REQUEST: + case HOST_CMD_ADD_NEW_STATION: + ret =3D nxpwifi_uap_prepare_cmd(priv, cmd_node, + cmd_action, cmd_oid); + break; + default: + ret =3D nxpwifi_sta_prepare_cmd(priv, cmd_node, + cmd_action, cmd_oid); + break; + } + } else { + ret =3D nxpwifi_cmd_host_cmd(priv, cmd_node); + cmd_node->cmd_flag |=3D CMD_F_HOSTCMD; + } + + /* Return error, since the command preparation failed */ + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: cmd %#x preparation failed\n", + cmd_no); + nxpwifi_insert_cmd_to_free_q(adapter, cmd_node); + return -1; + } + + /* Send command */ + if (cmd_no =3D=3D HOST_CMD_802_11_SCAN || + cmd_no =3D=3D HOST_CMD_802_11_SCAN_EXT) { + nxpwifi_queue_scan_cmd(priv, cmd_node); + } else { + nxpwifi_insert_cmd_to_pending_q(adapter, cmd_node); + queue_work(adapter->workqueue, &adapter->main_work); + if (cmd_node->wait_q_enabled) + ret =3D nxpwifi_wait_queue_complete(adapter, cmd_node); + } + + return ret; +} + +/* This function queues a command to the command pending queue. + * + * This in effect adds the command to the command list to be executed. + * Exit PS command is handled specially, by placing it always to the + * front of the command queue. + */ +void +nxpwifi_insert_cmd_to_pending_q(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + struct host_cmd_ds_command *host_cmd =3D NULL; + u16 command; + bool add_tail =3D true; + + host_cmd =3D (struct host_cmd_ds_command *)(cmd_node->cmd_skb->data); + if (!host_cmd) { + nxpwifi_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n"); + return; + } + + command =3D le16_to_cpu(host_cmd->command); + + /* Exit_PS command needs to be queued in the header always. */ + if (command =3D=3D HOST_CMD_802_11_PS_MODE_ENH) { + struct host_cmd_ds_802_11_ps_mode_enh *pm =3D + &host_cmd->params.psmode_enh; + if ((le16_to_cpu(pm->action) =3D=3D DIS_PS) || + (le16_to_cpu(pm->action) =3D=3D DIS_AUTO_PS)) { + if (adapter->ps_state !=3D PS_STATE_AWAKE) + add_tail =3D false; + } + } + + /* Same with exit host sleep cmd, luckily that can't happen at the same t= ime as EXIT_PS */ + if (command =3D=3D HOST_CMD_802_11_HS_CFG_ENH) { + struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg =3D + &host_cmd->params.opt_hs_cfg; + + if (le16_to_cpu(hs_cfg->action) =3D=3D HS_ACTIVATE) + add_tail =3D false; + } + + spin_lock_bh(&adapter->cmd_pending_q_lock); + if (add_tail) + list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); + else + list_add(&cmd_node->list, &adapter->cmd_pending_q); + spin_unlock_bh(&adapter->cmd_pending_q_lock); + + atomic_inc(&adapter->cmd_pending); + nxpwifi_dbg(adapter, CMD, + "cmd: QUEUE_CMD: cmd=3D%#x, cmd_pending=3D%d\n", + command, atomic_read(&adapter->cmd_pending)); +} + +/* This function executes the next command in command pending queue. + * + * This function will fail if a command is already in processing stage, + * otherwise it will dequeue the first command from the command pending + * queue and send to the firmware. + * + * If the device is currently in host sleep mode, any commands, except the + * host sleep configuration command will de-activate the host sleep. For PS + * mode, the function will put the firmware back to sleep if applicable. + */ +int nxpwifi_exec_next_cmd(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + struct cmd_ctrl_node *cmd_node; + int ret =3D 0; + struct host_cmd_ds_command *host_cmd; + + /* Check if already in processing */ + if (adapter->curr_cmd) { + nxpwifi_dbg(adapter, FATAL, + "EXEC_NEXT_CMD: cmd in processing\n"); + return -1; + } + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + /* Check if any command is pending */ + spin_lock_bh(&adapter->cmd_pending_q_lock); + if (list_empty(&adapter->cmd_pending_q)) { + spin_unlock_bh(&adapter->cmd_pending_q_lock); + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + return 0; + } + cmd_node =3D list_first_entry(&adapter->cmd_pending_q, + struct cmd_ctrl_node, list); + + host_cmd =3D (struct host_cmd_ds_command *)(cmd_node->cmd_skb->data); + priv =3D cmd_node->priv; + + if (adapter->ps_state !=3D PS_STATE_AWAKE) { + nxpwifi_dbg(adapter, ERROR, + "%s: cannot send cmd in sleep state,\t" + "this should not happen\n", __func__); + spin_unlock_bh(&adapter->cmd_pending_q_lock); + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + return ret; + } + + list_del(&cmd_node->list); + spin_unlock_bh(&adapter->cmd_pending_q_lock); + + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + ret =3D nxpwifi_dnld_cmd_to_fw(priv, cmd_node); + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + /* Any command sent to the firmware when host is in sleep + * mode should de-configure host sleep. We should skip the + * host sleep configuration command itself though + */ + if (priv && host_cmd->command !=3D + cpu_to_le16(HOST_CMD_802_11_HS_CFG_ENH)) { + if (adapter->hs_activated) { + clear_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags); + nxpwifi_hs_activated_event(priv, false); + } + } + + return ret; +} + +static void +nxpwifi_process_cmdresp_error(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11_ps_mode_enh *pm; + + nxpwifi_dbg(adapter, ERROR, + "CMD_RESP: cmd %#x error, result=3D%#x\n", + resp->command, resp->result); + + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status =3D -1; + + switch (le16_to_cpu(resp->command)) { + case HOST_CMD_802_11_PS_MODE_ENH: + pm =3D &resp->params.psmode_enh; + nxpwifi_dbg(adapter, ERROR, + "PS_MODE_ENH cmd failed: result=3D0x%x action=3D0x%X\n", + resp->result, le16_to_cpu(pm->action)); + break; + case HOST_CMD_802_11_SCAN: + case HOST_CMD_802_11_SCAN_EXT: + nxpwifi_cancel_scan(adapter); + break; + + case HOST_CMD_MAC_CONTROL: + break; + + case HOST_CMD_SDIO_SP_RX_AGGR_CFG: + nxpwifi_dbg(adapter, MSG, + "SDIO RX single-port aggregation Not support\n"); + break; + + default: + break; + } + /* Handling errors here */ + nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->curr_cmd =3D NULL; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); +} + +/* This function handles the command response. + * + * After processing, the function cleans the command node and puts + * it back to the command free queue. + */ +int nxpwifi_process_cmdresp(struct nxpwifi_adapter *adapter) +{ + struct host_cmd_ds_command *resp; + struct nxpwifi_private *priv =3D + nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + int ret =3D 0; + u16 orig_cmdresp_no; + u16 cmdresp_no; + u16 cmdresp_result; + + if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { + resp =3D (struct host_cmd_ds_command *)adapter->upld_buf; + nxpwifi_dbg(adapter, ERROR, + "CMD_RESP: NULL curr_cmd, %#x\n", + le16_to_cpu(resp->command)); + return -1; + } + + resp =3D (struct host_cmd_ds_command *)adapter->curr_cmd->resp_skb->data; + orig_cmdresp_no =3D le16_to_cpu(resp->command); + cmdresp_no =3D (orig_cmdresp_no & HOST_CMD_ID_MASK); + + if (adapter->curr_cmd->cmd_no !=3D cmdresp_no) { + nxpwifi_dbg(adapter, ERROR, + "cmdresp error: cmd=3D0x%x cmd_resp=3D0x%x\n", + adapter->curr_cmd->cmd_no, cmdresp_no); + return -1; + } + /* Now we got response from FW, cancel the command timer */ + del_timer_sync(&adapter->cmd_timer); + clear_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags); + + if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { + /* Copy original response back to response buffer */ + struct nxpwifi_ds_misc_cmd *hostcmd; + u16 size =3D le16_to_cpu(resp->size); + + nxpwifi_dbg(adapter, INFO, + "info: host cmd resp size =3D %d\n", size); + size =3D min_t(u16, size, NXPWIFI_SIZE_OF_CMD_BUFFER); + if (adapter->curr_cmd->data_buf) { + hostcmd =3D adapter->curr_cmd->data_buf; + hostcmd->len =3D size; + memcpy(hostcmd->cmd, resp, size); + } + } + + /* Get BSS number and corresponding priv */ + priv =3D nxpwifi_get_priv_by_id + (adapter, HOST_GET_BSS_NO(le16_to_cpu(resp->seq_num)), + HOST_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); + if (!priv) + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + /* Clear RET_BIT from HOST */ + resp->command =3D cpu_to_le16(orig_cmdresp_no & HOST_CMD_ID_MASK); + + cmdresp_no =3D le16_to_cpu(resp->command); + cmdresp_result =3D le16_to_cpu(resp->result); + + /* Save the last command response to debug log */ + adapter->dbg.last_cmd_resp_index =3D + (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; + adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =3D + orig_cmdresp_no; + + nxpwifi_dbg(adapter, CMD, + "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", + orig_cmdresp_no, cmdresp_result, + le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); + nxpwifi_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp, + le16_to_cpu(resp->size)); + + if (!(orig_cmdresp_no & HOST_RET_BIT)) { + nxpwifi_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n"); + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status =3D -1; + + nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->curr_cmd =3D NULL; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + return -1; + } + + if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { + adapter->curr_cmd->cmd_flag &=3D ~CMD_F_HOSTCMD; + if (cmdresp_result =3D=3D HOST_RESULT_OK && + cmdresp_no =3D=3D HOST_CMD_802_11_HS_CFG_ENH) + ret =3D nxpwifi_ret_802_11_hs_cfg(priv, resp); + } else { + if (resp->result !=3D HOST_RESULT_OK) { + nxpwifi_process_cmdresp_error(priv, resp); + return -1; + } + if (adapter->curr_cmd->cmd_resp) { + void *data_buf =3D adapter->curr_cmd->data_buf; + + ret =3D adapter->curr_cmd->cmd_resp(priv, resp, + cmdresp_no, + data_buf); + } + } + + /* Check init command response */ + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_INITIALIZING) { + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "%s: cmd %#x failed during\t" + "initialization\n", __func__, cmdresp_no); + nxpwifi_init_fw_complete(adapter); + return -1; + } else if (adapter->last_init_cmd =3D=3D cmdresp_no) { + adapter->hw_status =3D NXPWIFI_HW_STATUS_INIT_DONE; + } + } + + if (adapter->curr_cmd) { + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status =3D ret; + + nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->curr_cmd =3D NULL; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + } + + return ret; +} + +void nxpwifi_process_assoc_resp(struct nxpwifi_adapter *adapter) +{ + struct cfg80211_rx_assoc_resp_data assoc_resp =3D { + .uapsd_queues =3D -1, + }; + struct nxpwifi_private *priv =3D + nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA); + + if (priv->assoc_rsp_size) { + assoc_resp.links[0].bss =3D priv->req_bss; + assoc_resp.buf =3D priv->assoc_rsp_buf; + assoc_resp.len =3D priv->assoc_rsp_size; + cfg80211_rx_assoc_resp(priv->netdev, + &assoc_resp); + priv->assoc_rsp_size =3D 0; + } +} + +/* This function handles the timeout of command sending. + * + * It will re-send the same command again. + */ +void +nxpwifi_cmd_timeout_func(struct timer_list *t) +{ + struct nxpwifi_adapter *adapter =3D from_timer(adapter, t, cmd_timer); + struct cmd_ctrl_node *cmd_node; + + set_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags); + if (!adapter->curr_cmd) { + nxpwifi_dbg(adapter, ERROR, + "cmd: empty curr_cmd\n"); + return; + } + cmd_node =3D adapter->curr_cmd; + if (cmd_node) { + adapter->dbg.timeout_cmd_id =3D + adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; + adapter->dbg.timeout_cmd_act =3D + adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; + nxpwifi_dbg(adapter, MSG, + "%s: Timeout cmd id =3D %#x, act =3D %#x\n", __func__, + adapter->dbg.timeout_cmd_id, + adapter->dbg.timeout_cmd_act); + + nxpwifi_dbg(adapter, MSG, + "num_data_h2c_failure =3D %d\n", + adapter->dbg.num_tx_host_to_card_failure); + nxpwifi_dbg(adapter, MSG, + "num_cmd_h2c_failure =3D %d\n", + adapter->dbg.num_cmd_host_to_card_failure); + + nxpwifi_dbg(adapter, MSG, + "is_cmd_timedout =3D %d\n", + test_bit(NXPWIFI_IS_CMD_TIMEDOUT, + &adapter->work_flags)); + nxpwifi_dbg(adapter, MSG, + "num_tx_timeout =3D %d\n", + adapter->dbg.num_tx_timeout); + + nxpwifi_dbg(adapter, MSG, + "last_cmd_index =3D %d\n", + adapter->dbg.last_cmd_index); + nxpwifi_dbg(adapter, MSG, + "last_cmd_id: %*ph\n", + (int)sizeof(adapter->dbg.last_cmd_id), + adapter->dbg.last_cmd_id); + nxpwifi_dbg(adapter, MSG, + "last_cmd_act: %*ph\n", + (int)sizeof(adapter->dbg.last_cmd_act), + adapter->dbg.last_cmd_act); + + nxpwifi_dbg(adapter, MSG, + "last_cmd_resp_index =3D %d\n", + adapter->dbg.last_cmd_resp_index); + nxpwifi_dbg(adapter, MSG, + "last_cmd_resp_id: %*ph\n", + (int)sizeof(adapter->dbg.last_cmd_resp_id), + adapter->dbg.last_cmd_resp_id); + + nxpwifi_dbg(adapter, MSG, + "last_event_index =3D %d\n", + adapter->dbg.last_event_index); + nxpwifi_dbg(adapter, MSG, + "last_event: %*ph\n", + (int)sizeof(adapter->dbg.last_event), + adapter->dbg.last_event); + + nxpwifi_dbg(adapter, MSG, + "data_sent=3D%d cmd_sent=3D%d\n", + adapter->data_sent, adapter->cmd_sent); + + nxpwifi_dbg(adapter, MSG, + "ps_mode=3D%d ps_state=3D%d\n", + adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status =3D -ETIMEDOUT; + nxpwifi_cancel_pending_ioctl(adapter); + } + } + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_INITIALIZING) { + nxpwifi_init_fw_complete(adapter); + return; + } + + if (adapter->if_ops.device_dump) + adapter->if_ops.device_dump(adapter); + + if (adapter->if_ops.card_reset) + adapter->if_ops.card_reset(adapter); +} + +void +nxpwifi_cancel_pending_scan_cmd(struct nxpwifi_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node =3D NULL, *tmp_node; + + /* Cancel all pending scan command */ + spin_lock_bh(&adapter->scan_pending_q_lock); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + cmd_node->wait_q_enabled =3D false; + nxpwifi_insert_cmd_to_free_q(adapter, cmd_node); + } + spin_unlock_bh(&adapter->scan_pending_q_lock); +} + +/* This function cancels all the pending commands. + * + * The current command, all commands in command pending queue and all scan + * commands in scan pending queue are cancelled. All the completion callba= cks + * are called with failure status to ensure cleanup. + */ +void +nxpwifi_cancel_all_pending_cmd(struct nxpwifi_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node =3D NULL, *tmp_node; + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + /* Cancel current cmd */ + if (adapter->curr_cmd && adapter->curr_cmd->wait_q_enabled) { + adapter->cmd_wait_q.status =3D -1; + nxpwifi_complete_cmd(adapter, adapter->curr_cmd); + adapter->curr_cmd->wait_q_enabled =3D false; + /* no recycle probably wait for response */ + } + /* Cancel all pending command */ + spin_lock_bh(&adapter->cmd_pending_q_lock); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->cmd_pending_q, list) { + list_del(&cmd_node->list); + + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status =3D -1; + nxpwifi_recycle_cmd_node(adapter, cmd_node); + } + spin_unlock_bh(&adapter->cmd_pending_q_lock); + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + nxpwifi_cancel_scan(adapter); +} + +/* This function cancels all pending commands that matches with + * the given IOCTL request. + * + * Both the current command buffer and the pending command queue are + * searched for matching IOCTL request. The completion callback of + * the matched command is called with failure status to ensure cleanup. + * In case of scan commands, all pending commands in scan pending queue + * are cancelled. + */ +static void +nxpwifi_cancel_pending_ioctl(struct nxpwifi_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node =3D NULL; + + if (adapter->curr_cmd && + adapter->curr_cmd->wait_q_enabled) { + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + cmd_node =3D adapter->curr_cmd; + /* setting curr_cmd to NULL is quite dangerous, because + * nxpwifi_process_cmdresp checks curr_cmd to be !=3D NULL + * at the beginning then relies on it and dereferences + * it at will + * this probably works since nxpwifi_cmd_timeout_func + * is the only caller of this function and responses + * at that point + */ + adapter->curr_cmd =3D NULL; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + nxpwifi_recycle_cmd_node(adapter, cmd_node); + } + + nxpwifi_cancel_scan(adapter); +} + +/* This function sends the sleep confirm command to firmware, if + * possible. + * + * The sleep confirm command cannot be issued if command response, + * data response or event response is awaiting handling, or if we + * are in the middle of sending a command, or expecting a command + * response. + */ +void +nxpwifi_check_ps_cond(struct nxpwifi_adapter *adapter) +{ + if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) && + !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) + nxpwifi_dnld_sleep_confirm_cmd(adapter); + else + nxpwifi_dbg(adapter, CMD, + "cmd: Delay Sleep Confirm (%s%s%s%s)\n", + (adapter->cmd_sent) ? "D" : "", + atomic_read(&adapter->tx_hw_pending) ? "T" : "", + (adapter->curr_cmd) ? "C" : "", + (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); +} + +/* This function sends a Host Sleep activated event to applications. + * + * This event is generated by the driver, with a blank event body. + */ +void +nxpwifi_hs_activated_event(struct nxpwifi_private *priv, u8 activated) +{ + if (activated) { + if (test_bit(NXPWIFI_IS_HS_CONFIGURED, + &priv->adapter->work_flags)) { + priv->adapter->hs_activated =3D true; + nxpwifi_update_rxreor_flags(priv->adapter, + RXREOR_FORCE_NO_DROP); + nxpwifi_dbg(priv->adapter, EVENT, + "event: hs_activated\n"); + priv->adapter->hs_activate_wait_q_woken =3D true; + wake_up_interruptible(&priv->adapter->hs_activate_wait_q); + } else { + nxpwifi_dbg(priv->adapter, EVENT, + "event: HS not configured\n"); + } + } else { + nxpwifi_dbg(priv->adapter, EVENT, + "event: hs_deactivated\n"); + priv->adapter->hs_activated =3D false; + } +} + +/* This function handles the command response of a Host Sleep configuration + * command. + * + * Handling includes changing the header fields into CPU format + * and setting the current host sleep activation status in driver. + * + * In case host sleep status change, the function generates an event to + * notify the applications. + */ +int nxpwifi_ret_802_11_hs_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg =3D + &resp->params.opt_hs_cfg; + u32 conditions =3D le32_to_cpu(phs_cfg->params.hs_config.conditions); + + if (phs_cfg->action =3D=3D cpu_to_le16(HS_ACTIVATE)) { + nxpwifi_hs_activated_event(priv, true); + goto done; + } else { + nxpwifi_dbg(adapter, CMD, + "cmd: CMD_RESP: HS_CFG cmd reply\t" + " result=3D%#x, conditions=3D0x%x gpio=3D0x%x gap=3D0x%x\n", + resp->result, conditions, + phs_cfg->params.hs_config.gpio, + phs_cfg->params.hs_config.gap); + } + if (conditions !=3D HS_CFG_CANCEL) { + set_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); + } else { + clear_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); + if (adapter->hs_activated) + nxpwifi_hs_activated_event(priv, false); + } + +done: + return 0; +} + +/* This function wakes up the adapter and generates a Host Sleep + * cancel event on receiving the power up interrupt. + */ +void +nxpwifi_process_hs_config(struct nxpwifi_adapter *adapter) +{ + nxpwifi_dbg(adapter, INFO, + "info: %s: auto cancelling host sleep\t" + "since there is interrupt from the firmware\n", + __func__); + + adapter->if_ops.wakeup(adapter); + + if (adapter->hs_activated_manually) { + nxpwifi_cancel_hs(nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY), + NXPWIFI_ASYNC_CMD); + adapter->hs_activated_manually =3D false; + } + + adapter->hs_activated =3D false; + clear_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); + clear_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags); + nxpwifi_hs_activated_event(nxpwifi_get_priv(adapter, + NXPWIFI_BSS_ROLE_ANY), + false); +} +EXPORT_SYMBOL_GPL(nxpwifi_process_hs_config); + +/* This function handles the command response of a sleep confirm command. + * + * The function sets the card state to SLEEP if the response indicates suc= cess. + */ +void +nxpwifi_process_sleep_confirm_resp(struct nxpwifi_adapter *adapter, + u8 *pbuf, u32 upld_len) +{ + struct host_cmd_ds_command *cmd =3D (struct host_cmd_ds_command *)pbuf; + u16 result =3D le16_to_cpu(cmd->result); + u16 command =3D le16_to_cpu(cmd->command); + u16 seq_num =3D le16_to_cpu(cmd->seq_num); + + if (!upld_len) { + nxpwifi_dbg(adapter, ERROR, + "%s: cmd size is 0\n", __func__); + return; + } + + nxpwifi_dbg(adapter, CMD, + "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", + command, result, le16_to_cpu(cmd->size), seq_num); + + /* Update sequence number */ + seq_num =3D HOST_GET_SEQ_NO(seq_num); + /* Clear RET_BIT from HOST */ + command &=3D HOST_CMD_ID_MASK; + + if (command !=3D HOST_CMD_802_11_PS_MODE_ENH) { + nxpwifi_dbg(adapter, ERROR, + "%s: rcvd unexpected resp for cmd %#x, result =3D %x\n", + __func__, command, result); + return; + } + + if (result) { + nxpwifi_dbg(adapter, ERROR, + "%s: sleep confirm cmd failed\n", + __func__); + adapter->pm_wakeup_card_req =3D false; + adapter->ps_state =3D PS_STATE_AWAKE; + return; + } + adapter->pm_wakeup_card_req =3D true; + if (test_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags)) + nxpwifi_hs_activated_event(nxpwifi_get_priv + (adapter, NXPWIFI_BSS_ROLE_ANY), + true); + adapter->ps_state =3D PS_STATE_SLEEP; + cmd->command =3D cpu_to_le16(command); + cmd->seq_num =3D cpu_to_le16(seq_num); +} +EXPORT_SYMBOL_GPL(nxpwifi_process_sleep_confirm_resp); --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2088.outbound.protection.outlook.com [40.107.8.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2014016F8ED; Fri, 21 Jun 2024 07:53:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.88 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956407; cv=fail; b=tZqwRuhx+3juGBZZxqWOVxO4nAJfOWdd+oiQY+CeezGOtpiTayAiyQqA2gZkkPRtZFt7b32cfauEPOjnKnBNvGijKpi90AdYQHrCvIMJqzdH2Bp7I+b8wboHmcZ91baqbhMd6htnuVW/DAgr7Rb/BhbuPt0ZP8E+rMGb3v/J/Dw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956407; c=relaxed/simple; bh=b9BACCGZPUQG3r7U52sbZC9QfzAACODw9hPhs8w41WQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=M1DKAC0iPRNUP2PVOsQ3ojyxTmFJQB9JJCS79mV880VEqJmfVRYXmwNNBhuj6PMA5V638P177Shk7ZRmNgy6TyHQ8RY/+KrUqt+7OJXoBk6XO//RtgVEAnelPa40Z8FgJE/bcjQ7r0Fc+paOy+6z9O3f9NQF1sOOuT5KYljrib8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=IcPFPhpZ; arc=fail smtp.client-ip=40.107.8.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="IcPFPhpZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lXg8Bqq6bL3NUEEnSD5vYlFlk/YV39A3iKG/7a777gmRniq5J2rM7auAGHG8QAyPJJqlxV9Ic0dfrg3s1IRTbAA76xNxMhqjuJtJvWVVtddx/VX7Jz49eAa27bMhWMY6tnjdDHwlQ2z3KNsVRP6IQrHBt0jQS+nLnNbSGQh3JtdXsfRNGI3oBD2oIMqjpjVVHaLL26a6JjYlajsMDl/TeanMs7VhyjJR4+AceSPus8dek6lykWmu3qZ5vB52rt1YV7zbIPorJWR08h87p96Ot5jkGfTY4cJNGTbFoSr8U4gDTSxyfhtyTuqSDyOGARWwNfgDFCRvcKK2xxY5Kr6rHg== 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=4JkUKaNqWRk/Y4SBf1iVQ7Kez44XgXRZzuriAUricH4=; b=UKd1t/PmhOK1ZkaK+tJuEreiS7qg5D5lvFo6m4VtiV6G2fU1Hpu3qYUoCmgV3Ggvx5edxtM8VOMw5OQTo3y53JcTgF54/gLNehe8Pd8mZNu+vbJOY68y6K6Fk96kMAeTkbacwpDL8ZR5Ff/zAoBbVNxAtEb5v4M6RgwV1hLjZkerkpgjXAf2gsTP5snEvxDBHpZ7kaNxlwOsguhFygfW+FA0NnqTNhFNpxX9fQwoGfKzpFNgL0XTt0p7g+ZF4hc3b4S4FwGcplFhENek1vHdTd0NKZIAE5Byd9xz6JBerBk2rqveu8cjdmg/JG9kaLDBag30QsYiru4ipwJ7IEiqdQ== 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=4JkUKaNqWRk/Y4SBf1iVQ7Kez44XgXRZzuriAUricH4=; b=IcPFPhpZe3nrovfvG2D67HqhBga4mL4p5Z2tZtJB4AE3Z3hxmVcwOIzqjTS8LHvbwzPFV3u+D420vnGs5KPsr8s7Ld/ZSG/GWb7lUrON37WewjZA/SQ2B7WhxUGqCKjt1tmjt84oQ1wiVOa8wcPauMLFGiiKSV/DY71UOmEw9Ok= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:21 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:21 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 14/43] wifi: nxpwifi: add cmdevt.h Date: Fri, 21 Jun 2024 15:51:39 +0800 Message-Id: <20240621075208.513497-15-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: f0ae2b74-dfbc-457a-0a3e-08dc91c73834 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?mSK6JQu4bKbkICHHuWLE0y/Irqa/EaKjezw2UFfLQb6LnuH9fX/9+DJP8mOG?= =?us-ascii?Q?yQQt1mZaX49lzaOCvB9ONVwGb9Gqbz9il69D1chaXx4v1oJypNTCsall14qZ?= =?us-ascii?Q?Sbn0XJdTsqaDJ5mGVUFHW89CoHvSzLmMGOrf3wcarThLkbNLKR4ypGTMd9/s?= =?us-ascii?Q?NB9gWzFXJCyF0grZOtfuIKDG6g8uUWlWbr9TN6Z62Ww1Wy+3HdaLJnzaiQW1?= =?us-ascii?Q?SZ0n2dYF1Sh3vqplCZqvt/K0nDh4rlRvn6jQu2EfHZfnNNHlpNXGa2jqPk4f?= =?us-ascii?Q?+5aJTlqREXsVDu8QKpp7xBP80J3E7yTKRYIYa4dpMPNFjF9AsMxLuM9wksZn?= =?us-ascii?Q?0ETu9t7tDxZZkxBsFYntDr6f0EqHx/utml/89qLqd+SIYCitAxNdWyl9R4Qo?= =?us-ascii?Q?PRw0yL0x3Kk/QAPuIAZfyHkukfD1AIl9Zzp/ML4uq+FwjaM2MQqha96zGR4i?= =?us-ascii?Q?SYb5ldUWmBDHMxLiJ+Cf2JsWlwev+MIYMBtdIc6GL25LrPrh3n2utjCaRU8Z?= =?us-ascii?Q?l+md0Xwz2pXgY1ts6DL/6oJFt7HB95hESq2T+6SUT9mLjZ+DpgvQ4urJFPOm?= =?us-ascii?Q?SFXVDYCHQU1cb894DoYu424vDSgwRSXd4nDAJd0lwOI3bS4awTpPcfHiWIBh?= =?us-ascii?Q?2Dz+ffD8EJMUT5KKclkSs7s7vNLuB6brHJjw95MSA+Bhw2SYlJu0WGZ/519R?= =?us-ascii?Q?mTDWZg/VCBSmV5QPQ6+IbsmY8+9ht4rUhhXOz5zRDVj8JnKk34WCAn9l8BLR?= =?us-ascii?Q?aU13mHg7tBeYqxrYeIZ5LJCBCksC7DkMIQqRcylp0cZNGVkMaUpnjrrtY/e3?= =?us-ascii?Q?3l34yeELKy+iyJle49lw1JH+CF0lOfIq8F2n5JiBAtkCV2S1wmGicQE0IXnp?= =?us-ascii?Q?x1cHhra+ZFBhG3yrbslnkeSKpsFnr1KAfA7QvFN2I/czlLgn6a81MikjImm5?= =?us-ascii?Q?g7beH4qub+luC4G9g4RamdNg7mrfw04kTGlYv3A8dDwt1tk6EYa5wemSDqsE?= =?us-ascii?Q?AXoFJ3iuqtaQ12FOFq7Hu4kLZ+bYh2HcKiW7WaUH6S73MAtATsyMqJY2GWuZ?= =?us-ascii?Q?+QcMV0I3P6Hl8iZSE08cb4gEjmRDB1Pm32aHejV3Ob3x3YjsM/YMuk4tcZEy?= =?us-ascii?Q?AB0tLCNWZ4XHTo+MxdJBZ6jX/oZnu3F0ohWBFKdbbGawQqMxf1pUNb9vW5vC?= =?us-ascii?Q?KIEzCeEo7gU6EmTtCo46fiSK3nf3xGcplYbGTn+elPtSBQO4oCxnLv347J3K?= =?us-ascii?Q?78SRuRtNi+PucdT368SWNp85I/j/vdlJSF4xTKFDyXjizflh11wCnAgoQWZu?= =?us-ascii?Q?4UZYeI8Ij9POQEkFr/EfCN+BcGcsGqEkPK/7eoxLFal1IPEax46UE/5+tbc7?= =?us-ascii?Q?HHbBBgI=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?A1vZGR92btf2k3PHIaFB8myFIMlFqmtxoJjK5bHUTPgpHH0becH3Ut6Jvu2M?= =?us-ascii?Q?eOqzbi3cKhQSx63bNe23sm3oCLk56+CecIl02EJo4MYE74iPbA7DD8UOX1AM?= =?us-ascii?Q?qPtIr7FRTVH9ar4H0ICBucGj/X0wL4x27rfclnft8Q66IvZt8PTD8OvVurBi?= =?us-ascii?Q?754jBxzjSBqGpb8IWI47XGdc1khIUJtas12Lj1eZHJQc8FpvZNT1Hb1/5qUv?= =?us-ascii?Q?9GQKMaO2Y3kmd/y34CTxLUnjLAJU/7cPQq9Ru/ENtDoToPlTe2j2K+UQRfS4?= =?us-ascii?Q?sB6+fffvIujoJRuO3V2PqFE5+LfQx/OmAxUAjDwFeSUIvtTSQAOf+xwHU24D?= =?us-ascii?Q?Np/nBQutSpm/lHJDzVPjHaVsP1umACpGiUiwaFA39KM+QzQxoZifWHwme7P3?= =?us-ascii?Q?X/+ybv0h/GyPRv4e8oOWHVkwemgWCjwTMe2e9ZFBMPbqBMI7nPpo3veYAq2S?= =?us-ascii?Q?k2JRr+07rPGBcCFxrtOLrKbmeOHHgL6vzSM6l02oFWTfsudHPyinOGLQTzTT?= =?us-ascii?Q?QRr0mPSgMA6M2DloJMWQHAntcD8gxbF0GvTpVBvdJsNFET8XdC709VNegWEP?= =?us-ascii?Q?17C00BX76fiTMbSuvTrRo2u3ZLioT18+fSzO1pFa8CdPVfKDcVabT/9f93uL?= =?us-ascii?Q?Q8dLPPxNLv7wEGvTtKwmvsnKkraWpCuzh9xvd5zIJCr4PqupPpAv0HfTDrA8?= =?us-ascii?Q?iyWxyAs+9V/NgSo/LmHwX/9muIGah7o1+EfQJO2ThJNCOvPaESugpZLmOTyc?= =?us-ascii?Q?1MGgN9ry9jzXLz81BVF49E+ogZDfkrdKNnIxcH6mjF8zhl7aGRsdbb5oGNAs?= =?us-ascii?Q?k1YEK9Uj7dU2yhxFlT3vDN+O06r6U1zOQYmKfOcJn2BcjDFYzBod6aihQmya?= =?us-ascii?Q?BwdbzF1fpq7VbBvboHfuj0LZ8Mlyv9QR9IFGmUL5BXFpppp+2eSrUGlfflKr?= =?us-ascii?Q?ObXGKdKL9rI9eUhyz0IR0mpq92Tz/2TJu8zgTLWp5uusqa28I/4W8+pSwk3v?= =?us-ascii?Q?svtWym0UPNntvY99os1vW4LlQs0h8SWEYjEWiESpXT5qUy2kZzDu51Yw40g0?= =?us-ascii?Q?tswhsS8IBGNQeFz1frIuj4VeYO/mRlBcc2uBAU1eRvD5qIpCaz5KOlSjlxnV?= =?us-ascii?Q?gmQkJinrdyvv7vw/US80OGFdjpWGXS6GQorK8r/JGkmyrLMBoNiwjfTYePOM?= =?us-ascii?Q?YVAaz3YqwfNiPOVljnq8XYp4NAbkhYmJNTMtOgAp7dOu2j6oQzGcxHgE6O9W?= =?us-ascii?Q?RPQ/Xomb4Fvx72+nTXshINoiJ82vjPYnpMbrIvpKipBDhbMW/iVUmzv0SjFk?= =?us-ascii?Q?2iXQ938eZfuT9IE7QLeOqbH8nunZIvkdjty8G8NeQhQ2tVSpeZDNQrrNOgMz?= =?us-ascii?Q?UPx6Of0DyWp1B2oQ3DCHrfA0uazwu+/lg4rkvonN7yEwG7DXkQg5MUZvXBZC?= =?us-ascii?Q?wt9JrzVc+MaG3OlUuprDUoEdsSEGv/9ddCVM6KFP+omXnW8wJolJL7fEo0ip?= =?us-ascii?Q?iTLqHBTmmBsxJxxdAFFMfplklIftMJ/eNriAOsVi/H9gkM4wURYywht32/+a?= =?us-ascii?Q?59w4w+E3EbWXOBlUTznCCAo/xd4K2c7RCpulWuby?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: f0ae2b74-dfbc-457a-0a3e-08dc91c73834 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:21.0588 (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: 2niKnbYc81inFLBrHjgGJ+/AH3AmwEqgXh7BtYKbq6Jug43rZiZH9luXS/5ulqad8EQXwBXqZ3jPJudsIjaY/Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/cmdevt.h | 92 +++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/cmdevt.h diff --git a/drivers/net/wireless/nxp/nxpwifi/cmdevt.h b/drivers/net/wirele= ss/nxp/nxpwifi/cmdevt.h new file mode 100644 index 000000000000..a7774151fa5d --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/cmdevt.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: commands and events + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_CMD_EVT_H_ +#define _NXPWIFI_CMD_EVT_H_ + +struct nxpwifi_cmd_entry { + u16 cmd_no; + int (*prepare_cmd)(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type); + int (*cmd_resp)(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf); +}; + +struct nxpwifi_evt_entry { + u32 event_cause; + int (*event_handler)(struct nxpwifi_private *priv); +}; + +static inline int +nxpwifi_cmd_fill_head_only(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(cmd_no); + cmd->size =3D cpu_to_le16(S_DS_GEN); + + return 0; +} + +int nxpwifi_send_cmd(struct nxpwifi_private *priv, u16 cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync); +int nxpwifi_sta_prepare_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node, + u16 cmd_action, u32 cmd_oid); +int nxpwifi_dnld_dt_cfgdata(struct nxpwifi_private *priv, + struct device_node *node, const char *prefix); +int nxpwifi_sta_init_cmd(struct nxpwifi_private *priv, u8 first_sta, bool = init); +int nxpwifi_uap_prepare_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node, + u16 cmd_action, u32 type); +int nxpwifi_set_secure_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_config, + struct cfg80211_ap_settings *params); +void nxpwifi_set_ht_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params); +void nxpwifi_set_vht_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params); +void nxpwifi_set_tpc_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params); +void nxpwifi_set_uap_rates(struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params); +void nxpwifi_set_vht_width(struct nxpwifi_private *priv, + enum nl80211_chan_width width, + bool ap_11ac_disable); +void nxpwifi_set_sys_config_invalid_data(struct nxpwifi_uap_bss_param *con= fig); +void nxpwifi_set_wmm_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params); +void nxpwifi_config_uap_11d(struct nxpwifi_private *priv, + struct cfg80211_beacon_data *beacon_data); +void nxpwifi_uap_set_channel(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_chan_def chandef); +int nxpwifi_config_start_uap(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg); + +int nxpwifi_process_event(struct nxpwifi_adapter *adapter); +int nxpwifi_process_sta_event(struct nxpwifi_private *priv); +int nxpwifi_process_uap_event(struct nxpwifi_private *priv); +void nxpwifi_reset_connect_state(struct nxpwifi_private *priv, u16 reason, + bool from_ap); +void nxpwifi_process_multi_chan_event(struct nxpwifi_private *priv, + struct sk_buff *event_skb); +void nxpwifi_process_tx_pause_event(struct nxpwifi_private *priv, + struct sk_buff *event); +void nxpwifi_bt_coex_wlan_param_update_event(struct nxpwifi_private *priv, + struct sk_buff *event_skb); + +#endif /* !_NXPWIFI_CMD_EVT_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2088.outbound.protection.outlook.com [40.107.8.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1D3D16F905; Fri, 21 Jun 2024 07:53:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.88 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956410; cv=fail; b=mTTJuF0fNiN3VJTwyIjNxy6MFfaeIBu9fdMifKISIViuN3I6frG5XvtIHHuKYq2fMaZRyr998bt87kxnJfgqsZ+MHvpJz0I9pypjveIR6eH+gWYNHx4WjDswM2Dbsl/i7uv2X+uRAMrPgRLOrqWzzB5kNZCsAMgAebpR/fU9e2k= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956410; c=relaxed/simple; bh=O9zC7nxARtu8Utgdqb5SDJBsyimkmxezkQ8Z5n74sxU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=bXCE6sftN906nej2hM5RJVNdN/thypZZmG3D1dW/MSQxeTMuVt1Ln0OW0Gu631wUeIBJPsyMA/wFWmRTn73RUpwHkU45Gv4BAnXdIAdsfM6AMhY0piezGBt5sVY8tfyNQjowWQMrxFSLh2cLyi6pkXVZJx3KLFiGpkOogpS+NIY= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=SmhTn203; arc=fail smtp.client-ip=40.107.8.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="SmhTn203" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gfei6jZ+y27l9Rf82Yhzi8Q3XAEDmOSGB6Nsgb5Ba0/EdMQ7VOiz56BM2/5HgJX5YmVDf0gN5Jh7T2v38UrXxqnsu9U8p2an3A4fMg4hUTRpYo7iKf5ExkXDJTedhj/xgZSez4jLBUFlSKZO0rxMHY8M3/iNqgQo4zxMTG8yjtwUFUa1B91rnIMqFX1/hrRFnD2psjOZ9q4fR3LmZbaSnL0Rpa9Ty0czosDQK9aadFuLcMgxUmSa1XaYIF5aMn+BZFeHkoZzXPJf2Gi/xJ8ySQNr9Wen8s2oqmwpmR8IknAJdR9IPvmHHbXZum+FXe41lLFeiItCaMJZjOQzvXcRHQ== 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=KEByDU6kgCIcP2eQUtCGOSVgVUGgLKu8u97PTTe6uJI=; b=TLUcYyDZPB7ErK+egTtafEd/kMXAgKndA/IGZNgIR4boNBTe8N3UUH9wWbvCcJC8syl/sajucfP1R2ghNYIcMGEeq/vH6MwyhPkAHQ5ZxW95j5TtaOlRg+3XiTXaC7zlyf92MW72rCUogA1lENkFr0wk9KXFUy/YjsLZAvOIwuMs/LBKH9Ix8BvzkNiXIVqbe3a9Ni5xkpNKC87h/Vv54iJWvKBybLbKySX/Ywlq+sDI8hA0aJy+hssTuuUvtH8g85jxPmhl3zPXlQCDwg3TVS8bNsHvyOvLPnvT8TKP267yxhwH7D4uARb9Ffpo1U6kGiyj+oR55FFmFohrIS2jIQ== 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=KEByDU6kgCIcP2eQUtCGOSVgVUGgLKu8u97PTTe6uJI=; b=SmhTn203vVWh/vEBrdhEwixSpwo86vvTIPQ94kVh8L4oOKQrK91XEgo0ebE1TXiRuVL9SvIsOk3i1pOoa2B/oqrw0l+VByFfJkBFjYs067WYUfFtdYRIDhNMzXLrI31hvdH5weZKMY1JRoHNWzz7RFZpc6plKZ7PHOQBkCV13Cc= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:24 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:24 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 15/43] wifi: nxpwifi: add debugfs.c Date: Fri, 21 Jun 2024 15:51:40 +0800 Message-Id: <20240621075208.513497-16-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: 8aae8548-26ff-4db6-2a8f-08dc91c739f8 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?h/1tv7PAWrcNXcVQM6/9JdEXmnGLjCFza+/hjN+roZA6XG1VrDkGUbCRw8I1?= =?us-ascii?Q?qPVdq3RDnAt1wyst1fM2O4ksFEfoYFMlS+etAesanxlVajzLzs5A77WzOplv?= =?us-ascii?Q?x+0wtU4y/eyLxwbOaLj88BimQ6mm5nmtfe7/H31QBGfX9oM6Ve9U/v5MzNil?= =?us-ascii?Q?xce8R7jRedZlortPWI3dppuhgBXMUfF45r8NBpq8Y5XpCsXT+7B1UVIBIJFR?= =?us-ascii?Q?gsn3c0Ej3iclt0v9JdvK6kPsGRw6Xd1iSK/V83XWT9uEmoO67Fr+u3xSWwB+?= =?us-ascii?Q?y3s9K30Ye2EMk121UBzwHqF6FQg3mZi4HfBO+hb0RJ9uI6dvOJa2E7RMStLO?= =?us-ascii?Q?lA/zYB+MLQtqSMF4TgFUT7sBNhKKOh2QRb/OvHxBEGL9/vzedehtep5QpYIM?= =?us-ascii?Q?JiDuXBjPw4Mz1p6JZAZXLSylrht8R/HEWrThbnoQ/5jPVnHmQVkzFyK0C/2e?= =?us-ascii?Q?yqtpO+tKXzNjGWFeJT/fktFGtOV/5vkz4+GVu+vWONf+MqyKysMu71oroZEY?= =?us-ascii?Q?pECO6i7BjifowHxVSh4tkU2LQcEwJhANEVL9OMDDtDo5VOWuTSejodMwXdTt?= =?us-ascii?Q?VlSuJ1aAaQiDb8PcYWqkci4rriPDmTEG2IMfqP1gAAqFgVsVOnTmhA3VlYyg?= =?us-ascii?Q?d5rjcrxCkgKJJ3g13qb2txGn90r4L7guTM4xln1OJ1dBN/Jt4dncRcGuOaXt?= =?us-ascii?Q?UvOZAEumCV0aZ8dumLnuWnxWMh/VEr4gfkkCnEBV0vhCw1DFAGDlxs78KeEW?= =?us-ascii?Q?5lZX7qR7djAYzTD14+47/0tP+G8ghfT9z5Qd1VysePmixtG7aER1vqYpPAEE?= =?us-ascii?Q?e7y3wgSvWLPd5Ke8JzsNRDKCO0B7nC1kmK2DgoxmQ4v0pYJR8GPeH5K/CRVz?= =?us-ascii?Q?5dEjTLg4y87bi5B6SafuxBtIEklxluocD0cgQcjCwMGf+YXTWn36jcTMStiY?= =?us-ascii?Q?g30FOxpvOnIka+mNQqd011vF9q1VQ1PEXgkLX3DRhYS6Z2JdMa+RZyjJAmsv?= =?us-ascii?Q?vFKv0zAz1N4bVoGYaZybMep+1hJBJ7a+me9Pzs/jeuOI4EMBqqDXnwsO5KZl?= =?us-ascii?Q?8jbkD2oVJ0B0juthpNwBthm5tzAcGnOauuiMYh7UvS0CQYBQg5mxC5qJzMB1?= =?us-ascii?Q?noOZhXXARnEeQq7iK3NsyMP5d6QN4pOGrZIOFsy7kKEQFCqxqyYINpnulu1V?= =?us-ascii?Q?QDtc5VMwoKYTLcdNQJvV7kH+RFQE0UZ+9S00Uz8M+O1utpRmCH9m1b+hTuzS?= =?us-ascii?Q?I/BlZ2/0ghOAGZ+OVzGgXnc0M/to1DqJXyRGFTSV1farnZX5ee1KxMFwkgiS?= =?us-ascii?Q?LyxfAEEYRLIzDzn/UaP6RmGvCcPGnb/7Av/YUTCLlTUuwIhMm5ISRAloU/A0?= =?us-ascii?Q?jNdB6pw=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?pApfPFKfDvvmg61WZfDpXJnqutV6+FnPSKpt0I/Kvxrx9tUHijQxbZATZ0rI?= =?us-ascii?Q?FzAgmaS1MUly3t1HLuMg+Bo7tsNTipSjDdbwEu2lUO7tLjZ1QtYzFqGymV2F?= =?us-ascii?Q?wkIvU2ex+jGurU5LzJW59aKpyPHH7rhVhYq9KoVkEpnp8HYZ3jUwXZtQb8zh?= =?us-ascii?Q?hE1I9ApqbDLnaHAiuDkUiq4k6YmyS1nsonlGfBz0b3FenFq31t4zCeUYGDwW?= =?us-ascii?Q?RwbAOlmiWDTYfBD90PL4DjGjT4GqlPkSH/4KLnzfZhV9mE5VGDfE2fchEE5H?= =?us-ascii?Q?1Qvdd1iHRhC3Ka5BUVJ0Ir2q5vkVWCI3xY9Ct9HHqf27JBJADnc1wqWyhSk8?= =?us-ascii?Q?kq8jnzKnXkMglw7iYf+4QQE9ThvUiChZvHwzR1UjyqWACmkE9JsBRt04lj2f?= =?us-ascii?Q?mq14RLOY6U++MDSMnyowQYpcFhXXQ0rHcKwNE50n5W1WLgoSAs4YRJyJ/1th?= =?us-ascii?Q?pZEOu0Mi6FvIhx7bjAj4ClCdYHHmfuPnklM6ejlke+GyKl78dhzNLpCJ8F3D?= =?us-ascii?Q?znDzoj8Uk9kBxjlqN08V8k44yCWGXH2B8nZ2iDcw490VJxR4LwUfDjL+9xz6?= =?us-ascii?Q?qlXjV3x1hK84ubl5PE/01O38xywTDh54Qn+ADcFAciFgwW0JpWSZP9aM/pm+?= =?us-ascii?Q?SOMaUtzLYno4LECCU02OIfLbUYM+9oOzyFceBBkB9F5HUjYGWxIazU0KbCEt?= =?us-ascii?Q?qzrl1aNB//E+k1Nlz19l+aF4tSQkwhZFbtV6jEILSTYsqFvI/2jnmkjTAhfZ?= =?us-ascii?Q?HH+55pbh+YTRbJmjoIbl7K3DC1GKaKIYb7jtmnfiUhXdakKo14Domu2q7Ugu?= =?us-ascii?Q?SlLIOX/pmh1bvjjc1bUFZ9ywZ3KO3sFk7Z9ni9Pj/8YsNe7WWB/7qVsYNy3f?= =?us-ascii?Q?imsiq4II85ezmVgn5OeDRw/HVNC7ISyJw0pOZGLIYCsx//suxc7Sc06IAgWr?= =?us-ascii?Q?+YURkeIl+cG8FMMuz5D8Hi6NttGjwLeDoZglyvCUESBDAZ9FNE/o6HRhcAwt?= =?us-ascii?Q?JUv4F4wX5CoUqXCY31SKM0yTWfvJNgCG88yjcnvDtkq+v/DT9/ZLW2QCYWB+?= =?us-ascii?Q?TLxODkbf3XB0/AraXx+hUEwGrzUtxiXYPO4ClL/9673akVlaqAPU+sDxfw+R?= =?us-ascii?Q?oOeEME0S7Q6nDI42E5IGuVXjUQ2pqaWFyn3nGMDvVFDjHgWL53CV6zPMPSGs?= =?us-ascii?Q?/vQvcVqua4N07TZhgDuucMO0HC6UM4+qxeAW5uCDXSr83ifDhAkpJ4NgFRN+?= =?us-ascii?Q?EOsWyakf5MDXAh7F7qaqt/JBNqlx5Ov10Y6qPL8lgRl5foq3z5TLiXocBPjv?= =?us-ascii?Q?c5D3x3Lbi8nQ68bpVSKSnEwG2YBUMoUIIS4jfxgMIDajspSwqaEzPtovgU0k?= =?us-ascii?Q?m+QclqmqCIAf3AOanMo2k2ht7xhbreeGEOz84t1Bxt2x0aiRC8TVE7wmy/jD?= =?us-ascii?Q?b8oQjoj7EUgOE64SY65ZtQs1WQ5U4M2DaxT8rxpUyQgILFC8uQ+Z52XarhDc?= =?us-ascii?Q?MWRhGNCIjAAu1oYGFZEFaZ1MvRu9rC7iXNa9lHiYccSHptxgmj2cQI6lSuHh?= =?us-ascii?Q?ic091r6CmiUGWlS2mGlhxH0qPm/+e2BvmrGFTKUI?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8aae8548-26ff-4db6-2a8f-08dc91c739f8 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:24.2880 (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: kPRyfIbfsdnBjd3X6elSqg7KOv352VyWO63yJOPIyVzZC8hyIFOaxgh0Ud8RKLzkqrNPocKYs4J11YzLkO9GHg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/debugfs.c | 1042 ++++++++++++++++++++ 1 file changed, 1042 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/debugfs.c diff --git a/drivers/net/wireless/nxp/nxpwifi/debugfs.c b/drivers/net/wirel= ess/nxp/nxpwifi/debugfs.c new file mode 100644 index 000000000000..f2c3e5159ff5 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/debugfs.c @@ -0,0 +1,1042 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: debugfs + * + * Copyright 2011-2024 NXP + */ + +#include + +#include "main.h" +#include "cmdevt.h" +#include "11n.h" + +static struct dentry *nxpwifi_dfs_dir; + +static char *bss_modes[] =3D { + "UNSPECIFIED", + "ADHOC", + "STATION", + "AP", + "AP_VLAN", + "WDS", + "MONITOR", + "MESH_POINT", + "P2P_CLIENT", + "P2P_GO", + "P2P_DEVICE", +}; + +/* Proc info file read handler. + * + * This function is called when the 'info' file is opened for reading. + * It prints the following driver related information - + * - Driver name + * - Driver version + * - Driver extended version + * - Interface name + * - BSS mode + * - Media state (connected or disconnected) + * - MAC address + * - Total number of Tx bytes + * - Total number of Rx bytes + * - Total number of Tx packets + * - Total number of Rx packets + * - Total number of dropped Tx packets + * - Total number of dropped Rx packets + * - Total number of corrupted Tx packets + * - Total number of corrupted Rx packets + * - Carrier status (on or off) + * - Tx queue status (started or stopped) + * + * For STA mode drivers, it also prints the following extra - + * - ESSID + * - BSSID + * - Channel + * - Region code + * - Multicast count + * - Multicast addresses + */ +static ssize_t +nxpwifi_info_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + struct net_device *netdev =3D priv->netdev; + struct netdev_hw_addr *ha; + struct netdev_queue *txq; + unsigned long page =3D get_zeroed_page(GFP_KERNEL); + char *p =3D (char *)page, fmt[64]; + struct nxpwifi_bss_info info; + ssize_t ret; + int i =3D 0; + + if (!p) + return -ENOMEM; + + memset(&info, 0, sizeof(info)); + ret =3D nxpwifi_get_bss_info(priv, &info); + if (ret) + goto free_and_exit; + + nxpwifi_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); + + nxpwifi_get_ver_ext(priv, 0); + + p +=3D sprintf(p, "driver_name =3D "); + p +=3D sprintf(p, "\"nxpwifi\"\n"); + p +=3D sprintf(p, "driver_version =3D %s", fmt); + p +=3D sprintf(p, "\nverext =3D %s", priv->version_str); + p +=3D sprintf(p, "\ninterface_name=3D\"%s\"\n", netdev->name); + + if (info.bss_mode >=3D ARRAY_SIZE(bss_modes)) + p +=3D sprintf(p, "bss_mode=3D\"%d\"\n", info.bss_mode); + else + p +=3D sprintf(p, "bss_mode=3D\"%s\"\n", bss_modes[info.bss_mode]); + + p +=3D sprintf(p, "media_state=3D\"%s\"\n", + (!priv->media_connected ? "Disconnected" : "Connected")); + p +=3D sprintf(p, "mac_address=3D\"%pM\"\n", netdev->dev_addr); + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) { + p +=3D sprintf(p, "multicast_count=3D\"%d\"\n", + netdev_mc_count(netdev)); + p +=3D sprintf(p, "essid=3D\"%.*s\"\n", info.ssid.ssid_len, + info.ssid.ssid); + p +=3D sprintf(p, "bssid=3D\"%pM\"\n", info.bssid); + p +=3D sprintf(p, "channel=3D\"%d\"\n", (int)info.bss_chan); + p +=3D sprintf(p, "country_code =3D \"%s\"\n", info.country_code); + p +=3D sprintf(p, "region_code=3D\"0x%x\"\n", + priv->adapter->region_code); + + netdev_for_each_mc_addr(ha, netdev) + p +=3D sprintf(p, "multicast_address[%d]=3D\"%pM\"\n", + i++, ha->addr); + } + + p +=3D sprintf(p, "num_tx_bytes =3D %lu\n", priv->stats.tx_bytes); + p +=3D sprintf(p, "num_rx_bytes =3D %lu\n", priv->stats.rx_bytes); + p +=3D sprintf(p, "num_tx_pkts =3D %lu\n", priv->stats.tx_packets); + p +=3D sprintf(p, "num_rx_pkts =3D %lu\n", priv->stats.rx_packets); + p +=3D sprintf(p, "num_tx_pkts_dropped =3D %lu\n", priv->stats.tx_dropped= ); + p +=3D sprintf(p, "num_rx_pkts_dropped =3D %lu\n", priv->stats.rx_dropped= ); + p +=3D sprintf(p, "num_tx_pkts_err =3D %lu\n", priv->stats.tx_errors); + p +=3D sprintf(p, "num_rx_pkts_err =3D %lu\n", priv->stats.rx_errors); + p +=3D sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) + ? "on" : "off")); + p +=3D sprintf(p, "tx queue"); + for (i =3D 0; i < netdev->num_tx_queues; i++) { + txq =3D netdev_get_tx_queue(netdev, i); + p +=3D sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ? + "stopped" : "started"); + } + p +=3D sprintf(p, "\n"); + + ret =3D simple_read_from_buffer(ubuf, count, ppos, (char *)page, + (unsigned long)p - page); + +free_and_exit: + free_page(page); + return ret; +} + +/* Proc getlog file read handler. + * + * This function is called when the 'getlog' file is opened for reading + * It prints the following log information - + * - Number of multicast Tx frames + * - Number of failed packets + * - Number of Tx retries + * - Number of multicast Tx retries + * - Number of duplicate frames + * - Number of RTS successes + * - Number of RTS failures + * - Number of ACK failures + * - Number of fragmented Rx frames + * - Number of multicast Rx frames + * - Number of FCS errors + * - Number of Tx frames + * - WEP ICV error counts + * - Number of received beacons + * - Number of missed beacons + */ +static ssize_t +nxpwifi_getlog_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + unsigned long page =3D get_zeroed_page(GFP_KERNEL); + char *p =3D (char *)page; + ssize_t ret; + struct nxpwifi_ds_get_stats stats; + + if (!p) + return -ENOMEM; + + memset(&stats, 0, sizeof(stats)); + ret =3D nxpwifi_get_stats_info(priv, &stats); + if (ret) + goto free_and_exit; + + p +=3D sprintf(p, "\n" + "mcasttxframe %u\n" + "failed %u\n" + "retry %u\n" + "multiretry %u\n" + "framedup %u\n" + "rtssuccess %u\n" + "rtsfailure %u\n" + "ackfailure %u\n" + "rxfrag %u\n" + "mcastrxframe %u\n" + "fcserror %u\n" + "txframe %u\n" + "wepicverrcnt-1 %u\n" + "wepicverrcnt-2 %u\n" + "wepicverrcnt-3 %u\n" + "wepicverrcnt-4 %u\n" + "bcn_rcv_cnt %u\n" + "bcn_miss_cnt %u\n", + stats.mcast_tx_frame, + stats.failed, + stats.retry, + stats.multi_retry, + stats.frame_dup, + stats.rts_success, + stats.rts_failure, + stats.ack_failure, + stats.rx_frag, + stats.mcast_rx_frame, + stats.fcs_error, + stats.tx_frame, + stats.wep_icv_error[0], + stats.wep_icv_error[1], + stats.wep_icv_error[2], + stats.wep_icv_error[3], + stats.bcn_rcv_cnt, + stats.bcn_miss_cnt); + + ret =3D simple_read_from_buffer(ubuf, count, ppos, (char *)page, + (unsigned long)p - page); + +free_and_exit: + free_page(page); + return ret; +} + +/* Sysfs histogram file read handler. + * + * This function is called when the 'histogram' file is opened for reading + * It prints the following histogram information - + * - Number of histogram samples + * - Receive packet number of each rx_rate + * - Receive packet number of each snr + * - Receive packet number of each nosie_flr + * - Receive packet number of each signal streath + */ +static ssize_t +nxpwifi_histogram_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + ssize_t ret; + struct nxpwifi_histogram_data *phist_data; + int i, value; + unsigned long page =3D get_zeroed_page(GFP_KERNEL); + char *p =3D (char *)page; + + if (!p) + return -ENOMEM; + + if (!priv || !priv->hist_data) { + ret =3D -EFAULT; + goto free_and_exit; + } + + phist_data =3D priv->hist_data; + + p +=3D sprintf(p, "\n" + "total samples =3D %d\n", + atomic_read(&phist_data->num_samples)); + + p +=3D sprintf(p, + "rx rates (in Mbps): 0=3D1M 1=3D2M 2=3D5.5M 3=3D11M 4=3D6M 5= =3D9M 6=3D12M\n" + "7=3D18M 8=3D24M 9=3D36M 10=3D48M 11=3D54M 12-27=3DMCS0-15(BW20= ) 28-43=3DMCS0-15(BW40)\n"); + + if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) { + p +=3D sprintf(p, + "44-53=3DMCS0-9(VHT:BW20) 54-63=3DMCS0-9(VHT:BW40) 64-73=3DMCS0-9(= VHT:BW80)\n\n"); + } else { + p +=3D sprintf(p, "\n"); + } + + for (i =3D 0; i < NXPWIFI_MAX_RX_RATES; i++) { + value =3D atomic_read(&phist_data->rx_rate[i]); + if (value) + p +=3D sprintf(p, "rx_rate[%02d] =3D %d\n", i, value); + } + + if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) { + for (i =3D NXPWIFI_MAX_RX_RATES; i < NXPWIFI_MAX_AC_RX_RATES; + i++) { + value =3D atomic_read(&phist_data->rx_rate[i]); + if (value) + p +=3D sprintf(p, "rx_rate[%02d] =3D %d\n", + i, value); + } + } + + for (i =3D 0; i < NXPWIFI_MAX_SNR; i++) { + value =3D atomic_read(&phist_data->snr[i]); + if (value) + p +=3D sprintf(p, "snr[%02ddB] =3D %d\n", i, value); + } + for (i =3D 0; i < NXPWIFI_MAX_NOISE_FLR; i++) { + value =3D atomic_read(&phist_data->noise_flr[i]); + if (value) + p +=3D sprintf(p, "noise_flr[%02ddBm] =3D %d\n", + (int)(i - 128), value); + } + for (i =3D 0; i < NXPWIFI_MAX_SIG_STRENGTH; i++) { + value =3D atomic_read(&phist_data->sig_str[i]); + if (value) + p +=3D sprintf(p, "sig_strength[-%02ddBm] =3D %d\n", + i, value); + } + + ret =3D simple_read_from_buffer(ubuf, count, ppos, (char *)page, + (unsigned long)p - page); + +free_and_exit: + free_page(page); + return ret; +} + +static ssize_t +nxpwifi_histogram_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D (void *)file->private_data; + + if (priv && priv->hist_data) + nxpwifi_hist_data_reset(priv); + return 0; +} + +static struct nxpwifi_debug_info info; + +/* Proc debug file read handler. + * + * This function is called when the 'debug' file is opened for reading + * It prints the following log information - + * - Interrupt count + * - WMM AC VO packets count + * - WMM AC VI packets count + * - WMM AC BE packets count + * - WMM AC BK packets count + * - Maximum Tx buffer size + * - Tx buffer size + * - Current Tx buffer size + * - Power Save mode + * - Power Save state + * - Deep Sleep status + * - Device wakeup required status + * - Number of wakeup tries + * - Host Sleep configured status + * - Host Sleep activated status + * - Number of Tx timeouts + * - Number of command timeouts + * - Last timed out command ID + * - Last timed out command action + * - Last command ID + * - Last command action + * - Last command index + * - Last command response ID + * - Last command response index + * - Last event + * - Last event index + * - Number of host to card command failures + * - Number of sleep confirm command failures + * - Number of host to card data failure + * - Number of deauthentication events + * - Number of disassociation events + * - Number of link lost events + * - Number of deauthentication commands + * - Number of association success commands + * - Number of association failure commands + * - Number of commands sent + * - Number of data packets sent + * - Number of command responses received + * - Number of events received + * - Tx BA stream table (TID, RA) + * - Rx reorder table (TID, TA, Start window, Window size, Buffer) + */ +static ssize_t +nxpwifi_debug_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + unsigned long page =3D get_zeroed_page(GFP_KERNEL); + char *p =3D (char *)page; + ssize_t ret; + + if (!p) + return -ENOMEM; + + ret =3D nxpwifi_get_debug_info(priv, &info); + if (ret) + goto free_and_exit; + + p +=3D nxpwifi_debug_info_to_buffer(priv, p, &info); + + ret =3D simple_read_from_buffer(ubuf, count, ppos, (char *)page, + (unsigned long)p - page); + +free_and_exit: + free_page(page); + return ret; +} + +static u32 saved_reg_type, saved_reg_offset, saved_reg_value; + +/* Proc regrdwr file write handler. + * + * This function is called when the 'regrdwr' file is opened for writing + * + * This function can be used to write to a register. + */ +static ssize_t +nxpwifi_regrdwr_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + char *buf; + int ret; + u32 reg_type =3D 0, reg_offset =3D 0, reg_value =3D UINT_MAX; + int rv; + + buf =3D memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + rv =3D sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); + + if (rv !=3D 3) { + ret =3D -EINVAL; + goto done; + } + + if (reg_type =3D=3D 0 || reg_offset =3D=3D 0) { + ret =3D -EINVAL; + goto done; + } else { + saved_reg_type =3D reg_type; + saved_reg_offset =3D reg_offset; + saved_reg_value =3D reg_value; + ret =3D count; + } +done: + kfree(buf); + return ret; +} + +/* Proc regrdwr file read handler. + * + * This function is called when the 'regrdwr' file is opened for reading + * + * This function can be used to read from a register. + */ +static ssize_t +nxpwifi_regrdwr_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + unsigned long addr =3D get_zeroed_page(GFP_KERNEL); + char *buf =3D (char *)addr; + int pos =3D 0, ret =3D 0; + u32 reg_value; + + if (!buf) + return -ENOMEM; + + if (!saved_reg_type) { + /* No command has been given */ + pos +=3D snprintf(buf, PAGE_SIZE, "0"); + goto done; + } + /* Set command has been given */ + if (saved_reg_value !=3D UINT_MAX) { + ret =3D nxpwifi_reg_write(priv, saved_reg_type, saved_reg_offset, + saved_reg_value); + + pos +=3D snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", + saved_reg_type, saved_reg_offset, + saved_reg_value); + + ret =3D simple_read_from_buffer(ubuf, count, ppos, buf, pos); + + goto done; + } + /* Get command has been given */ + ret =3D nxpwifi_reg_read(priv, saved_reg_type, + saved_reg_offset, ®_value); + if (ret) { + ret =3D -EINVAL; + goto done; + } + + pos +=3D snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type, + saved_reg_offset, reg_value); + + ret =3D simple_read_from_buffer(ubuf, count, ppos, buf, pos); + +done: + free_page(addr); + return ret; +} + +/* Proc debug_mask file read handler. + * This function is called when the 'debug_mask' file is opened for reading + * This function can be used read driver debugging mask value. + */ +static ssize_t +nxpwifi_debug_mask_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + unsigned long page =3D get_zeroed_page(GFP_KERNEL); + char *buf =3D (char *)page; + size_t ret =3D 0; + int pos =3D 0; + + if (!buf) + return -ENOMEM; + + pos +=3D snprintf(buf, PAGE_SIZE, "debug mask=3D0x%08x\n", + priv->adapter->debug_mask); + ret =3D simple_read_from_buffer(ubuf, count, ppos, buf, pos); + + free_page(page); + return ret; +} + +/* Proc debug_mask file read handler. + * This function is called when the 'debug_mask' file is opened for reading + * This function can be used read driver debugging mask value. + */ +static ssize_t +nxpwifi_debug_mask_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + int ret; + unsigned long debug_mask; + struct nxpwifi_private *priv =3D (void *)file->private_data; + char *buf; + + buf =3D memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + if (kstrtoul(buf, 0, &debug_mask)) { + ret =3D -EINVAL; + goto done; + } + + priv->adapter->debug_mask =3D debug_mask; + ret =3D count; +done: + kfree(buf); + return ret; +} + +/* debugfs verext file write handler. + * This function is called when the 'verext' file is opened for write + */ +static ssize_t +nxpwifi_verext_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + int ret; + u32 versionstrsel; + struct nxpwifi_private *priv =3D (void *)file->private_data; + + ret =3D kstrtou32_from_user(ubuf, count, 10, &versionstrsel); + if (ret) + return ret; + + priv->versionstrsel =3D versionstrsel; + + return count; +} + +/* Proc verext file read handler. + * This function is called when the 'verext' file is opened for reading + * This function can be used read driver exteneed verion string. + */ +static ssize_t +nxpwifi_verext_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + char buf[256]; + int ret; + + nxpwifi_get_ver_ext(priv, priv->versionstrsel); + ret =3D snprintf(buf, sizeof(buf), "version string: %s\n", + priv->version_str); + + return simple_read_from_buffer(ubuf, count, ppos, buf, ret); +} + +/* Proc memrw file write handler. + * This function is called when the 'memrw' file is opened for writing + * This function can be used to write to a memory location. + */ +static ssize_t +nxpwifi_memrw_write(struct file *file, const char __user *ubuf, size_t cou= nt, + loff_t *ppos) +{ + int ret; + char cmd; + struct nxpwifi_ds_mem_rw mem_rw; + u16 cmd_action; + struct nxpwifi_private *priv =3D (void *)file->private_data; + char *buf; + + buf =3D memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + ret =3D sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value); + if (ret !=3D 3) { + ret =3D -EINVAL; + goto done; + } + + if ((cmd =3D=3D 'r') || (cmd =3D=3D 'R')) { + cmd_action =3D HOST_ACT_GEN_GET; + mem_rw.value =3D 0; + } else if ((cmd =3D=3D 'w') || (cmd =3D=3D 'W')) { + cmd_action =3D HOST_ACT_GEN_SET; + } else { + ret =3D -EINVAL; + goto done; + } + + memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw)); + if (nxpwifi_send_cmd(priv, HOST_CMD_MEM_ACCESS, cmd_action, 0, + &mem_rw, true)) + ret =3D -1; + else + ret =3D count; + +done: + kfree(buf); + return ret; +} + +/* Proc memrw file read handler. + * This function is called when the 'memrw' file is opened for reading + * This function can be used to read from a memory location. + */ +static ssize_t +nxpwifi_memrw_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D (void *)file->private_data; + unsigned long addr =3D get_zeroed_page(GFP_KERNEL); + char *buf =3D (char *)addr; + int ret, pos =3D 0; + + if (!buf) + return -ENOMEM; + + pos +=3D snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr, + priv->mem_rw.value); + ret =3D simple_read_from_buffer(ubuf, count, ppos, buf, pos); + + free_page(addr); + return ret; +} + +static u32 saved_offset =3D -1, saved_bytes =3D -1; + +/* Proc rdeeprom file write handler. + * + * This function is called when the 'rdeeprom' file is opened for writing + * + * This function can be used to write to a RDEEPROM location. + */ +static ssize_t +nxpwifi_rdeeprom_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + char *buf; + int ret =3D 0; + int offset =3D -1, bytes =3D -1; + int rv; + + buf =3D memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + rv =3D sscanf(buf, "%d %d", &offset, &bytes); + + if (rv !=3D 2) { + ret =3D -EINVAL; + goto done; + } + + if (offset =3D=3D -1 || bytes =3D=3D -1) { + ret =3D -EINVAL; + goto done; + } else { + saved_offset =3D offset; + saved_bytes =3D bytes; + ret =3D count; + } +done: + kfree(buf); + return ret; +} + +/* Proc rdeeprom read write handler. + * + * This function is called when the 'rdeeprom' file is opened for reading + * + * This function can be used to read from a RDEEPROM location. + */ +static ssize_t +nxpwifi_rdeeprom_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D + (struct nxpwifi_private *)file->private_data; + unsigned long addr =3D get_zeroed_page(GFP_KERNEL); + char *buf =3D (char *)addr; + int pos, ret, i; + u8 value[MAX_EEPROM_DATA]; + + if (!buf) + return -ENOMEM; + + if (saved_offset =3D=3D -1) { + /* No command has been given */ + pos =3D snprintf(buf, PAGE_SIZE, "0"); + goto done; + } + + /* Get command has been given */ + ret =3D nxpwifi_eeprom_read(priv, (u16)saved_offset, + (u16)saved_bytes, value); + if (ret) { + ret =3D -EINVAL; + goto out_free; + } + + pos =3D snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); + + for (i =3D 0; i < saved_bytes; i++) + pos +=3D scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]); + +done: + ret =3D simple_read_from_buffer(ubuf, count, ppos, buf, pos); +out_free: + free_page(addr); + return ret; +} + +/* Proc hscfg file write handler + * This function can be used to configure the host sleep parameters. + */ +static ssize_t +nxpwifi_hscfg_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D (void *)file->private_data; + char *buf; + int ret, arg_num; + struct nxpwifi_ds_hs_cfg hscfg; + int conditions =3D HS_CFG_COND_DEF; + u32 gpio =3D HS_CFG_GPIO_DEF, gap =3D HS_CFG_GAP_DEF; + + buf =3D memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + arg_num =3D sscanf(buf, "%d %x %x", &conditions, &gpio, &gap); + + memset(&hscfg, 0, sizeof(struct nxpwifi_ds_hs_cfg)); + + if (arg_num > 3) { + nxpwifi_dbg(priv->adapter, ERROR, + "Too many arguments\n"); + ret =3D -EINVAL; + goto done; + } + + if (arg_num >=3D 1 && arg_num < 3) + nxpwifi_set_hs_params(priv, HOST_ACT_GEN_GET, + NXPWIFI_SYNC_CMD, &hscfg); + + if (arg_num) { + if (conditions =3D=3D HS_CFG_CANCEL) { + nxpwifi_cancel_hs(priv, NXPWIFI_ASYNC_CMD); + ret =3D count; + goto done; + } + hscfg.conditions =3D conditions; + } + if (arg_num >=3D 2) + hscfg.gpio =3D gpio; + if (arg_num =3D=3D 3) + hscfg.gap =3D gap; + + hscfg.is_invoke_hostcmd =3D false; + nxpwifi_set_hs_params(priv, HOST_ACT_GEN_SET, + NXPWIFI_SYNC_CMD, &hscfg); + + nxpwifi_enable_hs(priv->adapter); + clear_bit(NXPWIFI_IS_HS_ENABLING, &priv->adapter->work_flags); + ret =3D count; +done: + kfree(buf); + return ret; +} + +/* Proc hscfg file read handler + * This function can be used to read host sleep configuration + * parameters from driver. + */ +static ssize_t +nxpwifi_hscfg_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D (void *)file->private_data; + unsigned long addr =3D get_zeroed_page(GFP_KERNEL); + char *buf =3D (char *)addr; + int pos, ret; + struct nxpwifi_ds_hs_cfg hscfg; + + if (!buf) + return -ENOMEM; + + nxpwifi_set_hs_params(priv, HOST_ACT_GEN_GET, + NXPWIFI_SYNC_CMD, &hscfg); + + pos =3D snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions, + hscfg.gpio, hscfg.gap); + + ret =3D simple_read_from_buffer(ubuf, count, ppos, buf, pos); + + free_page(addr); + return ret; +} + +static ssize_t +nxpwifi_timeshare_coex_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D file->private_data; + char buf[3]; + bool timeshare_coex; + int ret; + unsigned int len; + + if (priv->adapter->fw_api_ver !=3D NXPWIFI_FW_V15) + return -EOPNOTSUPP; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_ROBUST_COEX, + HOST_ACT_GEN_GET, 0, ×hare_coex, true); + if (ret) + return ret; + + len =3D sprintf(buf, "%d\n", timeshare_coex); + return simple_read_from_buffer(ubuf, count, ppos, buf, len); +} + +static ssize_t +nxpwifi_timeshare_coex_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + bool timeshare_coex; + struct nxpwifi_private *priv =3D file->private_data; + int ret; + + if (priv->adapter->fw_api_ver !=3D NXPWIFI_FW_V15) + return -EOPNOTSUPP; + + ret =3D kstrtobool_from_user(ubuf, count, ×hare_coex); + if (ret) + return ret; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_ROBUST_COEX, + HOST_ACT_GEN_SET, 0, ×hare_coex, true); + if (ret) + return ret; + else + return count; +} + +static ssize_t +nxpwifi_reset_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D file->private_data; + struct nxpwifi_adapter *adapter =3D priv->adapter; + bool result; + int rc; + + rc =3D kstrtobool_from_user(ubuf, count, &result); + if (rc) + return rc; + + if (!result) + return -EINVAL; + + if (adapter->if_ops.card_reset) { + dev_info(adapter->dev, "Resetting per request\n"); + adapter->if_ops.card_reset(adapter); + } + + return count; +} + +static ssize_t +nxpwifi_fake_radar_detect_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct nxpwifi_private *priv =3D file->private_data; + struct nxpwifi_adapter *adapter =3D priv->adapter; + bool result; + int rc; + + rc =3D kstrtobool_from_user(ubuf, count, &result); + if (rc) + return rc; + + if (!result) + return -EINVAL; + + if (priv->wdev.cac_started) { + nxpwifi_dbg(adapter, MSG, + "Generate fake radar detected during CAC\n"); + if (nxpwifi_stop_radar_detection(priv, &priv->dfs_chandef)) + nxpwifi_dbg(adapter, ERROR, + "Failed to stop CAC in FW\n"); + cancel_delayed_work_sync(&priv->dfs_cac_work); + cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); + cfg80211_radar_event(adapter->wiphy, &priv->dfs_chandef, + GFP_KERNEL); + } else { + if (priv->bss_chandef.chan->dfs_cac_ms) { + nxpwifi_dbg(adapter, MSG, + "Generate fake radar detected\n"); + cfg80211_radar_event(adapter->wiphy, + &priv->dfs_chandef, + GFP_KERNEL); + } + } + + return count; +} + +#define NXPWIFI_DFS_ADD_FILE(name) debugfs_create_file(#name, 0644, \ + priv->dfs_dev_dir, priv, \ + &nxpwifi_dfs_##name##_fops) + +#define NXPWIFI_DFS_FILE_OPS(name) \ +static const struct file_operations nxpwifi_dfs_##name##_fops =3D { \ + .read =3D nxpwifi_##name##_read, \ + .write =3D nxpwifi_##name##_write, \ + .open =3D simple_open, \ +} + +#define NXPWIFI_DFS_FILE_READ_OPS(name) \ +static const struct file_operations nxpwifi_dfs_##name##_fops =3D { \ + .read =3D nxpwifi_##name##_read, \ + .open =3D simple_open, \ +} + +#define NXPWIFI_DFS_FILE_WRITE_OPS(name) \ +static const struct file_operations nxpwifi_dfs_##name##_fops =3D { \ + .write =3D nxpwifi_##name##_write, \ + .open =3D simple_open, \ +} + +NXPWIFI_DFS_FILE_READ_OPS(info); +NXPWIFI_DFS_FILE_READ_OPS(debug); +NXPWIFI_DFS_FILE_READ_OPS(getlog); +NXPWIFI_DFS_FILE_OPS(regrdwr); +NXPWIFI_DFS_FILE_OPS(rdeeprom); +NXPWIFI_DFS_FILE_OPS(memrw); +NXPWIFI_DFS_FILE_OPS(hscfg); +NXPWIFI_DFS_FILE_OPS(histogram); +NXPWIFI_DFS_FILE_OPS(debug_mask); +NXPWIFI_DFS_FILE_OPS(timeshare_coex); +NXPWIFI_DFS_FILE_WRITE_OPS(reset); +NXPWIFI_DFS_FILE_WRITE_OPS(fake_radar_detect); +NXPWIFI_DFS_FILE_OPS(verext); + +/* This function creates the debug FS directory structure and the files. + */ +void +nxpwifi_dev_debugfs_init(struct nxpwifi_private *priv) +{ + if (!nxpwifi_dfs_dir || !priv) + return; + + priv->dfs_dev_dir =3D debugfs_create_dir(priv->netdev->name, + nxpwifi_dfs_dir); + + NXPWIFI_DFS_ADD_FILE(info); + NXPWIFI_DFS_ADD_FILE(debug); + NXPWIFI_DFS_ADD_FILE(getlog); + NXPWIFI_DFS_ADD_FILE(regrdwr); + NXPWIFI_DFS_ADD_FILE(rdeeprom); + + NXPWIFI_DFS_ADD_FILE(memrw); + NXPWIFI_DFS_ADD_FILE(hscfg); + NXPWIFI_DFS_ADD_FILE(histogram); + NXPWIFI_DFS_ADD_FILE(debug_mask); + NXPWIFI_DFS_ADD_FILE(timeshare_coex); + NXPWIFI_DFS_ADD_FILE(reset); + NXPWIFI_DFS_ADD_FILE(fake_radar_detect); + NXPWIFI_DFS_ADD_FILE(verext); +} + +/* This function removes the debug FS directory structure and the files. + */ +void +nxpwifi_dev_debugfs_remove(struct nxpwifi_private *priv) +{ + if (!priv) + return; + + debugfs_remove_recursive(priv->dfs_dev_dir); +} + +/* This function creates the top level proc directory. + */ +void +nxpwifi_debugfs_init(void) +{ + if (!nxpwifi_dfs_dir) + nxpwifi_dfs_dir =3D debugfs_create_dir("nxpwifi", NULL); +} + +/* This function removes the top level proc directory. + */ +void +nxpwifi_debugfs_remove(void) +{ + debugfs_remove(nxpwifi_dfs_dir); +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2088.outbound.protection.outlook.com [40.107.8.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DF1E316FF36; Fri, 21 Jun 2024 07:53:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.88 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956412; cv=fail; b=jZXzCbMMPbhgnV5WfodLfb93yLKEzDnZEnlRRMHDVIt9H3o8THcMBCAJEQKrrmXSnlaMLpenz+wkGzj9djoD7AGLVbGPwg+dIrZXxyGk/eTkQj5QODhiyUOfHXlq/sYYoj1udHYAO8K7jSZTUSsfD+eBMXVxm0Ir4iXLhBk6blA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956412; c=relaxed/simple; bh=mvA4LH9J4HyE3Bh49/UOaR/HaM8DFdOj9h6R0CtjV80=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=KqTAeCr3/qRuAJpVega7igDcawilFSABs47JfOUSimIumtDNsCboaeyFwqlsOMTZugRLuCnXhGh3IffUHnUySjIZOPYz9pN13uDz2pBTL5naGbLlOeHCFwhGSVDhQVsV0LnGu9fmdMn3jMaev161sYJxLii/8TpeIcugpAHuuTs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=V0u37CUe; arc=fail smtp.client-ip=40.107.8.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="V0u37CUe" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=cX2Nm/y+gxAnQOYvQPvVACPGcIqcTH6WWJVBrPY5P95/r635/7Pn1wJt6TGsX4i4osZYIng9IAXyVecUPVMv9JAHVrQjAa0Q/iTqYDA3TgEuVMIyrTjbgwQVaaRfBreaMtjvzK2Us2rJAhsF2zdO8A2h6/7EE04m692WVwVYPONDjNVzpXhM4f8wlHLVwHhfR+hhsrA1HT9wNTiD1htHFVJswKURwykWEYrqlm8yzfesb8iiyQylcBEsq9nIBkRe6XQltVtNw2NABQGKzklE9X0d5H2gY0BNFOAx7v6xBXnFPT7QYo/d7UyqA90R1/CXlX20nEHA1sOVlw+uNShnmw== 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=I7fLqB4wnyaH6ytFNpYg24/WN+k1D88xA+QUejWYlsw=; b=WI10RFiRaUGzpQXW08iBAEDfjLsot8JyDHzXg8Z3YCwYcuXylmHoX8XEvBNFN/V0+e8ZsvhaIkYP/D0s59F00wmz4ige0kWDSnBS1PyNCJO4vFp3XHOPkmhDZxE+aYIvsijtwlij1DczF+Ds2QU5e9C8zEKNTukeMGZzqWXx02h/5qgsxETc0WJk86YPoPTzY9EP9eMdX0iDpAODW4PCuZSDIHIyk44UyQXaKrqBzrr5jsnlNaXBZXC1sc3qX/Pe4uj4ZmZ1Iv8EM6CKv+7pCpE3qk3sNQVTQiQ3g4XAxu0dy+BRO56TCQ+7QKHfsY+yZ6g6MV3N3EGonGw6TW8Q0g== 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=I7fLqB4wnyaH6ytFNpYg24/WN+k1D88xA+QUejWYlsw=; b=V0u37CUeKkfILMnDWu88rhKtagkbAW7Auwknjj2JQGgntBuyRHPWm5QRe0K7ZaEpLvg7KsWZIDjb7cSd1PfW7Cdqm+L63Xdywbdd86gxI3VM52UhsQfeBnpnWESH2W8NGdY35IKY1pc3yFdPptJ5wx5YGoHcHaoZfVMULkd7gPY= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:27 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:27 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 16/43] wifi: nxpwifi: add decl.h Date: Fri, 21 Jun 2024 15:51:41 +0800 Message-Id: <20240621075208.513497-17-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: be5906c5-b39e-42bc-bb0b-08dc91c73bdd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?vwTIFp9L/AlZe9yE9VcKlvncGmidiWw6dYS2t5ldDBry1SOb++fuLIV3HwGU?= =?us-ascii?Q?PnLGo8GK+L+88BJbWNE4b/jYoUf71196VbnDXD1XWST9zKkjzfnsBGgL/Hub?= =?us-ascii?Q?WF30uOEjyizNZAgqm+H8xACy9XhfxtLQa+F+mlTaPlqnGq3Xcx2FQqzbCZpR?= =?us-ascii?Q?L1RlGyIU11XISfYoeQLRzQh6PIi4iG5R+8Noo9ohkfoMgeLqwAzz0D/+88Be?= =?us-ascii?Q?fpJTsZWy0RCBFvA0NCnTN8lKi8Vvymkpa8/vBctuk4e+fCs7eEVgEaTCEBOk?= =?us-ascii?Q?KpMGYLje7hZkPmin+StfLyCnr5WX8IbOyg6egu73tWtrisbzzdCvrf/DcgR1?= =?us-ascii?Q?ESgfZd5sO/4EcoeAaYMCT0d0w4LFU0HZVtXpWTiM5TgfB2G/V9eRnHY8+5QN?= =?us-ascii?Q?KhJ1VZiYP7dg/QcdcPqENxVlHW5Iv2g0Ug9Ii/XDkIiZN5NZlz1FKqTCaXcA?= =?us-ascii?Q?5VwFknAQOxwXjOoHEGjXa61iJRngIbQg9QhdJnwpb4jFRUf1SKlGTrFTjluh?= =?us-ascii?Q?5yqgBRNhqjRWI7GqY8V8jH0jm0SadiQorIJNyqAj7TIiTKm42xfTuVPtq1mY?= =?us-ascii?Q?aaUn6Cqy2avgB6MmeZQM0U9M0LMmnl8jesZPsLEiV7Of3vV7UOqe+73Phw8p?= =?us-ascii?Q?yg+cnyse+4SzkxcFTT5udIzYWaaNVuIE+bRmtuwU4WYD8Q8XaEtG/qsb7vvi?= =?us-ascii?Q?l7fxJOFDmvJZfRiw21dbYJ87yAe0K6xtJoosjyOckjHup3rlytY1rCVhRGjA?= =?us-ascii?Q?03hmrmXLma7Wy/6b3xgLjpBba50W8UEeHEIWW35E9KiuQdb9cdqM3PsjYk0w?= =?us-ascii?Q?mdJKHSe9qNqj5tTU59htUoR7KSK65D66ztpthiOCwFC2WDlcxP21AR8VxJxP?= =?us-ascii?Q?G/yb/pNiiEe+OxOi37SjpLsfmi+H7ZFWACb/NRLdanMcvkwi+del4AgsQa6U?= =?us-ascii?Q?V7YMsLSAPAV3dMQpZHQT6TbARygQmjxfR3W5Ml6fE5DUDybsu/Cq3pbfEWV6?= =?us-ascii?Q?ZbbheADNkAmYkrDewl4YulBo9axzxhFKi7Y+5Yt+DJFi2NwW63ZrjozqGWgX?= =?us-ascii?Q?aHIgDstAtCnm92/M5bdmr7eQ7DKIutIa6SrRALAfXhHmqXmgWj9I/yICJm2V?= =?us-ascii?Q?LlP3eYz9HU9buLW9X8h7qGiEFbGp2z+mSgVolAWixkhrJ63zBDpZlOiIbLkI?= =?us-ascii?Q?SQZ3sSRl6ZWzZvQT2vECMqhIUIv3lv0z110cigKPXN3VjzZ1otKJ8fkfqWT1?= =?us-ascii?Q?ot5gW1q2cag6FbEkENryrN1VfSpSewq4MZGcMnvXveDmNGo4zZzqtDKnrwFQ?= =?us-ascii?Q?Sy3P88UIk8A+HAEhbmnpnYJS5RLZHE82FW6SPQZohO83z3MRjSyU2wuDeJYQ?= =?us-ascii?Q?ycp17Yo=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?LO45ySEYhnCnnOMDWklvI/pmx1g2kUTfsdsiUZlMg+K6WHyGCl1F1Hh0CzTG?= =?us-ascii?Q?HBZSKL22psoRcb9Ut9Csf9OUL/CSN65QfnDN9s7UV87F3INXqlsTHqAjdpsF?= =?us-ascii?Q?VO+5JTkGYxIgCcjcwAuhOwvHyvRGuFmSbL0DUqd7D2dllvQ4UM9aH2Jw9lCy?= =?us-ascii?Q?xy97MH8UTbtCPRJ9wwy3AACpSAewE6hdTjwOsca4i88+hlE19ZYy9A7ajbCQ?= =?us-ascii?Q?l7L1O4uJvHaiQSVGkorx6I1AzxOpqDM7C+LFXfhBketT5lwCUeUzfCjQIEVz?= =?us-ascii?Q?KPcYPpZd/h/v7lf7nhf2/PBuLED5pRwfBzbyBEHsIvaeAHDtPE9wlbeWm9JQ?= =?us-ascii?Q?5c/gxEU0JujNZCv+UjaUxCjRZMQhmFsgHuwgTm9n+1WTGVXn514CnqMZdSP+?= =?us-ascii?Q?FiLgBBO5sM9iwknzCTD72ifC11waEcAg7qaeOZpLJ3fMbMQ4mvOh6ke/hSMp?= =?us-ascii?Q?3bQMs+IiXz9ob/IqkcA46mYk0O8KSoA83OEOfXzwhwpnPL78h3wipF16oL3w?= =?us-ascii?Q?pEnu6TxBUUftN4k1zf07B9WaGx47k1J9wxaJuZjBFc8DOeogaRgB5uwmFsy6?= =?us-ascii?Q?2LRQzJx1NTLqVLbgOIs+g9vV4G/+7ZkBs2FD0Lx1MuoXzQDt0sAKMhlhvsqz?= =?us-ascii?Q?+unVRQ7+IkRWyQUbmIbgdNRVdY0nr0b45D/9VoEEdmHyK+f42Z4ugezOAaZ8?= =?us-ascii?Q?HhxYebmBGLnBBQyWrmjeg1ABm6Dmyoja/V13VrYsK+8RrToOq6W8cQwylzGP?= =?us-ascii?Q?bRGICKunbdvZmete27imReNaP91mROjwKf+cPVHgWT6Mf5NrdUGScY8PERHo?= =?us-ascii?Q?h77KxRfhs4P4C0pNLZrTDpp0ak4JTaK6nKAEXcSsaErnAele5BWoBozSItYX?= =?us-ascii?Q?kBIdl8Mp+HTMTOgV5bHtwEL5xqY4j8yq3tTW5WGqcOk/u1SknJ0XjLa0tPuz?= =?us-ascii?Q?7w6Oa7F2mfbN8LcNUSxBCxbUY4I0fIAacV8CmvlHGs2c4X/xb5Lsxevyely5?= =?us-ascii?Q?rGmCxiDle9lxBCT+1pokeXwBWE0WOogA5Xi4N9YUNFz0TEri5S9ytDXcfyJe?= =?us-ascii?Q?/x54YVd58pyp4pt62JyhbyQKBVAx5PElmMDOvwrI3yYD3/WmYcAmqc682EPS?= =?us-ascii?Q?v34O5dU+qi7ztulhZoi03bb/p5d0aYDLlTCTl6lGDf9UuURJf4epUn7shd3w?= =?us-ascii?Q?TcBuCo+sIURcAi1l3ON3G1h5IxBH/e2fN3HG9HhqURYP3mjGdyXqlZfmZ1yy?= =?us-ascii?Q?/LxR4V7wisB/SE3qtGe/H6HQsrpS5fTEJM7ap7LFPaNDqyZWaid0dUlXRjAx?= =?us-ascii?Q?iHBefUenjQY8lEjXw5W+72jtCPa+9N537M4vVOS2uK+S9INT4ri5M/6P7hnV?= =?us-ascii?Q?jUiMy4x2PfG7UaGbRysTt6nARms5iblOHi4oyjX0dPqkhXnSJaSNwNTOzuR1?= =?us-ascii?Q?Lw5Y9TlbrPAgC2iDutFTIGepnwc60xYAXCbbwwjq3IRoXA9nsPIDft1P/BbR?= =?us-ascii?Q?p3JwX6x1HK6yUvtL2lp1tnhSpjE/czAfr6QbWaC8dLI7OPeDogcpctxKDpiT?= =?us-ascii?Q?J+KZq1m7MIMAtv4jiBLrfGwZapfFzy/i2bCofuyh?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: be5906c5-b39e-42bc-bb0b-08dc91c73bdd X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:27.2598 (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: EZ3TtO8jEDxwg3bNnn3GNNkSBRa413zGIBOaB97342qUKzly0odjum5WHIcUivw05IJ21AJa1EVT6AVa4ZZfWg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/decl.h | 299 ++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/decl.h diff --git a/drivers/net/wireless/nxp/nxpwifi/decl.h b/drivers/net/wireless= /nxp/nxpwifi/decl.h new file mode 100644 index 000000000000..1d4dee4a5f48 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/decl.h @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: generic data structures and APIs + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_DECL_H_ +#define _NXPWIFI_DECL_H_ + +#undef pr_fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +#define NXPWIFI_BSS_COEX_COUNT 2 +#define NXPWIFI_MAX_BSS_NUM (2) + +#define NXPWIFI_MAX_CSA_COUNTERS 5 + +#define NXPWIFI_DMA_ALIGN_SZ 64 +#define NXPWIFI_RX_HEADROOM 64 +#define MAX_TXPD_SZ 32 +#define INTF_HDR_ALIGN 4 +/* special FW 4 address management header */ +#define NXPWIFI_MIN_DATA_HEADER_LEN (NXPWIFI_DMA_ALIGN_SZ + INTF_HDR_ALIGN= + \ + MAX_TXPD_SZ) + +#define NXPWIFI_MGMT_FRAME_HEADER_SIZE 8 /* sizeof(pkt_type) + * + sizeof(tx_control) + */ + +#define FRMCTL_LEN 2 +#define DURATION_LEN 2 +#define SEQCTL_LEN 2 +#define NXPWIFI_MGMT_HEADER_LEN (FRMCTL_LEN + FRMCTL_LEN + ETH_ALEN + \ + ETH_ALEN + ETH_ALEN + SEQCTL_LEN + ETH_ALEN) + +#define AUTH_ALG_LEN 2 +#define AUTH_TRANSACTION_LEN 2 +#define AUTH_STATUS_LEN 2 +#define NXPWIFI_AUTH_BODY_LEN (AUTH_ALG_LEN + AUTH_TRANSACTION_LEN + \ + AUTH_STATUS_LEN) + +#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 WLAN_AUTH_NONE 0xFFFF + +#define NXPWIFI_MAX_TX_BASTREAM_SUPPORTED 2 +#define NXPWIFI_MAX_RX_BASTREAM_SUPPORTED 16 + +#define NXPWIFI_STA_AMPDU_DEF_TXWINSIZE 64 +#define NXPWIFI_STA_AMPDU_DEF_RXWINSIZE 64 +#define NXPWIFI_STA_COEX_AMPDU_DEF_RXWINSIZE 16 + +#define NXPWIFI_UAP_AMPDU_DEF_TXWINSIZE 32 + +#define NXPWIFI_UAP_COEX_AMPDU_DEF_RXWINSIZE 16 + +#define NXPWIFI_UAP_AMPDU_DEF_RXWINSIZE 16 +#define NXPWIFI_11AC_STA_AMPDU_DEF_TXWINSIZE 64 +#define NXPWIFI_11AC_STA_AMPDU_DEF_RXWINSIZE 64 +#define NXPWIFI_11AC_UAP_AMPDU_DEF_TXWINSIZE 64 +#define NXPWIFI_11AC_UAP_AMPDU_DEF_RXWINSIZE 64 + +#define NXPWIFI_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff + +#define NXPWIFI_RATE_BITMAP_MCS0 32 + +#define NXPWIFI_RX_DATA_BUF_SIZE (4 * 1024) +#define NXPWIFI_RX_CMD_BUF_SIZE (2 * 1024) + +#define MAX_BEACON_PERIOD (4000) +#define MIN_BEACON_PERIOD (50) +#define MAX_DTIM_PERIOD (100) +#define MIN_DTIM_PERIOD (1) + +#define NXPWIFI_RTS_MIN_VALUE (0) +#define NXPWIFI_RTS_MAX_VALUE (2347) +#define NXPWIFI_FRAG_MIN_VALUE (256) +#define NXPWIFI_FRAG_MAX_VALUE (2346) +#define NXPWIFI_WMM_VERSION 0x01 +#define NXPWIFI_WMM_SUBTYPE 0x01 + +#define NXPWIFI_RETRY_LIMIT 14 +#define NXPWIFI_SDIO_BLOCK_SIZE 256 + +#define NXPWIFI_BUF_FLAG_REQUEUED_PKT BIT(0) +#define NXPWIFI_BUF_FLAG_BRIDGED_PKT BIT(1) +#define NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS BIT(3) +#define NXPWIFI_BUF_FLAG_ACTION_TX_STATUS BIT(4) +#define NXPWIFI_BUF_FLAG_AGGR_PKT BIT(5) + +#define NXPWIFI_BRIDGED_PKTS_THR_HIGH 1024 +#define NXPWIFI_BRIDGED_PKTS_THR_LOW 128 + +/* 54M rates, index from 0 to 11 */ +#define NXPWIFI_RATE_INDEX_MCS0 12 +/* 12-27=3DMCS0-15(BW20) */ +#define NXPWIFI_BW20_MCS_NUM 15 + +/* Rate index for OFDM 0 */ +#define NXPWIFI_RATE_INDEX_OFDM0 4 + +#define NXPWIFI_MAX_STA_NUM 3 +#define NXPWIFI_MAX_UAP_NUM 3 + +#define NXPWIFI_A_BAND_START_FREQ 5000 + +/* SDIO Aggr data packet special info */ +#define SDIO_MAX_AGGR_BUF_SIZE (256 * 255) +#define BLOCK_NUMBER_OFFSET 15 +#define SDIO_HEADER_OFFSET 28 + +#define NXPWIFI_SIZE_4K 0x4000 + +enum nxpwifi_bss_type { + NXPWIFI_BSS_TYPE_STA =3D 0, + NXPWIFI_BSS_TYPE_UAP =3D 1, + NXPWIFI_BSS_TYPE_ANY =3D 0xff, +}; + +enum nxpwifi_bss_role { + NXPWIFI_BSS_ROLE_STA =3D 0, + NXPWIFI_BSS_ROLE_UAP =3D 1, + NXPWIFI_BSS_ROLE_ANY =3D 0xff, +}; + +#define BSS_ROLE_BIT_MASK BIT(0) + +#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) + +enum nxpwifi_data_frame_type { + NXPWIFI_DATA_FRAME_TYPE_ETH_II =3D 0, + NXPWIFI_DATA_FRAME_TYPE_802_11, +}; + +struct nxpwifi_fw_image { + u8 *helper_buf; + u32 helper_len; + u8 *fw_buf; + u32 fw_len; +}; + +struct nxpwifi_802_11_ssid { + u32 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; +}; + +struct nxpwifi_wait_queue { + wait_queue_head_t wait; + int status; +}; + +struct nxpwifi_rxinfo { + struct sk_buff *parent; + u8 bss_num; + u8 bss_type; + u8 use_count; + u8 buf_type; +}; + +struct nxpwifi_txinfo { + u8 flags; + u8 bss_num; + u8 bss_type; + u8 aggr_num; + u32 pkt_len; + u8 ack_frame_id; + u64 cookie; +}; + +enum nxpwifi_wmm_ac_e { + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VO +} __packed; + +struct ieee_types_wmm_ac_parameters { + u8 aci_aifsn_bitmap; + u8 ecw_bitmap; + __le16 tx_op_limit; +} __packed; + +struct nxpwifi_types_wmm_info { + u8 oui[4]; + u8 subtype; + u8 version; + u8 qos_info; + u8 reserved; + struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; +} __packed; + +struct nxpwifi_arp_eth_header { + struct arphdr hdr; + u8 ar_sha[ETH_ALEN]; + u8 ar_sip[4]; + u8 ar_tha[ETH_ALEN]; + u8 ar_tip[4]; +} __packed; + +struct nxpwifi_chan_stats { + u8 chan_num; + u8 bandcfg; + u8 flags; + s8 noise; + u16 total_bss; + u16 cca_scan_dur; + u16 cca_busy_dur; +} __packed; + +#define NXPWIFI_HIST_MAX_SAMPLES 1048576 +#define NXPWIFI_MAX_RX_RATES 44 +#define NXPWIFI_MAX_AC_RX_RATES 74 +#define NXPWIFI_MAX_SNR 256 +#define NXPWIFI_MAX_NOISE_FLR 256 +#define NXPWIFI_MAX_SIG_STRENGTH 256 + +struct nxpwifi_histogram_data { + atomic_t rx_rate[NXPWIFI_MAX_AC_RX_RATES]; + atomic_t snr[NXPWIFI_MAX_SNR]; + atomic_t noise_flr[NXPWIFI_MAX_NOISE_FLR]; + atomic_t sig_str[NXPWIFI_MAX_SIG_STRENGTH]; + atomic_t num_samples; +}; + +struct nxpwifi_iface_comb { + u8 sta_intf; + u8 uap_intf; +}; + +struct nxpwifi_radar_params { + struct cfg80211_chan_def *chandef; + u32 cac_time_ms; +} __packed; + +struct nxpwifi_11h_intf_state { + bool is_11h_enabled; + bool is_11h_active; +} __packed; + +#define NXPWIFI_FW_DUMP_IDX 0xff +#define NXPWIFI_FW_DUMP_MAX_MEMSIZE 0x160000 +#define NXPWIFI_DRV_INFO_IDX 20 +#define FW_DUMP_MAX_NAME_LEN 8 +#define FW_DUMP_HOST_READY 0xEE +#define FW_DUMP_DONE 0xFF +#define FW_DUMP_READ_DONE 0xFE + +struct memory_type_mapping { + u8 mem_name[FW_DUMP_MAX_NAME_LEN]; + u8 *mem_ptr; + u32 mem_size; + u8 done_flag; +}; + +enum rdwr_status { + RDWR_STATUS_SUCCESS =3D 0, + RDWR_STATUS_FAILURE =3D 1, + RDWR_STATUS_DONE =3D 2 +}; + +enum nxpwifi_chan_band { + BAND_2GHZ =3D 0, + BAND_5GHZ, + BAND_6GHZ, + BAND_4GHZ, +}; + +enum nxpwifi_chan_width { + CHAN_BW_20MHZ =3D 0, + CHAN_BW_10MHZ, + CHAN_BW_40MHZ, + CHAN_BW_80MHZ, + CHAN_BW_8080MHZ, + CHAN_BW_160MHZ, + CHAN_BW_5MHZ, +}; + +enum nxpwifi_chan_offset { + SEC_CHAN_NONE =3D 0, + SEC_CHAN_ABOVE =3D 1, + SEC_CHAN_5MHZ =3D 2, + SEC_CHAN_BELOW =3D 3 +}; + +#endif /* !_NXPWIFI_DECL_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2076.outbound.protection.outlook.com [40.107.7.76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7CAD170833; Fri, 21 Jun 2024 07:53:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.76 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956416; cv=fail; b=UPn2pGpVJ8x2LhnaXCfkKB2OHNFIVPGa96qZLP+F2jlMgL7G3mRUgbgj0+EfQ+sL+dCAIeipFWSMMC5WPydtyCWgT7LFDwRYC9R06weypBzjwtAYQPImpDtlRsinjEyyjwkH7oPWBuZJQaGUpxXnCtjGufD81V2NXBI2LBaZx7U= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956416; c=relaxed/simple; bh=C2PJC2GYMQd+svoclbtT5F6+/rEcoiBzzYvpkip8W+Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=AegMjksf89Sscqafk4z7r3hr5582I4aomI1Y3qMy3qnyhUf2NxGkxKG3c1gT51C+O0ATSGjgkvsex5ms3wkBNVM9y17eCm7jl7313X8kdhdTuoYT8gPnc0vEsCmTfl7QebIzVakfoWiGDUiXFzc6yNuPUvnYfJ0HzuDrkyf/p5I= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=TLrRkJsr; arc=fail smtp.client-ip=40.107.7.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="TLrRkJsr" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FQLgTVxzZkUbUPcYu2sZquujhqbxT1I9R+u8T9ohEoDruAg15qGWLPuoOessxiwa/f69H+imgj8HJQkg5o7BK821rz67hvj7C1H4o3cM7yEvJha2oUcObjzS7m9bTMw8VNILvBJZgjTBmMqo+RpF54G7ps3foY4kfGcyr5lHnuS96T9DeV/KQ75SvpQX6QDO/m0UbPpN4wXc3y376IKN7aHWFML6IOs45OxNtaPSSzXLKKNzp8HsRni5eJjOBBWGgrwpCXFoppi7xHHobJVYo5m6PhmM4DOtWI8eknc41I9zJhh6SkSvcx2BwIKb7IMPthEMVoLmmAsdjw1I9QqUlQ== 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=tfz0pAV1vC5xkzeShdbYbimiHZAN473eBr+M6CSIn98=; b=MmFylhqAuWbigf+yRunzjSqUMlsG97B6eDS+LOyJwt8x7wsIUMq71M7IbSNDGbVKa3/Be2g2BKFwhIxJ2R4/6j8VoA9wxx86AARVnOc1LItJP40kQYDpn7cEbPLoTm7tfvOsMYaUWj9ZUDyqUGEXZbBnM+aa9/C6iSZ7j+XG53iOHEVWGcMQDBc1uc8coGHp9cO0XIa+Nlsk/0ti9ku2RLJiqarZ4GRbAXCMmn/OjvHAcK0J04gcjpqjucVOSQrjWQJm0boWFzEsBt7T5IzNIccK4fNTW1tdnBl+3SsrTXEmOLiCQeZpojPHvheQunArzTUCL/KtCcUxz1bkWG3bNQ== 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=tfz0pAV1vC5xkzeShdbYbimiHZAN473eBr+M6CSIn98=; b=TLrRkJsrq5TBJxQsRVKSlhaZXGxCmynxvWsaYGuTrga1j4ChLrTFVM5agCOPD4V6F4Qjar9fNvbR1jbhgy6lL8Li7g2IcfO4ygrh1eLK7KdEcKY91lRa6XlYtwjB2PCs/6ZhDYYufLz/ucWE9XkyKd6thXVr2MiqNwVhVeinkHI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:31 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:31 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 17/43] wifi: nxpwifi: add ethtool.c Date: Fri, 21 Jun 2024 15:51:42 +0800 Message-Id: <20240621075208.513497-18-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 833531df-6d99-487b-5c81-08dc91c73d9f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?lP4tL8APz/amCKjnldZNBxavbhY8sfglzOfjr4cLhLnkxkBs6Ggjjk51XGhk?= =?us-ascii?Q?E3Lja8j3WRJPD/zDkNjyzANI3NGC/S6dtoct7FTATliCHkOl6B0yetRJatAz?= =?us-ascii?Q?Vt8cgOv4+PhALC4wgfmcpRZVYUQ/mC0j2spIhxH+10pd1B8BiMQevXz4SDvZ?= =?us-ascii?Q?1GoGhxvdNXSSSznkNCUtBPMFhTSiMiaoIQwz3Sy4diruguavTweB2jf/S2Np?= =?us-ascii?Q?8+eg4t8v8bKIEz/TB8965VPJ5DyK6PA0FO0pCY0rrGqSje7RAd6GNw8bUeDk?= =?us-ascii?Q?HCeAX5KlXW0q5kVwFcL83FgpvD2CZmCFQkvjmU2V1BnYADrmNmoP/+N8Yzfw?= =?us-ascii?Q?0qg0ZTr+7IadTHSJirMWYJnZnf0chKCsSTCC241RWNvudfodmb/c7DQMQQKJ?= =?us-ascii?Q?fajrpoJssSwJ7TL+/rKTNksCcZ/xT1wnuqUU4mvkxDTwb9gFvAeBEYtXfDPc?= =?us-ascii?Q?Ced9zYvsOastIAS9UAu6cK+k2WmnfaJHBi1XzEpFG96kFztAFl+E5G7bprpd?= =?us-ascii?Q?CcunF2Aw1uA4JozPie3ZKKRZQOxZvB7qQLZAmlItKT2lsrwrCSR1s+uES7Fd?= =?us-ascii?Q?hQEn1FZrjKsetSkGVoyOFEtTXks9lBX8Z8Xuw59IoMIipb9Q/yxm496Zkn1O?= =?us-ascii?Q?VdQV31yH/ByeHfuHnymJVFaT9VIceTyItQPFKimA+Sq6zIbfuHYMoSf20b9X?= =?us-ascii?Q?jRqDZKY4euE3AuPIh9a3OLOQ/xDjHatHoG3AQLjjFK8XSgF6NiTXOrJqd2jn?= =?us-ascii?Q?NUIlqF+bjF0J5cSxsHl7Ic5AYWkM9KOLV22ZXiNBFAKfkY+IhHzCst6+I/Xv?= =?us-ascii?Q?WRvOFJoPIBF/urcekyCkWs2CbVQWOfNgcXvjNV7d/M+C16xMWE0o8Qpun0H9?= =?us-ascii?Q?X5CuqgBL6Kkh8GJpnDZi0fl3c59d0b9WZcx9oRItnhsGfKKyRG7BVEW9AGdU?= =?us-ascii?Q?dC1Asb+Tv3v+a++oHrHNGZkNxZ0Kng5jkystTMQqawjdm/Nt5Rd7MzIz26dZ?= =?us-ascii?Q?8R+Y6Vb8z5VXrQ/xFOQ+2fSG5/rxu6zIKbeAq+dQX5TllkG6hsgXcGEgFrO5?= =?us-ascii?Q?2FSL32se43zKrZsUDFqLLlzdJmGF8EYlJqKtvSz8jf1yAiTzglEFJjNd6Bjn?= =?us-ascii?Q?Yb2kvvv4tkCZMS9qGwc7ej+nqSSYITZohiQgpIB1sifnPuKJj9WmNewERTTR?= =?us-ascii?Q?JeOrGLgmjRT+cYYiilCiW7KW7+uZwGj9is9LjNWo1np0ZfScWzKcyCVs5Aov?= =?us-ascii?Q?F5VgeJQ5KLgFsDTJml1LVtfNdLA5dwFS6oSyJvEjjeF8pxRZN//60w1vIMJO?= =?us-ascii?Q?klFuMcxfcoWma0x6sfzeG1x8dvkKkKGnPXxJwyDbGSywElDuNBg+FKfo+rvn?= =?us-ascii?Q?t6b4tY8=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?ivdIee2nXl85rExFz6ImmGJmuup8ANm2RBaF9T1RIPdpianYKONZd0W8l5eT?= =?us-ascii?Q?YN7LGTTQkdlL63FiL8oOYHAC17aM4xfkhpHbwuMxMMe7BjOpaXunnVBEGvMG?= =?us-ascii?Q?Ki5GvQuWLZjunPyXFzrWXx/fofWgsTiuGEG5QGo4ei9bzAPkogBKdkZ0WzZC?= =?us-ascii?Q?jiDEByGLbFB3lLBf3iUVTI9SHXpyCD2fUj3xl/zgywEXu6BXfCK9U0A2sgHQ?= =?us-ascii?Q?jfJHtFMp/5LXbgMe9lj/R4pB4IIKswaPWm6bBtthwr8NgSJiEjKq1SbLvYVJ?= =?us-ascii?Q?9cg5Nx2wsrdzz6aafd8nNi1ZXJS8IwMSYptw0B1JtSshDLQiy8+wwVachV6M?= =?us-ascii?Q?ij6rOnYywHgwaGABngFM6zK9E4fmgvEyoos7b8uqE/GszD+FFdrV4u1HLolc?= =?us-ascii?Q?yNjTLesA+oRt4Dkoe3p4AetSZY3rN1wm4KC0w2PNdoSFOtxQX4XXo+Cnuw2+?= =?us-ascii?Q?Jw8+5UZ9Ha1WwUqecl2dWzWS3e47IXLUWBGGCjdF8+/c/fmS6NxoYDfWFGGO?= =?us-ascii?Q?IW71fcmckm5r1WhM6L8WkoOsghvLaxKkfPutVqSe0QxfR7PWdeIWZ7L+icVl?= =?us-ascii?Q?JGz+AqyIiBnrX7SEIibqYmMLbMIezAyJb4dkTaWZ+JHTzDuCVfw7wkVV9AZF?= =?us-ascii?Q?Ie7YI7l6DAhvWqvP4mgzGlgq6znICCcCdQTb05/Nd7oSD/KwEsmPU1bM9YUf?= =?us-ascii?Q?1uH6+DWFsAm57VT/QvPd3PEH1j40PFmN2TkYQM/V3aciOIY7J6P5rj2L2+fp?= =?us-ascii?Q?/RVxxd/BzsSk2RUnQnJDtsjhPrLKRlquPj/lnwK7Vl+JqLMexp86hc12I1G8?= =?us-ascii?Q?LvAwf8egdeYB/bfWTz2W6L7Zk3sn74Qh/hPGdctphtE77t3cpr1J11aJsNjD?= =?us-ascii?Q?nNVcmNgyhhxlhh/UKSwoXimTyqa0kUyhg0U4EadOE9RU5dbGxSGJZvJdkN7l?= =?us-ascii?Q?5drPewxxX7cNqAy5Fw0WFQgPjfFquNrjFMAlFVfkD2fKkmJY19mgAmv1wkSx?= =?us-ascii?Q?NAeYNyNxTgYVSsvg7Spxr1btFjtf1TVL7cue6wfUxgUnM5a+i5P7ct5JZmRJ?= =?us-ascii?Q?/m1SrCPuTt66z0IbRTuMzCL54WkHgrNeOhu9g+9pPfzWYzGhT1uTbyy6HZID?= =?us-ascii?Q?Pye1GrFJQbEjGuKkK3BEmXX3JsLK1sOvJjKDlg54dqvAIyb/qcz/B1CkUcXm?= =?us-ascii?Q?IhAvD5I7GtGrpmmFOftIaSLw9Hmbfi5E4uunQ/ICl9lBXhmXjMK9z9dAKXp1?= =?us-ascii?Q?vCawYUUxLxFpdU9NygKc4sSHwzNLf8XioOg4L2eXla15JVV2HHygx38hNIcy?= =?us-ascii?Q?BxmR1nddD416RPIwPl04QVJfvt5bEy7iaWZcix34ATbC0SIa29lK+mScsS6B?= =?us-ascii?Q?ST8llwEJXNr2/6lrNsLHRBUN3L/o0qR3doPd9LomM58xgXsve2+abuHScQQG?= =?us-ascii?Q?lHlq6ULtLSbMkeJcU+AhWPgaXpme4qyJO3WhWJ5LpWLPd/2rPBwmWmvt435I?= =?us-ascii?Q?nkF4YSd8XjuKKmtd3gDv85GVdVR61LZGHjtmmR0bi5eY6y/tduFgwEMQVZcS?= =?us-ascii?Q?pHIOWjWHGHgSCRvUPB7V/XBxGiExVwvfFAjYYBRI?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 833531df-6d99-487b-5c81-08dc91c73d9f X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:31.6723 (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: tzE9W234d1pORXistFJf0Vfi9rPILrO62GQ/8DdZqBJ3PToN14+f2AsP+0jISrf/CvzQtFA6xFyR0SJY8LzRuw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/ethtool.c | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/ethtool.c diff --git a/drivers/net/wireless/nxp/nxpwifi/ethtool.c b/drivers/net/wirel= ess/nxp/nxpwifi/ethtool.c new file mode 100644 index 000000000000..6cefa6e6f5b3 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/ethtool.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: ethtool + * + * Copyright 2011-2024 NXP + */ + +#include "main.h" + +static void nxpwifi_ethtool_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + u32 conditions =3D le32_to_cpu(priv->adapter->hs_cfg.conditions); + + wol->supported =3D WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_PHY; + + if (conditions =3D=3D HS_CFG_COND_DEF) + return; + + if (conditions & HS_CFG_COND_UNICAST_DATA) + wol->wolopts |=3D WAKE_UCAST; + if (conditions & HS_CFG_COND_MULTICAST_DATA) + wol->wolopts |=3D WAKE_MCAST; + if (conditions & HS_CFG_COND_BROADCAST_DATA) + wol->wolopts |=3D WAKE_BCAST; + if (conditions & HS_CFG_COND_MAC_EVENT) + wol->wolopts |=3D WAKE_PHY; +} + +static int nxpwifi_ethtool_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + u32 conditions =3D 0; + + if (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_PHY)) + return -EOPNOTSUPP; + + if (wol->wolopts & WAKE_UCAST) + conditions |=3D HS_CFG_COND_UNICAST_DATA; + if (wol->wolopts & WAKE_MCAST) + conditions |=3D HS_CFG_COND_MULTICAST_DATA; + if (wol->wolopts & WAKE_BCAST) + conditions |=3D HS_CFG_COND_BROADCAST_DATA; + if (wol->wolopts & WAKE_PHY) + conditions |=3D HS_CFG_COND_MAC_EVENT; + if (wol->wolopts =3D=3D 0) + conditions |=3D HS_CFG_COND_DEF; + priv->adapter->hs_cfg.conditions =3D cpu_to_le32(conditions); + + return 0; +} + +const struct ethtool_ops nxpwifi_ethtool_ops =3D { + .get_wol =3D nxpwifi_ethtool_get_wol, + .set_wol =3D nxpwifi_ethtool_set_wol, +}; --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2068.outbound.protection.outlook.com [40.107.7.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D5D1171648; Fri, 21 Jun 2024 07:53:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956424; cv=fail; b=kKgEh0FPScAFYlxR/lhDwMHw3gRUHGi4Hojw7MaIxxu01YjDRZAABEWnXBBOuegO9OdYD6k7LnCkQIyUv15Qgd8mxcb5UWPm/lCf8CoDbXGaWWuenuNELzguxAo7yBwAVaVR4icEb7W/C1F8Ba7eeCN0+8ReFdCq52NI2LxRR2s= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956424; c=relaxed/simple; bh=zfAmQA6hfQe97XEMs5DXEDpWVBdyty5rzkHbIomF8SI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=dla7nudJO3F7CWJSmzalUo0BHvsMRdhbqXmDJOxNTYis3+GlSW1SOmvBIFUy/h9zlNH/hL8deJU/0ZDnVwRmFFCnXBraB98hUu+tF6VXso+LpjO49DSeeYoWPJZaX9HLBOq6Uo/8UQWDsGkEqpiAg3QCir8/Nrt+7vTWQ5PAwPc= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=hTMCXINe; arc=fail smtp.client-ip=40.107.7.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="hTMCXINe" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bTb7fXiycY08+lF8d/WB3npsZiC0x5LpJ14YqQA4IHJMnA3sMKefOeor4JGEtFB7u+vq/wpPpB5RgK3yokrgXWkuUCgx593Yi/FIIZmNFtu57baUK2/5uMqGTSgTnJ3lsH2W2OIOC8k2NSDA4zZ2mZhfxosW4DO7IVeX8TLjiNUJNIEylq/1B9d3esh2Rh6TfJQXlNnruN2BlSBcuEH3No9mSARGEdsLc77DRtVhPJ5rydT7OojyOG4CM0jGxUyYEpve17PUz2cZhwT0A8+sFh1+oMKeuMdMiNVJkrxCGSpgYZ/btZwWKAM6pwQNIOUhyj+KttODLKB+7Ms1NHoc4g== 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=niK1qbq0p+m/qiOqqT6iMh4FXykJ4fE4JfEwik0/hh8=; b=Ca9AVu/T9uJGTW15XaGP6gpZbNrHy4vWypNUwa7vUwT7osYrDYJgy/4rvNh9LcJAIKfCOct98dFSDLS0yc1NllZXbE3nEUWescm79yA9Nc6D9hCLxfZarO9J8VDChKHV/pi0ITnz69gRMTinaX5Dp9pUxgXLYBheUW1D9OUgIeuY/JR7dIurE8e4cBBY96h8pANy+QKX34LCejhIUPcyD8OL/kD6Qo+sLPV8FmbQ3x42VrvQsnqRiTbcrZ7f4kA/8SMceXWRk2LTJs4TxGsSoxzpHpQR6E1cQoCsxhCW5VTB5iIwRAMMHKnwR/o9AZyHUvmscdN/igRi7H6QvBRNZw== 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=niK1qbq0p+m/qiOqqT6iMh4FXykJ4fE4JfEwik0/hh8=; b=hTMCXINe7jP5JWoTkfnTdYKZEqUlJswBe0Hyz7Bdmq+juEvx4QTGlAjiK+hxA4UqR6loGsVkiHnRx2kVSk/3jIDYhm6IZrkobEwhEKGgV2E6K7Kwb9x0O/Be4a68Qi+cwkIO3wxP7lggS+q2UUWl2Xfe3RFj8c8V0ATQfiHNz+U= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:36 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:36 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 18/43] wifi: nxpwifi: add fw.h Date: Fri, 21 Jun 2024 15:51:43 +0800 Message-Id: <20240621075208.513497-19-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: b5c298c1-77fe-481e-c13e-08dc91c7404d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?q0zpJirtZhAc+DXzNmRvMqRbrOfwrM7fDQqX5mVyhrZoeT7WsAUurnyTBZfi?= =?us-ascii?Q?VrXfgAemLUlncrItef3ZpXRJCIwKthF/+TFuXo/aMNWAYkqhMa7RtMYF3FCB?= =?us-ascii?Q?mJkmBqjIgR3WpLZvZuwzjD0Zz6AOz1tmLvBqscQDV73NnEUPa4NfZlyJWKc3?= =?us-ascii?Q?eCRnUdqaDB+8DXcJHhwlyErxIhV1sij/JBKWWd+M4I6dwQEmqy4DJ7idIdMH?= =?us-ascii?Q?0sMEbGV9Zw/WwZ9GidxDvLXgcjlaJha6O5ZGyFjQzA+8OAHpk34LXco6P1kd?= =?us-ascii?Q?+Av6xdxsSNZ5LnWd9WX6oL31oUybjT2qKG2GwAE34X33jUzZeTIsnFV7odwn?= =?us-ascii?Q?3UcthWBKKZ72F8BdrJasUP/vyiWEFetMixPU38Ptzw7n85BjQQ0OsKpRcmf1?= =?us-ascii?Q?r1chHLtcI8JPFRnlQ50BhAAElxdnTw/onde1ZWfSJqUJC0scfu2tVfpB8V9X?= =?us-ascii?Q?6T/waQWM1JnK2YAE+fWgwxT4WprJLDUUg2rSBSPysWH1gH/l50FoYBtj/icF?= =?us-ascii?Q?fJggRFIYBUBvRvMFnpqNNcpl9DEVzaDp/Zb/1QHJtSnIgQeYoEtQ8ZQp/q0V?= =?us-ascii?Q?7MlFkb3fQ0+ZDMfqklD6aSozjoW1lK3e4A5YyocKrp+ZNul68MokbvyvBrP5?= =?us-ascii?Q?SplUGf0HWdrgzURJSYtQPYZT9cpdwnSWz9Gm6yeGtQJS8sQXpOuNrx/SmhDQ?= =?us-ascii?Q?K4uQ+fIwqsB5puegogv2Ra0+TBMUstsaEPBLqaJmttwDkhF6W3NaUc2lzsEp?= =?us-ascii?Q?/A4FYg2Za/wBfcleA4uSURRC1glwxs4Wnm8KPUwfLkA+DYlONVJh/milIDeC?= =?us-ascii?Q?ThCPjK79JeV4Yy65sW1Fc9ytP13ev8H6vEjYTwIZoXTARmSFANjQgqTPcti5?= =?us-ascii?Q?+hrbztz3AVhJlaKiaam0PxbnHMKzjW32pB4d5P0SVo7CZQBldwuHMTnEK8oW?= =?us-ascii?Q?g0yWs6CRPCaKT64xvscH8HhpAWrhLxXDWuAVsehuBg+kP7iM3L/mJc3srcWT?= =?us-ascii?Q?Zh2gu81E19o0djUzclnIir+4ltPKFiJ++xc1Edjq/Z9u/5I0zWeSTgkKbPSm?= =?us-ascii?Q?GsL7y3A4UbVDS1Cg2WhnOnRp6DBjpwKTr+zpRx5fLdYodCWu6lVzWVwurmp6?= =?us-ascii?Q?3nUQwYsHZa5cA9iW9nW1nPnjJagOldCg13T9QH/GwBzmnppqi7e2l2B72ruv?= =?us-ascii?Q?+U8lsfnoJ9RjI/zc0Droo0/Yy8JLMjCMB/evgkkgh6mby2J4WRsvQHUHIlJ1?= =?us-ascii?Q?/z/FrcrOjdjZPg9CqMUiTVLYkmYgqVbsIZhIGJmeQuzjrp9YtxWVmeu1rxO+?= =?us-ascii?Q?uzoY4lPJb0wORI8fN6oEL02UmBSAOoR2dZOyyJdN6AMJB/hUhRkWsmt3VGCz?= =?us-ascii?Q?EoLHFoM=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Tv86faytsbRBXSMgtqzwn82gFPQXL/9o/N3YHErlZGBBPYcpGdzk/NLt0ZFh?= =?us-ascii?Q?3QZH48sLrWN1Tx9yU0pfv7U09uDirteON9aiac/xwjTffiRXDaoyo0MTM5tH?= =?us-ascii?Q?zHAa7cSBHzrHuIWs0IVb/mcOz84ATrpK0PAZ2d872WAbWvb8qSjRqB/fUdjT?= =?us-ascii?Q?KWKicbApZNW7+Qn9+GGyWHG+3qTgTQwgPaKau+2en5PW9O8JxjvYHgZz3VNr?= =?us-ascii?Q?o6lOzIIIRh+/bbT7/yjA9Jmg51h7WFW9sX8cVpqZ0Z/Tq7DUCxxs721zYSMM?= =?us-ascii?Q?IZXn8MvLrETAmWyMBqoYhAfYWc3vPHu2AKM13STsvqtd9HEM3JGlGLu3y5Ha?= =?us-ascii?Q?pUEp6ZLS6TbSI/TGDurNT9Pyofa3lzri69mvFJ0HFuQt2SRf7DoCujSNAGez?= =?us-ascii?Q?YzbKjKJ48FzKQE/DWDk0oIyA8DWl4ZubiA5PUP0Fd2d4JQTXaNlRF3UE1c+c?= =?us-ascii?Q?PdQPBCcv1PHbSiEd8SnPhiXgsRIXoqtuKx3qd9alDhcyQpp6AJU0GHWxr0qk?= =?us-ascii?Q?jtrMLOwrE9tsJT3aBr4cEvH8dEpIm6paadJAsG/zNCtPs6/DYbzYNXgZtG27?= =?us-ascii?Q?4sDUBNMhx/VTdUPyfWuMb79B5QTtk1Q6ipmaqL4oM8MY/DRIvhvWK6QBZjxB?= =?us-ascii?Q?Mb+ArPOk9gKRPAKmuo2rFZ8SyjuPDYR00OYgT1G8ioiqgCN/JSsq72zR1nx8?= =?us-ascii?Q?BftummogGKTRBjLTZ9Lil9mImYzHRVW9BnyEfFlO0Qa0cYw5EjuOggUbhwgr?= =?us-ascii?Q?jj76KvvVym43DXCaDULWLijaB03QNd0m97JnVXroeXMT9Al3/+53fvjeD21D?= =?us-ascii?Q?mmWZQQHiJh6uuaGIjDTlTwKAD3kAC+ZhZZim/U9WZzXYYjh94iBVGtcE27n4?= =?us-ascii?Q?q9OFickb9SKye4IQVTjuSjMeZyu0JsE5iXi1S/iOMZGfxweHZvO6+1pq2hRz?= =?us-ascii?Q?w4lhC7fjUE8BXM4slgRh2XxFC+H1pmW+ye7W+STBgMgXVnjEA1Effh5B+y/i?= =?us-ascii?Q?W4o70D7GM4DEoeV2dTjIwhZeMXIZm0taSRzR3JKKzfe1DtEDJl3yLBnhgs/d?= =?us-ascii?Q?4rMw+D1cA/Ja6aQeldS3eiHNzLg2kr4zocEsDuSlQK/M/o3riu5R6F4MqrAi?= =?us-ascii?Q?dndf5lPVE1+c+0E+jw5fOrRBWTOfIrXjRH8g92QcmVIgr9nBkRok2Uj5kbke?= =?us-ascii?Q?lPbdZcICfytxx7ltM0MepJ0rQyRIwGrQ3SdtabqzeaIXY/RSYrLFW2MGIzE7?= =?us-ascii?Q?90n275/r3Tw4jJEIHaM2qqRSjBq9/NsTe1iIDJg900o4js+t0YRdpvbXIjEy?= =?us-ascii?Q?w5lGdC2URx31SAzoX92oeJ9X1BJbYTmKpoXx7r4P/omCAz5XaoSuQbtcs4EK?= =?us-ascii?Q?a0qy7PwIICgQQJiIt1ORh13zZC/aiozlvEf0JNTPSLsDQ2/HSP2ai1vCC/kn?= =?us-ascii?Q?1OxbudMCu7RqunKr4ynUM+zxsZE+u9N+AQ7V3sy51cxBpaTmzh5RwJdirWOn?= =?us-ascii?Q?6VTeTUF8BNsLpSZ6gDkNdCNemwSyurSIy63LGX+djHVuoPK/Fcu0bmH2TqRI?= =?us-ascii?Q?+Sdc4WUlchuAYN6nxHZ/XKAqP4trxr9BpMygPPsz?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: b5c298c1-77fe-481e-c13e-08dc91c7404d X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:36.1249 (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: v6jCxbo4XKCBn2M2lBs1K31JZWPhquWNJR+PVWr0tILUqzxi4GC5SaUVNFn41prH+cMnvzHTN2SRE/KPIgf7Og== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/fw.h | 2262 +++++++++++++++++++++++++ 1 file changed, 2262 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/fw.h diff --git a/drivers/net/wireless/nxp/nxpwifi/fw.h b/drivers/net/wireless/n= xp/nxpwifi/fw.h new file mode 100644 index 000000000000..e38ca7d99d17 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/fw.h @@ -0,0 +1,2262 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: Firmware specific macros & structures + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_FW_H_ +#define _NXPWIFI_FW_H_ + +#include + +#define INTF_HEADER_LEN 4 + +struct rfc_1042_hdr { + u8 llc_dsap; + u8 llc_ssap; + u8 llc_ctrl; + u8 snap_oui[3]; + __be16 snap_type; +} __packed; + +struct rx_packet_hdr { + struct ethhdr eth803_hdr; + struct rfc_1042_hdr rfc1042_hdr; +} __packed; + +struct tx_packet_hdr { + struct ethhdr eth803_hdr; + struct rfc_1042_hdr rfc1042_hdr; +} __packed; + +struct nxpwifi_fw_header { + __le32 dnld_cmd; + __le32 base_addr; + __le32 data_length; + __le32 crc; +} __packed; + +struct nxpwifi_fw_data { + struct nxpwifi_fw_header header; + __le32 seq_num; + u8 data[]; +} __packed; + +struct nxpwifi_fw_dump_header { + __le16 seq_num; + __le16 reserved; + __le16 type; + __le16 len; +} __packed; + +#define FW_DUMP_INFO_ENDED 0x0002 + +#define NXPWIFI_FW_DNLD_CMD_1 0x1 +#define NXPWIFI_FW_DNLD_CMD_5 0x5 +#define NXPWIFI_FW_DNLD_CMD_6 0x6 +#define NXPWIFI_FW_DNLD_CMD_7 0x7 + +#define B_SUPPORTED_RATES 5 +#define G_SUPPORTED_RATES 9 +#define BG_SUPPORTED_RATES 13 +#define A_SUPPORTED_RATES 9 +#define HOSTCMD_SUPPORTED_RATES 14 +#define N_SUPPORTED_RATES 3 +#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN | \ + BAND_AN | BAND_AAC) + +#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \ + BIT(13)) +#define IS_SUPPORT_MULTI_BANDS(adapter) \ + ((adapter)->fw_cap_info & FW_MULTI_BANDS_SUPPORT) + +/* bit 13: 11ac BAND_AAC + * bit 12: reserved for lab testing, will be reused for BAND_AN + * bit 11: 11n BAND_GN + * bit 10: 11a BAND_A + * bit 9: 11g BAND_G + * bit 8: 11b BAND_B + * Map these bits to band capability by right shifting 8 bits. + */ +#define GET_FW_DEFAULT_BANDS(adapter) \ + ((((adapter)->fw_cap_info & 0x2f00) >> 8) & \ + ALL_802_11_BANDS) + +#define HOST_WEP_KEY_INDEX_MASK 0x3fff + +#define KEY_INFO_ENABLED 0x01 +enum KEY_TYPE_ID { + KEY_TYPE_ID_WEP =3D 0, + KEY_TYPE_ID_TKIP, + KEY_TYPE_ID_AES, + KEY_TYPE_ID_WAPI, + KEY_TYPE_ID_AES_CMAC, + KEY_TYPE_ID_AES_CMAC_DEF, +}; + +#define WPA_PN_SIZE 8 +#define KEY_PARAMS_FIXED_LEN 10 +#define KEY_INDEX_MASK 0xf +#define KEY_API_VER_MAJOR_V2 2 + +#define KEY_MCAST BIT(0) +#define KEY_UNICAST BIT(1) +#define KEY_ENABLED BIT(2) +#define KEY_DEFAULT BIT(3) +#define KEY_TX_KEY BIT(4) +#define KEY_RX_KEY BIT(5) +#define KEY_IGTK BIT(10) + +#define MAX_POLL_TRIES 10000 +#define MAX_FIRMWARE_POLL_TRIES 300 + +#define FIRMWARE_READY_SDIO 0xfedc +#define FIRMWARE_READY_PCIE 0xfedcba00 + +#define NXPWIFI_COEX_MODE_TIMESHARE 0x01 +#define NXPWIFI_COEX_MODE_SPATIAL 0x82 + +enum nxpwifi_usb_ep { + NXPWIFI_USB_EP_CMD_EVENT =3D 1, + NXPWIFI_USB_EP_DATA =3D 2, + NXPWIFI_USB_EP_DATA_CH2 =3D 3, +}; + +enum NXPWIFI_802_11_PRIVACY_FILTER { + NXPWIFI_802_11_PRIV_FILTER_ACCEPT_ALL, + NXPWIFI_802_11_PRIV_FILTER_8021X_WEP +}; + +#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI) - (s16)(NF))) +#define CAL_RSSI(SNR, NF) ((s16)((s16)(SNR) + (s16)(NF))) + +#define UAP_BSS_PARAMS_I 0 +#define UAP_CUSTOM_IE_I 1 +#define NXPWIFI_AUTO_IDX_MASK 0xffff +#define NXPWIFI_DELETE_MASK 0x0000 +#define MGMT_MASK_ASSOC_REQ 0x01 +#define MGMT_MASK_REASSOC_REQ 0x04 +#define MGMT_MASK_ASSOC_RESP 0x02 +#define MGMT_MASK_REASSOC_RESP 0x08 +#define MGMT_MASK_PROBE_REQ 0x10 +#define MGMT_MASK_PROBE_RESP 0x20 +#define MGMT_MASK_BEACON 0x100 + +#define TLV_TYPE_UAP_SSID 0x0000 +#define TLV_TYPE_UAP_RATES 0x0001 +#define TLV_TYPE_PWR_CONSTRAINT 0x0020 + +#define PROPRIETARY_TLV_BASE_ID 0x0100 +#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) +#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) +#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) +#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) +#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) +#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) +#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) +#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) +#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) +#define TLV_TYPE_BGSCAN_START_LATER (PROPRIETARY_TLV_BASE_ID + 30) +#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) +#define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) +#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) +#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) +#define TLV_TYPE_UAP_MAC_ADDRESS (PROPRIETARY_TLV_BASE_ID + 43) +#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) +#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) +#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) +#define TLV_TYPE_UAP_PREAMBLE_CTL (PROPRIETARY_TLV_BASE_ID + 49) +#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) +#define TLV_TYPE_UAP_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 57) +#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59) +#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) +#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) +#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65) +#define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70) +#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) +#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) +#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) +#define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) +#define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) +#define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91) +#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) +#define TLV_TYPE_ROBUST_COEX (PROPRIETARY_TLV_BASE_ID + 96) +#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) +#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) +#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) +#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) +#define TLV_TYPE_UAP_PS_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 123) +#define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) +#define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) +#define TLV_TYPE_TX_PAUSE (PROPRIETARY_TLV_BASE_ID + 148) +#define TLV_TYPE_RXBA_SYNC (PROPRIETARY_TLV_BASE_ID + 153) +#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) +#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) +#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 176) +#define TLV_TYPE_PS_PARAMS_IN_HS (PROPRIETARY_TLV_BASE_ID + 181) +#define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) +#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184) +#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) +#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) +#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198) +#define TLV_BTCOEX_WL_AGGR_WINSIZE (PROPRIETARY_TLV_BASE_ID + 202) +#define TLV_BTCOEX_WL_SCANTIME (PROPRIETARY_TLV_BASE_ID + 203) +#define TLV_TYPE_BSS_MODE (PROPRIETARY_TLV_BASE_ID + 206) +#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_UAP_STA_FLAGS (PROPRIETARY_TLV_BASE_ID + 313) +#define TLV_TYPE_SAE_PWE_MODE (PROPRIETARY_TLV_BASE_ID + 339) + +#define NXPWIFI_TX_DATA_BUF_SIZE_2K 2048 + +#define SSN_MASK 0xfff0 + +#define BA_RESULT_SUCCESS 0x0 +#define BA_RESULT_TIMEOUT 0x2 + +#define IS_BASTREAM_SETUP(ptr) ((ptr)->ba_status) + +#define BA_STREAM_NOT_ALLOWED 0xff + +#define IS_11N_ENABLED(priv) ({ \ + typeof(priv) (_priv) =3D priv; \ + (((_priv)->adapter->config_bands & BAND_GN || \ + (_priv)->adapter->config_bands & BAND_AN) && \ + (_priv)->curr_bss_params.bss_descriptor.bcn_ht_cap && \ + !(_priv)->curr_bss_params.bss_descriptor.disable_11n); \ + }) +#define INITIATOR_BIT(del_ba_param_set) (((del_ba_param_set) &\ + BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS) + +#define NXPWIFI_TX_DATA_BUF_SIZE_4K 4096 +#define NXPWIFI_TX_DATA_BUF_SIZE_8K 8192 +#define NXPWIFI_TX_DATA_BUF_SIZE_12K 12288 + +#define ISSUPP_11NENABLED(fw_cap_info) ((fw_cap_info) & BIT(11)) +#define ISSUPP_DRCS_ENABLED(fw_cap_info) ((fw_cap_info) & BIT(15)) +#define ISSUPP_SDIO_SPA_ENABLED(fw_cap_info) ((fw_cap_info) & BIT(16)) +#define ISSUPP_RANDOM_MAC(fw_cap_info) ((fw_cap_info) & BIT(27)) +#define ISSUPP_FIRMWARE_SUPPLICANT(fw_cap_info) ((fw_cap_info) & BIT(21)) + +#define NXPWIFI_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ + IEEE80211_HT_CAP_SM_PS) + +#define NXPWIFI_DEF_11N_TX_BF_CAP 0x09E1E008 + +#define NXPWIFI_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR + +/* dev_cap bitmap + * BIT + * 0-16 reserved + * 17 IEEE80211_HT_CAP_SUP_WIDTH_20_40 + * 18-22 reserved + * 23 IEEE80211_HT_CAP_SGI_20 + * 24 IEEE80211_HT_CAP_SGI_40 + * 25 IEEE80211_HT_CAP_TX_STBC + * 26 IEEE80211_HT_CAP_RX_STBC + * 27-28 reserved + * 29 IEEE80211_HT_CAP_GRN_FLD + * 30-31 reserved + */ +#define ISSUPP_CHANWIDTH40(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(17)) +#define ISSUPP_SHORTGI20(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(23)) +#define ISSUPP_SHORTGI40(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(24)) +#define ISSUPP_TXSTBC(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(25)) +#define ISSUPP_RXSTBC(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(26)) +#define ISSUPP_GREENFIELD(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(29)) +#define ISENABLED_40MHZ_INTOLERANT(dot_11n_dev_cap) ((dot_11n_dev_cap) & B= IT(8)) +#define ISSUPP_RXLDPC(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(22)) +#define ISSUPP_BEAMFORMING(dot_11n_dev_cap) ((dot_11n_dev_cap) & BIT(30)) +#define ISALLOWED_CHANWIDTH40(ht_param) ((ht_param) & BIT(2)) +#define GETSUPP_TXBASTREAMS(dot_11n_dev_cap) (((dot_11n_dev_cap) >> 18) & = 0xF) + +/* httxcfg bitmap + * 0 reserved + * 1 20/40 Mhz enable(1)/disable(0) + * 2-3 reserved + * 4 green field enable(1)/disable(0) + * 5 short GI in 20 Mhz enable(1)/disable(0) + * 6 short GI in 40 Mhz enable(1)/disable(0) + * 7-15 reserved + */ +#define NXPWIFI_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6)) + +/* 11AC Tx and Rx MCS map for 1x1 mode: + * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 + * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 7 streams + */ +#define NXPWIFI_11AC_MCS_MAP_1X1 0xfffefffe + +/* 11AC Tx and Rx MCS map for 2x2 mode: + * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 and 2 + * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 6 streams + */ +#define NXPWIFI_11AC_MCS_MAP_2X2 0xfffafffa + +#define GET_RXMCSSUPP(dev_mcs_supported) ((dev_mcs_supported) & 0x0f) +#define SETHT_MCS32(x) (x[4] |=3D 1) +#define HT_STREAM_1X1 0x11 +#define HT_STREAM_2X2 0x22 + +#define SET_SECONDARYCHAN(radio_type, sec_chan) \ + ((radio_type) |=3D ((sec_chan) << 4)) + +#define LLC_SNAP_LEN 8 + +/* HW_SPEC fw_cap_info */ + +#define ISSUPP_11ACENABLED(fw_cap_info) ((fw_cap_info) & BIT(13)) + +#define GET_VHTCAP_CHWDSET(vht_cap_info) (((vht_cap_info) >> 2) & 0x3) +#define GET_VHTNSSMCS(mcs_mapset, nss) \ + (((mcs_mapset) >> (2 * ((nss) - 1))) & 0x3) +#define SET_VHTNSSMCS(mcs_mapset, nss, value) \ + ((mcs_mapset) |=3D ((value) & 0x3) << (2 * ((nss) - 1))) +#define GET_DEVTXMCSMAP(dev_mcs_map) ((dev_mcs_map) >> 16) +#define GET_DEVRXMCSMAP(dev_mcs_map) ((dev_mcs_map) & 0xFFFF) + +/* Clear SU Beanformer, MU beanformer, MU beanformee and + * sounding dimensions bits + */ +#define NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK \ + (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | \ + IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE | \ + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | \ + IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK) + +#define MOD_CLASS_HR_DSSS 0x03 +#define MOD_CLASS_OFDM 0x07 +#define MOD_CLASS_HT 0x08 +#define HT_BW_20 0 +#define HT_BW_40 1 + +#define DFS_CHAN_MOVE_TIME 10000 + +#define HOST_CMD_GET_HW_SPEC 0x0003 +#define HOST_CMD_802_11_SCAN 0x0006 +#define HOST_CMD_802_11_GET_LOG 0x000b +#define HOST_CMD_MAC_MULTICAST_ADR 0x0010 +#define HOST_CMD_802_11_ASSOCIATE 0x0012 +#define HOST_CMD_802_11_SNMP_MIB 0x0016 +#define HOST_CMD_MAC_REG_ACCESS 0x0019 +#define HOST_CMD_BBP_REG_ACCESS 0x001a +#define HOST_CMD_RF_REG_ACCESS 0x001b +#define HOST_CMD_RF_TX_PWR 0x001e +#define HOST_CMD_RF_ANTENNA 0x0020 +#define HOST_CMD_802_11_DEAUTHENTICATE 0x0024 +#define HOST_CMD_MAC_CONTROL 0x0028 +#define HOST_CMD_802_11_MAC_ADDRESS 0x004D +#define HOST_CMD_802_11_EEPROM_ACCESS 0x0059 +#define HOST_CMD_802_11D_DOMAIN_INFO 0x005b +#define HOST_CMD_802_11_KEY_MATERIAL 0x005e +#define HOST_CMD_802_11_BG_SCAN_CONFIG 0x006b +#define HOST_CMD_802_11_BG_SCAN_QUERY 0x006c +#define HOST_CMD_WMM_GET_STATUS 0x0071 +#define HOST_CMD_802_11_SUBSCRIBE_EVENT 0x0075 +#define HOST_CMD_802_11_TX_RATE_QUERY 0x007f +#define HOST_CMD_MEM_ACCESS 0x0086 +#define HOST_CMD_CFG_DATA 0x008f +#define HOST_CMD_VERSION_EXT 0x0097 +#define HOST_CMD_MEF_CFG 0x009a +#define HOST_CMD_RSSI_INFO 0x00a4 +#define HOST_CMD_FUNC_INIT 0x00a9 +#define HOST_CMD_FUNC_SHUTDOWN 0x00aa +#define HOST_CMD_PMIC_REG_ACCESS 0x00ad +#define HOST_CMD_APCMD_SYS_RESET 0x00af +#define HOST_CMD_UAP_SYS_CONFIG 0x00b0 +#define HOST_CMD_UAP_BSS_START 0x00b1 +#define HOST_CMD_UAP_BSS_STOP 0x00b2 +#define HOST_CMD_APCMD_STA_LIST 0x00b3 +#define HOST_CMD_UAP_STA_DEAUTH 0x00b5 +#define HOST_CMD_11N_CFG 0x00cd +#define HOST_CMD_11N_ADDBA_REQ 0x00ce +#define HOST_CMD_11N_ADDBA_RSP 0x00cf +#define HOST_CMD_11N_DELBA 0x00d0 +#define HOST_CMD_TXPWR_CFG 0x00d1 +#define HOST_CMD_TX_RATE_CFG 0x00d6 +#define HOST_CMD_RECONFIGURE_TX_BUFF 0x00d9 +#define HOST_CMD_CHAN_REPORT_REQUEST 0x00dd +#define HOST_CMD_AMSDU_AGGR_CTRL 0x00df +#define HOST_CMD_ROBUST_COEX 0x00e0 +#define HOST_CMD_802_11_PS_MODE_ENH 0x00e4 +#define HOST_CMD_802_11_HS_CFG_ENH 0x00e5 +#define HOST_CMD_CAU_REG_ACCESS 0x00ed +#define HOST_CMD_SET_BSS_MODE 0x00f7 +#define HOST_CMD_PCIE_DESC_DETAILS 0x00fa +#define HOST_CMD_802_11_SCAN_EXT 0x0107 +#define HOST_CMD_COALESCE_CFG 0x010a +#define HOST_CMD_MGMT_FRAME_REG 0x010c +#define HOST_CMD_REMAIN_ON_CHAN 0x010d +#define HOST_CMD_GTK_REKEY_OFFLOAD_CFG 0x010f +#define HOST_CMD_11AC_CFG 0x0112 +#define HOST_CMD_HS_WAKEUP_REASON 0x0116 +#define HOST_CMD_MC_POLICY 0x0121 +#define HOST_CMD_FW_DUMP_EVENT 0x0125 +#define HOST_CMD_SDIO_SP_RX_AGGR_CFG 0x0223 +#define HOST_CMD_STA_CONFIGURE 0x023f +#define HOST_CMD_CHAN_REGION_CFG 0x0242 +#define HOST_CMD_PACKET_AGGR_CTRL 0x0251 +#define HOST_CMD_ADD_NEW_STATION 0x025f + +#define PROTOCOL_NO_SECURITY 0x01 +#define PROTOCOL_STATIC_WEP 0x02 +#define PROTOCOL_WPA 0x08 +#define PROTOCOL_WPA2 0x20 +#define PROTOCOL_WPA2_MIXED 0x28 +#define PROTOCOL_EAP 0x40 +#define KEY_MGMT_EAP 0x01 +#define KEY_MGMT_PSK 0x02 +#define KEY_MGMT_NONE 0x04 +#define KEY_MGMT_OWE 0x200 +#define KEY_MGMT_SAE 0x400 +#define CIPHER_TKIP 0x04 +#define CIPHER_AES_CCMP 0x08 +#define VALID_CIPHER_BITMAP 0x0c + +enum ENH_PS_MODES { + EN_PS =3D 1, + DIS_PS =3D 2, + EN_AUTO_DS =3D 3, + DIS_AUTO_DS =3D 4, + SLEEP_CONFIRM =3D 5, + GET_PS =3D 0, + EN_AUTO_PS =3D 0xff, + DIS_AUTO_PS =3D 0xfe, +}; + +enum nxpwifi_channel_flags { + NXPWIFI_CHANNEL_PASSIVE =3D BIT(0), + NXPWIFI_CHANNEL_DFS =3D BIT(1), + NXPWIFI_CHANNEL_NOHT40 =3D BIT(2), + NXPWIFI_CHANNEL_NOHT80 =3D BIT(3), + NXPWIFI_CHANNEL_DISABLED =3D BIT(7), +}; + +#define HOST_RET_BIT 0x8000 +#define HOST_ACT_GEN_GET 0x0000 +#define HOST_ACT_GEN_SET 0x0001 +#define HOST_ACT_GEN_REMOVE 0x0004 +#define HOST_ACT_BITWISE_SET 0x0002 +#define HOST_ACT_BITWISE_CLR 0x0003 +#define HOST_RESULT_OK 0x0000 +#define HOST_ACT_MAC_RX_ON BIT(0) +#define HOST_ACT_MAC_TX_ON BIT(1) +#define HOST_ACT_MAC_WEP_ENABLE BIT(3) +#define HOST_ACT_MAC_ETHERNETII_ENABLE BIT(4) +#define HOST_ACT_MAC_PROMISCUOUS_ENABLE BIT(7) +#define HOST_ACT_MAC_ALL_MULTICAST_ENABLE BIT(8) +#define HOST_ACT_MAC_DYNAMIC_BW_ENABLE BIT(16) + +#define HOST_BSS_MODE_IBSS 0x0002 +#define HOST_BSS_MODE_ANY 0x0003 + +#define HOST_SCAN_RADIO_TYPE_BG 0 +#define HOST_SCAN_RADIO_TYPE_A 1 + +#define HS_CFG_CANCEL 0xffffffff +#define HS_CFG_COND_DEF 0x00000000 +#define HS_CFG_GPIO_DEF 0xff +#define HS_CFG_GAP_DEF 0xff +#define HS_CFG_COND_BROADCAST_DATA 0x00000001 +#define HS_CFG_COND_UNICAST_DATA 0x00000002 +#define HS_CFG_COND_MAC_EVENT 0x00000004 +#define HS_CFG_COND_MULTICAST_DATA 0x00000008 + +#define CONNECT_ERR_AUTH_ERR_STA_FAILURE 0xFFFB +#define CONNECT_ERR_ASSOC_ERR_TIMEOUT 0xFFFC +#define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED 0xFFFD +#define CONNECT_ERR_AUTH_MSG_UNHANDLED 0xFFFE +#define CONNECT_ERR_STA_FAILURE 0xFFFF + +#define CMD_F_HOSTCMD BIT(0) + +#define HOST_CMD_ID_MASK 0x0fff + +#define HOST_SEQ_NUM_MASK 0x00ff + +#define HOST_BSS_NUM_MASK 0x0f00 + +#define HOST_BSS_TYPE_MASK 0xf000 + +#define HOST_ACT_SET_RX 0x0001 +#define HOST_ACT_SET_TX 0x0002 +#define HOST_ACT_SET_BOTH 0x0003 +#define HOST_ACT_GET_RX 0x0004 +#define HOST_ACT_GET_TX 0x0008 +#define HOST_ACT_GET_BOTH 0x000c + +#define HOST_ACT_REMOVE_STA 0x0 +#define HOST_ACT_ADD_STA 0x1 + +#define RF_ANTENNA_AUTO 0xFFFF + +#define HOST_SET_SEQ_NO_BSS_INFO(seq, num, type) \ + ((((seq) & 0x00ff) | \ + (((num) & 0x000f) << 8)) | \ + (((type) & 0x000f) << 12)) + +#define HOST_GET_SEQ_NO(seq) \ + ((seq) & HOST_SEQ_NUM_MASK) + +#define HOST_GET_BSS_NO(seq) \ + (((seq) & HOST_BSS_NUM_MASK) >> 8) + +#define HOST_GET_BSS_TYPE(seq) \ + (((seq) & HOST_BSS_TYPE_MASK) >> 12) + +#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001 +#define EVENT_LINK_LOST 0x00000003 +#define EVENT_LINK_SENSED 0x00000004 +#define EVENT_MIB_CHANGED 0x00000006 +#define EVENT_INIT_DONE 0x00000007 +#define EVENT_DEAUTHENTICATED 0x00000008 +#define EVENT_DISASSOCIATED 0x00000009 +#define EVENT_PS_AWAKE 0x0000000a +#define EVENT_PS_SLEEP 0x0000000b +#define EVENT_MIC_ERR_MULTICAST 0x0000000d +#define EVENT_MIC_ERR_UNICAST 0x0000000e +#define EVENT_DEEP_SLEEP_AWAKE 0x00000010 +#define EVENT_WMM_STATUS_CHANGE 0x00000017 +#define EVENT_BG_SCAN_REPORT 0x00000018 +#define EVENT_RSSI_LOW 0x00000019 +#define EVENT_SNR_LOW 0x0000001a +#define EVENT_MAX_FAIL 0x0000001b +#define EVENT_RSSI_HIGH 0x0000001c +#define EVENT_SNR_HIGH 0x0000001d +#define EVENT_DATA_RSSI_LOW 0x00000024 +#define EVENT_DATA_SNR_LOW 0x00000025 +#define EVENT_DATA_RSSI_HIGH 0x00000026 +#define EVENT_DATA_SNR_HIGH 0x00000027 +#define EVENT_LINK_QUALITY 0x00000028 +#define EVENT_PORT_RELEASE 0x0000002b +#define EVENT_UAP_STA_DEAUTH 0x0000002c +#define EVENT_UAP_STA_ASSOC 0x0000002d +#define EVENT_UAP_BSS_START 0x0000002e +#define EVENT_PRE_BEACON_LOST 0x00000031 +#define EVENT_ADDBA 0x00000033 +#define EVENT_DELBA 0x00000034 +#define EVENT_BA_STREAM_TIEMOUT 0x00000037 +#define EVENT_AMSDU_AGGR_CTRL 0x00000042 +#define EVENT_UAP_BSS_IDLE 0x00000043 +#define EVENT_UAP_BSS_ACTIVE 0x00000044 +#define EVENT_WEP_ICV_ERR 0x00000046 +#define EVENT_HS_ACT_REQ 0x00000047 +#define EVENT_BW_CHANGE 0x00000048 +#define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c +#define EVENT_HOSTWAKE_STAIE 0x0000004d +#define EVENT_CHANNEL_SWITCH_ANN 0x00000050 +#define EVENT_RADAR_DETECTED 0x00000053 +#define EVENT_CHANNEL_REPORT_RDY 0x00000054 +#define EVENT_TX_DATA_PAUSE 0x00000055 +#define EVENT_EXT_SCAN_REPORT 0x00000058 +#define EVENT_RXBA_SYNC 0x00000059 +#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f +#define EVENT_UNKNOWN_DEBUG 0x00000063 +#define EVENT_BG_SCAN_STOPPED 0x00000065 +#define EVENT_MULTI_CHAN_INFO 0x0000006a +#define EVENT_FW_DUMP_INFO 0x00000073 +#define EVENT_TX_STATUS_REPORT 0x00000074 +#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076 + +#define EVENT_ID_MASK 0xffff +#define BSS_NUM_MASK 0xf + +#define EVENT_GET_BSS_NUM(event_cause) \ + (((event_cause) >> 16) & BSS_NUM_MASK) + +#define EVENT_GET_BSS_TYPE(event_cause) \ + (((event_cause) >> 24) & 0x00ff) + +#define NXPWIFI_MAX_PATTERN_LEN 40 +#define NXPWIFI_MAX_OFFSET_LEN 100 +#define NXPWIFI_MAX_ND_MATCH_SETS 10 + +#define STACK_NBYTES 100 +#define TYPE_DNUM 1 +#define TYPE_BYTESEQ 2 +#define MAX_OPERAND 0x40 +#define TYPE_EQ (MAX_OPERAND + 1) +#define TYPE_EQ_DNUM (MAX_OPERAND + 2) +#define TYPE_EQ_BIT (MAX_OPERAND + 3) +#define TYPE_AND (MAX_OPERAND + 4) +#define TYPE_OR (MAX_OPERAND + 5) +#define MEF_MODE_HOST_SLEEP 1 +#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 +#define MEF_ACTION_AUTO_ARP 0x10 +#define NXPWIFI_CRITERIA_BROADCAST BIT(0) +#define NXPWIFI_CRITERIA_UNICAST BIT(1) +#define NXPWIFI_CRITERIA_MULTICAST BIT(3) +#define NXPWIFI_MAX_SUPPORTED_IPADDR 4 + +#define NXPWIFI_DEF_CS_UNIT_TIME 2 +#define NXPWIFI_DEF_CS_THR_OTHERLINK 10 +#define NXPWIFI_DEF_THR_DIRECTLINK 0 +#define NXPWIFI_DEF_CS_TIME 10 +#define NXPWIFI_DEF_CS_TIMEOUT 16 +#define NXPWIFI_DEF_CS_REG_CLASS 12 +#define NXPWIFI_DEF_CS_PERIODICITY 1 + +#define NXPWIFI_FW_V15 15 + +#define NXPWIFI_MASTER_RADAR_DET_MASK BIT(1) + +struct nxpwifi_ie_types_header { + __le16 type; + __le16 len; +} __packed; + +struct nxpwifi_ie_types_data { + struct nxpwifi_ie_types_header header; + u8 data[]; +} __packed; + +#define NXPWIFI_TxPD_POWER_MGMT_NULL_PACKET 0x01 +#define NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET 0x08 +#define NXPWIFI_TXPD_FLAGS_REQ_TX_STATUS 0x20 + +enum HS_WAKEUP_REASON { + NO_HSWAKEUP_REASON =3D 0, + BCAST_DATA_MATCHED, + MCAST_DATA_MATCHED, + UCAST_DATA_MATCHED, + MASKTABLE_EVENT_MATCHED, + NON_MASKABLE_EVENT_MATCHED, + NON_MASKABLE_CONDITION_MATCHED, + MAGIC_PATTERN_MATCHED, + CONTROL_FRAME_MATCHED, + MANAGEMENT_FRAME_MATCHED, + GTK_REKEY_FAILURE, + RESERVED +}; + +struct txpd { + u8 bss_type; + u8 bss_num; + __le16 tx_pkt_length; + __le16 tx_pkt_offset; + __le16 tx_pkt_type; + __le32 tx_control; + u8 priority; + u8 flags; + u8 pkt_delay_2ms; + u8 reserved1[2]; + u8 tx_token_id; + u8 reserved[2]; +} __packed; + +struct rxpd { + u8 bss_type; + u8 bss_num; + __le16 rx_pkt_length; + __le16 rx_pkt_offset; + __le16 rx_pkt_type; + __le16 seq_num; + u8 priority; + u8 rx_rate; + s8 snr; + s8 nf; + + /* For: Non-802.11 AC cards + * + * Ht Info [Bit 0] RxRate format: LG=3D0, HT=3D1 + * [Bit 1] HT Bandwidth: BW20 =3D 0, BW40 =3D 1 + * [Bit 2] HT Guard Interval: LGI =3D 0, SGI =3D 1 + * + * For: 802.11 AC cards + * [Bit 1] [Bit 0] RxRate format: legacy rate =3D 00 HT =3D 01 VHT =3D 10 + * [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 =3D 00 BW40 =3D 01 + * BW80 =3D 10 BW160 =3D 11 + * [Bit 4] HT/VHT Guard interval LGI =3D 0 SGI =3D 1 + * [Bit 5] STBC support Enabled =3D 1 + * [Bit 6] LDPC support Enabled =3D 1 + * [Bit 7] Reserved + */ + u8 ht_info; + u8 reserved[3]; + u8 flags; +} __packed; + +struct uap_txpd { + u8 bss_type; + u8 bss_num; + __le16 tx_pkt_length; + __le16 tx_pkt_offset; + __le16 tx_pkt_type; + __le32 tx_control; + u8 priority; + u8 flags; + u8 pkt_delay_2ms; + u8 reserved1[2]; + u8 tx_token_id; + u8 reserved[2]; +} __packed; + +struct uap_rxpd { + u8 bss_type; + u8 bss_num; + __le16 rx_pkt_length; + __le16 rx_pkt_offset; + __le16 rx_pkt_type; + __le16 seq_num; + u8 priority; + u8 rx_rate; + s8 snr; + s8 nf; + u8 ht_info; + u8 reserved[3]; + u8 flags; +} __packed; + +struct nxpwifi_auth { + __le16 auth_alg; + __le16 auth_transaction; + __le16 status_code; + /* possibly followed by Challenge text */ + u8 variable[]; +} __packed; + +struct nxpwifi_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]; + struct nxpwifi_auth auth; +} __packed; + +struct nxpwifi_fw_chan_stats { + u8 chan_num; + u8 bandcfg; + u8 flags; + s8 noise; + __le16 total_bss; + __le16 cca_scan_dur; + __le16 cca_busy_dur; +} __packed; + +enum nxpwifi_chan_scan_mode_bitmasks { + NXPWIFI_PASSIVE_SCAN =3D BIT(0), + NXPWIFI_DISABLE_CHAN_FILT =3D BIT(1), + NXPWIFI_HIDDEN_SSID_REPORT =3D BIT(4), +}; + +struct nxpwifi_chan_scan_param_set { + u8 radio_type; + u8 chan_number; + u8 chan_scan_mode_bmap; + __le16 min_scan_time; + __le16 max_scan_time; +} __packed; + +struct nxpwifi_ie_types_chan_list_param_set { + struct nxpwifi_ie_types_header header; + struct nxpwifi_chan_scan_param_set chan_scan_param[]; +} __packed; + +struct nxpwifi_ie_types_rxba_sync { + struct nxpwifi_ie_types_header header; + u8 mac[ETH_ALEN]; + u8 tid; + u8 reserved; + __le16 seq_num; + __le16 bitmap_len; + u8 bitmap[]; +} __packed; + +struct chan_band_param_set { + u8 radio_type; + u8 chan_number; +}; + +struct nxpwifi_ie_types_chan_band_list_param_set { + struct nxpwifi_ie_types_header header; + struct chan_band_param_set chan_band_param[]; +} __packed; + +struct nxpwifi_ie_types_rates_param_set { + struct nxpwifi_ie_types_header header; + u8 rates[]; +} __packed; + +struct nxpwifi_ie_types_ssid_param_set { + struct nxpwifi_ie_types_header header; + u8 ssid[]; +} __packed; + +struct nxpwifi_ie_types_host_mlme { + struct nxpwifi_ie_types_header header; + u8 host_mlme; +} __packed; + +struct nxpwifi_ie_types_num_probes { + struct nxpwifi_ie_types_header header; + __le16 num_probes; +} __packed; + +struct nxpwifi_ie_types_repeat_count { + struct nxpwifi_ie_types_header header; + __le16 repeat_count; +} __packed; + +struct nxpwifi_ie_types_min_rssi_threshold { + struct nxpwifi_ie_types_header header; + __le16 rssi_threshold; +} __packed; + +struct nxpwifi_ie_types_bgscan_start_later { + struct nxpwifi_ie_types_header header; + __le16 start_later; +} __packed; + +struct nxpwifi_ie_types_scan_chan_gap { + struct nxpwifi_ie_types_header header; + /* time gap in TUs to be used between two consecutive channels scan */ + __le16 chan_gap; +} __packed; + +struct nxpwifi_ie_types_random_mac { + struct nxpwifi_ie_types_header header; + u8 mac[ETH_ALEN]; +} __packed; + +struct nxpwifi_ietypes_chanstats { + struct nxpwifi_ie_types_header header; + struct nxpwifi_fw_chan_stats chanstats[]; +} __packed; + +struct nxpwifi_ie_types_wildcard_ssid_params { + struct nxpwifi_ie_types_header header; + u8 max_ssid_length; + u8 ssid[]; +} __packed; + +#define TSF_DATA_SIZE 8 +struct nxpwifi_ie_types_tsf_timestamp { + struct nxpwifi_ie_types_header header; + u8 tsf_data[]; +} __packed; + +struct nxpwifi_cf_param_set { + u8 cfp_cnt; + u8 cfp_period; + __le16 cfp_max_duration; + __le16 cfp_duration_remaining; +} __packed; + +struct nxpwifi_ibss_param_set { + __le16 atim_window; +} __packed; + +struct nxpwifi_ie_types_ss_param_set { + struct nxpwifi_ie_types_header header; + union { + struct nxpwifi_cf_param_set cf_param_set[1]; + struct nxpwifi_ibss_param_set ibss_param_set[1]; + } cf_ibss; +} __packed; + +struct nxpwifi_fh_param_set { + __le16 dwell_time; + u8 hop_set; + u8 hop_pattern; + u8 hop_index; +} __packed; + +struct nxpwifi_ds_param_set { + u8 current_chan; +} __packed; + +struct nxpwifi_ie_types_phy_param_set { + struct nxpwifi_ie_types_header header; + union { + struct nxpwifi_fh_param_set fh_param_set[1]; + struct nxpwifi_ds_param_set ds_param_set[1]; + } fh_ds; +} __packed; + +struct nxpwifi_ie_types_auth_type { + struct nxpwifi_ie_types_header header; + __le16 auth_type; +} __packed; + +struct nxpwifi_ie_types_vendor_param_set { + struct nxpwifi_ie_types_header header; + u8 ie[NXPWIFI_MAX_VSIE_LEN]; +}; + +#define NXPWIFI_AUTHTYPE_SAE 6 + +struct nxpwifi_ie_types_sae_pwe_mode { + struct nxpwifi_ie_types_header header; + u8 pwe[]; +} __packed; + +struct nxpwifi_ie_types_rsn_param_set { + struct nxpwifi_ie_types_header header; + u8 rsn_ie[]; +} __packed; + +#define KEYPARAMSET_FIXED_LEN 6 + +#define IGTK_PN_LEN 8 + +struct nxpwifi_cmac_param { + u8 ipn[IGTK_PN_LEN]; + u8 key[WLAN_KEY_LEN_AES_CMAC]; +} __packed; + +struct nxpwifi_wep_param { + __le16 key_len; + u8 key[WLAN_KEY_LEN_WEP104]; +} __packed; + +struct nxpwifi_tkip_param { + u8 pn[WPA_PN_SIZE]; + __le16 key_len; + u8 key[WLAN_KEY_LEN_TKIP]; +} __packed; + +struct nxpwifi_aes_param { + u8 pn[WPA_PN_SIZE]; + __le16 key_len; + u8 key[WLAN_KEY_LEN_CCMP_256]; +} __packed; + +struct nxpwifi_cmac_aes_param { + u8 ipn[IGTK_PN_LEN]; + __le16 key_len; + u8 key[WLAN_KEY_LEN_AES_CMAC]; +} __packed; + +struct nxpwifi_ie_type_key_param_set { + __le16 type; + __le16 len; + u8 mac_addr[ETH_ALEN]; + u8 key_idx; + u8 key_type; + __le16 key_info; + union { + struct nxpwifi_wep_param wep; + struct nxpwifi_tkip_param tkip; + struct nxpwifi_aes_param aes; + struct nxpwifi_cmac_aes_param cmac_aes; + } key_params; +} __packed; + +struct host_cmd_ds_802_11_key_material { + __le16 action; + struct nxpwifi_ie_type_key_param_set key_param_set; +} __packed; + +struct host_cmd_ds_gen { + __le16 command; + __le16 size; + __le16 seq_num; + __le16 result; +}; + +#define S_DS_GEN sizeof(struct host_cmd_ds_gen) + +enum sleep_resp_ctrl { + RESP_NOT_NEEDED =3D 0, + RESP_NEEDED, +}; + +struct nxpwifi_ps_param { + __le16 null_pkt_interval; + __le16 multiple_dtims; + __le16 bcn_miss_timeout; + __le16 local_listen_interval; + __le16 reserved; + __le16 mode; + __le16 delay_to_ps; +} __packed; + +#define HS_DEF_WAKE_INTERVAL 100 +#define HS_DEF_INACTIVITY_TIMEOUT 50 + +struct nxpwifi_ps_param_in_hs { + struct nxpwifi_ie_types_header header; + __le32 hs_wake_int; + __le32 hs_inact_timeout; +} __packed; + +#define BITMAP_AUTO_DS 0x01 +#define BITMAP_STA_PS 0x10 + +struct nxpwifi_ie_types_auto_ds_param { + struct nxpwifi_ie_types_header header; + __le16 deep_sleep_timeout; +} __packed; + +struct nxpwifi_ie_types_ps_param { + struct nxpwifi_ie_types_header header; + struct nxpwifi_ps_param param; +} __packed; + +struct host_cmd_ds_802_11_ps_mode_enh { + __le16 action; + + union { + struct nxpwifi_ps_param opt_ps; + __le16 ps_bitmap; + } params; +} __packed; + +enum API_VER_ID { + KEY_API_VER_ID =3D 1, + FW_API_VER_ID =3D 2, + UAP_FW_API_VER_ID =3D 3, + CHANRPT_API_VER_ID =3D 4, + FW_HOTFIX_VER_ID =3D 5, +}; + +struct hw_spec_api_rev { + struct nxpwifi_ie_types_header header; + __le16 api_id; + u8 major_ver; + u8 minor_ver; +} __packed; + +struct host_cmd_ds_get_hw_spec { + __le16 hw_if_version; + __le16 version; + __le16 reserved; + __le16 num_of_mcast_adr; + u8 permanent_addr[ETH_ALEN]; + __le16 region_code; + __le16 number_of_antenna; + __le32 fw_release_number; + __le32 reserved_1; + __le32 reserved_2; + __le32 reserved_3; + __le32 fw_cap_info; + __le32 dot_11n_dev_cap; + u8 dev_mcs_support; + __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ + __le16 mgmt_buf_count; /* mgmt IE buffer count */ + __le32 reserved_4; + __le32 reserved_5; + __le32 dot_11ac_dev_cap; + __le32 dot_11ac_mcs_support; + u8 tlvs[]; +} __packed; + +struct host_cmd_ds_802_11_rssi_info { + __le16 action; + __le16 ndata; + __le16 nbcn; + __le16 reserved[9]; + long long reserved_1; +} __packed; + +struct host_cmd_ds_802_11_rssi_info_rsp { + __le16 action; + __le16 ndata; + __le16 nbcn; + __le16 data_rssi_last; + __le16 data_nf_last; + __le16 data_rssi_avg; + __le16 data_nf_avg; + __le16 bcn_rssi_last; + __le16 bcn_nf_last; + __le16 bcn_rssi_avg; + __le16 bcn_nf_avg; + long long tsf_bcn; +} __packed; + +struct host_cmd_ds_802_11_mac_address { + __le16 action; + u8 mac_addr[ETH_ALEN]; +} __packed; + +struct host_cmd_ds_mac_control { + __le32 action; +}; + +struct host_cmd_ds_mac_multicast_adr { + __le16 action; + __le16 num_of_adrs; + u8 mac_list[NXPWIFI_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; +} __packed; + +struct host_cmd_ds_802_11_deauthenticate { + u8 mac_addr[ETH_ALEN]; + __le16 reason_code; +} __packed; + +struct host_cmd_ds_802_11_associate { + u8 peer_sta_addr[ETH_ALEN]; + __le16 cap_info_bitmap; + __le16 listen_interval; + __le16 beacon_period; + u8 dtim_period; +} __packed; + +struct ieee_types_assoc_rsp { + __le16 cap_info_bitmap; + __le16 status_code; + __le16 a_id; + u8 ie_buffer[]; +} __packed; + +struct host_cmd_ds_802_11_associate_rsp { + struct ieee_types_assoc_rsp assoc_rsp; +} __packed; + +struct ieee_types_cf_param_set { + u8 element_id; + u8 len; + u8 cfp_cnt; + u8 cfp_period; + __le16 cfp_max_duration; + __le16 cfp_duration_remaining; +} __packed; + +struct ieee_types_ibss_param_set { + u8 element_id; + u8 len; + __le16 atim_window; +} __packed; + +union ieee_types_ss_param_set { + struct ieee_types_cf_param_set cf_param_set; + struct ieee_types_ibss_param_set ibss_param_set; +} __packed; + +struct ieee_types_fh_param_set { + u8 element_id; + u8 len; + __le16 dwell_time; + u8 hop_set; + u8 hop_pattern; + u8 hop_index; +} __packed; + +struct ieee_types_ds_param_set { + u8 element_id; + u8 len; + u8 current_chan; +} __packed; + +union ieee_types_phy_param_set { + struct ieee_types_fh_param_set fh_param_set; + struct ieee_types_ds_param_set ds_param_set; +} __packed; + +struct ieee_types_oper_mode_ntf { + u8 element_id; + u8 len; + u8 oper_mode; +} __packed; + +struct host_cmd_ds_802_11_get_log { + __le32 mcast_tx_frame; + __le32 failed; + __le32 retry; + __le32 multi_retry; + __le32 frame_dup; + __le32 rts_success; + __le32 rts_failure; + __le32 ack_failure; + __le32 rx_frag; + __le32 mcast_rx_frame; + __le32 fcs_error; + __le32 tx_frame; + __le32 reserved; + __le32 wep_icv_err_cnt[4]; + __le32 bcn_rcv_cnt; + __le32 bcn_miss_cnt; +} __packed; + +/* Enumeration for rate format */ +enum nxpwifi_rate_format { + NXPWIFI_RATE_FORMAT_LG =3D 0, + NXPWIFI_RATE_FORMAT_HT, + NXPWIFI_RATE_FORMAT_VHT, + NXPWIFI_RATE_FORMAT_AUTO =3D 0xFF, +}; + +struct host_cmd_ds_tx_rate_query { + u8 tx_rate; + /* Tx Rate Info: For 802.11 AC cards + * + * [Bit 0-1] tx rate formate: LG =3D 0, HT =3D 1, VHT =3D 2 + * [Bit 2-3] HT/VHT Bandwidth: BW20 =3D 0, BW40 =3D 1, BW80 =3D 2, BW160 = =3D 3 + * [Bit 4] HT/VHT Guard Interval: LGI =3D 0, SGI =3D 1 + * + * For non-802.11 AC cards + * Ht Info [Bit 0] RxRate format: LG=3D0, HT=3D1 + * [Bit 1] HT Bandwidth: BW20 =3D 0, BW40 =3D 1 + * [Bit 2] HT Guard Interval: LGI =3D 0, SGI =3D 1 + */ + u8 ht_info; +} __packed; + +struct nxpwifi_tx_pause_tlv { + struct nxpwifi_ie_types_header header; + u8 peermac[ETH_ALEN]; + u8 tx_pause; + u8 pkt_cnt; +} __packed; + +enum host_sleep_action { + HS_CONFIGURE =3D 0x0001, + HS_ACTIVATE =3D 0x0002, +}; + +struct nxpwifi_hs_config_param { + __le32 conditions; + u8 gpio; + u8 gap; +} __packed; + +struct hs_activate_param { + __le16 resp_ctrl; +} __packed; + +struct host_cmd_ds_802_11_hs_cfg_enh { + __le16 action; + + union { + struct nxpwifi_hs_config_param hs_config; + struct hs_activate_param hs_activate; + } params; +} __packed; + +enum SNMP_MIB_INDEX { + OP_RATE_SET_I =3D 1, + DTIM_PERIOD_I =3D 3, + RTS_THRESH_I =3D 5, + SHORT_RETRY_LIM_I =3D 6, + LONG_RETRY_LIM_I =3D 7, + FRAG_THRESH_I =3D 8, + DOT11D_I =3D 9, + DOT11H_I =3D 10, +}; + +enum nxpwifi_assocmd_failurepoint { + NXPWIFI_ASSOC_CMD_SUCCESS =3D 0, + NXPWIFI_ASSOC_CMD_FAILURE_ASSOC, + NXPWIFI_ASSOC_CMD_FAILURE_AUTH, + NXPWIFI_ASSOC_CMD_FAILURE_JOIN +}; + +#define MAX_SNMP_BUF_SIZE 128 + +struct host_cmd_ds_802_11_snmp_mib { + __le16 query_type; + __le16 oid; + __le16 buf_size; + u8 value[]; +} __packed; + +struct nxpwifi_rate_scope { + __le16 type; + __le16 length; + __le16 hr_dsss_rate_bitmap; + __le16 ofdm_rate_bitmap; + __le16 ht_mcs_rate_bitmap[8]; + __le16 vht_mcs_rate_bitmap[8]; +} __packed; + +struct nxpwifi_rate_drop_pattern { + __le16 type; + __le16 length; + __le32 rate_drop_mode; +} __packed; + +struct host_cmd_ds_tx_rate_cfg { + __le16 action; + __le16 cfg_index; +} __packed; + +struct nxpwifi_power_group { + u8 modulation_class; + u8 first_rate_code; + u8 last_rate_code; + s8 power_step; + s8 power_min; + s8 power_max; + u8 ht_bandwidth; + u8 reserved; +} __packed; + +struct nxpwifi_types_power_group { + __le16 type; + __le16 length; +} __packed; + +struct host_cmd_ds_txpwr_cfg { + __le16 action; + __le16 cfg_index; + __le32 mode; +} __packed; + +struct host_cmd_ds_rf_tx_pwr { + __le16 action; + __le16 cur_level; + u8 max_power; + u8 min_power; +} __packed; + +struct host_cmd_ds_rf_ant_mimo { + __le16 action_tx; + __le16 tx_ant_mode; + __le16 action_rx; + __le16 rx_ant_mode; +} __packed; + +struct host_cmd_ds_rf_ant_siso { + __le16 action; + __le16 ant_mode; +} __packed; + +#define BAND_CFG_CHAN_BAND_MASK 0x03 +#define BAND_CFG_CHAN_BAND_SHIFT_BIT 0 +#define BAND_CFG_CHAN_WIDTH_MASK 0x0C +#define BAND_CFG_CHAN_WIDTH_SHIFT_BIT 2 +#define BAND_CFG_CHAN2_OFFSET_MASK 0x30 +#define BAND_CFG_CHAN2_SHIFT_BIT 4 + +struct nxpwifi_chan_desc { + __le16 start_freq; + u8 band_cfg; + u8 chan_num; +} __packed; + +struct host_cmd_ds_chan_rpt_req { + struct nxpwifi_chan_desc chan_desc; + __le32 msec_dwell_time; +} __packed; + +struct host_cmd_ds_chan_rpt_event { + __le32 result; + __le64 start_tsf; + __le32 duration; + u8 tlvbuf[]; +} __packed; + +struct host_cmd_sdio_sp_rx_aggr_cfg { + u8 action; + u8 enable; + __le16 block_size; +} __packed; + +struct nxpwifi_fixed_bcn_param { + __le64 timestamp; + __le16 beacon_period; + __le16 cap_info_bitmap; +} __packed; + +struct nxpwifi_event_scan_result { + __le16 event_id; + u8 bss_index; + u8 bss_type; + u8 more_event; + u8 reserved[3]; + __le16 buf_size; + u8 num_of_set; +} __packed; + +struct tx_status_event { + u8 packet_type; + u8 tx_token_id; + u8 status; +} __packed; + +#define NXPWIFI_USER_SCAN_CHAN_MAX 50 + +#define NXPWIFI_MAX_SSID_LIST_LENGTH 10 + +struct nxpwifi_scan_cmd_config { + /* BSS mode to be sent in the firmware command + */ + u8 bss_mode; + + /* Specific BSSID used to filter scan results in the firmware */ + u8 specific_bssid[ETH_ALEN]; + + /* Length of TLVs sent in command starting at tlvBuffer */ + u32 tlv_buf_len; + + /* SSID TLV(s) and ChanList TLVs to be sent in the firmware command + * + * TLV_TYPE_CHANLIST, nxpwifi_ie_types_chan_list_param_set + * WLAN_EID_SSID, nxpwifi_ie_types_ssid_param_set + */ + u8 tlv_buf[1]; /* SSID TLV(s) and ChanList TLVs are stored here */ +} __packed; + +struct nxpwifi_user_scan_chan { + u8 chan_number; + u8 radio_type; + u8 scan_type; + u8 reserved; + u32 scan_time; +} __packed; + +struct nxpwifi_user_scan_cfg { + /* BSS mode to be sent in the firmware command + */ + u8 bss_mode; + /* Configure the number of probe requests for active chan scans */ + u8 num_probes; + u8 reserved; + /* BSSID filter sent in the firmware command to limit the results */ + u8 specific_bssid[ETH_ALEN]; + /* SSID filter list used in the firmware to limit the scan results */ + struct cfg80211_ssid *ssid_list; + u8 num_ssids; + /* Variable number (fixed maximum) of channels to scan up */ + struct nxpwifi_user_scan_chan chan_list[NXPWIFI_USER_SCAN_CHAN_MAX]; + u16 scan_chan_gap; + u8 random_mac[ETH_ALEN]; +} __packed; + +#define NXPWIFI_BG_SCAN_CHAN_MAX 38 +#define NXPWIFI_BSS_MODE_INFRA 1 +#define NXPWIFI_BGSCAN_ACT_GET 0x0000 +#define NXPWIFI_BGSCAN_ACT_SET 0x0001 +#define NXPWIFI_BGSCAN_ACT_SET_ALL 0xff01 +/** ssid match */ +#define NXPWIFI_BGSCAN_SSID_MATCH 0x0001 +/** ssid match and RSSI exceeded */ +#define NXPWIFI_BGSCAN_SSID_RSSI_MATCH 0x0004 +/**wait for all channel scan to complete to report scan result*/ +#define NXPWIFI_BGSCAN_WAIT_ALL_CHAN_DONE 0x80000000 + +struct nxpwifi_bg_scan_cfg { + u16 action; + u8 enable; + u8 bss_type; + u8 chan_per_scan; + u32 scan_interval; + u32 report_condition; + u8 num_probes; + u8 rssi_threshold; + u8 snr_threshold; + u16 repeat_count; + u16 start_later; + struct cfg80211_match_set *ssid_list; + u8 num_ssids; + struct nxpwifi_user_scan_chan chan_list[NXPWIFI_BG_SCAN_CHAN_MAX]; + u16 scan_chan_gap; +} __packed; + +struct ie_body { + u8 grp_key_oui[4]; + u8 ptk_cnt[2]; + u8 ptk_body[4]; +} __packed; + +struct host_cmd_ds_802_11_scan { + u8 bss_mode; + u8 bssid[ETH_ALEN]; + u8 tlv_buffer[]; +} __packed; + +struct host_cmd_ds_802_11_scan_rsp { + __le16 bss_descript_size; + u8 number_of_sets; + u8 bss_desc_and_tlv_buffer[]; +} __packed; + +struct host_cmd_ds_802_11_scan_ext { + u32 reserved; + u8 tlv_buffer[]; +} __packed; + +struct nxpwifi_ie_types_bss_mode { + struct nxpwifi_ie_types_header header; + u8 bss_mode; +} __packed; + +struct nxpwifi_ie_types_bss_scan_rsp { + struct nxpwifi_ie_types_header header; + u8 bssid[ETH_ALEN]; + u8 frame_body[]; +} __packed; + +struct nxpwifi_ie_types_bss_scan_info { + struct nxpwifi_ie_types_header header; + __le16 rssi; + __le16 anpi; + u8 cca_busy_fraction; + u8 radio_type; + u8 channel; + u8 reserved; + __le64 tsf; +} __packed; + +struct host_cmd_ds_802_11_bg_scan_config { + __le16 action; + u8 enable; + u8 bss_type; + u8 chan_per_scan; + u8 reserved; + __le16 reserved1; + __le32 scan_interval; + __le32 reserved2; + __le32 report_condition; + __le16 reserved3; + u8 tlv[]; +} __packed; + +struct host_cmd_ds_802_11_bg_scan_query { + u8 flush; +} __packed; + +struct host_cmd_ds_802_11_bg_scan_query_rsp { + __le32 report_condition; + struct host_cmd_ds_802_11_scan_rsp scan_resp; +} __packed; + +struct nxpwifi_ietypes_domain_param_set { + struct nxpwifi_ie_types_header header; + u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; + struct ieee80211_country_ie_triplet triplet[]; +} __packed; + +struct host_cmd_ds_802_11d_domain_info { + __le16 action; + struct nxpwifi_ietypes_domain_param_set domain; +} __packed; + +struct host_cmd_ds_802_11d_domain_info_rsp { + __le16 action; + struct nxpwifi_ietypes_domain_param_set domain; +} __packed; + +struct host_cmd_ds_11n_addba_req { + u8 add_req_result; + u8 peer_mac_addr[ETH_ALEN]; + u8 dialog_token; + __le16 block_ack_param_set; + __le16 block_ack_tmo; + __le16 ssn; +} __packed; + +struct host_cmd_ds_11n_addba_rsp { + u8 add_rsp_result; + u8 peer_mac_addr[ETH_ALEN]; + u8 dialog_token; + __le16 status_code; + __le16 block_ack_param_set; + __le16 block_ack_tmo; + __le16 ssn; +} __packed; + +struct host_cmd_ds_11n_delba { + u8 del_result; + u8 peer_mac_addr[ETH_ALEN]; + __le16 del_ba_param_set; + __le16 reason_code; + u8 reserved; +} __packed; + +struct host_cmd_ds_11n_batimeout { + u8 tid; + u8 peer_mac_addr[ETH_ALEN]; + u8 origninator; +} __packed; + +struct host_cmd_ds_11n_cfg { + __le16 action; + __le16 ht_tx_cap; + __le16 ht_tx_info; + __le16 misc_config; /* Needed for 802.11AC cards only */ +} __packed; + +struct host_cmd_ds_txbuf_cfg { + __le16 action; + __le16 buff_size; + __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ + __le16 reserved3; +} __packed; + +struct host_cmd_ds_amsdu_aggr_ctrl { + __le16 action; + __le16 enable; + __le16 curr_buf_size; +} __packed; + +struct host_cmd_ds_sta_deauth { + u8 mac[ETH_ALEN]; + __le16 reason; +} __packed; + +struct nxpwifi_ie_types_sta_info { + struct nxpwifi_ie_types_header header; + u8 mac[ETH_ALEN]; + u8 power_mfg_status; + s8 rssi; +}; + +struct host_cmd_ds_sta_list { + __le16 sta_count; + u8 tlv[]; +} __packed; + +struct nxpwifi_ie_types_pwr_capability { + struct nxpwifi_ie_types_header header; + s8 min_pwr; + s8 max_pwr; +}; + +struct nxpwifi_ie_types_local_pwr_constraint { + struct nxpwifi_ie_types_header header; + u8 chan; + u8 constraint; +}; + +struct nxpwifi_ie_types_wmm_param_set { + struct nxpwifi_ie_types_header header; + u8 wmm_ie[]; +} __packed; + +struct nxpwifi_ie_types_mgmt_frame { + struct nxpwifi_ie_types_header header; + __le16 frame_control; + u8 frame_contents[]; +}; + +struct nxpwifi_ie_types_wmm_queue_status { + struct nxpwifi_ie_types_header header; + u8 queue_index; + u8 disabled; + __le16 medium_time; + u8 flow_required; + u8 flow_created; + u32 reserved; +}; + +struct ieee_types_vendor_header { + u8 element_id; + u8 len; + struct { + u8 oui[3]; + u8 oui_type; + } __packed oui; +} __packed; + +struct ieee_types_wmm_parameter { + /* WMM Parameter IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [24] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [1] + * Version [1] + */ + struct ieee_types_vendor_header vend_hdr; + u8 oui_subtype; + u8 version; + + u8 qos_info_bitmap; + u8 reserved; + struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; +} __packed; + +struct ieee_types_wmm_info { + /* WMM Info IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [7] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [0] + * Version [1] + */ + struct ieee_types_vendor_header vend_hdr; + u8 oui_subtype; + u8 version; + + u8 qos_info_bitmap; +} __packed; + +struct host_cmd_ds_wmm_get_status { + u8 queue_status_tlv[sizeof(struct nxpwifi_ie_types_wmm_queue_status) * + IEEE80211_NUM_ACS]; + u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; +} __packed; + +struct nxpwifi_wmm_ac_status { + u8 disabled; + u8 flow_required; + u8 flow_created; +}; + +struct nxpwifi_ie_types_htcap { + struct nxpwifi_ie_types_header header; + struct ieee80211_ht_cap ht_cap; +} __packed; + +struct nxpwifi_ie_types_vhtcap { + struct nxpwifi_ie_types_header header; + struct ieee80211_vht_cap vht_cap; +} __packed; + +struct nxpwifi_ie_types_aid { + struct nxpwifi_ie_types_header header; + __le16 aid; +} __packed; + +struct nxpwifi_ie_types_oper_mode_ntf { + struct nxpwifi_ie_types_header header; + u8 oper_mode; +} __packed; + +/* VHT Operations IE */ +struct nxpwifi_ie_types_vht_oper { + struct nxpwifi_ie_types_header header; + u8 chan_width; + u8 chan_center_freq_1; + u8 chan_center_freq_2; + /* Basic MCS set map, each 2 bits stands for a NSS */ + __le16 basic_mcs_map; +} __packed; + +struct nxpwifi_ie_types_wmmcap { + struct nxpwifi_ie_types_header header; + struct nxpwifi_types_wmm_info wmm_info; +} __packed; + +struct nxpwifi_ie_types_htinfo { + struct nxpwifi_ie_types_header header; + struct ieee80211_ht_operation ht_oper; +} __packed; + +struct nxpwifi_ie_types_2040bssco { + struct nxpwifi_ie_types_header header; + u8 bss_co_2040; +} __packed; + +struct nxpwifi_ie_types_extcap { + struct nxpwifi_ie_types_header header; + u8 ext_capab[]; +} __packed; + +struct host_cmd_ds_mem_access { + __le16 action; + __le16 reserved; + __le32 addr; + __le32 value; +} __packed; + +struct nxpwifi_ie_types_qos_info { + struct nxpwifi_ie_types_header header; + u8 qos_info; +} __packed; + +struct host_cmd_ds_mac_reg_access { + __le16 action; + __le16 offset; + __le32 value; +} __packed; + +struct host_cmd_ds_bbp_reg_access { + __le16 action; + __le16 offset; + u8 value; + u8 reserved[3]; +} __packed; + +struct host_cmd_ds_rf_reg_access { + __le16 action; + __le16 offset; + u8 value; + u8 reserved[3]; +} __packed; + +struct host_cmd_ds_pmic_reg_access { + __le16 action; + __le16 offset; + u8 value; + u8 reserved[3]; +} __packed; + +struct host_cmd_ds_802_11_eeprom_access { + __le16 action; + + __le16 offset; + __le16 byte_count; + u8 value; +} __packed; + +struct nxpwifi_assoc_event { + u8 sta_addr[ETH_ALEN]; + __le16 type; + __le16 len; + __le16 frame_control; + __le16 cap_info; + __le16 listen_interval; + u8 data[]; +} __packed; + +struct host_cmd_ds_sys_config { + __le16 action; + u8 tlv[]; +}; + +struct host_cmd_11ac_vht_cfg { + __le16 action; + u8 band_config; + u8 misc_config; + __le32 cap_info; + __le32 mcs_tx_set; + __le32 mcs_rx_set; +} __packed; + +struct host_cmd_tlv_akmp { + struct nxpwifi_ie_types_header header; + __le16 key_mgmt; + __le16 key_mgmt_operation; +} __packed; + +struct host_cmd_tlv_pwk_cipher { + struct nxpwifi_ie_types_header header; + __le16 proto; + u8 cipher; + u8 reserved; +} __packed; + +struct host_cmd_tlv_gwk_cipher { + struct nxpwifi_ie_types_header header; + u8 cipher; + u8 reserved; +} __packed; + +struct host_cmd_tlv_passphrase { + struct nxpwifi_ie_types_header header; + u8 passphrase[]; +} __packed; + +struct host_cmd_tlv_wep_key { + struct nxpwifi_ie_types_header header; + u8 key_index; + u8 is_default; + u8 key[]; +}; + +struct host_cmd_tlv_auth_type { + struct nxpwifi_ie_types_header header; + u8 auth_type; + u8 pwe_derivation; + u8 transition_disable; +} __packed; + +struct host_cmd_tlv_encrypt_protocol { + struct nxpwifi_ie_types_header header; + __le16 proto; +} __packed; + +struct host_cmd_tlv_ssid { + struct nxpwifi_ie_types_header header; + u8 ssid[]; +} __packed; + +struct host_cmd_tlv_rates { + struct nxpwifi_ie_types_header header; + u8 rates[]; +} __packed; + +struct nxpwifi_ie_types_bssid_list { + struct nxpwifi_ie_types_header header; + u8 bssid[ETH_ALEN]; +} __packed; + +struct host_cmd_tlv_bcast_ssid { + struct nxpwifi_ie_types_header header; + u8 bcast_ctl; +} __packed; + +struct host_cmd_tlv_beacon_period { + struct nxpwifi_ie_types_header header; + __le16 period; +} __packed; + +struct host_cmd_tlv_dtim_period { + struct nxpwifi_ie_types_header header; + u8 period; +} __packed; + +struct host_cmd_tlv_frag_threshold { + struct nxpwifi_ie_types_header header; + __le16 frag_thr; +} __packed; + +struct host_cmd_tlv_rts_threshold { + struct nxpwifi_ie_types_header header; + __le16 rts_thr; +} __packed; + +struct host_cmd_tlv_retry_limit { + struct nxpwifi_ie_types_header header; + u8 limit; +} __packed; + +struct host_cmd_tlv_mac_addr { + struct nxpwifi_ie_types_header header; + u8 mac_addr[ETH_ALEN]; +} __packed; + +struct host_cmd_tlv_channel_band { + struct nxpwifi_ie_types_header header; + u8 band_config; + u8 channel; +} __packed; + +struct host_cmd_tlv_ageout_timer { + struct nxpwifi_ie_types_header header; + __le32 sta_ao_timer; +} __packed; + +struct host_cmd_tlv_power_constraint { + struct nxpwifi_ie_types_header header; + u8 constraint; +} __packed; + +struct nxpwifi_ie_types_btcoex_scan_time { + struct nxpwifi_ie_types_header header; + u8 coex_scan; + u8 reserved; + __le16 min_scan_time; + __le16 max_scan_time; +} __packed; + +struct nxpwifi_ie_types_btcoex_aggr_win_size { + struct nxpwifi_ie_types_header header; + u8 coex_win_size; + u8 tx_win_size; + u8 rx_win_size; + u8 reserved; +} __packed; + +struct nxpwifi_ie_types_robust_coex { + struct nxpwifi_ie_types_header header; + __le32 mode; +} __packed; + +#define NXPWIFI_VERSION_STR_LENGTH 128 + +struct host_cmd_ds_version_ext { + u8 version_str_sel; + char version_str[NXPWIFI_VERSION_STR_LENGTH]; +} __packed; + +struct host_cmd_ds_mgmt_frame_reg { + __le16 action; + __le32 mask; +} __packed; + +struct host_cmd_ds_remain_on_chan { + __le16 action; + u8 status; + u8 reserved; + u8 band_cfg; + u8 channel; + __le32 duration; +} __packed; + +struct host_cmd_ds_802_11_ibss_status { + __le16 action; + __le16 enable; + u8 bssid[ETH_ALEN]; + __le16 beacon_interval; + __le16 atim_window; + __le16 use_g_rate_protect; +} __packed; + +struct nxpwifi_fw_mef_entry { + u8 mode; + u8 action; + __le16 exprsize; + u8 expr[]; +} __packed; + +struct host_cmd_ds_mef_cfg { + __le32 criteria; + __le16 num_entries; + u8 mef_entry_data[]; +} __packed; + +#define CONNECTION_TYPE_INFRA 0 +#define CONNECTION_TYPE_AP 2 + +struct host_cmd_ds_set_bss_mode { + u8 con_type; +} __packed; + +struct host_cmd_ds_pcie_details { + /* TX buffer descriptor ring address */ + __le32 txbd_addr_lo; + __le32 txbd_addr_hi; + /* TX buffer descriptor ring count */ + __le32 txbd_count; + + /* RX buffer descriptor ring address */ + __le32 rxbd_addr_lo; + __le32 rxbd_addr_hi; + /* RX buffer descriptor ring count */ + __le32 rxbd_count; + + /* Event buffer descriptor ring address */ + __le32 evtbd_addr_lo; + __le32 evtbd_addr_hi; + /* Event buffer descriptor ring count */ + __le32 evtbd_count; + + /* Sleep cookie buffer physical address */ + __le32 sleep_cookie_addr_lo; + __le32 sleep_cookie_addr_hi; +} __packed; + +struct nxpwifi_ie_types_rssi_threshold { + struct nxpwifi_ie_types_header header; + u8 abs_value; + u8 evt_freq; +} __packed; + +#define NXPWIFI_DFS_REC_HDR_LEN 8 +#define NXPWIFI_DFS_REC_HDR_NUM 10 +#define NXPWIFI_BIN_COUNTER_LEN 7 + +struct nxpwifi_radar_det_event { + __le32 detect_count; + u8 reg_domain; /*1=3Dfcc, 2=3Detsi, 3=3Dmic*/ + u8 det_type; /*0=3Dnone, 1=3Dpw(chirp), 2=3Dpri(radar)*/ + __le16 pw_chirp_type; + u8 pw_chirp_idx; + u8 pw_value; + u8 pri_radar_type; + u8 pri_bincnt; + u8 bin_counter[NXPWIFI_BIN_COUNTER_LEN]; + u8 num_dfs_records; + u8 dfs_record_hdr[NXPWIFI_DFS_REC_HDR_NUM][NXPWIFI_DFS_REC_HDR_LEN]; + __le32 passed; +} __packed; + +struct nxpwifi_ie_types_multi_chan_info { + struct nxpwifi_ie_types_header header; + __le16 status; + u8 tlv_buffer[]; +} __packed; + +struct nxpwifi_ie_types_mc_group_info { + struct nxpwifi_ie_types_header header; + u8 chan_group_id; + u8 chan_buf_weight; + u8 band_config; + u8 chan_num; + __le32 chan_time; + __le32 reserved; + union { + u8 sdio_func_num; + u8 usb_ep_num; + } hid_num; + u8 intf_num; + u8 bss_type_numlist[]; +} __packed; + +#define MEAS_RPT_MAP_RADAR_MASK 0x08 +#define MEAS_RPT_MAP_RADAR_SHIFT_BIT 3 + +struct nxpwifi_ie_types_chan_rpt_data { + struct nxpwifi_ie_types_header header; + u8 meas_rpt_map; +} __packed; + +struct host_cmd_ds_802_11_subsc_evt { + __le16 action; + __le16 events; +} __packed; + +struct chan_switch_result { + u8 cur_chan; + u8 status; + u8 reason; +} __packed; + +struct nxpwifi_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 nxpwifi_ie_list { + __le16 type; + __le16 len; + struct nxpwifi_ie ie_list[MAX_MGMT_IE_INDEX]; +} __packed; + +struct coalesce_filt_field_param { + u8 operation; + u8 operand_len; + __le16 offset; + u8 operand_byte_stream[4]; +}; + +struct coalesce_receive_filt_rule { + struct nxpwifi_ie_types_header header; + u8 num_of_fields; + u8 pkt_type; + __le16 max_coalescing_delay; + struct coalesce_filt_field_param params[]; +} __packed; + +struct host_cmd_ds_coalesce_cfg { + __le16 action; + __le16 num_of_rules; + u8 rule_data[]; +} __packed; + +struct host_cmd_ds_multi_chan_policy { + __le16 action; + __le16 policy; +} __packed; + +struct host_cmd_ds_robust_coex { + __le16 action; + __le16 reserved; +} __packed; + +struct host_cmd_ds_wakeup_reason { + __le16 wakeup_reason; +} __packed; + +struct host_cmd_ds_gtk_rekey_params { + __le16 action; + u8 kck[NL80211_KCK_LEN]; + u8 kek[NL80211_KEK_LEN]; + __le32 replay_ctr_low; + __le32 replay_ctr_high; +} __packed; + +struct host_cmd_ds_chan_region_cfg { + __le16 action; +} __packed; + +struct host_cmd_ds_pkt_aggr_ctrl { + __le16 action; + __le16 enable; + __le16 tx_aggr_max_size; + __le16 tx_aggr_max_num; + __le16 tx_aggr_align; +} __packed; + +struct host_cmd_ds_sta_configure { + __le16 action; + u8 tlv_buffer[]; +} __packed; + +struct nxpwifi_ie_types_sta_flag { + struct nxpwifi_ie_types_header header; + __le32 sta_flags; +} __packed; + +struct host_cmd_ds_add_station { + __le16 action; + __le16 aid; + u8 peer_mac[ETH_ALEN]; + __le32 listen_interval; + __le16 cap_info; + u8 tlv[]; +} __packed; + +struct host_cmd_ds_command { + __le16 command; + __le16 size; + __le16 seq_num; + __le16 result; + union { + struct host_cmd_ds_get_hw_spec hw_spec; + struct host_cmd_ds_mac_control mac_ctrl; + struct host_cmd_ds_802_11_mac_address mac_addr; + struct host_cmd_ds_mac_multicast_adr mc_addr; + struct host_cmd_ds_802_11_get_log get_log; + struct host_cmd_ds_802_11_rssi_info rssi_info; + struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp; + struct host_cmd_ds_802_11_snmp_mib smib; + struct host_cmd_ds_tx_rate_query tx_rate; + struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; + struct host_cmd_ds_txpwr_cfg txp_cfg; + struct host_cmd_ds_rf_tx_pwr txp; + struct host_cmd_ds_rf_ant_mimo ant_mimo; + struct host_cmd_ds_rf_ant_siso ant_siso; + struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; + struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; + struct host_cmd_ds_802_11_scan scan; + struct host_cmd_ds_802_11_scan_ext ext_scan; + struct host_cmd_ds_802_11_scan_rsp scan_resp; + struct host_cmd_ds_802_11_bg_scan_config bg_scan_config; + struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; + struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; + struct host_cmd_ds_802_11_associate associate; + struct host_cmd_ds_802_11_associate_rsp associate_rsp; + struct host_cmd_ds_802_11_deauthenticate deauth; + struct host_cmd_ds_802_11d_domain_info domain_info; + struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp; + struct host_cmd_ds_11n_addba_req add_ba_req; + struct host_cmd_ds_11n_addba_rsp add_ba_rsp; + struct host_cmd_ds_11n_delba del_ba; + struct host_cmd_ds_txbuf_cfg tx_buf; + struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl; + struct host_cmd_ds_11n_cfg htcfg; + struct host_cmd_ds_wmm_get_status get_wmm_status; + struct host_cmd_ds_802_11_key_material key_material; + struct host_cmd_ds_version_ext verext; + struct host_cmd_ds_mgmt_frame_reg reg_mask; + struct host_cmd_ds_remain_on_chan roc_cfg; + struct host_cmd_ds_802_11_ibss_status ibss_coalescing; + struct host_cmd_ds_mef_cfg mef_cfg; + struct host_cmd_ds_mem_access mem; + struct host_cmd_ds_mac_reg_access mac_reg; + struct host_cmd_ds_bbp_reg_access bbp_reg; + struct host_cmd_ds_rf_reg_access rf_reg; + struct host_cmd_ds_pmic_reg_access pmic_reg; + struct host_cmd_ds_set_bss_mode bss_mode; + struct host_cmd_ds_pcie_details pcie_host_spec; + struct host_cmd_ds_802_11_eeprom_access eeprom; + struct host_cmd_ds_802_11_subsc_evt subsc_evt; + struct host_cmd_ds_sys_config uap_sys_config; + struct host_cmd_ds_sta_deauth sta_deauth; + struct host_cmd_ds_sta_list sta_list; + struct host_cmd_11ac_vht_cfg vht_cfg; + struct host_cmd_ds_coalesce_cfg coalesce_cfg; + struct host_cmd_ds_chan_rpt_req chan_rpt_req; + struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; + struct host_cmd_ds_multi_chan_policy mc_policy; + struct host_cmd_ds_robust_coex coex; + struct host_cmd_ds_wakeup_reason hs_wakeup_reason; + struct host_cmd_ds_gtk_rekey_params rekey; + struct host_cmd_ds_chan_region_cfg reg_cfg; + struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl; + struct host_cmd_ds_sta_configure sta_cfg; + struct host_cmd_ds_add_station sta_info; + } params; +} __packed; + +struct nxpwifi_opt_sleep_confirm { + __le16 command; + __le16 size; + __le16 seq_num; + __le16 result; + __le16 action; + __le16 resp_ctrl; +} __packed; + +struct hw_spec_max_conn { + struct nxpwifi_ie_types_header header; + u8 reserved; + u8 max_sta_conn; +} __packed; + +#endif /* !_NXPWIFI_FW_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2068.outbound.protection.outlook.com [40.107.7.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 21033171677; Fri, 21 Jun 2024 07:53:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956427; cv=fail; b=bp2ZHv2cXALa2L0ma2MQ5UwW+vE/9iFJhOPHhhedzDcyRrrOhqciLAboByeSrnLbQSOVkYSUqmYomp7ohO9bhCfGiDmWQ3K6Gl2GqMWDbo8XU4RfqyZmeRh7LPraMQSIHSWkOVpdvxxzD8Vx25YnLVcRHxw8PX6t/bSQTWUoYDs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956427; c=relaxed/simple; bh=rCz00Uli2faMqJJSU5LHpor3/j9sZt6gkTHezCzSQnQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=q3xZci/vWrEohxSDjy7pPYhOI0QspF/HZfs+o+LEYmxNm/thHfYW+1hihWVNIPkNHsXgUDmRx5dAK//lfA1F/0HvqCEA3YiRIT2VYYktz97r9iFg0nxMInGegyLXzFwy54/Oy2e2j5YzqJWsRwVKL60nobYDOrC4B8v82e+cXvM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=cHROco4E; arc=fail smtp.client-ip=40.107.7.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="cHROco4E" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lw/neFAc2Yz3C8GpD8Aml3WHZG0zpbL2AN79KIkpPQcucAtyDHf4XJKO4K+0seR0hXeVZzKnJmG2AEbmNdUB4kR+/yt7kdqwNjhn5F+iDMIDxTdNfwrW6kAwk5RBxEkFyD4cPJkyTD+Z9MlJc9S/jYAQUEqkavjvYUHGqfRCAn9EwUiYUR2PfDT7/a9FDi4I9QE33pKg78fWNfX9MiHW8ohF0Cx6sI4HE2h8KbBs81l7ZgXUuzqqNYV1Aza6Y3cemvKCADaRM/VvFjaH7MO/ZyhZsPrSXSVPbYp/NNOTJw0h4qVhmQwwAA3djxcxqFAfpgv/wDB3THJcTPWCMxjNIA== 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=TsuiSCNjDFYiyxR8M0UNu87k8nejJMNOt35czm6Qd7I=; b=QS3Awpgh2IagWRyIC1u+x6VOaSDRrDxGKyV1z7bBWhTe3a4YQvNeQ4nD4sM9ITAGXcjDsSyEdRTEZVHqxIdovhIcjXxWMmNkGub7LY7MsbG08RqFADUFaztJVWZDiCJReJbsIAF7E0vXNN8zZ78LTltsYPn+2ZGxmp73vRa30F4vsXcbci88ewpLtqNXiB0eLTYE8bf3gZu7foRzetQIkQ72E8O6DfwwpqZLXD9S5u49O/l6p4sQqkLHK2HnTNvkFZ3vgbWfTecdbxr4+gSe7fMZfmAPgst6kgvpilCYHRtswRQHO7m+8YvGCu5R5O0BX2Iod9Ptv8I1ZMRWmkw5fg== 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=TsuiSCNjDFYiyxR8M0UNu87k8nejJMNOt35czm6Qd7I=; b=cHROco4EYNm8GYSFN4oTqUZJqoO9rpoigA/D3I/k+H1vcHJEgYroZb8AyLAtH4LuimVZCOvp5KBrW4LiCBq6FpSPvN4lc+g1W3MjAstA/bNAg2nto+eZFL2ON2ACeW/O1uL5Z0ejEJYYNp+XcURnwd8ZMSLF4fTyZMonzml3XTw= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:39 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:39 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 19/43] wifi: nxpwifi: add ie.c Date: Fri, 21 Jun 2024 15:51:44 +0800 Message-Id: <20240621075208.513497-20-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 6da158f1-980d-493d-7080-08dc91c742e8 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?eNubAaywsZgqaXSL7uOdHATyB1Kp26yh4npUBzBhuPQj0xcMDYdawE7/k5mq?= =?us-ascii?Q?YfrEFHHKjrofccalh0JIlkYVLIXyDmGoAjFK9rdS/Xh4XTWFy+zyk+UqQptl?= =?us-ascii?Q?liSZ4H4u/1MkV++sUaS38rYXMMAJeu1d/FCxJCb9tZ02iVpkKxf3/OGUAEQb?= =?us-ascii?Q?t25MxsxJ4M0Iuyrg7FF1lnCOPy7ECxmTNCJ185XibtDART4AYctJV51YkA1z?= =?us-ascii?Q?bY1Grdi7dS1DGz9ktBmBHT2AENdnBdwmWXF/Q1p3lp79AUOfyidCBTquhnq7?= =?us-ascii?Q?d7dT1xVYSdW6eJdK33W+GTK7lBYKbOmqKLgrMwi/I/x0OmgmAA/ysfwvJTYR?= =?us-ascii?Q?kdMSQD20eeUI4KCbvs6rCUty/nYwl/lz/wLXc2ZiiW/LcdC+j9aOyIqWKpsL?= =?us-ascii?Q?tX95jsXRnPhkbvZd8sI9fZxd+yQ2316KJas+A+7+SW8Nzy4HvnoVVbSKNWHG?= =?us-ascii?Q?tfumYHFXqp8CGs/D9tlhjteFiWuNlrNcXeuKP6TfwlFbremTDtlyWZ84NIBQ?= =?us-ascii?Q?bCecjajw38eEZ91+SjLvcIHIYMLO1NAVNM9Fcj8WCQOSfE3c9OtuVX2NPFJ/?= =?us-ascii?Q?+5w3+IGuGR4v19yPZvMwvTSFFZQhQK4UKEdIPNob/Ndb1/FlcrV0kPfy3J4w?= =?us-ascii?Q?BIn4TEYsC2cA200KUeBC0igqHocy5LYwEd04wZyCv62YmBamdvo5Fl1eL+VN?= =?us-ascii?Q?2HHx3XOnyhDQZ54ItqEw7LOl3y0pD5g5rAfYj1vIDXHBmYnuN/eSjrkb87fz?= =?us-ascii?Q?uowED9538LTJdHErlQWx1M9ynOLErFTriJO53roqrnIIVPE2aAfFKqZIcLh3?= =?us-ascii?Q?6vva2C2oyFFQQTkxLg75Vo/RojMCMUhAMHn31njEnLu/4H3h80o9ZHjnlpnS?= =?us-ascii?Q?nu5DdEoCdLRYAIVdMamnLCFAGaFN7CZq4V7haWLqIphCUpRGhgBm59/hGcpG?= =?us-ascii?Q?9NY8SL3M98OrDLV6F92eIs4lwkNTEot2ydLVS2JoGtYXbegS+xnA/UHkW/PA?= =?us-ascii?Q?hIbr/6XwkbvREeALiWJVnI1m3AhbG2qDjetXfq6YyXrf53TEb/2PhnzpOJhp?= =?us-ascii?Q?1AYvZtB7lmlZwWSg9WfiYqrS53M/+PmA4hbhbGwA84K/L1BhOYwjpsREmyQD?= =?us-ascii?Q?OUZq52rOY4KhKyRmU7zuw0I3LSIxU0sotignCMN0KZeDOtX2s4oB+llDEo/+?= =?us-ascii?Q?vCubCH4qMx3SuKK6G7PtzxIkWXtu46o/4AhswTvnKU3uDbR/0v8Cm2ZDk/5k?= =?us-ascii?Q?LIzppjBE4kDNmrdMOpo43m3BEcVTnXdYIHrDzFKV4VOn5z8flynTwriMFgdI?= =?us-ascii?Q?5VTaT85aX+yk8cbj+qooP5LF+JaHTgVYqNYzGIoDorzo6SHNj3NHmQ1mDBNV?= =?us-ascii?Q?Kjos91I=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?jGitULrlmTWl6oL4MoZpHLQbslpC+ovLXTmvCd1BZPQ7jB4Ns0i17tdJK8uB?= =?us-ascii?Q?QDo33XlZqsJJlRF9qD04JptTd4zpaEbx5yhMh5Y9Eem0N77gtiKgnrYfSSap?= =?us-ascii?Q?py9/vwZ+kUOKYprxOcRMiGaFOEprQZe9PR7gq8E/dKUXenS3b8RGsq2sMb5U?= =?us-ascii?Q?AI2dUUwmE2GKW+WpN7XNlALoFVoS8BGG2DPPAcpYueohB4Ab4tj/JPMm/Um7?= =?us-ascii?Q?25kNyeFEgKvpVoUqfqimcsPgtgtj1HQWQjBgl8H7/Zycst/Tpu8ibZ/Mz8cT?= =?us-ascii?Q?EoENC9xuRrJek4S4O0KaqyOTuJDtykM1fB6/+v86hCKR3/7iSSn6Hc2vXZuC?= =?us-ascii?Q?HeV4gqExAFRAxQk0MVxF8u4e1UxxTlDv1CYZK9G3FnZL0hRQCMoJOWZsN7VY?= =?us-ascii?Q?7yANLixYkRZLmV1C39if1XDrWxOpZg2nCtf7kTAKglg5yqc6XA3iQfdSNiVj?= =?us-ascii?Q?jzJtN8yPIflc3Z0XvgMVdQZlXyN0uZn5GmQxG5NsFK7hsyPTpAmgNXL5wnDV?= =?us-ascii?Q?lBk9OdvSayStHWl3Y7a0tN2LI9HVjtLjhp4AGttx+UYs/ClB8Ptb/7+BjgD+?= =?us-ascii?Q?B1ieMumyehwJ6ygi5iYtvRV38SYKhMLlb0rfKieg2f8BhwtFGeO5hV4wlRIw?= =?us-ascii?Q?HPDQYLRFOz0zTB29JEcKi1nl8nkmE1N+QbrWPLmNxXyg2EcOWIyYihuJ/ipJ?= =?us-ascii?Q?MV1KJsR+XgbChFlEk3cKZpTVCBjW8Z5RjdgRbDVxXjFBYur3ygE8r2daN+YT?= =?us-ascii?Q?Q/U84lQC2n8n5811+lftmB2NHHaR2U9GgV5q0+GLAq45Vr8ITYtg+6D3Q5oR?= =?us-ascii?Q?KZz1d7K9H2jxyUb8HrBVtqIcUs1KTdZiurPUtktV06hZnsRPjmmFw9QZwcTl?= =?us-ascii?Q?eZLNHbOgy19YSqK8v9REh7rVZJy0s1KO8gzloexctVZEgvcUVHEog77oAO4z?= =?us-ascii?Q?rJyvq7GXrQoL7yJrEQMSVou8gZT8sDrtgj0NRQBvnfjQAetZPRoPcmVvlB3U?= =?us-ascii?Q?p1exetBtsUrXlvW4ugcf2XUKT9Kn0/ym/bYTxvesNJMgwiztPsBipT9Qzs0R?= =?us-ascii?Q?YG+dyaLfbYX7oQV6QNgI/Crq7os8MBLpBBq03ipKfNiTRSyehCcC8nXOnsJl?= =?us-ascii?Q?6Gq4eJJzXlLdM6uFz5412r6kFaQJLe11NhB+n+qaXfqTAS4gsm9FWdgruD+w?= =?us-ascii?Q?I3boEuY35FJdF2N9qgMX+++9BHv0MxKyw8Uo2FrJlNwfqD6MXlfvAaTSTvXu?= =?us-ascii?Q?uTsUCaQyCXvK9Rrq8Rmaw2tJuMciIKj2ADAgyICoavGMc/oPNulFUxK8OgK+?= =?us-ascii?Q?ABODlVd8JmeDRmA73RI8wj4A8Fo2uHO9hUbrloatLWTsqDqzuFV79/GZwqIN?= =?us-ascii?Q?I4mkUjIlpAG565ZHtntEq4wKFYyzqylZuMZ35SwXjKuD2vMqAiyBUmMSioYe?= =?us-ascii?Q?dvh1bDBUfOqHqEps6TxD85//7SHEKr2Y9WOqO8fSY/NND+VrQIpj0/DrxtkW?= =?us-ascii?Q?Mr20ORpdQlLmjgTVQnC1XiZGnu6Xocbhiq2Tqf63+piwdxQ5GR42uvOaWIdh?= =?us-ascii?Q?Yd7LXLH1OKKnjupVk/YyQUnG+TCZ/rkqNt/PvoZP?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6da158f1-980d-493d-7080-08dc91c742e8 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:39.0045 (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: dryi7Wb/QQUjBB7/kaW7l8zmS8vI7J8kF9hjHmzQfr4qZw1GvhSh3ygL2kuSEjurSiHHTccLIjW9tIvTLUs/XA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/ie.c | 502 ++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/ie.c diff --git a/drivers/net/wireless/nxp/nxpwifi/ie.c b/drivers/net/wireless/n= xp/nxpwifi/ie.c new file mode 100644 index 000000000000..cfe16e68d068 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/ie.c @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: management IE handling- setting and + * deleting IE. + * + * Copyright 2011-2024 NXP + */ + +#include "main.h" +#include "cmdevt.h" + +/* This function checks if current IE index is used by any on other interf= ace. + * Return: -1: yes, current IE index is used by someone else. + * 0: no, current IE index is NOT used by other interface. + */ +static int +nxpwifi_ie_index_used_by_other_intf(struct nxpwifi_private *priv, u16 idx) +{ + int i; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ie *ie; + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i] !=3D priv) { + ie =3D &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 +nxpwifi_ie_get_autoidx(struct nxpwifi_private *priv, u16 subtype_mask, + struct nxpwifi_ie *ie, u16 *index) +{ + u16 mask, len, i; + + for (i =3D 0; i < priv->adapter->max_mgmt_ie_index; i++) { + mask =3D le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask); + len =3D le16_to_cpu(ie->ie_length); + + if (mask =3D=3D NXPWIFI_AUTO_IDX_MASK) + continue; + + if (mask =3D=3D subtype_mask) { + if (len > IEEE_MAX_IE_SIZE) + continue; + + *index =3D i; + return 0; + } + + if (!priv->mgmt_ie[i].ie_length) { + if (nxpwifi_ie_index_used_by_other_intf(priv, i)) + continue; + + *index =3D i; + return 0; + } + } + + return -1; +} + +/* This function prepares IE data buffer for command to be sent to FW */ +static int +nxpwifi_update_autoindex_ies(struct nxpwifi_private *priv, + struct nxpwifi_ie_list *ie_list) +{ + u16 travel_len, index, mask; + s16 input_len, tlv_len; + struct nxpwifi_ie *ie; + u8 *tmp; + + input_len =3D le16_to_cpu(ie_list->len); + travel_len =3D sizeof(struct nxpwifi_ie_types_header); + + ie_list->len =3D 0; + + while (input_len >=3D sizeof(struct nxpwifi_ie_types_header)) { + ie =3D (struct nxpwifi_ie *)(((u8 *)ie_list) + travel_len); + tlv_len =3D le16_to_cpu(ie->ie_length); + travel_len +=3D tlv_len + NXPWIFI_IE_HDR_SIZE; + + if (input_len < tlv_len + NXPWIFI_IE_HDR_SIZE) + return -1; + index =3D le16_to_cpu(ie->ie_index); + mask =3D le16_to_cpu(ie->mgmt_subtype_mask); + + if (index =3D=3D NXPWIFI_AUTO_IDX_MASK) { + /* automatic addition */ + if (nxpwifi_ie_get_autoidx(priv, mask, ie, &index)) + return -1; + if (index =3D=3D NXPWIFI_AUTO_IDX_MASK) + return -1; + + tmp =3D (u8 *)&priv->mgmt_ie[index].ie_buffer; + memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length)); + priv->mgmt_ie[index].ie_length =3D ie->ie_length; + priv->mgmt_ie[index].ie_index =3D cpu_to_le16(index); + priv->mgmt_ie[index].mgmt_subtype_mask =3D + cpu_to_le16(mask); + + ie->ie_index =3D cpu_to_le16(index); + } else { + if (mask !=3D NXPWIFI_DELETE_MASK) + return -1; + /* Check if this index is being used on any + * other interface. + */ + if (nxpwifi_ie_index_used_by_other_intf(priv, index)) + return -1; + + ie->ie_length =3D 0; + memcpy(&priv->mgmt_ie[index], ie, + sizeof(struct nxpwifi_ie)); + } + + le16_unaligned_add_cpu + (&ie_list->len, + le16_to_cpu(priv->mgmt_ie[index].ie_length) + + NXPWIFI_IE_HDR_SIZE); + input_len -=3D tlv_len + NXPWIFI_IE_HDR_SIZE; + } + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) + return nxpwifi_send_cmd(priv, HOST_CMD_UAP_SYS_CONFIG, + HOST_ACT_GEN_SET, + UAP_CUSTOM_IE_I, ie_list, true); + + return 0; +} + +/* Copy individual custom IEs for beacon, probe response and assoc response + * and prepare single structure for IE setting. + * This function also updates allocated IE indices from driver. + */ +static int +nxpwifi_update_uap_custom_ie(struct nxpwifi_private *priv, + struct nxpwifi_ie *beacon_ie, u16 *beacon_idx, + struct nxpwifi_ie *pr_ie, u16 *probe_idx, + struct nxpwifi_ie *ar_ie, u16 *assoc_idx) +{ + struct nxpwifi_ie_list *ap_custom_ie; + u8 *pos; + u16 len; + int ret; + + ap_custom_ie =3D kzalloc(sizeof(*ap_custom_ie), GFP_KERNEL); + if (!ap_custom_ie) + return -ENOMEM; + + ap_custom_ie->type =3D cpu_to_le16(TLV_TYPE_MGMT_IE); + pos =3D (u8 *)ap_custom_ie->ie_list; + + if (beacon_ie) { + len =3D sizeof(struct nxpwifi_ie) - IEEE_MAX_IE_SIZE + + le16_to_cpu(beacon_ie->ie_length); + memcpy(pos, beacon_ie, len); + pos +=3D len; + le16_unaligned_add_cpu(&ap_custom_ie->len, len); + } + if (pr_ie) { + len =3D sizeof(struct nxpwifi_ie) - IEEE_MAX_IE_SIZE + + le16_to_cpu(pr_ie->ie_length); + memcpy(pos, pr_ie, len); + pos +=3D len; + le16_unaligned_add_cpu(&ap_custom_ie->len, len); + } + if (ar_ie) { + len =3D sizeof(struct nxpwifi_ie) - IEEE_MAX_IE_SIZE + + le16_to_cpu(ar_ie->ie_length); + memcpy(pos, ar_ie, len); + pos +=3D len; + le16_unaligned_add_cpu(&ap_custom_ie->len, len); + } + + ret =3D nxpwifi_update_autoindex_ies(priv, ap_custom_ie); + + pos =3D (u8 *)(&ap_custom_ie->ie_list[0].ie_index); + if (beacon_ie && *beacon_idx =3D=3D NXPWIFI_AUTO_IDX_MASK) { + /* save beacon ie index after auto-indexing */ + *beacon_idx =3D le16_to_cpu(ap_custom_ie->ie_list[0].ie_index); + len =3D sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE + + le16_to_cpu(beacon_ie->ie_length); + pos +=3D len; + } + if (pr_ie && le16_to_cpu(pr_ie->ie_index) =3D=3D NXPWIFI_AUTO_IDX_MASK) { + /* save probe resp ie index after auto-indexing */ + *probe_idx =3D *((u16 *)pos); + len =3D sizeof(*pr_ie) - IEEE_MAX_IE_SIZE + + le16_to_cpu(pr_ie->ie_length); + pos +=3D len; + } + if (ar_ie && le16_to_cpu(ar_ie->ie_index) =3D=3D NXPWIFI_AUTO_IDX_MASK) + /* save assoc resp ie index after auto-indexing */ + *assoc_idx =3D *((u16 *)pos); + + kfree(ap_custom_ie); + return ret; +} + +/* This function checks if the vendor specified IE is present in passed bu= ffer + * and copies it to nxpwifi_ie structure. + * Function takes pointer to struct nxpwifi_ie pointer as argument. + * If the vendor specified IE is present then memory is allocated for + * nxpwifi_ie pointer and filled in with IE. Caller should take care of fr= eeing + * this memory. + */ +static int nxpwifi_update_vs_ie(const u8 *ies, int ies_len, + struct nxpwifi_ie **ie_ptr, u16 mask, + unsigned int oui, u8 oui_type) +{ + struct ieee_types_header *vs_ie; + struct nxpwifi_ie *ie =3D *ie_ptr; + const u8 *vendor_ie; + + vendor_ie =3D cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len); + if (vendor_ie) { + if (!*ie_ptr) { + *ie_ptr =3D kzalloc(sizeof(*ie_ptr), GFP_KERNEL); + if (!*ie_ptr) + return -ENOMEM; + ie =3D *ie_ptr; + } + + vs_ie =3D (struct ieee_types_header *)vendor_ie; + if (le16_to_cpu(ie->ie_length) + vs_ie->len + 2 > + IEEE_MAX_IE_SIZE) + return -EINVAL; + memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length), + vs_ie, vs_ie->len + 2); + le16_unaligned_add_cpu(&ie->ie_length, vs_ie->len + 2); + ie->mgmt_subtype_mask =3D cpu_to_le16(mask); + ie->ie_index =3D cpu_to_le16(NXPWIFI_AUTO_IDX_MASK); + } + + *ie_ptr =3D ie; + return 0; +} + +/* This function parses beacon IEs, probe response IEs, association respon= se IEs + * from cfg80211_ap_settings->beacon and sets these IE to FW. + */ +static int nxpwifi_set_mgmt_beacon_data_ies(struct nxpwifi_private *priv, + struct cfg80211_beacon_data *data) +{ + struct nxpwifi_ie *beacon_ie =3D NULL, *pr_ie =3D NULL, *ar_ie =3D NULL; + u16 beacon_idx =3D NXPWIFI_AUTO_IDX_MASK, pr_idx =3D NXPWIFI_AUTO_IDX_MAS= K; + u16 ar_idx =3D NXPWIFI_AUTO_IDX_MASK; + int ret =3D 0; + + if (data->beacon_ies && data->beacon_ies_len) { + nxpwifi_update_vs_ie(data->beacon_ies, data->beacon_ies_len, + &beacon_ie, MGMT_MASK_BEACON, + WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS); + nxpwifi_update_vs_ie(data->beacon_ies, data->beacon_ies_len, + &beacon_ie, MGMT_MASK_BEACON, + WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); + } + + if (data->proberesp_ies && data->proberesp_ies_len) { + nxpwifi_update_vs_ie(data->proberesp_ies, + data->proberesp_ies_len, &pr_ie, + MGMT_MASK_PROBE_RESP, WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS); + nxpwifi_update_vs_ie(data->proberesp_ies, + data->proberesp_ies_len, &pr_ie, + MGMT_MASK_PROBE_RESP, + WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); + } + + if (data->assocresp_ies && data->assocresp_ies_len) { + nxpwifi_update_vs_ie(data->assocresp_ies, + data->assocresp_ies_len, &ar_ie, + MGMT_MASK_ASSOC_RESP | + MGMT_MASK_REASSOC_RESP, + WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS); + nxpwifi_update_vs_ie(data->assocresp_ies, + data->assocresp_ies_len, &ar_ie, + MGMT_MASK_ASSOC_RESP | + MGMT_MASK_REASSOC_RESP, WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P); + } + + if (beacon_ie || pr_ie || ar_ie) { + ret =3D nxpwifi_update_uap_custom_ie(priv, beacon_ie, + &beacon_idx, pr_ie, + &pr_idx, ar_ie, &ar_idx); + if (ret) + goto done; + } + + priv->beacon_idx =3D beacon_idx; + priv->proberesp_idx =3D pr_idx; + priv->assocresp_idx =3D ar_idx; + +done: + kfree(beacon_ie); + kfree(pr_ie); + kfree(ar_ie); + + return ret; +} + +/* This function parses head and tail IEs, from cfg80211_beacon_data and = sets + * these IE to FW. + */ +static int nxpwifi_uap_parse_tail_ies(struct nxpwifi_private *priv, + struct cfg80211_beacon_data *info) +{ + struct nxpwifi_ie *gen_ie; + struct ieee_types_header *hdr; + struct ieee80211_vendor_ie *vendorhdr; + u16 gen_idx =3D NXPWIFI_AUTO_IDX_MASK, ie_len =3D 0; + int left_len, parsed_len =3D 0; + unsigned int token_len; + int err =3D 0; + + if (!info->tail || !info->tail_len) + return 0; + + gen_ie =3D kzalloc(sizeof(*gen_ie), GFP_KERNEL); + if (!gen_ie) + return -ENOMEM; + + left_len =3D info->tail_len; + + /* Many IEs are generated in FW by parsing bss configuration. + * Let's not add them here; else we may end up duplicating these IEs + */ + while (left_len > sizeof(struct ieee_types_header)) { + hdr =3D (void *)(info->tail + parsed_len); + token_len =3D hdr->len + sizeof(struct ieee_types_header); + if (token_len > left_len) { + err =3D -EINVAL; + goto out; + } + + switch (hdr->element_id) { + case WLAN_EID_SSID: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_COUNTRY: + case WLAN_EID_PWR_CONSTRAINT: + case WLAN_EID_ERP_INFO: + case WLAN_EID_EXT_SUPP_RATES: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_HT_OPERATION: + case WLAN_EID_VHT_CAPABILITY: + case WLAN_EID_VHT_OPERATION: + break; + case WLAN_EID_VENDOR_SPECIFIC: + /* Skip only Microsoft WMM IE */ + if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WMM, + (const u8 *)hdr, + token_len)) + break; + fallthrough; + default: + if (ie_len + token_len > IEEE_MAX_IE_SIZE) { + err =3D -EINVAL; + goto out; + } + memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len); + ie_len +=3D token_len; + break; + } + left_len -=3D token_len; + parsed_len +=3D token_len; + } + + /* parse only WPA vendor IE from tail, WMM IE is configured by + * bss_config command + */ + vendorhdr =3D (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + info->tail, info->tail_len); + if (vendorhdr) { + token_len =3D vendorhdr->len + sizeof(struct ieee_types_header); + if (ie_len + token_len > IEEE_MAX_IE_SIZE) { + err =3D -EINVAL; + goto out; + } + memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len); + ie_len +=3D token_len; + } + + if (!ie_len) + goto out; + + gen_ie->ie_index =3D cpu_to_le16(gen_idx); + gen_ie->mgmt_subtype_mask =3D cpu_to_le16(MGMT_MASK_BEACON | + MGMT_MASK_PROBE_RESP | + MGMT_MASK_ASSOC_RESP); + gen_ie->ie_length =3D cpu_to_le16(ie_len); + + if (nxpwifi_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL, + NULL, NULL)) { + err =3D -EINVAL; + goto out; + } + + priv->gen_idx =3D gen_idx; + + out: + kfree(gen_ie); + return err; +} + +/* This function parses different IEs-head & tail IEs, beacon IEs, + * probe response IEs, association response IEs from cfg80211_ap_settings + * function and sets these IE to FW. + */ +int nxpwifi_set_mgmt_ies(struct nxpwifi_private *priv, + struct cfg80211_beacon_data *info) +{ + int ret; + + ret =3D nxpwifi_uap_parse_tail_ies(priv, info); + + if (ret) + return ret; + + return nxpwifi_set_mgmt_beacon_data_ies(priv, info); +} + +/* This function removes management IE set */ +int nxpwifi_del_mgmt_ies(struct nxpwifi_private *priv) +{ + struct nxpwifi_ie *beacon_ie =3D NULL, *pr_ie =3D NULL; + struct nxpwifi_ie *ar_ie =3D NULL, *gen_ie =3D NULL; + int ret =3D 0; + + if (priv->gen_idx !=3D NXPWIFI_AUTO_IDX_MASK) { + gen_ie =3D kmalloc(sizeof(*gen_ie), GFP_KERNEL); + if (!gen_ie) + return -ENOMEM; + + gen_ie->ie_index =3D cpu_to_le16(priv->gen_idx); + gen_ie->mgmt_subtype_mask =3D cpu_to_le16(NXPWIFI_DELETE_MASK); + gen_ie->ie_length =3D 0; + if (nxpwifi_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx, + NULL, &priv->proberesp_idx, + NULL, &priv->assocresp_idx)) { + ret =3D -1; + goto done; + } + + priv->gen_idx =3D NXPWIFI_AUTO_IDX_MASK; + } + + if (priv->beacon_idx !=3D NXPWIFI_AUTO_IDX_MASK) { + beacon_ie =3D kmalloc(sizeof(*beacon_ie), GFP_KERNEL); + if (!beacon_ie) { + ret =3D -ENOMEM; + goto done; + } + beacon_ie->ie_index =3D cpu_to_le16(priv->beacon_idx); + beacon_ie->mgmt_subtype_mask =3D cpu_to_le16(NXPWIFI_DELETE_MASK); + beacon_ie->ie_length =3D 0; + } + if (priv->proberesp_idx !=3D NXPWIFI_AUTO_IDX_MASK) { + pr_ie =3D kmalloc(sizeof(*pr_ie), GFP_KERNEL); + if (!pr_ie) { + ret =3D -ENOMEM; + goto done; + } + pr_ie->ie_index =3D cpu_to_le16(priv->proberesp_idx); + pr_ie->mgmt_subtype_mask =3D cpu_to_le16(NXPWIFI_DELETE_MASK); + pr_ie->ie_length =3D 0; + } + if (priv->assocresp_idx !=3D NXPWIFI_AUTO_IDX_MASK) { + ar_ie =3D kmalloc(sizeof(*ar_ie), GFP_KERNEL); + if (!ar_ie) { + ret =3D -ENOMEM; + goto done; + } + ar_ie->ie_index =3D cpu_to_le16(priv->assocresp_idx); + ar_ie->mgmt_subtype_mask =3D cpu_to_le16(NXPWIFI_DELETE_MASK); + ar_ie->ie_length =3D 0; + } + + if (beacon_ie || pr_ie || ar_ie) + ret =3D nxpwifi_update_uap_custom_ie(priv, + beacon_ie, &priv->beacon_idx, + pr_ie, &priv->proberesp_idx, + ar_ie, &priv->assocresp_idx); + +done: + kfree(gen_ie); + kfree(beacon_ie); + kfree(pr_ie); + kfree(ar_ie); + + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2069.outbound.protection.outlook.com [40.107.8.69]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0F7717166E; Fri, 21 Jun 2024 07:53:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.69 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956427; cv=fail; b=OvSf2UER7B1c7EGqvbsnYMJztGB1w+UfHFHXz6gAB3xFwwtMfG6/zo0lSzy1Bny6bALiAKs0eAPVQwi54qq4Z+km1GCxw474JINMsXPeZeuunfCuw0KBU/YUjEZKATrwJ//d8ESfM1kOVvy7xp+/rvULs0nwAmQwWI9PbtfMip0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956427; c=relaxed/simple; bh=fwahuzSqlOgzx7xggO7pGwA/UCEBjcfeVKOkB+5T7E4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=fq5dstTHTGS37vBYGbnn0YBprX9GxCFvbrpfaCeP2+QbNnQBrK+fCTlmOs6KMmn2t5xIfITtsQYSluqKmlFl+r9ckluE6NcQy+MkoK4PScMhzsCURXHp8JF5/e/3gyMibGINZwXs5KqtZo0Wro3GwOvTvjiFrWQsCPLBee9DXPk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=ahPXlbq0; arc=fail smtp.client-ip=40.107.8.69 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="ahPXlbq0" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=P+f9GsISshIV8M0Dyrm15Y5mozTW7h7pZ6cvp5ilrovPb/AtvyfK3xnrW/9ybo+1Srm9kIN/DMJP6UBLPe8Hw+ri6x26rQTpM82/cPglrv90AUbFPDkYFfzXqvuYtqyTgZ3vLnRwGl3tlUgFnaS4uBFQz0kXZXpGSPbh+/XtQapiJ5zJHx9YYx/VJg1Y4znlX2Knb3qMYQgUYokHen87ZhoOHp5uCeUSx8ySnI7Hfp4+s0ldFoYcsVVc0lrOOW93O52+mP98EhIGlNsRnvo+HPej3SIdNkPBmp8sqin5r85Nn3ZBz5cjmxC/wWEnPNTZ1JgvpHtFpZMMEmiux+iNJw== 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=pNbDWSfKHx1T8QiK+SUlWoPo54vRTjDOgM8l/zmkn4U=; b=b5DkJITuS6ro5YxjZG+b6qt3wvtb8zuKRTEe/UYdyjr/bT7apnuH2oYrknaVX6StNp2LI2fCNZRXgHEKKe45oj9HXONBUUYGHwM7gzEkEhCtF0U119JJX8wd/t8LwLpFhPp+13UgsdCwcdfWRhNrLM/76mlVQ6XQLECVfWJ1rzWzdPFteUI4uOMl29fLI1ljOj3gkj6cDLe/OkCx4q+D89htYm6wljEo9cXjudarEl3/Ck8rrm8VHQUZpcDVvWOjzIgUgK9cUQhh+/ofb285OnVh66d2fdHUyjw3hgd4++63rdc8PbNp+xvy/sV0i4ldElhbydEpLbZPN/EOSSuX+A== 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=pNbDWSfKHx1T8QiK+SUlWoPo54vRTjDOgM8l/zmkn4U=; b=ahPXlbq02MyDnVLcJeCJpxWUxBzvp8U3v2YlWh6RJOckxY2knJ7Bz8xIdw3q41NxFKA83sYthQQs7HH71xSwUOn/R3Z2sUjrYHCC8rLNht+kssKWI416pV7ClPo55/nIlLhvCYpqGBHcxlz4JV0gOJHLfBkiNcqeoxxIez7BhkA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:53:42 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:41 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 20/43] wifi: nxpwifi: add init.c Date: Fri, 21 Jun 2024 15:51:45 +0800 Message-Id: <20240621075208.513497-21-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: f67eee80-6a3b-45c8-c220-08dc91c744a2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?otuZina4hDQZ4QeOJ6SQfA5BLrXR5uf3IUw7aPq/VE1nB5LmmHy9BI/D06Ml?= =?us-ascii?Q?2Bq3MheOEAWrwy4JpiQFc4iWGggbZns6n3CaKdlSn3+AcrDTiJnPvK7UysVJ?= =?us-ascii?Q?5v37W6+joN4aWUc/fiMo//bXdD7s52HA1cc+qrsLILQ+NuRIjheR79fH0AVB?= =?us-ascii?Q?2YQOQ8IcrpQtqRIf0ZA35BU76TxPuRR6pHu/nHxCZ8l07ugqzNZDchIA1PRs?= =?us-ascii?Q?RBP9DrIfU9HT7SsUJgy+qQocw8x+jAk+3x08Jli37Cc8rLgDhk33zLGOqYdJ?= =?us-ascii?Q?/VIz4FGPGbkgu682ENKGYxHgYzVitoiijTumb3vxk0fPNA97yW2DY6uqWev1?= =?us-ascii?Q?A+9WhnR9D6xw7tOKglfjTC2s7ekuWaUlcXm/nZbZf/Oyjx5tE75mxCGJSxr7?= =?us-ascii?Q?udGAMw/Bs1CYJgJlhXoEll369xDY9OuiWFkq66vLDdc8rSuqKm35cDYDc3lM?= =?us-ascii?Q?/TvXGFiXCrV8uJER7ARh5QXzxbN58AZ2ErrWEyQExtM3lnTdCwGZzbBkpsje?= =?us-ascii?Q?w9DDXwWATOTqP5MEAFhiMP0Wi7KdaJmhEefdn+rFl3+C+EGeRg4u0ROAwrAC?= =?us-ascii?Q?feSWUvhs4FkvtZR223TTHy88J8uT30fQ1CCfoP+M/rlNxypncEK5w75gGLku?= =?us-ascii?Q?ubEMzEPSeUPtOgzUhnzJL8C4/P2EYOfvUwF7vDaYxQ8Gt9Qn4+9kTByWnVg1?= =?us-ascii?Q?zmgg3BiJH/7WW4Jni9GHW3lDvEDx/72gZP4WRap0Oopjnc2X4yinkfro+Ym0?= =?us-ascii?Q?/3q85bopYxfM2+Na3NIPF9U0ob0NQC5vXnbqMfodRX8nMP/OYKLE8OrJxKqi?= =?us-ascii?Q?fhJw7/ES0dYmQcvffabqoXZI98S34fOXbu2D50efifUbXSi6o7Y6LxnASYzT?= =?us-ascii?Q?7r2RVnEl41KYxks5147CsGAryDmftgz4QF4AxE0acKU+02rbuiJGzt5Bk+Ig?= =?us-ascii?Q?8lxSJglviTk8tXg7GTCoRJfH/N6YFa5UpijI9LePUslTbrCF1IW1Y5G9txdj?= =?us-ascii?Q?rBNltaFZXJmxjpQM7Jo+Nq9uv5bKkYStPnE2blwo5JAMm+8/dwmsAo8xTzh6?= =?us-ascii?Q?F/2B0GkPytw9W4+pmCNoaB52xgnPE4zLo5ZGHuiOOKWoqkCNB9J1JH+GX2SJ?= =?us-ascii?Q?/ntSpkpDFfGsHloA6qQ3aBAZrQeshciy4YHDfP018+lZ7gkSttYzSAlzkJwK?= =?us-ascii?Q?bYkcXHo18sUeeZjfPGX43smJzkswh1oDfOqqP8QGlzUBVQEvfjHlN3evQHBm?= =?us-ascii?Q?sDs2FZpmVue6gwd2b2PJ+nplUF4alMHatwwcHigwzZj3NdsPsjRtAGdCkzvA?= =?us-ascii?Q?5LE6SxC/aHNq2uc64Dg4+Oiv4xWsvQPd4DZ7KEmndRsnhl8JvzGEYhhcczYu?= =?us-ascii?Q?2zSx6n8=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?USV+KLPFX66IBimVi9AJjKHsdMaYb9lH5BTZp1t9dadr0QZMD4KPvtXN9t+I?= =?us-ascii?Q?7xs5TUFz5tHjwxmVxp5eBNUis7CVonE3NBLy7bMWkuVQAovlRJx4wy3CahQ2?= =?us-ascii?Q?mu5fjns/0hE6g6j9CoTrDJmTwJkGwAhiCMK6yTGLMV+a86SYOzODT9NDoS9R?= =?us-ascii?Q?vsZ5G7u9sH3eJqYtrbmwWcnGELA2z8ioOAH4Ewk9ghW5LOHAc8YYfIWCenyZ?= =?us-ascii?Q?ph08ZY/NlQhohgHcQnNCRIuYCOEQS/fW3Pn0rSVr+x/znyjN/CfM5VA8Dy/Q?= =?us-ascii?Q?c/1dn4mx3IAgPIIle4yPCmDQqo8AFN3FaZ5bb0EXzYjLilOLLuWcsJ9NCdbR?= =?us-ascii?Q?krgeQte+21+HaYpyWNwntMJtTuySIGcekkEkMGPuJ7uEoTOLS9nT/2ld9C9g?= =?us-ascii?Q?xOB3JjocYJRJLLRAELX+63hPoZZW2aQiFwgRFuzAC5wwKitrpEvdMMB6GaXk?= =?us-ascii?Q?/yKJpoCZOXKw0UOZgWBdnyS3g6i7KvnDuw4AlUL6Bmn7iil68dSYUVoOxTKR?= =?us-ascii?Q?nfNvhR4cL3vWAT2i8G7y57Gt0ppeUB0g7cdd8nSErAgQCFXp1otTEY8wanGa?= =?us-ascii?Q?O1zSqU2goE/YLGyp0SYaT33SM9ne9OZxyJ7lkeapk6bUaWL+2NNjDSgOOWHR?= =?us-ascii?Q?AWTDrTXb4A2eVQKkonKTuGE2S9mTsXZSE4V/3Nla3WmfiYcts2yFKsWNosZU?= =?us-ascii?Q?xs+3YGEXtPrG4XA8LR1r3y2I8vxZ9asKgpnMhWnUHzvQ3dBI8aAVxi9YP2cM?= =?us-ascii?Q?GTyzJ7oPs81fQzwxyljVMDef3PVwcQ2GSxsp/lCv+6hm8Mms6Z6+q87HbalO?= =?us-ascii?Q?7PZbtlVC1GUpLpWJJGrnAYZriBd2WhCBoIwV4JRTzIsugNkkcVaajrBhAQg5?= =?us-ascii?Q?TSqGlqKD6d18PictiFfr3fb8sKCdgDTPDtXj9GnUL3tz2JX/ngLciNLvndsP?= =?us-ascii?Q?qfKMTk+sAN8uFF+UKqM+NdTGys4MhIsDysZn0PRHTwpOl5QUF1dUK8genn8O?= =?us-ascii?Q?grIofdSnatxolk9TLvrm+kaEKKwqhSLKEKZ9Q8dNS3f08CCdnOitHYiTzZwn?= =?us-ascii?Q?w6NZ6ezHZGAg1rStVp3SfrJICyQzCqNdIEmr/7HVYztwcaNjzhwFhrjmhTh3?= =?us-ascii?Q?E5RWRkOR6K+5LbhlWPn912ib45qGZJadroQcUTMZ5xuBhfvczVU16k56h8QG?= =?us-ascii?Q?0neG+SJZD+b1EwEXCBXQVOuI0eP2sUjpUieMZdQqN/kzfexjDKvtssLrxIur?= =?us-ascii?Q?QZUy078IFQahh/GYr8CvDXYSwkiBDZCJKB8Y3yjYyqCTHEmNByDzAOr/VXxe?= =?us-ascii?Q?t3p1e19hgNK6C+dfGnMJjq0V96pF/xaj46+37puOXGb7J1ZiKdx8eyP21ZXm?= =?us-ascii?Q?kMfioZObdrxrX+kwavhbTOGXDRSXTLvFn0iLJkTLZPnVQlU9W9Wgp0eiZIhL?= =?us-ascii?Q?2bCMf0Iss8FERZESKixyD88yFtMar48SSTdWPWEjJryBVLEMiOJcfbLDuJA8?= =?us-ascii?Q?woiG5eomq/neUwSeX0EqqpodtOpPiQRYk4QALBBxxlBqCXoDBjSc4R2VdfkV?= =?us-ascii?Q?nQ6JND4Gb7XttYlOaJ6r7zgnp7PkvhLfOQvwxQVU?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: f67eee80-6a3b-45c8-c220-08dc91c744a2 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:41.9207 (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: XUqbrh8J02Lsr7uq6z708p10XV9flkCv9sCZOrsDn1eIIsIfWJLxcr88FjGs9vaBpQE5oE357UPsfhqxiSz/qA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/init.c | 696 ++++++++++++++++++++++++ 1 file changed, 696 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/init.c diff --git a/drivers/net/wireless/nxp/nxpwifi/init.c b/drivers/net/wireless= /nxp/nxpwifi/init.c new file mode 100644 index 000000000000..792eb346a797 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/init.c @@ -0,0 +1,696 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: HW/FW Initialization + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" + +/* This function adds a BSS priority table to the table list. + * + * The function allocates a new BSS priority table node and adds it to + * the end of BSS priority table list, kept in driver memory. + */ +static int nxpwifi_add_bss_prio_tbl(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_bss_prio_node *bss_prio; + struct nxpwifi_bss_prio_tbl *tbl =3D adapter->bss_prio_tbl; + + bss_prio =3D kzalloc(sizeof(*bss_prio), GFP_KERNEL); + if (!bss_prio) + return -ENOMEM; + + bss_prio->priv =3D priv; + INIT_LIST_HEAD(&bss_prio->list); + + spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock); + list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head); + spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock); + + return 0; +} + +static void wakeup_timer_fn(struct timer_list *t) +{ + struct nxpwifi_adapter *adapter =3D from_timer(adapter, t, wakeup_timer); + + nxpwifi_dbg(adapter, ERROR, "Firmware wakeup failed\n"); + adapter->hw_status =3D NXPWIFI_HW_STATUS_RESET; + nxpwifi_cancel_all_pending_cmd(adapter); + + if (adapter->if_ops.card_reset) + adapter->if_ops.card_reset(adapter); +} + +static void fw_dump_work(struct work_struct *work) +{ + struct nxpwifi_adapter *adapter =3D + container_of(work, struct nxpwifi_adapter, devdump_work.work); + + nxpwifi_upload_device_dump(adapter); +} + +/* This function initializes the private structure and sets default + * values to the members. + * + * Additionally, it also initializes all the locks and sets up all the + * lists. + */ +int nxpwifi_init_priv(struct nxpwifi_private *priv) +{ + u32 i; + + priv->media_connected =3D false; + eth_broadcast_addr(priv->curr_addr); + priv->port_open =3D false; + priv->usb_port =3D NXPWIFI_USB_EP_DATA; + priv->pkt_tx_ctrl =3D 0; + priv->bss_mode =3D NL80211_IFTYPE_UNSPECIFIED; + priv->data_rate =3D 0; /* Initially indicate the rate as auto */ + priv->is_data_rate_auto =3D true; + priv->bcn_avg_factor =3D DEFAULT_BCN_AVG_FACTOR; + priv->data_avg_factor =3D DEFAULT_DATA_AVG_FACTOR; + + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + + priv->sec_info.wep_enabled =3D 0; + priv->sec_info.authentication_mode =3D NL80211_AUTHTYPE_OPEN_SYSTEM; + priv->sec_info.encryption_mode =3D 0; + for (i =3D 0; i < ARRAY_SIZE(priv->wep_key); i++) + memset(&priv->wep_key[i], 0, sizeof(struct nxpwifi_wep_key)); + priv->wep_key_curr_index =3D 0; + priv->curr_pkt_filter =3D HOST_ACT_MAC_DYNAMIC_BW_ENABLE | + HOST_ACT_MAC_RX_ON | HOST_ACT_MAC_TX_ON | + HOST_ACT_MAC_ETHERNETII_ENABLE; + + priv->beacon_period =3D 100; /* beacon interval */ + priv->attempted_bss_desc =3D NULL; + memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params)); + priv->listen_interval =3D NXPWIFI_DEFAULT_LISTEN_INTERVAL; + + memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid)); + memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid)); + memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); + priv->assoc_rsp_size =3D 0; + priv->atim_window =3D 0; + priv->tx_power_level =3D 0; + priv->max_tx_power_level =3D 0; + priv->min_tx_power_level =3D 0; + priv->tx_ant =3D 0; + priv->rx_ant =3D 0; + priv->tx_rate =3D 0; + priv->rxpd_htinfo =3D 0; + priv->rxpd_rate =3D 0; + priv->rate_bitmap =3D 0; + priv->data_rssi_last =3D 0; + priv->data_rssi_avg =3D 0; + priv->data_nf_avg =3D 0; + priv->data_nf_last =3D 0; + priv->bcn_rssi_last =3D 0; + priv->bcn_rssi_avg =3D 0; + priv->bcn_nf_avg =3D 0; + priv->bcn_nf_last =3D 0; + memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie)); + memset(&priv->aes_key, 0, sizeof(priv->aes_key)); + priv->wpa_ie_len =3D 0; + priv->wpa_is_gtk_set =3D false; + + memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf)); + priv->assoc_tlv_buf_len =3D 0; + memset(&priv->wps, 0, sizeof(priv->wps)); + memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); + priv->gen_ie_buf_len =3D 0; + memset(priv->vs_ie, 0, sizeof(priv->vs_ie)); + + priv->wmm_required =3D true; + priv->wmm_enabled =3D false; + priv->wmm_qosinfo =3D 0; + priv->curr_bcn_buf =3D NULL; + priv->curr_bcn_size =3D 0; + priv->wps_ie =3D NULL; + priv->wps_ie_len =3D 0; + priv->ap_11n_enabled =3D 0; + memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); + + priv->scan_block =3D false; + + priv->csa_chan =3D 0; + priv->csa_expire_time =3D 0; + priv->del_list_idx =3D 0; + priv->hs2_enabled =3D false; + memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); + + nxpwifi_init_11h_params(priv); + + return nxpwifi_add_bss_prio_tbl(priv); +} + +/* This function allocates buffers for members of the adapter + * structure. + * + * The memory allocated includes scan table, command buffers, and + * sleep confirm command buffer. In addition, the queues are + * also initialized. + */ +static int nxpwifi_allocate_adapter(struct nxpwifi_adapter *adapter) +{ + int ret; + + /* Allocate command buffer */ + ret =3D nxpwifi_alloc_cmd_buffer(adapter); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "%s: failed to alloc cmd buffer\n", + __func__); + return -1; + } + + adapter->sleep_cfm =3D + dev_alloc_skb(sizeof(struct nxpwifi_opt_sleep_confirm) + + INTF_HEADER_LEN); + + if (!adapter->sleep_cfm) { + nxpwifi_dbg(adapter, ERROR, + "%s: failed to alloc sleep cfm\t" + " cmd buffer\n", __func__); + return -1; + } + skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN); + + return 0; +} + +/* This function initializes the adapter structure and sets default + * values to the members of adapter. + * + * This also initializes the WMM related parameters in the driver private + * structures. + */ +static void nxpwifi_init_adapter(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_opt_sleep_confirm *sleep_cfm_buf =3D NULL; + + skb_put(adapter->sleep_cfm, sizeof(struct nxpwifi_opt_sleep_confirm)); + + adapter->cmd_sent =3D false; + adapter->data_sent =3D true; + + adapter->intf_hdr_len =3D INTF_HEADER_LEN; + + adapter->cmd_resp_received =3D false; + adapter->event_received =3D false; + adapter->data_received =3D false; + adapter->assoc_resp_received =3D false; + adapter->priv_link_lost =3D NULL; + adapter->host_mlme_link_lost =3D false; + + clear_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + + adapter->hw_status =3D NXPWIFI_HW_STATUS_INITIALIZING; + + adapter->ps_mode =3D NXPWIFI_802_11_POWER_MODE_CAM; + adapter->ps_state =3D PS_STATE_AWAKE; + adapter->need_to_wakeup =3D false; + + adapter->scan_mode =3D HOST_BSS_MODE_ANY; + adapter->specific_scan_time =3D NXPWIFI_SPECIFIC_SCAN_CHAN_TIME; + adapter->active_scan_time =3D NXPWIFI_ACTIVE_SCAN_CHAN_TIME; + adapter->passive_scan_time =3D NXPWIFI_PASSIVE_SCAN_CHAN_TIME; + adapter->scan_chan_gap_time =3D NXPWIFI_DEF_SCAN_CHAN_GAP_TIME; + + adapter->scan_probes =3D 1; + + adapter->multiple_dtim =3D 1; + + /* default value in firmware will be used */ + adapter->local_listen_interval =3D 0; + + adapter->is_deep_sleep =3D false; + + adapter->delay_null_pkt =3D false; + adapter->delay_to_ps =3D 1000; + adapter->enhanced_ps_mode =3D PS_MODE_AUTO; + + /* Disable NULL Pkg generation by default */ + adapter->gen_null_pkt =3D false; + /* Disable pps/uapsd mode by default */ + adapter->pps_uapsd_mode =3D false; + adapter->pm_wakeup_card_req =3D false; + + adapter->pm_wakeup_fw_try =3D false; + + adapter->curr_tx_buf_size =3D NXPWIFI_TX_DATA_BUF_SIZE_2K; + + clear_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); + adapter->hs_cfg.conditions =3D cpu_to_le32(HS_CFG_COND_DEF); + adapter->hs_cfg.gpio =3D HS_CFG_GPIO_DEF; + adapter->hs_cfg.gap =3D HS_CFG_GAP_DEF; + adapter->hs_activated =3D false; + + memset(adapter->event_body, 0, sizeof(adapter->event_body)); + adapter->hw_dot_11n_dev_cap =3D 0; + adapter->hw_dev_mcs_support =3D 0; + adapter->sec_chan_offset =3D 0; + + nxpwifi_wmm_init(adapter); + atomic_set(&adapter->tx_hw_pending, 0); + + sleep_cfm_buf =3D (struct nxpwifi_opt_sleep_confirm *) + adapter->sleep_cfm->data; + memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); + sleep_cfm_buf->command =3D cpu_to_le16(HOST_CMD_802_11_PS_MODE_ENH); + sleep_cfm_buf->size =3D cpu_to_le16(adapter->sleep_cfm->len); + sleep_cfm_buf->result =3D 0; + sleep_cfm_buf->action =3D cpu_to_le16(SLEEP_CONFIRM); + sleep_cfm_buf->resp_ctrl =3D cpu_to_le16(RESP_NEEDED); + + memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); + adapter->tx_lock_flag =3D false; + adapter->null_pkt_interval =3D 0; + adapter->fw_bands =3D 0; + adapter->config_bands =3D 0; + adapter->fw_release_number =3D 0; + adapter->fw_cap_info =3D 0; + memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); + adapter->event_cause =3D 0; + adapter->region_code =3D 0; + adapter->bcn_miss_time_out =3D DEFAULT_BCN_MISS_TIMEOUT; + memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); + adapter->arp_filter_size =3D 0; + adapter->max_mgmt_ie_index =3D MAX_MGMT_IE_INDEX; + adapter->key_api_major_ver =3D 0; + adapter->key_api_minor_ver =3D 0; + eth_broadcast_addr(adapter->perm_addr); + adapter->iface_limit.sta_intf =3D NXPWIFI_MAX_STA_NUM; + adapter->iface_limit.uap_intf =3D NXPWIFI_MAX_UAP_NUM; + adapter->active_scan_triggered =3D false; + timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0); + adapter->devdump_len =3D 0; + INIT_DELAYED_WORK(&adapter->devdump_work, fw_dump_work); +} + +/* This function sets trans_start per tx_queue + */ +void nxpwifi_set_trans_start(struct net_device *dev) +{ + int i; + + for (i =3D 0; i < dev->num_tx_queues; i++) + txq_trans_cond_update(netdev_get_tx_queue(dev, i)); + + netif_trans_update(dev); +} + +/* This function wakes up all queues in net_device + */ +void nxpwifi_wake_up_net_dev_queue(struct net_device *netdev, + struct nxpwifi_adapter *adapter) +{ + spin_lock_bh(&adapter->queue_lock); + netif_tx_wake_all_queues(netdev); + spin_unlock_bh(&adapter->queue_lock); +} + +/* This function stops all queues in net_device + */ +void nxpwifi_stop_net_dev_queue(struct net_device *netdev, + struct nxpwifi_adapter *adapter) +{ + spin_lock_bh(&adapter->queue_lock); + netif_tx_stop_all_queues(netdev); + spin_unlock_bh(&adapter->queue_lock); +} + +/* This function invalidates the list heads. + */ +static void nxpwifi_invalidate_lists(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + s32 i, j; + + list_del(&adapter->cmd_free_q); + list_del(&adapter->cmd_pending_q); + list_del(&adapter->scan_pending_q); + + for (i =3D 0; i < adapter->priv_num; i++) + list_del(&adapter->bss_prio_tbl[i].bss_prio_head); + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv =3D adapter->priv[i]; + for (j =3D 0; j < MAX_NUM_TID; ++j) + list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); + list_del(&priv->tx_ba_stream_tbl_ptr); + list_del(&priv->rx_reorder_tbl_ptr); + list_del(&priv->sta_list); + } + } +} + +/* This function performs cleanup for adapter structure. + * + * The cleanup is done recursively, by canceling all pending + * commands, freeing the member buffers previously allocated + * (command buffers, scan table buffer, sleep confirm command + * buffer), stopping the timers and calling the cleanup routines + * for every interface. + */ +static void +nxpwifi_adapter_cleanup(struct nxpwifi_adapter *adapter) +{ + del_timer(&adapter->wakeup_timer); + cancel_delayed_work_sync(&adapter->devdump_work); + nxpwifi_cancel_all_pending_cmd(adapter); + wake_up_interruptible(&adapter->cmd_wait_q.wait); + wake_up_interruptible(&adapter->hs_activate_wait_q); +} + +void nxpwifi_free_cmd_buffers(struct nxpwifi_adapter *adapter) +{ + nxpwifi_invalidate_lists(adapter); + + /* Free command buffer */ + nxpwifi_dbg(adapter, INFO, "info: free cmd buffer\n"); + nxpwifi_free_cmd_buffer(adapter); + + if (adapter->sleep_cfm) + dev_kfree_skb_any(adapter->sleep_cfm); +} + +/* This function intializes the lock variables and + * the list heads. + */ +int nxpwifi_init_lock_list(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + s32 i, j; + + spin_lock_init(&adapter->int_lock); + spin_lock_init(&adapter->main_proc_lock); + spin_lock_init(&adapter->nxpwifi_cmd_lock); + spin_lock_init(&adapter->queue_lock); + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv =3D adapter->priv[i]; + spin_lock_init(&priv->wmm.ra_list_spinlock); + spin_lock_init(&priv->curr_bcn_buf_lock); + spin_lock_init(&priv->sta_list_spinlock); + } + } + + /* Initialize cmd_free_q */ + INIT_LIST_HEAD(&adapter->cmd_free_q); + /* Initialize cmd_pending_q */ + INIT_LIST_HEAD(&adapter->cmd_pending_q); + /* Initialize scan_pending_q */ + INIT_LIST_HEAD(&adapter->scan_pending_q); + + spin_lock_init(&adapter->cmd_free_q_lock); + spin_lock_init(&adapter->cmd_pending_q_lock); + spin_lock_init(&adapter->scan_pending_q_lock); + spin_lock_init(&adapter->rx_proc_lock); + + skb_queue_head_init(&adapter->rx_data_q); + skb_queue_head_init(&adapter->tx_data_q); + + for (i =3D 0; i < adapter->priv_num; ++i) { + INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); + spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); + } + + for (i =3D 0; i < adapter->priv_num; i++) { + if (!adapter->priv[i]) + continue; + priv =3D adapter->priv[i]; + for (j =3D 0; j < MAX_NUM_TID; ++j) + INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); + INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); + INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); + INIT_LIST_HEAD(&priv->sta_list); + skb_queue_head_init(&priv->bypass_txq); + + spin_lock_init(&priv->tx_ba_stream_tbl_lock); + spin_lock_init(&priv->rx_reorder_tbl_lock); + + spin_lock_init(&priv->ack_status_lock); + idr_init(&priv->ack_status_frames); + } + + return 0; +} + +/* This function initializes the firmware. + * + * The following operations are performed sequentially - + * - Allocate adapter structure + * - Initialize the adapter structure + * - Initialize the private structure + * - Add BSS priority tables to the adapter structure + * - For each interface, send the init commands to firmware + * - Send the first command in command pending queue, if available + */ +int nxpwifi_init_fw(struct nxpwifi_adapter *adapter) +{ + int ret; + struct nxpwifi_private *priv; + u8 i, first_sta =3D true; + int is_cmd_pend_q_empty; + + adapter->hw_status =3D NXPWIFI_HW_STATUS_INITIALIZING; + + /* Allocate memory for member of adapter structure */ + ret =3D nxpwifi_allocate_adapter(adapter); + if (ret) + return -1; + + /* Initialize adapter structure */ + nxpwifi_init_adapter(adapter); + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv =3D adapter->priv[i]; + + /* Initialize private structure */ + ret =3D nxpwifi_init_priv(priv); + if (ret) + return -1; + } + } + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + ret =3D nxpwifi_sta_init_cmd(adapter->priv[i], + first_sta, true); + if (ret =3D=3D -1) + return -1; + + first_sta =3D false; + } + } + + spin_lock_bh(&adapter->cmd_pending_q_lock); + is_cmd_pend_q_empty =3D list_empty(&adapter->cmd_pending_q); + spin_unlock_bh(&adapter->cmd_pending_q_lock); + if (!is_cmd_pend_q_empty) { + /* Send the first command in queue and return */ + if (nxpwifi_main_process(adapter) !=3D -1) + ret =3D -EINPROGRESS; + } else { + adapter->hw_status =3D NXPWIFI_HW_STATUS_READY; + } + + return ret; +} + +/* This function deletes the BSS priority tables. + * + * The function traverses through all the allocated BSS priority nodes + * in every BSS priority table and frees them. + */ +static void nxpwifi_delete_bss_prio_tbl(struct nxpwifi_private *priv) +{ + int i; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_bss_prio_node *bssprio_node, *tmp_node; + struct list_head *head; + spinlock_t *lock; /* bss priority lock */ + + for (i =3D 0; i < adapter->priv_num; ++i) { + head =3D &adapter->bss_prio_tbl[i].bss_prio_head; + lock =3D &adapter->bss_prio_tbl[i].bss_prio_lock; + nxpwifi_dbg(adapter, INFO, + "info: delete BSS priority table,\t" + "bss_type =3D %d, bss_num =3D %d, i =3D %d,\t" + "head =3D %p\n", + priv->bss_type, priv->bss_num, i, head); + + { + spin_lock_bh(lock); + list_for_each_entry_safe(bssprio_node, tmp_node, head, + list) { + if (bssprio_node->priv =3D=3D priv) { + nxpwifi_dbg(adapter, INFO, + "info: Delete\t" + "node %p, next =3D %p\n", + bssprio_node, tmp_node); + list_del(&bssprio_node->list); + kfree(bssprio_node); + } + } + spin_unlock_bh(lock); + } + } +} + +/* This function frees the private structure, including cleans + * up the TX and RX queues and frees the BSS priority tables. + */ +void nxpwifi_free_priv(struct nxpwifi_private *priv) +{ + nxpwifi_clean_txrx(priv); + nxpwifi_delete_bss_prio_tbl(priv); + nxpwifi_free_curr_bcn(priv); +} + +/* This function is used to shutdown the driver. + * + * The following operations are performed sequentially - + * - Check if already shut down + * - Make sure the main process has stopped + * - Clean up the Tx and Rx queues + * - Delete BSS priority tables + * - Free the adapter + * - Notify completion + */ +void +nxpwifi_shutdown_drv(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + s32 i; + struct sk_buff *skb; + + /* nxpwifi already shutdown */ + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_NOT_READY) + return; + + /* cancel current command */ + if (adapter->curr_cmd) { + nxpwifi_dbg(adapter, WARN, + "curr_cmd is still in processing\n"); + del_timer_sync(&adapter->cmd_timer); + nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); + adapter->curr_cmd =3D NULL; + } + + /* shut down nxpwifi */ + nxpwifi_dbg(adapter, MSG, + "info: shutdown nxpwifi...\n"); + + /* Clean up Tx/Rx queues and delete BSS priority table */ + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv =3D adapter->priv[i]; + + nxpwifi_abort_cac(priv); + nxpwifi_free_priv(priv); + } + } + + atomic_set(&adapter->tx_queued, 0); + while ((skb =3D skb_dequeue(&adapter->tx_data_q))) + nxpwifi_write_data_complete(adapter, skb, 0, 0); + + spin_lock_bh(&adapter->rx_proc_lock); + + while ((skb =3D skb_dequeue(&adapter->rx_data_q))) { + struct nxpwifi_rxinfo *rx_info =3D NXPWIFI_SKB_RXCB(skb); + + atomic_dec(&adapter->rx_pending); + priv =3D adapter->priv[rx_info->bss_num]; + if (priv) + priv->stats.rx_dropped++; + + dev_kfree_skb_any(skb); + } + + spin_unlock_bh(&adapter->rx_proc_lock); + + nxpwifi_adapter_cleanup(adapter); + + adapter->hw_status =3D NXPWIFI_HW_STATUS_NOT_READY; +} + +/* This function downloads the firmware to the card. + * + * The actual download is preceded by two sanity checks - + * - Check if firmware is already running + * - Check if the interface is the winner to download the firmware + * + * ...and followed by another - + * - Check if the firmware is downloaded successfully + * + * After download is successfully completed, the host interrupts are enabl= ed. + */ +int nxpwifi_dnld_fw(struct nxpwifi_adapter *adapter, + struct nxpwifi_fw_image *pmfw) +{ + int ret; + u32 poll_num =3D 1; + + /* check if firmware is already running */ + ret =3D adapter->if_ops.check_fw_status(adapter, poll_num); + if (!ret) { + nxpwifi_dbg(adapter, MSG, + "WLAN FW already running! Skip FW dnld\n"); + return 0; + } + + /* check if we are the winner for downloading FW */ + if (adapter->if_ops.check_winner_status) { + adapter->winner =3D 0; + ret =3D adapter->if_ops.check_winner_status(adapter); + + poll_num =3D MAX_FIRMWARE_POLL_TRIES; + if (ret) { + nxpwifi_dbg(adapter, MSG, + "WLAN read winner status failed!\n"); + return ret; + } + + if (!adapter->winner) { + nxpwifi_dbg(adapter, MSG, + "WLAN is not the winner! Skip FW dnld\n"); + goto poll_fw; + } + } + + if (pmfw) { + /* Download firmware with helper */ + ret =3D adapter->if_ops.prog_fw(adapter, pmfw); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "prog_fw failed ret=3D%#x\n", ret); + return ret; + } + } + +poll_fw: + /* Check if the firmware is downloaded successfully or not */ + ret =3D adapter->if_ops.check_fw_status(adapter, poll_num); + if (ret) + nxpwifi_dbg(adapter, ERROR, + "FW failed to be active in time\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(nxpwifi_dnld_fw); --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5EF57171E6A; Fri, 21 Jun 2024 07:53:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956431; cv=fail; b=GGo9LFkHI6QuYR9xuIqkuVAT5tGE2gSvrhg0aPcRoCB8fnkx4EvD0uoGm3gIQQlv8WhDsRH6RC8jPVCnkjFj26UPLX1/AWT5rqNkgIJubbyw4CFWpnz3ypwTHnVqT8GIDTF49eXp1c2FODLiMazO1ABiBSN+gROuoSDvO4lC+eU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956431; c=relaxed/simple; bh=+Hc38o8j24z5H8NImnvPilD/fhU5NEpS24m3JhDdxE4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=jidpjJvhS5bR2vji299K+LMg6P5rQXo/znuuxhp0g+HUlslK/aM36nvDgLmu/a4rMU/IdM504M7ZLLyVSBME7UkvnfDdqUetmHNitBeEN/FE/WGXd8sNcOBMPAo6ODRDEY3WrEz5Lc7jh2Gj3geXk0YNqxJjbRDIU7kFyn7wjSs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=MUL1Ey08; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="MUL1Ey08" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Yu3HUPMGAzMZafN6ZUVcVPN8aHKb/m5VuN77EICIY2SO/CGGTZWMG4wI7npRn1uPdwOz6UGmAYq5mC8sl7tMrIrAPiGiTtuGJC2zBIrSK83hWEdAjtAV0hHRhRTT3RRxVRWgkOEMuroQuiE7mSARYDUP/o7LgseQorV9He7LyiL4M641y55cWEC3O9Uygyh7fxlwB2zcjIudDpqci/OITkJ7k+Qt+okn26zpD9tUUKjIyz3BZoQQmIbllofiFJDfnG6yxUXn2SdIyGSzoJRS9iLVVnb3l8my379B8bUd7u/j6mDiAVPcjUalEcm4QxUvHnKQzmRbvYExpfFttcSwQA== 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=GFc39Lj0uGo092n8QLjDs8jPw9mCJvcmIKCEJw+1DeE=; b=YXczyMr9BFLt99R31oqXuka8GZCsIafeatY7B4FIkSkAVnzy9ND20KNCXgcMZCHpB5bb7PYzF4/dqZb3cVqxKxllwkkiB2zu0FT6CmBBs33t1D4p1WM7ZMaEMD4h/HXZ5E9N4JoGZZCt88cz/BGD9bqw9TyF5+16pbnxih4Zh8c4TVR5FrmFwyGKxs8mEcwYERFx3U++kMz1Y43NT+ED1lya3fldxxXRxBqzqxG78MVkArumXuhdWbh/aPPuai8MRQKLHwQgsYPzPhr3TUnCagQluU5JlkSfs6AiY87PNIe3z2barhTl9/JUmii205mggBGFFY99Nus2XQad+DhFyA== 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=GFc39Lj0uGo092n8QLjDs8jPw9mCJvcmIKCEJw+1DeE=; b=MUL1Ey08FWdnSqRfXQqG3IEDF4m++HSdzo/zAJ1ehT+KflNGrWo2YuILNBSNkRIQRcmjAiGuJwFMDdH9Bhs8f8YDGTBFOWUkAc9MxI6DDH4qsqc70iY2bFyQpEJ/xCm5e2tTnnLdro6bCKPYywaDyWNBjlNcurBWGJ17mZ108qI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:44 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:44 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 21/43] wifi: nxpwifi: add ioctl.h Date: Fri, 21 Jun 2024 15:51:46 +0800 Message-Id: <20240621075208.513497-22-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 82e06da8-24e2-41ab-01bf-08dc91c74665 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?UBj3RHjaXlVNoOhOBzI9tHIPoAAOrWbdWZbYS1z8+xcjuwZsRnok8ofpZkgi?= =?us-ascii?Q?ut0R89cio6k1Qfc8Vys1LhfJenju3ugcilZ2hbruKZkokKCbJYnR4gibkarD?= =?us-ascii?Q?7ByPcTFq5xSTc+FxECtkyxa3Slyox2fKi8LlysBIBRL3Aq83TB8hdxnX+DSL?= =?us-ascii?Q?ujjrGnwv/KwJwZieTWr8D1/SPmHFdJtIOrPDlyzQ40DrPWGn4t8pDJOVFmQs?= =?us-ascii?Q?WpYs/kU2SWOoYxWtgU6DiEBxPa/2/nEa6ThPYK1DvV/8aA7o8RJGNES5XM0N?= =?us-ascii?Q?ge2+T7P7pw2slLQSMexw+1WyxzPMxxcnQCgIejhv/w9zGxoQqFZ8XpbWWgZL?= =?us-ascii?Q?DwxOA1J7y4JQSS013QP7G1VoCgP89joqDVUFlLtCjkGaUgfeZgYAyk1m4JbK?= =?us-ascii?Q?X12aC2uFoR7RAGPW+kNbrVNDaZASw9xCVIGzuuzNpJ6gan+j1r/IEhf3tBj5?= =?us-ascii?Q?JlSOqc3rl0oG4jD+ZfTTzXJ9vZOmQt4B5H3lA4aePdjq4swUrASh5oPIghQS?= =?us-ascii?Q?aDJkgNrYqxBqK+4QvRnO18hmThI2sjEav9stsR0I5Oz99OMedg47YHQbe801?= =?us-ascii?Q?yVmb3SGe7ZWH5Olad5xSADZ5Aqua7WEzIQ+61CII8a68YXiIAPGPGtUDJT8g?= =?us-ascii?Q?zoHPpOWrSMrZOAYzTtU/baFDeWs7OWNbxniyFpxjxQJWVkKty7o7AbU6rwKj?= =?us-ascii?Q?nvBh+T923Zh/P2UKSj0ReD8I2n0c0Smf8L0yGNkj2QxK9/bn6tzLnkGjuDxr?= =?us-ascii?Q?Ye9Gv11wfJ9fpYMOcLpzqC0iVn04bNxdLQtia+c4GHwy5Z/WPUNVqOu0ptkZ?= =?us-ascii?Q?h2ICwX30NaHWHzEujCkfNinb7Arjg4IH4mOUiXpY9oyY3q5EdIezGMWT/IdN?= =?us-ascii?Q?LmuMcM92ueUY67846eNlGXX0gvw/xMLLVDa0cIa+It0purzznc5yXO0yxIY0?= =?us-ascii?Q?35k2jTKgz/toQt9MPbxmgtS9M0+3KiaO5E/916YhF5PwFfo17KCALap4sDBt?= =?us-ascii?Q?1IGGCX4XDRhw9eel8ef1WEx6iNnPoDyaAKTLOSk+Bw5koaob2TiwpdstK1wG?= =?us-ascii?Q?70DKfIll48z7HkyHgU1gPUlnvypvAao1z/HXuAT1Bs+hudiUh5+DCmDM4Qw1?= =?us-ascii?Q?0fyILG8k0Yq4XkzyCd+lzFJlfDQC2nCrTofG5AK2Fcxpx+POd6F1dLncMkOr?= =?us-ascii?Q?Oz1uxRW9b0lRWxSh7v3/4Y0IiQXOOop2KXIJGL4wHCMG3biZGbnx+5dc2pm1?= =?us-ascii?Q?jvVlgZNAtyTOVbhxb3qRMmi6AusmyiKQGkoAAftYbjfU71gPB/ONXf+5DuOW?= =?us-ascii?Q?dkjd+Cvg1EiiBG6+82AOrmfGAsi5KgFnQgM0P6dkaRr3ccJdv/JNgN31om2h?= =?us-ascii?Q?eVvmfPY=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?mde35GWc+sSFU3Qf+eVHlh5oaMCKEMjjVr1d0aeVq0Rdgk3edWoLOYbF0E4o?= =?us-ascii?Q?0mV4K5u34uawlM/N4bVHrCqPk70kCd2cqKnSyuCoeXLLWea5J4fR7bhnLuC0?= =?us-ascii?Q?JOyZNuaw1XRtcmJhYRu2apc7UlUOpG13BR3yfavDKOZTwspm3Z1Y1XE7B8sa?= =?us-ascii?Q?1Tx+2lkHLSKeh2hj2aFvhnDlOkB3m1MAdpbrHXzu0qTrwd2jHtpEnh6mZFNZ?= =?us-ascii?Q?ljuKcxUNwg+u/te6nyo/CKN91yN/YSZ47/EZ8tSmN34wLTrX7QvNl7ucKwbm?= =?us-ascii?Q?lLEfQWm6mOTEFxIuJ+snzqfLHcaKDIXwOriOC4BNFjFMXahwqZfzXGy5cM+u?= =?us-ascii?Q?yYklYi6mfZfTbT+E6KRyPHpfKr1EJrzv+Z6qoDyV6NQBx/TuuGkbMJ5n7FUh?= =?us-ascii?Q?HpAnpetE15TNKYng5lcbzlFNyo8nzUELneYRSqjk3cjlMlq6550UZhK6hnPX?= =?us-ascii?Q?kxw3iBQnMYJ7fPYxYDE/vrF7XOr/wWGFSvEQxDAIiZNPCAJxVRAFiG5ZhOhC?= =?us-ascii?Q?wPmNa+Pn/1OIzF3pCxbFxe8qpQ/ZmmUSoAJ+kqLMrzxHTaSJEb/Zjo6dvIEC?= =?us-ascii?Q?3cOOrXrNbz/4jSJLfcb0OKTDHMGnMSrGww/31DH2X3ZVXmN39zElZnnYe8KP?= =?us-ascii?Q?ll1hKfU7LTZ/4p/LKLWo3ubkmHCCTnY1TN7uTOGdGGLDWbcRRbT65nZFMrSv?= =?us-ascii?Q?1idP+7x/0+9meVYpvy+l7Wjg2UZpYuDPC6S0cw3fAwmw+KUj/y7nUSYVHoWQ?= =?us-ascii?Q?UlvCsizFJpV/7KFNoD6b1SER+ZvQ7TdN7/VSyWW+1DyS7dYChief6JGg/XMa?= =?us-ascii?Q?X+EkbwadhFCdsMGYG+mANFmguOZBz1UA/Dru2Fu4ncyrPLKOnq+wWlSb6UX/?= =?us-ascii?Q?VqiGIKec1MW8wWn9ZrAbIIz8eMV59UVf4f1LWuvK0Fvixe6mNooX/ReemalG?= =?us-ascii?Q?cdDXF7fwmOv0mneLM6m5EQS0wnX/ygct9aUVRhAfrkk0w+6MMsBJ7skhYqly?= =?us-ascii?Q?NG4O4M6gbz7IjTT/nJxmB8yXMSUTPit82o9YA/rgeuNdMHIoZSPKCjfAcC5l?= =?us-ascii?Q?MroBY0c1hR1DbCnd9hMzrkvwgrJ7iooXBWP0wan2eYK+KymPJGna5GwD89WJ?= =?us-ascii?Q?ReItTEoq/hkmChKvLSZX04XaXT09p8RhV4rOMNow784xeaN/xEybJQNy+J5j?= =?us-ascii?Q?nfu/h9v7uD+1RWS5F1RtqLvHUXtpdx4sPNC+SQ+V2pG9uFQlHcpGqEqDQTMt?= =?us-ascii?Q?Trj127CMfhyjq7DWErtif86s/MUhySV3bIMn1nd6cdiR6nPFttCsOTOsVw09?= =?us-ascii?Q?/9iaVpm/VEQFsSpx9dEFTHLetBV7liCS+IvyJXeHWBHx6EgJkpFbQB6Q0dPU?= =?us-ascii?Q?CqFp4gZAP+v/5Cc98gRFL74EqcgUZkKtBxD897eWh20U8CbEeccaqjHs5f2Q?= =?us-ascii?Q?nVYortj8S0UYES0+Yi0R0xrXgYYHABk6iZSu5CFNXIQ2QkFHArb2MHyfYW1k?= =?us-ascii?Q?bJpQWD3WrlPNy+qfIJ0Vq2OV5ZOGhLL05+pb8FnWO2DjuPJ/ebuYyqt64T8j?= =?us-ascii?Q?s3UYvW69QXIYpnsG3j2s6clXR8I1IUuCHdOCzQEG?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 82e06da8-24e2-41ab-01bf-08dc91c74665 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:44.8570 (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: x1X8P2BO3H0IhteIHzB+M2JZxYHPIQJS5N3pEtWmw3BfjIkcIvm07VM89jH7NqOm4aV3E9wHsYT4hQsdZLcgHg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/ioctl.h | 445 +++++++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/ioctl.h diff --git a/drivers/net/wireless/nxp/nxpwifi/ioctl.h b/drivers/net/wireles= s/nxp/nxpwifi/ioctl.h new file mode 100644 index 000000000000..b55dfb872b76 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/ioctl.h @@ -0,0 +1,445 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: ioctl data structures & APIs + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_IOCTL_H_ +#define _NXPWIFI_IOCTL_H_ + +#include + +enum { + NXPWIFI_SCAN_TYPE_UNCHANGED =3D 0, + NXPWIFI_SCAN_TYPE_ACTIVE, + NXPWIFI_SCAN_TYPE_PASSIVE +}; + +#define NXPWIFI_PROMISC_MODE 1 +#define NXPWIFI_MULTICAST_MODE 2 +#define NXPWIFI_ALL_MULTI_MODE 4 +#define NXPWIFI_MAX_MULTICAST_LIST_SIZE 32 + +struct nxpwifi_multicast_list { + u32 mode; + u32 num_multicast_addr; + u8 mac_list[NXPWIFI_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; +}; + +struct nxpwifi_chan_freq { + u32 channel; + u32 freq; +}; + +struct nxpwifi_ssid_bssid { + struct cfg80211_ssid ssid; + u8 bssid[ETH_ALEN]; +}; + +enum { + BAND_B =3D 1, + BAND_G =3D 2, + BAND_A =3D 4, + BAND_GN =3D 8, + BAND_AN =3D 16, + BAND_AAC =3D 32, +}; + +#define NXPWIFI_WPA_PASSHPHRASE_LEN 64 +struct wpa_param { + u8 pairwise_cipher_wpa; + u8 pairwise_cipher_wpa2; + u8 group_cipher; + u32 length; + u8 passphrase[NXPWIFI_WPA_PASSHPHRASE_LEN]; +}; + +struct wep_key { + u8 key_index; + u8 is_default; + u16 length; + u8 key[WLAN_KEY_LEN_WEP104]; +}; + +#define KEY_MGMT_ON_HOST 0x03 +#define NXPWIFI_AUTH_MODE_AUTO 0xFF +#define BAND_CONFIG_BG 0x00 +#define BAND_CONFIG_A 0x01 +#define NXPWIFI_SEC_CHAN_BELOW 0x30 +#define NXPWIFI_SEC_CHAN_ABOVE 0x10 +#define NXPWIFI_SUPPORTED_RATES 14 +#define NXPWIFI_SUPPORTED_RATES_EXT 32 +#define NXPWIFI_PRIO_BK 2 +#define NXPWIFI_PRIO_VI 5 +#define NXPWIFI_SUPPORTED_CHANNELS 2 +#define NXPWIFI_OPERATING_CLASSES 16 + +struct nxpwifi_uap_bss_param { + u8 mac_addr[ETH_ALEN]; + u8 channel; + u8 band_cfg; + u16 rts_threshold; + u16 frag_threshold; + u8 retry_limit; + struct nxpwifi_802_11_ssid ssid; + u8 bcast_ssid_ctl; + u8 radio_ctl; + u8 dtim_period; + u16 beacon_period; + u16 auth_mode; + u16 protocol; + u16 key_mgmt; + u16 key_mgmt_operation; + struct wpa_param wpa_cfg; + struct wep_key wep_cfg[NUM_WEP_KEYS]; + struct ieee80211_ht_cap ht_cap; + struct ieee80211_vht_cap vht_cap; + u8 rates[NXPWIFI_SUPPORTED_RATES]; + u32 sta_ao_timer; + u32 ps_sta_ao_timer; + u8 qos_info; + u8 power_constraint; + struct nxpwifi_types_wmm_info wmm_info; +}; + +struct nxpwifi_ds_get_stats { + u32 mcast_tx_frame; + u32 failed; + u32 retry; + u32 multi_retry; + u32 frame_dup; + u32 rts_success; + u32 rts_failure; + u32 ack_failure; + u32 rx_frag; + u32 mcast_rx_frame; + u32 fcs_error; + u32 tx_frame; + u32 wep_icv_error[4]; + u32 bcn_rcv_cnt; + u32 bcn_miss_cnt; +}; + +#define NXPWIFI_MAX_VER_STR_LEN 128 + +struct nxpwifi_ver_ext { + u32 version_str_sel; + char version_str[NXPWIFI_MAX_VER_STR_LEN]; +}; + +struct nxpwifi_bss_info { + u32 bss_mode; + struct cfg80211_ssid ssid; + u32 bss_chan; + u8 country_code[3]; + u32 media_connected; + u32 max_power_level; + u32 min_power_level; + signed int bcn_nf_last; + u32 wep_status; + u32 is_hs_configured; + u32 is_deep_sleep; + u8 bssid[ETH_ALEN]; +}; + +struct nxpwifi_sta_info { + u8 peer_mac[ETH_ALEN]; + struct station_parameters *params; +}; + +#define MAX_NUM_TID 8 + +#define MAX_RX_WINSIZE 64 + +struct nxpwifi_ds_rx_reorder_tbl { + u16 tid; + u8 ta[ETH_ALEN]; + u32 start_win; + u32 win_size; + u32 buffer[MAX_RX_WINSIZE]; +}; + +struct nxpwifi_ds_tx_ba_stream_tbl { + u16 tid; + u8 ra[ETH_ALEN]; + u8 amsdu; +}; + +#define DBG_CMD_NUM 5 +#define NXPWIFI_DBG_SDIO_MP_NUM 10 + +struct nxpwifi_debug_info { + unsigned int debug_mask; + u32 int_counter; + u32 packets_out[MAX_NUM_TID]; + u32 tx_buf_size; + u32 curr_tx_buf_size; + u32 tx_tbl_num; + struct nxpwifi_ds_tx_ba_stream_tbl + tx_tbl[NXPWIFI_MAX_TX_BASTREAM_SUPPORTED]; + u32 rx_tbl_num; + struct nxpwifi_ds_rx_reorder_tbl rx_tbl + [NXPWIFI_MAX_RX_BASTREAM_SUPPORTED]; + u16 ps_mode; + u32 ps_state; + u8 is_deep_sleep; + u8 pm_wakeup_card_req; + u32 pm_wakeup_fw_try; + u8 is_hs_configured; + u8 hs_activated; + u32 num_cmd_host_to_card_failure; + u32 num_cmd_sleep_cfm_host_to_card_failure; + u32 num_tx_host_to_card_failure; + u32 num_event_deauth; + u32 num_event_disassoc; + u32 num_event_link_lost; + u32 num_cmd_deauth; + u32 num_cmd_assoc_success; + u32 num_cmd_assoc_failure; + u32 num_tx_timeout; + u8 is_cmd_timedout; + u16 timeout_cmd_id; + u16 timeout_cmd_act; + u16 last_cmd_id[DBG_CMD_NUM]; + u16 last_cmd_act[DBG_CMD_NUM]; + u16 last_cmd_index; + u16 last_cmd_resp_id[DBG_CMD_NUM]; + u16 last_cmd_resp_index; + u16 last_event[DBG_CMD_NUM]; + u16 last_event_index; + u8 data_sent; + u8 cmd_sent; + u8 cmd_resp_received; + u8 event_received; + u32 last_mp_wr_bitmap[NXPWIFI_DBG_SDIO_MP_NUM]; + u32 last_mp_wr_ports[NXPWIFI_DBG_SDIO_MP_NUM]; + u32 last_mp_wr_len[NXPWIFI_DBG_SDIO_MP_NUM]; + u32 last_mp_curr_wr_port[NXPWIFI_DBG_SDIO_MP_NUM]; + u8 last_sdio_mp_index; +}; + +#define NXPWIFI_KEY_INDEX_UNICAST 0x40000000 +#define PN_LEN 16 + +struct nxpwifi_ds_encrypt_key { + u32 key_disable; + u32 key_index; + u32 key_len; + u8 key_material[WLAN_MAX_KEY_LEN]; + u8 mac_addr[ETH_ALEN]; + u8 pn[PN_LEN]; /* packet number */ + u8 pn_len; + u8 is_igtk_key; + u8 is_current_wep_key; + u8 is_rx_seq_valid; + u8 is_igtk_def_key; +}; + +struct nxpwifi_power_cfg { + u32 is_power_auto; + u32 is_power_fixed; + u32 power_level; +}; + +struct nxpwifi_ds_hs_cfg { + u32 is_invoke_hostcmd; + /* Bit0: non-unicast data + * Bit1: unicast data + * Bit2: mac events + * Bit3: magic packet + */ + u32 conditions; + u32 gpio; + u32 gap; +}; + +struct nxpwifi_ds_wakeup_reason { + u16 hs_wakeup_reason; +}; + +#define DEEP_SLEEP_ON 1 +#define DEEP_SLEEP_OFF 0 +#define DEEP_SLEEP_IDLE_TIME 100 +#define PS_MODE_AUTO 1 + +struct nxpwifi_ds_auto_ds { + u16 auto_ds; + u16 idle_time; +}; + +struct nxpwifi_ds_pm_cfg { + union { + u32 ps_mode; + struct nxpwifi_ds_hs_cfg hs_cfg; + struct nxpwifi_ds_auto_ds auto_deep_sleep; + u32 sleep_period; + } param; +}; + +struct nxpwifi_11ac_vht_cfg { + u8 band_config; + u8 misc_config; + u32 cap_info; + u32 mcs_tx_set; + u32 mcs_rx_set; +}; + +struct nxpwifi_ds_11n_tx_cfg { + u16 tx_htcap; + u16 tx_htinfo; + u16 misc_config; /* Needed for 802.11AC cards only */ +}; + +struct nxpwifi_ds_11n_amsdu_aggr_ctrl { + u16 enable; + u16 curr_buf_size; +}; + +struct nxpwifi_ds_ant_cfg { + u32 tx_ant; + u32 rx_ant; +}; + +#define NXPWIFI_NUM_OF_CMD_BUFFER 50 +#define NXPWIFI_SIZE_OF_CMD_BUFFER 2048 + +enum { + NXPWIFI_IE_TYPE_GEN_IE =3D 0, + NXPWIFI_IE_TYPE_ARP_FILTER, +}; + +enum { + NXPWIFI_REG_MAC =3D 1, + NXPWIFI_REG_BBP, + NXPWIFI_REG_RF, + NXPWIFI_REG_PMIC, + NXPWIFI_REG_CAU, +}; + +struct nxpwifi_ds_reg_rw { + u32 type; + u32 offset; + u32 value; +}; + +#define MAX_EEPROM_DATA 256 + +struct nxpwifi_ds_read_eeprom { + u16 offset; + u16 byte_count; + u8 value[MAX_EEPROM_DATA]; +}; + +struct nxpwifi_ds_mem_rw { + u32 addr; + u32 value; +}; + +#define IEEE_MAX_IE_SIZE 256 + +#define NXPWIFI_IE_HDR_SIZE (sizeof(struct nxpwifi_ie) - IEEE_MAX_IE_SIZE) + +struct nxpwifi_ds_misc_gen_ie { + u32 type; + u32 len; + u8 ie_data[IEEE_MAX_IE_SIZE]; +}; + +struct nxpwifi_ds_misc_cmd { + u32 len; + u8 cmd[NXPWIFI_SIZE_OF_CMD_BUFFER]; +}; + +#define BITMASK_BCN_RSSI_LOW BIT(0) +#define BITMASK_BCN_RSSI_HIGH BIT(4) + +enum subsc_evt_rssi_state { + EVENT_HANDLED, + RSSI_LOW_RECVD, + RSSI_HIGH_RECVD +}; + +struct subsc_evt_cfg { + u8 abs_value; + u8 evt_freq; +}; + +struct nxpwifi_ds_misc_subsc_evt { + u16 action; + u16 events; + struct subsc_evt_cfg bcn_l_rssi_cfg; + struct subsc_evt_cfg bcn_h_rssi_cfg; +}; + +#define NXPWIFI_MEF_MAX_BYTESEQ 6 /* non-adjustable */ +#define NXPWIFI_MEF_MAX_FILTERS 10 + +struct nxpwifi_mef_filter { + u16 repeat; + u16 offset; + s8 byte_seq[NXPWIFI_MEF_MAX_BYTESEQ + 1]; + u8 filt_type; + u8 filt_action; +}; + +struct nxpwifi_mef_entry { + u8 mode; + u8 action; + struct nxpwifi_mef_filter filter[NXPWIFI_MEF_MAX_FILTERS]; +}; + +struct nxpwifi_ds_mef_cfg { + u32 criteria; + u16 num_entries; + struct nxpwifi_mef_entry *mef_entry; +}; + +#define NXPWIFI_MAX_VSIE_LEN (256) +#define NXPWIFI_MAX_VSIE_NUM (8) +#define NXPWIFI_VSIE_MASK_CLEAR 0x00 +#define NXPWIFI_VSIE_MASK_SCAN 0x01 +#define NXPWIFI_VSIE_MASK_ASSOC 0x02 +#define NXPWIFI_VSIE_MASK_BGSCAN 0x08 + +enum { + NXPWIFI_FUNC_INIT =3D 1, + NXPWIFI_FUNC_SHUTDOWN, +}; + +enum COALESCE_OPERATION { + RECV_FILTER_MATCH_TYPE_EQ =3D 0x80, + RECV_FILTER_MATCH_TYPE_NE, +}; + +enum COALESCE_PACKET_TYPE { + PACKET_TYPE_UNICAST =3D 1, + PACKET_TYPE_MULTICAST =3D 2, + PACKET_TYPE_BROADCAST =3D 3 +}; + +#define NXPWIFI_COALESCE_MAX_RULES 8 +#define NXPWIFI_COALESCE_MAX_BYTESEQ 4 /* non-adjustable */ +#define NXPWIFI_COALESCE_MAX_FILTERS 4 +#define NXPWIFI_MAX_COALESCING_DELAY 100 /* in msecs */ + +struct filt_field_param { + u8 operation; + u8 operand_len; + u16 offset; + u8 operand_byte_stream[NXPWIFI_COALESCE_MAX_BYTESEQ]; +}; + +struct nxpwifi_coalesce_rule { + u16 max_coalescing_delay; + u8 num_of_fields; + u8 pkt_type; + struct filt_field_param params[NXPWIFI_COALESCE_MAX_FILTERS]; +}; + +struct nxpwifi_ds_coalesce_cfg { + u16 num_of_rules; + struct nxpwifi_coalesce_rule rule[NXPWIFI_COALESCE_MAX_RULES]; +}; + +#endif /* !_NXPWIFI_IOCTL_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32AE417276D; Fri, 21 Jun 2024 07:53:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956435; cv=fail; b=YRh7TTP797RSGy+ytqTDtDuez4WSFQyfZxXDVCJ3fK15wezL2ctQ5yOY8q/1kJItQHeE6ZOz5TqKk/aNIIJdgDhirGO8poe0fJ5s7C367e3D9HNkNGY9mo6N/M5Ga8oCnJqYFUs2EoDSDQJnVvUdSaOOp0sHTBNBtO5x22op560= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956435; c=relaxed/simple; bh=X+9VxM65+O9aRIiGka3xGpgSCoUHsm6ZFi6q5V1+CxU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=NJCBe7PclQYSH4u3fVZsvFMeIaBh4CtACs6a5mwev32mQziknstry3wnSfoTkp7IEsD+kNp70ZVJhRPuzvhkMNSnqZye/z+thiSFfAt+c+mZC9eGktu1ZMN+Z4SlFDNx0O8u61ToSNwWGcsbJJpMdcSM+0cg5jh0C6QWHulSvEQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=GU8wrCfh; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="GU8wrCfh" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZuceImCKFy0K1eIZaJjzgdQ+h9gYzJ9Z1G+jienYf3OUI78O78sf0NjIlIbe4xSCcp5+gyFLe5g7tTAIhXgdM5+W/B6//UAdUBkECnimw9L3DyfgGXQiXJW50r+q7NVZJGNtk3Z0EqwweLqcTFd2nW2fXcNux2bnkk3gqXbW8Ndojm9pC/Dt+k7FB/tjw6WxEZMf+lVhY0ZMQgpPj0fpZtOhZyV+t8t2g/z7PzlSPF1ZxoYZLNrvRbuUNNoXl5fcTVPO/xoAYVUKfuFJPstl+oIUg6VX958Px3/KLsNrLyUqYJiVvgoR023f7/8iq0t/kcXMjnM2OoA+k3YHiPGAAA== 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=491aHzeYwgNPJtrgU9rlL8s0tBKa++vzVk9oOfO/2mc=; b=WX+MEH347sKG+RYrPBF1wAOwLkg5ZbpC/nONU6onnWcITAOJANGQnBqD20bE4btbO0mqxcVphnO1A4NYiXvQ4NTHwlrbM2K8nz4e0wKdFj/dMiVRxDHGEbNfiTh2/RS+nRLZl8cVIRGnOPb0ejkGyy3afQdUjk92yDiBrUjLehy/kR7W3D8ybZayOmWAJzGGcMW/3fkqqZ+A/BBrLccgKEUwgKFnML+DRQUbXjRN9ePtEkE9r+V/a8sCC8RCwvfkBMMNhy4xmJYJro6imSmMeRHk7h3c8Xvbjw3TaNrP0jnSF9LN+7b/I/A/zZTyHePgzzqcpKlzBEq63UFxpg8kaw== 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=491aHzeYwgNPJtrgU9rlL8s0tBKa++vzVk9oOfO/2mc=; b=GU8wrCfhZhwy26YpbpRw+wEHdAUE8a3ceZHvQAxOO1itam7Hd/gtO6B3OdSRSsy9MK4gdpVtbIZFBG1u2GM1OQFOO2aeoaaK1yB26nhbd2kEy3MNfeoFoClmU/WfwkNZE18pcL8G3KjlLQzOzK6NJqtOcpUvLGmsIUY2njEIxxA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:47 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:47 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 22/43] wifi: nxpwifi: add join.c Date: Fri, 21 Jun 2024 15:51:47 +0800 Message-Id: <20240621075208.513497-23-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 59dbe823-9fc3-4713-d87c-08dc91c7481e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?gZAdab7D/xsRr0Xogj4Hy6aUc3tapKXGOb20Kh8Y5zgB4Gy4Y0QW+hI/5FCQ?= =?us-ascii?Q?qinZ/uuueWcDvZnTz+R+/cARB5vbO024nZtdaiAorhZLXGOYCZJjuN9/0GBV?= =?us-ascii?Q?RH2gjbT1iMb0jjsEti4hnAoT1Aa83SP82zzwMcFVnmfPDjZHWEuon8vR4Oek?= =?us-ascii?Q?402SXsh/yi2YhAVV/XrjYfTbykGShkWt1wdAcv/NA41nMjfLXGP2lZ1wkT8p?= =?us-ascii?Q?eZJ9fQsDNZZljoAy9wX3sYrn+O0vpaFk651XtSAmERr+6e0JtdMRjntlSilC?= =?us-ascii?Q?PS1I2sCzrY5uRzzFioMY7ynTJJh6koB2ITodJwpMW7TNj28s/uf1VXxfQfMB?= =?us-ascii?Q?YSn+GiJpCQPNh/8AAEJ+ZYjyiU/tEmByhIlTs+3BZktvQFccSN01hfRn8FqS?= =?us-ascii?Q?WGz/4qVx3dIQTXTj/fmciCOy9Mh8OfuOk6BEid0jlD1X8Bkt3kJjZEknaCxh?= =?us-ascii?Q?8s45+DA+hxynm/t1cdZk0BwHN7asE0wqUk6lOdGjlQKprYkWwW2vmGzXaF+m?= =?us-ascii?Q?bCOSyssVQB+hLM0sMg7vA1SmRgEnUbKkJqrrKZ8S23117FADFyln9dMLp944?= =?us-ascii?Q?tXz3lk5zOLKtXKwak34NjrN8jdurS5v27f+o6IVEL0kOHujAgV2syTbSZFgl?= =?us-ascii?Q?a8t0nI25HBdJtH/5eVLxsEgMAlE3A3vKJt9TOoNY9+I7daJjcPgV+OXa4w9W?= =?us-ascii?Q?1osHz/e1ZuI0jRk1/N+7ozGQcEsWnOUhHwong+MdW49OYfESbnsZdpAsegjh?= =?us-ascii?Q?Iq+oFzwrRdh5iP73+fI8pgJOaVyx7XYW8max/U0Op5c6p75SJr3jbyvCox7F?= =?us-ascii?Q?jK0gKox3e4yEj5A/N7XQneRnAWrga6cm7yr9vOTIT8SM4aJ9niqEOnj21KiH?= =?us-ascii?Q?p1NhR2zxOltfebNynV6SROGp45LjvUEky4GapTkIvG01KdMmn3HcDWRrTaM4?= =?us-ascii?Q?8KeGvzYZe16HGT1BoigaLkX98bA0exVTsqVYg6E29BfsjQKdyqPDn7q+Hid/?= =?us-ascii?Q?GQhX64JeN9hf77fRdPy/vHhNSf3NQWiXoQosKPeNrsOg1P+laqV7KVJioDCn?= =?us-ascii?Q?c4xpC6jv7UZD6QhzivJ1GMa9L9R+laJsgtQw+I2GilwrCnrnpY86S8Sb1DwH?= =?us-ascii?Q?zSSMu10tJwSLuZdwsmZ/i5UDc18K1KXJA5JydhgyGGZO5S8Joe5vcV+/SVJB?= =?us-ascii?Q?BcmgbTwIGKGy79zeuL0m4+MrUIZNLMbN3mqKBpBrt0KICQlQDfIDSLTjpF4+?= =?us-ascii?Q?byyYEc0EggjvhvM4SE8+NjDixeaQUtS3k7/z3Kqy95TVZDTItqOX3CqSqvWz?= =?us-ascii?Q?aMARGQ+Pdqj+Ka2vb+btpKvGIGg9FFYisCAqVJyGTIiXK9kN9s8RpuxjYNCu?= =?us-ascii?Q?BmWJINQ=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?CcU8hykDo/4gp5+YP/ZmVHseQd0nJBVKr2oAYLXZIcfom5I+LmP11RaY9q3q?= =?us-ascii?Q?TRTInA5NoLSbkfgXX6KJErqGkMHCwbJoB2Cz76IlR8IBELFeZqM1nc+fRWvL?= =?us-ascii?Q?XfDXOCvCQNRmYF5rKMYbG2ERd2Wh398LWp3RHGWsZ/HLBsXzHrZhJiMvWH3w?= =?us-ascii?Q?JI96Gy6KstmxouEaQkNylHHDCy83n8TMSRVUPT+YVvD+iPiGjw9D+VmfbCzd?= =?us-ascii?Q?RTY0QuMT4HXq22Deiaj08KFsAu0EIFF389hl23foYtTsVuLbJAZQXDhBshuN?= =?us-ascii?Q?ZYtz0YgDhPwK+FLyv8FexRsBaKK1LILqiHPc/7tVDgi25jp7H8Vfroey2tDl?= =?us-ascii?Q?+5+CQTBoW9FXFixm6FjiffzhggeMDFkVproNW1r6G9cWbhKPtosRBtIv1T37?= =?us-ascii?Q?lIa5hJQ+2C7YtEIwuxOnHoHVoRj4+yjkXiHik5WAandTUnJD/myMNfkerO91?= =?us-ascii?Q?apn+Uq4YPTJu6UGE5qaJTkOjXtlZ3dMIpfG69r489cQDh5MsNBmX3yJOKNdg?= =?us-ascii?Q?WIWsE2IaW89LUle3IGfPhOlT3s+CfSDQ54OBtdldfdkloc9ag2wb2fH1314x?= =?us-ascii?Q?zt7gZJxLqsDAKuULDDAmrKhU+2K6vQgvT2rY2XvuBoQPmZqSLGniO/doCkRz?= =?us-ascii?Q?j27e9AMuuDDmrYGl9NOcYPkTrF0R3sU1Y8gV7Xob6SeKlTXDa1Xi1qq0kbsW?= =?us-ascii?Q?2JPCD3ZDBlmchRbdnZTpPE6RXub0UyhzszwUqH4305KcqaAaEK2eRvX/ZFtp?= =?us-ascii?Q?hOX9PtHvH3jEqogulzAPxbF9RmVr03MhbpqL/xYXYpNzMbK37eaEDT47SXmC?= =?us-ascii?Q?K2jkixSGn9so8eA64dJ49PEcjtWrINeoV6ADXT+zYECdVFjTkbymw8eXtTr3?= =?us-ascii?Q?8Ssv85OsszxIZkKnRfjVa4jPxv9dKChzI7X+CgdyV3eETJC4qzYilikDOYmM?= =?us-ascii?Q?ArKTuMZEyIVOP5QBVNlN2KP951KpvWmAZczjRlLY9axRBa1DfbbciIdHOEcF?= =?us-ascii?Q?jYwOoTPsOMDMv7UfR4uJSKgAOFFYgONHv96ZU4GPGgSP0Jku1pBL8RSazi0I?= =?us-ascii?Q?xu19/cyAyxntOjoOtRkQzpq6RN60PcIhDnfAzB1E+qX3J1qwQq0/zKqEomWm?= =?us-ascii?Q?yd14X94mxpewSVa6vf7vgJ5dbdoa/xy/Vilgg9SSfSi0jBds/EECwMbgCfGU?= =?us-ascii?Q?dZ6Q/PHeLa42xOb7QPLjWtSWSqEbGJQfwoX9eHfRa1q839RKFygKgGtjXO/J?= =?us-ascii?Q?Jm2YDcqhcSKoUKXx5Ze7iHuP8O1H/u1GfJBmVcjicG0qQIb22pKqsbK7vnv7?= =?us-ascii?Q?BvaY/W9/PD+PDBRVA2DC3O5K6h51N3m/1j8H5A+PyOU2wcjZEeLo+M6uzw39?= =?us-ascii?Q?Bw3f2wSD9WT3FSZee3g6krCQ5A6s2S5/1HytZipaytv5UGv4phQ3H94XCYE7?= =?us-ascii?Q?HxvACEQIFn2gdTjQOYHFXbV3ZiWTnwgeMogZioBh5xBJqZ1r0IlSD6ZI6fLP?= =?us-ascii?Q?Ed41Xw9+tW5WObhl4DLzpfd0lLsCH05J9YYq0XZBpgY4xh+pUe6fL0b76tPh?= =?us-ascii?Q?9t3Uyxe3TLqPQwts2Hg0ZtDK9+WN36xzvCmZEk3d?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 59dbe823-9fc3-4713-d87c-08dc91c7481e X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:47.7681 (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: yfOAYJ3DY3OcnaqcJ3Oz9fqlV+YCofTDs9HWevP7kgenIr8vsUOXPQnwiQ/XidH1mRPYUgGcXBBu3TIJIGsGCg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/join.c | 910 ++++++++++++++++++++++++ 1 file changed, 910 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/join.c diff --git a/drivers/net/wireless/nxp/nxpwifi/join.c b/drivers/net/wireless= /nxp/nxpwifi/join.c new file mode 100644 index 000000000000..a492821dd87a --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/join.c @@ -0,0 +1,910 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: association and ad-hoc start/join + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" +#include "11ac.h" + +#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) + +/* Append a generic IE as a pass through TLV to a TLV buffer. + * + * This function is called from the network join command preparation routi= ne. + * + * If the IE buffer has been setup by the application, this routine appends + * the buffer as a pass through TLV type to the request. + */ +static int +nxpwifi_cmd_append_generic_ie(struct nxpwifi_private *priv, u8 **buffer) +{ + int ret_len =3D 0; + struct nxpwifi_ie_types_header ie_header; + + /* Null Checks */ + if (!buffer) + return 0; + if (!(*buffer)) + return 0; + + /* If there is a generic ie buffer setup, append it to the return + * parameter buffer pointer. + */ + if (priv->gen_ie_buf_len) { + nxpwifi_dbg(priv->adapter, INFO, + "info: %s: append generic ie len %d to %p\n", + __func__, priv->gen_ie_buf_len, *buffer); + + /* Wrap the generic IE buffer with a pass through TLV type */ + ie_header.type =3D cpu_to_le16(TLV_TYPE_PASSTHROUGH); + ie_header.len =3D cpu_to_le16(priv->gen_ie_buf_len); + memcpy(*buffer, &ie_header, sizeof(ie_header)); + + /* Increment the return size and the return buffer pointer + * param + */ + *buffer +=3D sizeof(ie_header); + ret_len +=3D sizeof(ie_header); + + /* Copy the generic IE buffer to the output buffer, advance + * pointer + */ + memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); + + /* Increment the return size and the return buffer pointer + * param + */ + *buffer +=3D priv->gen_ie_buf_len; + ret_len +=3D priv->gen_ie_buf_len; + + /* Reset the generic IE buffer */ + priv->gen_ie_buf_len =3D 0; + } + + /* return the length appended to the buffer */ + return ret_len; +} + +/* Append TSF tracking info from the scan table for the target AP. + * + * This function is called from the network join command preparation routi= ne. + * + * The TSF table TSF sent to the firmware contains two TSF values: + * - The TSF of the target AP from its previous beacon/probe response + * - The TSF timestamp of our local MAC at the time we observed the + * beacon/probe response. + * + * The firmware uses the timestamp values to set an initial TSF value + * in the MAC for the new association after a reassociation attempt. + */ +static int +nxpwifi_cmd_append_tsf_tlv(struct nxpwifi_private *priv, u8 **buffer, + struct nxpwifi_bssdescriptor *bss_desc) +{ + struct nxpwifi_ie_types_tsf_timestamp tsf_tlv; + __le64 tsf_val; + + /* Null Checks */ + if (!buffer) + return 0; + if (!*buffer) + return 0; + + memset(&tsf_tlv, 0x00, sizeof(struct nxpwifi_ie_types_tsf_timestamp)); + + tsf_tlv.header.type =3D cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); + tsf_tlv.header.len =3D cpu_to_le16(2 * sizeof(tsf_val)); + + memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); + *buffer +=3D sizeof(tsf_tlv.header); + + /* TSF at the time when beacon/probe_response was received */ + tsf_val =3D cpu_to_le64(bss_desc->fw_tsf); + memcpy(*buffer, &tsf_val, sizeof(tsf_val)); + *buffer +=3D sizeof(tsf_val); + + tsf_val =3D cpu_to_le64(bss_desc->timestamp); + + nxpwifi_dbg(priv->adapter, INFO, + "info: %s: TSF offset calc: %016llx - %016llx\n", + __func__, bss_desc->timestamp, bss_desc->fw_tsf); + + memcpy(*buffer, &tsf_val, sizeof(tsf_val)); + *buffer +=3D sizeof(tsf_val); + + return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); +} + +/* This function finds out the common rates between rate1 and rate2. + * + * It will fill common rates in rate1 as output if found. + * + * NOTE: Setting the MSB of the basic rates needs to be taken + * care of, either before or after calling this function. + */ +static int nxpwifi_get_common_rates(struct nxpwifi_private *priv, u8 *rate= 1, + u32 rate1_size, u8 *rate2, u32 rate2_size) +{ + int ret; + u8 *ptr =3D rate1, *tmp; + u32 i, j; + + tmp =3D kmemdup(rate1, rate1_size, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + memset(rate1, 0, rate1_size); + + for (i =3D 0; i < rate2_size && rate2[i]; i++) { + for (j =3D 0; j < rate1_size && tmp[j]; j++) { + /* Check common rate, excluding the bit for + * basic rate + */ + if ((rate2[i] & 0x7F) =3D=3D (tmp[j] & 0x7F)) { + *rate1++ =3D tmp[j]; + break; + } + } + } + + nxpwifi_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n", + priv->data_rate); + + if (!priv->is_data_rate_auto) { + while (*ptr) { + if ((*ptr & 0x7f) =3D=3D priv->data_rate) { + ret =3D 0; + goto done; + } + ptr++; + } + nxpwifi_dbg(priv->adapter, ERROR, + "previously set fixed data rate %#x\t" + "is not compatible with the network\n", + priv->data_rate); + + ret =3D -1; + goto done; + } + + ret =3D 0; +done: + kfree(tmp); + return ret; +} + +/* This function creates the intersection of the rates supported by a + * target BSS and our adapter settings for use in an assoc/join command. + */ +static int +nxpwifi_setup_rates_from_bssdesc(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc, + u8 *out_rates, u32 *out_rates_size) +{ + u8 card_rates[NXPWIFI_SUPPORTED_RATES]; + u32 card_rates_size; + + /* Copy AP supported rates */ + memcpy(out_rates, bss_desc->supported_rates, NXPWIFI_SUPPORTED_RATES); + /* Get the STA supported rates */ + card_rates_size =3D nxpwifi_get_active_data_rates(priv, card_rates); + /* Get the common rates between AP and STA supported rates */ + if (nxpwifi_get_common_rates(priv, out_rates, NXPWIFI_SUPPORTED_RATES, + card_rates, card_rates_size)) { + *out_rates_size =3D 0; + nxpwifi_dbg(priv->adapter, ERROR, + "%s: cannot get common rates\n", + __func__); + return -1; + } + + *out_rates_size =3D + min_t(size_t, strlen(out_rates), NXPWIFI_SUPPORTED_RATES); + + return 0; +} + +/* This function appends a WPS IE. It is called from the network join comm= and + * preparation routine. + * + * If the IE buffer has been setup by the application, this routine appends + * the buffer as a WPS TLV type to the request. + */ +static int +nxpwifi_cmd_append_wps_ie(struct nxpwifi_private *priv, u8 **buffer) +{ + int ret_len =3D 0; + struct nxpwifi_ie_types_header ie_header; + + if (!buffer || !*buffer) + return 0; + + /* If there is a wps ie buffer setup, append it to the return + * parameter buffer pointer. + */ + if (priv->wps_ie_len) { + nxpwifi_dbg(priv->adapter, CMD, + "cmd: append wps ie %d to %p\n", + priv->wps_ie_len, *buffer); + + /* Wrap the generic IE buffer with a pass through TLV type */ + ie_header.type =3D cpu_to_le16(TLV_TYPE_PASSTHROUGH); + ie_header.len =3D cpu_to_le16(priv->wps_ie_len); + memcpy(*buffer, &ie_header, sizeof(ie_header)); + *buffer +=3D sizeof(ie_header); + ret_len +=3D sizeof(ie_header); + + memcpy(*buffer, priv->wps_ie, priv->wps_ie_len); + *buffer +=3D priv->wps_ie_len; + ret_len +=3D priv->wps_ie_len; + } + + kfree(priv->wps_ie); + priv->wps_ie_len =3D 0; + return ret_len; +} + +/* This function appends rsn ie tlv for wpa/wpa2 security modes. + * It is called from the network join command preparation routine. + */ +static int nxpwifi_append_rsn_ie_wpa_wpa2(struct nxpwifi_private *priv, + u8 **buffer) +{ + struct nxpwifi_ie_types_rsn_param_set *rsn_ie_tlv; + int rsn_ie_len; + + if (!buffer || !(*buffer)) + return 0; + + rsn_ie_tlv =3D (struct nxpwifi_ie_types_rsn_param_set *)(*buffer); + rsn_ie_tlv->header.type =3D cpu_to_le16((u16)priv->wpa_ie[0]); + rsn_ie_tlv->header.type =3D + cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); + rsn_ie_tlv->header.len =3D cpu_to_le16((u16)priv->wpa_ie[1]); + rsn_ie_tlv->header.len =3D cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) + & 0x00FF); + if (le16_to_cpu(rsn_ie_tlv->header.len) <=3D (sizeof(priv->wpa_ie) - 2)) + memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], + le16_to_cpu(rsn_ie_tlv->header.len)); + else + return -1; + + rsn_ie_len =3D sizeof(rsn_ie_tlv->header) + + le16_to_cpu(rsn_ie_tlv->header.len); + *buffer +=3D rsn_ie_len; + + return rsn_ie_len; +} + +/* This function prepares command for association. + * + * This sets the following parameters - + * - Peer MAC address + * - Listen interval + * - Beacon interval + * - Capability information + * + * ...and the following TLVs, as required - + * - SSID TLV + * - PHY TLV + * - SS TLV + * - Rates TLV + * - Authentication TLV + * - Channel TLV + * - WPA/WPA2 IE + * - 11n TLV + * - Vendor specific TLV + * - WMM TLV + * - Generic IE + * - TSF TLV + * + * Preparation also includes - + * - Setting command ID and proper size + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_802_11_associate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + struct nxpwifi_bssdescriptor *bss_desc) +{ + struct host_cmd_ds_802_11_associate *assoc =3D &cmd->params.associate; + struct nxpwifi_ie_types_host_mlme *host_mlme_tlv; + struct nxpwifi_ie_types_ssid_param_set *ssid_tlv; + struct nxpwifi_ie_types_phy_param_set *phy_tlv; + struct nxpwifi_ie_types_ss_param_set *ss_tlv; + struct nxpwifi_ie_types_rates_param_set *rates_tlv; + struct nxpwifi_ie_types_auth_type *auth_tlv; + struct nxpwifi_ie_types_sae_pwe_mode *sae_pwe_tlv; + struct nxpwifi_ie_types_chan_list_param_set *chan_tlv; + u8 rates[NXPWIFI_SUPPORTED_RATES]; + u32 rates_size; + u16 tmp_cap; + u8 *pos; + int rsn_ie_len =3D 0; + + pos =3D (u8 *)assoc; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_ASSOCIATE); + + /* Save so we know which BSS Desc to use in the response handler */ + priv->attempted_bss_desc =3D bss_desc; + + memcpy(assoc->peer_sta_addr, + bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); + pos +=3D sizeof(assoc->peer_sta_addr); + + /* Set the listen interval */ + assoc->listen_interval =3D cpu_to_le16(priv->listen_interval); + /* Set the beacon period */ + assoc->beacon_period =3D cpu_to_le16(bss_desc->beacon_period); + + pos +=3D sizeof(assoc->cap_info_bitmap); + pos +=3D sizeof(assoc->listen_interval); + pos +=3D sizeof(assoc->beacon_period); + pos +=3D sizeof(assoc->dtim_period); + + host_mlme_tlv =3D (struct nxpwifi_ie_types_host_mlme *)pos; + host_mlme_tlv->header.type =3D cpu_to_le16(TLV_TYPE_HOST_MLME); + host_mlme_tlv->header.len =3D cpu_to_le16(sizeof(host_mlme_tlv->host_mlme= )); + host_mlme_tlv->host_mlme =3D 1; + pos +=3D sizeof(host_mlme_tlv->header) + sizeof(host_mlme_tlv->host_mlme); + + ssid_tlv =3D (struct nxpwifi_ie_types_ssid_param_set *)pos; + ssid_tlv->header.type =3D cpu_to_le16(WLAN_EID_SSID); + ssid_tlv->header.len =3D cpu_to_le16((u16)bss_desc->ssid.ssid_len); + memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, + le16_to_cpu(ssid_tlv->header.len)); + pos +=3D sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); + + phy_tlv =3D (struct nxpwifi_ie_types_phy_param_set *)pos; + phy_tlv->header.type =3D cpu_to_le16(WLAN_EID_DS_PARAMS); + phy_tlv->header.len =3D cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); + memcpy(&phy_tlv->fh_ds.ds_param_set, + &bss_desc->phy_param_set.ds_param_set.current_chan, + sizeof(phy_tlv->fh_ds.ds_param_set)); + pos +=3D sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); + + ss_tlv =3D (struct nxpwifi_ie_types_ss_param_set *)pos; + ss_tlv->header.type =3D cpu_to_le16(WLAN_EID_CF_PARAMS); + ss_tlv->header.len =3D cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); + pos +=3D sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); + + /* Get the common rates supported between the driver and the BSS Desc */ + if (nxpwifi_setup_rates_from_bssdesc + (priv, bss_desc, rates, &rates_size)) + return -1; + + /* Save the data rates into Current BSS state structure */ + priv->curr_bss_params.num_of_rates =3D rates_size; + memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); + + /* Setup the Rates TLV in the association command */ + rates_tlv =3D (struct nxpwifi_ie_types_rates_param_set *)pos; + rates_tlv->header.type =3D cpu_to_le16(WLAN_EID_SUPP_RATES); + rates_tlv->header.len =3D cpu_to_le16((u16)rates_size); + memcpy(rates_tlv->rates, rates, rates_size); + pos +=3D sizeof(rates_tlv->header) + rates_size; + nxpwifi_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size =3D %d\n", + rates_size); + + /* Add the Authentication type */ + auth_tlv =3D (struct nxpwifi_ie_types_auth_type *)pos; + auth_tlv->header.type =3D cpu_to_le16(TLV_TYPE_AUTH_TYPE); + auth_tlv->header.len =3D cpu_to_le16(sizeof(auth_tlv->auth_type)); + if (priv->sec_info.wep_enabled) + auth_tlv->auth_type =3D + cpu_to_le16((u16)priv->sec_info.authentication_mode); + else + auth_tlv->auth_type =3D cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); + + pos +=3D sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); + + if (priv->sec_info.authentication_mode =3D=3D WLAN_AUTH_SAE) { + auth_tlv->auth_type =3D cpu_to_le16(NXPWIFI_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 =3D + (struct nxpwifi_ie_types_sae_pwe_mode *)pos; + sae_pwe_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_SAE_PWE_MODE); + sae_pwe_tlv->header.len =3D + cpu_to_le16(sizeof(sae_pwe_tlv->pwe[0])); + sae_pwe_tlv->pwe[0] =3D bss_desc->bcn_rsnx_ie->data[0]; + pos +=3D 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 && + (priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN) && + bss_desc->bcn_ht_cap)) { + /* Append a channel TLV for the channel the attempted AP was + * found on + */ + chan_tlv =3D (struct nxpwifi_ie_types_chan_list_param_set *)pos; + chan_tlv->header.type =3D cpu_to_le16(TLV_TYPE_CHANLIST); + chan_tlv->header.len =3D + cpu_to_le16(sizeof(struct nxpwifi_chan_scan_param_set)); + + memset(chan_tlv->chan_scan_param, 0x00, + sizeof(struct nxpwifi_chan_scan_param_set)); + chan_tlv->chan_scan_param[0].chan_number =3D + (bss_desc->phy_param_set.ds_param_set.current_chan); + nxpwifi_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan =3D %d\n", + chan_tlv->chan_scan_param[0].chan_number); + + chan_tlv->chan_scan_param[0].radio_type =3D + nxpwifi_band_to_radio_type((u8)bss_desc->bss_band); + + nxpwifi_dbg(priv->adapter, INFO, "info: Assoc: TLV Band =3D %d\n", + chan_tlv->chan_scan_param[0].radio_type); + pos +=3D sizeof(chan_tlv->header) + + sizeof(struct nxpwifi_chan_scan_param_set); + } + + if (!priv->wps.session_enable) { + if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) + rsn_ie_len =3D nxpwifi_append_rsn_ie_wpa_wpa2(priv, &pos); + + if (rsn_ie_len =3D=3D -1) + return -1; + } + + if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && + !bss_desc->disable_11n && + (priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN)) + nxpwifi_cmd_append_11n_tlv(priv, bss_desc, &pos); + + if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && + !bss_desc->disable_11n && !bss_desc->disable_11ac && + priv->adapter->config_bands & BAND_AAC) + nxpwifi_cmd_append_11ac_tlv(priv, bss_desc, &pos); + + /* Append vendor specific IE TLV */ + nxpwifi_cmd_append_vsie_tlv(priv, NXPWIFI_VSIE_MASK_ASSOC, &pos); + + nxpwifi_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, + bss_desc->bcn_ht_cap); + + if (priv->wps.session_enable && priv->wps_ie_len) + nxpwifi_cmd_append_wps_ie(priv, &pos); + + nxpwifi_cmd_append_generic_ie(priv, &pos); + + nxpwifi_cmd_append_tsf_tlv(priv, &pos, bss_desc); + + nxpwifi_11h_process_join(priv, &pos, bss_desc); + + cmd->size =3D cpu_to_le16((u16)(pos - (u8 *)assoc) + S_DS_GEN); + + /* Set the Capability info at last */ + tmp_cap =3D bss_desc->cap_info_bitmap; + + if (priv->adapter->config_bands =3D=3D BAND_B) + tmp_cap &=3D ~WLAN_CAPABILITY_SHORT_SLOT_TIME; + + tmp_cap &=3D CAPINFO_MASK; + nxpwifi_dbg(priv->adapter, INFO, + "info: ASSOC_CMD: tmp_cap=3D%4X CAPINFO_MASK=3D%4lX\n", + tmp_cap, CAPINFO_MASK); + assoc->cap_info_bitmap =3D cpu_to_le16(tmp_cap); + + return 0; +} + +static const char *assoc_failure_reason_to_str(u16 cap_info) +{ + switch (cap_info) { + case CONNECT_ERR_AUTH_ERR_STA_FAILURE: + return "CONNECT_ERR_AUTH_ERR_STA_FAILURE"; + case CONNECT_ERR_AUTH_MSG_UNHANDLED: + return "CONNECT_ERR_AUTH_MSG_UNHANDLED"; + case CONNECT_ERR_ASSOC_ERR_TIMEOUT: + return "CONNECT_ERR_ASSOC_ERR_TIMEOUT"; + case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED: + return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED"; + case CONNECT_ERR_STA_FAILURE: + return "CONNECT_ERR_STA_FAILURE"; + } + + return "Unknown connect failure"; +} + +/* Association firmware command response handler + * + * The response buffer for the association command has the following + * memory layout. + * + * For cases where an association response was not received (indicated + * by the CapInfo and AId field): + * + * .------------------------------------------------------------. + * | Header(4 * sizeof(t_u16)): Standard command response hdr | + * .------------------------------------------------------------. + * | cap_info/Error Return(t_u16): | + * | 0xFFFF(-1): Internal error | + * | 0xFFFE(-2): Authentication unhandled message | + * | 0xFFFD(-3): Authentication refused | + * | 0xFFFC(-4): Timeout waiting for AP response | + * .------------------------------------------------------------. + * | status_code(t_u16): | + * | If cap_info is -1: | + * | An internal firmware failure prevented the | + * | command from being processed. The status_code | + * | will be set to 1. | + * | | + * | If cap_info is -2: | + * | An authentication frame was received but was | + * | not handled by the firmware. IEEE Status | + * | code for the failure is returned. | + * | | + * | If cap_info is -3: | + * | An authentication frame was received and the | + * | status_code is the IEEE Status reported in the | + * | response. | + * | | + * | If cap_info is -4: | + * | (1) Association response timeout | + * | (2) Authentication response timeout | + * .------------------------------------------------------------. + * | a_id(t_u16): 0xFFFF | + * .------------------------------------------------------------. + * + * + * For cases where an association response was received, the IEEE + * standard association response frame is returned: + * + * .------------------------------------------------------------. + * | Header(4 * sizeof(t_u16)): Standard command response hdr | + * .------------------------------------------------------------. + * | cap_info(t_u16): IEEE Capability | + * .------------------------------------------------------------. + * | status_code(t_u16): IEEE Status Code | + * .------------------------------------------------------------. + * | a_id(t_u16): IEEE Association ID | + * .------------------------------------------------------------. + * | IEEE IEs(variable): Any received IEs comprising the | + * | remaining portion of a received | + * | association response frame. | + * .------------------------------------------------------------. + * + * For simplistic handling, the status_code field can be used to determine + * an association success (0) or failure (non-zero). + */ +int nxpwifi_ret_802_11_associate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret =3D 0; + struct ieee_types_assoc_rsp *assoc_rsp; + struct nxpwifi_bssdescriptor *bss_desc; + bool enable_data =3D true; + 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) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: failed, association terminated by host\n", + __func__); + goto done; + } + + hdr =3D (struct ieee80211_mgmt *)&resp->params; + if (!memcmp(hdr->bssid, priv->attempted_bss_desc->mac_address, + ETH_ALEN)) + assoc_rsp =3D (struct ieee_types_assoc_rsp *)&hdr->u.assoc_resp; + else + assoc_rsp =3D (struct ieee_types_assoc_rsp *)&resp->params; + + cap_info =3D le16_to_cpu(assoc_rsp->cap_info_bitmap); + status_code =3D le16_to_cpu(assoc_rsp->status_code); + aid =3D le16_to_cpu(assoc_rsp->a_id); + + if ((aid & (BIT(15) | BIT(14))) !=3D (BIT(15) | BIT(14))) + dev_err(priv->adapter->dev, + "invalid AID value 0x%x; bits 15:14 not set\n", + aid); + + aid &=3D ~(BIT(15) | BIT(14)); + + priv->assoc_rsp_size =3D min(le16_to_cpu(resp->size) - S_DS_GEN, + sizeof(priv->assoc_rsp_buf)); + + assoc_rsp->a_id =3D cpu_to_le16(aid); + memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); + + if (status_code) { + priv->adapter->dbg.num_cmd_assoc_failure++; + nxpwifi_dbg(priv->adapter, ERROR, + "ASSOC_RESP: failed,\t" + "status code=3D%d err=3D%#x a_id=3D%#x\n", + status_code, cap_info, + le16_to_cpu(assoc_rsp->a_id)); + + nxpwifi_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n", + assoc_failure_reason_to_str(cap_info)); + if (cap_info =3D=3D CONNECT_ERR_ASSOC_ERR_TIMEOUT) { + if (status_code =3D=3D NXPWIFI_ASSOC_CMD_FAILURE_AUTH) { + ret =3D WLAN_STATUS_AUTH_TIMEOUT; + nxpwifi_dbg(priv->adapter, ERROR, + "ASSOC_RESP: AUTH timeout\n"); + } else { + ret =3D WLAN_STATUS_UNSPECIFIED_FAILURE; + nxpwifi_dbg(priv->adapter, ERROR, + "ASSOC_RESP: UNSPECIFIED failure\n"); + } + + priv->assoc_rsp_size =3D 0; + } else { + ret =3D status_code; + } + + goto done; + } + + /* Send a Media Connected event, according to the Spec */ + priv->media_connected =3D true; + + priv->adapter->ps_state =3D PS_STATE_AWAKE; + priv->adapter->pps_uapsd_mode =3D false; + priv->adapter->tx_lock_flag =3D false; + + /* Set the attempted BSSID Index to current */ + bss_desc =3D priv->attempted_bss_desc; + + nxpwifi_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n", + bss_desc->ssid.ssid); + + /* Make a copy of current BSSID descriptor */ + memcpy(&priv->curr_bss_params.bss_descriptor, + bss_desc, sizeof(struct nxpwifi_bssdescriptor)); + + /* Update curr_bss_params */ + priv->curr_bss_params.bss_descriptor.channel =3D + bss_desc->phy_param_set.ds_param_set.current_chan; + + priv->curr_bss_params.band =3D (u8)bss_desc->bss_band; + + if (bss_desc->wmm_ie.vend_hdr.element_id =3D=3D WLAN_EID_VENDOR_SPECIFIC) + priv->curr_bss_params.wmm_enabled =3D true; + else + priv->curr_bss_params.wmm_enabled =3D false; + + if ((priv->wmm_required || bss_desc->bcn_ht_cap) && + priv->curr_bss_params.wmm_enabled) + priv->wmm_enabled =3D true; + else + priv->wmm_enabled =3D false; + + priv->curr_bss_params.wmm_uapsd_enabled =3D false; + + if (priv->wmm_enabled) + priv->curr_bss_params.wmm_uapsd_enabled =3D + ((bss_desc->wmm_ie.qos_info_bitmap & + IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); + + /* Store the bandwidth information from assoc response */ + ie_ptr =3D cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer, + priv->assoc_rsp_size + - sizeof(struct ieee_types_assoc_rsp)); + if (ie_ptr) { + assoc_resp_ht_oper =3D (struct ieee80211_ht_operation *)(ie_ptr + + sizeof(struct ieee_types_header)); + priv->assoc_resp_ht_param =3D assoc_resp_ht_oper->ht_param; + priv->ht_param_present =3D true; + } else { + priv->ht_param_present =3D false; + } + + nxpwifi_dbg(priv->adapter, INFO, + "info: ASSOC_RESP: curr_pkt_filter is %#x\n", + priv->curr_pkt_filter); + if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) + priv->wpa_is_gtk_set =3D false; + + if (priv->wmm_enabled) { + /* Don't re-enable carrier until we get the WMM_GET_STATUS + * event + */ + enable_data =3D false; + } else { + /* Since WMM is not enabled, setup the queues with the + * defaults + */ + nxpwifi_wmm_setup_queue_priorities(priv, NULL); + nxpwifi_wmm_setup_ac_downgrade(priv); + } + + if (enable_data) + nxpwifi_dbg(priv->adapter, INFO, + "info: post association, re-enabling data flow\n"); + + /* Reset SNR/NF/RSSI values */ + priv->data_rssi_last =3D 0; + priv->data_nf_last =3D 0; + priv->data_rssi_avg =3D 0; + priv->data_nf_avg =3D 0; + priv->bcn_rssi_last =3D 0; + priv->bcn_nf_last =3D 0; + priv->bcn_rssi_avg =3D 0; + priv->bcn_nf_avg =3D 0; + priv->rxpd_rate =3D 0; + priv->rxpd_htinfo =3D 0; + + nxpwifi_save_curr_bcn(priv); + + priv->adapter->dbg.num_cmd_assoc_success++; + + nxpwifi_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 + */ + nxpwifi_ralist_add(priv, + priv->curr_bss_params.bss_descriptor.mac_address); + + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + nxpwifi_wake_up_net_dev_queue(priv->netdev, adapter); + + if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) + priv->scan_block =3D true; + else + priv->port_open =3D true; + +done: + /* Need to indicate IOCTL complete */ + if (adapter->curr_cmd->wait_q_enabled) { + if (ret) + adapter->cmd_wait_q.status =3D -1; + else + adapter->cmd_wait_q.status =3D 0; + } + + return ret; +} + +/* This function associates to a specific BSS discovered in a scan. + * + * It clears any past association response stored for application + * retrieval and calls the command preparation routine to send the + * command to firmware. + */ +int nxpwifi_associate(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + /* Return error if the adapter is not STA role or table entry + * is not marked as infra. + */ + if ((GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_STA) || + bss_desc->bss_mode !=3D NL80211_IFTYPE_STATION) + return -1; + + if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && + !bss_desc->disable_11n && !bss_desc->disable_11ac && + priv->adapter->config_bands & BAND_AAC) + nxpwifi_set_11ac_ba_params(priv); + else + nxpwifi_set_ba_params(priv); + + /* Clear any past association response stored for application + * retrieval + */ + priv->assoc_rsp_size =3D 0; + + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_ASSOCIATE, + HOST_ACT_GEN_SET, 0, bss_desc, true); +} + +/* This function deauthenticates/disconnects from infra network by sending + * deauthentication request. + */ +static int nxpwifi_deauthenticate_infra(struct nxpwifi_private *priv, u8 *= mac) +{ + u8 mac_address[ETH_ALEN]; + int ret; + + if (!mac || is_zero_ether_addr(mac)) + memcpy(mac_address, + priv->curr_bss_params.bss_descriptor.mac_address, + ETH_ALEN); + else + memcpy(mac_address, mac, ETH_ALEN); + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_DEAUTHENTICATE, + HOST_ACT_GEN_SET, 0, mac_address, true); + + return ret; +} + +/* This function deauthenticates/disconnects from a BSS. + * + * In case of infra made, it sends deauthentication request, and + * in case of ad-hoc mode, a stop network request is sent to the firmware. + * In AP mode, a command to stop bss is sent to firmware. + */ +int nxpwifi_deauthenticate(struct nxpwifi_private *priv, u8 *mac) +{ + int ret =3D 0; + + if (!priv->media_connected) + return 0; + + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + priv->host_mlme_reg =3D false; + priv->mgmt_frame_mask =3D 0; + if (nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, + HOST_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false)) { + nxpwifi_dbg(priv->adapter, ERROR, + "could not unregister mgmt frame rx\n"); + return -1; + } + + switch (priv->bss_mode) { + case NL80211_IFTYPE_STATION: + ret =3D nxpwifi_deauthenticate_infra(priv, mac); + if (ret) + cfg80211_disconnected(priv->netdev, 0, NULL, 0, + true, GFP_KERNEL); + break; + case NL80211_IFTYPE_AP: + return nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_STOP, + HOST_ACT_GEN_SET, 0, NULL, true); + default: + break; + } + + return ret; +} + +/* This function deauthenticates/disconnects from all BSS. */ +void nxpwifi_deauthenticate_all(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + int i; + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv) + nxpwifi_deauthenticate(priv, NULL); + } +} +EXPORT_SYMBOL_GPL(nxpwifi_deauthenticate_all); + +/* This function converts band to radio type used in channel TLV. + */ +u8 +nxpwifi_band_to_radio_type(u8 band) +{ + switch (band) { + case BAND_A: + case BAND_AN: + case BAND_A | BAND_AN: + case BAND_A | BAND_AN | BAND_AAC: + return HOST_SCAN_RADIO_TYPE_A; + case BAND_B: + case BAND_G: + case BAND_B | BAND_G: + default: + return HOST_SCAN_RADIO_TYPE_BG; + } +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA92716DEC8; Fri, 21 Jun 2024 07:53:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956439; cv=fail; b=Z2EfmhMjNlB+pe7lWJQEe+/ltK8g1ziIGFXo8Xq6j1CZz8tXxuFmzJ2fIUB//9qr2ui6Z+RwEiuEJ9IVJM91HE4pwrcCF4Br7B7ByTivOd7kLs6iyO6LzyDRCBf5dKXFcxLVXhcRrrN/k2dJfEJQbHoyQazG+xc8Rkqok9oVIOE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956439; c=relaxed/simple; bh=BWZHUmJjxBDkgmuqSNRLRyDE/QBbdQsFQ91mlEyA1Nk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=uiqXxhOUhhTDM2Qra3IL18OsAToqc7Fwh2+W2WaT3XI8WFMegg6B/f81BykZvv+uOfUORYjfCoOfUVsAEPWXZjIeMHl9zfQotSSiEzWVrVIkEvJgeFEvZ0a1f8vqhhvvAjlP2NGbUZl3WqeT1lDd+gbX8FLKu7rWC66GDej/7uo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=TkDWB8Sf; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="TkDWB8Sf" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=MLHRR6s5fvoXNrpoIvZmP5s7dsSZLib5csicCZEFmuS4kwok7pt2OJjQTnPVWG/Tl563mmVKKhALvTCVSEqkKTkImUm9rAsvZgUlb/RBsgqoCx4c1dPRjyGu7jzrAY8oXmZSEzpFimj6ijk52qe2R/kxDFREB3sZGoj2zkqTaTo/L9fiwtTyMq1xwqG3pLAjvAul6nW3en+VloqH6Lzr5XxQoVzyVQqhip+OCBhIlF8JSIk4yR4RRh5SsUj4FyGEimVDCcqbUKj5MvqLUjbtrfn9QGw4XW0d7xWidJhxnovcTb2ovKQF/tkNmajK6R4XXo7+bfs/4W/TqmQPP1Kwbg== 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=Vw46EMk1sSeIc8xa6ACtpOqBf9G1hTWRhHgKDoQunwg=; b=IG5emUdFi1eLkXi0OXeenmS1Q7GCqYRQKY4tIVBUOIWUVBb8ppNUjJfQWbqRx7Vw53XOA+pvK/H0huLCxbVleMaDY6aG6KiV/VhusN3iqSB7juiUO4mpqNWkBNERNJ7CPzG+gXukmy+MH4Bz6qsEOTrOjn91v9CgnUgmKuDqTR3uN4cMqEEsRw5jUa3B6UQFzI8THy4keogrBzjeOAUJtafgHA9tTi8Z9ThU8DXCOLSJF91E5a5tqkv9AYGZzHZ2nAapHDc4GxSmZNBpRAt3hrKgX5lJOAVZ54yfDu8qOFVpFTRJPczP73i/xL8KQZ9IcMGYuFLC5/lsOK7di/feeA== 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=Vw46EMk1sSeIc8xa6ACtpOqBf9G1hTWRhHgKDoQunwg=; b=TkDWB8SfCKbmqecVyL6ANHtMi9IwFF19hB1K43+2kjd0VRctgPq/sIkJ1XGkjxFqrAs83+U0nYyRO79MhoI7lwsyHbGyQxdkU7IlogQfMObKM6KcTd4Y4tSOtEmMHhwM9sDW89y8dODC2vBrztxXasPsoa/2+tBQ1A0UI69PJWQ= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:51 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:51 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 23/43] wifi: nxpwifi: add main.c Date: Fri, 21 Jun 2024 15:51:48 +0800 Message-Id: <20240621075208.513497-24-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 32a563ac-22ea-434d-c52e-08dc91c749de X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?Z4mqo3xGSPSYW+LywEPiuQvS7tgprR2rvD8mN9GjliC1HFOwotQPCN3ntyuI?= =?us-ascii?Q?57D6oEhkSBWHC1lRQTBk5IPPEkvvplKRM8a+RTIl1NG+QXdcyVaiSaIAR7Q/?= =?us-ascii?Q?EEcFQXiqQlNABEx1JMciMaa/bV5iVGqjUCdwcmGMvQFMXXKf6l7C2l8kKFtc?= =?us-ascii?Q?L/aKeThmO8SLRDJ+qUK2nXA1RNBsBeVWdbXAZw5YGhvRYfpzp+HK6Tm4SNnc?= =?us-ascii?Q?zNb7IKfisIdQ29VemW0Kb00SilJmzShSBV+lWyNp3HUgt4c335yuaL//iIKz?= =?us-ascii?Q?1gLqLC8X/b72POzv/v8yuelYJi88scznncjwSeqFau+UH2uQPVYnm2zvSkox?= =?us-ascii?Q?72Nk45hXH0cZgP3AaKAmZqU/dY7FSh632f1O9mQXnIbFUuSHUzkDkSqQVIHc?= =?us-ascii?Q?SOrccEyZqAHQakqdOo0SwidSiCZmtbcmTQmV3viX92ilptJHjtKYxg++axNS?= =?us-ascii?Q?jWB10GfESkaAjrI123ILa8uCd67Uwt0YWPVmTSEqOmmxJ84xuCYpki7ITsxW?= =?us-ascii?Q?s96eeYOsvCCChuxljfzhuYbJC/pyPvF3YbOP0We3LjE15eZYg40WxkEelCaD?= =?us-ascii?Q?YwneL/sviEsa40th9L7SfkjPhJ0CDqXQlzJzA59WFKl9XAWXc7S++pMREOH7?= =?us-ascii?Q?Kj1ZyQFq1chf3RIJUOvXVwojoKt1XH7u830d3bG5+LPwUtKSJUfL9ucTITNi?= =?us-ascii?Q?9P1QnHG9hfgYGeR47K2G7lJthBTCN7QWH9+fpeQcRszz5li+w266BuvWrryf?= =?us-ascii?Q?vdRgqMBrU2DI+oLFCR8HP8vfzYk3r82mIo7BHmb6y9CJwBwS86MXYK2yhKMP?= =?us-ascii?Q?UAJ1SFBeq5LKwMEJsHQm89BFFA8gJ9YRGstJee0JQDnfcPWO0vSVJ+iAcCiJ?= =?us-ascii?Q?XgOYrFQrBTaStBySFYGD8xeHAek1r0Lod1GZKL8huRb01qxYNv76EkARan3e?= =?us-ascii?Q?iV1p9r0H2EztOA2jtOpJfDggZgrB/8TKWE665Tk/WKpm4bDA9Tq0acZsjR+u?= =?us-ascii?Q?/QMkkCZnnzEerWYnHOfEkxfaNq66QNbQCm0HeDa62kOU+yNqDlW0kfxXWYYF?= =?us-ascii?Q?mKXoSI+bY9FP1EE32N+MiCCpJk7DVkRzAsEJDlztdCFaBgmxZiWE2QGLWoVk?= =?us-ascii?Q?bLUFDq0jGpiSwiLDITAysy1nIzwGz1nj+2I3JS84mcNY3I4/TiODWh8IZjue?= =?us-ascii?Q?9Bmu9t0yxqSFUAe2+AYSsLEl6TPpNzViel4cUKjjTI++DTAEeb6FBPd+evA6?= =?us-ascii?Q?Il2nJ5htPvVaSKHTvZptBAH19GNa2XZShYyxbqh4De9ma83rjgIlBeBC1lpr?= =?us-ascii?Q?IpNDFyvZUnc0KpfTu/FdyaAcYXiX7Q75HOWN3ya5/z4ZgsIhlC1v9ITrVtbk?= =?us-ascii?Q?ppuTgRM=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?usCBpxNlWRtyB6omc7vyx9aCb52KMXwhorE+6MszI/wZD9C/HjCbI/ZR2fg4?= =?us-ascii?Q?DWpOLW1iWRsmQb2c1JdRfkMNujKXlZLzJuj73TprFPldaJ8wUY0s8zBioUMZ?= =?us-ascii?Q?PlYgZqcvJ4wgpnliLpjf1l36RcCOdEKavBZsucEaMUUyWWGqNwAfHuqa7y+r?= =?us-ascii?Q?CMHYfjMArFHWgYk8UGpbPtWFnUBaxXPX0590nQuEMxCxTai9AwXO8VHsR3BV?= =?us-ascii?Q?4N59fFFuyJwNP2xud2/H3o9EpAnsyaoci0hUaXuJvNDkwd4IqH8LSq1qpX12?= =?us-ascii?Q?G5UH20MJuIk4sP4gVLQX1kKwe5UbFo03hfBVRBBcrNVGWmCn2jpGVDB4BBS0?= =?us-ascii?Q?hk3RaQAUX4P8hG+DqRqYsTk+sMTNtoxRdLWuezthK2hS08AvQhprITz0yEbZ?= =?us-ascii?Q?t6gvMv3to/sQrRbgyslRgpCeIFK10cXU6USpUth8F6sjMKnHf9YFnrsWtGcs?= =?us-ascii?Q?QYvK4lRWYuOlx/M/GaKUiLdgThiY0pigTrn/yjz7EUGS6RK159NBMZqMcMF3?= =?us-ascii?Q?gjnhX/eXShTIIyEX4vP7T7NsT1+5CYR6dJn/vPqmEzp/aa8TlZceGepMNljq?= =?us-ascii?Q?TyvqTf8iExLA9ZxZbIpSYO3Sl+tCllv87xqUsCxO4djZu0B2WhP1fRs3ucEw?= =?us-ascii?Q?Qi9J/m+aGsfOdw7pdrPt+GqQtX3uhQsmWiEZtvYy9uqderSpGI+726qCtKk9?= =?us-ascii?Q?3P0ObY+obXFUjVsVojC+Xp6senRydXy0qFBWNDowsvQE8tVtj+1g6tD8CTow?= =?us-ascii?Q?/SOBwS6raoiHud07hlPjgIgZlWVnOYZ6Qe/g7mNcbM5R08DS+QukdKLjRDZp?= =?us-ascii?Q?RIvP1xvTGNLcg+4OlZMhasNgrnYfVKRX0uAmMW/mPu2gsgItlvyNNltP/kJ0?= =?us-ascii?Q?1TK8fzWr1tgtJ/CY661uC1tCstpWKJ5/zarkBSIjRYheLGAAn/tWfh897uQ1?= =?us-ascii?Q?/Lrg1y7rAu1d371gvwoZjhdBpzZkizIw73adl4EnkS/j+PqgLC6C/15VKHy+?= =?us-ascii?Q?MZB0LfnF4aUqjVQh7+AtkUxi1sGjvErDMIGwxHY9VIz2m1iKe43ghZ+KqGaB?= =?us-ascii?Q?+8QKBp2db4Ti2eAeNfDkfKdV2gqpcr3jRNMU9IQB5gnpOFSTti7bdorKwXfd?= =?us-ascii?Q?z5lcmFBxjAW61E+FwZGsQfvK3Aam7LrUSmW1bgWJSZZ2yiYTt8EPSN87sf1i?= =?us-ascii?Q?iX3/N5k8vUsFz0Xb6rKGANrgSFIYfESCVquHs5CL3PhSUIMGyEJhj2NV3POQ?= =?us-ascii?Q?XGKFRwM0XKoMX+PLSz0FKGB43pZTAhOqfUk6G6k6u0SyDySeREpBSTxQ8AgH?= =?us-ascii?Q?/UeLQ+e9rvrJw9k0Y4QA7qs3Ds0vlKEnVmFVWQWPkHoPqYohFhkQbuTtO1ka?= =?us-ascii?Q?AFuCh+w4LxhGcSZlHys8awHWzBYVMigASq+uefASX8GZtCCk4UfOW+O0+f0q?= =?us-ascii?Q?WGkZvYGaZtZ8kFnj3FfZdyhkgmCyj8LyPUzqnbd8Ae7Z5zrLrjjNu/yuVbVK?= =?us-ascii?Q?ftENZ01LhqkbQtvgfGzgkyEjzY2QIdz3/YXhm0BhqZ3dms82AA7LfELmyF4W?= =?us-ascii?Q?3EIuAk1LNrqjAXxyf41krzZf6NmnHMpmUMUcV7H/?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 32a563ac-22ea-434d-c52e-08dc91c749de X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:51.2297 (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: pK0zS+yc5rTjVzbmS48O5otXMxJrenoD2bJyoa43IbA2TBX8sMEiOPi7aCtnSVr620J8E9a3mRIQlEZwO206/Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/main.c | 1726 +++++++++++++++++++++++ 1 file changed, 1726 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/main.c diff --git a/drivers/net/wireless/nxp/nxpwifi/main.c b/drivers/net/wireless= /nxp/nxpwifi/main.c new file mode 100644 index 000000000000..54d224bdb315 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/main.c @@ -0,0 +1,1726 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: major functions + * + * Copyright 2011-2024 NXP + */ + +#include + +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "cfg80211.h" +#include "11n.h" + +#define VERSION "1.0" + +static unsigned int debug_mask =3D NXPWIFI_DEFAULT_DEBUG_MASK; + +char driver_version[] =3D "nxpwifi " VERSION " (%s) "; + +const u16 nxpwifi_1d_to_wmm_queue[8] =3D { 1, 0, 0, 1, 2, 2, 3, 3 }; + +/* This function registers the device and performs all the necessary + * initializations. + * + * The following initialization operations are performed - + * - Allocate adapter structure + * - Save interface specific operations table in adapter + * - Call interface specific initialization routine + * - Allocate private structures + * - Set default adapter structure parameters + * - Initialize locks + * + * In case of any errors during inittialization, this function also ensures + * proper cleanup before exiting. + */ +static int nxpwifi_register(void *card, struct device *dev, + struct nxpwifi_if_ops *if_ops, void **padapter) +{ + struct nxpwifi_adapter *adapter; + int i; + + adapter =3D kzalloc(sizeof(*adapter), GFP_KERNEL); + if (!adapter) + return -ENOMEM; + + *padapter =3D adapter; + adapter->dev =3D dev; + adapter->card =3D card; + + /* Save interface specific operations in adapter */ + memmove(&adapter->if_ops, if_ops, sizeof(struct nxpwifi_if_ops)); + adapter->debug_mask =3D debug_mask; + + /* card specific initialization has been deferred until now .. */ + if (adapter->if_ops.init_if) + if (adapter->if_ops.init_if(adapter)) + goto error; + + adapter->priv_num =3D 0; + + for (i =3D 0; i < NXPWIFI_MAX_BSS_NUM; i++) { + /* Allocate memory for private structure */ + adapter->priv[i] =3D + kzalloc(sizeof(struct nxpwifi_private), GFP_KERNEL); + if (!adapter->priv[i]) + goto error; + + adapter->priv[i]->adapter =3D adapter; + adapter->priv_num++; + } + nxpwifi_init_lock_list(adapter); + + timer_setup(&adapter->cmd_timer, nxpwifi_cmd_timeout_func, 0); + + return 0; + +error: + nxpwifi_dbg(adapter, ERROR, + "info: leave %s with error\n", __func__); + + for (i =3D 0; i < adapter->priv_num; i++) + kfree(adapter->priv[i]); + + kfree(adapter); + + return -1; +} + +/* This function unregisters the device and performs all the necessary + * cleanups. + * + * The following cleanup operations are performed - + * - Free the timers + * - Free beacon buffers + * - Free private structures + * - Free adapter structure + */ +static int nxpwifi_unregister(struct nxpwifi_adapter *adapter) +{ + s32 i; + + if (adapter->if_ops.cleanup_if) + adapter->if_ops.cleanup_if(adapter); + + del_timer_sync(&adapter->cmd_timer); + + /* Free private structures */ + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + nxpwifi_free_curr_bcn(adapter->priv[i]); + kfree(adapter->priv[i]); + } + } + + if (adapter->nd_info) { + for (i =3D 0 ; i < adapter->nd_info->n_matches ; i++) + kfree(adapter->nd_info->matches[i]); + kfree(adapter->nd_info); + adapter->nd_info =3D NULL; + } + + kfree(adapter->regd); + + kfree(adapter); + return 0; +} + +void nxpwifi_queue_main_work(struct nxpwifi_adapter *adapter) +{ + unsigned long flags; + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + if (adapter->nxpwifi_processing) { + adapter->more_task_flag =3D true; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + } else { + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + queue_work(adapter->workqueue, &adapter->main_work); + } +} +EXPORT_SYMBOL_GPL(nxpwifi_queue_main_work); + +static void nxpwifi_queue_rx_work(struct nxpwifi_adapter *adapter) +{ + spin_lock_bh(&adapter->rx_proc_lock); + if (adapter->rx_processing) { + spin_unlock_bh(&adapter->rx_proc_lock); + } else { + spin_unlock_bh(&adapter->rx_proc_lock); + queue_work(adapter->rx_workqueue, &adapter->rx_work); + } +} + +static int nxpwifi_process_rx(struct nxpwifi_adapter *adapter) +{ + struct sk_buff *skb; + struct nxpwifi_rxinfo *rx_info; + + spin_lock_bh(&adapter->rx_proc_lock); + if (adapter->rx_processing || adapter->rx_locked) { + spin_unlock_bh(&adapter->rx_proc_lock); + goto exit_rx_proc; + } else { + adapter->rx_processing =3D true; + spin_unlock_bh(&adapter->rx_proc_lock); + } + + /* Check for Rx data */ + while ((skb =3D skb_dequeue(&adapter->rx_data_q))) { + atomic_dec(&adapter->rx_pending); + if (adapter->delay_main_work && + (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { + adapter->delay_main_work =3D false; + nxpwifi_queue_main_work(adapter); + } + rx_info =3D NXPWIFI_SKB_RXCB(skb); + if (rx_info->buf_type =3D=3D NXPWIFI_TYPE_AGGR_DATA) { + if (adapter->if_ops.deaggr_pkt) + adapter->if_ops.deaggr_pkt(adapter, skb); + dev_kfree_skb_any(skb); + } else { + nxpwifi_handle_rx_packet(adapter, skb); + } + } + spin_lock_bh(&adapter->rx_proc_lock); + adapter->rx_processing =3D false; + spin_unlock_bh(&adapter->rx_proc_lock); + +exit_rx_proc: + return 0; +} + +static void maybe_quirk_fw_disable_ds(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_RO= LE_STA); + struct nxpwifi_ver_ext ver_ext; + + if (test_and_set_bit(NXPWIFI_IS_REQUESTING_FW_VEREXT, &adapter->work_flag= s)) + return; + + memset(&ver_ext, 0, sizeof(ver_ext)); + ver_ext.version_str_sel =3D 1; + if (nxpwifi_send_cmd(priv, HOST_CMD_VERSION_EXT, + HOST_ACT_GEN_GET, 0, &ver_ext, false)) { + nxpwifi_dbg(priv->adapter, MSG, + "Checking hardware revision failed.\n"); + } +} + +/* The main process. + * + * This function is the main procedure of the driver and handles various d= river + * operations. It runs in a loop and provides the core functionalities. + * + * The main responsibilities of this function are - + * - Ensure concurrency control + * - Handle pending interrupts and call interrupt handlers + * - Wake up the card if required + * - Handle command responses and call response handlers + * - Handle events and call event handlers + * - Execute pending commands + * - Transmit pending data packets + */ +int nxpwifi_main_process(struct nxpwifi_adapter *adapter) +{ + int ret =3D 0; + unsigned long flags; + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + + /* Check if already processing */ + if (adapter->nxpwifi_processing || adapter->main_locked) { + adapter->more_task_flag =3D true; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + return 0; + } + + adapter->nxpwifi_processing =3D true; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + +process_start: + do { + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_NOT_READY) + break; + + /* For non-USB interfaces, If we process interrupts first, it + * would increase RX pending even further. Avoid this by + * checking if rx_pending has crossed high threshold and + * schedule rx work queue and then process interrupts. + * For USB interface, there are no interrupts. We already have + * HIGH_RX_PENDING check in usb.c + */ + if (atomic_read(&adapter->rx_pending) >=3D HIGH_RX_PENDING) { + adapter->delay_main_work =3D true; + nxpwifi_queue_rx_work(adapter); + break; + } + + /* Handle pending interrupt if any */ + if (adapter->int_status) { + if (adapter->hs_activated) + nxpwifi_process_hs_config(adapter); + if (adapter->if_ops.process_int_status) + adapter->if_ops.process_int_status(adapter); + } + + if (adapter->rx_work_enabled && adapter->data_received) + nxpwifi_queue_rx_work(adapter); + + /* Need to wake up the card ? */ + if (adapter->ps_state =3D=3D PS_STATE_SLEEP && + (adapter->pm_wakeup_card_req && + !adapter->pm_wakeup_fw_try) && + (is_command_pending(adapter) || + !skb_queue_empty(&adapter->tx_data_q) || + !nxpwifi_bypass_txlist_empty(adapter) || + !nxpwifi_wmm_lists_empty(adapter))) { + adapter->pm_wakeup_fw_try =3D true; + mod_timer(&adapter->wakeup_timer, jiffies + (HZ * 3)); + adapter->if_ops.wakeup(adapter); + continue; + } + + if (IS_CARD_RX_RCVD(adapter)) { + adapter->data_received =3D false; + adapter->pm_wakeup_fw_try =3D false; + del_timer(&adapter->wakeup_timer); + if (adapter->ps_state =3D=3D PS_STATE_SLEEP) + adapter->ps_state =3D PS_STATE_AWAKE; + } else { + /* We have tried to wakeup the card already */ + if (adapter->pm_wakeup_fw_try) + break; + if (adapter->ps_state =3D=3D PS_STATE_PRE_SLEEP) + nxpwifi_check_ps_cond(adapter); + + if (adapter->ps_state !=3D PS_STATE_AWAKE) + break; + if (adapter->tx_lock_flag) + break; + + if ((!adapter->scan_chan_gap_enabled && + adapter->scan_processing) || adapter->data_sent || + (nxpwifi_wmm_lists_empty(adapter) && + nxpwifi_bypass_txlist_empty(adapter) && + skb_queue_empty(&adapter->tx_data_q))) { + if (adapter->cmd_sent || adapter->curr_cmd || + (!is_command_pending(adapter))) + break; + } + } + + /* Check for event */ + if (adapter->event_received) { + adapter->event_received =3D false; + nxpwifi_process_event(adapter); + } + + /* Check for Cmd Resp */ + if (adapter->cmd_resp_received) { + adapter->cmd_resp_received =3D false; + nxpwifi_process_cmdresp(adapter); + + /* call nxpwifi back when init_fw is done */ + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_INIT_DONE) { + adapter->hw_status =3D NXPWIFI_HW_STATUS_READY; + nxpwifi_init_fw_complete(adapter); + maybe_quirk_fw_disable_ds(adapter); + } + } + + /* Check if we need to confirm Sleep Request + * received previously + */ + if (adapter->ps_state =3D=3D PS_STATE_PRE_SLEEP) + nxpwifi_check_ps_cond(adapter); + + /* * The ps_state may have been changed during processing of + * Sleep Request event. + */ + if (adapter->ps_state =3D=3D PS_STATE_SLEEP || + adapter->ps_state =3D=3D PS_STATE_PRE_SLEEP || + adapter->ps_state =3D=3D PS_STATE_SLEEP_CFM) { + continue; + } + + if (adapter->tx_lock_flag) + continue; + + if (!adapter->cmd_sent && !adapter->curr_cmd) { + if (nxpwifi_exec_next_cmd(adapter) =3D=3D -1) { + ret =3D -1; + break; + } + } + + if ((adapter->scan_chan_gap_enabled || + !adapter->scan_processing) && + !adapter->data_sent && + !skb_queue_empty(&adapter->tx_data_q)) { + if (adapter->hs_activated_manually) { + nxpwifi_cancel_hs(nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY), + NXPWIFI_ASYNC_CMD); + adapter->hs_activated_manually =3D false; + } + + nxpwifi_process_tx_queue(adapter); + if (adapter->hs_activated) { + clear_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags); + nxpwifi_hs_activated_event + (nxpwifi_get_priv + (adapter, NXPWIFI_BSS_ROLE_ANY), + false); + } + } + + if ((adapter->scan_chan_gap_enabled || + !adapter->scan_processing) && + !adapter->data_sent && + !nxpwifi_bypass_txlist_empty(adapter)) { + if (adapter->hs_activated_manually) { + nxpwifi_cancel_hs(nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY), + NXPWIFI_ASYNC_CMD); + adapter->hs_activated_manually =3D false; + } + + nxpwifi_process_bypass_tx(adapter); + if (adapter->hs_activated) { + clear_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags); + nxpwifi_hs_activated_event + (nxpwifi_get_priv + (adapter, NXPWIFI_BSS_ROLE_ANY), + false); + } + } + + if ((adapter->scan_chan_gap_enabled || + !adapter->scan_processing) && + !adapter->data_sent && !nxpwifi_wmm_lists_empty(adapter)) { + if (adapter->hs_activated_manually) { + nxpwifi_cancel_hs(nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY), + NXPWIFI_ASYNC_CMD); + adapter->hs_activated_manually =3D false; + } + + nxpwifi_wmm_process_tx(adapter); + if (adapter->hs_activated) { + clear_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags); + nxpwifi_hs_activated_event + (nxpwifi_get_priv + (adapter, NXPWIFI_BSS_ROLE_ANY), + false); + } + } + + if (adapter->delay_null_pkt && !adapter->cmd_sent && + !adapter->curr_cmd && !is_command_pending(adapter) && + (nxpwifi_wmm_lists_empty(adapter) && + nxpwifi_bypass_txlist_empty(adapter) && + skb_queue_empty(&adapter->tx_data_q))) { + if (!nxpwifi_send_null_packet + (nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA), + NXPWIFI_TxPD_POWER_MGMT_NULL_PACKET | + NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET)) { + adapter->delay_null_pkt =3D false; + adapter->ps_state =3D PS_STATE_SLEEP; + } + break; + } + } while (true); + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + if (adapter->more_task_flag) { + adapter->more_task_flag =3D false; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + goto process_start; + } + adapter->nxpwifi_processing =3D false; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(nxpwifi_main_process); + +/* This function frees the adapter structure. + * + * Additionally, this closes the netlink socket, frees the timers + * and private structures. + */ +static void nxpwifi_free_adapter(struct nxpwifi_adapter *adapter) +{ + if (!adapter) { + pr_err("%s: adapter is NULL\n", __func__); + return; + } + + nxpwifi_unregister(adapter); + pr_debug("info: %s: free adapter\n", __func__); +} + +/* This function cancels all works in the queue and destroys + * the main workqueue. + */ +static void nxpwifi_terminate_workqueue(struct nxpwifi_adapter *adapter) +{ + if (adapter->workqueue) { + destroy_workqueue(adapter->workqueue); + adapter->workqueue =3D NULL; + } + + if (adapter->rx_workqueue) { + destroy_workqueue(adapter->rx_workqueue); + adapter->rx_workqueue =3D NULL; + } + + if (adapter->host_mlme_workqueue) { + destroy_workqueue(adapter->host_mlme_workqueue); + adapter->host_mlme_workqueue =3D NULL; + } +} + +/* This function gets firmware and initializes it. + * + * The main initialization steps followed are - + * - Download the correct firmware to card + * - Issue the init commands to firmware + */ +static int _nxpwifi_fw_dpc(const struct firmware *firmware, void *context) +{ + int ret; + char fmt[64]; + struct nxpwifi_adapter *adapter =3D context; + struct nxpwifi_fw_image fw; + bool init_failed =3D false; + struct wireless_dev *wdev; + struct completion *fw_done =3D adapter->fw_done; + + if (!firmware) { + nxpwifi_dbg(adapter, ERROR, + "Failed to get firmware %s\n", adapter->fw_name); + goto err_dnld_fw; + } + + memset(&fw, 0, sizeof(struct nxpwifi_fw_image)); + adapter->firmware =3D firmware; + fw.fw_buf =3D (u8 *)adapter->firmware->data; + fw.fw_len =3D adapter->firmware->size; + + if (adapter->if_ops.dnld_fw) + ret =3D adapter->if_ops.dnld_fw(adapter, &fw); + else + ret =3D nxpwifi_dnld_fw(adapter, &fw); + + if (ret =3D=3D -1) + goto err_dnld_fw; + + nxpwifi_dbg(adapter, MSG, "WLAN FW is active\n"); + + /* enable host interrupt after fw dnld is successful */ + if (adapter->if_ops.enable_int) { + if (adapter->if_ops.enable_int(adapter)) + goto err_dnld_fw; + } + + adapter->init_wait_q_woken =3D false; + ret =3D nxpwifi_init_fw(adapter); + if (ret =3D=3D -1) { + goto err_init_fw; + } else if (!ret) { + adapter->hw_status =3D NXPWIFI_HW_STATUS_READY; + goto done; + } + /* Wait for nxpwifi_init to complete */ + wait_event_interruptible(adapter->init_wait_q, + adapter->init_wait_q_woken); + if (adapter->hw_status !=3D NXPWIFI_HW_STATUS_READY) + goto err_init_fw; + + if (!adapter->wiphy) { + if (nxpwifi_register_cfg80211(adapter)) { + nxpwifi_dbg(adapter, ERROR, + "cannot register with cfg80211\n"); + goto err_init_fw; + } + } + + if (nxpwifi_init_channel_scan_gap(adapter)) { + nxpwifi_dbg(adapter, ERROR, + "could not init channel stats table\n"); + goto err_init_chan_scan; + } + + rtnl_lock(); + wiphy_lock(adapter->wiphy); + /* Create station interface by default */ + wdev =3D nxpwifi_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM, + NL80211_IFTYPE_STATION, NULL); + if (IS_ERR(wdev)) { + nxpwifi_dbg(adapter, ERROR, + "cannot create default STA interface\n"); + wiphy_unlock(adapter->wiphy); + rtnl_unlock(); + goto err_add_intf; + } + + wdev =3D nxpwifi_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM, + NL80211_IFTYPE_AP, NULL); + if (IS_ERR(wdev)) { + nxpwifi_dbg(adapter, ERROR, + "cannot create AP interface\n"); + wiphy_unlock(adapter->wiphy); + rtnl_unlock(); + goto err_add_intf; + } + + wiphy_unlock(adapter->wiphy); + rtnl_unlock(); + + nxpwifi_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); + nxpwifi_dbg(adapter, MSG, "driver_version =3D %s\n", fmt); + adapter->is_up =3D true; + goto done; + +err_add_intf: + vfree(adapter->chan_stats); +err_init_chan_scan: + wiphy_unregister(adapter->wiphy); + wiphy_free(adapter->wiphy); +err_init_fw: + if (adapter->if_ops.disable_int) + adapter->if_ops.disable_int(adapter); +err_dnld_fw: + nxpwifi_dbg(adapter, ERROR, + "info: %s: unregister device\n", __func__); + if (adapter->if_ops.unregister_dev) + adapter->if_ops.unregister_dev(adapter); + + set_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + nxpwifi_terminate_workqueue(adapter); + + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_READY) { + pr_debug("info: %s: shutdown nxpwifi\n", __func__); + nxpwifi_shutdown_drv(adapter); + nxpwifi_free_cmd_buffers(adapter); + } + + init_failed =3D true; +done: + if (adapter->cal_data) { + release_firmware(adapter->cal_data); + adapter->cal_data =3D NULL; + } + if (adapter->firmware) { + release_firmware(adapter->firmware); + adapter->firmware =3D NULL; + } + if (init_failed) { + if (adapter->irq_wakeup >=3D 0) + device_init_wakeup(adapter->dev, false); + nxpwifi_free_adapter(adapter); + } + /* Tell all current and future waiters we're finished */ + complete_all(fw_done); + + return init_failed ? -EIO : 0; +} + +static void nxpwifi_fw_dpc(const struct firmware *firmware, void *context) +{ + _nxpwifi_fw_dpc(firmware, context); +} + +/* This function gets the firmware and (if called asynchronously) kicks of= f the + * HW init when done. + */ +static int nxpwifi_init_hw_fw(struct nxpwifi_adapter *adapter, + bool req_fw_nowait) +{ + int ret; + + if (req_fw_nowait) { + ret =3D request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name, + adapter->dev, GFP_KERNEL, adapter, + nxpwifi_fw_dpc); + } else { + ret =3D request_firmware(&adapter->firmware, + adapter->fw_name, + adapter->dev); + } + + if (ret < 0) + nxpwifi_dbg(adapter, ERROR, "request_firmware%s error %d\n", + req_fw_nowait ? "_nowait" : "", ret); + return ret; +} + +/* CFG802.11 network device handler for open. + * + * Starts the data queue. + */ +static int +nxpwifi_open(struct net_device *dev) +{ + netif_carrier_off(dev); + + return 0; +} + +/* CFG802.11 network device handler for close. + */ +static int +nxpwifi_close(struct net_device *dev) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + if (priv->scan_request) { + struct cfg80211_scan_info info =3D { + .aborted =3D true, + }; + + nxpwifi_dbg(priv->adapter, INFO, + "aborting scan on ndo_stop\n"); + cfg80211_scan_done(priv->scan_request, &info); + priv->scan_request =3D NULL; + priv->scan_aborting =3D true; + } + + if (priv->sched_scanning) { + nxpwifi_dbg(priv->adapter, INFO, + "aborting bgscan on ndo_stop\n"); + nxpwifi_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0); + } + + return 0; +} + +static bool +nxpwifi_bypass_tx_queue(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct ethhdr *eth_hdr =3D (struct ethhdr *)skb->data; + + if (eth_hdr->h_proto =3D=3D htons(ETH_P_PAE) || + nxpwifi_is_skb_mgmt_frame(skb)) { + nxpwifi_dbg(priv->adapter, DATA, + "bypass txqueue; eth type %#x, mgmt %d\n", + ntohs(eth_hdr->h_proto), + nxpwifi_is_skb_mgmt_frame(skb)); + if (eth_hdr->h_proto =3D=3D htons(ETH_P_PAE)) + nxpwifi_dbg(priv->adapter, MSG, + "key: send EAPOL to %pM\n", + eth_hdr->h_dest); + return true; + } + + return false; +} + +/* Add buffer into wmm tx queue and queue work to transmit it. + */ +int nxpwifi_queue_tx_pkt(struct nxpwifi_private *priv, struct sk_buff *skb) +{ + struct netdev_queue *txq; + int index =3D nxpwifi_1d_to_wmm_queue[skb->priority]; + + if (atomic_inc_return(&priv->wmm_tx_pending[index]) >=3D MAX_TX_PENDING) { + txq =3D netdev_get_tx_queue(priv->netdev, index); + if (!netif_tx_queue_stopped(txq)) { + netif_tx_stop_queue(txq); + nxpwifi_dbg(priv->adapter, DATA, + "stop queue: %d\n", index); + } + } + + if (nxpwifi_bypass_tx_queue(priv, skb)) { + atomic_inc(&priv->adapter->tx_pending); + atomic_inc(&priv->adapter->bypass_tx_pending); + nxpwifi_wmm_add_buf_bypass_txqueue(priv, skb); + } else { + atomic_inc(&priv->adapter->tx_pending); + nxpwifi_wmm_add_buf_txqueue(priv, skb); + } + + nxpwifi_queue_main_work(priv->adapter); + + return 0; +} + +struct sk_buff * +nxpwifi_clone_skb_for_tx_status(struct nxpwifi_private *priv, + struct sk_buff *skb, u8 flag, u64 *cookie) +{ + struct sk_buff *orig_skb =3D skb; + struct nxpwifi_txinfo *tx_info, *orig_tx_info; + + skb =3D skb_clone(skb, GFP_ATOMIC); + if (skb) { + int id; + + spin_lock_bh(&priv->ack_status_lock); + id =3D idr_alloc(&priv->ack_status_frames, orig_skb, + 1, 0x10, GFP_ATOMIC); + spin_unlock_bh(&priv->ack_status_lock); + + if (id >=3D 0) { + tx_info =3D NXPWIFI_SKB_TXCB(skb); + tx_info->ack_frame_id =3D id; + tx_info->flags |=3D flag; + orig_tx_info =3D NXPWIFI_SKB_TXCB(orig_skb); + orig_tx_info->ack_frame_id =3D id; + orig_tx_info->flags |=3D flag; + + if (flag =3D=3D NXPWIFI_BUF_FLAG_ACTION_TX_STATUS && cookie) + orig_tx_info->cookie =3D *cookie; + + } else if (skb_shared(skb)) { + kfree_skb(orig_skb); + } else { + kfree_skb(skb); + skb =3D orig_skb; + } + } else { + /* couldn't clone -- lose tx status ... */ + skb =3D orig_skb; + } + + return skb; +} + +/* CFG802.11 network device handler for data transmission. + */ +static netdev_tx_t +nxpwifi_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct sk_buff *new_skb; + struct nxpwifi_txinfo *tx_info; + bool multicast; + + nxpwifi_dbg(priv->adapter, DATA, + "data: %lu BSS(%d-%d): Data <=3D kernel\n", + jiffies, priv->bss_type, priv->bss_num); + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &priv->adapter->work_flags)) { + kfree_skb(skb); + priv->stats.tx_dropped++; + return 0; + } + if (!skb->len || skb->len > ETH_FRAME_LEN) { + nxpwifi_dbg(priv->adapter, ERROR, + "Tx: bad skb len %d\n", skb->len); + kfree_skb(skb); + priv->stats.tx_dropped++; + return 0; + } + if (skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN) { + nxpwifi_dbg(priv->adapter, DATA, + "data: Tx: insufficient skb headroom %d\n", + skb_headroom(skb)); + /* Insufficient skb headroom - allocate a new skb */ + new_skb =3D + skb_realloc_headroom(skb, NXPWIFI_MIN_DATA_HEADER_LEN); + if (unlikely(!new_skb)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Tx: cannot alloca new_skb\n"); + kfree_skb(skb); + priv->stats.tx_dropped++; + return 0; + } + kfree_skb(skb); + skb =3D new_skb; + nxpwifi_dbg(priv->adapter, INFO, + "info: new skb headroomd %d\n", + skb_headroom(skb)); + } + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num =3D priv->bss_num; + tx_info->bss_type =3D priv->bss_type; + tx_info->pkt_len =3D skb->len; + + multicast =3D is_multicast_ether_addr(skb->data); + + if (unlikely(!multicast && skb->sk && + skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS && + priv->adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15)) + skb =3D nxpwifi_clone_skb_for_tx_status(priv, + skb, + NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS, NULL); + + /* Record the current time the packet was queued; used to + * determine the amount of time the packet was queued in + * the driver before it was sent to the firmware. + * The delay is then sent along with the packet to the + * firmware for aggregate delay calculation for stats and + * MSDU lifetime expiry. + */ + __net_timestamp(skb); + + nxpwifi_queue_tx_pkt(priv, skb); + + return 0; +} + +int nxpwifi_set_mac_address(struct nxpwifi_private *priv, + struct net_device *dev, bool external, + u8 *new_mac) +{ + int ret; + u64 mac_addr, old_mac_addr; + + old_mac_addr =3D ether_addr_to_u64(priv->curr_addr); + + if (external) { + mac_addr =3D ether_addr_to_u64(new_mac); + } else { + /* Internal mac address change */ + if (priv->bss_type =3D=3D NXPWIFI_BSS_TYPE_ANY) + return -EOPNOTSUPP; + + mac_addr =3D old_mac_addr; + + if (priv->adapter->priv[0] !=3D priv) { + /* Set mac address based on bss_type/bss_num */ + mac_addr ^=3D BIT_ULL(priv->bss_type + 8); + mac_addr +=3D priv->bss_num; + } + } + + u64_to_ether_addr(mac_addr, priv->curr_addr); + + /* Send request to firmware */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_MAC_ADDRESS, + HOST_ACT_GEN_SET, 0, NULL, true); + + if (ret) { + u64_to_ether_addr(old_mac_addr, priv->curr_addr); + nxpwifi_dbg(priv->adapter, ERROR, + "set mac address failed: ret=3D%d\n", ret); + return ret; + } + + eth_hw_addr_set(dev, priv->curr_addr); + return 0; +} + +/* CFG802.11 network device handler for setting MAC address. + */ +static int +nxpwifi_ndo_set_mac_address(struct net_device *dev, void *addr) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct sockaddr *hw_addr =3D addr; + + return nxpwifi_set_mac_address(priv, dev, true, hw_addr->sa_data); +} + +/* CFG802.11 network device handler for setting multicast list. + */ +static void nxpwifi_set_multicast_list(struct net_device *dev) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + struct nxpwifi_multicast_list mcast_list; + + if (dev->flags & IFF_PROMISC) { + mcast_list.mode =3D NXPWIFI_PROMISC_MODE; + } else if (dev->flags & IFF_ALLMULTI || + netdev_mc_count(dev) > NXPWIFI_MAX_MULTICAST_LIST_SIZE) { + mcast_list.mode =3D NXPWIFI_ALL_MULTI_MODE; + } else { + mcast_list.mode =3D NXPWIFI_MULTICAST_MODE; + mcast_list.num_multicast_addr =3D + nxpwifi_copy_mcast_addr(&mcast_list, dev); + } + nxpwifi_request_set_multicast_list(priv, &mcast_list); +} + +/* CFG802.11 network device handler for transmission timeout. + */ +static void +nxpwifi_tx_timeout(struct net_device *dev, unsigned int txqueue) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + priv->num_tx_timeout++; + priv->tx_timeout_cnt++; + nxpwifi_dbg(priv->adapter, ERROR, + "%lu : Tx timeout(#%d), bss_type-num =3D %d-%d\n", + jiffies, priv->tx_timeout_cnt, priv->bss_type, + priv->bss_num); + nxpwifi_set_trans_start(dev); + + if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD && + priv->adapter->if_ops.card_reset) { + nxpwifi_dbg(priv->adapter, ERROR, + "tx_timeout_cnt exceeds threshold.\t" + "Triggering card reset!\n"); + priv->adapter->if_ops.card_reset(priv->adapter); + } +} + +void nxpwifi_upload_device_dump(struct nxpwifi_adapter *adapter) +{ + /* Dump all the memory data into single file, a userspace script will + * be used to split all the memory data to multiple files + */ + nxpwifi_dbg(adapter, MSG, + "=3D=3D nxpwifi dump information to /sys/class/devcoredump start\n"); + dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len, + GFP_KERNEL); + nxpwifi_dbg(adapter, MSG, + "=3D=3D nxpwifi dump information to /sys/class/devcoredump end\n"); + + /* Device dump data will be freed in device coredump release function + * after 5 min. Here reset adapter->devdump_data and ->devdump_len + * to avoid it been accidentally reused. + */ + adapter->devdump_data =3D NULL; + adapter->devdump_len =3D 0; +} +EXPORT_SYMBOL_GPL(nxpwifi_upload_device_dump); + +void nxpwifi_drv_info_dump(struct nxpwifi_adapter *adapter) +{ + char *p; + char drv_version[64]; + struct sdio_mmc_card *sdio_card; + struct nxpwifi_private *priv; + int i, idx; + struct netdev_queue *txq; + struct nxpwifi_debug_info *debug_info; + + nxpwifi_dbg(adapter, MSG, "=3D=3D=3Dnxpwifi driverinfo dump start=3D=3D= =3D\n"); + + p =3D adapter->devdump_data; + strscpy(p, "=3D=3D=3D=3D=3D=3D=3D=3DStart dump driverinfo=3D=3D=3D=3D=3D= =3D=3D=3D\n", NXPWIFI_FW_DUMP_SIZE); + p +=3D strlen("=3D=3D=3D=3D=3D=3D=3D=3DStart dump driverinfo=3D=3D=3D=3D= =3D=3D=3D=3D\n"); + p +=3D sprintf(p, "driver_name =3D "); + p +=3D sprintf(p, "\"nxpwifi\"\n"); + + nxpwifi_drv_get_driver_version(adapter, drv_version, + sizeof(drv_version) - 1); + p +=3D sprintf(p, "driver_version =3D %s\n", drv_version); + + p +=3D sprintf(p, "tx_pending =3D %d\n", + atomic_read(&adapter->tx_pending)); + p +=3D sprintf(p, "rx_pending =3D %d\n", + atomic_read(&adapter->rx_pending)); + + if (adapter->iface_type =3D=3D NXPWIFI_SDIO) { + sdio_card =3D (struct sdio_mmc_card *)adapter->card; + p +=3D sprintf(p, "\nmp_rd_bitmap=3D0x%x curr_rd_port=3D0x%x\n", + sdio_card->mp_rd_bitmap, sdio_card->curr_rd_port); + p +=3D sprintf(p, "mp_wr_bitmap=3D0x%x curr_wr_port=3D0x%x\n", + sdio_card->mp_wr_bitmap, sdio_card->curr_wr_port); + } + + for (i =3D 0; i < adapter->priv_num; i++) { + if (!adapter->priv[i] || !adapter->priv[i]->netdev) + continue; + priv =3D adapter->priv[i]; + p +=3D sprintf(p, "\n[interface : \"%s\"]\n", + priv->netdev->name); + p +=3D sprintf(p, "wmm_tx_pending[0] =3D %d\n", + atomic_read(&priv->wmm_tx_pending[0])); + p +=3D sprintf(p, "wmm_tx_pending[1] =3D %d\n", + atomic_read(&priv->wmm_tx_pending[1])); + p +=3D sprintf(p, "wmm_tx_pending[2] =3D %d\n", + atomic_read(&priv->wmm_tx_pending[2])); + p +=3D sprintf(p, "wmm_tx_pending[3] =3D %d\n", + atomic_read(&priv->wmm_tx_pending[3])); + p +=3D sprintf(p, "media_state=3D\"%s\"\n", !priv->media_connected ? + "Disconnected" : "Connected"); + p +=3D sprintf(p, "carrier %s\n", (netif_carrier_ok(priv->netdev) + ? "on" : "off")); + for (idx =3D 0; idx < priv->netdev->num_tx_queues; idx++) { + txq =3D netdev_get_tx_queue(priv->netdev, idx); + p +=3D sprintf(p, "tx queue %d:%s ", idx, + netif_tx_queue_stopped(txq) ? + "stopped" : "started"); + } + p +=3D sprintf(p, "\n%s: num_tx_timeout =3D %d\n", + priv->netdev->name, priv->num_tx_timeout); + } + + if (adapter->iface_type =3D=3D NXPWIFI_SDIO) { + p +=3D sprintf(p, "\n=3D=3D=3D %s register dump=3D=3D=3D\n", "SDIO"); + if (adapter->if_ops.reg_dump) + p +=3D adapter->if_ops.reg_dump(adapter, p); + } + p +=3D sprintf(p, "\n=3D=3D=3D more debug information\n"); + debug_info =3D kzalloc(sizeof(*debug_info), GFP_KERNEL); + if (debug_info) { + for (i =3D 0; i < adapter->priv_num; i++) { + if (!adapter->priv[i] || !adapter->priv[i]->netdev) + continue; + priv =3D adapter->priv[i]; + nxpwifi_get_debug_info(priv, debug_info); + p +=3D nxpwifi_debug_info_to_buffer(priv, p, debug_info); + break; + } + kfree(debug_info); + } + + p +=3D sprintf(p, "\n=3D=3D=3D=3D=3D=3D=3D=3DEnd dump=3D=3D=3D=3D=3D=3D= =3D=3D\n"); + nxpwifi_dbg(adapter, MSG, "=3D=3D=3Dnxpwifi driverinfo dump end=3D=3D=3D\= n"); + adapter->devdump_len =3D p - (char *)adapter->devdump_data; +} +EXPORT_SYMBOL_GPL(nxpwifi_drv_info_dump); + +void nxpwifi_prepare_fw_dump_info(struct nxpwifi_adapter *adapter) +{ + u8 idx; + char *fw_dump_ptr; + u32 dump_len =3D 0; + + for (idx =3D 0; idx < adapter->num_mem_types; idx++) { + struct memory_type_mapping *entry =3D + &adapter->mem_type_mapping_tbl[idx]; + + if (entry->mem_ptr) { + dump_len +=3D (strlen("=3D=3D=3D=3D=3D=3D=3D=3DStart dump ") + + strlen(entry->mem_name) + + strlen("=3D=3D=3D=3D=3D=3D=3D=3D\n") + + (entry->mem_size + 1) + + strlen("\n=3D=3D=3D=3D=3D=3D=3D=3DEnd dump=3D=3D=3D=3D=3D=3D=3D=3D\n"= )); + } + } + + if (dump_len + 1 + adapter->devdump_len > NXPWIFI_FW_DUMP_SIZE) { + /* Realloc in case buffer overflow */ + fw_dump_ptr =3D vzalloc(dump_len + 1 + adapter->devdump_len); + nxpwifi_dbg(adapter, MSG, "Realloc device dump data.\n"); + if (!fw_dump_ptr) { + vfree(adapter->devdump_data); + nxpwifi_dbg(adapter, ERROR, + "vzalloc devdump data failure!\n"); + return; + } + + memmove(fw_dump_ptr, adapter->devdump_data, + adapter->devdump_len); + vfree(adapter->devdump_data); + adapter->devdump_data =3D fw_dump_ptr; + } + + fw_dump_ptr =3D (char *)adapter->devdump_data + adapter->devdump_len; + + for (idx =3D 0; idx < adapter->num_mem_types; idx++) { + struct memory_type_mapping *entry =3D + &adapter->mem_type_mapping_tbl[idx]; + + if (entry->mem_ptr) { + fw_dump_ptr +=3D sprintf(fw_dump_ptr, "=3D=3D=3D=3D=3D=3D=3D=3DStart du= mp "); + fw_dump_ptr +=3D sprintf(fw_dump_ptr, "%s", entry->mem_name); + fw_dump_ptr +=3D sprintf(fw_dump_ptr, "=3D=3D=3D=3D=3D=3D=3D=3D\n"); + memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size); + fw_dump_ptr +=3D entry->mem_size; + fw_dump_ptr +=3D sprintf(fw_dump_ptr, "\n=3D=3D=3D=3D=3D=3D=3D=3DEnd du= mp=3D=3D=3D=3D=3D=3D=3D=3D\n"); + } + } + + adapter->devdump_len =3D fw_dump_ptr - (char *)adapter->devdump_data; + + for (idx =3D 0; idx < adapter->num_mem_types; idx++) { + struct memory_type_mapping *entry =3D + &adapter->mem_type_mapping_tbl[idx]; + + vfree(entry->mem_ptr); + entry->mem_ptr =3D NULL; + entry->mem_size =3D 0; + } +} +EXPORT_SYMBOL_GPL(nxpwifi_prepare_fw_dump_info); + +/* CFG802.11 network device handler for statistics retrieval. + */ +static struct net_device_stats *nxpwifi_get_stats(struct net_device *dev) +{ + struct nxpwifi_private *priv =3D nxpwifi_netdev_get_priv(dev); + + return &priv->stats; +} + +static u16 +nxpwifi_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *sk= b, + struct net_device *sb_dev) +{ + skb->priority =3D cfg80211_classify8021d(skb, NULL); + return nxpwifi_1d_to_wmm_queue[skb->priority]; +} + +/* Network device handlers */ +static const struct net_device_ops nxpwifi_netdev_ops =3D { + .ndo_open =3D nxpwifi_open, + .ndo_stop =3D nxpwifi_close, + .ndo_start_xmit =3D nxpwifi_hard_start_xmit, + .ndo_set_mac_address =3D nxpwifi_ndo_set_mac_address, + .ndo_validate_addr =3D eth_validate_addr, + .ndo_tx_timeout =3D nxpwifi_tx_timeout, + .ndo_get_stats =3D nxpwifi_get_stats, + .ndo_set_rx_mode =3D nxpwifi_set_multicast_list, + .ndo_select_queue =3D nxpwifi_netdev_select_wmm_queue, +}; + +/* This function initializes the private structure parameters. + * + * The following wait queues are initialized - + * - IOCTL wait queue + * - Command wait queue + * - Statistics wait queue + * + * ...and the following default parameters are set - + * - Current key index : Set to 0 + * - Rate index : Set to auto + * - Media connected : Set to disconnected + * - Nick name : Set to null + * - Number of Tx timeout : Set to 0 + * - Device address : Set to current address + * - Rx histogram statistc : Set to 0 + * + * In addition, the CFG80211 work queue is also created. + */ +void nxpwifi_init_priv_params(struct nxpwifi_private *priv, + struct net_device *dev) +{ + dev->netdev_ops =3D &nxpwifi_netdev_ops; + dev->needs_free_netdev =3D true; + /* Initialize private structure */ + priv->current_key_index =3D 0; + priv->media_connected =3D false; + memset(priv->mgmt_ie, 0, + sizeof(struct nxpwifi_ie) * MAX_MGMT_IE_INDEX); + priv->beacon_idx =3D NXPWIFI_AUTO_IDX_MASK; + priv->proberesp_idx =3D NXPWIFI_AUTO_IDX_MASK; + priv->assocresp_idx =3D NXPWIFI_AUTO_IDX_MASK; + priv->gen_idx =3D NXPWIFI_AUTO_IDX_MASK; + priv->num_tx_timeout =3D 0; + if (is_valid_ether_addr(dev->dev_addr)) + ether_addr_copy(priv->curr_addr, dev->dev_addr); + else + ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr); + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA || + GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + priv->hist_data =3D kmalloc(sizeof(*priv->hist_data), GFP_KERNEL); + if (priv->hist_data) + nxpwifi_hist_data_reset(priv); + } +} + +/* This function check if command is pending. + */ +int is_command_pending(struct nxpwifi_adapter *adapter) +{ + int is_cmd_pend_q_empty; + + spin_lock_bh(&adapter->cmd_pending_q_lock); + is_cmd_pend_q_empty =3D list_empty(&adapter->cmd_pending_q); + spin_unlock_bh(&adapter->cmd_pending_q_lock); + + return !is_cmd_pend_q_empty; +} + +/* This is the host mlme work queue function. + * It handles the host mlme operations. + */ +static void nxpwifi_host_mlme_work_queue(struct work_struct *work) +{ + struct nxpwifi_adapter *adapter =3D + container_of(work, struct nxpwifi_adapter, host_mlme_work); + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) + return; + + /* Check for host mlme disconnection */ + if (adapter->host_mlme_link_lost) { + if (adapter->priv_link_lost) { + nxpwifi_reset_connect_state(adapter->priv_link_lost, + WLAN_REASON_DEAUTH_LEAVING, + true); + adapter->priv_link_lost =3D NULL; + } + adapter->host_mlme_link_lost =3D false; + } + + /* Check for host mlme Assoc Resp */ + if (adapter->assoc_resp_received) { + nxpwifi_process_assoc_resp(adapter); + adapter->assoc_resp_received =3D false; + } +} + +/* This is the RX work queue function. + * + * It handles the RX operations. + */ +static void nxpwifi_rx_work_queue(struct work_struct *work) +{ + struct nxpwifi_adapter *adapter =3D + container_of(work, struct nxpwifi_adapter, rx_work); + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) + return; + nxpwifi_process_rx(adapter); +} + +/* This is the main work queue function. + * + * It handles the main process, which in turn handles the complete + * driver operations. + */ +static void nxpwifi_main_work_queue(struct work_struct *work) +{ + struct nxpwifi_adapter *adapter =3D + container_of(work, struct nxpwifi_adapter, main_work); + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) + return; + nxpwifi_main_process(adapter); +} + +/* Common teardown code used for both device removal and reset */ +static void nxpwifi_uninit_sw(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + int i; + + /* We can no longer handle interrupts once we start doing the teardown + * below. + */ + if (adapter->if_ops.disable_int) + adapter->if_ops.disable_int(adapter); + + set_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + nxpwifi_terminate_workqueue(adapter); + adapter->int_status =3D 0; + + /* Stop data */ + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv && priv->netdev) { + nxpwifi_stop_net_dev_queue(priv->netdev, adapter); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + netif_device_detach(priv->netdev); + } + } + + nxpwifi_dbg(adapter, CMD, "cmd: calling nxpwifi_shutdown_drv...\n"); + nxpwifi_shutdown_drv(adapter); + nxpwifi_dbg(adapter, CMD, "cmd: nxpwifi_shutdown_drv done\n"); + + if (atomic_read(&adapter->rx_pending) || + atomic_read(&adapter->tx_pending) || + atomic_read(&adapter->cmd_pending)) { + nxpwifi_dbg(adapter, ERROR, + "rx_pending=3D%d, tx_pending=3D%d,\t" + "cmd_pending=3D%d\n", + atomic_read(&adapter->rx_pending), + atomic_read(&adapter->tx_pending), + atomic_read(&adapter->cmd_pending)); + } + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (!priv) + continue; + rtnl_lock(); + if (priv->netdev && + priv->wdev.iftype !=3D NL80211_IFTYPE_UNSPECIFIED) { + /* Close the netdev now, because if we do it later, the + * netdev notifiers will need to acquire the wiphy lock + * again --> deadlock. + */ + dev_close(priv->wdev.netdev); + wiphy_lock(adapter->wiphy); + nxpwifi_del_virtual_intf(adapter->wiphy, &priv->wdev); + wiphy_unlock(adapter->wiphy); + } + rtnl_unlock(); + } + + wiphy_unregister(adapter->wiphy); + wiphy_free(adapter->wiphy); + adapter->wiphy =3D NULL; + + vfree(adapter->chan_stats); + nxpwifi_free_cmd_buffers(adapter); +} + +/* This function can be used for shutting down the adapter SW. + */ +int nxpwifi_shutdown_sw(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + + if (!adapter) + return 0; + + wait_for_completion(adapter->fw_done); + /* Caller should ensure we aren't suspending while this happens */ + reinit_completion(adapter->fw_done); + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + nxpwifi_deauthenticate(priv, NULL); + + nxpwifi_init_shutdown_fw(priv, NXPWIFI_FUNC_SHUTDOWN); + + nxpwifi_uninit_sw(adapter); + adapter->is_up =3D false; + + return 0; +} +EXPORT_SYMBOL_GPL(nxpwifi_shutdown_sw); + +/* This function can be used for reinitting the adapter SW. Required + * code is extracted from nxpwifi_add_card() + */ +int +nxpwifi_reinit_sw(struct nxpwifi_adapter *adapter) +{ + int ret; + + nxpwifi_init_lock_list(adapter); + if (adapter->if_ops.up_dev) + adapter->if_ops.up_dev(adapter); + + adapter->hw_status =3D NXPWIFI_HW_STATUS_INITIALIZING; + clear_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + init_waitqueue_head(&adapter->init_wait_q); + clear_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags); + adapter->hs_activated =3D false; + clear_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags); + init_waitqueue_head(&adapter->hs_activate_wait_q); + init_waitqueue_head(&adapter->cmd_wait_q.wait); + adapter->cmd_wait_q.status =3D 0; + adapter->scan_wait_q_woken =3D false; + + if (num_possible_cpus() > 1) + adapter->rx_work_enabled =3D true; + + adapter->workqueue =3D + alloc_workqueue("NXPWIFI_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (!adapter->workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->main_work, nxpwifi_main_work_queue); + + if (adapter->rx_work_enabled) { + adapter->rx_workqueue =3D alloc_workqueue("NXPWIFI_RX_WORK_QUEUE", + WQ_HIGHPRI | + WQ_MEM_RECLAIM | + WQ_UNBOUND, 0); + if (!adapter->rx_workqueue) + goto err_kmalloc; + INIT_WORK(&adapter->rx_work, nxpwifi_rx_work_queue); + } + + adapter->host_mlme_workqueue =3D + alloc_workqueue("NXPWIFI_HOST_MLME_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (!adapter->host_mlme_workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->host_mlme_work, nxpwifi_host_mlme_work_queue); + + /* Register the device. Fill up the private data structure with + * relevant information from the card. Some code extracted from + * nxpwifi_register_dev() + */ + nxpwifi_dbg(adapter, INFO, "%s, nxpwifi_init_hw_fw()...\n", __func__); + + if (nxpwifi_init_hw_fw(adapter, false)) { + nxpwifi_dbg(adapter, ERROR, + "%s: firmware init failed\n", __func__); + goto err_init_fw; + } + + /* _nxpwifi_fw_dpc() does its own cleanup */ + ret =3D _nxpwifi_fw_dpc(adapter->firmware, adapter); + if (ret) { + pr_err("Failed to bring up adapter: %d\n", ret); + return ret; + } + nxpwifi_dbg(adapter, INFO, "%s, successful\n", __func__); + + return 0; + +err_init_fw: + nxpwifi_dbg(adapter, ERROR, "info: %s: unregister device\n", __func__); + if (adapter->if_ops.unregister_dev) + adapter->if_ops.unregister_dev(adapter); + +err_kmalloc: + set_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + nxpwifi_terminate_workqueue(adapter); + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_READY) { + nxpwifi_dbg(adapter, ERROR, + "info: %s: shutdown nxpwifi\n", __func__); + nxpwifi_shutdown_drv(adapter); + nxpwifi_free_cmd_buffers(adapter); + } + + complete_all(adapter->fw_done); + nxpwifi_dbg(adapter, INFO, "%s, error\n", __func__); + + return -1; +} +EXPORT_SYMBOL_GPL(nxpwifi_reinit_sw); + +static irqreturn_t nxpwifi_irq_wakeup_handler(int irq, void *priv) +{ + struct nxpwifi_adapter *adapter =3D priv; + + dev_dbg(adapter->dev, "%s: wake by wifi", __func__); + adapter->wake_by_wifi =3D true; + disable_irq_nosync(irq); + + /* Notify PM core we are wakeup source */ + pm_wakeup_event(adapter->dev, 0); + pm_system_wakeup(); + + return IRQ_HANDLED; +} + +static void nxpwifi_probe_of(struct nxpwifi_adapter *adapter) +{ + int ret; + struct device *dev =3D adapter->dev; + + if (!dev->of_node) + goto err_exit; + + adapter->dt_node =3D dev->of_node; + adapter->irq_wakeup =3D irq_of_parse_and_map(adapter->dt_node, 0); + if (!adapter->irq_wakeup) { + dev_dbg(dev, "fail to parse irq_wakeup from device tree\n"); + goto err_exit; + } + + ret =3D devm_request_irq(dev, adapter->irq_wakeup, + nxpwifi_irq_wakeup_handler, IRQF_TRIGGER_LOW, + "wifi_wake", adapter); + if (ret) { + dev_err(dev, "Failed to request irq_wakeup %d (%d)\n", + adapter->irq_wakeup, ret); + goto err_exit; + } + + disable_irq(adapter->irq_wakeup); + if (device_init_wakeup(dev, true)) { + dev_err(dev, "fail to init wakeup for nxpwifi\n"); + goto err_exit; + } + return; + +err_exit: + adapter->irq_wakeup =3D -1; +} + +/* This function adds the card. + * + * This function follows the following major steps to set up the device - + * - Initialize software. This includes probing the card, registering + * the interface operations table, and allocating/initializing the + * adapter structure + * - Set up the netlink socket + * - Create and start the main work queue + * - Register the device + * - Initialize firmware and hardware + * - Add logical interfaces + */ +int +nxpwifi_add_card(void *card, struct completion *fw_done, + struct nxpwifi_if_ops *if_ops, u8 iface_type, + struct device *dev) +{ + struct nxpwifi_adapter *adapter; + + if (nxpwifi_register(card, dev, if_ops, (void **)&adapter)) { + pr_err("%s: software init failed\n", __func__); + goto err_init_sw; + } + + nxpwifi_probe_of(adapter); + + adapter->iface_type =3D iface_type; + adapter->fw_done =3D fw_done; + + adapter->hw_status =3D NXPWIFI_HW_STATUS_INITIALIZING; + clear_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + init_waitqueue_head(&adapter->init_wait_q); + clear_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags); + adapter->hs_activated =3D false; + init_waitqueue_head(&adapter->hs_activate_wait_q); + init_waitqueue_head(&adapter->cmd_wait_q.wait); + adapter->cmd_wait_q.status =3D 0; + adapter->scan_wait_q_woken =3D false; + + if (num_possible_cpus() > 1) + adapter->rx_work_enabled =3D true; + + adapter->workqueue =3D + alloc_workqueue("NXPWIFI_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (!adapter->workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->main_work, nxpwifi_main_work_queue); + + if (adapter->rx_work_enabled) { + adapter->rx_workqueue =3D alloc_workqueue("NXPWIFI_RX_WORK_QUEUE", + WQ_HIGHPRI | + WQ_MEM_RECLAIM | + WQ_UNBOUND, 0); + if (!adapter->rx_workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->rx_work, nxpwifi_rx_work_queue); + } + + adapter->host_mlme_workqueue =3D + alloc_workqueue("NXPWIFI_HOST_MLME_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (!adapter->host_mlme_workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->host_mlme_work, nxpwifi_host_mlme_work_queue); + + /* Register the device. Fill up the private data structure with relevant + * information from the card. + */ + if (adapter->if_ops.register_dev(adapter)) { + pr_err("%s: failed to register nxpwifi device\n", __func__); + goto err_registerdev; + } + + if (nxpwifi_init_hw_fw(adapter, true)) { + pr_err("%s: firmware init failed\n", __func__); + goto err_init_fw; + } + + return 0; + +err_init_fw: + pr_debug("info: %s: unregister device\n", __func__); + if (adapter->if_ops.unregister_dev) + adapter->if_ops.unregister_dev(adapter); +err_registerdev: + set_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); + nxpwifi_terminate_workqueue(adapter); + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_READY) { + pr_debug("info: %s: shutdown nxpwifi\n", __func__); + nxpwifi_shutdown_drv(adapter); + nxpwifi_free_cmd_buffers(adapter); + } +err_kmalloc: + if (adapter->irq_wakeup >=3D 0) + device_init_wakeup(adapter->dev, false); + nxpwifi_free_adapter(adapter); + +err_init_sw: + + return -1; +} +EXPORT_SYMBOL_GPL(nxpwifi_add_card); + +/* This function removes the card. + * + * This function follows the following major steps to remove the device - + * - Stop data traffic + * - Shutdown firmware + * - Remove the logical interfaces + * - Terminate the work queue + * - Unregister the device + * - Free the adapter structure + */ +int nxpwifi_remove_card(struct nxpwifi_adapter *adapter) +{ + if (!adapter) + return 0; + + if (adapter->is_up) + nxpwifi_uninit_sw(adapter); + + if (adapter->irq_wakeup >=3D 0) + device_init_wakeup(adapter->dev, false); + + /* Unregister device */ + nxpwifi_dbg(adapter, INFO, + "info: unregister device\n"); + if (adapter->if_ops.unregister_dev) + adapter->if_ops.unregister_dev(adapter); + /* Free adapter structure */ + nxpwifi_dbg(adapter, INFO, + "info: free adapter\n"); + nxpwifi_free_adapter(adapter); + + return 0; +} +EXPORT_SYMBOL_GPL(nxpwifi_remove_card); + +void _nxpwifi_dbg(const struct nxpwifi_adapter *adapter, int mask, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (!(adapter->debug_mask & mask)) + return; + + va_start(args, fmt); + + vaf.fmt =3D fmt; + vaf.va =3D &args; + + if (adapter->dev) + dev_info(adapter->dev, "%pV", &vaf); + else + pr_info("%pV", &vaf); + + va_end(args); +} +EXPORT_SYMBOL_GPL(_nxpwifi_dbg); + +/* This function initializes the module. + * + * The debug FS is also initialized if configured. + */ +static int +nxpwifi_init_module(void) +{ +#ifdef CONFIG_DEBUG_FS + nxpwifi_debugfs_init(); +#endif + return 0; +} + +/* This function cleans up the module. + * + * The debug FS is removed if available. + */ +static void +nxpwifi_cleanup_module(void) +{ +#ifdef CONFIG_DEBUG_FS + nxpwifi_debugfs_remove(); +#endif +} + +module_init(nxpwifi_init_module); +module_exit(nxpwifi_cleanup_module); + +MODULE_AUTHOR("NXP International Ltd."); +MODULE_DESCRIPTION("NXP WiFi Driver version " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B21C173329; Fri, 21 Jun 2024 07:54:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956443; cv=fail; b=X826KtvYj05SrcDyN6JGjcmDMmCsFJ5TN6u/nCOtI1uO4QOBEPKxJvD1Y8/W4gvN7JzJC1aYXOjwzc1OlYdchGG6JqcuP9sPeex2W8XVEj7wtsFreoPBF2xQdWAB6pk+QO1QCHjmEoJx+UuVsfgtlJEEd+atIKF29arXAuIAGu8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956443; c=relaxed/simple; bh=mXnNF5MjrP0viIKumfX53Cj/AMAWGVZth38a3nmec8o=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=uc+XRuJFsDuCVygftJCy34IW3hCi+uZV+31JC2u/XiTlLV45XYeE26GrvhTrd6ZvYjdObon5j2cGOiytvC1Q+rcD4wgbMWiXF4taLmzZMGv1Ot+pbBLsnuAevr2KZ0I1sPdDwFQeyK9xByYY5ATyH0Z5po7W4vmH7Q+OvmjW9tk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=Eh1tFmcf; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="Eh1tFmcf" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Rs9DYhrHMOaLHycvfZQ5pNYAGWJVUX7jwmCRCPEG57jjjCvhgiLUT7Fe9aj+8PAj8KN+Ohaz68r5c0gKz+MvsUmiQGnotiO1hcZDEhIe8KWk5cIQGiUKy7dB+Z0UW3kOqNcv6ObbM9LY4r+9LcsO9M/vTWiK8Dx8xeR5w9jKECPyexEDV3MkBc5rgUufTCtBJnd//4wxJI7IQrwL7vM0cKytlbrkpGbm2nk0RzzsnT8EIua/iTgWqr7c9ct6cMkzKEik5j0S7cOXaiU9H/ijCar/ampn/rVx6ObRm0zWtJb/vl2sAb4uQA9gPtT/4pNyrZavyDnYOO3RTJEch8ZxlA== 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=G6DQdqzf3x6pio9nRUBYj3YNVCn1a4t1jjJ7TH+XZGo=; b=D3AAu4Mg7vDF9xl02Wj/J8ntzSZrR4ceI0b7Ut4EjZH0h1uVsDz374BUHzpD3VxUdx0MGH3n9V6ll0C48u6qMGy2tkz4B8RabrDAfyDUdVCZQT3Fv1iBNtYj9rtBO9RnxHQSO1Ei/543Qe5yJbMmCckUiu6yrf3IjjxTVsRkVQd7iJgk+gwL6mFrtfr8ca43OlHuEwamMORP8VIqAjlQatW4W9+kOR2/b+jOnNpKuR1RXcLSZi4wkC+E+cw7R1mQ2yvPcatCTqrGSknAYkcpM/gj8be+TtgXKnp3Yo74gz1rWpEZdL3jDR84AkUPcy+xav5WUeSluZ5xQDNz2uBOsA== 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=G6DQdqzf3x6pio9nRUBYj3YNVCn1a4t1jjJ7TH+XZGo=; b=Eh1tFmcfzjUpr9AJSSPb9MOAIpbh9eVL0DSmE2vz7fZm9IK+Z53T0e1QERByllw7Jo1Mgc6tdh825cUw1re+OidR4AZEO1DmPHH42lKHBDjN7ezBcwEJu8/ZYmI71VJW1evMOCF33KWbhnjf7JMmJuUwK16f0ZfBlYUkewiBhH8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:54 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:54 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 24/43] wifi: nxpwifi: add main.h Date: Fri, 21 Jun 2024 15:51:49 +0800 Message-Id: <20240621075208.513497-25-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 328d4097-d0c1-4b34-ec1e-08dc91c74bf1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?s4T3UIbZQkM06a/0yVaYcL936ON5jQFDj7rDMYUASAh7aTOydq4ZySjFob96?= =?us-ascii?Q?KzwjMAyt3aQrxpauk/iHyXPbOcagerMJR+8hYLV9eBzvFV2vpcbrmYPgHBVE?= =?us-ascii?Q?rvPpxM0iUiksBWGKBmlQ1B8LYJ1DAwGfd3UEY14/rIaiB/zYtPdLIWDrYSur?= =?us-ascii?Q?KN6/AYuMOsSNAiqDbXAcIbMWXRYxU0Izg4CRtazWQgS4fdogEn32JMi99K+H?= =?us-ascii?Q?Z8wjcNY7BjBrf+RBzHSBNVbq/6ZKC8YVIsWSsapy6ouh+uFlirxd5brYepX5?= =?us-ascii?Q?PgJxcD4rrUrEeQu5/l0W+m4bWq0cJ/Yd7kFY7xVvytslzjAWYdGPHlCN2lYj?= =?us-ascii?Q?XmymwMkHSYaoE62Juy89YLrp8UNrfzQmkdYeHBrN2lmI1y5yZN2OYXs3E5M5?= =?us-ascii?Q?7/QkQAPy9gPyhv50eJkVdOa6cRJetdmWUI9Mu/fKPDpLAyvqg5qM4P7S+OkJ?= =?us-ascii?Q?RSjsLAuv0WY+U69UWwRC78wfbTQNnKcthDPHbKbQy0xzCwVEJuUo915ovnt8?= =?us-ascii?Q?SqqJE5SpsVRZrwSMkUo3Dwf9Ru6pGJX+E0JIhBp+WM408S/+Drq99od97QyA?= =?us-ascii?Q?uyb25Wx0FmflRxRmNHOjMh7moLZOtIMZuOsaGv0h0E9PnaMp8RMBzwIr93Wx?= =?us-ascii?Q?9u5vIVrbF0p3gdvb70e/9e9F7tISy1MfbUKAgrEhnOBxMKcqXl49f6Tc4MvD?= =?us-ascii?Q?5eFyBO3bKVVX8SbbdbHpqduj0rl+vaJr0K7yDhphxh68ZtjUGIrVhXDNoZzs?= =?us-ascii?Q?+qf2KvCtVn8Zefr7ZDXrheG+Hr0VF7SOtxddPjLLYU/INvTlLtJGFq3WW290?= =?us-ascii?Q?gIG+hwjBfumkAjHHLvDsb0CmFIxZzokgYzvP8sHazBCkSQMeMM2LlLBsv5j6?= =?us-ascii?Q?sS3JJL2Qcf1bVRW2wWHfLDO29g224kWDNY6kYF2TI1zdm63JNyUyNfUi1aCi?= =?us-ascii?Q?i99uFfgeMnLflHX2NOnF2TyQUFQBIrMQgugkHsXqX4ht9PL+RcHxqOoSKALi?= =?us-ascii?Q?MqNtwjVECc19ZD77f1zdNQlYxKHNUXxAPdJssurjNbjowfOKC9DWKEVqypmd?= =?us-ascii?Q?+AoNttJQw1BOTMM4SLVNMcqFXm8oPaGBlKpOTdth6FFgF3u+fxY5idvKGRlc?= =?us-ascii?Q?Ufdy9USN/soa5IZOVPWyk8RCZtZDg6FTy6JryHQvBvA6pqa7Hi7AMXcvZ33o?= =?us-ascii?Q?53L/TkoqyvCBpXVwMZFRZqsOOiR27UvvKVWQ0GjH5NsJp5xeD+ydPJmz6t7d?= =?us-ascii?Q?PuynUJ6UE85+wLRfMGQqV11v5FRYRYyT2PnXTLeodj8XfrXlayjocZEqOFeZ?= =?us-ascii?Q?DkWrEfZvotmVz1tP+DuE/AgLtb1a2qnpX6cMYivRQrxFNNX3BiMmRlQAdOQc?= =?us-ascii?Q?YXmGajs=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?+8+4s/28lpAlVCTmWDH0P3Vky72OyLfrUVUw9+aaOFDGv3KjAHKazy9EALsW?= =?us-ascii?Q?4wNCnQVKRWs/S+sDF7DMmqwHUQY0i58ucuYnl+wGcmYk/dxZxqua+bp71X5i?= =?us-ascii?Q?oKtdHvtCFgF7hC6r4JKGrWcJZ/Jg+PTTF4gww1WA61miXXlaV1QG5WZL22xJ?= =?us-ascii?Q?UmPf+p9uPtHKqg8MYxNevRgbrTcaaEYKQYiasQt2BzDqk3ASYZtQBlwH6rba?= =?us-ascii?Q?p1N0814a1rI1CQIQ559XMxB6d+e7eMOvAA44UIJTG9oIWMhWffgxA/0KM7ey?= =?us-ascii?Q?R7cQ4XTrBx+s+nTsZXu8swAchnoW81o8XPaWAqlyxKR4zHDXky7lS8fQuQkD?= =?us-ascii?Q?2Zxc8CIkmb/TeZKFuEGkRUwuCb7LrCzmx1rlTQ3EKj6Ldx3yxp4jNyb6qy66?= =?us-ascii?Q?8MSR0XXSVRzvP5u+GKIr4bSpxtb0dsVniueYCKwIGI77XlhPQHk/Pg0fSSXo?= =?us-ascii?Q?zxwX2diNDmI64HLXfKJ6EQb5mpfLfC7RSInDs7JXLIjiKcA14qFf2w6QWR+X?= =?us-ascii?Q?s4HhVnA5IidaoyR/SIDcUcqbRG5/m7Qr7e4PdMk97VnVZfuUTVqmF2XarnaT?= =?us-ascii?Q?reyu4pzt0rpiQTJDbqufmf1Lm+qSdMVPGEj9h/BkwQh+u6EApvL7irsH7xbM?= =?us-ascii?Q?Zm4KZkvmClu+Iw3MiRkB1MP3K3E9ahQu/AwaVl60jHAWfm6cD4Z7oJZYpaqt?= =?us-ascii?Q?g1c4Wp7+LH1ruTUG3ncv1Q7CKbFUeHTPq9sjImrg2w4TKmmhG1aeepksFAao?= =?us-ascii?Q?KXhz7yDmtwDvzRc5EE1xdSGiUwErBCn03WsJDZtYfyc1p1hfZDaxavXQi7aU?= =?us-ascii?Q?zlLJRo36ApolFipBYpIf/R0nnLzhb5qU3mIT7ralvSqdTR/cFex9d+qDpkRk?= =?us-ascii?Q?kK3C1+yI+0OT6CBvXaYxLTpn6sO3U5Rirv+N1vVkc7gu0hxFmWivEXRd8iXp?= =?us-ascii?Q?dP/eknaDEPoSW6hW/SiVbUagHIffZQDNZAXXXalNjaIBn152M/mJ1dUnnqWG?= =?us-ascii?Q?Qa0mthPVJL9gK0sUMCc2msOUQo+mgL5wU6JWNmc7cnBQgSiV+PLzyM1S4b2I?= =?us-ascii?Q?LD1AOWnbG7mFi+h8XK5uJ5tayQBTZyTtt61JTTn/20szL6XScv2Zd00IQREt?= =?us-ascii?Q?ZcS+juE3jSHFIbSyq/O3zNwKY8x5TXrSbwlY9uYpyk/yn6t+CGVFVmtCV2xF?= =?us-ascii?Q?nWDjoAjRK57dafI/Yr3aaEcJIWnBl1GdXsHb1cuTJrVq61PlQNJ/+I/yBhm0?= =?us-ascii?Q?6CJT9a35g+LIAvWy3ZAX37EeaAmUgOxnr8tiJEYYTWo9PsGFYqVEquZ+uPtR?= =?us-ascii?Q?Y+gAhrBl49zKSsYZgHZKruMXnlbNqG18A1nFIw3O+GgnloDIVshvvAN1kUa8?= =?us-ascii?Q?qyxHbdh3MJtkLbhbK9/DZBi5x0fr0szb4SqOGb0FXKIafELLF1fmK07LCj2x?= =?us-ascii?Q?i/HvsvqGaciK955+28+x2dKNHwbX8gPilfLZyLXNFlB60sJ9luowzZHpcy7u?= =?us-ascii?Q?ZjCdrK8KkKGR5DT3zFQChjkkKkRssheHPX0WkLhBeh72V/JMaZbcibbC7yVj?= =?us-ascii?Q?xZr9hLkIjFRMB7MGHBeYn6m/nEj0Uo4BLs+sCEOs?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 328d4097-d0c1-4b34-ec1e-08dc91c74bf1 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:54.4401 (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: tsfzL58kOb97ER4wsX9+QmyWOa3/M0avtvessIN8oAslFibG+oVoNWilM0MuPylU2IqqMoWhR9XcAjh0snVzbQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/main.h | 1507 +++++++++++++++++++++++ 1 file changed, 1507 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/main.h diff --git a/drivers/net/wireless/nxp/nxpwifi/main.h b/drivers/net/wireless= /nxp/nxpwifi/main.h new file mode 100644 index 000000000000..e9878ea03d6e --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/main.h @@ -0,0 +1,1507 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: major data structures and prototypes + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_MAIN_H_ +#define _NXPWIFI_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "sdio.h" + +extern char driver_version[]; + +struct nxpwifi_adapter; +struct nxpwifi_private; + +enum { + NXPWIFI_ASYNC_CMD, + NXPWIFI_SYNC_CMD +}; + +#define NXPWIFI_MAX_AP 64 + +#define NXPWIFI_MAX_PKTS_TXQ 16 + +#define NXPWIFI_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) + +#define NXPWIFI_TIMER_10S 10000 +#define NXPWIFI_TIMER_1S 1000 + +#define MAX_TX_PENDING 400 +#define LOW_TX_PENDING 380 + +#define HIGH_RX_PENDING 50 +#define LOW_RX_PENDING 20 + +#define NXPWIFI_UPLD_SIZE (2312) + +#define MAX_EVENT_SIZE 2048 + +#define NXPWIFI_FW_DUMP_SIZE (2 * 1024 * 1024) + +#define ARP_FILTER_MAX_BUF_SIZE 68 + +#define NXPWIFI_KEY_BUFFER_SIZE 16 +#define NXPWIFI_DEFAULT_LISTEN_INTERVAL 10 +#define NXPWIFI_MAX_REGION_CODE 9 + +#define DEFAULT_BCN_AVG_FACTOR 8 +#define DEFAULT_DATA_AVG_FACTOR 8 + +#define FIRST_VALID_CHANNEL 0xff + +#define DEFAULT_BCN_MISS_TIMEOUT 5 + +#define MAX_SCAN_BEACON_BUFFER 8000 + +#define SCAN_BEACON_ENTRY_PAD 6 + +#define NXPWIFI_PASSIVE_SCAN_CHAN_TIME 110 +#define NXPWIFI_ACTIVE_SCAN_CHAN_TIME 40 +#define NXPWIFI_SPECIFIC_SCAN_CHAN_TIME 40 +#define NXPWIFI_DEF_SCAN_CHAN_GAP_TIME 50 + +#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) + +#define NXPWIFI_MAX_TOTAL_SCAN_TIME (NXPWIFI_TIMER_10S - NXPWIFI_TIMER_1S) + +#define WPA_GTK_OUI_OFFSET 2 +#define RSN_GTK_OUI_OFFSET 2 + +#define NXPWIFI_OUI_NOT_PRESENT 0 +#define NXPWIFI_OUI_PRESENT 1 + +#define PKT_TYPE_MGMT 0xE5 + +/* Do not check for data_received for USB, as data_received + * is handled in nxpwifi_usb_recv for USB + */ +#define IS_CARD_RX_RCVD(adapter) ({ \ + typeof(adapter) (_adapter) =3D adapter; \ + ((_adapter)->cmd_resp_received || \ + (_adapter)->event_received || \ + (_adapter)->data_received); \ + }) + +#define NXPWIFI_TYPE_CMD 1 +#define NXPWIFI_TYPE_DATA 0 +#define NXPWIFI_TYPE_AGGR_DATA 10 +#define NXPWIFI_TYPE_EVENT 3 + +#define MAX_BITMAP_RATES_SIZE 18 + +#define MAX_CHANNEL_BAND_BG 14 +#define MAX_CHANNEL_BAND_A 165 + +#define MAX_FREQUENCY_BAND_BG 2484 + +#define NXPWIFI_EVENT_HEADER_LEN 4 +#define NXPWIFI_UAP_EVENT_EXTRA_HEADER 2 + +#define NXPWIFI_TYPE_LEN 4 +#define NXPWIFI_USB_TYPE_CMD 0xF00DFACE +#define NXPWIFI_USB_TYPE_DATA 0xBEADC0DE +#define NXPWIFI_USB_TYPE_EVENT 0xBEEFFACE + +/* Threshold for tx_timeout_cnt before we trigger a card reset */ +#define TX_TIMEOUT_THRESHOLD 6 + +#define NXPWIFI_DRV_INFO_SIZE_MAX 0x40000 + +/* Address alignment */ +#define NXPWIFI_ALIGN_ADDR(p, a) ({ \ + typeof(a) (_a) =3D a; \ + (((long)(p) + (_a) - 1) & ~((_a) - 1)); \ + }) + +#define NXPWIFI_MAC_LOCAL_ADMIN_BIT 41 + +/** + *enum nxpwifi_debug_level - nxp wifi debug level + */ +enum NXPWIFI_DEBUG_LEVEL { + NXPWIFI_DBG_MSG =3D 0x00000001, + NXPWIFI_DBG_FATAL =3D 0x00000002, + NXPWIFI_DBG_ERROR =3D 0x00000004, + NXPWIFI_DBG_DATA =3D 0x00000008, + NXPWIFI_DBG_CMD =3D 0x00000010, + NXPWIFI_DBG_EVENT =3D 0x00000020, + NXPWIFI_DBG_INTR =3D 0x00000040, + NXPWIFI_DBG_IOCTL =3D 0x00000080, + + NXPWIFI_DBG_MPA_D =3D 0x00008000, + NXPWIFI_DBG_DAT_D =3D 0x00010000, + NXPWIFI_DBG_CMD_D =3D 0x00020000, + NXPWIFI_DBG_EVT_D =3D 0x00040000, + NXPWIFI_DBG_FW_D =3D 0x00080000, + NXPWIFI_DBG_IF_D =3D 0x00100000, + + NXPWIFI_DBG_ENTRY =3D 0x10000000, + NXPWIFI_DBG_WARN =3D 0x20000000, + NXPWIFI_DBG_INFO =3D 0x40000000, + NXPWIFI_DBG_DUMP =3D 0x80000000, + + NXPWIFI_DBG_ANY =3D 0xffffffff +}; + +#define NXPWIFI_DEFAULT_DEBUG_MASK (NXPWIFI_DBG_MSG | \ + NXPWIFI_DBG_FATAL | \ + NXPWIFI_DBG_ERROR) + +__printf(3, 4) +void _nxpwifi_dbg(const struct nxpwifi_adapter *adapter, int mask, + const char *fmt, ...); +#define nxpwifi_dbg(adapter, mask, fmt, ...) \ + _nxpwifi_dbg(adapter, NXPWIFI_DBG_##mask, fmt, ##__VA_ARGS__) + +#define DEBUG_DUMP_DATA_MAX_LEN 128 +#define nxpwifi_dbg_dump(adapter, dbg_mask, str, buf, len) \ +do { \ + if ((adapter)->debug_mask & NXPWIFI_DBG_##dbg_mask) \ + print_hex_dump(KERN_DEBUG, str, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, len, false); \ +} while (0) + +/** Min BGSCAN interval 15 second */ +#define NXPWIFI_BGSCAN_INTERVAL 15000 +/** default repeat count */ +#define NXPWIFI_BGSCAN_REPEAT_COUNT 6 + +struct nxpwifi_dbg { + u32 num_cmd_host_to_card_failure; + u32 num_cmd_sleep_cfm_host_to_card_failure; + u32 num_tx_host_to_card_failure; + u32 num_event_deauth; + u32 num_event_disassoc; + u32 num_event_link_lost; + u32 num_cmd_deauth; + u32 num_cmd_assoc_success; + u32 num_cmd_assoc_failure; + u32 num_tx_timeout; + u16 timeout_cmd_id; + u16 timeout_cmd_act; + u16 last_cmd_id[DBG_CMD_NUM]; + u16 last_cmd_act[DBG_CMD_NUM]; + u16 last_cmd_index; + u16 last_cmd_resp_id[DBG_CMD_NUM]; + u16 last_cmd_resp_index; + u16 last_event[DBG_CMD_NUM]; + u16 last_event_index; + u32 last_mp_wr_bitmap[NXPWIFI_DBG_SDIO_MP_NUM]; + u32 last_mp_wr_ports[NXPWIFI_DBG_SDIO_MP_NUM]; + u32 last_mp_wr_len[NXPWIFI_DBG_SDIO_MP_NUM]; + u32 last_mp_curr_wr_port[NXPWIFI_DBG_SDIO_MP_NUM]; + u8 last_sdio_mp_index; +}; + +enum NXPWIFI_HARDWARE_STATUS { + NXPWIFI_HW_STATUS_READY, + NXPWIFI_HW_STATUS_INITIALIZING, + NXPWIFI_HW_STATUS_INIT_DONE, + NXPWIFI_HW_STATUS_RESET, + NXPWIFI_HW_STATUS_NOT_READY +}; + +enum NXPWIFI_802_11_POWER_MODE { + NXPWIFI_802_11_POWER_MODE_CAM, + NXPWIFI_802_11_POWER_MODE_PSP +}; + +struct nxpwifi_tx_param { + u32 next_pkt_len; +}; + +enum NXPWIFI_PS_STATE { + PS_STATE_AWAKE, + PS_STATE_PRE_SLEEP, + PS_STATE_SLEEP_CFM, + PS_STATE_SLEEP +}; + +enum nxpwifi_iface_type { + NXPWIFI_SDIO +}; + +struct nxpwifi_add_ba_param { + u32 tx_win_size; + u32 rx_win_size; + u32 timeout; + u8 tx_amsdu; + u8 rx_amsdu; +}; + +struct nxpwifi_tx_aggr { + u8 ampdu_user; + u8 ampdu_ap; + u8 amsdu; +}; + +enum nxpwifi_ba_status { + BA_SETUP_NONE =3D 0, + BA_SETUP_INPROGRESS, + BA_SETUP_COMPLETE +}; + +struct nxpwifi_ra_list_tbl { + struct list_head list; + struct sk_buff_head skb_head; + u8 ra[ETH_ALEN]; + u32 is_11n_enabled; + u16 max_amsdu; + u16 ba_pkt_count; + u8 ba_packet_thr; + enum nxpwifi_ba_status ba_status; + u8 amsdu_in_ampdu; + u16 total_pkt_count; + bool tx_paused; +}; + +struct nxpwifi_tid_tbl { + struct list_head ra_list; +}; + +#define WMM_HIGHEST_PRIORITY 7 +#define HIGH_PRIO_TID 7 +#define LOW_PRIO_TID 0 +#define NO_PKT_PRIO_TID -1 +#define NXPWIFI_WMM_DRV_DELAY_MAX 510 + +struct nxpwifi_wmm_desc { + struct nxpwifi_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; + u32 packets_out[MAX_NUM_TID]; + u32 pkts_paused[MAX_NUM_TID]; + /* spin lock to protect ra_list */ + spinlock_t ra_list_spinlock; + struct nxpwifi_wmm_ac_status ac_status[IEEE80211_NUM_ACS]; + enum nxpwifi_wmm_ac_e ac_down_graded_vals[IEEE80211_NUM_ACS]; + u32 drv_pkt_delay_max; + u8 queue_priority[IEEE80211_NUM_ACS]; + u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ + /* Number of transmit packets queued */ + atomic_t tx_pkts_queued; + /* Tracks highest priority with a packet queued */ + atomic_t highest_queued_prio; +}; + +struct nxpwifi_802_11_security { + u8 wpa_enabled; + u8 wpa2_enabled; + u8 wep_enabled; + u32 authentication_mode; + u8 is_authtype_auto; + u32 encryption_mode; +}; + +struct ieee_types_header { + u8 element_id; + u8 len; +} __packed; + +struct ieee_types_vendor_specific { + struct ieee_types_vendor_header vend_hdr; + u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; +} __packed; + +struct ieee_types_generic { + struct ieee_types_header ieee_hdr; + u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; +} __packed; + +struct ieee_types_bss_co_2040 { + struct ieee_types_header ieee_hdr; + u8 bss_2040co; +} __packed; + +struct ieee_types_extcap { + struct ieee_types_header ieee_hdr; + u8 ext_capab[8]; +} __packed; + +struct ieee_types_vht_cap { + struct ieee_types_header ieee_hdr; + struct ieee80211_vht_cap vhtcap; +} __packed; + +struct ieee_types_vht_oper { + struct ieee_types_header ieee_hdr; + struct ieee80211_vht_operation vhtoper; +} __packed; + +struct ieee_types_aid { + struct ieee_types_header ieee_hdr; + u16 aid; +} __packed; + +struct nxpwifi_bssdescriptor { + u8 mac_address[ETH_ALEN]; + struct cfg80211_ssid ssid; + u32 privacy; + s32 rssi; + u32 channel; + u32 freq; + u16 beacon_period; + u8 erp_flags; + u32 bss_mode; + u8 supported_rates[NXPWIFI_SUPPORTED_RATES]; + u8 data_rates[NXPWIFI_SUPPORTED_RATES]; + /* Network band. + * BAND_B(0x01): 'b' band + * BAND_G(0x02): 'g' band + * BAND_A(0X04): 'a' band + */ + u16 bss_band; + u64 fw_tsf; + u64 timestamp; + union ieee_types_phy_param_set phy_param_set; + union ieee_types_ss_param_set ss_param_set; + u16 cap_info_bitmap; + struct ieee_types_wmm_parameter wmm_ie; + u8 disable_11n; + struct ieee80211_ht_cap *bcn_ht_cap; + u16 ht_cap_offset; + struct ieee80211_ht_operation *bcn_ht_oper; + u16 ht_info_offset; + u8 *bcn_bss_co_2040; + u16 bss_co_2040_offset; + u8 *bcn_ext_cap; + u16 ext_cap_offset; + struct ieee80211_vht_cap *bcn_vht_cap; + u16 vht_cap_offset; + struct ieee80211_vht_operation *bcn_vht_oper; + u16 vht_info_offset; + struct ieee_types_oper_mode_ntf *oper_mode; + u16 oper_mode_offset; + u8 disable_11ac; + struct ieee_types_vendor_specific *bcn_wpa_ie; + u16 wpa_offset; + struct ieee_types_generic *bcn_rsn_ie; + u16 rsn_offset; + struct ieee_types_generic *bcn_rsnx_ie; + u16 rsnx_offset; + u8 *beacon_buf; + u32 beacon_buf_size; + u8 sensed_11h; + u8 local_constraint; + u8 chan_sw_ie_present; +}; + +struct nxpwifi_current_bss_params { + struct nxpwifi_bssdescriptor bss_descriptor; + u8 wmm_enabled; + u8 wmm_uapsd_enabled; + u8 band; + u32 num_of_rates; + u8 data_rates[NXPWIFI_SUPPORTED_RATES]; +}; + +struct nxpwifi_sleep_period { + u16 period; + u16 reserved; +}; + +struct nxpwifi_wep_key { + u32 length; + u32 key_index; + u32 key_length; + u8 key_material[NXPWIFI_KEY_BUFFER_SIZE]; +}; + +#define MAX_REGION_CHANNEL_NUM 2 + +struct nxpwifi_chan_freq_power { + u16 channel; + u32 freq; + u16 max_tx_power; + u8 unsupported; +}; + +enum state_11d_t { + DISABLE_11D =3D 0, + ENABLE_11D =3D 1, +}; + +#define NXPWIFI_MAX_TRIPLET_802_11D 83 + +struct nxpwifi_802_11d_domain_reg { + u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; + u8 no_of_triplet; + struct ieee80211_country_ie_triplet + triplet[NXPWIFI_MAX_TRIPLET_802_11D]; +}; + +struct nxpwifi_vendor_spec_cfg_ie { + u16 mask; + u16 flag; + u8 ie[NXPWIFI_MAX_VSIE_LEN]; +}; + +struct wps { + u8 session_enable; +}; + +struct nxpwifi_roc_cfg { + u64 cookie; + struct ieee80211_channel chan; +}; + +enum nxpwifi_iface_work_flags { + NXPWIFI_IFACE_WORK_DEVICE_DUMP, + NXPWIFI_IFACE_WORK_CARD_RESET, +}; + +enum nxpwifi_adapter_work_flags { + NXPWIFI_SURPRISE_REMOVED, + NXPWIFI_IS_CMD_TIMEDOUT, + NXPWIFI_IS_SUSPENDED, + NXPWIFI_IS_HS_CONFIGURED, + NXPWIFI_IS_HS_ENABLING, + NXPWIFI_IS_REQUESTING_FW_VEREXT, +}; + +struct nxpwifi_band_config { + u8 chan_band:2; + u8 chan_width:2; + u8 chan2_offset:2; + u8 scan_mode:2; +} __packed; + +struct nxpwifi_channel_band { + struct nxpwifi_band_config band_config; + u8 channel; +}; + +struct nxpwifi_private { + struct nxpwifi_adapter *adapter; + u8 bss_type; + u8 bss_role; + 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; + u8 port_open; + u8 usb_port; + u32 num_tx_timeout; + /* track consecutive timeout */ + u8 tx_timeout_cnt; + struct net_device *netdev; + struct net_device_stats stats; + u32 curr_pkt_filter; + u32 bss_mode; + u32 pkt_tx_ctrl; + u16 tx_power_level; + u8 max_tx_power_level; + u8 min_tx_power_level; + u32 tx_ant; + u32 rx_ant; + u8 tx_rate; + u8 tx_htinfo; + u8 rxpd_htinfo; + u8 rxpd_rate; + u16 rate_bitmap; + u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; + u32 data_rate; + u8 is_data_rate_auto; + u16 bcn_avg_factor; + u16 data_avg_factor; + s16 data_rssi_last; + s16 data_nf_last; + s16 data_rssi_avg; + s16 data_nf_avg; + s16 bcn_rssi_last; + s16 bcn_nf_last; + s16 bcn_rssi_avg; + s16 bcn_nf_avg; + struct nxpwifi_bssdescriptor *attempted_bss_desc; + struct cfg80211_ssid prev_ssid; + u8 prev_bssid[ETH_ALEN]; + struct nxpwifi_current_bss_params curr_bss_params; + u16 beacon_period; + u8 dtim_period; + u16 listen_interval; + u16 atim_window; + struct nxpwifi_802_11_security sec_info; + struct nxpwifi_wep_key wep_key[NUM_WEP_KEYS]; + u16 wep_key_curr_index; + u8 wpa_ie[256]; + u16 wpa_ie_len; + u8 wpa_is_gtk_set; + struct host_cmd_ds_802_11_key_material aes_key; + u8 *wps_ie; + u16 wps_ie_len; + u8 wmm_required; + u8 wmm_enabled; + u8 wmm_qosinfo; + struct nxpwifi_wmm_desc wmm; + atomic_t wmm_tx_pending[IEEE80211_NUM_ACS]; + struct list_head sta_list; + /* spin lock for associated station list */ + spinlock_t sta_list_spinlock; + struct list_head tx_ba_stream_tbl_ptr; + /* spin lock for tx_ba_stream_tbl_ptr queue */ + spinlock_t tx_ba_stream_tbl_lock; + struct nxpwifi_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; + struct nxpwifi_add_ba_param add_ba_param; + u16 rx_seq[MAX_NUM_TID]; + u8 tos_to_tid_inv[MAX_NUM_TID]; + struct list_head rx_reorder_tbl_ptr; + /* spin lock for rx_reorder_tbl_ptr queue */ + spinlock_t rx_reorder_tbl_lock; +#define NXPWIFI_ASSOC_RSP_BUF_SIZE 500 + u8 assoc_rsp_buf[NXPWIFI_ASSOC_RSP_BUF_SIZE]; + u32 assoc_rsp_size; + struct cfg80211_bss *req_bss; + +#define NXPWIFI_GENIE_BUF_SIZE 256 + u8 gen_ie_buf[NXPWIFI_GENIE_BUF_SIZE]; + u8 gen_ie_buf_len; + + struct nxpwifi_vendor_spec_cfg_ie vs_ie[NXPWIFI_MAX_VSIE_NUM]; + +#define NXPWIFI_ASSOC_TLV_BUF_SIZE 256 + u8 assoc_tlv_buf[NXPWIFI_ASSOC_TLV_BUF_SIZE]; + u8 assoc_tlv_buf_len; + + u8 *curr_bcn_buf; + u32 curr_bcn_size; + /* spin lock for beacon buffer */ + spinlock_t curr_bcn_buf_lock; + struct wireless_dev wdev; + struct nxpwifi_chan_freq_power cfp; + u32 versionstrsel; + char version_str[NXPWIFI_VERSION_STR_LENGTH]; +#ifdef CONFIG_DEBUG_FS + struct dentry *dfs_dev_dir; +#endif + u16 current_key_index; + /* mutex for scan */ + struct mutex async_mutex; + struct cfg80211_scan_request *scan_request; + u8 cfg_bssid[6]; + struct wps wps; + u8 scan_block; + s32 cqm_rssi_thold; + u32 cqm_rssi_hyst; + u8 subsc_evt_rssi_state; + struct nxpwifi_ds_misc_subsc_evt async_subsc_evt_storage; + struct nxpwifi_ie mgmt_ie[MAX_MGMT_IE_INDEX]; + u16 beacon_idx; + u16 proberesp_idx; + u16 assocresp_idx; + u16 gen_idx; + u8 ap_11n_enabled; + u8 ap_11ac_enabled; + bool host_mlme_reg; + u32 mgmt_frame_mask; + struct nxpwifi_roc_cfg roc_cfg; + bool scan_aborting; + u8 sched_scanning; + u8 csa_chan; + unsigned long csa_expire_time; + u8 del_list_idx; + bool hs2_enabled; + struct nxpwifi_uap_bss_param bss_cfg; + struct cfg80211_chan_def bss_chandef; + struct station_parameters *sta_params; + struct idr ack_status_frames; + /* spin lock for ack status */ + spinlock_t ack_status_lock; + /** rx histogram data */ + struct nxpwifi_histogram_data *hist_data; + struct cfg80211_chan_def dfs_chandef; + struct workqueue_struct *dfs_cac_workqueue; + struct delayed_work dfs_cac_work; + struct workqueue_struct *dfs_chan_sw_workqueue; + struct delayed_work dfs_chan_sw_work; + bool uap_stop_tx; + struct cfg80211_beacon_data beacon_after; + struct nxpwifi_11h_intf_state state_11h; + struct nxpwifi_ds_mem_rw mem_rw; + struct sk_buff_head bypass_txq; + struct nxpwifi_user_scan_chan hidden_chan[NXPWIFI_USER_SCAN_CHAN_MAX]; + u8 assoc_resp_ht_param; + bool ht_param_present; +}; + +struct nxpwifi_tx_ba_stream_tbl { + struct list_head list; + int tid; + u8 ra[ETH_ALEN]; + enum nxpwifi_ba_status ba_status; + u8 amsdu; +}; + +struct nxpwifi_rx_reorder_tbl; + +struct reorder_tmr_cnxt { + struct timer_list timer; + struct nxpwifi_rx_reorder_tbl *ptr; + struct nxpwifi_private *priv; + u8 timer_is_set; +}; + +struct nxpwifi_rx_reorder_tbl { + struct list_head list; + int tid; + u8 ta[ETH_ALEN]; + int init_win; + int start_win; + int win_size; + void **rx_reorder_ptr; + struct reorder_tmr_cnxt timer_context; + u8 amsdu; + u8 flags; +}; + +struct nxpwifi_bss_prio_node { + struct list_head list; + struct nxpwifi_private *priv; +}; + +struct nxpwifi_bss_prio_tbl { + struct list_head bss_prio_head; + /* spin lock for bss priority */ + spinlock_t bss_prio_lock; + struct nxpwifi_bss_prio_node *bss_prio_cur; +}; + +struct cmd_ctrl_node { + struct list_head list; + struct nxpwifi_private *priv; + u32 cmd_no; + u32 cmd_flag; + struct sk_buff *cmd_skb; + struct sk_buff *resp_skb; + void *data_buf; + u32 wait_q_enabled; + struct sk_buff *skb; + u8 *condition; + u8 cmd_wait_q_woken; + int (*cmd_resp)(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf); +}; + +struct nxpwifi_bss_priv { + u8 band; + u64 fw_tsf; +}; + +struct nxpwifi_station_stats { + u64 last_rx; + s8 rssi; + u64 rx_bytes; + u64 tx_bytes; + u32 rx_packets; + u32 tx_packets; + u32 tx_failed; + u8 last_tx_rate; + u8 last_tx_htinfo; +}; + +/* This is AP specific structure which stores information + * about associated/peer STA + */ +struct nxpwifi_sta_node { + struct list_head list; + u8 mac_addr[ETH_ALEN]; + u8 is_wmm_enabled; + u8 is_11n_enabled; + u8 is_11ac_enabled; + u8 ampdu_sta[MAX_NUM_TID]; + u16 rx_seq[MAX_NUM_TID]; + u16 max_amsdu; + struct nxpwifi_station_stats stats; + u8 tx_pause; +}; + +#define NXPWIFI_TYPE_AGGR_DATA_V2 11 +#define NXPWIFI_BUS_AGGR_MODE_LEN_V2 (2) +#define NXPWIFI_BUS_AGGR_MAX_LEN 16000 +#define NXPWIFI_BUS_AGGR_MAX_NUM 10 +struct bus_aggr_params { + u16 enable; + u16 mode; + u16 tx_aggr_max_size; + u16 tx_aggr_max_num; + u16 tx_aggr_align; +}; + +struct nxpwifi_if_ops { + int (*init_if)(struct nxpwifi_adapter *adapter); + void (*cleanup_if)(struct nxpwifi_adapter *adapter); + int (*check_fw_status)(struct nxpwifi_adapter *adapter, u32 poll_num); + int (*check_winner_status)(struct nxpwifi_adapter *adapter); + int (*prog_fw)(struct nxpwifi_adapter *adapter, + struct nxpwifi_fw_image *fw); + int (*register_dev)(struct nxpwifi_adapter *adapter); + void (*unregister_dev)(struct nxpwifi_adapter *adapter); + int (*enable_int)(struct nxpwifi_adapter *adapter); + void (*disable_int)(struct nxpwifi_adapter *adapter); + int (*process_int_status)(struct nxpwifi_adapter *adapter); + int (*host_to_card)(struct nxpwifi_adapter *adapter, u8 type, + struct sk_buff *skb, + struct nxpwifi_tx_param *tx_param); + int (*wakeup)(struct nxpwifi_adapter *adapter); + int (*wakeup_complete)(struct nxpwifi_adapter *adapter); + + /* Interface specific functions */ + void (*update_mp_end_port)(struct nxpwifi_adapter *adapter, u16 port); + void (*cleanup_mpa_buf)(struct nxpwifi_adapter *adapter); + int (*cmdrsp_complete)(struct nxpwifi_adapter *adapter, + struct sk_buff *skb); + int (*event_complete)(struct nxpwifi_adapter *adapter, + struct sk_buff *skb); + int (*dnld_fw)(struct nxpwifi_adapter *adapter, + struct nxpwifi_fw_image *fw); + void (*card_reset)(struct nxpwifi_adapter *adapter); + int (*reg_dump)(struct nxpwifi_adapter *adapter, char *drv_buf); + void (*device_dump)(struct nxpwifi_adapter *adapter); + void (*iface_work)(struct work_struct *work); + void (*deaggr_pkt)(struct nxpwifi_adapter *adapter, + struct sk_buff *skb); + bool (*is_port_ready)(struct nxpwifi_private *adapter); + void (*up_dev)(struct nxpwifi_adapter *adapter); +}; + +struct nxpwifi_adapter { + u8 iface_type; + unsigned int debug_mask; + struct nxpwifi_iface_comb iface_limit; + struct nxpwifi_iface_comb curr_iface_comb; + struct nxpwifi_private *priv[NXPWIFI_MAX_BSS_NUM]; + u8 priv_num; + const struct firmware *firmware; + char fw_name[32]; + int winner; + struct device *dev; + struct wiphy *wiphy; + u8 perm_addr[ETH_ALEN]; + unsigned long work_flags; + u32 fw_release_number; + u8 intf_hdr_len; + u16 init_wait_q_woken; + wait_queue_head_t init_wait_q; + void *card; + struct nxpwifi_if_ops if_ops; + atomic_t bypass_tx_pending; + atomic_t rx_pending; + atomic_t tx_pending; + atomic_t cmd_pending; + atomic_t tx_hw_pending; + struct workqueue_struct *workqueue; + struct work_struct main_work; + struct workqueue_struct *rx_workqueue; + struct work_struct rx_work; + struct workqueue_struct *host_mlme_workqueue; + struct work_struct host_mlme_work; + bool rx_work_enabled; + bool rx_processing; + bool delay_main_work; + bool rx_locked; + bool main_locked; + struct nxpwifi_bss_prio_tbl bss_prio_tbl[NXPWIFI_MAX_BSS_NUM]; + /* spin lock for main process */ + spinlock_t main_proc_lock; + u32 nxpwifi_processing; + u8 more_task_flag; + u16 tx_buf_size; + u16 curr_tx_buf_size; + /* sdio single port rx aggregation capability */ + bool host_disable_sdio_rx_aggr; + bool sdio_rx_aggr_enable; + u16 sdio_rx_block_size; + u32 ioport; + enum NXPWIFI_HARDWARE_STATUS hw_status; + u16 number_of_antenna; + u32 fw_cap_info; + /* spin lock for interrupt handling */ + spinlock_t int_lock; + u8 int_status; + u32 event_cause; + struct sk_buff *event_skb; + u8 upld_buf[NXPWIFI_UPLD_SIZE]; + u8 data_sent; + u8 cmd_sent; + u8 cmd_resp_received; + u8 event_received; + u8 data_received; + u8 assoc_resp_received; + struct nxpwifi_private *priv_link_lost; + u8 host_mlme_link_lost; + u16 seq_num; + struct cmd_ctrl_node *cmd_pool; + struct cmd_ctrl_node *curr_cmd; + /* spin lock for command */ + spinlock_t nxpwifi_cmd_lock; + u16 last_init_cmd; + struct timer_list cmd_timer; + struct list_head cmd_free_q; + /* spin lock for cmd_free_q */ + spinlock_t cmd_free_q_lock; + struct list_head cmd_pending_q; + /* spin lock for cmd_pending_q */ + spinlock_t cmd_pending_q_lock; + struct list_head scan_pending_q; + /* spin lock for scan_pending_q */ + spinlock_t scan_pending_q_lock; + /* spin lock for RX processing routine */ + spinlock_t rx_proc_lock; + struct sk_buff_head tx_data_q; + atomic_t tx_queued; + u32 scan_processing; + u16 region_code; + struct nxpwifi_802_11d_domain_reg domain_reg; + u16 scan_probes; + u32 scan_mode; + u16 specific_scan_time; + u16 active_scan_time; + u16 passive_scan_time; + u16 scan_chan_gap_time; + u8 fw_bands; + u8 config_bands; + u8 tx_lock_flag; + struct nxpwifi_sleep_period sleep_period; + u16 ps_mode; + u32 ps_state; + u8 need_to_wakeup; + u16 multiple_dtim; + u16 local_listen_interval; + u16 null_pkt_interval; + struct sk_buff *sleep_cfm; + u16 bcn_miss_time_out; + u8 is_deep_sleep; + u8 delay_null_pkt; + u16 delay_to_ps; + u16 enhanced_ps_mode; + u8 pm_wakeup_card_req; + u16 gen_null_pkt; + u16 pps_uapsd_mode; + u32 pm_wakeup_fw_try; + struct timer_list wakeup_timer; + struct nxpwifi_hs_config_param hs_cfg; + u8 hs_activated; + u8 hs_activated_manually; + u16 hs_activate_wait_q_woken; + wait_queue_head_t hs_activate_wait_q; + u8 event_body[MAX_EVENT_SIZE]; + u32 hw_dot_11n_dev_cap; + u8 hw_dev_mcs_support; + u8 user_dev_mcs_support; + u8 sec_chan_offset; + struct nxpwifi_dbg dbg; + u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; + u32 arp_filter_size; + struct nxpwifi_wait_queue cmd_wait_q; + u8 scan_wait_q_woken; + spinlock_t queue_lock; /* lock for tx queues */ + u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; + u16 max_mgmt_ie_index; + const struct firmware *cal_data; + struct device_node *dt_node; + + /* 11AC */ + u32 is_hw_11ac_capable; + u32 hw_dot_11ac_dev_cap; + u32 hw_dot_11ac_mcs_support; + u32 usr_dot_11ac_dev_cap_bg; + u32 usr_dot_11ac_dev_cap_a; + u32 usr_dot_11ac_mcs_support; + + atomic_t pending_bridged_pkts; + + /* For synchronizing FW initialization with device lifecycle. */ + struct completion *fw_done; + bool is_up; + + bool ext_scan; + u8 fw_api_ver; + u8 key_api_major_ver, key_api_minor_ver; + u8 max_sta_conn; + struct memory_type_mapping *mem_type_mapping_tbl; + u8 num_mem_types; + bool scan_chan_gap_enabled; + struct sk_buff_head rx_data_q; + struct nxpwifi_chan_stats *chan_stats; + u32 num_in_chan_stats; + int survey_idx; + u8 coex_scan; + u8 coex_min_scan_time; + u8 coex_max_scan_time; + u8 coex_win_size; + u8 coex_tx_win_size; + u8 coex_rx_win_size; + u8 active_scan_triggered; + bool usb_mc_status; + bool usb_mc_setup; + struct cfg80211_wowlan_nd_info *nd_info; + struct ieee80211_regdomain *regd; + + /* Wake-on-WLAN (WoWLAN) */ + int irq_wakeup; + bool wake_by_wifi; + /* Aggregation parameters*/ + struct bus_aggr_params bus_aggr; + /* Device dump data/length */ + void *devdump_data; + int devdump_len; + struct delayed_work devdump_work; + + bool ignore_btcoex_events; +}; + +void nxpwifi_process_tx_queue(struct nxpwifi_adapter *adapter); + +int nxpwifi_init_lock_list(struct nxpwifi_adapter *adapter); + +void nxpwifi_set_trans_start(struct net_device *dev); + +void nxpwifi_stop_net_dev_queue(struct net_device *netdev, + struct nxpwifi_adapter *adapter); + +void nxpwifi_wake_up_net_dev_queue(struct net_device *netdev, + struct nxpwifi_adapter *adapter); + +int nxpwifi_init_priv(struct nxpwifi_private *priv); +void nxpwifi_free_priv(struct nxpwifi_private *priv); + +int nxpwifi_init_fw(struct nxpwifi_adapter *adapter); + +int nxpwifi_init_fw_complete(struct nxpwifi_adapter *adapter); + +void nxpwifi_shutdown_drv(struct nxpwifi_adapter *adapter); + +int nxpwifi_dnld_fw(struct nxpwifi_adapter *adapter, + struct nxpwifi_fw_image *fw); + +int nxpwifi_recv_packet(struct nxpwifi_private *priv, struct sk_buff *skb); +int nxpwifi_uap_recv_packet(struct nxpwifi_private *priv, + struct sk_buff *skb); + +void nxpwifi_host_mlme_disconnect(struct nxpwifi_private *priv, + u16 reason_code, u8 *sa); + +int nxpwifi_process_mgmt_packet(struct nxpwifi_private *priv, + struct sk_buff *skb); + +int nxpwifi_complete_cmd(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node); + +void nxpwifi_cmd_timeout_func(struct timer_list *t); + +int nxpwifi_get_debug_info(struct nxpwifi_private *priv, + struct nxpwifi_debug_info *info); + +int nxpwifi_alloc_cmd_buffer(struct nxpwifi_adapter *adapter); +void nxpwifi_free_cmd_buffer(struct nxpwifi_adapter *adapter); +void nxpwifi_free_cmd_buffers(struct nxpwifi_adapter *adapter); +void nxpwifi_cancel_all_pending_cmd(struct nxpwifi_adapter *adapter); +void nxpwifi_cancel_pending_scan_cmd(struct nxpwifi_adapter *adapter); +void nxpwifi_cancel_scan(struct nxpwifi_adapter *adapter); + +void nxpwifi_recycle_cmd_node(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node); + +void nxpwifi_insert_cmd_to_pending_q(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node); + +int nxpwifi_exec_next_cmd(struct nxpwifi_adapter *adapter); +int nxpwifi_process_cmdresp(struct nxpwifi_adapter *adapter); +void nxpwifi_process_assoc_resp(struct nxpwifi_adapter *adapter); +int nxpwifi_handle_rx_packet(struct nxpwifi_adapter *adapter, + struct sk_buff *skb); +int nxpwifi_process_tx(struct nxpwifi_private *priv, struct sk_buff *skb, + struct nxpwifi_tx_param *tx_param); +int nxpwifi_send_null_packet(struct nxpwifi_private *priv, u8 flags); +int nxpwifi_write_data_complete(struct nxpwifi_adapter *adapter, + struct sk_buff *skb, int aggr, int status); +void nxpwifi_clean_txrx(struct nxpwifi_private *priv); +u8 nxpwifi_check_last_packet_indication(struct nxpwifi_private *priv); +void nxpwifi_check_ps_cond(struct nxpwifi_adapter *adapter); +void nxpwifi_process_sleep_confirm_resp(struct nxpwifi_adapter *adapter, + u8 *pbuf, u32 upld_len); +void nxpwifi_process_hs_config(struct nxpwifi_adapter *adapter); +void nxpwifi_hs_activated_event(struct nxpwifi_private *priv, + u8 activated); +int nxpwifi_set_hs_params(struct nxpwifi_private *priv, u16 action, + int cmd_type, struct nxpwifi_ds_hs_cfg *hs_cfg); +int nxpwifi_ret_802_11_hs_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp); +int nxpwifi_process_rx_packet(struct nxpwifi_private *priv, + struct sk_buff *skb); +int nxpwifi_process_sta_rx_packet(struct nxpwifi_private *priv, + struct sk_buff *skb); +int nxpwifi_process_uap_rx_packet(struct nxpwifi_private *priv, + struct sk_buff *skb); +int nxpwifi_handle_uap_rx_forward(struct nxpwifi_private *priv, + struct sk_buff *skb); +void nxpwifi_delete_all_station_list(struct nxpwifi_private *priv); +void nxpwifi_wmm_del_peer_ra_list(struct nxpwifi_private *priv, + const u8 *ra_addr); +void nxpwifi_process_sta_txpd(struct nxpwifi_private *priv, + struct sk_buff *skb); +void nxpwifi_process_uap_txpd(struct nxpwifi_private *priv, + struct sk_buff *skb); +int nxpwifi_cmd_802_11_scan(struct host_cmd_ds_command *cmd, + struct nxpwifi_scan_cmd_config *scan_cfg); +void nxpwifi_queue_scan_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node); +int nxpwifi_ret_802_11_scan(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp); +int nxpwifi_associate(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc); +int nxpwifi_cmd_802_11_associate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + struct nxpwifi_bssdescriptor *bss_desc); +int nxpwifi_ret_802_11_associate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp); +u8 nxpwifi_band_to_radio_type(u8 band); +int nxpwifi_deauthenticate(struct nxpwifi_private *priv, u8 *mac); +void nxpwifi_deauthenticate_all(struct nxpwifi_adapter *adapter); +int nxpwifi_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); +struct nxpwifi_chan_freq_power *nxpwifi_get_cfp(struct nxpwifi_private *pr= iv, + u8 band, u16 channel, u32 freq); +u32 nxpwifi_index_to_data_rate(struct nxpwifi_private *priv, + u8 index, u8 ht_info); +u32 nxpwifi_index_to_acs_data_rate(struct nxpwifi_private *priv, + u8 index, u8 ht_info); +int nxpwifi_cmd_append_vsie_tlv(struct nxpwifi_private *priv, u16 vsie_mas= k, + u8 **buffer); +u32 nxpwifi_get_active_data_rates(struct nxpwifi_private *priv, + u8 *rates); +u32 nxpwifi_get_supported_rates(struct nxpwifi_private *priv, u8 *rates); +u32 nxpwifi_get_rates_from_cfg80211(struct nxpwifi_private *priv, + u8 *rates, u8 radio_type); +u8 nxpwifi_is_rate_auto(struct nxpwifi_private *priv); +extern u16 region_code_index[NXPWIFI_MAX_REGION_CODE]; +void nxpwifi_save_curr_bcn(struct nxpwifi_private *priv); +void nxpwifi_free_curr_bcn(struct nxpwifi_private *priv); +int is_command_pending(struct nxpwifi_adapter *adapter); +void nxpwifi_init_priv_params(struct nxpwifi_private *priv, + struct net_device *dev); +void nxpwifi_set_ba_params(struct nxpwifi_private *priv); +void nxpwifi_update_ampdu_txwinsize(struct nxpwifi_adapter *pmadapter); +void nxpwifi_set_11ac_ba_params(struct nxpwifi_private *priv); +int nxpwifi_cmd_802_11_scan_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int nxpwifi_ret_802_11_scan_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp); +int nxpwifi_handle_event_ext_scan_report(struct nxpwifi_private *priv, + void *buf); +int nxpwifi_cmd_802_11_bg_scan_config(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int nxpwifi_stop_bg_scan(struct nxpwifi_private *priv); + +/* This function checks if the queuing is RA based or not. + */ +static inline u8 +nxpwifi_queuing_ra_based(struct nxpwifi_private *priv) +{ + /* Currently we assume if we are in Infra, then DA=3DRA. This might not be + * true in the future + */ + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION && + (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA)) + return false; + + return true; +} + +/* This function copies rates. + */ +static inline u32 +nxpwifi_copy_rates(u8 *dest, u32 pos, u8 *src, int len) +{ + int i; + + for (i =3D 0; i < len && src[i]; i++, pos++) { + if (pos >=3D NXPWIFI_SUPPORTED_RATES) + break; + dest[pos] =3D src[i]; + } + + return pos; +} + +/* This function returns the correct private structure pointer based + * upon the BSS type and BSS number. + */ +static inline struct nxpwifi_private * +nxpwifi_get_priv_by_id(struct nxpwifi_adapter *adapter, + u8 bss_num, u8 bss_type) +{ + int i; + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + if (adapter->priv[i]->bss_num =3D=3D bss_num && + adapter->priv[i]->bss_type =3D=3D bss_type) + break; + } + } + return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); +} + +/* This function returns the first available private structure pointer + * based upon the BSS role. + */ +static inline struct nxpwifi_private * +nxpwifi_get_priv(struct nxpwifi_adapter *adapter, + enum nxpwifi_bss_role bss_role) +{ + int i; + + for (i =3D 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + if (bss_role =3D=3D NXPWIFI_BSS_ROLE_ANY || + GET_BSS_ROLE(adapter->priv[i]) =3D=3D bss_role) + break; + } + } + + return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); +} + +/* This function checks available bss_num when adding new interface or + * changing interface type. + */ +static inline u8 +nxpwifi_get_unused_bss_num(struct nxpwifi_adapter *adapter, u8 bss_type) +{ + u8 i, j; + int index[NXPWIFI_MAX_BSS_NUM]; + + memset(index, 0, sizeof(index)); + for (i =3D 0; i < adapter->priv_num; i++) + if (adapter->priv[i]) { + if (adapter->priv[i]->bss_type =3D=3D bss_type && + !(adapter->priv[i]->bss_mode =3D=3D + NL80211_IFTYPE_UNSPECIFIED)) { + index[adapter->priv[i]->bss_num] =3D 1; + } + } + for (j =3D 0; j < NXPWIFI_MAX_BSS_NUM; j++) + if (!index[j]) + return j; + return -1; +} + +/* This function returns the first available unused private structure poin= ter. + */ +static inline struct nxpwifi_private * +nxpwifi_get_unused_priv_by_bss_type(struct nxpwifi_adapter *adapter, + u8 bss_type) +{ + u8 i; + + for (i =3D 0; i < adapter->priv_num; i++) + if (adapter->priv[i]->bss_mode =3D=3D + NL80211_IFTYPE_UNSPECIFIED) { + adapter->priv[i]->bss_num =3D + nxpwifi_get_unused_bss_num(adapter, bss_type); + break; + } + + return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); +} + +/* This function returns the driver private structure of a network device. + */ +static inline struct nxpwifi_private * +nxpwifi_netdev_get_priv(struct net_device *dev) +{ + return (struct nxpwifi_private *)(*(unsigned long *)netdev_priv(dev)); +} + +/* This function checks if a skb holds a management frame. + */ +static inline bool nxpwifi_is_skb_mgmt_frame(struct sk_buff *skb) +{ + return (get_unaligned_le32(skb->data) =3D=3D PKT_TYPE_MGMT); +} + +/* This function retrieves channel closed for operation by Channel + * Switch Announcement. + */ +static inline u8 +nxpwifi_11h_get_csa_closed_channel(struct nxpwifi_private *priv) +{ + if (!priv->csa_chan) + return 0; + + /* Clear csa channel, if DFS channel move time has passed */ + if (time_after(jiffies, priv->csa_expire_time)) { + priv->csa_chan =3D 0; + priv->csa_expire_time =3D 0; + } + + return priv->csa_chan; +} + +static inline u8 nxpwifi_is_any_intf_active(struct nxpwifi_private *priv) +{ + struct nxpwifi_private *priv_num; + int i; + + for (i =3D 0; i < priv->adapter->priv_num; i++) { + priv_num =3D priv->adapter->priv[i]; + if (priv_num) { + if ((GET_BSS_ROLE(priv_num) =3D=3D NXPWIFI_BSS_ROLE_UAP && + priv_num->bss_started) || + (GET_BSS_ROLE(priv_num) =3D=3D NXPWIFI_BSS_ROLE_STA && + priv_num->media_connected)) + return 1; + } + } + + return 0; +} + +/* Disable platform specific wakeup interrupt */ +static inline void nxpwifi_disable_wake(struct nxpwifi_adapter *adapter) +{ + if (adapter->irq_wakeup >=3D 0) { + disable_irq_wake(adapter->irq_wakeup); + disable_irq(adapter->irq_wakeup); + if (adapter->wake_by_wifi) + /* Undo our disable, since interrupt handler already + * did this. + */ + enable_irq(adapter->irq_wakeup); + } +} + +/* Enable platform specific wakeup interrupt */ +static inline void nxpwifi_enable_wake(struct nxpwifi_adapter *adapter) +{ + /* Enable platform specific wakeup interrupt */ + if (adapter->irq_wakeup >=3D 0) { + adapter->wake_by_wifi =3D false; + enable_irq(adapter->irq_wakeup); + enable_irq_wake(adapter->irq_wakeup); + } +} + +int nxpwifi_init_shutdown_fw(struct nxpwifi_private *priv, + u32 func_init_shutdown); + +int nxpwifi_add_card(void *card, struct completion *fw_done, + struct nxpwifi_if_ops *if_ops, u8 iface_type, + struct device *dev); +int nxpwifi_remove_card(struct nxpwifi_adapter *adapter); + +void nxpwifi_get_version(struct nxpwifi_adapter *adapter, char *version, + int maxlen); +int +nxpwifi_request_set_multicast_list(struct nxpwifi_private *priv, + struct nxpwifi_multicast_list *mcast_list); +int nxpwifi_copy_mcast_addr(struct nxpwifi_multicast_list *mlist, + struct net_device *dev); +int nxpwifi_wait_queue_complete(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_queued); +int nxpwifi_bss_start(struct nxpwifi_private *priv, struct cfg80211_bss *b= ss, + struct cfg80211_ssid *req_ssid); +int nxpwifi_cancel_hs(struct nxpwifi_private *priv, int cmd_type); +int nxpwifi_enable_hs(struct nxpwifi_adapter *adapter); +int nxpwifi_disable_auto_ds(struct nxpwifi_private *priv); +int nxpwifi_drv_get_data_rate(struct nxpwifi_private *priv, u32 *rate); +int nxpwifi_request_scan(struct nxpwifi_private *priv, + struct cfg80211_ssid *req_ssid); +int nxpwifi_scan_networks(struct nxpwifi_private *priv, + const struct nxpwifi_user_scan_cfg *user_scan_in); +int nxpwifi_set_radio(struct nxpwifi_private *priv, u8 option); + +int nxpwifi_set_encode(struct nxpwifi_private *priv, struct key_params *kp, + const u8 *key, int key_len, u8 key_index, + const u8 *mac_addr, int disable); + +int nxpwifi_set_gen_ie(struct nxpwifi_private *priv, const u8 *ie, int ie_= len); + +int nxpwifi_get_ver_ext(struct nxpwifi_private *priv, u32 version_str_sel); + +int nxpwifi_remain_on_chan_cfg(struct nxpwifi_private *priv, u16 action, + struct ieee80211_channel *chan, + unsigned int duration); + +int nxpwifi_get_stats_info(struct nxpwifi_private *priv, + struct nxpwifi_ds_get_stats *log); + +int nxpwifi_reg_write(struct nxpwifi_private *priv, u32 reg_type, + u32 reg_offset, u32 reg_value); + +int nxpwifi_reg_read(struct nxpwifi_private *priv, u32 reg_type, + u32 reg_offset, u32 *value); + +int nxpwifi_eeprom_read(struct nxpwifi_private *priv, u16 offset, u16 byte= s, + u8 *value); + +int nxpwifi_set_11n_httx_cfg(struct nxpwifi_private *priv, int data); + +int nxpwifi_get_11n_httx_cfg(struct nxpwifi_private *priv, int *data); + +int nxpwifi_set_tx_rate_cfg(struct nxpwifi_private *priv, int tx_rate_inde= x); + +int nxpwifi_get_tx_rate_cfg(struct nxpwifi_private *priv, int *tx_rate_ind= ex); + +int nxpwifi_drv_set_power(struct nxpwifi_private *priv, u32 *ps_mode); + +int nxpwifi_drv_get_driver_version(struct nxpwifi_adapter *adapter, + char *version, int max_len); + +int nxpwifi_set_tx_power(struct nxpwifi_private *priv, + struct nxpwifi_power_cfg *power_cfg); + +int nxpwifi_main_process(struct nxpwifi_adapter *adapter); + +int nxpwifi_queue_tx_pkt(struct nxpwifi_private *priv, struct sk_buff *skb= ); + +int nxpwifi_get_bss_info(struct nxpwifi_private *priv, + struct nxpwifi_bss_info *info); +int nxpwifi_fill_new_bss_desc(struct nxpwifi_private *priv, + struct cfg80211_bss *bss, + struct nxpwifi_bssdescriptor *bss_desc); +int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter, + struct nxpwifi_bssdescriptor *bss_entry); +int nxpwifi_check_network_compatibility(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc); + +u8 nxpwifi_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_typ= e); +u8 nxpwifi_get_chan_type(struct nxpwifi_private *priv); + +struct wireless_dev *nxpwifi_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params); +int nxpwifi_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wde= v); + +int nxpwifi_add_wowlan_magic_pkt_filter(struct nxpwifi_adapter *adapter); + +int nxpwifi_set_mgmt_ies(struct nxpwifi_private *priv, + struct cfg80211_beacon_data *data); +int nxpwifi_del_mgmt_ies(struct nxpwifi_private *priv); +u8 *nxpwifi_11d_code_2_region(u8 code); +void nxpwifi_init_11h_params(struct nxpwifi_private *priv); +int nxpwifi_is_11h_active(struct nxpwifi_private *priv); +int nxpwifi_11h_activate(struct nxpwifi_private *priv, bool flag); +void nxpwifi_11h_process_join(struct nxpwifi_private *priv, u8 **buffer, + struct nxpwifi_bssdescriptor *bss_desc); +int nxpwifi_11h_handle_event_chanswann(struct nxpwifi_private *priv); +void nxpwifi_dnld_txpwr_table(struct nxpwifi_private *priv); + +extern const struct ethtool_ops nxpwifi_ethtool_ops; + +void nxpwifi_del_all_sta_list(struct nxpwifi_private *priv); +void nxpwifi_del_sta_entry(struct nxpwifi_private *priv, const u8 *mac); +void +nxpwifi_set_sta_ht_cap(struct nxpwifi_private *priv, const u8 *ies, + int ies_len, struct nxpwifi_sta_node *node); +struct nxpwifi_sta_node * +nxpwifi_add_sta_entry(struct nxpwifi_private *priv, const u8 *mac); +struct nxpwifi_sta_node * +nxpwifi_get_sta_entry(struct nxpwifi_private *priv, const u8 *mac); +bool nxpwifi_is_bss_in_11ac_mode(struct nxpwifi_private *priv); +u8 nxpwifi_get_center_freq_index(struct nxpwifi_private *priv, u8 band, + u32 pri_chan, u8 chan_bw); +int nxpwifi_init_channel_scan_gap(struct nxpwifi_adapter *adapter); + +int nxpwifi_cmd_issue_chan_report_request(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int nxpwifi_11h_handle_chanrpt_ready(struct nxpwifi_private *priv, + struct sk_buff *skb); + +void nxpwifi_parse_tx_status_event(struct nxpwifi_private *priv, + void *event_body); + +struct sk_buff * +nxpwifi_clone_skb_for_tx_status(struct nxpwifi_private *priv, + struct sk_buff *skb, u8 flag, u64 *cookie); +void nxpwifi_dfs_cac_work_queue(struct work_struct *work); +void nxpwifi_dfs_chan_sw_work_queue(struct work_struct *work); +void nxpwifi_abort_cac(struct nxpwifi_private *priv); +int nxpwifi_stop_radar_detection(struct nxpwifi_private *priv, + struct cfg80211_chan_def *chandef); +int nxpwifi_11h_handle_radar_detected(struct nxpwifi_private *priv, + struct sk_buff *skb); + +void nxpwifi_hist_data_set(struct nxpwifi_private *priv, u8 rx_rate, s8 sn= r, + s8 nflr); +void nxpwifi_hist_data_reset(struct nxpwifi_private *priv); +void nxpwifi_hist_data_add(struct nxpwifi_private *priv, + u8 rx_rate, s8 snr, s8 nflr); +u8 nxpwifi_adjust_data_rate(struct nxpwifi_private *priv, + u8 rx_rate, u8 ht_info); + +void nxpwifi_drv_info_dump(struct nxpwifi_adapter *adapter); +void nxpwifi_prepare_fw_dump_info(struct nxpwifi_adapter *adapter); +void nxpwifi_upload_device_dump(struct nxpwifi_adapter *adapter); +void *nxpwifi_alloc_dma_align_buf(int rx_len, gfp_t flags); +void nxpwifi_fw_dump_event(struct nxpwifi_private *priv); +void nxpwifi_queue_main_work(struct nxpwifi_adapter *adapter); +int nxpwifi_get_wakeup_reason(struct nxpwifi_private *priv, u16 action, + int cmd_type, + struct nxpwifi_ds_wakeup_reason *wakeup_reason); +int nxpwifi_get_chan_info(struct nxpwifi_private *priv, + struct nxpwifi_channel_band *channel_band); +void nxpwifi_coex_ampdu_rxwinsize(struct nxpwifi_adapter *adapter); +void nxpwifi_11n_delba(struct nxpwifi_private *priv, int tid); +int nxpwifi_send_domain_info_cmd_fw(struct wiphy *wiphy); +int nxpwifi_set_mac_address(struct nxpwifi_private *priv, + struct net_device *dev, + bool external, u8 *new_mac); +void nxpwifi_devdump_tmo_func(unsigned long function_context); + +#ifdef CONFIG_DEBUG_FS +void nxpwifi_debugfs_init(void); +void nxpwifi_debugfs_remove(void); + +void nxpwifi_dev_debugfs_init(struct nxpwifi_private *priv); +void nxpwifi_dev_debugfs_remove(struct nxpwifi_private *priv); +#endif +int nxpwifi_reinit_sw(struct nxpwifi_adapter *adapter); +int nxpwifi_shutdown_sw(struct nxpwifi_adapter *adapter); +#endif /* !_NXPWIFI_MAIN_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAF1D16E861; Fri, 21 Jun 2024 07:54:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956448; cv=fail; b=QyATi0JcFQ/faFYkJJ1L2rQMwvpNPtMoo/On1RdCgCEzQ5NYsKF3mVrvwMTs9zlA6ycvaod2ikmXQuThMyArHz2rGlljYgjCJxxQ9LKeRgGxQw8wqySKEa2Bnx+Wj6omWrGjWly+RgvgYlBIZ9WOIScCOG23b5SZ3aajP/gjaXY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956448; c=relaxed/simple; bh=18hbQibZVuoKdzzayZc5tqJ8S3FSA/OY5Y5wjqHwBBQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Crk5d4/Ss2A5tOkwzKolOFULbqvsXm6wFrJp4CjLjw4L3/XDpkSt+/HS1suDIY+qnKxRWSci6M/wWjSMilvjk3NM3V9gyzCNH2Iw6mKQT0dRQ5Nt3GEyiV7tlCI+cGrdFdp9MrFUITb/ltuIt8u38nsPSInUVmLRmyT+l9ssmLA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=Wv6P8W8O; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="Wv6P8W8O" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=eiAjsHmTOltsM+18yZL7KgUTBfdENZf4bLXdpPpK56O68sOT7+6RB9ycQLIOfQfR++katYL5DeNxC41LNwFnreiT1Ci4eAdJpg2NL5W/ldsKTRt+qO/01kxWZ0jiayC2ngRISjP6DOjqifm0ROfH5qepvy8AnJggPG4eMu9+DOQTYzvJzdIVgdTZchUb0nDiWCDYog4P7bQY3OC4oLLLkgYQuB4EVQzdGE6bT/Yn9ZK3k+12tRTRUoKTzGcQItvxEwTUEjuBaOcDQ4yvORYErvJ145bM0hwjO/jkwmh7t5PDGoQ4rTnLDzpeBSDDSU8pvTwnTA0XAWGadwOAfmGfsQ== 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=DqGi3CvNzKqt+p9zl5EvfFwDJJy3kYBna19f5btsNQY=; b=T4FHuKYdOSNuQydK2SWc4jv0rMna28ONl2ZaUDy8ynCb7/OBvlW0WmqduZt9w+urI1t15uIFLOmUU03my4C/kb9MR5mH2rlV3CJlPuEM6japqYw9o+fL474OXmrwjuJJGBZm43eob/Zv6adeg5JGzPOX2gpQtH8ZS/mM6QEJzE9QFw2QDpBYATJ8AXyl0/fn1A4HHmKqS7XTS80D+6NikRzl9hQO0tLSai7UYQG0g3mg0lEyQVjQCGgveW1PyAcEzUQ2BoppvcFKe3z9CMyTkWyRfn+SliCrXSszOf5mVzI/12H1LF5gOm/kac/HDYZyBfrvvFSRAGjhwRCL1Q3fcg== 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=DqGi3CvNzKqt+p9zl5EvfFwDJJy3kYBna19f5btsNQY=; b=Wv6P8W8OXz37L9khdbwAVbQu8MwOuKl8+KpMsA1C0Go0iD1LY5/wCDYeQ3KMZSiGOkdM3VFQGzCS45YfwqlNwPk2jd9IgTA8yL22nz+adxhBcbGzzaisqSA5C4DlU3/3NfvHPkU0cu6ZTOQYMpzhWP8MxXC36/KDcxaVcnMvFRg= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:53:58 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:53:58 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 25/43] wifi: nxpwifi: add scan.c Date: Fri, 21 Jun 2024 15:51:50 +0800 Message-Id: <20240621075208.513497-26-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: d11a735a-0fd9-4fbb-e3c8-08dc91c74dd5 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?UKJJeJDbTF7R6FIRN7LpNBGmiZGFBa1uOYVjzuzdSr0m+DVWQkXLGaghbBwn?= =?us-ascii?Q?6JGSYyscdsfo+QOjBX12XaCAd3uikL1lNeVKuxEk/sBiu4JO6EtDQUOQ88LX?= =?us-ascii?Q?z3jZS6gcYMSNZ8hZLOKjAIyjos7bBgH1WwE3vdyjJLBLxcLFZVgRytk0pjgs?= =?us-ascii?Q?pP8Qu+qlllyKSL5U5ff9rDZHn+/cmmtlklNAs9P+awmP0ymMT/z5rmKXYGG6?= =?us-ascii?Q?51FoWv6WDXgTI4+UpvbG1qELFrmPXi7ObIIMz+2B9zDyBn4cOxQcPPyuAkW3?= =?us-ascii?Q?vqH6TcubsfxzYoz7oO1axB7FJiTL3lpRc6ghSpql59XzDm8sxHrh0Mp47K81?= =?us-ascii?Q?OvWl4/qhJ6E2k2zkVuT+AxfgRMud1rA7xscpzqVBys5CzlzV/49CS5Vu33DL?= =?us-ascii?Q?kWrKdd1MxPvsrQ74FmWWbkL7iHMqSF001g+ScLUt52TRdWXsaPkbvFZtiZjc?= =?us-ascii?Q?DQhyKR0ajjV7cXYH7GoMIWOeKjqUmRDJsPW8eB+jYT+OCVh8l3cA/HXlaJQE?= =?us-ascii?Q?rxNjyfpGTTGNXipoiTqS51tC6Yb4qS1FHjnfPduJipg2ncpSKjXWQOK4V0Km?= =?us-ascii?Q?n7nQXUJwNOs8vJg2HLRVAxPlscV5SALny342N/j1AQhKi8C9a4SxEm5hOcYi?= =?us-ascii?Q?LWGOIKO7hTXVWtLwzuaDRcdkLGHtrBSCNhcIjJLY59cTjxsUs7cfQdHkL1E8?= =?us-ascii?Q?JFKHe39ayJHZMlC1ujbqJ41I7PG+HzbrFvkS9Iuf2m6LKhGQwHo51vnaEokL?= =?us-ascii?Q?sOV1euZ7nJ0A2OnRjY4DWXf6SbTfqppv6ddoI7jHb7MmTfNUI11FKJ7gMHvZ?= =?us-ascii?Q?DAMNsVQCJaGpdC48iEM+bOBTliFh/dxH06rbL3iWzwQ/6/t2I5be9sJGIHzT?= =?us-ascii?Q?LGP4HXaJ/AtRuRWjTGX1F7pfmi/fzUfM1XBy2DWDl3fBMgEAWQnRmfq83IC1?= =?us-ascii?Q?BEqOs1MXqMrAu9cB1vzjG/NsgJ1h7LbnI8aPx+oHzayNbgCudmzJdcpmgcHB?= =?us-ascii?Q?k4ePa64NxuCjlAzhkhTuIrhzp4GHy+fgi+ziQ98IdWmTwVKs8tbbGwucDiWB?= =?us-ascii?Q?0qdu65wwy4bQAnxTTbHygBmEan7+Gb78DMuzEBYg9ymqh6t29RASymQXHm4K?= =?us-ascii?Q?x4yPWmxL1vX7uTOzytuErPQrE8qlLc7vOTdyvf5PvZgjTh8gQ+289BI4GOtN?= =?us-ascii?Q?05m65Ko+gyFjYqjfUkrihk0sK6mXT/RkYviq60ghRNIeIY64njkM+eUXxMj7?= =?us-ascii?Q?Y7E6j1un8LbLSiwTFvkFhprSBUe2wcr+oO6TQuNt9NA5+3jGZG5Tr0L6a7Kp?= =?us-ascii?Q?AaZt4YOaqorVm9W+sxctOU0JGQhbKKwUljxQzdukq4lyBrJtkaS5YNxbDqBI?= =?us-ascii?Q?9ZYdecA=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?gZD/+vPIL0gexqXMFwqhP6EU5fUDueiE2V9QHYDQInDErCCtVMbg2a2oOMJL?= =?us-ascii?Q?RDCx8sdRSDsyw3oLYa+cyc0LpVHauXzCmvti9ayDevE5nuPW0qE7qohz6k4/?= =?us-ascii?Q?+rTc00oqdw091EaE5dAQysZs8Tazql98ceb4FS/7tXqj3CMvo9fe0wLS/grf?= =?us-ascii?Q?rJeOUjjn1iJBKpycrOTrGYB+LhgipyyQOTuDxY3vLAlxE2ZtGxYTHOHfmzV2?= =?us-ascii?Q?0rIdaqbNlcZgVdjp7b+YyX6b/DEQiEIjADAvJ9wSQKBzSNgumk/Pc3+3xUBn?= =?us-ascii?Q?f8jxkTeIZhMm+YALlbO7bURWEz6/MTfscLTVwjyMNYvjlDij45qBWOtvTrlF?= =?us-ascii?Q?xKI+FsrixfCpAIfyBGDIK5luA45Gmt/K4E4wo1dPnYhvmlxHMMBg7r0ZZ/Sh?= =?us-ascii?Q?J9DjxWzAoWwZMSwhySixDgsxy0DofzpURtbxHFnWcOlZ+YjIQi09a/WJfW3Y?= =?us-ascii?Q?ayupbgbAx74UxrR3VMeMxxB4kB2a57cW7ka6Tm1xgepsXZwTZ9wK5F7NaQ73?= =?us-ascii?Q?m61DBtP55zdsEualc0iu9oeT0FzJFlDuNARs+SMj6khMhCqbxtfzuwl7PIb2?= =?us-ascii?Q?HexC3bfjIjXdBf3SKT1vBtUoDBiPtup9QOQCn7+lzlguqLFYhjB4jAdqS32k?= =?us-ascii?Q?y/FA0WtaBmRko5xieVMLCT1v5Jfegm7AMVKbRx6qJoz9eh1ZZduBfbX0c8gm?= =?us-ascii?Q?UUMK0cpVVpQ5sk0UmxIkCUfpYBE1tWhHUX6e8h1AHsM1qozqnX92gCQa/frV?= =?us-ascii?Q?Cr62ZA1pq1FAN3oRVWl/t+19oDDBHqmPd5s0bBLvQX46bJHBHeJd31IHCOm2?= =?us-ascii?Q?k5DWXgvii29ztYddmansxjcysc/XUiGjpMjhuavu3MwOnkwv4Q7jl//DQccL?= =?us-ascii?Q?Ipb2UkZUliUGodNAowmqEfuzwDaRJ8TbkTqTCgqs+hWwz5k0WiMrhjPHQg8y?= =?us-ascii?Q?2jK5Q0aJGjQVsuTf1TcnJqXw1BBMfVcnWuGcLlQO7em6UDFBLq0SoInx9eiv?= =?us-ascii?Q?ucsJpx94qnMYEpVRnp53l30hkXk/Uu+jBg5JGeamOakbLwAl4F6ZbiUEGsGL?= =?us-ascii?Q?j0J/TKYExvtwk0wycMbu9ZJr3r0dydWOaigULa0+8CY8qMq8r/LWIOOw1NUm?= =?us-ascii?Q?AvMgvKFmDdNVsqgc1Ic0yTAgDbUmu3hcduKxI+E4HwHQttvddmWiy6JNxIAb?= =?us-ascii?Q?u9bJdbh/635XWfErfSszp5XFsXufB41z3lOY/lj2lUh7Xtl6aYF5YIkq+MVS?= =?us-ascii?Q?K4AGLheLxwg2HtkaHLiFqWbrFiR0KYbqWTCtqUAWihd3hKzyFjtTzMoR7bLS?= =?us-ascii?Q?WCKXYfGqloKuwfGE9jPjGtZKDfyhVtWsrsonTV6Z9V4V46bo2lnU6rwUMrxb?= =?us-ascii?Q?pcXhGimVZ3TAT36svd8kJ7BtAg+PXuUexhzr8dYi1daS+dLe5UgUYvAJ3FzR?= =?us-ascii?Q?HzUA69F+7OFayTWuwS23IWdfuuUnZccyA7QmJOXQaDYo8Yh0PUln+TIraqPf?= =?us-ascii?Q?Zga1eKOU9UDxQejJ6GuaXZMlwKbg4ePbtpxaNfH3z4W1Kp3S5GVzDj0izcRq?= =?us-ascii?Q?tVNRl2upr1AqBRbsitK315wQ/897te0VC++PwXlR?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: d11a735a-0fd9-4fbb-e3c8-08dc91c74dd5 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:53:58.1407 (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: hdyBNRC8odwbrlQy7XYy1APY/XIhljDxQg+iOeJF4doRzmV7qO6A4Um+/CrgVAgPYQn1rcxJ2dNdUPKZYTH+cA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/scan.c | 2894 +++++++++++++++++++++++ 1 file changed, 2894 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/scan.c diff --git a/drivers/net/wireless/nxp/nxpwifi/scan.c b/drivers/net/wireless= /nxp/nxpwifi/scan.c new file mode 100644 index 000000000000..a41d561cfe57 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/scan.c @@ -0,0 +1,2894 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: scan ioctl and command handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "11n.h" +#include "cfg80211.h" + +/* The maximum number of channels the firmware can scan per command */ +#define NXPWIFI_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 + +#define NXPWIFI_DEF_CHANNELS_PER_SCAN_CMD 4 + +/* Memory needed to store a max sized Channel List TLV for a firmware scan= */ +#define CHAN_TLV_MAX_SIZE (sizeof(struct nxpwifi_ie_types_header) \ + + (NXPWIFI_MAX_CHANNELS_PER_SPECIFIC_SCAN \ + * sizeof(struct nxpwifi_chan_scan_param_set))) + +/* Memory needed to store supported rate */ +#define RATE_TLV_MAX_SIZE (sizeof(struct nxpwifi_ie_types_rates_param_se= t) \ + + HOSTCMD_SUPPORTED_RATES) + +/* Memory needed to store a max number/size WildCard SSID TLV for a firmwa= re + * scan + */ +#define WILDCARD_SSID_TLV_MAX_SIZE \ + (NXPWIFI_MAX_SSID_LIST_LENGTH * \ + (sizeof(struct nxpwifi_ie_types_wildcard_ssid_params) \ + + IEEE80211_MAX_SSID_LEN)) + +/* Maximum memory needed for a nxpwifi_scan_cmd_config with all TLVs at ma= x */ +#define MAX_SCAN_CFG_ALLOC (sizeof(struct nxpwifi_scan_cmd_config) \ + + sizeof(struct nxpwifi_ie_types_num_probes) \ + + sizeof(struct nxpwifi_ie_types_htcap) \ + + CHAN_TLV_MAX_SIZE \ + + RATE_TLV_MAX_SIZE \ + + WILDCARD_SSID_TLV_MAX_SIZE) + +union nxpwifi_scan_cmd_config_tlv { + /* Scan configuration (variable length) */ + struct nxpwifi_scan_cmd_config config; + /* Max allocated block */ + u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC]; +}; + +enum cipher_suite { + CIPHER_SUITE_TKIP, + CIPHER_SUITE_CCMP, + CIPHER_SUITE_MAX +}; + +static u8 nxpwifi_wpa_oui[CIPHER_SUITE_MAX][4] =3D { + { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */ + { 0x00, 0x50, 0xf2, 0x04 }, /* AES */ +}; + +static u8 nxpwifi_rsn_oui[CIPHER_SUITE_MAX][4] =3D { + { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */ + { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ +}; + +static void +_dbg_security_flags(int log_level, const char *func, const char *desc, + struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + _nxpwifi_dbg(priv->adapter, log_level, + "info: %s: %s:\twpa_ie=3D%#x wpa2_ie=3D%#x WEP=3D%s WPA=3D%s WPA2= =3D%s\tEncMode=3D%#x privacy=3D%#x\n", + func, desc, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, + priv->sec_info.wep_enabled ? "e" : "d", + priv->sec_info.wpa_enabled ? "e" : "d", + priv->sec_info.wpa2_enabled ? "e" : "d", + priv->sec_info.encryption_mode, + bss_desc->privacy); +} + +#define dbg_security_flags(mask, desc, priv, bss_desc) \ + _dbg_security_flags(NXPWIFI_DBG_##mask, desc, __func__, priv, bss_desc) + +static bool +has_ieee_hdr(struct ieee_types_generic *ie, u8 key) +{ + return (ie && ie->ieee_hdr.element_id =3D=3D key); +} + +static bool +has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key) +{ + return (ie && ie->vend_hdr.element_id =3D=3D key); +} + +/* This function parses a given IE for a given OUI. + * + * This is used to parse a WPA/RSN IE to find if it has + * a given oui in PTK. + */ +static u8 +nxpwifi_search_oui_in_ie(struct ie_body *iebody, u8 *oui) +{ + u8 count; + + count =3D iebody->ptk_cnt[0]; + + /* There could be multiple OUIs for PTK hence + * 1) Take the length. + * 2) Check all the OUIs for AES. + * 3) If one of them is AES then pass success. + */ + while (count) { + if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body))) + return NXPWIFI_OUI_PRESENT; + + --count; + if (count) + iebody =3D (struct ie_body *)((u8 *)iebody + + sizeof(iebody->ptk_body)); + } + + pr_debug("info: %s: OUI is not found in PTK\n", __func__); + return NXPWIFI_OUI_NOT_PRESENT; +} + +/* This function checks if a given OUI is present in a RSN IE. + * + * The function first checks if a RSN IE is present or not in the + * BSS descriptor. It tries to locate the OUI only if such an IE is + * present. + */ +static u8 +nxpwifi_is_rsn_oui_present(struct nxpwifi_bssdescriptor *bss_desc, u32 cip= her) +{ + u8 *oui; + struct ie_body *iebody; + u8 ret =3D NXPWIFI_OUI_NOT_PRESENT; + + if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) { + iebody =3D (struct ie_body *) + (((u8 *)bss_desc->bcn_rsn_ie->data) + + RSN_GTK_OUI_OFFSET); + oui =3D &nxpwifi_rsn_oui[cipher][0]; + ret =3D nxpwifi_search_oui_in_ie(iebody, oui); + if (ret) + return ret; + } + return ret; +} + +/* This function checks if a given OUI is present in a WPA IE. + * + * The function first checks if a WPA IE is present or not in the + * BSS descriptor. It tries to locate the OUI only if such an IE is + * present. + */ +static u8 +nxpwifi_is_wpa_oui_present(struct nxpwifi_bssdescriptor *bss_desc, u32 cip= her) +{ + u8 *oui; + struct ie_body *iebody; + u8 ret =3D NXPWIFI_OUI_NOT_PRESENT; + + if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) { + iebody =3D (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data + + WPA_GTK_OUI_OFFSET); + oui =3D &nxpwifi_wpa_oui[cipher][0]; + ret =3D nxpwifi_search_oui_in_ie(iebody, oui); + if (ret) + return ret; + } + return ret; +} + +/* This function checks if driver is configured with no security mode and + * scanned network is compatible with it. + */ +static bool +nxpwifi_is_bss_no_sec(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && + !priv->sec_info.wpa2_enabled && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && + !priv->sec_info.encryption_mode && !bss_desc->privacy) { + return true; + } + return false; +} + +/* This function checks if static WEP is enabled in driver and scanned net= work + * is compatible with it. + */ +static bool +nxpwifi_is_bss_static_wep(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && + !priv->sec_info.wpa2_enabled && bss_desc->privacy) { + return true; + } + return false; +} + +/* This function checks if wpa is enabled in driver and scanned network is + * compatible with it. + */ +static bool +nxpwifi_is_bss_wpa(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && + !priv->sec_info.wpa2_enabled && + has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) + /* Privacy bit may NOT be set in some APs like + * LinkSys WRT54G && bss_desc->privacy + */ + ) { + dbg_security_flags(INFO, "WPA", priv, bss_desc); + return true; + } + return false; +} + +/* This function checks if wpa2 is enabled in driver and scanned network is + * compatible with it. + */ +static bool +nxpwifi_is_bss_wpa2(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && + priv->sec_info.wpa2_enabled && + has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) { + /* Privacy bit may NOT be set in some APs like + * LinkSys WRT54G && bss_desc->privacy + */ + dbg_security_flags(INFO, "WAP2", priv, bss_desc); + return true; + } + return false; +} + +/* This function checks if dynamic WEP is enabled in driver and scanned ne= twork + * is compatible with it. + */ +static bool +nxpwifi_is_bss_dynamic_wep(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && + !priv->sec_info.wpa2_enabled && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && + priv->sec_info.encryption_mode && bss_desc->privacy) { + dbg_security_flags(INFO, "dynamic", priv, bss_desc); + return true; + } + return false; +} + +/* This function checks if a scanned network is compatible with the driver + * settings. + * + * WEP WPA WPA2 encrypt Network + * -enabled -enabled -enabled mode Privacy WPA WPA2 Compatible + * 0 0 0 NONE 0 0 0 yes No security + * 0 1 0 x 1x 1 x yes WPA (disable + * HT if no AES) + * 0 0 1 x 1x x 1 yes WPA2 (disable + * HT if no AES) + * 1 0 0 NONE 1 0 0 yes Static WEP + * (disable HT) + * 0 0 0 !=3DNONE 1 0 0 yes Dynamic WEP + * + * Compatibility is not matched while roaming, except for mode. + */ +static s32 +nxpwifi_is_network_compatible(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc, u32 mode) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + bss_desc->disable_11n =3D false; + + /* Don't check for compatibility if roaming */ + if (priv->media_connected && + priv->bss_mode =3D=3D NL80211_IFTYPE_STATION && + bss_desc->bss_mode =3D=3D NL80211_IFTYPE_STATION) + return 0; + + if (priv->wps.session_enable) { + nxpwifi_dbg(adapter, IOCTL, + "info: return success directly in WPS period\n"); + return 0; + } + + if (bss_desc->chan_sw_ie_present) { + nxpwifi_dbg(adapter, INFO, + "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n"); + return -1; + } + + if (bss_desc->bss_mode =3D=3D mode) { + if (nxpwifi_is_bss_no_sec(priv, bss_desc)) { + /* No security */ + return 0; + } else if (nxpwifi_is_bss_static_wep(priv, bss_desc)) { + /* Static WEP enabled */ + nxpwifi_dbg(adapter, INFO, + "info: Disable 11n in WEP mode.\n"); + bss_desc->disable_11n =3D true; + return 0; + } else if (nxpwifi_is_bss_wpa(priv, bss_desc)) { + /* WPA enabled */ + if (((priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN) && + bss_desc->bcn_ht_cap) && + !nxpwifi_is_wpa_oui_present(bss_desc, + CIPHER_SUITE_CCMP)) { + if (nxpwifi_is_wpa_oui_present + (bss_desc, CIPHER_SUITE_TKIP)) { + nxpwifi_dbg(adapter, INFO, + "info: Disable 11n if AES\t" + "is not supported by AP\n"); + bss_desc->disable_11n =3D true; + } else { + return -1; + } + } + return 0; + } else if (nxpwifi_is_bss_wpa2(priv, bss_desc)) { + /* WPA2 enabled */ + if (((priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN) && + bss_desc->bcn_ht_cap) && + !nxpwifi_is_rsn_oui_present(bss_desc, + CIPHER_SUITE_CCMP)) { + if (nxpwifi_is_rsn_oui_present + (bss_desc, CIPHER_SUITE_TKIP)) { + nxpwifi_dbg(adapter, INFO, + "info: Disable 11n if AES\t" + "is not supported by AP\n"); + bss_desc->disable_11n =3D true; + } else { + return -1; + } + } + return 0; + } else if (nxpwifi_is_bss_dynamic_wep(priv, bss_desc)) { + /* Dynamic WEP enabled */ + return 0; + } + + /* Security doesn't match */ + dbg_security_flags(ERROR, "failed", priv, bss_desc); + return -1; + } + + /* Mode doesn't match */ + return -1; +} + +/* This function creates a channel list for the driver to scan, based + * on region/band information. + * + * This routine is used for any scan that is not provided with a + * specific channel list to scan. + */ +static int +nxpwifi_scan_create_channel_list(struct nxpwifi_private *priv, + const struct nxpwifi_user_scan_cfg + *user_scan_in, + struct nxpwifi_chan_scan_param_set + *scan_chan_list, + u8 filtered_scan) +{ + enum nl80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct nxpwifi_adapter *adapter =3D priv->adapter; + int chan_idx =3D 0, i; + u16 scan_time =3D 0; + + if (user_scan_in) + scan_time =3D (u16)user_scan_in->chan_list[0].scan_time; + + for (band =3D 0; (band < NUM_NL80211_BANDS) ; band++) { + if (!priv->wdev.wiphy->bands[band]) + continue; + + sband =3D priv->wdev.wiphy->bands[band]; + + for (i =3D 0; (i < sband->n_channels) ; i++) { + ch =3D &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + scan_chan_list[chan_idx].radio_type =3D band; + + if (scan_time) + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(scan_time); + else if ((ch->flags & IEEE80211_CHAN_NO_IR) || + (ch->flags & IEEE80211_CHAN_RADAR)) + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(adapter->passive_scan_time); + else + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(adapter->active_scan_time); + + if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].chan_scan_mode_bmap |=3D + (NXPWIFI_PASSIVE_SCAN | NXPWIFI_HIDDEN_SSID_REPORT); + else + scan_chan_list[chan_idx].chan_scan_mode_bmap &=3D + ~NXPWIFI_PASSIVE_SCAN; + + scan_chan_list[chan_idx].chan_number =3D (u32)ch->hw_value; + scan_chan_list[chan_idx].chan_scan_mode_bmap |=3D + NXPWIFI_DISABLE_CHAN_FILT; + + if (filtered_scan && + !((ch->flags & IEEE80211_CHAN_NO_IR) || + (ch->flags & IEEE80211_CHAN_RADAR))) + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(adapter->specific_scan_time); + + chan_idx++; + } + } + return chan_idx; +} + +/* This function creates a channel list tlv for bgscan config, based + * on region/band information. + */ +static int +nxpwifi_bgscan_create_channel_list(struct nxpwifi_private *priv, + const struct nxpwifi_bg_scan_cfg + *bgscan_cfg_in, + struct nxpwifi_chan_scan_param_set + *scan_chan_list) +{ + enum nl80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct nxpwifi_adapter *adapter =3D priv->adapter; + int chan_idx =3D 0, i; + u16 scan_time =3D 0, specific_scan_time =3D adapter->specific_scan_time; + + if (bgscan_cfg_in) + scan_time =3D (u16)bgscan_cfg_in->chan_list[0].scan_time; + + for (band =3D 0; (band < NUM_NL80211_BANDS); band++) { + if (!priv->wdev.wiphy->bands[band]) + continue; + + sband =3D priv->wdev.wiphy->bands[band]; + + for (i =3D 0; (i < sband->n_channels) ; i++) { + ch =3D &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + scan_chan_list[chan_idx].radio_type =3D band; + + if (scan_time) + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(scan_time); + else if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(adapter->passive_scan_time); + else + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(specific_scan_time); + + if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].chan_scan_mode_bmap |=3D + NXPWIFI_PASSIVE_SCAN; + else + scan_chan_list[chan_idx].chan_scan_mode_bmap &=3D + ~NXPWIFI_PASSIVE_SCAN; + + scan_chan_list[chan_idx].chan_number =3D (u32)ch->hw_value; + chan_idx++; + } + } + return chan_idx; +} + +/* This function appends rate TLV to scan config command. */ +static int +nxpwifi_append_rate_tlv(struct nxpwifi_private *priv, + struct nxpwifi_scan_cmd_config *scan_cfg_out, + u8 radio) +{ + struct nxpwifi_ie_types_rates_param_set *rates_tlv; + u8 rates[NXPWIFI_SUPPORTED_RATES], *tlv_pos; + u32 rates_size; + + memset(rates, 0, sizeof(rates)); + + tlv_pos =3D (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len; + + if (priv->scan_request) + rates_size =3D nxpwifi_get_rates_from_cfg80211(priv, rates, + radio); + else + rates_size =3D nxpwifi_get_supported_rates(priv, rates); + + nxpwifi_dbg(priv->adapter, CMD, + "info: SCAN_CMD: Rates size =3D %d\n", + rates_size); + rates_tlv =3D (struct nxpwifi_ie_types_rates_param_set *)tlv_pos; + rates_tlv->header.type =3D cpu_to_le16(WLAN_EID_SUPP_RATES); + rates_tlv->header.len =3D cpu_to_le16((u16)rates_size); + memcpy(rates_tlv->rates, rates, rates_size); + scan_cfg_out->tlv_buf_len +=3D sizeof(rates_tlv->header) + rates_size; + + return rates_size; +} + +/* This function constructs and sends multiple scan config commands to + * the firmware. + * + * Previous routines in the code flow have created a scan command configur= ation + * with any requested TLVs. This function splits the channel TLV into max= imum + * channels supported per scan lists and sends the portion of the channel = TLV, + * along with the other TLVs, to the firmware. + */ +static int +nxpwifi_scan_channel_list(struct nxpwifi_private *priv, + u32 max_chan_per_scan, u8 filtered_scan, + struct nxpwifi_scan_cmd_config *scan_cfg_out, + struct nxpwifi_ie_types_chan_list_param_set *tlv_o, + struct nxpwifi_chan_scan_param_set *scan_chan_list) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret =3D 0; + struct nxpwifi_chan_scan_param_set *tmp_chan_list; + u32 tlv_idx, rates_size, cmd_no; + u32 total_scan_time; + u32 done_early; + u8 radio_type; + + if (!scan_cfg_out || !tlv_o || !scan_chan_list) { + nxpwifi_dbg(priv->adapter, ERROR, + "info: Scan: Null detect: %p, %p, %p\n", + scan_cfg_out, tlv_o, scan_chan_list); + return -1; + } + + /* Check csa channel expiry before preparing scan list */ + nxpwifi_11h_get_csa_closed_channel(priv); + + tlv_o->header.type =3D cpu_to_le16(TLV_TYPE_CHANLIST); + + /* Set the temp channel struct pointer to the start of the desired + * list + */ + tmp_chan_list =3D scan_chan_list; + + /* Loop through the desired channel list, sending a new firmware scan + * commands for each max_chan_per_scan channels (or for 1,6,11 + * individually if configured accordingly) + */ + while (tmp_chan_list->chan_number) { + tlv_idx =3D 0; + total_scan_time =3D 0; + radio_type =3D 0; + tlv_o->header.len =3D 0; + done_early =3D false; + + /* Construct the Channel TLV for the scan command. Continue to + * insert channel TLVs until: + * - the tlv_idx hits the maximum configured per scan command + * - the next channel to insert is 0 (end of desired channel + * list) + * - done_early is set (controlling individual scanning of + * 1,6,11) + */ + while (tlv_idx < max_chan_per_scan && + tmp_chan_list->chan_number && !done_early) { + if (tmp_chan_list->chan_number =3D=3D priv->csa_chan) { + tmp_chan_list++; + continue; + } + + radio_type =3D tmp_chan_list->radio_type; + nxpwifi_dbg(priv->adapter, INFO, + "info: Scan: Chan(%3d), Radio(%d),\t" + "Mode(%d, %d), Dur(%d)\n", + tmp_chan_list->chan_number, + tmp_chan_list->radio_type, + tmp_chan_list->chan_scan_mode_bmap + & NXPWIFI_PASSIVE_SCAN, + (tmp_chan_list->chan_scan_mode_bmap + & NXPWIFI_DISABLE_CHAN_FILT) >> 1, + le16_to_cpu(tmp_chan_list->max_scan_time)); + + /* Copy the current channel TLV to the command being + * prepared + */ + memcpy(&tlv_o->chan_scan_param[tlv_idx], + tmp_chan_list, + sizeof(*tlv_o->chan_scan_param)); + + /* Increment the TLV header length by the size + * appended + */ + le16_unaligned_add_cpu(&tlv_o->header.len, + sizeof(*tlv_o->chan_scan_param)); + + /* The tlv buffer length is set to the number of bytes + * of the between the channel tlv pointer and the start + * of the tlv buffer. This compensates for any TLVs + * that were appended before the channel list. + */ + scan_cfg_out->tlv_buf_len =3D (u32)((u8 *)tlv_o - + scan_cfg_out->tlv_buf); + + /* Add the size of the channel tlv header and the data + * length + */ + scan_cfg_out->tlv_buf_len +=3D + (sizeof(tlv_o->header) + + le16_to_cpu(tlv_o->header.len)); + + /* Increment the index to the channel tlv we are + * constructing + */ + tlv_idx++; + + /* Count the total scan time per command */ + total_scan_time +=3D + le16_to_cpu(tmp_chan_list->max_scan_time); + + done_early =3D false; + + /* Stop the loop if the *current* channel is in the + * 1,6,11 set and we are not filtering on a BSSID + * or SSID. + */ + if (!filtered_scan && + (tmp_chan_list->chan_number =3D=3D 1 || + tmp_chan_list->chan_number =3D=3D 6 || + tmp_chan_list->chan_number =3D=3D 11)) + done_early =3D true; + + /* Increment the tmp pointer to the next channel to + * be scanned + */ + tmp_chan_list++; + + /* Stop the loop if the *next* channel is in the 1,6,11 + * set. This will cause it to be the only channel + * scanned on the next interation + */ + if (!filtered_scan && + (tmp_chan_list->chan_number =3D=3D 1 || + tmp_chan_list->chan_number =3D=3D 6 || + tmp_chan_list->chan_number =3D=3D 11)) + done_early =3D true; + } + + /* The total scan time should be less than scan command timeout + * value + */ + if (total_scan_time > NXPWIFI_MAX_TOTAL_SCAN_TIME) { + nxpwifi_dbg(priv->adapter, ERROR, + "total scan time %dms\t" + "is over limit (%dms), scan skipped\n", + total_scan_time, + NXPWIFI_MAX_TOTAL_SCAN_TIME); + ret =3D -1; + break; + } + + rates_size =3D nxpwifi_append_rate_tlv(priv, scan_cfg_out, + radio_type); + + /* Send the scan command to the firmware with the specified + * cfg + */ + if (priv->adapter->ext_scan) + cmd_no =3D HOST_CMD_802_11_SCAN_EXT; + else + cmd_no =3D HOST_CMD_802_11_SCAN; + + ret =3D nxpwifi_send_cmd(priv, cmd_no, HOST_ACT_GEN_SET, + 0, scan_cfg_out, false); + + /* rate IE is updated per scan command but same starting + * pointer is used each time so that rate IE from earlier + * scan_cfg_out->buf is overwritten with new one. + */ + scan_cfg_out->tlv_buf_len -=3D + sizeof(struct nxpwifi_ie_types_header) + rates_size; + + if (ret) { + nxpwifi_cancel_pending_scan_cmd(adapter); + break; + } + } + + if (ret) + return -1; + + return 0; +} + +/* This function constructs a scan command configuration structure to use + * in scan commands. + * + * Application layer or other functions can invoke network scanning + * with a scan configuration supplied in a user scan configuration structu= re. + * This structure is used as the basis of one or many scan command configu= ration + * commands that are sent to the command processing module and eventually = to the + * firmware. + * + * This function creates a scan command configuration structure based on = the + * following user supplied parameters (if present): + * - SSID filter + * - BSSID filter + * - Number of Probes to be sent + * - Channel list + * + * If the SSID or BSSID filter is not present, the filter is disabled/clea= red. + * If the number of probes is not set, adapter default setting is used. + */ +static void +nxpwifi_config_scan(struct nxpwifi_private *priv, + const struct nxpwifi_user_scan_cfg *user_scan_in, + struct nxpwifi_scan_cmd_config *scan_cfg_out, + struct nxpwifi_ie_types_chan_list_param_set **chan_list_out, + struct nxpwifi_chan_scan_param_set *scan_chan_list, + u8 *max_chan_per_scan, u8 *filtered_scan, + u8 *scan_current_only) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ie_types_num_probes *num_probes_tlv; + struct nxpwifi_ie_types_scan_chan_gap *chan_gap_tlv; + struct nxpwifi_ie_types_random_mac *random_mac_tlv; + struct nxpwifi_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; + struct nxpwifi_ie_types_bssid_list *bssid_tlv; + u8 *tlv_pos; + u32 num_probes; + u32 ssid_len; + u32 chan_idx; + u32 scan_time; + u32 scan_type; + u16 scan_dur; + u8 channel; + u8 radio_type; + int i; + u8 ssid_filter; + struct nxpwifi_ie_types_htcap *ht_cap; + struct nxpwifi_ie_types_bss_mode *bss_mode; + + /* The tlv_buf_len is calculated for each scan command. The TLVs added + * in this routine will be preserved since the routine that sends the + * command will append channelTLVs at *chan_list_out. The difference + * between the *chan_list_out and the tlv_buf start will be used to + * calculate the size of anything we add in this routine. + */ + scan_cfg_out->tlv_buf_len =3D 0; + + /* Running tlv pointer. Assigned to chan_list_out at end of function + * so later routines know where channels can be added to the command + * buf + */ + tlv_pos =3D scan_cfg_out->tlv_buf; + + /* Initialize the scan as un-filtered; the flag is later set to TRUE + * below if a SSID or BSSID filter is sent in the command + */ + *filtered_scan =3D false; + + /* Initialize the scan as not being only on the current channel. If + * the channel list is customized, only contains one channel, and is + * the active channel, this is set true and data flow is not halted. + */ + *scan_current_only =3D false; + + if (user_scan_in) { + u8 tmpaddr[ETH_ALEN]; + + /* Default the ssid_filter flag to TRUE, set false under + * certain wildcard conditions and qualified by the existence + * of an SSID list before marking the scan as filtered + */ + ssid_filter =3D true; + + /* Set the BSS type scan filter, use Adapter setting if + * unset + */ + scan_cfg_out->bss_mode =3D + (u8)(user_scan_in->bss_mode ?: adapter->scan_mode); + + /* Set the number of probes to send, use Adapter setting + * if unset + */ + num_probes =3D user_scan_in->num_probes ?: adapter->scan_probes; + + /* Set the BSSID filter to the incoming configuration, + * if non-zero. If not set, it will remain disabled + * (all zeros). + */ + memcpy(scan_cfg_out->specific_bssid, + user_scan_in->specific_bssid, + sizeof(scan_cfg_out->specific_bssid)); + + memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN); + + if (adapter->ext_scan && + !is_zero_ether_addr(tmpaddr)) { + bssid_tlv =3D + (struct nxpwifi_ie_types_bssid_list *)tlv_pos; + bssid_tlv->header.type =3D cpu_to_le16(TLV_TYPE_BSSID); + bssid_tlv->header.len =3D cpu_to_le16(ETH_ALEN); + memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid, + ETH_ALEN); + tlv_pos +=3D sizeof(struct nxpwifi_ie_types_bssid_list); + } + + for (i =3D 0; i < user_scan_in->num_ssids; i++) { + ssid_len =3D user_scan_in->ssid_list[i].ssid_len; + + wildcard_ssid_tlv =3D + (struct nxpwifi_ie_types_wildcard_ssid_params *) + tlv_pos; + wildcard_ssid_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_WILDCARDSSID); + wildcard_ssid_tlv->header.len =3D + cpu_to_le16((u16)(ssid_len + sizeof(u8))); + + /* max_ssid_length =3D 0 tells firmware to perform + * specific scan for the SSID filled, whereas + * max_ssid_length =3D IEEE80211_MAX_SSID_LEN is for + * wildcard scan. + */ + if (ssid_len) + wildcard_ssid_tlv->max_ssid_length =3D 0; + else + wildcard_ssid_tlv->max_ssid_length =3D + IEEE80211_MAX_SSID_LEN; + + if (!memcmp(user_scan_in->ssid_list[i].ssid, + "DIRECT-", 7)) + wildcard_ssid_tlv->max_ssid_length =3D 0xfe; + + memcpy(wildcard_ssid_tlv->ssid, + user_scan_in->ssid_list[i].ssid, ssid_len); + + tlv_pos +=3D (sizeof(wildcard_ssid_tlv->header) + + le16_to_cpu(wildcard_ssid_tlv->header.len)); + + nxpwifi_dbg(adapter, INFO, + "info: scan: ssid[%d]: %s, %d\n", + i, wildcard_ssid_tlv->ssid, + wildcard_ssid_tlv->max_ssid_length); + + /* Empty wildcard ssid with a maxlen will match many or + * potentially all SSIDs (maxlen =3D=3D 32), therefore do + * not treat the scan as + * filtered. + */ + if (!ssid_len && wildcard_ssid_tlv->max_ssid_length) + ssid_filter =3D false; + } + + /* The default number of channels sent in the command is low to + * ensure the response buffer from the firmware does not + * truncate scan results. That is not an issue with an SSID + * or BSSID filter applied to the scan results in the firmware. + */ + memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN); + if ((i && ssid_filter) || + !is_zero_ether_addr(tmpaddr)) + *filtered_scan =3D true; + + if (user_scan_in->scan_chan_gap) { + nxpwifi_dbg(adapter, INFO, + "info: scan: channel gap =3D %d\n", + user_scan_in->scan_chan_gap); + *max_chan_per_scan =3D + NXPWIFI_MAX_CHANNELS_PER_SPECIFIC_SCAN; + + chan_gap_tlv =3D (void *)tlv_pos; + chan_gap_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP); + chan_gap_tlv->header.len =3D + cpu_to_le16(sizeof(chan_gap_tlv->chan_gap)); + chan_gap_tlv->chan_gap =3D + cpu_to_le16((user_scan_in->scan_chan_gap)); + tlv_pos +=3D + sizeof(struct nxpwifi_ie_types_scan_chan_gap); + } + + if (!is_zero_ether_addr(user_scan_in->random_mac)) { + random_mac_tlv =3D (void *)tlv_pos; + random_mac_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_RANDOM_MAC); + random_mac_tlv->header.len =3D + cpu_to_le16(sizeof(random_mac_tlv->mac)); + ether_addr_copy(random_mac_tlv->mac, + user_scan_in->random_mac); + tlv_pos +=3D + sizeof(struct nxpwifi_ie_types_random_mac); + } + } else { + scan_cfg_out->bss_mode =3D (u8)adapter->scan_mode; + num_probes =3D adapter->scan_probes; + } + + /* If a specific BSSID or SSID is used, the number of channels in the + * scan command will be increased to the absolute maximum. + */ + if (*filtered_scan) { + *max_chan_per_scan =3D NXPWIFI_MAX_CHANNELS_PER_SPECIFIC_SCAN; + } else { + if (!priv->media_connected) + *max_chan_per_scan =3D NXPWIFI_DEF_CHANNELS_PER_SCAN_CMD; + else + *max_chan_per_scan =3D + NXPWIFI_DEF_CHANNELS_PER_SCAN_CMD / 2; + } + + if (adapter->ext_scan) { + bss_mode =3D (struct nxpwifi_ie_types_bss_mode *)tlv_pos; + bss_mode->header.type =3D cpu_to_le16(TLV_TYPE_BSS_MODE); + bss_mode->header.len =3D cpu_to_le16(sizeof(bss_mode->bss_mode)); + bss_mode->bss_mode =3D scan_cfg_out->bss_mode; + tlv_pos +=3D sizeof(bss_mode->header) + + le16_to_cpu(bss_mode->header.len); + } + + /* If the input config or adapter has the number of Probes set, + * add tlv + */ + if (num_probes) { + nxpwifi_dbg(adapter, INFO, + "info: scan: num_probes =3D %d\n", + num_probes); + + num_probes_tlv =3D (struct nxpwifi_ie_types_num_probes *)tlv_pos; + num_probes_tlv->header.type =3D cpu_to_le16(TLV_TYPE_NUMPROBES); + num_probes_tlv->header.len =3D + cpu_to_le16(sizeof(num_probes_tlv->num_probes)); + num_probes_tlv->num_probes =3D cpu_to_le16((u16)num_probes); + + tlv_pos +=3D sizeof(num_probes_tlv->header) + + le16_to_cpu(num_probes_tlv->header.len); + } + + if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && + (priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN)) { + ht_cap =3D (struct nxpwifi_ie_types_htcap *)tlv_pos; + memset(ht_cap, 0, sizeof(struct nxpwifi_ie_types_htcap)); + ht_cap->header.type =3D cpu_to_le16(WLAN_EID_HT_CAPABILITY); + ht_cap->header.len =3D + cpu_to_le16(sizeof(struct ieee80211_ht_cap)); + radio_type =3D + nxpwifi_band_to_radio_type(priv->adapter->config_bands); + nxpwifi_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); + tlv_pos +=3D sizeof(struct nxpwifi_ie_types_htcap); + } + + /* Append vendor specific IE TLV */ + nxpwifi_cmd_append_vsie_tlv(priv, NXPWIFI_VSIE_MASK_SCAN, &tlv_pos); + + /* Set the output for the channel TLV to the address in the tlv buffer + * past any TLVs that were added in this function (SSID, num_probes). + * Channel TLVs will be added past this for each scan command, + * preserving the TLVs that were previously added. + */ + *chan_list_out =3D + (struct nxpwifi_ie_types_chan_list_param_set *)tlv_pos; + + if (user_scan_in && user_scan_in->chan_list[0].chan_number) { + nxpwifi_dbg(adapter, INFO, + "info: Scan: Using supplied channel list\n"); + + for (chan_idx =3D 0; + chan_idx < NXPWIFI_USER_SCAN_CHAN_MAX && + user_scan_in->chan_list[chan_idx].chan_number; + chan_idx++) { + channel =3D user_scan_in->chan_list[chan_idx].chan_number; + scan_chan_list[chan_idx].chan_number =3D channel; + + radio_type =3D + user_scan_in->chan_list[chan_idx].radio_type; + scan_chan_list[chan_idx].radio_type =3D radio_type; + + scan_type =3D user_scan_in->chan_list[chan_idx].scan_type; + + if (scan_type =3D=3D NXPWIFI_SCAN_TYPE_PASSIVE) + scan_chan_list[chan_idx].chan_scan_mode_bmap |=3D + (NXPWIFI_PASSIVE_SCAN | + NXPWIFI_HIDDEN_SSID_REPORT); + else + scan_chan_list[chan_idx].chan_scan_mode_bmap &=3D + ~NXPWIFI_PASSIVE_SCAN; + + scan_chan_list[chan_idx].chan_scan_mode_bmap |=3D + NXPWIFI_DISABLE_CHAN_FILT; + + scan_time =3D user_scan_in->chan_list[chan_idx].scan_time; + + if (scan_time) { + scan_dur =3D (u16)scan_time; + } else { + if (scan_type =3D=3D NXPWIFI_SCAN_TYPE_PASSIVE) + scan_dur =3D adapter->passive_scan_time; + else if (*filtered_scan) + scan_dur =3D adapter->specific_scan_time; + else + scan_dur =3D adapter->active_scan_time; + } + + scan_chan_list[chan_idx].min_scan_time =3D + cpu_to_le16(scan_dur); + scan_chan_list[chan_idx].max_scan_time =3D + cpu_to_le16(scan_dur); + } + + /* Check if we are only scanning the current channel */ + if (chan_idx =3D=3D 1 && + user_scan_in->chan_list[0].chan_number =3D=3D + priv->curr_bss_params.bss_descriptor.channel) { + *scan_current_only =3D true; + nxpwifi_dbg(adapter, INFO, + "info: Scan: Scanning current channel only\n"); + } + } else { + nxpwifi_dbg(adapter, INFO, + "info: Scan: Creating full region channel list\n"); + nxpwifi_scan_create_channel_list(priv, user_scan_in, + scan_chan_list, + *filtered_scan); + } +} + +/* This function inspects the scan response buffer for pointers to + * expected TLVs. + * + * TLVs can be included at the end of the scan response BSS information. + * + * Data in the buffer is parsed pointers to TLVs that can potentially + * be passed back in the response. + */ +static void +nxpwifi_ret_802_11_scan_get_tlv_ptrs(struct nxpwifi_adapter *adapter, + struct nxpwifi_ie_types_data *tlv, + u32 tlv_buf_size, u32 req_tlv_type, + struct nxpwifi_ie_types_data **tlv_data) +{ + struct nxpwifi_ie_types_data *current_tlv; + u32 tlv_buf_left; + u32 tlv_type; + u32 tlv_len; + + current_tlv =3D tlv; + tlv_buf_left =3D tlv_buf_size; + *tlv_data =3D NULL; + + nxpwifi_dbg(adapter, INFO, + "info: SCAN_RESP: tlv_buf_size =3D %d\n", + tlv_buf_size); + + while (tlv_buf_left >=3D sizeof(struct nxpwifi_ie_types_header)) { + tlv_type =3D le16_to_cpu(current_tlv->header.type); + tlv_len =3D le16_to_cpu(current_tlv->header.len); + + if (sizeof(tlv->header) + tlv_len > tlv_buf_left) { + nxpwifi_dbg(adapter, ERROR, + "SCAN_RESP: TLV buffer corrupt\n"); + break; + } + + if (req_tlv_type =3D=3D tlv_type) { + switch (tlv_type) { + case TLV_TYPE_TSFTIMESTAMP: + nxpwifi_dbg(adapter, INFO, + "info: SCAN_RESP: TSF\t" + "timestamp TLV, len =3D %d\n", + tlv_len); + *tlv_data =3D current_tlv; + break; + case TLV_TYPE_CHANNELBANDLIST: + nxpwifi_dbg(adapter, INFO, + "info: SCAN_RESP: channel\t" + "band list TLV, len =3D %d\n", + tlv_len); + *tlv_data =3D current_tlv; + break; + default: + nxpwifi_dbg(adapter, ERROR, + "SCAN_RESP: unhandled TLV =3D %d\n", + tlv_type); + /* Give up, this seems corrupted */ + return; + } + } + + if (*tlv_data) + break; + + tlv_buf_left -=3D (sizeof(tlv->header) + tlv_len); + current_tlv =3D + (struct nxpwifi_ie_types_data *)(current_tlv->data + + tlv_len); + } /* while */ +} + +/* This function parses provided beacon buffer and updates + * respective fields in bss descriptor structure. + */ +int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter, + struct nxpwifi_bssdescriptor *bss_entry) +{ + u8 element_id; + struct ieee_types_fh_param_set *fh_param_set; + struct ieee_types_ds_param_set *ds_param_set; + struct ieee_types_cf_param_set *cf_param_set; + struct ieee_types_ibss_param_set *ibss_param_set; + u8 *current_ptr; + u8 *rate; + u8 element_len; + u16 total_ie_len; + u8 bytes_to_copy; + u8 rate_size; + u8 found_data_rate_ie; + u32 bytes_left; + struct ieee_types_vendor_specific *vendor_ie; + const u8 wpa_oui[4] =3D { 0x00, 0x50, 0xf2, 0x01 }; + const u8 wmm_oui[4] =3D { 0x00, 0x50, 0xf2, 0x02 }; + + found_data_rate_ie =3D false; + rate_size =3D 0; + current_ptr =3D bss_entry->beacon_buf; + bytes_left =3D bss_entry->beacon_buf_size; + + /* Process variable IE */ + while (bytes_left >=3D 2) { + element_id =3D *current_ptr; + element_len =3D *(current_ptr + 1); + total_ie_len =3D element_len + sizeof(struct ieee_types_header); + + if (bytes_left < total_ie_len) { + nxpwifi_dbg(adapter, ERROR, + "err: InterpretIE: in processing\t" + "IE, bytes left < IE length\n"); + return -EINVAL; + } + switch (element_id) { + case WLAN_EID_SSID: + if (element_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + bss_entry->ssid.ssid_len =3D element_len; + memcpy(bss_entry->ssid.ssid, (current_ptr + 2), + element_len); + nxpwifi_dbg(adapter, INFO, + "info: InterpretIE: ssid: %-32s\n", + bss_entry->ssid.ssid); + break; + + case WLAN_EID_SUPP_RATES: + if (element_len > NXPWIFI_SUPPORTED_RATES) + return -EINVAL; + memcpy(bss_entry->data_rates, current_ptr + 2, + element_len); + memcpy(bss_entry->supported_rates, current_ptr + 2, + element_len); + rate_size =3D element_len; + found_data_rate_ie =3D true; + break; + + case WLAN_EID_FH_PARAMS: + if (total_ie_len < sizeof(*fh_param_set)) + return -EINVAL; + fh_param_set =3D + (struct ieee_types_fh_param_set *)current_ptr; + memcpy(&bss_entry->phy_param_set.fh_param_set, + fh_param_set, + sizeof(struct ieee_types_fh_param_set)); + break; + + case WLAN_EID_DS_PARAMS: + if (total_ie_len < sizeof(*ds_param_set)) + return -EINVAL; + ds_param_set =3D + (struct ieee_types_ds_param_set *)current_ptr; + + bss_entry->channel =3D ds_param_set->current_chan; + + memcpy(&bss_entry->phy_param_set.ds_param_set, + ds_param_set, + sizeof(struct ieee_types_ds_param_set)); + break; + + case WLAN_EID_CF_PARAMS: + if (total_ie_len < sizeof(*cf_param_set)) + return -EINVAL; + cf_param_set =3D + (struct ieee_types_cf_param_set *)current_ptr; + memcpy(&bss_entry->ss_param_set.cf_param_set, + cf_param_set, + sizeof(struct ieee_types_cf_param_set)); + break; + + case WLAN_EID_IBSS_PARAMS: + if (total_ie_len < sizeof(*ibss_param_set)) + return -EINVAL; + ibss_param_set =3D + (struct ieee_types_ibss_param_set *) + current_ptr; + memcpy(&bss_entry->ss_param_set.ibss_param_set, + ibss_param_set, + sizeof(struct ieee_types_ibss_param_set)); + break; + + case WLAN_EID_ERP_INFO: + if (!element_len) + return -EINVAL; + bss_entry->erp_flags =3D *(current_ptr + 2); + break; + + case WLAN_EID_PWR_CONSTRAINT: + if (!element_len) + return -EINVAL; + bss_entry->local_constraint =3D *(current_ptr + 2); + bss_entry->sensed_11h =3D true; + break; + + case WLAN_EID_CHANNEL_SWITCH: + bss_entry->chan_sw_ie_present =3D true; + fallthrough; + case WLAN_EID_PWR_CAPABILITY: + case WLAN_EID_TPC_REPORT: + case WLAN_EID_QUIET: + bss_entry->sensed_11h =3D true; + break; + + case WLAN_EID_EXT_SUPP_RATES: + /* Only process extended supported rate + * if data rate is already found. + * Data rate IE should come before + * extended supported rate IE + */ + if (found_data_rate_ie) { + if ((element_len + rate_size) > + NXPWIFI_SUPPORTED_RATES) + bytes_to_copy =3D + (NXPWIFI_SUPPORTED_RATES - + rate_size); + else + bytes_to_copy =3D element_len; + + rate =3D (u8 *)bss_entry->data_rates; + rate +=3D rate_size; + memcpy(rate, current_ptr + 2, bytes_to_copy); + + rate =3D (u8 *)bss_entry->supported_rates; + rate +=3D rate_size; + memcpy(rate, current_ptr + 2, bytes_to_copy); + } + break; + + case WLAN_EID_VENDOR_SPECIFIC: + vendor_ie =3D (struct ieee_types_vendor_specific *) + current_ptr; + + /* 802.11 requires at least 3-byte OUI. */ + if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui)) + return -EINVAL; + + /* Not long enough for a match? Skip it. */ + if (element_len < sizeof(wpa_oui)) + break; + + if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui, + sizeof(wpa_oui))) { + bss_entry->bcn_wpa_ie =3D + (struct ieee_types_vendor_specific *) + current_ptr; + bss_entry->wpa_offset =3D (u16) + (current_ptr - bss_entry->beacon_buf); + } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui, + sizeof(wmm_oui))) { + if (total_ie_len =3D=3D + sizeof(struct ieee_types_wmm_parameter) || + total_ie_len =3D=3D + sizeof(struct ieee_types_wmm_info)) + /* Only accept and copy the WMM IE if + * it matches the size expected for the + * WMM Info IE or the WMM Parameter IE. + */ + memcpy((u8 *)&bss_entry->wmm_ie, + current_ptr, total_ie_len); + } + break; + case WLAN_EID_RSN: + bss_entry->bcn_rsn_ie =3D + (struct ieee_types_generic *)current_ptr; + bss_entry->rsn_offset =3D (u16)(current_ptr - + bss_entry->beacon_buf); + break; + case WLAN_EID_RSNX: + bss_entry->bcn_rsnx_ie =3D + (struct ieee_types_generic *)current_ptr; + bss_entry->rsnx_offset =3D + (u16)(current_ptr - bss_entry->beacon_buf); + break; + case WLAN_EID_HT_CAPABILITY: + bss_entry->bcn_ht_cap =3D (struct ieee80211_ht_cap *) + (current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->ht_cap_offset =3D (u16)(current_ptr + + sizeof(struct ieee_types_header) - + bss_entry->beacon_buf); + break; + case WLAN_EID_HT_OPERATION: + bss_entry->bcn_ht_oper =3D + (struct ieee80211_ht_operation *)(current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->ht_info_offset =3D (u16)(current_ptr + + sizeof(struct ieee_types_header) - + bss_entry->beacon_buf); + break; + case WLAN_EID_VHT_CAPABILITY: + bss_entry->disable_11ac =3D false; + bss_entry->bcn_vht_cap =3D + (void *)(current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->vht_cap_offset =3D + (u16)((u8 *)bss_entry->bcn_vht_cap - + bss_entry->beacon_buf); + break; + case WLAN_EID_VHT_OPERATION: + bss_entry->bcn_vht_oper =3D + (void *)(current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->vht_info_offset =3D + (u16)((u8 *)bss_entry->bcn_vht_oper - + bss_entry->beacon_buf); + break; + case WLAN_EID_BSS_COEX_2040: + bss_entry->bcn_bss_co_2040 =3D current_ptr; + bss_entry->bss_co_2040_offset =3D + (u16)(current_ptr - bss_entry->beacon_buf); + break; + case WLAN_EID_EXT_CAPABILITY: + bss_entry->bcn_ext_cap =3D current_ptr; + bss_entry->ext_cap_offset =3D + (u16)(current_ptr - bss_entry->beacon_buf); + break; + case WLAN_EID_OPMODE_NOTIF: + bss_entry->oper_mode =3D (void *)current_ptr; + bss_entry->oper_mode_offset =3D + (u16)((u8 *)bss_entry->oper_mode - + bss_entry->beacon_buf); + break; + default: + break; + } + + current_ptr +=3D total_ie_len; + bytes_left -=3D total_ie_len; + + } /* while (bytes_left > 2) */ + return 0; +} + +/* This function converts radio type scan parameter to a band configuration + * to be used in join command. + */ +static u8 +nxpwifi_radio_type_to_band(u8 radio_type) +{ + switch (radio_type) { + case HOST_SCAN_RADIO_TYPE_A: + return BAND_A; + case HOST_SCAN_RADIO_TYPE_BG: + default: + return BAND_G; + } +} + +/* This is an internal function used to start a scan based on an input + * configuration. + * + * This uses the input user scan configuration information when provided in + * order to send the appropriate scan commands to firmware to populate or + * update the internal driver scan table. + */ +int nxpwifi_scan_networks(struct nxpwifi_private *priv, + const struct nxpwifi_user_scan_cfg *user_scan_in) +{ + int ret; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct cmd_ctrl_node *cmd_node; + union nxpwifi_scan_cmd_config_tlv *scan_cfg_out; + struct nxpwifi_ie_types_chan_list_param_set *chan_list_out; + struct nxpwifi_chan_scan_param_set *scan_chan_list; + u8 filtered_scan; + u8 scan_current_chan_only; + u8 max_chan_per_scan; + + if (adapter->scan_processing) { + nxpwifi_dbg(adapter, WARN, + "cmd: Scan already in process...\n"); + return -EBUSY; + } + + if (priv->scan_block) { + nxpwifi_dbg(adapter, WARN, + "cmd: Scan is blocked during association...\n"); + return -EBUSY; + } + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags) || + test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "Ignore scan. Card removed or firmware in bad state\n"); + return -EFAULT; + } + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->scan_processing =3D true; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + scan_cfg_out =3D kzalloc(sizeof(union nxpwifi_scan_cmd_config_tlv), + GFP_KERNEL); + if (!scan_cfg_out) { + ret =3D -ENOMEM; + goto done; + } + + scan_chan_list =3D kcalloc(NXPWIFI_USER_SCAN_CHAN_MAX, + sizeof(struct nxpwifi_chan_scan_param_set), + GFP_KERNEL); + if (!scan_chan_list) { + kfree(scan_cfg_out); + ret =3D -ENOMEM; + goto done; + } + + nxpwifi_config_scan(priv, user_scan_in, &scan_cfg_out->config, + &chan_list_out, scan_chan_list, &max_chan_per_scan, + &filtered_scan, &scan_current_chan_only); + + ret =3D nxpwifi_scan_channel_list(priv, max_chan_per_scan, filtered_scan, + &scan_cfg_out->config, chan_list_out, + scan_chan_list); + + /* Get scan command from scan_pending_q and put to cmd_pending_q */ + if (!ret) { + spin_lock_bh(&adapter->scan_pending_q_lock); + if (!list_empty(&adapter->scan_pending_q)) { + cmd_node =3D list_first_entry(&adapter->scan_pending_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_bh(&adapter->scan_pending_q_lock); + nxpwifi_insert_cmd_to_pending_q(adapter, cmd_node); + queue_work(adapter->workqueue, &adapter->main_work); + + /* Perform internal scan synchronously */ + if (!priv->scan_request) { + nxpwifi_dbg(adapter, INFO, + "wait internal scan\n"); + nxpwifi_wait_queue_complete(adapter, cmd_node); + } + } else { + spin_unlock_bh(&adapter->scan_pending_q_lock); + } + } + + kfree(scan_cfg_out); + kfree(scan_chan_list); +done: + if (ret) { + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->scan_processing =3D false; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + } + return ret; +} + +/* This function prepares a scan command to be sent to the firmware. + * + * This uses the scan command configuration sent to the command processing + * module in command preparation stage to configure a scan command structu= re + * to send to firmware. + * + * The fixed fields specifying the BSS type and BSSID filters as well as a + * variable number/length of TLVs are sent in the command to firmware. + * + * Preparation also includes - + * - Setting command ID, and proper size + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_802_11_scan(struct host_cmd_ds_command *cmd, + struct nxpwifi_scan_cmd_config *scan_cfg) +{ + struct host_cmd_ds_802_11_scan *scan_cmd =3D &cmd->params.scan; + + /* Set fixed field variables in scan command */ + scan_cmd->bss_mode =3D scan_cfg->bss_mode; + memcpy(scan_cmd->bssid, scan_cfg->specific_bssid, + sizeof(scan_cmd->bssid)); + memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_SCAN); + + /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ + cmd->size =3D cpu_to_le16((u16)(sizeof(scan_cmd->bss_mode) + + sizeof(scan_cmd->bssid) + + scan_cfg->tlv_buf_len + S_DS_GEN)); + + return 0; +} + +/* This function checks compatibility of requested network with current + * driver settings. + */ +int nxpwifi_check_network_compatibility(struct nxpwifi_private *priv, + struct nxpwifi_bssdescriptor *bss_desc) +{ + int ret =3D -1; + + if (!bss_desc) + return -1; + + if ((nxpwifi_get_cfp(priv, (u8)bss_desc->bss_band, + (u16)bss_desc->channel, 0))) { + switch (priv->bss_mode) { + case NL80211_IFTYPE_STATION: + ret =3D nxpwifi_is_network_compatible(priv, bss_desc, + priv->bss_mode); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "Incompatible network settings\n"); + break; + default: + ret =3D 0; + } + } + + return ret; +} + +/* This function checks if SSID string contains all zeroes or length is ze= ro */ +static bool nxpwifi_is_hidden_ssid(struct cfg80211_ssid *ssid) +{ + int idx; + + for (idx =3D 0; idx < ssid->ssid_len; idx++) { + if (ssid->ssid[idx]) + return false; + } + + return true; +} + +/* This function checks if any hidden SSID found in passive scan channels + * and save those channels for specific SSID active scan + */ +static int nxpwifi_save_hidden_ssid_channels(struct nxpwifi_private *priv, + struct cfg80211_bss *bss) +{ + struct nxpwifi_bssdescriptor *bss_desc; + int ret; + int chid; + + /* Allocate and fill new bss descriptor */ + bss_desc =3D kzalloc(sizeof(*bss_desc), GFP_KERNEL); + if (!bss_desc) + return -ENOMEM; + + ret =3D nxpwifi_fill_new_bss_desc(priv, bss, bss_desc); + if (ret) + goto done; + + if (nxpwifi_is_hidden_ssid(&bss_desc->ssid)) { + nxpwifi_dbg(priv->adapter, INFO, "found hidden SSID\n"); + for (chid =3D 0 ; chid < NXPWIFI_USER_SCAN_CHAN_MAX; chid++) { + if (priv->hidden_chan[chid].chan_number =3D=3D + bss->channel->hw_value) + break; + + if (!priv->hidden_chan[chid].chan_number) { + priv->hidden_chan[chid].chan_number =3D + bss->channel->hw_value; + priv->hidden_chan[chid].radio_type =3D + bss->channel->band; + priv->hidden_chan[chid].scan_type =3D + NXPWIFI_SCAN_TYPE_ACTIVE; + break; + } + } + } + +done: + /* beacon_ie buffer was allocated in function + * nxpwifi_fill_new_bss_desc(). Free it now. + */ + kfree(bss_desc->beacon_buf); + kfree(bss_desc); + return 0; +} + +static int nxpwifi_update_curr_bss_params(struct nxpwifi_private *priv, + struct cfg80211_bss *bss) +{ + struct nxpwifi_bssdescriptor *bss_desc; + int ret; + + /* Allocate and fill new bss descriptor */ + bss_desc =3D kzalloc(sizeof(*bss_desc), GFP_KERNEL); + if (!bss_desc) + return -ENOMEM; + + ret =3D nxpwifi_fill_new_bss_desc(priv, bss, bss_desc); + if (ret) + goto done; + + ret =3D nxpwifi_check_network_compatibility(priv, bss_desc); + if (ret) + goto done; + + spin_lock_bh(&priv->curr_bcn_buf_lock); + /* Make a copy of current BSSID descriptor */ + memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, + sizeof(priv->curr_bss_params.bss_descriptor)); + + /* The contents of beacon_ie will be copied to its own buffer + * in nxpwifi_save_curr_bcn() + */ + nxpwifi_save_curr_bcn(priv); + spin_unlock_bh(&priv->curr_bcn_buf_lock); + +done: + /* beacon_ie buffer was allocated in function + * nxpwifi_fill_new_bss_desc(). Free it now. + */ + kfree(bss_desc->beacon_buf); + kfree(bss_desc); + return 0; +} + +static int +nxpwifi_parse_single_response_buf(struct nxpwifi_private *priv, u8 **bss_i= nfo, + u32 *bytes_left, u64 fw_tsf, u8 *radio_type, + bool ext_scan, s32 rssi_val) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_chan_freq_power *cfp; + struct cfg80211_bss *bss; + u8 bssid[ETH_ALEN]; + s32 rssi; + const u8 *ie_buf; + size_t ie_len; + u16 channel =3D 0; + u16 beacon_size =3D 0; + u32 curr_bcn_bytes; + u32 freq; + u16 beacon_period; + u16 cap_info_bitmap; + u8 *current_ptr; + u64 timestamp; + struct nxpwifi_fixed_bcn_param *bcn_param; + struct nxpwifi_bss_priv *bss_priv; + + if (*bytes_left >=3D sizeof(beacon_size)) { + /* Extract & convert beacon size from command buffer */ + beacon_size =3D get_unaligned_le16((*bss_info)); + *bytes_left -=3D sizeof(beacon_size); + *bss_info +=3D sizeof(beacon_size); + } + + if (!beacon_size || beacon_size > *bytes_left) { + *bss_info +=3D *bytes_left; + *bytes_left =3D 0; + return -EFAULT; + } + + /* Initialize the current working beacon pointer for this BSS + * iteration + */ + current_ptr =3D *bss_info; + + /* Advance the return beacon pointer past the current beacon */ + *bss_info +=3D beacon_size; + *bytes_left -=3D beacon_size; + + curr_bcn_bytes =3D beacon_size; + + /* First 5 fields are bssid, RSSI(for legacy scan only), + * time stamp, beacon interval, and capability information + */ + if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) + + sizeof(struct nxpwifi_fixed_bcn_param)) { + nxpwifi_dbg(adapter, ERROR, + "InterpretIE: not enough bytes left\n"); + return -EFAULT; + } + + memcpy(bssid, current_ptr, ETH_ALEN); + current_ptr +=3D ETH_ALEN; + curr_bcn_bytes -=3D ETH_ALEN; + + if (!ext_scan) { + rssi =3D (s32)*current_ptr; + rssi =3D (-rssi) * 100; /* Convert dBm to mBm */ + current_ptr +=3D sizeof(u8); + curr_bcn_bytes -=3D sizeof(u8); + nxpwifi_dbg(adapter, INFO, + "info: InterpretIE: RSSI=3D%d\n", rssi); + } else { + rssi =3D rssi_val; + } + + bcn_param =3D (struct nxpwifi_fixed_bcn_param *)current_ptr; + current_ptr +=3D sizeof(*bcn_param); + curr_bcn_bytes -=3D sizeof(*bcn_param); + + timestamp =3D le64_to_cpu(bcn_param->timestamp); + beacon_period =3D le16_to_cpu(bcn_param->beacon_period); + + cap_info_bitmap =3D le16_to_cpu(bcn_param->cap_info_bitmap); + nxpwifi_dbg(adapter, INFO, + "info: InterpretIE: capabilities=3D0x%X\n", + cap_info_bitmap); + + /* Rest of the current buffer are IE's */ + ie_buf =3D current_ptr; + ie_len =3D curr_bcn_bytes; + nxpwifi_dbg(adapter, INFO, + "info: InterpretIE: IELength for this AP =3D %d\n", + curr_bcn_bytes); + + while (curr_bcn_bytes >=3D sizeof(struct ieee_types_header)) { + u8 element_id, element_len; + + element_id =3D *current_ptr; + element_len =3D *(current_ptr + 1); + if (curr_bcn_bytes < element_len + + sizeof(struct ieee_types_header)) { + nxpwifi_dbg(adapter, ERROR, + "%s: bytes left < IE length\n", __func__); + return -EFAULT; + } + if (element_id =3D=3D WLAN_EID_DS_PARAMS) { + channel =3D *(current_ptr + + sizeof(struct ieee_types_header)); + break; + } + + current_ptr +=3D element_len + sizeof(struct ieee_types_header); + curr_bcn_bytes -=3D element_len + + sizeof(struct ieee_types_header); + } + + if (channel) { + struct ieee80211_channel *chan; + struct nxpwifi_bssdescriptor *bss_desc; + u8 band; + + /* Skip entry if on csa closed channel */ + if (channel =3D=3D priv->csa_chan) { + nxpwifi_dbg(adapter, WARN, + "Dropping entry on csa closed channel\n"); + return 0; + } + + band =3D BAND_G; + if (radio_type) + band =3D nxpwifi_radio_type_to_band(*radio_type & + (BIT(0) | BIT(1))); + + cfp =3D nxpwifi_get_cfp(priv, band, channel, 0); + + freq =3D cfp ? cfp->freq : 0; + + chan =3D ieee80211_get_channel(priv->wdev.wiphy, freq); + + if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { + bss =3D cfg80211_inform_bss(priv->wdev.wiphy, chan, + CFG80211_BSS_FTYPE_UNKNOWN, + bssid, timestamp, + cap_info_bitmap, + beacon_period, + ie_buf, ie_len, rssi, + GFP_ATOMIC); + if (bss) { + bss_priv =3D (struct nxpwifi_bss_priv *)bss->priv; + bss_priv->band =3D band; + bss_priv->fw_tsf =3D fw_tsf; + bss_desc =3D + &priv->curr_bss_params.bss_descriptor; + if (priv->media_connected && + !memcmp(bssid, bss_desc->mac_address, + ETH_ALEN)) + nxpwifi_update_curr_bss_params(priv, + bss); + + if ((chan->flags & IEEE80211_CHAN_RADAR) || + (chan->flags & IEEE80211_CHAN_NO_IR)) { + nxpwifi_dbg(adapter, INFO, + "radar or passive channel %d\n", + channel); + nxpwifi_save_hidden_ssid_channels(priv, + bss); + } + + cfg80211_put_bss(priv->wdev.wiphy, bss); + } + } + } else { + nxpwifi_dbg(adapter, WARN, "missing BSS channel IE\n"); + } + + return 0; +} + +static void nxpwifi_complete_scan(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->survey_idx =3D 0; + if (adapter->curr_cmd->wait_q_enabled) { + adapter->cmd_wait_q.status =3D 0; + if (!priv->scan_request) { + nxpwifi_dbg(adapter, INFO, + "complete internal scan\n"); + nxpwifi_complete_cmd(adapter, adapter->curr_cmd); + } + } +} + +/* This function checks if any hidden SSID found in passive scan channels + * and do specific SSID active scan for those channels + */ +static int +nxpwifi_active_scan_req_for_passive_chan(struct nxpwifi_private *priv) +{ + int ret; + struct nxpwifi_adapter *adapter =3D priv->adapter; + u8 id =3D 0; + struct nxpwifi_user_scan_cfg *user_scan_cfg; + + if (adapter->active_scan_triggered || !priv->scan_request || + priv->scan_aborting) { + adapter->active_scan_triggered =3D false; + return 0; + } + + if (!priv->hidden_chan[0].chan_number) { + nxpwifi_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channel= s\n"); + return 0; + } + user_scan_cfg =3D kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); + + if (!user_scan_cfg) + return -ENOMEM; + + for (id =3D 0; id < NXPWIFI_USER_SCAN_CHAN_MAX; id++) { + if (!priv->hidden_chan[id].chan_number) + break; + memcpy(&user_scan_cfg->chan_list[id], + &priv->hidden_chan[id], + sizeof(struct nxpwifi_user_scan_chan)); + } + + adapter->active_scan_triggered =3D true; + if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) + ether_addr_copy(user_scan_cfg->random_mac, + priv->scan_request->mac_addr); + user_scan_cfg->num_ssids =3D priv->scan_request->n_ssids; + user_scan_cfg->ssid_list =3D priv->scan_request->ssids; + + ret =3D nxpwifi_scan_networks(priv, user_scan_cfg); + kfree(user_scan_cfg); + + memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan)); + + if (ret) { + dev_err(priv->adapter->dev, "scan failed: %d\n", ret); + return ret; + } + + return 0; +} + +static void nxpwifi_check_next_scan_command(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct cmd_ctrl_node *cmd_node; + + spin_lock_bh(&adapter->scan_pending_q_lock); + if (list_empty(&adapter->scan_pending_q)) { + spin_unlock_bh(&adapter->scan_pending_q_lock); + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->scan_processing =3D false; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + nxpwifi_active_scan_req_for_passive_chan(priv); + + if (!adapter->ext_scan) + nxpwifi_complete_scan(priv); + + if (priv->scan_request) { + struct cfg80211_scan_info info =3D { + .aborted =3D false, + }; + + nxpwifi_dbg(adapter, INFO, + "info: notifying scan done\n"); + cfg80211_scan_done(priv->scan_request, &info); + priv->scan_request =3D NULL; + priv->scan_aborting =3D false; + } else { + priv->scan_aborting =3D false; + nxpwifi_dbg(adapter, INFO, + "info: scan already aborted\n"); + } + } else if ((priv->scan_aborting && !priv->scan_request) || + priv->scan_block) { + spin_unlock_bh(&adapter->scan_pending_q_lock); + + nxpwifi_cancel_pending_scan_cmd(adapter); + + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->scan_processing =3D false; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + + if (!adapter->active_scan_triggered) { + if (priv->scan_request) { + struct cfg80211_scan_info info =3D { + .aborted =3D true, + }; + + nxpwifi_dbg(adapter, INFO, + "info: aborting scan\n"); + cfg80211_scan_done(priv->scan_request, &info); + priv->scan_request =3D NULL; + priv->scan_aborting =3D false; + } else { + priv->scan_aborting =3D false; + nxpwifi_dbg(adapter, INFO, + "info: scan already aborted\n"); + } + } + } else { + /* Get scan command from scan_pending_q and put to + * cmd_pending_q + */ + cmd_node =3D list_first_entry(&adapter->scan_pending_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_bh(&adapter->scan_pending_q_lock); + nxpwifi_insert_cmd_to_pending_q(adapter, cmd_node); + } +} + +void nxpwifi_cancel_scan(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + int i; + + nxpwifi_cancel_pending_scan_cmd(adapter); + + if (adapter->scan_processing) { + spin_lock_bh(&adapter->nxpwifi_cmd_lock); + adapter->scan_processing =3D false; + spin_unlock_bh(&adapter->nxpwifi_cmd_lock); + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (!priv) + continue; + if (priv->scan_request) { + struct cfg80211_scan_info info =3D { + .aborted =3D true, + }; + + nxpwifi_dbg(adapter, INFO, + "info: aborting scan\n"); + cfg80211_scan_done(priv->scan_request, &info); + priv->scan_request =3D NULL; + priv->scan_aborting =3D false; + } + } + } +} + +/* This function handles the command response of scan. + * + * The response buffer for the scan command has the following + * memory layout: + * + * .-------------------------------------------------------------. + * | Header (4 * sizeof(t_u16)): Standard command response hdr | + * .-------------------------------------------------------------. + * | BufSize (t_u16) : sizeof the BSS Description data | + * .-------------------------------------------------------------. + * | NumOfSet (t_u8) : Number of BSS Descs returned | + * .-------------------------------------------------------------. + * | BSSDescription data (variable, size given in BufSize) | + * .-------------------------------------------------------------. + * | TLV data (variable, size calculated using Header->Size, | + * | BufSize and sizeof the fixed fields above) | + * .-------------------------------------------------------------. + */ +int nxpwifi_ret_802_11_scan(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + int ret =3D 0; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11_scan_rsp *scan_rsp; + struct nxpwifi_ie_types_data *tlv_data; + struct nxpwifi_ie_types_tsf_timestamp *tsf_tlv; + u8 *bss_info; + u32 scan_resp_size; + u32 bytes_left; + u32 idx; + u32 tlv_buf_size; + struct nxpwifi_ie_types_chan_band_list_param_set *chan_band_tlv; + struct chan_band_param_set *chan_band; + u8 is_bgscan_resp; + __le64 fw_tsf =3D 0; + u8 *radio_type; + struct cfg80211_wowlan_nd_match *pmatch; + struct cfg80211_sched_scan_request *nd_config =3D NULL; + + is_bgscan_resp =3D (le16_to_cpu(resp->command) + =3D=3D HOST_CMD_802_11_BG_SCAN_QUERY); + if (is_bgscan_resp) + scan_rsp =3D &resp->params.bg_scan_query_resp.scan_resp; + else + scan_rsp =3D &resp->params.scan_resp; + + if (scan_rsp->number_of_sets > NXPWIFI_MAX_AP) { + nxpwifi_dbg(adapter, ERROR, + "SCAN_RESP: too many AP returned (%d)\n", + scan_rsp->number_of_sets); + ret =3D -1; + goto check_next_scan; + } + + /* Check csa channel expiry before parsing scan response */ + nxpwifi_11h_get_csa_closed_channel(priv); + + bytes_left =3D le16_to_cpu(scan_rsp->bss_descript_size); + nxpwifi_dbg(adapter, INFO, + "info: SCAN_RESP: bss_descript_size %d\n", + bytes_left); + + scan_resp_size =3D le16_to_cpu(resp->size); + + nxpwifi_dbg(adapter, INFO, + "info: SCAN_RESP: returned %d APs before parsing\n", + scan_rsp->number_of_sets); + + bss_info =3D scan_rsp->bss_desc_and_tlv_buffer; + + /* The size of the TLV buffer is equal to the entire command response + * size (scan_resp_size) minus the fixed fields (sizeof()'s), the + * BSS Descriptions (bss_descript_size as bytesLef) and the command + * response header (S_DS_GEN) + */ + tlv_buf_size =3D scan_resp_size - (bytes_left + + sizeof(scan_rsp->bss_descript_size) + + sizeof(scan_rsp->number_of_sets) + + S_DS_GEN); + + tlv_data =3D (struct nxpwifi_ie_types_data *) + (scan_rsp->bss_desc_and_tlv_buffer + bytes_left); + + /* Search the TLV buffer space in the scan response for any valid + * TLVs + */ + nxpwifi_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, + TLV_TYPE_TSFTIMESTAMP, + (struct nxpwifi_ie_types_data **) + &tsf_tlv); + + /* Search the TLV buffer space in the scan response for any valid + * TLVs + */ + nxpwifi_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, + TLV_TYPE_CHANNELBANDLIST, + (struct nxpwifi_ie_types_data **) + &chan_band_tlv); + +#ifdef CONFIG_PM + if (priv->wdev.wiphy->wowlan_config) + nd_config =3D priv->wdev.wiphy->wowlan_config->nd_config; +#endif + + if (nd_config) { + adapter->nd_info =3D + kzalloc(struct_size(adapter->nd_info, matches, + scan_rsp->number_of_sets), + GFP_ATOMIC); + + if (adapter->nd_info) + adapter->nd_info->n_matches =3D scan_rsp->number_of_sets; + } + + for (idx =3D 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { + /* If the TSF TLV was appended to the scan results, save this + * entry's TSF value in the fw_tsf field. It is the firmware's + * TSF value at the time the beacon or probe response was + * received. + */ + if (tsf_tlv) + memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], + sizeof(fw_tsf)); + + if (chan_band_tlv) { + chan_band =3D &chan_band_tlv->chan_band_param[idx]; + radio_type =3D &chan_band->radio_type; + } else { + radio_type =3D NULL; + } + + if (chan_band_tlv && adapter->nd_info) { + adapter->nd_info->matches[idx] =3D + kzalloc(sizeof(*pmatch) + sizeof(u32), + GFP_ATOMIC); + + pmatch =3D adapter->nd_info->matches[idx]; + + if (pmatch) { + pmatch->n_channels =3D 1; + pmatch->channels[0] =3D chan_band->chan_number; + } + } + + ret =3D nxpwifi_parse_single_response_buf(priv, &bss_info, + &bytes_left, + le64_to_cpu(fw_tsf), + radio_type, false, 0); + if (ret) + goto check_next_scan; + } + +check_next_scan: + nxpwifi_check_next_scan_command(priv); + return ret; +} + +/* This function prepares an extended scan command to be sent to the firmw= are + * + * This uses the scan command configuration sent to the command processing + * module in command preparation stage to configure a extended scan command + * structure to send to firmware. + */ +int nxpwifi_cmd_802_11_scan_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_scan_ext *ext_scan =3D &cmd->params.ext_scan; + struct nxpwifi_scan_cmd_config *scan_cfg =3D data_buf; + + memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_SCAN_EXT); + + /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ + cmd->size =3D cpu_to_le16((u16)(sizeof(ext_scan->reserved) + + scan_cfg->tlv_buf_len + S_DS_GEN)); + + return 0; +} + +/* This function prepares an background scan config command to be sent + * to the firmware + */ +int nxpwifi_cmd_802_11_bg_scan_config(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =3D + &cmd->params.bg_scan_config; + struct nxpwifi_bg_scan_cfg *bgscan_cfg_in =3D data_buf; + u8 *tlv_pos =3D bgscan_config->tlv; + u8 num_probes; + u32 ssid_len, chan_idx, scan_time, scan_type, scan_dur, chan_num; + int i; + struct nxpwifi_ie_types_num_probes *num_probes_tlv; + struct nxpwifi_ie_types_repeat_count *repeat_count_tlv; + struct nxpwifi_ie_types_min_rssi_threshold *rssi_threshold_tlv; + struct nxpwifi_ie_types_bgscan_start_later *start_later_tlv; + struct nxpwifi_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; + struct nxpwifi_ie_types_chan_list_param_set *tlv_l; + struct nxpwifi_chan_scan_param_set *temp_chan; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_BG_SCAN_CONFIG); + cmd->size =3D cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN); + + bgscan_config->action =3D cpu_to_le16(bgscan_cfg_in->action); + bgscan_config->enable =3D bgscan_cfg_in->enable; + bgscan_config->bss_type =3D bgscan_cfg_in->bss_type; + bgscan_config->scan_interval =3D + cpu_to_le32(bgscan_cfg_in->scan_interval); + bgscan_config->report_condition =3D + cpu_to_le32(bgscan_cfg_in->report_condition); + + /* stop sched scan */ + if (!bgscan_config->enable) + return 0; + + bgscan_config->chan_per_scan =3D bgscan_cfg_in->chan_per_scan; + + num_probes =3D (bgscan_cfg_in->num_probes ? + bgscan_cfg_in->num_probes : priv->adapter->scan_probes); + + if (num_probes) { + num_probes_tlv =3D (struct nxpwifi_ie_types_num_probes *)tlv_pos; + num_probes_tlv->header.type =3D cpu_to_le16(TLV_TYPE_NUMPROBES); + num_probes_tlv->header.len =3D + cpu_to_le16(sizeof(num_probes_tlv->num_probes)); + num_probes_tlv->num_probes =3D cpu_to_le16((u16)num_probes); + + tlv_pos +=3D sizeof(num_probes_tlv->header) + + le16_to_cpu(num_probes_tlv->header.len); + } + + if (bgscan_cfg_in->repeat_count) { + repeat_count_tlv =3D + (struct nxpwifi_ie_types_repeat_count *)tlv_pos; + repeat_count_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_REPEAT_COUNT); + repeat_count_tlv->header.len =3D + cpu_to_le16(sizeof(repeat_count_tlv->repeat_count)); + repeat_count_tlv->repeat_count =3D + cpu_to_le16(bgscan_cfg_in->repeat_count); + + tlv_pos +=3D sizeof(repeat_count_tlv->header) + + le16_to_cpu(repeat_count_tlv->header.len); + } + + if (bgscan_cfg_in->rssi_threshold) { + rssi_threshold_tlv =3D + (struct nxpwifi_ie_types_min_rssi_threshold *)tlv_pos; + rssi_threshold_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_RSSI_LOW); + rssi_threshold_tlv->header.len =3D + cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold)); + rssi_threshold_tlv->rssi_threshold =3D + cpu_to_le16(bgscan_cfg_in->rssi_threshold); + + tlv_pos +=3D sizeof(rssi_threshold_tlv->header) + + le16_to_cpu(rssi_threshold_tlv->header.len); + } + + for (i =3D 0; i < bgscan_cfg_in->num_ssids; i++) { + ssid_len =3D bgscan_cfg_in->ssid_list[i].ssid.ssid_len; + + wildcard_ssid_tlv =3D + (struct nxpwifi_ie_types_wildcard_ssid_params *)tlv_pos; + wildcard_ssid_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_WILDCARDSSID); + wildcard_ssid_tlv->header.len =3D + cpu_to_le16((u16)(ssid_len + sizeof(u8))); + + /* max_ssid_length =3D 0 tells firmware to perform + * specific scan for the SSID filled, whereas + * max_ssid_length =3D IEEE80211_MAX_SSID_LEN is for + * wildcard scan. + */ + if (ssid_len) + wildcard_ssid_tlv->max_ssid_length =3D 0; + else + wildcard_ssid_tlv->max_ssid_length =3D + IEEE80211_MAX_SSID_LEN; + + memcpy(wildcard_ssid_tlv->ssid, + bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len); + + tlv_pos +=3D (sizeof(wildcard_ssid_tlv->header) + + le16_to_cpu(wildcard_ssid_tlv->header.len)); + } + + tlv_l =3D (struct nxpwifi_ie_types_chan_list_param_set *)tlv_pos; + + if (bgscan_cfg_in->chan_list[0].chan_number) { + dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n= "); + + tlv_l->header.type =3D cpu_to_le16(TLV_TYPE_CHANLIST); + + for (chan_idx =3D 0; + chan_idx < NXPWIFI_BG_SCAN_CHAN_MAX && + bgscan_cfg_in->chan_list[chan_idx].chan_number; + chan_idx++) { + temp_chan =3D &tlv_l->chan_scan_param[chan_idx]; + + /* Increment the TLV header length by size appended */ + le16_unaligned_add_cpu(&tlv_l->header.len, + sizeof(*tlv_l->chan_scan_param)); + + temp_chan->chan_number =3D + bgscan_cfg_in->chan_list[chan_idx].chan_number; + temp_chan->radio_type =3D + bgscan_cfg_in->chan_list[chan_idx].radio_type; + + scan_type =3D + bgscan_cfg_in->chan_list[chan_idx].scan_type; + + if (scan_type =3D=3D NXPWIFI_SCAN_TYPE_PASSIVE) + temp_chan->chan_scan_mode_bmap |=3D + NXPWIFI_PASSIVE_SCAN; + else + temp_chan->chan_scan_mode_bmap &=3D + ~NXPWIFI_PASSIVE_SCAN; + + scan_time =3D bgscan_cfg_in->chan_list[chan_idx].scan_time; + + if (scan_time) { + scan_dur =3D (u16)scan_time; + } else { + scan_dur =3D (scan_type =3D=3D + NXPWIFI_SCAN_TYPE_PASSIVE) ? + priv->adapter->passive_scan_time : + priv->adapter->specific_scan_time; + } + + temp_chan->min_scan_time =3D cpu_to_le16(scan_dur); + temp_chan->max_scan_time =3D cpu_to_le16(scan_dur); + } + } else { + dev_dbg(priv->adapter->dev, + "info: bgscan: Creating full region channel list\n"); + chan_num =3D + nxpwifi_bgscan_create_channel_list + (priv, bgscan_cfg_in, + tlv_l->chan_scan_param); + le16_unaligned_add_cpu(&tlv_l->header.len, + chan_num * + sizeof(*tlv_l->chan_scan_param)); + } + + tlv_pos +=3D (sizeof(tlv_l->header) + + le16_to_cpu(tlv_l->header.len)); + + if (bgscan_cfg_in->start_later) { + start_later_tlv =3D + (struct nxpwifi_ie_types_bgscan_start_later *)tlv_pos; + start_later_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER); + start_later_tlv->header.len =3D + cpu_to_le16(sizeof(start_later_tlv->start_later)); + start_later_tlv->start_later =3D + cpu_to_le16(bgscan_cfg_in->start_later); + + tlv_pos +=3D sizeof(start_later_tlv->header) + + le16_to_cpu(start_later_tlv->header.len); + } + + /* Append vendor specific IE TLV */ + nxpwifi_cmd_append_vsie_tlv(priv, NXPWIFI_VSIE_MASK_BGSCAN, &tlv_pos); + + le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv); + + return 0; +} + +int nxpwifi_stop_bg_scan(struct nxpwifi_private *priv) +{ + struct nxpwifi_bg_scan_cfg *bgscan_cfg; + + if (!priv->sched_scanning) { + dev_dbg(priv->adapter->dev, "bgscan already stopped!\n"); + return 0; + } + + bgscan_cfg =3D kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL); + if (!bgscan_cfg) + return -ENOMEM; + + bgscan_cfg->bss_type =3D NXPWIFI_BSS_MODE_INFRA; + bgscan_cfg->action =3D NXPWIFI_BGSCAN_ACT_SET; + bgscan_cfg->enable =3D false; + + if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_CONFIG, + HOST_ACT_GEN_SET, 0, bgscan_cfg, true)) { + kfree(bgscan_cfg); + return -EFAULT; + } + + kfree(bgscan_cfg); + priv->sched_scanning =3D false; + + return 0; +} + +static void +nxpwifi_update_chan_statistics(struct nxpwifi_private *priv, + struct nxpwifi_ietypes_chanstats *tlv_stat) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u8 i, num_chan; + struct nxpwifi_fw_chan_stats *fw_chan_stats; + struct nxpwifi_chan_stats chan_stats; + + fw_chan_stats =3D (void *)((u8 *)tlv_stat + + sizeof(struct nxpwifi_ie_types_header)); + num_chan =3D le16_to_cpu(tlv_stat->header.len) / + sizeof(struct nxpwifi_chan_stats); + + for (i =3D 0 ; i < num_chan; i++) { + if (adapter->survey_idx >=3D adapter->num_in_chan_stats) { + nxpwifi_dbg(adapter, WARN, + "FW reported too many channel results (max %d)\n", + adapter->num_in_chan_stats); + return; + } + chan_stats.chan_num =3D fw_chan_stats->chan_num; + chan_stats.bandcfg =3D fw_chan_stats->bandcfg; + chan_stats.flags =3D fw_chan_stats->flags; + chan_stats.noise =3D fw_chan_stats->noise; + chan_stats.total_bss =3D le16_to_cpu(fw_chan_stats->total_bss); + chan_stats.cca_scan_dur =3D + le16_to_cpu(fw_chan_stats->cca_scan_dur); + chan_stats.cca_busy_dur =3D + le16_to_cpu(fw_chan_stats->cca_busy_dur); + nxpwifi_dbg(adapter, INFO, + "chan=3D%d, noise=3D%d, total_network=3D%d scan_duration=3D%d, busy= _duration=3D%d\n", + chan_stats.chan_num, + chan_stats.noise, + chan_stats.total_bss, + chan_stats.cca_scan_dur, + chan_stats.cca_busy_dur); + memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats, + sizeof(struct nxpwifi_chan_stats)); + fw_chan_stats++; + } +} + +/* This function handles the command response of extended scan */ +int nxpwifi_ret_802_11_scan_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11_scan_ext *ext_scan_resp; + struct nxpwifi_ie_types_header *tlv; + struct nxpwifi_ietypes_chanstats *tlv_stat; + u16 buf_left, type, len; + + struct host_cmd_ds_command *cmd_ptr; + struct cmd_ctrl_node *cmd_node; + bool complete_scan =3D false; + + nxpwifi_dbg(adapter, INFO, "info: EXT scan returns successfully\n"); + + ext_scan_resp =3D &resp->params.ext_scan; + + tlv =3D (void *)ext_scan_resp->tlv_buffer; + buf_left =3D le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN + - 1); + + while (buf_left >=3D sizeof(struct nxpwifi_ie_types_header)) { + type =3D le16_to_cpu(tlv->type); + len =3D le16_to_cpu(tlv->len); + + if (buf_left < (sizeof(struct nxpwifi_ie_types_header) + len)) { + nxpwifi_dbg(adapter, ERROR, + "error processing scan response TLVs"); + break; + } + + switch (type) { + case TLV_TYPE_CHANNEL_STATS: + tlv_stat =3D (void *)tlv; + nxpwifi_update_chan_statistics(priv, tlv_stat); + break; + default: + break; + } + + buf_left -=3D len + sizeof(struct nxpwifi_ie_types_header); + tlv =3D (void *)((u8 *)tlv + len + + sizeof(struct nxpwifi_ie_types_header)); + } + + spin_lock_bh(&adapter->cmd_pending_q_lock); + spin_lock_bh(&adapter->scan_pending_q_lock); + if (list_empty(&adapter->scan_pending_q)) { + complete_scan =3D true; + list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { + cmd_ptr =3D (void *)cmd_node->cmd_skb->data; + if (le16_to_cpu(cmd_ptr->command) =3D=3D + HOST_CMD_802_11_SCAN_EXT) { + nxpwifi_dbg(adapter, INFO, + "Scan pending in command pending list"); + complete_scan =3D false; + break; + } + } + } + spin_unlock_bh(&adapter->scan_pending_q_lock); + spin_unlock_bh(&adapter->cmd_pending_q_lock); + + if (complete_scan) + nxpwifi_complete_scan(priv); + + return 0; +} + +/* This function This function handles the event extended scan report. It + * parses extended scan results and informs to cfg80211 stack. + */ +int nxpwifi_handle_event_ext_scan_report(struct nxpwifi_private *priv, + void *buf) +{ + int ret =3D 0; + struct nxpwifi_adapter *adapter =3D priv->adapter; + u8 *bss_info; + u32 bytes_left, bytes_left_for_tlv, idx; + u16 type, len; + struct nxpwifi_ie_types_data *tlv; + struct nxpwifi_ie_types_bss_scan_rsp *scan_rsp_tlv; + struct nxpwifi_ie_types_bss_scan_info *scan_info_tlv; + u8 *radio_type; + u64 fw_tsf =3D 0; + s32 rssi =3D 0; + struct nxpwifi_event_scan_result *event_scan =3D buf; + u8 num_of_set =3D event_scan->num_of_set; + u8 *scan_resp =3D buf + sizeof(struct nxpwifi_event_scan_result); + u16 scan_resp_size =3D le16_to_cpu(event_scan->buf_size); + + if (num_of_set > NXPWIFI_MAX_AP) { + nxpwifi_dbg(adapter, ERROR, + "EXT_SCAN: Invalid number of AP returned (%d)!!\n", + num_of_set); + ret =3D -1; + goto check_next_scan; + } + + bytes_left =3D scan_resp_size; + nxpwifi_dbg(adapter, INFO, + "EXT_SCAN: size %d, returned %d APs...", + scan_resp_size, num_of_set); + nxpwifi_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf, + scan_resp_size + + sizeof(struct nxpwifi_event_scan_result)); + + tlv =3D (struct nxpwifi_ie_types_data *)scan_resp; + + for (idx =3D 0; idx < num_of_set && bytes_left; idx++) { + type =3D le16_to_cpu(tlv->header.type); + len =3D le16_to_cpu(tlv->header.len); + if (bytes_left < sizeof(struct nxpwifi_ie_types_header) + len) { + nxpwifi_dbg(adapter, ERROR, + "EXT_SCAN: Error bytes left < TLV length\n"); + break; + } + scan_rsp_tlv =3D NULL; + scan_info_tlv =3D NULL; + bytes_left_for_tlv =3D bytes_left; + + /* BSS response TLV with beacon or probe response buffer + * at the initial position of each descriptor + */ + if (type !=3D TLV_TYPE_BSS_SCAN_RSP) + break; + + bss_info =3D (u8 *)tlv; + scan_rsp_tlv =3D (struct nxpwifi_ie_types_bss_scan_rsp *)tlv; + tlv =3D (struct nxpwifi_ie_types_data *)(tlv->data + len); + bytes_left_for_tlv -=3D + (len + sizeof(struct nxpwifi_ie_types_header)); + + while (bytes_left_for_tlv >=3D + sizeof(struct nxpwifi_ie_types_header) && + le16_to_cpu(tlv->header.type) !=3D TLV_TYPE_BSS_SCAN_RSP) { + type =3D le16_to_cpu(tlv->header.type); + len =3D le16_to_cpu(tlv->header.len); + if (bytes_left_for_tlv < + sizeof(struct nxpwifi_ie_types_header) + len) { + nxpwifi_dbg(adapter, ERROR, + "EXT_SCAN: Error in processing TLV,\t" + "bytes left < TLV length\n"); + scan_rsp_tlv =3D NULL; + bytes_left_for_tlv =3D 0; + continue; + } + switch (type) { + case TLV_TYPE_BSS_SCAN_INFO: + scan_info_tlv =3D + (struct nxpwifi_ie_types_bss_scan_info *)tlv; + if (len !=3D + sizeof(struct nxpwifi_ie_types_bss_scan_info) - + sizeof(struct nxpwifi_ie_types_header)) { + bytes_left_for_tlv =3D 0; + continue; + } + break; + default: + break; + } + tlv =3D (struct nxpwifi_ie_types_data *)(tlv->data + len); + bytes_left -=3D + (len + sizeof(struct nxpwifi_ie_types_header)); + bytes_left_for_tlv -=3D + (len + sizeof(struct nxpwifi_ie_types_header)); + } + + if (!scan_rsp_tlv) + break; + + /* Advance pointer to the beacon buffer length and + * update the bytes count so that the function + * wlan_interpret_bss_desc_with_ie() can handle the + * scan buffer withut any change + */ + bss_info +=3D sizeof(u16); + bytes_left -=3D sizeof(u16); + + if (scan_info_tlv) { + rssi =3D (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi)); + rssi *=3D 100; /* Convert dBm to mBm */ + nxpwifi_dbg(adapter, INFO, + "info: InterpretIE: RSSI=3D%d\n", rssi); + fw_tsf =3D le64_to_cpu(scan_info_tlv->tsf); + radio_type =3D &scan_info_tlv->radio_type; + } else { + radio_type =3D NULL; + } + ret =3D nxpwifi_parse_single_response_buf(priv, &bss_info, + &bytes_left, fw_tsf, + radio_type, true, rssi); + if (ret) + goto check_next_scan; + } + +check_next_scan: + if (!event_scan->more_event) + nxpwifi_check_next_scan_command(priv); + + return ret; +} + +/* This function prepares command for background scan query. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting background scan flush parameter + * - Ensuring correct endian-ness + */ +int nxpwifi_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd) +{ + struct host_cmd_ds_802_11_bg_scan_query *bg_query =3D + &cmd->params.bg_scan_query; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_BG_SCAN_QUERY); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query) + + S_DS_GEN); + + bg_query->flush =3D 1; + + return 0; +} + +/* This function inserts scan command node to the scan pending queue. + */ +void +nxpwifi_queue_scan_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + cmd_node->wait_q_enabled =3D true; + cmd_node->condition =3D &adapter->scan_wait_q_woken; + spin_lock_bh(&adapter->scan_pending_q_lock); + list_add_tail(&cmd_node->list, &adapter->scan_pending_q); + spin_unlock_bh(&adapter->scan_pending_q_lock); +} + +/* This function sends a scan command for all available channels to the + * firmware, filtered on a specific SSID. + */ +static int nxpwifi_scan_specific_ssid(struct nxpwifi_private *priv, + struct cfg80211_ssid *req_ssid) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + struct nxpwifi_user_scan_cfg *scan_cfg; + + if (adapter->scan_processing) { + nxpwifi_dbg(adapter, WARN, + "cmd: Scan already in process...\n"); + return -EBUSY; + } + + if (priv->scan_block) { + nxpwifi_dbg(adapter, WARN, + "cmd: Scan is blocked during association...\n"); + return -EBUSY; + } + + scan_cfg =3D kzalloc(sizeof(*scan_cfg), GFP_KERNEL); + if (!scan_cfg) + return -ENOMEM; + + scan_cfg->ssid_list =3D req_ssid; + scan_cfg->num_ssids =3D 1; + + ret =3D nxpwifi_scan_networks(priv, scan_cfg); + + kfree(scan_cfg); + return ret; +} + +/* Sends IOCTL request to start a scan. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + * + * Scan command can be issued for both normal scan and specific SSID + * scan, depending upon whether an SSID is provided or not. + */ +int nxpwifi_request_scan(struct nxpwifi_private *priv, + struct cfg80211_ssid *req_ssid) +{ + int ret; + + if (mutex_lock_interruptible(&priv->async_mutex)) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: acquire semaphore fail\n", + __func__); + return -1; + } + + priv->adapter->scan_wait_q_woken =3D false; + + if (req_ssid && req_ssid->ssid_len !=3D 0) + /* Specific SSID scan */ + ret =3D nxpwifi_scan_specific_ssid(priv, req_ssid); + else + /* Normal scan */ + ret =3D nxpwifi_scan_networks(priv, NULL); + + mutex_unlock(&priv->async_mutex); + + return ret; +} + +/* This function appends the vendor specific IE TLV to a buffer. + */ +int +nxpwifi_cmd_append_vsie_tlv(struct nxpwifi_private *priv, + u16 vsie_mask, u8 **buffer) +{ + int id, ret_len =3D 0; + struct nxpwifi_ie_types_vendor_param_set *vs_param_set; + + if (!buffer) + return 0; + if (!(*buffer)) + return 0; + + /* Traverse through the saved vendor specific IE array and append + * the selected(scan/assoc) IE as TLV to the command + */ + for (id =3D 0; id < NXPWIFI_MAX_VSIE_NUM; id++) { + if (priv->vs_ie[id].mask & vsie_mask) { + vs_param_set =3D + (struct nxpwifi_ie_types_vendor_param_set *) + *buffer; + vs_param_set->header.type =3D + cpu_to_le16(TLV_TYPE_PASSTHROUGH); + vs_param_set->header.len =3D + cpu_to_le16((((u16)priv->vs_ie[id].ie[1]) + & 0x00FF) + 2); + if (le16_to_cpu(vs_param_set->header.len) > + NXPWIFI_MAX_VSIE_LEN) { + nxpwifi_dbg(priv->adapter, ERROR, + "Invalid param length!\n"); + break; + } + + memcpy(vs_param_set->ie, priv->vs_ie[id].ie, + le16_to_cpu(vs_param_set->header.len)); + *buffer +=3D le16_to_cpu(vs_param_set->header.len) + + sizeof(struct nxpwifi_ie_types_header); + ret_len +=3D le16_to_cpu(vs_param_set->header.len) + + sizeof(struct nxpwifi_ie_types_header); + } + } + return ret_len; +} + +/* This function saves a beacon buffer of the current BSS descriptor. + * + * The current beacon buffer is saved so that it can be restored in the + * following cases that makes the beacon buffer not to contain the current + * ssid's beacon buffer. + * - The current ssid was not found somehow in the last scan. + * - The current ssid was the last entry of the scan table and overlo= aded. + */ +void +nxpwifi_save_curr_bcn(struct nxpwifi_private *priv) +{ + struct nxpwifi_bssdescriptor *curr_bss =3D + &priv->curr_bss_params.bss_descriptor; + + if (!curr_bss->beacon_buf_size) + return; + + /* allocate beacon buffer at 1st time; or if it's size has changed */ + if (!priv->curr_bcn_buf || + priv->curr_bcn_size !=3D curr_bss->beacon_buf_size) { + priv->curr_bcn_size =3D curr_bss->beacon_buf_size; + + kfree(priv->curr_bcn_buf); + priv->curr_bcn_buf =3D kmalloc(curr_bss->beacon_buf_size, + GFP_ATOMIC); + if (!priv->curr_bcn_buf) + return; + } + + memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, + curr_bss->beacon_buf_size); + nxpwifi_dbg(priv->adapter, INFO, + "info: current beacon saved %d\n", + priv->curr_bcn_size); + + curr_bss->beacon_buf =3D priv->curr_bcn_buf; + + /* adjust the pointers in the current BSS descriptor */ + if (curr_bss->bcn_wpa_ie) + curr_bss->bcn_wpa_ie =3D + (struct ieee_types_vendor_specific *) + (curr_bss->beacon_buf + + curr_bss->wpa_offset); + + if (curr_bss->bcn_rsn_ie) + curr_bss->bcn_rsn_ie =3D (struct ieee_types_generic *) + (curr_bss->beacon_buf + + curr_bss->rsn_offset); + + if (curr_bss->bcn_ht_cap) + curr_bss->bcn_ht_cap =3D (struct ieee80211_ht_cap *) + (curr_bss->beacon_buf + + curr_bss->ht_cap_offset); + + if (curr_bss->bcn_ht_oper) + curr_bss->bcn_ht_oper =3D (struct ieee80211_ht_operation *) + (curr_bss->beacon_buf + + curr_bss->ht_info_offset); + + if (curr_bss->bcn_vht_cap) + curr_bss->bcn_vht_cap =3D (void *)(curr_bss->beacon_buf + + curr_bss->vht_cap_offset); + + if (curr_bss->bcn_vht_oper) + curr_bss->bcn_vht_oper =3D (void *)(curr_bss->beacon_buf + + curr_bss->vht_info_offset); + + if (curr_bss->bcn_bss_co_2040) + curr_bss->bcn_bss_co_2040 =3D + (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset); + + if (curr_bss->bcn_ext_cap) + curr_bss->bcn_ext_cap =3D curr_bss->beacon_buf + + curr_bss->ext_cap_offset; + + if (curr_bss->oper_mode) + curr_bss->oper_mode =3D (void *)(curr_bss->beacon_buf + + curr_bss->oper_mode_offset); +} + +/* This function frees the current BSS descriptor beacon buffer. + */ +void +nxpwifi_free_curr_bcn(struct nxpwifi_private *priv) +{ + kfree(priv->curr_bcn_buf); + priv->curr_bcn_buf =3D NULL; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F25221741F6; Fri, 21 Jun 2024 07:54:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956453; cv=fail; b=cmf9MWk6Z2uoBqsFBKp9wj/rFGhCYDEeToVAmUcn5USTXcMIJWvMRpjHD91/CfzY6Ur+96LpV/NVf6X/K6If7J2x9azH9sz2suRop1O+uE+ln6XZriumE6++QarkUw4/gK+UK/3oLjxOin+T43+JVAivWNaBvsUUi8JNL7M+7xI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956453; c=relaxed/simple; bh=P/mcp5L22eMSTulZxW7iFABO0Fr0mWuczcx9Kc4oej8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=sCCSsJoGK4DMaFhR19CplXw7KvwxrK2++iLpnIuL4W/TmmQ4aldJonhe7DTajZja9XoK61Zjf42cfG7NwhI1SsTjfGBF7N1zp9x3iA/XE5idUDzpkVavw/ftGmyyjPKrwGTADbV0eEVYYyuK0ytAmra27KxIP03FXkjU+Co7kf8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=Dl4qd9Oy; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="Dl4qd9Oy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RKqPC5fJlIAZ3Wk/q6qj04R3vQZ2C0GlPAJgAEZuQntU/6XN86AuR0SvWJ1mZGxuo/n7knsF9JYxnZFBGMDGliVtgFOuH2ycenaK2cCFwGQqjIDTkLSvustCqY5bklRG00a+DxWdvngd2/2SB1K3Rfwq0QmIvETK40M+EEa+63qD7yXaZpgtc/weThUBXGuBCTJfLreRMYAvWy8dqRSs693H3M/G+wRgrfdqCOBAeqmMvdUVBfG1PMyqi5Ybi+iAKvvJcSJGZiRQK+tvuMyVEgCYTg/Ot1qX4Zka2VaL74UBqt3t61MhFpbNOgWMDwOqenAeu1DJWhRSLs3droXw1A== 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=vszfFQY6HkZ2cM0O92DsJHkJ6U5K1ANyHXF2RgX4OFQ=; b=hcIb0jRE22xQCWbQm1tG9hkJn1bDw/BaaKclJXZ25OF5BR7MKdFSbu/oMqi2KMqtg0gTsfD9cTpqRbM70zGqIduzNs0cRp+9MJUgzw8P09aAO6rWOIBuZ6y2Bz/5iwIZoTfJJiC3MQnwuLjyJoCU7hsq5FkLnv5GEye0QNdi5fCXt+bx+NT+T/DHaFxOEPDl+R0nQI3JfK75/LKC7qKDyKKnfJjHA5aK9zdmS35FVoToqU506ZBOnGxErjahF/gnbuUfVLPACFWYRj/7VSWBR6aDZfJLQEL+Yr4aN53NUyWicyOh1+nKwMrBhSO7wUcZSBzAxaw9RsCFjcE8RI9cUw== 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=vszfFQY6HkZ2cM0O92DsJHkJ6U5K1ANyHXF2RgX4OFQ=; b=Dl4qd9OyOvR91Ah5CYZwg66aa4LQMDYOe7o9j5WLkbvQlCGXdOUKJRr21lr3d9W/OlpNHsZ0i6/u9zRFpG29onRKPY/HQCjg5NpxZAr91B9thVpTg6x3mlIZxEzZahIoU5xT1Wj81ETvyGqQmRescckdUzT2aIBbFODIA3LH8ak= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:54:01 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:01 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 26/43] wifi: nxpwifi: add sdio.c Date: Fri, 21 Jun 2024 15:51:51 +0800 Message-Id: <20240621075208.513497-27-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 793aa944-07f5-46fc-76b5-08dc91c7500c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?n13wZDTgMULy1WeseyjyAUrNWSyjbT8BWg/dfC2TM5+USYFi7uS27flT4AEQ?= =?us-ascii?Q?vQBoEoxiqTMdAr9QSLNRW6V+tBBfj/y9bqozhqzkITllGr00cWKwIJcExZIs?= =?us-ascii?Q?bHJCZ4704PF3OcRwy/dO+SCLHtYIRabQPu3lAftzfgQPdU3eP2iwQBn5PN2s?= =?us-ascii?Q?liHIiejFZFDCvOvg5HoLjrwZ6kpQDsF+KOoeFxViisgAzcbPoNznJvaWzwl0?= =?us-ascii?Q?fb0rEJy2nW+WKSfkUxM4mswZlQS7ujcHGigfuH6dGmKkC7lTYRW9OqjxJLtf?= =?us-ascii?Q?RxWsLj0SvEcrjGhOPzx/1yc5h8i5en37EjQTu+I6xANUsuLp11hGUgEdao9T?= =?us-ascii?Q?oX7Ylyk5+zwKBp429LqLIM7DM4Cw6Z+xPAenpNk68rIsj8YCHdFMxyF0fS3o?= =?us-ascii?Q?c7Ye79NBHsK9zJdPiW0i+ByVnFWqf04YogVw20vDFhSdJqMECYBwH5Gy0lB1?= =?us-ascii?Q?WQtHDg1eE9R2Lm/VWtqDWGIMuHtYHIpglbtJ6zWn/RQ9qAbncJFjEDX2w2tM?= =?us-ascii?Q?IoHZTPI6a48cWHeKk7w4zohZp2m8LGKmgmzYW+B2nM6iegmcCbcvuwNrbObW?= =?us-ascii?Q?Nx3zTzkRHEe9r91+vl8whYACdYEnKtbLQ5EhLRYJXsKjywtfODfDaeY6Xtaq?= =?us-ascii?Q?C/ZhuMwXO1UvKeZ3dVJTSmpvqFMfqfornZNKippXz+jqFkwIloG47YKrUW9u?= =?us-ascii?Q?bUHE63kJctKH9RgDob6JN5lMRjs3GcJ8p0Ct1bhKbISmkgPB1RDlwsiietUQ?= =?us-ascii?Q?3eNTi87eI1R8hB4Boq/sPKObiB3X54MLIOBj/EiRS0VHMDX537Xts5CCuO1c?= =?us-ascii?Q?Qhb6YZQlL+ZgS5aE4V1UdjDz4eWsBKmeUmAUiBrOxML4l0puGIxC3QUts2rt?= =?us-ascii?Q?JbhchPRT0md3ZB16T92JyRyqV2Ni82U1bw+W+sYTq93Tq3tiYePSbLT01dH1?= =?us-ascii?Q?JmC4sfCXB7Ej2RI0N1ioB7P/L/dJt4Or5bh9xADuahahsHAqiVkc9wVfO852?= =?us-ascii?Q?g9ch5mo9pEM5wP4sRZSeeGG3KQKDXxs44TtJEF1BibnCWcqJNDfZin75KISi?= =?us-ascii?Q?cDADXdfJO0sM/wAOvUvYmEarHYsfk5dZFvmzgmMyufblMJHzEAypcXVkHN4+?= =?us-ascii?Q?uiLAEdvDnSXN25DXmnSBQS4VBoV44lvacJuuncufFbz+FAHpx2fBtn7+y8Zj?= =?us-ascii?Q?ZGiSsWA1L2l9+tIpRIQD+YZSrqD/SLk/c1axLOu9bKA8JyLR9HkM0ZN5jfz3?= =?us-ascii?Q?Xof9mAF8mB65795AdEfuPapFeU6wg2BkVUfyDxSwDbAlQwTNxcVfgE6HRtIp?= =?us-ascii?Q?4e3whloCFRpr7D8qIpE7xXAtg3lPu3vcIQGNx/XdA1CXyvuPFLsiYZTkV7WF?= =?us-ascii?Q?DqkgLRw=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?WWzdSJkty7SKJ3TV4wraV/rFYJ7P3F0mUEye0NYlIxxhDUZjYSSoK06BXwKO?= =?us-ascii?Q?3/Y1RQAGqoe7XMiCe+ZANJ5JIzYHeDtGC334tFvMTsf108qsM05FCMBj5va7?= =?us-ascii?Q?P34ws8BmLYwTvgP9km+Tapqf8xYArzt2aNpaba0E8FCzGnYyh35lo+lD7SZg?= =?us-ascii?Q?dSG9FyLycoxNL/zjzprUG8tiLIZghkEWb5z2ZXMFC8SthT8ApdNbkPnfK4IO?= =?us-ascii?Q?q0JHVMlGG7xDFfaC3Gbf9LyQM2NTjYL7b2kxAXs8VUwiWtlEWO7px4tLL+07?= =?us-ascii?Q?Q1N2ZkFHG6Z0MK38LZAvIBqtzYXjN4qgpPaZ4DAyQWWwLDDK0PX/AgoaCEEw?= =?us-ascii?Q?UujQtYBgsoRsxQ+jebHIcRAQXyGcrJILCsExemd/SuJuiQC70NrUTUslGlLj?= =?us-ascii?Q?67ooyYoZVy8+WX1xDXQ3k6/AyUZ89H/2b3v2NN6mu9Ei5saPvVAOsoOXqy9s?= =?us-ascii?Q?gJ30q2/A1f6iddpH4xsX9fHYtL7T1yxr24PtbvXb3FpoDlbnklZejU9lrH4q?= =?us-ascii?Q?BKEKW5oADMJq+BFtznIBbmuGJgFbD11IHbMunYfZDGQbDjxPICNiIIpQEWdC?= =?us-ascii?Q?VHqwQSji2LOJB7OGFLss1rLlsKF1uSSmJtIkD2LjQLQQvQD/x4yuCLephuxp?= =?us-ascii?Q?XhebTk3JEMo8248VgClP1CHzOCgNxe5KNaj6MghhfAhMIRumwTrrR/EO9G/f?= =?us-ascii?Q?JaFnkr3FZCmw+5e+wjtws6/+yNj1GruQQHUBDR5LTh/2y7UqAScqku/oKihJ?= =?us-ascii?Q?XIe5h74KFLakODpBY2mLP3WSYF0f/udH7jG79DJZcYxlz4cBEd4i2BS4c8jz?= =?us-ascii?Q?XGNFkBBVUJGqTllzbQQkzebd2+NQVRi0H4fCwG+Hd7lWhM+rtFQrIwEmJg2a?= =?us-ascii?Q?VqVQpssLPQejhpyfED4wY/J9chnSULCaikpmSVXTJcceWgCbE7IjW6iit7hV?= =?us-ascii?Q?VyNav0A2Hfi4waTe8YQfAy4D1rFGRPFkOULJlKHnnlqosOX+PUWHACks8KKX?= =?us-ascii?Q?83pALxh45m6DMe4d6tDKGpPrcfrHZthqsvqocNVDBxbMTbHYfnvnFd/lp50V?= =?us-ascii?Q?UswhrvNvfl/3cuAEK+yLX+QWmndxaHx90dsFMZLXKuYCyk0wuHbn4bkvByYp?= =?us-ascii?Q?1dDp9ftEDiJtp6NJTupOMK5yqa5hEu9WlbYhKzXRcNADig17XYT5FxPw3UDP?= =?us-ascii?Q?5OKOmHfZfq7RHI8tS8Gl/q9Jk0EsP7+lMjugqCWLUprcixi9Iu0GfDzTAuv4?= =?us-ascii?Q?SAwgJ+fOd0MZgxyeEN8g9hOfwLflX5RADqfhIyuDpQdPKzxGn8G/ggf1fhwQ?= =?us-ascii?Q?cBkcMDx/p6vKmjk3DLt8mxA9GjVKhpQmemcR5rubOGvZsH30loSZVIG6Mc7q?= =?us-ascii?Q?wZ2mwEMnSZFGHensagJu1q/mTdfbryGAuEs9rCrNtTZ2UwfUAIKKDJtd+LVG?= =?us-ascii?Q?gdfgX6x1l8en4vJy3lSaCfxsZVbUjBAV3E631T9aLuJTVHzkcQS73fWS63XS?= =?us-ascii?Q?QRrz8+mYxcmFuCg7i2V32hjNFnaizkspV/jgmtVvH2KFtnYbUzrAH4+0ieY8?= =?us-ascii?Q?tOezVYSqq1bO8Z+ciJhOTnFM6W1sjM7AA4prJOgf?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 793aa944-07f5-46fc-76b5-08dc91c7500c X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:01.8493 (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: faUp+gmldIZbXIsLyhK8cgfhbFa8MT6Za8nKeKDPztxoQ6guY1LoJlLPQ+chQsWGzS/UXngNfyeY3CSgTrYcEw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sdio.c | 2646 +++++++++++++++++++++++ 1 file changed, 2646 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sdio.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sdio.c b/drivers/net/wireless= /nxp/nxpwifi/sdio.c new file mode 100644 index 000000000000..962c9b2f7db2 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sdio.c @@ -0,0 +1,2646 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: SDIO specific handling + * + * Copyright 2011-2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" +#include "sdio.h" + +#define SDIO_VERSION "1.0" + +static void nxpwifi_sdio_work(struct work_struct *work); + +static struct nxpwifi_if_ops sdio_ops; + +static const struct nxpwifi_sdio_card_reg nxpwifi_reg_iw61x =3D { + .start_rd_port =3D 0, + .start_wr_port =3D 0, + .base_0_reg =3D 0xF8, + .base_1_reg =3D 0xF9, + .poll_reg =3D 0x5C, + .host_int_enable =3D UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | + CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, + .host_int_rsr_reg =3D 0x4, + .host_int_status_reg =3D 0x0C, + .host_int_mask_reg =3D 0x08, + .host_strap_reg =3D 0xF4, + .host_strap_mask =3D 0x01, + .host_strap_value =3D 0x00, + .status_reg_0 =3D 0xE8, + .status_reg_1 =3D 0xE9, + .sdio_int_mask =3D 0xff, + .data_port_mask =3D 0xffffffff, + .io_port_0_reg =3D 0xE4, + .io_port_1_reg =3D 0xE5, + .io_port_2_reg =3D 0xE6, + .max_mp_regs =3D 196, + .rd_bitmap_l =3D 0x10, + .rd_bitmap_u =3D 0x11, + .rd_bitmap_1l =3D 0x12, + .rd_bitmap_1u =3D 0x13, + .wr_bitmap_l =3D 0x14, + .wr_bitmap_u =3D 0x15, + .wr_bitmap_1l =3D 0x16, + .wr_bitmap_1u =3D 0x17, + .rd_len_p0_l =3D 0x18, + .rd_len_p0_u =3D 0x19, + .card_misc_cfg_reg =3D 0xd8, + .card_cfg_2_1_reg =3D 0xd9, + .cmd_rd_len_0 =3D 0xc0, + .cmd_rd_len_1 =3D 0xc1, + .cmd_rd_len_2 =3D 0xc2, + .cmd_rd_len_3 =3D 0xc3, + .cmd_cfg_0 =3D 0xc4, + .cmd_cfg_1 =3D 0xc5, + .cmd_cfg_2 =3D 0xc6, + .cmd_cfg_3 =3D 0xc7, + .fw_dump_host_ready =3D 0xcc, + .fw_dump_ctrl =3D 0xf9, + .fw_dump_start =3D 0xf1, + .fw_dump_end =3D 0xf8, + .func1_dump_reg_start =3D 0x10, + .func1_dump_reg_end =3D 0x17, + .func1_scratch_reg =3D 0xE8, + .func1_spec_reg_num =3D 13, + .func1_spec_reg_table =3D {0x08, 0x58, 0x5C, 0x5D, 0x60, + 0x61, 0x62, 0x64, 0x65, 0x66, + 0x68, 0x69, 0x6a}, +}; + +static const struct nxpwifi_sdio_device nxpwifi_sdio_iw61x =3D { + .firmware =3D IW61X_SDIO_FW_NAME, + .reg =3D &nxpwifi_reg_iw61x, + .max_ports =3D 32, + .mp_agg_pkt_limit =3D 16, + .tx_buf_size =3D NXPWIFI_TX_DATA_BUF_SIZE_4K, + .mp_tx_agg_buf_size =3D NXPWIFI_MP_AGGR_BSIZE_MAX, + .mp_rx_agg_buf_size =3D NXPWIFI_MP_AGGR_BSIZE_MAX, + .can_dump_fw =3D true, + .fw_dump_enh =3D true, + .can_ext_scan =3D true, +}; + +static struct memory_type_mapping generic_mem_type_map[] =3D { + {"DUMP", NULL, 0, 0xDD}, +}; + +static struct memory_type_mapping mem_type_mapping_tbl[] =3D { + {"ITCM", NULL, 0, 0xF0}, + {"DTCM", NULL, 0, 0xF1}, + {"SQRAM", NULL, 0, 0xF2}, + {"APU", NULL, 0, 0xF3}, + {"CIU", NULL, 0, 0xF4}, + {"ICU", NULL, 0, 0xF5}, + {"MAC", NULL, 0, 0xF6}, + {"EXT7", NULL, 0, 0xF7}, + {"EXT8", NULL, 0, 0xF8}, + {"EXT9", NULL, 0, 0xF9}, + {"EXT10", NULL, 0, 0xFA}, + {"EXT11", NULL, 0, 0xFB}, + {"EXT12", NULL, 0, 0xFC}, + {"EXT13", NULL, 0, 0xFD}, + {"EXTLAST", NULL, 0, 0xFE}, +}; + +static const struct of_device_id nxpwifi_sdio_of_match_table[] __maybe_unu= sed =3D { + { } +}; + +/* This function parse device tree node using mmc subnode devicetree API. + * The device node is saved in card->plt_of_node. + * if the device tree node exist and include interrupts attributes, this + * function will also request platform specific wakeup interrupt. + */ +static int nxpwifi_sdio_probe_of(struct device *dev) +{ + if (!of_match_node(nxpwifi_sdio_of_match_table, dev->of_node)) { + dev_err(dev, "required compatible string missing\n"); + return -EINVAL; + } + + return 0; +} + +/* SDIO probe. + * + * This function probes an nxpwifi device and registers it. It allocates + * the card structure, enables SDIO function number and initiates the + * device registration and initialization procedure by adding a logical + * interface. + */ +static int +nxpwifi_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int ret; + struct sdio_mmc_card *card =3D NULL; + + pr_debug("info: vendor=3D0x%4.04X device=3D0x%4.04X class=3D%d function= =3D%d\n", + func->vendor, func->device, func->class, func->num); + + card =3D devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + init_completion(&card->fw_done); + + card->func =3D func; + + func->card->quirks |=3D MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + + if (id->driver_data) { + struct nxpwifi_sdio_device *data =3D (void *)id->driver_data; + + card->firmware =3D data->firmware; + card->firmware_sdiouart =3D data->firmware_sdiouart; + card->reg =3D data->reg; + card->max_ports =3D data->max_ports; + card->mp_agg_pkt_limit =3D data->mp_agg_pkt_limit; + card->tx_buf_size =3D data->tx_buf_size; + card->mp_tx_agg_buf_size =3D data->mp_tx_agg_buf_size; + card->mp_rx_agg_buf_size =3D data->mp_rx_agg_buf_size; + card->can_dump_fw =3D data->can_dump_fw; + card->fw_dump_enh =3D data->fw_dump_enh; + card->can_ext_scan =3D data->can_ext_scan; + INIT_WORK(&card->work, nxpwifi_sdio_work); + } + + sdio_claim_host(func); + ret =3D sdio_enable_func(func); + sdio_release_host(func); + + if (ret) { + dev_err(&func->dev, "failed to enable function\n"); + return ret; + } + + /* device tree node parsing and platform specific configuration*/ + if (func->dev.of_node) { + ret =3D nxpwifi_sdio_probe_of(&func->dev); + if (ret) + goto err_disable; + } + + ret =3D nxpwifi_add_card(card, &card->fw_done, &sdio_ops, + NXPWIFI_SDIO, &func->dev); + if (ret) { + dev_err(&func->dev, "add card failed\n"); + goto err_disable; + } + + return 0; + +err_disable: + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + + return ret; +} + +/* SDIO resume. + * + * Kernel needs to suspend all functions separately. Therefore all + * registered functions must have drivers with suspend and resume + * methods. Failing that the kernel simply removes the whole card. + * + * If already not resumed, this function turns on the traffic and + * sends a host sleep cancel request to the firmware. + */ +static int nxpwifi_sdio_resume(struct device *dev) +{ + struct sdio_func *func =3D dev_to_sdio_func(dev); + struct sdio_mmc_card *card; + struct nxpwifi_adapter *adapter; + + card =3D sdio_get_drvdata(func); + if (!card || !card->adapter) { + dev_err(dev, "resume: invalid card or adapter\n"); + return 0; + } + + adapter =3D card->adapter; + + if (!test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, WARN, + "device already resumed\n"); + return 0; + } + + clear_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags); + + /* Disable Host Sleep */ + nxpwifi_cancel_hs(nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA), + NXPWIFI_SYNC_CMD); + + nxpwifi_disable_wake(adapter); + + return 0; +} + +/* Write data into SDIO card register. Caller claims SDIO device. */ +static int +nxpwifi_write_reg_locked(struct sdio_func *func, u32 reg, u8 data) +{ + int ret =3D -1; + + sdio_writeb(func, data, reg, &ret); + return ret; +} + +/* This function writes data into SDIO card register. + */ +static int +nxpwifi_write_reg(struct nxpwifi_adapter *adapter, u32 reg, u8 data) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret; + + sdio_claim_host(card->func); + ret =3D nxpwifi_write_reg_locked(card->func, reg, data); + sdio_release_host(card->func); + + return ret; +} + +/* This function reads data from SDIO card register. + */ +static int +nxpwifi_read_reg(struct nxpwifi_adapter *adapter, u32 reg, u8 *data) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret =3D -1; + u8 val; + + sdio_claim_host(card->func); + val =3D sdio_readb(card->func, reg, &ret); + sdio_release_host(card->func); + + *data =3D val; + + return ret; +} + +/* This function writes multiple data into SDIO card memory. + * + * This does not work in suspended mode. + */ +static int +nxpwifi_write_data_sync(struct nxpwifi_adapter *adapter, + u8 *buffer, u32 pkt_len, u32 port) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret; + u8 blk_mode =3D + (port & NXPWIFI_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; + u32 blk_size =3D (blk_mode =3D=3D BLOCK_MODE) ? NXPWIFI_SDIO_BLOCK_SIZE := 1; + u32 blk_cnt =3D + (blk_mode =3D=3D + BLOCK_MODE) ? (pkt_len / + NXPWIFI_SDIO_BLOCK_SIZE) : pkt_len; + u32 ioport =3D (port & NXPWIFI_SDIO_IO_PORT_MASK); + + if (test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "%s: not allowed while suspended\n", __func__); + return -1; + } + + sdio_claim_host(card->func); + + ret =3D sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size); + + sdio_release_host(card->func); + + return ret; +} + +/* This function reads multiple data from SDIO card memory. + */ +static int nxpwifi_read_data_sync(struct nxpwifi_adapter *adapter, u8 *buf= fer, + u32 len, u32 port, u8 claim) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret; + u8 blk_mode =3D (port & NXPWIFI_SDIO_BYTE_MODE_MASK) ? BYTE_MODE + : BLOCK_MODE; + u32 blk_size =3D (blk_mode =3D=3D BLOCK_MODE) ? NXPWIFI_SDIO_BLOCK_SIZE := 1; + u32 blk_cnt =3D (blk_mode =3D=3D BLOCK_MODE) ? (len / NXPWIFI_SDIO_BLOCK_= SIZE) + : len; + u32 ioport =3D (port & NXPWIFI_SDIO_IO_PORT_MASK); + + if (claim) + sdio_claim_host(card->func); + + ret =3D sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size); + + if (claim) + sdio_release_host(card->func); + + return ret; +} + +/* This function reads the firmware status. + */ +static int +nxpwifi_sdio_read_fw_status(struct nxpwifi_adapter *adapter, u16 *dat) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + u8 fws0, fws1; + + if (nxpwifi_read_reg(adapter, reg->status_reg_0, &fws0)) + return -1; + + if (nxpwifi_read_reg(adapter, reg->status_reg_1, &fws1)) + return -1; + + *dat =3D (u16)((fws1 << 8) | fws0); + return 0; +} + +/* This function checks the firmware status in card. + */ +static int nxpwifi_check_fw_status(struct nxpwifi_adapter *adapter, + u32 poll_num) +{ + int ret =3D 0; + u16 firmware_stat =3D 0; + u32 tries; + + for (tries =3D 0; tries < poll_num; tries++) { + ret =3D nxpwifi_sdio_read_fw_status(adapter, &firmware_stat); + if (ret) + continue; + if (firmware_stat =3D=3D FIRMWARE_READY_SDIO) { + ret =3D 0; + break; + } + + msleep(100); + ret =3D -1; + } + + if (firmware_stat =3D=3D FIRMWARE_READY_SDIO) + /* firmware might pretend to be ready, when it's not. + * Wait a little bit more as a workaround. + */ + msleep(100); + + return ret; +} + +/* This function checks if WLAN is the winner. + */ +static int nxpwifi_check_winner_status(struct nxpwifi_adapter *adapter) +{ + int ret =3D 0; + u8 winner =3D 0; + struct sdio_mmc_card *card =3D adapter->card; + + if (nxpwifi_read_reg(adapter, card->reg->status_reg_0, &winner)) + return -1; + + if (winner) + adapter->winner =3D 0; + else + adapter->winner =3D 1; + + return ret; +} + +/* SDIO remove. + * + * This function removes the interface and frees up the card structure. + */ +static void +nxpwifi_sdio_remove(struct sdio_func *func) +{ + struct sdio_mmc_card *card; + struct nxpwifi_adapter *adapter; + struct nxpwifi_private *priv; + int ret =3D 0; + u16 firmware_stat; + + card =3D sdio_get_drvdata(func); + if (!card) + return; + + wait_for_completion(&card->fw_done); + + adapter =3D card->adapter; + if (!adapter || !adapter->priv_num) + return; + + nxpwifi_dbg(adapter, INFO, "info: SDIO func num=3D%d\n", func->num); + + ret =3D nxpwifi_sdio_read_fw_status(adapter, &firmware_stat); + if (!ret && firmware_stat =3D=3D FIRMWARE_READY_SDIO) { + nxpwifi_deauthenticate_all(adapter); + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + nxpwifi_disable_auto_ds(priv); + nxpwifi_init_shutdown_fw(priv, NXPWIFI_FUNC_SHUTDOWN); + } + + nxpwifi_remove_card(adapter); +} + +/* SDIO suspend. + * + * Kernel needs to suspend all functions separately. Therefore all + * registered functions must have drivers with suspend and resume + * methods. Failing that the kernel simply removes the whole card. + * + * If already not suspended, this function allocates and sends a host + * sleep activate request to the firmware and turns off the traffic. + */ +static int nxpwifi_sdio_suspend(struct device *dev) +{ + struct sdio_func *func =3D dev_to_sdio_func(dev); + struct sdio_mmc_card *card; + struct nxpwifi_adapter *adapter; + mmc_pm_flag_t pm_flag =3D 0; + int ret =3D 0; + + pm_flag =3D sdio_get_host_pm_caps(func); + pr_debug("cmd: %s: suspend: PM flag =3D 0x%x\n", + sdio_func_id(func), pm_flag); + if (!(pm_flag & MMC_PM_KEEP_POWER)) { + dev_err(dev, + "%s: cannot remain alive while host is suspended\n", + sdio_func_id(func)); + return -EPERM; + } + + card =3D sdio_get_drvdata(func); + if (!card) { + dev_err(dev, "suspend: invalid card\n"); + return 0; + } + + /* Might still be loading firmware */ + wait_for_completion(&card->fw_done); + + adapter =3D card->adapter; + if (!adapter) { + dev_err(dev, "adapter is not valid\n"); + return 0; + } + + if (!adapter->is_up) + return -EBUSY; + + nxpwifi_enable_wake(adapter); + + /* Enable the Host Sleep */ + if (!nxpwifi_enable_hs(adapter)) { + nxpwifi_dbg(adapter, ERROR, + "cmd: failed to suspend\n"); + clear_bit(NXPWIFI_IS_HS_ENABLING, &adapter->work_flags); + nxpwifi_disable_wake(adapter); + return -EFAULT; + } + + nxpwifi_dbg(adapter, INFO, + "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret =3D sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + + /* Indicate device suspended */ + set_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags); + clear_bit(NXPWIFI_IS_HS_ENABLING, &adapter->work_flags); + + return ret; +} + +static void nxpwifi_sdio_coredump(struct device *dev) +{ + struct sdio_func *func =3D dev_to_sdio_func(dev); + struct sdio_mmc_card *card; + + card =3D sdio_get_drvdata(func); + if (!test_and_set_bit(NXPWIFI_IFACE_WORK_DEVICE_DUMP, + &card->work_flags)) + schedule_work(&card->work); +} + +/* WLAN IDs */ +static const struct sdio_device_id nxpwifi_ids[] =3D { + {SDIO_DEVICE(SDIO_VENDOR_ID_NXP, SDIO_DEVICE_ID_NXP_IW61X), + .driver_data =3D (unsigned long)&nxpwifi_sdio_iw61x}, + {}, +}; + +MODULE_DEVICE_TABLE(sdio, nxpwifi_ids); + +static const struct dev_pm_ops nxpwifi_sdio_pm_ops =3D { + .suspend =3D nxpwifi_sdio_suspend, + .resume =3D nxpwifi_sdio_resume, +}; + +static struct sdio_driver nxpwifi_sdio =3D { + .name =3D "nxpwifi_sdio", + .id_table =3D nxpwifi_ids, + .probe =3D nxpwifi_sdio_probe, + .remove =3D nxpwifi_sdio_remove, + .drv =3D { + .owner =3D THIS_MODULE, + .coredump =3D nxpwifi_sdio_coredump, + .pm =3D &nxpwifi_sdio_pm_ops, + } +}; + +/* This function wakes up the card. + * + * A host power up command is written to the card configuration + * register to wake up the card. + */ +static int nxpwifi_pm_wakeup_card(struct nxpwifi_adapter *adapter) +{ + nxpwifi_dbg(adapter, EVENT, + "event: wakeup device...\n"); + + return nxpwifi_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); +} + +/* This function is called after the card has woken up. + * + * The card configuration register is reset. + */ +static int nxpwifi_pm_wakeup_card_complete(struct nxpwifi_adapter *adapter) +{ + nxpwifi_dbg(adapter, EVENT, + "cmd: wakeup device completed\n"); + + return nxpwifi_write_reg(adapter, CONFIGURATION_REG, 0); +} + +static int nxpwifi_sdio_dnld_fw(struct nxpwifi_adapter *adapter, + struct nxpwifi_fw_image *fw) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret; + + sdio_claim_host(card->func); + ret =3D nxpwifi_dnld_fw(adapter, fw); + sdio_release_host(card->func); + + return ret; +} + +/* This function is used to initialize IO ports for the + * chipsets supporting SDIO new mode. + */ +static int nxpwifi_init_sdio_new_mode(struct nxpwifi_adapter *adapter) +{ + u8 reg; + struct sdio_mmc_card *card =3D adapter->card; + + adapter->ioport =3D MEM_PORT; + + /* enable sdio new mode */ + if (nxpwifi_read_reg(adapter, card->reg->card_cfg_2_1_reg, ®)) + return -1; + if (nxpwifi_write_reg(adapter, card->reg->card_cfg_2_1_reg, + reg | CMD53_NEW_MODE)) + return -1; + + /* Configure cmd port and enable reading rx length from the register */ + if (nxpwifi_read_reg(adapter, card->reg->cmd_cfg_0, ®)) + return -1; + if (nxpwifi_write_reg(adapter, card->reg->cmd_cfg_0, + reg | CMD_PORT_RD_LEN_EN)) + return -1; + + /* Enable Dnld/Upld ready auto reset for cmd port after cmd53 is + * completed + */ + if (nxpwifi_read_reg(adapter, card->reg->cmd_cfg_1, ®)) + return -1; + if (nxpwifi_write_reg(adapter, card->reg->cmd_cfg_1, + reg | CMD_PORT_AUTO_EN)) + return -1; + + return 0; +} + +/* This function initializes the IO ports. + * + * The following operations are performed - + * - Read the IO ports (0, 1 and 2) + * - Set host interrupt Reset-To-Read to clear + * - Set auto re-enable interrupt + */ +static int nxpwifi_init_sdio_ioport(struct nxpwifi_adapter *adapter) +{ + u8 reg; + struct sdio_mmc_card *card =3D adapter->card; + + if (nxpwifi_init_sdio_new_mode(adapter)) + return -1; + + nxpwifi_dbg(adapter, INFO, + "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); + + /* Set Host interrupt reset to read to clear */ + if (nxpwifi_read_reg(adapter, card->reg->host_int_rsr_reg, ®)) + return -1; + if (nxpwifi_write_reg(adapter, card->reg->host_int_rsr_reg, + reg | card->reg->sdio_int_mask)) + return -1; + + /* Dnld/Upld ready set to auto reset */ + if (nxpwifi_read_reg(adapter, card->reg->card_misc_cfg_reg, ®)) + return -1; + if (nxpwifi_write_reg(adapter, card->reg->card_misc_cfg_reg, + reg | AUTO_RE_ENABLE_INT)) + return -1; + + return 0; +} + +/* This function sends data to the card. + */ +static int nxpwifi_write_data_to_card(struct nxpwifi_adapter *adapter, + u8 *payload, u32 pkt_len, u32 port) +{ + u32 i =3D 0; + int ret; + + do { + ret =3D nxpwifi_write_data_sync(adapter, payload, pkt_len, port); + if (ret) { + i++; + nxpwifi_dbg(adapter, ERROR, + "host_to_card, write iomem\t" + "(%d) failed: %d\n", i, ret); + if (nxpwifi_write_reg(adapter, CONFIGURATION_REG, 0x04)) + nxpwifi_dbg(adapter, ERROR, + "write CFG reg failed\n"); + + ret =3D -1; + if (i > MAX_WRITE_IOMEM_RETRY) + return ret; + } + } while (ret =3D=3D -1); + + return ret; +} + +/* This function gets the read port. + * + * If control port bit is set in MP read bitmap, the control port + * is returned, otherwise the current read port is returned and + * the value is increased (provided it does not reach the maximum + * limit, in which case it is reset to 1) + */ +static int nxpwifi_get_rd_port(struct nxpwifi_adapter *adapter, u8 *port) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + u32 rd_bitmap =3D card->mp_rd_bitmap; + + nxpwifi_dbg(adapter, DATA, + "data: mp_rd_bitmap=3D0x%08x\n", rd_bitmap); + + if (!(rd_bitmap & reg->data_port_mask)) + return -1; + + if (!(card->mp_rd_bitmap & (1 << card->curr_rd_port))) + return -1; + + /* We are now handling the SDIO data ports */ + card->mp_rd_bitmap &=3D (u32)(~(1 << card->curr_rd_port)); + *port =3D card->curr_rd_port; + + if (++card->curr_rd_port =3D=3D card->max_ports) + card->curr_rd_port =3D reg->start_rd_port; + + nxpwifi_dbg(adapter, DATA, + "data: port=3D%d mp_rd_bitmap=3D0x%08x -> 0x%08x\n", + *port, rd_bitmap, card->mp_rd_bitmap); + + return 0; +} + +/* This function gets the write port for data. + * + * The current write port is returned if available and the value is + * increased (provided it does not reach the maximum limit, in which + * case it is reset to 1) + */ +static int nxpwifi_get_wr_port_data(struct nxpwifi_adapter *adapter, u32 *= port) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + u32 wr_bitmap =3D card->mp_wr_bitmap; + + nxpwifi_dbg(adapter, DATA, + "data: mp_wr_bitmap=3D0x%08x\n", wr_bitmap); + + if (!(wr_bitmap & card->mp_data_port_mask)) { + adapter->data_sent =3D true; + return -EBUSY; + } + + if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { + card->mp_wr_bitmap &=3D (u32)(~(1 << card->curr_wr_port)); + *port =3D card->curr_wr_port; + if (++card->curr_wr_port =3D=3D card->mp_end_port) + card->curr_wr_port =3D reg->start_wr_port; + } else { + adapter->data_sent =3D true; + return -EBUSY; + } + + nxpwifi_dbg(adapter, DATA, + "data: port=3D%d mp_wr_bitmap=3D0x%08x -> 0x%08x\n", + *port, wr_bitmap, card->mp_wr_bitmap); + + return 0; +} + +/* This function polls the card status. + */ +static int +nxpwifi_sdio_poll_card_status(struct nxpwifi_adapter *adapter, u8 bits) +{ + struct sdio_mmc_card *card =3D adapter->card; + u32 tries; + u8 cs; + + for (tries =3D 0; tries < MAX_POLL_TRIES; tries++) { + if (nxpwifi_read_reg(adapter, card->reg->poll_reg, &cs)) + break; + else if ((cs & bits) =3D=3D bits) + return 0; + + usleep_range(10, 20); + } + + nxpwifi_dbg(adapter, ERROR, + "poll card status failed, tries =3D %d\n", tries); + + return -1; +} + +/* This function disables the host interrupt. + * + * The host interrupt mask is read, the disable bit is reset and + * written back to the card host interrupt mask register. + */ +static void nxpwifi_sdio_disable_host_int(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + struct sdio_func *func =3D card->func; + + sdio_claim_host(func); + nxpwifi_write_reg_locked(func, card->reg->host_int_mask_reg, 0); + sdio_release_irq(func); + sdio_release_host(func); +} + +/* This function reads the interrupt status from card. + */ +static void nxpwifi_interrupt_status(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + u8 sdio_ireg; + unsigned long flags; + + if (nxpwifi_read_data_sync(adapter, card->mp_regs, + card->reg->max_mp_regs, + REG_PORT | NXPWIFI_SDIO_BYTE_MODE_MASK, 0)) { + nxpwifi_dbg(adapter, ERROR, "read mp_regs failed\n"); + return; + } + + sdio_ireg =3D card->mp_regs[card->reg->host_int_status_reg]; + if (sdio_ireg) { + /* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS + * For SDIO new mode CMD port interrupts + * DN_LD_CMD_PORT_HOST_INT_STATUS and/or + * UP_LD_CMD_PORT_HOST_INT_STATUS + * Clear the interrupt status register + */ + nxpwifi_dbg(adapter, INTR, + "int: sdio_ireg =3D %#x\n", sdio_ireg); + spin_lock_irqsave(&adapter->int_lock, flags); + adapter->int_status |=3D sdio_ireg; + spin_unlock_irqrestore(&adapter->int_lock, flags); + } +} + +/* SDIO interrupt handler. + * + * This function reads the interrupt status from firmware and handles + * the interrupt in current thread (ksdioirqd) right away. + */ +static void +nxpwifi_sdio_interrupt(struct sdio_func *func) +{ + struct nxpwifi_adapter *adapter; + struct sdio_mmc_card *card; + + card =3D sdio_get_drvdata(func); + if (!card || !card->adapter) { + pr_err("int: func=3D%p card=3D%p adapter=3D%p\n", + func, card, card ? card->adapter : NULL); + return; + } + adapter =3D card->adapter; + + if (!adapter->pps_uapsd_mode && adapter->ps_state =3D=3D PS_STATE_SLEEP) + adapter->ps_state =3D PS_STATE_AWAKE; + + nxpwifi_interrupt_status(adapter); + nxpwifi_main_process(adapter); +} + +/* This function enables the host interrupt. + * + * The host interrupt enable mask is written to the card + * host interrupt mask register. + */ +static int nxpwifi_sdio_enable_host_int(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + struct sdio_func *func =3D card->func; + int ret; + + sdio_claim_host(func); + + /* Request the SDIO IRQ */ + ret =3D sdio_claim_irq(func, nxpwifi_sdio_interrupt); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "claim irq failed: ret=3D%d\n", ret); + goto out; + } + + /* Simply write the mask to the register */ + ret =3D nxpwifi_write_reg_locked(func, card->reg->host_int_mask_reg, + card->reg->host_int_enable); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "enable host interrupt failed\n"); + sdio_release_irq(func); + } + +out: + sdio_release_host(func); + return ret; +} + +/* This function gets a data buffer from the card. + */ +static int nxpwifi_sdio_card_to_host(struct nxpwifi_adapter *adapter, + u32 *type, u8 *buffer, + u32 npayload, u32 ioport) +{ + int ret; + u32 nb; + + if (!buffer) { + nxpwifi_dbg(adapter, ERROR, + "%s: buffer is NULL\n", __func__); + return -1; + } + + ret =3D nxpwifi_read_data_sync(adapter, buffer, npayload, ioport, 1); + + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "%s: read iomem failed: %d\n", __func__, + ret); + return -1; + } + + nb =3D get_unaligned_le16((buffer)); + if (nb > npayload) { + nxpwifi_dbg(adapter, ERROR, + "%s: invalid packet, nb=3D%d npayload=3D%d\n", + __func__, nb, npayload); + return -1; + } + + *type =3D get_unaligned_le16((buffer + 2)); + + return ret; +} + +/* This function downloads the firmware to the card. + * + * Firmware is downloaded to the card in blocks. Every block download + * is tested for CRC errors, and retried a number of times before + * returning failure. + */ +static int nxpwifi_prog_fw_w_helper(struct nxpwifi_adapter *adapter, + struct nxpwifi_fw_image *fw) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + int ret; + u8 *firmware =3D fw->fw_buf; + u32 firmware_len =3D fw->fw_len; + u32 offset =3D 0; + u8 base0, base1; + u8 *fwbuf; + u16 len =3D 0; + u32 txlen, tx_blocks =3D 0, tries; + u32 i =3D 0; + + if (!firmware_len) { + nxpwifi_dbg(adapter, ERROR, + "firmware image not found! Terminating download\n"); + return -1; + } + + nxpwifi_dbg(adapter, INFO, + "info: downloading FW image (%d bytes)\n", + firmware_len); + + /* Assume that the allocated buffer is 8-byte aligned */ + fwbuf =3D kzalloc(NXPWIFI_UPLD_SIZE, GFP_KERNEL); + if (!fwbuf) + return -ENOMEM; + + sdio_claim_host(card->func); + + /* Perform firmware data transfer */ + do { + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY + * bits + */ + ret =3D nxpwifi_sdio_poll_card_status(adapter, CARD_IO_READY | + DN_LD_CARD_RDY); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "FW download with helper:\t" + "poll status timeout @ %d\n", offset); + goto done; + } + + /* More data? */ + if (offset >=3D firmware_len) + break; + + for (tries =3D 0; tries < MAX_POLL_TRIES; tries++) { + ret =3D nxpwifi_read_reg(adapter, reg->base_0_reg, + &base0); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "dev BASE0 register read failed:\t" + "base0=3D%#04X(%d). Terminating dnld\n", + base0, base0); + goto done; + } + ret =3D nxpwifi_read_reg(adapter, reg->base_1_reg, + &base1); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "dev BASE1 register read failed:\t" + "base1=3D%#04X(%d). Terminating dnld\n", + base1, base1); + goto done; + } + len =3D (u16)(((base1 & 0xff) << 8) | (base0 & 0xff)); + + if (len) + break; + + usleep_range(10, 20); + } + + if (!len) { + break; + } else if (len > NXPWIFI_UPLD_SIZE) { + nxpwifi_dbg(adapter, ERROR, + "FW dnld failed @ %d, invalid length %d\n", + offset, len); + ret =3D -1; + goto done; + } + + txlen =3D len; + + if (len & BIT(0)) { + i++; + if (i > MAX_WRITE_IOMEM_RETRY) { + nxpwifi_dbg(adapter, ERROR, + "FW dnld failed @ %d, over max retry\n", + offset); + ret =3D -1; + goto done; + } + nxpwifi_dbg(adapter, ERROR, + "CRC indicated by the helper:\t" + "len =3D 0x%04X, txlen =3D %d\n", len, txlen); + len &=3D ~BIT(0); + /* Setting this to 0 to resend from same offset */ + txlen =3D 0; + } else { + i =3D 0; + + /* Set blocksize to transfer - checking for last + * block + */ + if (firmware_len - offset < txlen) + txlen =3D firmware_len - offset; + + tx_blocks =3D (txlen + NXPWIFI_SDIO_BLOCK_SIZE - 1) + / NXPWIFI_SDIO_BLOCK_SIZE; + + /* Copy payload to buffer */ + memmove(fwbuf, &firmware[offset], txlen); + } + + ret =3D nxpwifi_write_data_sync(adapter, fwbuf, tx_blocks * + NXPWIFI_SDIO_BLOCK_SIZE, + adapter->ioport); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "FW download, write iomem (%d) failed @ %d\n", + i, offset); + if (nxpwifi_write_reg(adapter, CONFIGURATION_REG, 0x04)) + nxpwifi_dbg(adapter, ERROR, + "write CFG reg failed\n"); + + ret =3D -1; + goto done; + } + + offset +=3D txlen; + } while (true); + + nxpwifi_dbg(adapter, MSG, + "info: FW download over, size %d bytes\n", offset); + + ret =3D 0; +done: + sdio_release_host(card->func); + kfree(fwbuf); + return ret; +} + +/* This function decodes sdio aggregation pkt. + * + * Based on the data block size and pkt_len, + * skb data will be decoded to few packets. + */ +static void nxpwifi_deaggr_sdio_pkt(struct nxpwifi_adapter *adapter, + struct sk_buff *skb) +{ + u32 total_pkt_len, pkt_len; + struct sk_buff *skb_deaggr; + u16 blk_size; + u8 blk_num; + u8 *data; + + data =3D skb->data; + total_pkt_len =3D skb->len; + + while (total_pkt_len >=3D (SDIO_HEADER_OFFSET + adapter->intf_hdr_len)) { + if (total_pkt_len < adapter->sdio_rx_block_size) + break; + blk_num =3D *(data + BLOCK_NUMBER_OFFSET); + blk_size =3D adapter->sdio_rx_block_size * blk_num; + if (blk_size > total_pkt_len) { + nxpwifi_dbg(adapter, ERROR, + "%s: error in blk_size,\t" + "blk_num=3D%d, blk_size=3D%d, total_pkt_len=3D%d\n", + __func__, blk_num, blk_size, total_pkt_len); + break; + } + pkt_len =3D get_unaligned_le16((data + + SDIO_HEADER_OFFSET)); + if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) { + nxpwifi_dbg(adapter, ERROR, + "%s: error in pkt_len,\t" + "pkt_len=3D%d, blk_size=3D%d\n", + __func__, pkt_len, blk_size); + break; + } + + skb_deaggr =3D nxpwifi_alloc_dma_align_buf(pkt_len, GFP_KERNEL); + if (!skb_deaggr) + break; + skb_put(skb_deaggr, pkt_len); + memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len); + skb_pull(skb_deaggr, adapter->intf_hdr_len); + + nxpwifi_handle_rx_packet(adapter, skb_deaggr); + data +=3D blk_size; + total_pkt_len -=3D blk_size; + } +} + +/* This function decodes a received packet. + * + * Based on the type, the packet is treated as either a data, or + * a command response, or an event, and the correct handler + * function is invoked. + */ +static int nxpwifi_decode_rx_packet(struct nxpwifi_adapter *adapter, + struct sk_buff *skb, u32 upld_typ) +{ + u8 *cmd_buf; + u16 pkt_len; + struct nxpwifi_rxinfo *rx_info; + + pkt_len =3D get_unaligned_le16(skb->data); + + if (upld_typ !=3D NXPWIFI_TYPE_AGGR_DATA) { + skb_trim(skb, pkt_len); + skb_pull(skb, adapter->intf_hdr_len); + } + + switch (upld_typ) { + case NXPWIFI_TYPE_AGGR_DATA: + nxpwifi_dbg(adapter, INFO, + "info: --- Rx: Aggr Data packet ---\n"); + rx_info =3D NXPWIFI_SKB_RXCB(skb); + rx_info->buf_type =3D NXPWIFI_TYPE_AGGR_DATA; + if (adapter->rx_work_enabled) { + skb_queue_tail(&adapter->rx_data_q, skb); + atomic_inc(&adapter->rx_pending); + adapter->data_received =3D true; + } else { + nxpwifi_deaggr_sdio_pkt(adapter, skb); + dev_kfree_skb_any(skb); + } + break; + + case NXPWIFI_TYPE_DATA: + nxpwifi_dbg(adapter, DATA, + "info: --- Rx: Data packet ---\n"); + if (adapter->rx_work_enabled) { + skb_queue_tail(&adapter->rx_data_q, skb); + adapter->data_received =3D true; + atomic_inc(&adapter->rx_pending); + } else { + nxpwifi_handle_rx_packet(adapter, skb); + } + break; + + case NXPWIFI_TYPE_CMD: + nxpwifi_dbg(adapter, CMD, + "info: --- Rx: Cmd Response ---\n"); + /* take care of curr_cmd =3D NULL case */ + if (!adapter->curr_cmd) { + cmd_buf =3D adapter->upld_buf; + + if (adapter->ps_state =3D=3D PS_STATE_SLEEP_CFM) + nxpwifi_process_sleep_confirm_resp(adapter, + skb->data, + skb->len); + + memcpy(cmd_buf, skb->data, + min_t(u32, NXPWIFI_SIZE_OF_CMD_BUFFER, + skb->len)); + + dev_kfree_skb_any(skb); + } else { + adapter->cmd_resp_received =3D true; + adapter->curr_cmd->resp_skb =3D skb; + } + break; + + case NXPWIFI_TYPE_EVENT: + nxpwifi_dbg(adapter, EVENT, + "info: --- Rx: Event ---\n"); + adapter->event_cause =3D get_unaligned_le32(skb->data); + + if (skb->len > 0 && skb->len < MAX_EVENT_SIZE) + memcpy(adapter->event_body, + skb->data + NXPWIFI_EVENT_HEADER_LEN, + skb->len); + + /* event cause has been saved to adapter->event_cause */ + adapter->event_received =3D true; + adapter->event_skb =3D skb; + + break; + + default: + nxpwifi_dbg(adapter, ERROR, + "unknown upload type %#x\n", upld_typ); + dev_kfree_skb_any(skb); + break; + } + + return 0; +} + +/* This function transfers received packets from card to driver, performing + * aggregation if required. + * + * For data received on control port, or if aggregation is disabled, the + * received buffers are uploaded as separate packets. However, if aggregat= ion + * is enabled and required, the buffers are copied onto an aggregation buf= fer, + * provided there is space left, processed and finally uploaded. + */ +static int nxpwifi_sdio_card_to_host_mp_aggr(struct nxpwifi_adapter *adapt= er, + u16 rx_len, u8 port) +{ + struct sdio_mmc_card *card =3D adapter->card; + s32 f_do_rx_aggr =3D 0; + s32 f_do_rx_cur =3D 0; + s32 f_aggr_cur =3D 0; + s32 f_post_aggr_cur =3D 0; + struct sk_buff *skb_deaggr; + struct sk_buff *skb =3D NULL; + u32 pkt_len, pkt_type, mport, pind; + u8 *curr_ptr; + + if (!card->mpa_rx.enabled) { + nxpwifi_dbg(adapter, WARN, + "info: %s: rx aggregation disabled\n", + __func__); + + f_do_rx_cur =3D 1; + goto rx_curr_single; + } + + if (card->mp_rd_bitmap & card->reg->data_port_mask) { + /* Some more data RX pending */ + nxpwifi_dbg(adapter, INFO, + "info: %s: not last packet\n", __func__); + + if (MP_RX_AGGR_IN_PROGRESS(card)) { + if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) { + f_aggr_cur =3D 1; + } else { + /* No room in Aggr buf, do rx aggr now */ + f_do_rx_aggr =3D 1; + f_post_aggr_cur =3D 1; + } + } else { + /* Rx aggr not in progress */ + f_aggr_cur =3D 1; + } + + } else { + /* No more data RX pending */ + nxpwifi_dbg(adapter, INFO, + "info: %s: last packet\n", __func__); + + if (MP_RX_AGGR_IN_PROGRESS(card)) { + f_do_rx_aggr =3D 1; + if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) + f_aggr_cur =3D 1; + else + /* No room in Aggr buf, do rx aggr now */ + f_do_rx_cur =3D 1; + } else { + f_do_rx_cur =3D 1; + } + } + + if (f_aggr_cur) { + nxpwifi_dbg(adapter, INFO, + "info: current packet aggregation\n"); + /* Curr pkt can be aggregated */ + mp_rx_aggr_setup(card, rx_len, port); + + if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || + mp_rx_aggr_port_limit_reached(card)) { + nxpwifi_dbg(adapter, INFO, + "info: %s: aggregated packet\t" + "limit reached\n", __func__); + /* No more pkts allowed in Aggr buf, rx it */ + f_do_rx_aggr =3D 1; + } + } + + if (f_do_rx_aggr) { + u32 port_count; + int i; + + /* do aggr RX now */ + nxpwifi_dbg(adapter, DATA, + "info: do_rx_aggr: num of packets: %d\n", + card->mpa_rx.pkt_cnt); + + for (i =3D 0, port_count =3D 0; i < card->max_ports; i++) + if (card->mpa_rx.ports & BIT(i)) + port_count++; + + /* Reading data from "start_port + 0" to "start_port + + * port_count -1", so decrease the count by 1 + */ + port_count--; + mport =3D (adapter->ioport | SDIO_MPA_ADDR_BASE | + (port_count << 8)) + card->mpa_rx.start_port; + + if (card->mpa_rx.pkt_cnt =3D=3D 1) + mport =3D adapter->ioport + card->mpa_rx.start_port; + + if (nxpwifi_read_data_sync(adapter, card->mpa_rx.buf, + card->mpa_rx.buf_len, mport, 1)) + goto error; + + curr_ptr =3D card->mpa_rx.buf; + + for (pind =3D 0; pind < card->mpa_rx.pkt_cnt; pind++) { + u32 *len_arr =3D card->mpa_rx.len_arr; + + /* get curr PKT len & type */ + pkt_len =3D get_unaligned_le16(&curr_ptr[0]); + pkt_type =3D get_unaligned_le16(&curr_ptr[2]); + + /* copy pkt to deaggr buf */ + skb_deaggr =3D nxpwifi_alloc_dma_align_buf(len_arr[pind], + GFP_KERNEL); + if (!skb_deaggr) { + nxpwifi_dbg(adapter, ERROR, "skb allocation failure\t" + "drop pkt len=3D%d type=3D%d\n", + pkt_len, pkt_type); + curr_ptr +=3D len_arr[pind]; + continue; + } + + skb_put(skb_deaggr, len_arr[pind]); + + if ((pkt_type =3D=3D NXPWIFI_TYPE_DATA || + (pkt_type =3D=3D NXPWIFI_TYPE_AGGR_DATA && + adapter->sdio_rx_aggr_enable)) && + pkt_len <=3D len_arr[pind]) { + memcpy(skb_deaggr->data, curr_ptr, pkt_len); + + skb_trim(skb_deaggr, pkt_len); + + /* Process de-aggr packet */ + nxpwifi_decode_rx_packet(adapter, skb_deaggr, + pkt_type); + } else { + nxpwifi_dbg(adapter, ERROR, + "drop wrong aggr pkt:\t" + "sdio_single_port_rx_aggr=3D%d\t" + "type=3D%d len=3D%d max_len=3D%d\n", + adapter->sdio_rx_aggr_enable, + pkt_type, pkt_len, len_arr[pind]); + dev_kfree_skb_any(skb_deaggr); + } + curr_ptr +=3D len_arr[pind]; + } + MP_RX_AGGR_BUF_RESET(card); + } + +rx_curr_single: + if (f_do_rx_cur) { + nxpwifi_dbg(adapter, INFO, "info: RX: port: %d, rx_len: %d\n", + port, rx_len); + + skb =3D nxpwifi_alloc_dma_align_buf(rx_len, GFP_KERNEL); + if (!skb) { + nxpwifi_dbg(adapter, ERROR, + "single skb allocated fail,\t" + "drop pkt port=3D%d len=3D%d\n", port, rx_len); + if (nxpwifi_sdio_card_to_host(adapter, &pkt_type, + card->mpa_rx.buf, rx_len, + adapter->ioport + port)) + goto error; + return 0; + } + + skb_put(skb, rx_len); + + if (nxpwifi_sdio_card_to_host(adapter, &pkt_type, + skb->data, skb->len, + adapter->ioport + port)) + goto error; + if (!adapter->sdio_rx_aggr_enable && + pkt_type =3D=3D NXPWIFI_TYPE_AGGR_DATA) { + nxpwifi_dbg(adapter, ERROR, "drop wrong pkt type %d\t" + "current SDIO RX Aggr not enabled\n", + pkt_type); + dev_kfree_skb_any(skb); + return 0; + } + + nxpwifi_decode_rx_packet(adapter, skb, pkt_type); + } + if (f_post_aggr_cur) { + nxpwifi_dbg(adapter, INFO, + "info: current packet aggregation\n"); + /* Curr pkt can be aggregated */ + mp_rx_aggr_setup(card, rx_len, port); + } + + return 0; +error: + if (MP_RX_AGGR_IN_PROGRESS(card)) + MP_RX_AGGR_BUF_RESET(card); + + if (f_do_rx_cur && skb) + /* Single transfer pending. Free curr buff also */ + dev_kfree_skb_any(skb); + + return -1; +} + +/* This function checks the current interrupt status. + * + * The following interrupts are checked and handled by this function - + * - Data sent + * - Command sent + * - Packets received + * + * Since the firmware does not generate download ready interrupt if the + * port updated is command port only, command sent interrupt checking + * should be done manually, and for every SDIO interrupt. + * + * In case of Rx packets received, the packets are uploaded from card to + * host and processed accordingly. + */ +static int nxpwifi_process_int_status(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + int ret =3D 0; + u8 sdio_ireg; + struct sk_buff *skb; + u8 port; + u32 len_reg_l, len_reg_u; + u32 rx_blocks; + u16 rx_len; + unsigned long flags; + u32 bitmap; + u8 cr; + + spin_lock_irqsave(&adapter->int_lock, flags); + sdio_ireg =3D adapter->int_status; + adapter->int_status =3D 0; + spin_unlock_irqrestore(&adapter->int_lock, flags); + + if (!sdio_ireg) + return ret; + + /* Following interrupt is only for SDIO new mode */ + if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS && adapter->cmd_sent) + adapter->cmd_sent =3D false; + + /* Following interrupt is only for SDIO new mode */ + if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) { + u32 pkt_type; + + /* read the len of control packet */ + rx_len =3D card->mp_regs[reg->cmd_rd_len_1] << 8; + rx_len |=3D (u16)card->mp_regs[reg->cmd_rd_len_0]; + rx_blocks =3D DIV_ROUND_UP(rx_len, NXPWIFI_SDIO_BLOCK_SIZE); + if (rx_len <=3D adapter->intf_hdr_len || + (rx_blocks * NXPWIFI_SDIO_BLOCK_SIZE) > + NXPWIFI_RX_DATA_BUF_SIZE) + return -1; + rx_len =3D (u16)(rx_blocks * NXPWIFI_SDIO_BLOCK_SIZE); + nxpwifi_dbg(adapter, INFO, "info: rx_len =3D %d\n", rx_len); + + skb =3D nxpwifi_alloc_dma_align_buf(rx_len, GFP_KERNEL); + if (!skb) + return -1; + + skb_put(skb, rx_len); + + if (nxpwifi_sdio_card_to_host(adapter, &pkt_type, skb->data, + skb->len, adapter->ioport | + CMD_PORT_SLCT)) { + nxpwifi_dbg(adapter, ERROR, + "%s: failed to card_to_host", __func__); + dev_kfree_skb_any(skb); + goto term_cmd; + } + + if (pkt_type !=3D NXPWIFI_TYPE_CMD && + pkt_type !=3D NXPWIFI_TYPE_EVENT) + nxpwifi_dbg(adapter, ERROR, + "%s:Received wrong packet on cmd port", + __func__); + + nxpwifi_decode_rx_packet(adapter, skb, pkt_type); + } + + if (sdio_ireg & DN_LD_HOST_INT_STATUS) { + bitmap =3D (u32)card->mp_regs[reg->wr_bitmap_l]; + bitmap |=3D ((u32)card->mp_regs[reg->wr_bitmap_u]) << 8; + bitmap |=3D ((u32)card->mp_regs[reg->wr_bitmap_1l]) << 16; + bitmap |=3D ((u32)card->mp_regs[reg->wr_bitmap_1u]) << 24; + card->mp_wr_bitmap =3D bitmap; + + nxpwifi_dbg(adapter, INTR, + "int: DNLD: wr_bitmap=3D0x%x\n", + card->mp_wr_bitmap); + if (adapter->data_sent && + (card->mp_wr_bitmap & card->mp_data_port_mask)) { + nxpwifi_dbg(adapter, INTR, + "info: <--- Tx DONE Interrupt --->\n"); + adapter->data_sent =3D false; + } + } + + nxpwifi_dbg(adapter, INTR, "info: cmd_sent=3D%d data_sent=3D%d\n", + adapter->cmd_sent, adapter->data_sent); + if (sdio_ireg & UP_LD_HOST_INT_STATUS) { + bitmap =3D (u32)card->mp_regs[reg->rd_bitmap_l]; + bitmap |=3D ((u32)card->mp_regs[reg->rd_bitmap_u]) << 8; + bitmap |=3D ((u32)card->mp_regs[reg->rd_bitmap_1l]) << 16; + bitmap |=3D ((u32)card->mp_regs[reg->rd_bitmap_1u]) << 24; + card->mp_rd_bitmap =3D bitmap; + nxpwifi_dbg(adapter, INTR, + "int: UPLD: rd_bitmap=3D0x%x\n", + card->mp_rd_bitmap); + + while (true) { + ret =3D nxpwifi_get_rd_port(adapter, &port); + if (ret) { + nxpwifi_dbg(adapter, INFO, + "info: no more rd_port available\n"); + break; + } + len_reg_l =3D reg->rd_len_p0_l + (port << 1); + len_reg_u =3D reg->rd_len_p0_u + (port << 1); + rx_len =3D ((u16)card->mp_regs[len_reg_u]) << 8; + rx_len |=3D (u16)card->mp_regs[len_reg_l]; + nxpwifi_dbg(adapter, INFO, + "info: RX: port=3D%d rx_len=3D%u\n", + port, rx_len); + rx_blocks =3D + (rx_len + NXPWIFI_SDIO_BLOCK_SIZE - + 1) / NXPWIFI_SDIO_BLOCK_SIZE; + if (rx_len <=3D adapter->intf_hdr_len || + (card->mpa_rx.enabled && + ((rx_blocks * NXPWIFI_SDIO_BLOCK_SIZE) > + card->mpa_rx.buf_size))) { + nxpwifi_dbg(adapter, ERROR, + "invalid rx_len=3D%d\n", + rx_len); + return -1; + } + + rx_len =3D (u16)(rx_blocks * NXPWIFI_SDIO_BLOCK_SIZE); + nxpwifi_dbg(adapter, INFO, "info: rx_len =3D %d\n", + rx_len); + + if (nxpwifi_sdio_card_to_host_mp_aggr(adapter, rx_len, + port)) { + nxpwifi_dbg(adapter, ERROR, + "card_to_host_mpa failed: int status=3D%#x\n", + sdio_ireg); + goto term_cmd; + } + } + } + + return 0; + +term_cmd: + /* terminate cmd */ + if (nxpwifi_read_reg(adapter, CONFIGURATION_REG, &cr)) + nxpwifi_dbg(adapter, ERROR, "read CFG reg failed\n"); + else + nxpwifi_dbg(adapter, INFO, + "info: CFG reg val =3D %d\n", cr); + + if (nxpwifi_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04))) + nxpwifi_dbg(adapter, ERROR, + "write CFG reg failed\n"); + else + nxpwifi_dbg(adapter, INFO, "info: write success\n"); + + if (nxpwifi_read_reg(adapter, CONFIGURATION_REG, &cr)) + nxpwifi_dbg(adapter, ERROR, + "read CFG reg failed\n"); + else + nxpwifi_dbg(adapter, INFO, + "info: CFG reg val =3D%x\n", cr); + + return -1; +} + +/* This function aggregates transmission buffers in driver and downloads + * the aggregated packet to card. + * + * The individual packets are aggregated by copying into an aggregation + * buffer and then downloaded to the card. Previous unsent packets in the + * aggregation buffer are pre-copied first before new packets are added. + * Aggregation is done till there is space left in the aggregation buffer, + * or till new packets are available. + * + * The function will only download the packet to the card when aggregation + * stops, otherwise it will just aggregate the packet in aggregation buffer + * and return. + */ +static int nxpwifi_host_to_card_mp_aggr(struct nxpwifi_adapter *adapter, + u8 *payload, u32 pkt_len, u32 port, + u32 next_pkt_len) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret =3D 0; + s32 f_send_aggr_buf =3D 0; + s32 f_send_cur_buf =3D 0; + s32 f_precopy_cur_buf =3D 0; + s32 f_postcopy_cur_buf =3D 0; + u32 mport; + int index; + + if (!card->mpa_tx.enabled || port =3D=3D CMD_PORT_SLCT) { + nxpwifi_dbg(adapter, WARN, + "info: %s: tx aggregation disabled\n", + __func__); + + f_send_cur_buf =3D 1; + goto tx_curr_single; + } + + if (next_pkt_len) { + /* More pkt in TX queue */ + nxpwifi_dbg(adapter, INFO, + "info: %s: more packets in queue.\n", + __func__); + + if (MP_TX_AGGR_IN_PROGRESS(card)) { + if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) { + f_precopy_cur_buf =3D 1; + + if (!(card->mp_wr_bitmap & + (1 << card->curr_wr_port)) || + !MP_TX_AGGR_BUF_HAS_ROOM + (card, pkt_len + next_pkt_len)) + f_send_aggr_buf =3D 1; + } else { + /* No room in Aggr buf, send it */ + f_send_aggr_buf =3D 1; + + if (!(card->mp_wr_bitmap & + (1 << card->curr_wr_port))) + f_send_cur_buf =3D 1; + else + f_postcopy_cur_buf =3D 1; + } + } else { + if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) && + (card->mp_wr_bitmap & (1 << card->curr_wr_port))) + f_precopy_cur_buf =3D 1; + else + f_send_cur_buf =3D 1; + } + } else { + /* Last pkt in TX queue */ + nxpwifi_dbg(adapter, INFO, + "info: %s: Last packet in Tx Queue.\n", + __func__); + + if (MP_TX_AGGR_IN_PROGRESS(card)) { + /* some packs in Aggr buf already */ + f_send_aggr_buf =3D 1; + + if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) + f_precopy_cur_buf =3D 1; + else + /* No room in Aggr buf, send it */ + f_send_cur_buf =3D 1; + } else { + f_send_cur_buf =3D 1; + } + } + + if (f_precopy_cur_buf) { + nxpwifi_dbg(adapter, DATA, + "data: %s: precopy current buffer\n", + __func__); + MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); + + if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) || + mp_tx_aggr_port_limit_reached(card)) + /* No more pkts allowed in Aggr buf, send it */ + f_send_aggr_buf =3D 1; + } + + if (f_send_aggr_buf) { + u32 port_count; + int i; + + nxpwifi_dbg(adapter, DATA, + "data: %s: send aggr buffer: %d %d\n", + __func__, card->mpa_tx.start_port, + card->mpa_tx.ports); + + for (i =3D 0, port_count =3D 0; i < card->max_ports; i++) + if (card->mpa_tx.ports & BIT(i)) + port_count++; + + /* Writing data from "start_port + 0" to "start_port + + * port_count -1", so decrease the count by 1 + */ + port_count--; + mport =3D (adapter->ioport | SDIO_MPA_ADDR_BASE | + (port_count << 8)) + card->mpa_tx.start_port; + + if (card->mpa_tx.pkt_cnt =3D=3D 1) + mport =3D adapter->ioport + card->mpa_tx.start_port; + + ret =3D nxpwifi_write_data_to_card(adapter, card->mpa_tx.buf, + card->mpa_tx.buf_len, mport); + + /* Save the last multi port tx aggregation info to debug log */ + index =3D adapter->dbg.last_sdio_mp_index; + index =3D (index + 1) % NXPWIFI_DBG_SDIO_MP_NUM; + adapter->dbg.last_sdio_mp_index =3D index; + adapter->dbg.last_mp_wr_ports[index] =3D mport; + adapter->dbg.last_mp_wr_bitmap[index] =3D card->mp_wr_bitmap; + adapter->dbg.last_mp_wr_len[index] =3D card->mpa_tx.buf_len; + adapter->dbg.last_mp_curr_wr_port[index] =3D card->curr_wr_port; + + MP_TX_AGGR_BUF_RESET(card); + } + +tx_curr_single: + if (f_send_cur_buf) { + nxpwifi_dbg(adapter, DATA, + "data: %s: send current buffer %d\n", + __func__, port); + ret =3D nxpwifi_write_data_to_card(adapter, payload, pkt_len, + adapter->ioport + port); + } + + if (f_postcopy_cur_buf) { + nxpwifi_dbg(adapter, DATA, + "data: %s: postcopy current buffer\n", + __func__); + MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); + } + + return ret; +} + +/* This function downloads data from driver to card. + * + * Both commands and data packets are transferred to the card by this + * function. + * + * This function adds the SDIO specific header to the front of the buffer + * before transferring. The header contains the length of the packet and + * the type. The firmware handles the packets based upon this set type. + */ +static int nxpwifi_sdio_host_to_card(struct nxpwifi_adapter *adapter, + u8 type, struct sk_buff *skb, + struct nxpwifi_tx_param *tx_param) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret; + u32 buf_block_len; + u32 blk_size; + u32 port; + u8 *payload =3D (u8 *)skb->data; + u32 pkt_len =3D skb->len; + + /* Allocate buffer and copy payload */ + blk_size =3D NXPWIFI_SDIO_BLOCK_SIZE; + buf_block_len =3D (pkt_len + blk_size - 1) / blk_size; + put_unaligned_le16((u16)pkt_len, payload + 0); + put_unaligned_le16((u16)type, payload + 2); + + /* This is SDIO specific header + * u16 length, + * u16 type (NXPWIFI_TYPE_DATA =3D 0, NXPWIFI_TYPE_CMD =3D 1, + * NXPWIFI_TYPE_EVENT =3D 3) + */ + if (type =3D=3D NXPWIFI_TYPE_DATA) { + ret =3D nxpwifi_get_wr_port_data(adapter, &port); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "%s: no wr_port available\n", + __func__); + return ret; + } + } else { + adapter->cmd_sent =3D true; + /* Type must be NXPWIFI_TYPE_CMD */ + + if (pkt_len <=3D adapter->intf_hdr_len || + pkt_len > NXPWIFI_UPLD_SIZE) + nxpwifi_dbg(adapter, ERROR, + "%s: payload=3D%p, nb=3D%d\n", + __func__, payload, pkt_len); + + port =3D CMD_PORT_SLCT; + } + + /* Transfer data to card */ + pkt_len =3D buf_block_len * blk_size; + + if (tx_param) + ret =3D nxpwifi_host_to_card_mp_aggr(adapter, payload, pkt_len, + port, tx_param->next_pkt_len + ); + else + ret =3D nxpwifi_host_to_card_mp_aggr(adapter, payload, pkt_len, + port, 0); + + if (ret) { + if (type =3D=3D NXPWIFI_TYPE_CMD) + adapter->cmd_sent =3D false; + if (type =3D=3D NXPWIFI_TYPE_DATA) { + adapter->data_sent =3D false; + /* restore curr_wr_port in error cases */ + card->curr_wr_port =3D port; + card->mp_wr_bitmap |=3D (u32)(1 << card->curr_wr_port); + } + } else { + if (type =3D=3D NXPWIFI_TYPE_DATA) { + if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) + adapter->data_sent =3D true; + else + adapter->data_sent =3D false; + } + } + + return ret; +} + +/* This function allocates the MPA Tx and Rx buffers. + */ +static int nxpwifi_alloc_sdio_mpa_buffers(struct nxpwifi_adapter *adapter, + u32 mpa_tx_buf_size, + u32 mpa_rx_buf_size) +{ + struct sdio_mmc_card *card =3D adapter->card; + u32 rx_buf_size; + int ret =3D 0; + + card->mpa_tx.buf =3D kzalloc(mpa_tx_buf_size, GFP_KERNEL); + if (!card->mpa_tx.buf) { + ret =3D -1; + goto error; + } + + card->mpa_tx.buf_size =3D mpa_tx_buf_size; + + rx_buf_size =3D max_t(u32, mpa_rx_buf_size, + (u32)SDIO_MAX_AGGR_BUF_SIZE); + card->mpa_rx.buf =3D kzalloc(rx_buf_size, GFP_KERNEL); + if (!card->mpa_rx.buf) { + ret =3D -1; + goto error; + } + + card->mpa_rx.buf_size =3D rx_buf_size; + +error: + if (ret) { + kfree(card->mpa_tx.buf); + kfree(card->mpa_rx.buf); + card->mpa_tx.buf_size =3D 0; + card->mpa_rx.buf_size =3D 0; + card->mpa_tx.buf =3D NULL; + card->mpa_rx.buf =3D NULL; + } + + return ret; +} + +/* This function unregisters the SDIO device. + * + * The SDIO IRQ is released, the function is disabled and driver + * data is set to null. + */ +static void +nxpwifi_unregister_dev(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + + if (adapter->card) { + card->adapter =3D NULL; + sdio_claim_host(card->func); + sdio_disable_func(card->func); + sdio_release_host(card->func); + } +} + +/* This function registers the SDIO device. + * + * SDIO IRQ is claimed, block size is set and driver data is initialized. + */ +static int nxpwifi_register_dev(struct nxpwifi_adapter *adapter) +{ + int ret; + struct sdio_mmc_card *card =3D adapter->card; + struct sdio_func *func =3D card->func; + const char *firmware =3D card->firmware; + + /* save adapter pointer in card */ + card->adapter =3D adapter; + adapter->tx_buf_size =3D card->tx_buf_size; + + sdio_claim_host(func); + + /* Set block size */ + ret =3D sdio_set_block_size(card->func, NXPWIFI_SDIO_BLOCK_SIZE); + sdio_release_host(func); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "cannot set SDIO block size\n"); + return ret; + } + + /* Select correct firmware (sdsd or sdiouart) firmware based on the strap= ping + * option + */ + if (card->firmware_sdiouart) { + u8 val; + + nxpwifi_read_reg(adapter, card->reg->host_strap_reg, &val); + if ((val & card->reg->host_strap_mask) =3D=3D card->reg->host_strap_valu= e) + firmware =3D card->firmware_sdiouart; + } + strscpy(adapter->fw_name, firmware, sizeof(adapter->fw_name)); + + if (card->fw_dump_enh) { + adapter->mem_type_mapping_tbl =3D generic_mem_type_map; + adapter->num_mem_types =3D 1; + } else { + adapter->mem_type_mapping_tbl =3D mem_type_mapping_tbl; + adapter->num_mem_types =3D ARRAY_SIZE(mem_type_mapping_tbl); + } + + return 0; +} + +/* This function initializes the SDIO driver. + * + * The following initializations steps are followed - + * - Read the Host interrupt status register to acknowledge + * the first interrupt got from bootloader + * - Disable host interrupt mask register + * - Get SDIO port + * - Initialize SDIO variables in card + * - Allocate MP registers + * - Allocate MPA Tx and Rx buffers + */ +static int nxpwifi_init_sdio(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + int ret; + u8 sdio_ireg; + + sdio_set_drvdata(card->func, card); + + /* Read the host_int_status_reg for ACK the first interrupt got + * from the bootloader. If we don't do this we get a interrupt + * as soon as we register the irq. + */ + nxpwifi_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg); + + /* Get SDIO ioport */ + if (nxpwifi_init_sdio_ioport(adapter)) + return -EIO; + + /* Initialize SDIO variables in card */ + card->mp_rd_bitmap =3D 0; + card->mp_wr_bitmap =3D 0; + card->curr_rd_port =3D reg->start_rd_port; + card->curr_wr_port =3D reg->start_wr_port; + + card->mp_data_port_mask =3D reg->data_port_mask; + + card->mpa_tx.buf_len =3D 0; + card->mpa_tx.pkt_cnt =3D 0; + card->mpa_tx.start_port =3D 0; + + card->mpa_tx.enabled =3D 1; + card->mpa_tx.pkt_aggr_limit =3D card->mp_agg_pkt_limit; + + card->mpa_rx.buf_len =3D 0; + card->mpa_rx.pkt_cnt =3D 0; + card->mpa_rx.start_port =3D 0; + + card->mpa_rx.enabled =3D 1; + card->mpa_rx.pkt_aggr_limit =3D card->mp_agg_pkt_limit; + + /* Allocate buffers for SDIO MP-A */ + card->mp_regs =3D kzalloc(reg->max_mp_regs, GFP_KERNEL); + if (!card->mp_regs) + return -ENOMEM; + + card->mpa_rx.len_arr =3D kcalloc(card->mp_agg_pkt_limit, + sizeof(*card->mpa_rx.len_arr), + GFP_KERNEL); + if (!card->mpa_rx.len_arr) { + kfree(card->mp_regs); + return -ENOMEM; + } + + ret =3D nxpwifi_alloc_sdio_mpa_buffers(adapter, + card->mp_tx_agg_buf_size, + card->mp_rx_agg_buf_size); + + /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */ + if (ret && (card->mp_tx_agg_buf_size =3D=3D NXPWIFI_MP_AGGR_BSIZE_MAX || + card->mp_rx_agg_buf_size =3D=3D NXPWIFI_MP_AGGR_BSIZE_MAX)) { + /* Disable rx single port aggregation */ + adapter->host_disable_sdio_rx_aggr =3D true; + + ret =3D nxpwifi_alloc_sdio_mpa_buffers(adapter, + NXPWIFI_MP_AGGR_BSIZE_32K, + NXPWIFI_MP_AGGR_BSIZE_32K); + if (ret) { + /* Disable multi port aggregation */ + card->mpa_tx.enabled =3D 0; + card->mpa_rx.enabled =3D 0; + } + } + + adapter->ext_scan =3D card->can_ext_scan; + return 0; +} + +/* This function resets the MPA Tx and Rx buffers. + */ +static void nxpwifi_cleanup_mpa_buf(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + + MP_TX_AGGR_BUF_RESET(card); + MP_RX_AGGR_BUF_RESET(card); +} + +/* This function cleans up the allocated card buffers. + * + * The following are freed by this function - + * - MP registers + * - MPA Tx buffer + * - MPA Rx buffer + */ +static void nxpwifi_cleanup_sdio(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + + cancel_work_sync(&card->work); + + kfree(card->mp_regs); + kfree(card->mpa_rx.len_arr); + kfree(card->mpa_tx.buf); + kfree(card->mpa_rx.buf); +} + +/* This function updates the MP end port in card. + */ +static void +nxpwifi_update_mp_end_port(struct nxpwifi_adapter *adapter, u16 port) +{ + struct sdio_mmc_card *card =3D adapter->card; + const struct nxpwifi_sdio_card_reg *reg =3D card->reg; + int i; + + card->mp_end_port =3D port; + + card->mp_data_port_mask =3D reg->data_port_mask; + + if (reg->start_wr_port) { + for (i =3D 1; i <=3D card->max_ports - card->mp_end_port; i++) + card->mp_data_port_mask &=3D + ~(1 << (card->max_ports - i)); + } + + card->curr_wr_port =3D reg->start_wr_port; + + nxpwifi_dbg(adapter, CMD, + "cmd: mp_end_port %d, data port mask 0x%x\n", + port, card->mp_data_port_mask); +} + +static void nxpwifi_sdio_card_reset_work(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + struct sdio_func *func =3D card->func; + int ret; + + /* Prepare the adapter for the reset. */ + nxpwifi_shutdown_sw(adapter); + clear_bit(NXPWIFI_IFACE_WORK_DEVICE_DUMP, &card->work_flags); + clear_bit(NXPWIFI_IFACE_WORK_CARD_RESET, &card->work_flags); + + /* Run a HW reset of the SDIO interface. */ + sdio_claim_host(func); + ret =3D mmc_hw_reset(func->card); + sdio_release_host(func); + + switch (ret) { + case 1: + dev_dbg(&func->dev, "SDIO HW reset asynchronous\n"); + complete_all(adapter->fw_done); + break; + case 0: + ret =3D nxpwifi_reinit_sw(adapter); + if (ret) + dev_err(&func->dev, "reinit failed: %d\n", ret); + break; + default: + dev_err(&func->dev, "SDIO HW reset failed: %d\n", ret); + break; + } +} + +/* This function read/write firmware */ +static enum +rdwr_status nxpwifi_sdio_rdwr_firmware(struct nxpwifi_adapter *adapter, + u8 doneflag) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret, tries; + u8 ctrl_data =3D 0; + + sdio_writeb(card->func, card->reg->fw_dump_host_ready, + card->reg->fw_dump_ctrl, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "SDIO Write ERR\n"); + return RDWR_STATUS_FAILURE; + } + for (tries =3D 0; tries < MAX_POLL_TRIES; tries++) { + ctrl_data =3D sdio_readb(card->func, card->reg->fw_dump_ctrl, + &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "SDIO read err\n"); + return RDWR_STATUS_FAILURE; + } + if (ctrl_data =3D=3D FW_DUMP_DONE) + break; + if (doneflag && ctrl_data =3D=3D doneflag) + return RDWR_STATUS_DONE; + if (ctrl_data !=3D card->reg->fw_dump_host_ready) { + nxpwifi_dbg(adapter, WARN, + "The ctrl reg was changed, re-try again\n"); + sdio_writeb(card->func, card->reg->fw_dump_host_ready, + card->reg->fw_dump_ctrl, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "SDIO write err\n"); + return RDWR_STATUS_FAILURE; + } + } + usleep_range(100, 200); + } + if (ctrl_data =3D=3D card->reg->fw_dump_host_ready) { + nxpwifi_dbg(adapter, ERROR, + "Fail to pull ctrl_data\n"); + return RDWR_STATUS_FAILURE; + } + + return RDWR_STATUS_SUCCESS; +} + +/* This function dump firmware memory to file */ +static void nxpwifi_sdio_fw_dump(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + int ret =3D 0; + unsigned int reg, reg_start, reg_end; + u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag =3D 0; + enum rdwr_status stat; + u32 memory_size; + + if (!card->can_dump_fw) + return; + + for (idx =3D 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) { + struct memory_type_mapping *entry =3D &mem_type_mapping_tbl[idx]; + + if (entry->mem_ptr) { + vfree(entry->mem_ptr); + entry->mem_ptr =3D NULL; + } + entry->mem_size =3D 0; + } + + nxpwifi_pm_wakeup_card(adapter); + sdio_claim_host(card->func); + + nxpwifi_dbg(adapter, MSG, "=3D=3D nxpwifi firmware dump start =3D=3D\n"); + + stat =3D nxpwifi_sdio_rdwr_firmware(adapter, doneflag); + if (stat =3D=3D RDWR_STATUS_FAILURE) + goto done; + + reg =3D card->reg->fw_dump_start; + /* Read the number of the memories which will dump */ + dump_num =3D sdio_readb(card->func, reg, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "SDIO read memory length err\n"); + goto done; + } + + /* Read the length of every memory which will dump */ + for (idx =3D 0; idx < dump_num; idx++) { + struct memory_type_mapping *entry =3D &mem_type_mapping_tbl[idx]; + + stat =3D nxpwifi_sdio_rdwr_firmware(adapter, doneflag); + if (stat =3D=3D RDWR_STATUS_FAILURE) + goto done; + + memory_size =3D 0; + reg =3D card->reg->fw_dump_start; + for (i =3D 0; i < 4; i++) { + read_reg =3D sdio_readb(card->func, reg, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "SDIO read err\n"); + goto done; + } + memory_size |=3D (read_reg << i * 8); + reg++; + } + + if (memory_size =3D=3D 0) { + nxpwifi_dbg(adapter, DUMP, "Firmware dump Finished!\n"); + ret =3D nxpwifi_write_reg(adapter, + card->reg->fw_dump_ctrl, + FW_DUMP_READ_DONE); + if (ret) { + nxpwifi_dbg(adapter, ERROR, "SDIO write err\n"); + return; + } + break; + } + + nxpwifi_dbg(adapter, DUMP, + "%s_SIZE=3D0x%x\n", entry->mem_name, memory_size); + entry->mem_ptr =3D vmalloc(memory_size + 1); + entry->mem_size =3D memory_size; + if (!entry->mem_ptr) + goto done; + dbg_ptr =3D entry->mem_ptr; + end_ptr =3D dbg_ptr + memory_size; + + doneflag =3D entry->done_flag; + nxpwifi_dbg(adapter, DUMP, + "Start %s output, please wait...\n", + entry->mem_name); + + do { + stat =3D nxpwifi_sdio_rdwr_firmware(adapter, doneflag); + if (stat =3D=3D RDWR_STATUS_FAILURE) + goto done; + + reg_start =3D card->reg->fw_dump_start; + reg_end =3D card->reg->fw_dump_end; + for (reg =3D reg_start; reg <=3D reg_end; reg++) { + *dbg_ptr =3D sdio_readb(card->func, reg, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "SDIO read err\n"); + goto done; + } + if (dbg_ptr < end_ptr) + dbg_ptr++; + else + nxpwifi_dbg(adapter, ERROR, + "Allocated buf not enough\n"); + } + + if (stat !=3D RDWR_STATUS_DONE) + continue; + + nxpwifi_dbg(adapter, DUMP, "%s done: size=3D0x%tx\n", + entry->mem_name, dbg_ptr - entry->mem_ptr); + break; + } while (1); + } + nxpwifi_dbg(adapter, MSG, "=3D=3D nxpwifi firmware dump end =3D=3D\n"); + +done: + sdio_release_host(card->func); +} + +static void nxpwifi_sdio_generic_fw_dump(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + struct memory_type_mapping *entry =3D &generic_mem_type_map[0]; + unsigned int reg, reg_start, reg_end; + u8 start_flag =3D 0, done_flag =3D 0; + u8 *dbg_ptr, *end_ptr; + enum rdwr_status stat; + int ret =3D -1, tries; + + if (!card->fw_dump_enh) + return; + + if (entry->mem_ptr) { + vfree(entry->mem_ptr); + entry->mem_ptr =3D NULL; + } + entry->mem_size =3D 0; + + nxpwifi_pm_wakeup_card(adapter); + sdio_claim_host(card->func); + + nxpwifi_dbg(adapter, MSG, "=3D=3D nxpwifi firmware dump start =3D=3D\n"); + + stat =3D nxpwifi_sdio_rdwr_firmware(adapter, done_flag); + if (stat =3D=3D RDWR_STATUS_FAILURE) + goto done; + + reg_start =3D card->reg->fw_dump_start; + reg_end =3D card->reg->fw_dump_end; + for (reg =3D reg_start; reg <=3D reg_end; reg++) { + for (tries =3D 0; tries < MAX_POLL_TRIES; tries++) { + start_flag =3D sdio_readb(card->func, reg, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "SDIO read err\n"); + goto done; + } + if (start_flag =3D=3D 0) + break; + if (tries =3D=3D MAX_POLL_TRIES) { + nxpwifi_dbg(adapter, ERROR, + "FW not ready to dump\n"); + ret =3D -1; + goto done; + } + } + usleep_range(100, 200); + } + + entry->mem_ptr =3D vmalloc(0xf0000 + 1); + if (!entry->mem_ptr) { + ret =3D -1; + goto done; + } + dbg_ptr =3D entry->mem_ptr; + entry->mem_size =3D 0xf0000; + end_ptr =3D dbg_ptr + entry->mem_size; + + done_flag =3D entry->done_flag; + nxpwifi_dbg(adapter, DUMP, + "Start %s output, please wait...\n", entry->mem_name); + + while (true) { + stat =3D nxpwifi_sdio_rdwr_firmware(adapter, done_flag); + if (stat =3D=3D RDWR_STATUS_FAILURE) + goto done; + for (reg =3D reg_start; reg <=3D reg_end; reg++) { + *dbg_ptr =3D sdio_readb(card->func, reg, &ret); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "SDIO read err\n"); + goto done; + } + dbg_ptr++; + if (dbg_ptr >=3D end_ptr) { + u8 *tmp_ptr; + + tmp_ptr =3D vmalloc(entry->mem_size + 0x4000 + 1); + if (!tmp_ptr) + goto done; + + memcpy(tmp_ptr, entry->mem_ptr, + entry->mem_size); + vfree(entry->mem_ptr); + entry->mem_ptr =3D tmp_ptr; + tmp_ptr =3D NULL; + dbg_ptr =3D entry->mem_ptr + entry->mem_size; + entry->mem_size +=3D 0x4000; + end_ptr =3D entry->mem_ptr + entry->mem_size; + } + } + if (stat =3D=3D RDWR_STATUS_DONE) { + entry->mem_size =3D dbg_ptr - entry->mem_ptr; + nxpwifi_dbg(adapter, DUMP, "dump %s done size=3D0x%x\n", + entry->mem_name, entry->mem_size); + ret =3D 0; + break; + } + } + nxpwifi_dbg(adapter, MSG, "=3D=3D nxpwifi firmware dump end =3D=3D\n"); + +done: + if (ret) { + nxpwifi_dbg(adapter, ERROR, "firmware dump failed\n"); + if (entry->mem_ptr) { + vfree(entry->mem_ptr); + entry->mem_ptr =3D NULL; + } + entry->mem_size =3D 0; + } + sdio_release_host(card->func); +} + +static void nxpwifi_sdio_device_dump_work(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + + adapter->devdump_data =3D vzalloc(NXPWIFI_FW_DUMP_SIZE); + if (!adapter->devdump_data) + return; + + nxpwifi_drv_info_dump(adapter); + if (card->fw_dump_enh) + nxpwifi_sdio_generic_fw_dump(adapter); + else + nxpwifi_sdio_fw_dump(adapter); + nxpwifi_prepare_fw_dump_info(adapter); + nxpwifi_upload_device_dump(adapter); +} + +static void nxpwifi_sdio_work(struct work_struct *work) +{ + struct sdio_mmc_card *card =3D + container_of(work, struct sdio_mmc_card, work); + + if (test_and_clear_bit(NXPWIFI_IFACE_WORK_DEVICE_DUMP, + &card->work_flags)) + nxpwifi_sdio_device_dump_work(card->adapter); + if (test_and_clear_bit(NXPWIFI_IFACE_WORK_CARD_RESET, + &card->work_flags)) + nxpwifi_sdio_card_reset_work(card->adapter); +} + +/* This function resets the card */ +static void nxpwifi_sdio_card_reset(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + + if (!test_and_set_bit(NXPWIFI_IFACE_WORK_CARD_RESET, &card->work_flags)) + schedule_work(&card->work); +} + +/* This function dumps FW information */ +static void nxpwifi_sdio_device_dump(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + + if (!test_and_set_bit(NXPWIFI_IFACE_WORK_DEVICE_DUMP, + &card->work_flags)) + schedule_work(&card->work); +} + +/* Function to dump SDIO function registers and SDIO scratch registers in = case + * of FW crash + */ +static int +nxpwifi_sdio_reg_dump(struct nxpwifi_adapter *adapter, char *drv_buf) +{ + char *p =3D drv_buf; + struct sdio_mmc_card *cardp =3D adapter->card; + int ret =3D 0; + u8 count, func, data, index =3D 0, size =3D 0; + u8 reg, reg_start, reg_end; + char buf[256], *ptr; + + if (!p) + return 0; + + nxpwifi_dbg(adapter, MSG, "SDIO register dump start\n"); + + nxpwifi_pm_wakeup_card(adapter); + + sdio_claim_host(cardp->func); + + for (count =3D 0; count < 5; count++) { + memset(buf, 0, sizeof(buf)); + ptr =3D buf; + + switch (count) { + case 0: + /* Read the registers of SDIO function0 */ + func =3D count; + reg_start =3D 0; + reg_end =3D 9; + break; + case 1: + /* Read the registers of SDIO function1 */ + func =3D count; + reg_start =3D cardp->reg->func1_dump_reg_start; + reg_end =3D cardp->reg->func1_dump_reg_end; + break; + case 2: + index =3D 0; + func =3D 1; + reg_start =3D cardp->reg->func1_spec_reg_table[index++]; + size =3D cardp->reg->func1_spec_reg_num; + reg_end =3D cardp->reg->func1_spec_reg_table[size - 1]; + break; + default: + /* Read the scratch registers of SDIO function1 */ + if (count =3D=3D 4) + mdelay(100); + func =3D 1; + reg_start =3D cardp->reg->func1_scratch_reg; + reg_end =3D reg_start + NXPWIFI_SDIO_SCRATCH_SIZE; + } + + if (count !=3D 2) + ptr +=3D sprintf(ptr, "SDIO Func%d (%#x-%#x): ", + func, reg_start, reg_end); + else + ptr +=3D sprintf(ptr, "SDIO Func%d: ", func); + + for (reg =3D reg_start; reg <=3D reg_end;) { + if (func =3D=3D 0) + data =3D sdio_f0_readb(cardp->func, reg, &ret); + else + data =3D sdio_readb(cardp->func, reg, &ret); + + if (count =3D=3D 2) + ptr +=3D sprintf(ptr, "(%#x) ", reg); + if (!ret) { + ptr +=3D sprintf(ptr, "%02x ", data); + } else { + ptr +=3D sprintf(ptr, "ERR"); + break; + } + + if (count =3D=3D 2 && reg < reg_end) + reg =3D cardp->reg->func1_spec_reg_table[index++]; + else + reg++; + } + + nxpwifi_dbg(adapter, MSG, "%s\n", buf); + p +=3D sprintf(p, "%s\n", buf); + } + + sdio_release_host(cardp->func); + + nxpwifi_dbg(adapter, MSG, "SDIO register dump end\n"); + + return p - drv_buf; +} + +/* sdio device/function initialization, code is extracted + * from init_if handler and register_dev handler. + */ +static void nxpwifi_sdio_up_dev(struct nxpwifi_adapter *adapter) +{ + struct sdio_mmc_card *card =3D adapter->card; + u8 sdio_ireg; + + sdio_claim_host(card->func); + sdio_enable_func(card->func); + sdio_set_block_size(card->func, NXPWIFI_SDIO_BLOCK_SIZE); + sdio_release_host(card->func); + + /* tx_buf_size might be changed to 3584 by firmware during + * data transfer, we will reset to default size. + */ + adapter->tx_buf_size =3D card->tx_buf_size; + + /* Read the host_int_status_reg for ACK the first interrupt got + * from the bootloader. If we don't do this we get a interrupt + * as soon as we register the irq. + */ + nxpwifi_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg); + + if (nxpwifi_init_sdio_ioport(adapter)) + dev_err(&card->func->dev, "error enabling SDIO port\n"); +} + +static struct nxpwifi_if_ops sdio_ops =3D { + .init_if =3D nxpwifi_init_sdio, + .cleanup_if =3D nxpwifi_cleanup_sdio, + .check_fw_status =3D nxpwifi_check_fw_status, + .check_winner_status =3D nxpwifi_check_winner_status, + .prog_fw =3D nxpwifi_prog_fw_w_helper, + .register_dev =3D nxpwifi_register_dev, + .unregister_dev =3D nxpwifi_unregister_dev, + .enable_int =3D nxpwifi_sdio_enable_host_int, + .disable_int =3D nxpwifi_sdio_disable_host_int, + .process_int_status =3D nxpwifi_process_int_status, + .host_to_card =3D nxpwifi_sdio_host_to_card, + .wakeup =3D nxpwifi_pm_wakeup_card, + .wakeup_complete =3D nxpwifi_pm_wakeup_card_complete, + + /* SDIO specific */ + .update_mp_end_port =3D nxpwifi_update_mp_end_port, + .cleanup_mpa_buf =3D nxpwifi_cleanup_mpa_buf, + .cmdrsp_complete =3D nxpwifi_sdio_cmdrsp_complete, + .event_complete =3D nxpwifi_sdio_event_complete, + .dnld_fw =3D nxpwifi_sdio_dnld_fw, + .card_reset =3D nxpwifi_sdio_card_reset, + .reg_dump =3D nxpwifi_sdio_reg_dump, + .device_dump =3D nxpwifi_sdio_device_dump, + .deaggr_pkt =3D nxpwifi_deaggr_sdio_pkt, + .up_dev =3D nxpwifi_sdio_up_dev, +}; + +module_driver(nxpwifi_sdio, sdio_register_driver, sdio_unregister_driver); + +MODULE_AUTHOR("NXP International Ltd."); +MODULE_DESCRIPTION("NXP WiFi SDIO Driver version " SDIO_VERSION); +MODULE_VERSION(SDIO_VERSION); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(IW61X_SDIO_FW_NAME); --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1EB87174EE4; Fri, 21 Jun 2024 07:54:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956456; cv=fail; b=IHaZbm7oa+oEI1PrJEvKzVGTyNaH39X6TIW/2kaElZLChF2RX6C9FAxL+ZpXQoQO5eAK1wczvb01q/M0epNbJWRcLWpTWanuNs75U+SYuV2Tt3xJym9d3ninaj3Otpmtj1c2Z6nIHeLLd0+KJls16pRpk3fROeiu/b4N4dGQ4aY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956456; c=relaxed/simple; bh=yCMM0VSY+qxTwI8nHoyn33atrcSTD4iIeI15LJsQUOc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=uQE3ZpLh4dl3lk+uWjUa9vDMC9NMsfUVZ/uL7ZhcISOhVS8ocb25VVzGZ2glBHQ2MpHWGREYLMcPMvlf8xXaYKZxV0sqmJIqf7FjPeHnDmEMmjfZ8OJ0bp5KaVdjDidqn4+iJM05aURmfTVC2l2JSHiXUnm+7F0867WeazvLIA0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=ow6G/UHe; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="ow6G/UHe" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FQhasRKcTpT1h2VKFMLMuvaI7ozkbExflCvV9BqmdGYmLJWSj9POLWP/0Ygno8JVWoIhqwJ9Ebv59ZWwgIbAIBAVX07mU9zor1l5BNc+OjC6ErM8sacT2xGKTt4SzmB2hPGr4oPqnQH0c0Ay/D/Oyof7hUxXBT0agn9xbp5njY2EbHbaBH6YI8NR3AWCh2YKPjQoov42BR2ZLZdjXEfq/MV7SDCtk+lQmlOU1DrzC/sE57RjVEki7tf24MUryoysT+U0zgiTKOsp2Cc49wsDHBCQczg2gJECl0k5jgAoJ12I6cnUEVidwT1A3WQ/70mh0/50cUvs4xFWNcUXFnfUxQ== 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=Kwy7f9r3/pe4RXzAg9uU+I6huax8c3zE+iIqAvtFt7M=; b=Y7lLAb9PWpBX+7ZFacpaAw5I2YZ0gAgqHAUokUmaQLW3/vcUBvMf2eOedxZp0U2mQoZMDhl1c3B8XwlwwGekYnQRealIwSWylgtBRU36HRvYys6O+al6w6fN+n7cNjND2uhkmLNSdGpxFm2snnazHIXzAfWhtd5hTUCyrasmvUYMYB3iYQI50wTqUSz8YGgP+UXwB6R2cdOiTdiwgrlowqrLzNrLJIIS6UTYNL7DFFDFHsfOK1FMz543YXcxjQ26b/nYKwDRhcWABb0QJOjXOuER66QPylHoAd2fnYz2Wy5Ka5VlQXE2kg+3P921q/W/Dm9W//TTnvOq41Ux73q54g== 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=Kwy7f9r3/pe4RXzAg9uU+I6huax8c3zE+iIqAvtFt7M=; b=ow6G/UHesKOMoLq3ZrQRlTZlN4ZM4xDbOx2H4sEBv0cLthBAyz5whVQ3XugD5rnzUsCRq4RCfJxe2CIbcthoZXwWjvOyCJrc3zX1fjvwYna31Dr+vD7xftivD2r5aV9C0l+9PF6kyzmEhRmHGiWKU3IETN4txyjr9rrkpgfx+4I= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:54:05 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:05 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 27/43] wifi: nxpwifi: add sdio.h Date: Fri, 21 Jun 2024 15:51:52 +0800 Message-Id: <20240621075208.513497-28-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: abeac904-8c57-46e4-ad31-08dc91c75246 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?lsHAW+OIZuKLDkByXdzFM9YB2fR29dF6/hQ5fK3aZQ86AozwN+CFc8wKfeOp?= =?us-ascii?Q?+OlpG8sLvBtICcwV6DyDSqTJxka7wiPyxz6Dxv3j2iYUfCpuVAlFMiU+2/6f?= =?us-ascii?Q?BucwRGqz2+iJkufKQG/3LOWg+7aaxh/jxyuenYPeXiy/zVhiFVCQitqyQKsO?= =?us-ascii?Q?XrSbqJHPbpvO19fXZ+oj67khEn7Wqho4PgHmyhGKd+XioaLoZXjQCJm7fUSj?= =?us-ascii?Q?VlKaIWm2xhy91nKOW3GacM9Rwldg6Z+xn11zFsBXOPomeTDJ9CkC6/IXIAVy?= =?us-ascii?Q?wFbhB3/j/PRLWwQuFKWc1jasmeWgeR7EPBBLoyN8kkmgXmhYRDNJ4ENycLOP?= =?us-ascii?Q?G6zrBn3NA3hycIOOm8YTe/gdrz9rUnZzHi5Zj2aqTuvv1Oesy5prkbe0yEIf?= =?us-ascii?Q?tSuDK6+v2jw2V8nhp7TsqEscGnFeys1WsTR+fIE1BIta9zRJ3rA8LMQawHOq?= =?us-ascii?Q?edffhM58/Tgm8yLuYrdlaIhHdfcM9jQ0MovBLYR4gYxWD59z2NnMukmpgoGq?= =?us-ascii?Q?FEf0xQDG/x5emQ6F8u/0Pi6y5st1vjHI8mmb23HK2Z2VEPiV4wV3wnXwRmUf?= =?us-ascii?Q?iEfVnJXAaGZYhuq02JNcB0Ww1VAFwnseTeE85HCzOOk9z7TlrnyuJwMc3OJl?= =?us-ascii?Q?nMJwjRFUNvKVFgD4R79NFFQd36UN+4tSWXGaK1BqZ8uSLT1aAyTs3d5QNOMk?= =?us-ascii?Q?/vQXoX4pyK+N+c/pnaT4UEN1ssL158HBzMfHngopLLxMCVku3rmOw636Szyd?= =?us-ascii?Q?S4NBcy4ygleX/VUKS/A8tKqQ5mkm6EYQCggnxkd92Y0S3Pn7IESoSXzTukME?= =?us-ascii?Q?GE91HWZGR3CfhZmOUU1+m9k6CUhcBSFK+d6UVrnuEbGzykw8Kd24DOrthFsC?= =?us-ascii?Q?rlG11nnknhWmrWDbeVVx4H25/xzFqSCjB/V+2Hf0Xp1t/zzb9TPAg4KLe1HV?= =?us-ascii?Q?yte9Gq3D1kNPqaIobcfGsV/mkd81gItIo7Z+z78tqBZb7OabVxqojKp2+2BB?= =?us-ascii?Q?S1ayHROv7+/zn5mtqPfA3yWAto5EUnJrWSh+jHWfVILLLEnaC1JVeHPbDPte?= =?us-ascii?Q?8ctDICDyzgXQm1T6y8DfRCV/HVC0NOFw6cNQePpTjxsHiDAMVBLVJvX9JbvJ?= =?us-ascii?Q?meh3w0lXF9zWoseQGmdLt7iIOQjyH75Yl7aySvVSlL3hwEZxyVbd60ZbJyDV?= =?us-ascii?Q?3H5AsArLj3ofZDKiLHQEbxDj60QYOT50RN689NrC0Z5kD8LViMVxmIIFB6Ox?= =?us-ascii?Q?iYcP9HhNBAArgbH02pQHZGKTScAlz86FJqAcorB4TW0AavcgAQIRSU64gb49?= =?us-ascii?Q?du5iIenGZLrzNPUgOBvESqKsXnYzylaz7AB8aJPd5ItAPND31U2hAb1+7tD7?= =?us-ascii?Q?uQ1cqv4=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?7r/gNiFKlHSXSTICN5o/N2GyjQNWlSjrcF77lE3vDEcKODEW9NKmWLdt5jQe?= =?us-ascii?Q?6rAQFDFn114Ki4bgrY+VLVfrhzCZTd53HRg+9CuGnaVhB7Z9MKXax7UvsCe7?= =?us-ascii?Q?4X3mqkkaYRc7Wm3jGMdpoa278wibiCp0ox4ClL2brwP7Ej0FiBCRGWNXULlS?= =?us-ascii?Q?JcQXcuPb7ZY8ZM88vs5Ls4ZNwZ/lyXylmzMBJ2W5OfMN24mlC6rqkA7TvU/0?= =?us-ascii?Q?ICs4qcEnSALCu0Zq+3lXIT0kwth9x2kGA5MaUPQeLsaSgiuWVLKMsWDSwW4Y?= =?us-ascii?Q?YvQBQcN2R+ShvXXlhem/+D9/nIAm9jzzoApoyLL2gxEvqOTLxHw5/8hs3Z1g?= =?us-ascii?Q?31KZITM3HQTfTgSbTk18HtN3HJ3RY4oQrGlS+2iiQvfEsOgzkKn8bf+uOE3V?= =?us-ascii?Q?2XYP04etBMfAP26ThJlBLeTTSW7tAKhGMeuga/ZPwtUfOg1q4G90DqLtENbD?= =?us-ascii?Q?EjtdOirMeCtybwFpBXwtFlQZh76JDZo6c3oPMwdbsnphKj4tTdGThG+nGL4Z?= =?us-ascii?Q?syKbp+IHySZrLEzpLmUvGU2j1SZWa3aoclBSzJP0jFP4Xay7lOlKUuc4Q7JQ?= =?us-ascii?Q?3WLtzpj0ZyM2S0y4fwzH+VKxBvik2QaWiciKxt0qJBMpoKijlrReVkQHIwW1?= =?us-ascii?Q?N9H29UgyIVxBCXlhMTRTSTjiPap8HsT3XZYqoWtxJuDvGFFUnJO60Yv+0Y9P?= =?us-ascii?Q?2HZu8/CPUwa3PlEFwKjiBLIbmxsASoQvmtMCxune7rWdKaT4YIaDAWpIog1u?= =?us-ascii?Q?gGO+b6jPeTQV5bMa0GWbhNv2FrHjQgvC2CJcWiE3esbt4f+WZTVHx5CcmuNR?= =?us-ascii?Q?/0DML0/kghbrtNUdKLjtJuzlRgRpO79m3ApLPvizi+o3gOVUuRZnocnj7XXo?= =?us-ascii?Q?JTcoQleTvKln0248LysYxkxg4rarJiux0Ha9adAQDmAi2NNxR/A5I1x/kO9C?= =?us-ascii?Q?2FqZsdxbMHeC3eRTdf7THWEgB+rgt17fFGq2c8TEWXETFQyh20Cu6wloDX8f?= =?us-ascii?Q?yWsD+G17/WEp9WEHtUY6s4W1/vdbmyVoZ5Tj0pEBikPgK5ovWbX+bhUqNY+u?= =?us-ascii?Q?3nnb/PN6XSftZUwur/Vppk6kESoSnAiLSZ+b6OgDVTjrEky4QCr98lGMkZ2l?= =?us-ascii?Q?qFvX+zPyAz8NisTph+Xl1Ajtk3HpeHYAu6ByIP94/h7evp89MUUcPjFM5x0S?= =?us-ascii?Q?kaEn4pjCeOf7ufbZ6b2p0f88EqYLfpzisz+JnNQ0Ki7Nins8S+km8SpmgJTN?= =?us-ascii?Q?g+R2Pn5xs9OeGLayjd5eXJvaLcqqK5qVnLvfG6lA71qZQ4eEnERQZfhF0Ff+?= =?us-ascii?Q?LqIGL6dGanuvQVTkiV0lj1ann3CCyjUxciveNE+rG4icMoOExybRsvTrBa6v?= =?us-ascii?Q?RUI/zL9CqAzP//lidk1pID5wY2MzrK7jlkaKiSqUeLlIGDxK5LbMwBC1PvtI?= =?us-ascii?Q?Mxk+PQs31DEP1vpFadNDUvN9MIPMD0zK0psvncx+yi57CsvZU8/E8IWVdwvH?= =?us-ascii?Q?oyFdqmuRnAyjqSSfBBPGrGHfKHyVmBJlWqcoSOVmtoEKVzny/xS9Yxpiq0E2?= =?us-ascii?Q?gEhYDFKQ1814uc5XKcKpJC7LOXLMfLRFSUsUr62B?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: abeac904-8c57-46e4-ad31-08dc91c75246 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:05.0056 (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: tL6vi5msSN7OcgtPn4U10OEgiOpdTGF0mz9REYPnLEMgEmUZjwtrzG3I1xTjN3TvY4VoH+/xaIGSTd+XZf1lKQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sdio.h | 340 ++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sdio.h diff --git a/drivers/net/wireless/nxp/nxpwifi/sdio.h b/drivers/net/wireless= /nxp/nxpwifi/sdio.h new file mode 100644 index 000000000000..de5c884a5b14 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sdio.h @@ -0,0 +1,340 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: SDIO specific definitions + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_SDIO_H +#define _NXPWIFI_SDIO_H + +#include "main.h" + +#define IW61X_SDIO_FW_NAME "nxp/sd_w61x_v1.bin.se" + +#define BLOCK_MODE 1 +#define BYTE_MODE 0 + +#define NXPWIFI_SDIO_IO_PORT_MASK 0xfffff + +#define NXPWIFI_SDIO_BYTE_MODE_MASK 0x80000000 + +#define NXPWIFI_MAX_FUNC2_REG_NUM 13 +#define NXPWIFI_SDIO_SCRATCH_SIZE 10 + +#define SDIO_MPA_ADDR_BASE 0x1000 + +#define CMD_PORT_UPLD_INT_MASK (0x1U << 6) +#define CMD_PORT_DNLD_INT_MASK (0x1U << 7) +#define HOST_TERM_CMD53 (0x1U << 2) +#define REG_PORT 0 +#define MEM_PORT 0x10000 + +#define CMD53_NEW_MODE (0x1U << 0) +#define CMD_PORT_RD_LEN_EN (0x1U << 2) +#define CMD_PORT_AUTO_EN (0x1U << 0) +#define CMD_PORT_SLCT 0x8000 +#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U) +#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U) + +#define NXPWIFI_MP_AGGR_BSIZE_32K (32768) +/* we leave one block of 256 bytes for DMA alignment*/ +#define NXPWIFI_MP_AGGR_BSIZE_MAX (65280) + +/* Misc. Config Register : Auto Re-enable interrupts */ +#define AUTO_RE_ENABLE_INT BIT(4) + +/* Host Control Registers : Configuration */ +#define CONFIGURATION_REG 0x00 +/* Host Control Registers : Host power up */ +#define HOST_POWER_UP (0x1U << 1) + +/* Host Control Registers : Upload host interrupt mask */ +#define UP_LD_HOST_INT_MASK (0x1U) +/* Host Control Registers : Download host interrupt mask */ +#define DN_LD_HOST_INT_MASK (0x2U) + +/* Host Control Registers : Upload host interrupt status */ +#define UP_LD_HOST_INT_STATUS (0x1U) +/* Host Control Registers : Download host interrupt status */ +#define DN_LD_HOST_INT_STATUS (0x2U) + +/* Host Control Registers : Host interrupt status */ +#define CARD_INT_STATUS_REG 0x28 + +/* Card Control Registers : Card I/O ready */ +#define CARD_IO_READY (0x1U << 3) +/* Card Control Registers : Download card ready */ +#define DN_LD_CARD_RDY (0x1U << 0) + +/* Max retry number of CMD53 write */ +#define MAX_WRITE_IOMEM_RETRY 2 + +/* SDIO Tx aggregation in progress ? */ +#define MP_TX_AGGR_IN_PROGRESS(a) ((a)->mpa_tx.pkt_cnt > 0) + +/* SDIO Tx aggregation buffer room for next packet ? */ +#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ({ \ + typeof(a) (_a) =3D a; \ + (((_a)->mpa_tx.buf_len + (len)) <=3D (_a)->mpa_tx.buf_size); \ + }) + +/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */ +#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do { \ + typeof(a) (_a) =3D (a); \ + typeof(pkt_len) (_pkt_len) =3D pkt_len; \ + typeof(port) (_port) =3D port; \ + memmove(&(_a)->mpa_tx.buf[(_a)->mpa_tx.buf_len], \ + payload, (_pkt_len)); \ + (_a)->mpa_tx.buf_len +=3D (_pkt_len); \ + if (!(_a)->mpa_tx.pkt_cnt) \ + (_a)->mpa_tx.start_port =3D (_port); \ + if ((_a)->mpa_tx.start_port <=3D (_port)) \ + (_a)->mpa_tx.ports |=3D (1 << ((_a)->mpa_tx.pkt_cnt)); \ + else \ + (_a)->mpa_tx.ports |=3D (1 << ((_a)->mpa_tx.pkt_cnt + 1 + \ + ((_a)->max_ports - \ + (_a)->mp_end_port))); \ + (_a)->mpa_tx.pkt_cnt++; \ +} while (0) + +/* SDIO Tx aggregation limit ? */ +#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) ({ \ + typeof(a) (_a) =3D a; \ + ((_a)->mpa_tx.pkt_cnt =3D=3D (_a)->mpa_tx.pkt_aggr_limit); \ + }) + +/* Reset SDIO Tx aggregation buffer parameters */ +#define MP_TX_AGGR_BUF_RESET(a) do { \ + typeof(a) (_a) =3D (a); \ + (_a)->mpa_tx.pkt_cnt =3D 0; \ + (_a)->mpa_tx.buf_len =3D 0; \ + (_a)->mpa_tx.ports =3D 0; \ + (_a)->mpa_tx.start_port =3D 0; \ +} while (0) + +/* SDIO Rx aggregation limit ? */ +#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) ({ \ + typeof(a) (_a) =3D a; \ + ((_a)->mpa_rx.pkt_cnt =3D=3D (_a)->mpa_rx.pkt_aggr_limit); \ + }) + +/* SDIO Rx aggregation in progress ? */ +#define MP_RX_AGGR_IN_PROGRESS(a) ((a)->mpa_rx.pkt_cnt > 0) + +/* SDIO Rx aggregation buffer room for next packet ? */ +#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) ({ \ + typeof(a) (_a) =3D a; \ + ((((_a)->mpa_rx.buf_len + (rx_len))) <=3D (_a)->mpa_rx.buf_size); \ + }) + +/* Reset SDIO Rx aggregation buffer parameters */ +#define MP_RX_AGGR_BUF_RESET(a) do { \ + typeof(a) (_a) =3D (a); \ + (_a)->mpa_rx.pkt_cnt =3D 0; \ + (_a)->mpa_rx.buf_len =3D 0; \ + (_a)->mpa_rx.ports =3D 0; \ + (_a)->mpa_rx.start_port =3D 0; \ +} while (0) + +/* data structure for SDIO MPA TX */ +struct nxpwifi_sdio_mpa_tx { + /* multiport tx aggregation buffer pointer */ + u8 *buf; + u32 buf_len; + u32 pkt_cnt; + u32 ports; + u16 start_port; + u8 enabled; + u32 buf_size; + u32 pkt_aggr_limit; +}; + +struct nxpwifi_sdio_mpa_rx { + u8 *buf; + u32 buf_len; + u32 pkt_cnt; + u32 ports; + u16 start_port; + u32 *len_arr; + u8 enabled; + u32 buf_size; + u32 pkt_aggr_limit; +}; + +int nxpwifi_bus_register(void); +void nxpwifi_bus_unregister(void); + +struct nxpwifi_sdio_card_reg { + u8 start_rd_port; + u8 start_wr_port; + u8 base_0_reg; + u8 base_1_reg; + u8 poll_reg; + u8 host_int_enable; + u8 host_int_rsr_reg; + u8 host_int_status_reg; + u8 host_int_mask_reg; + u8 host_strap_reg; + u8 host_strap_mask; + u8 host_strap_value; + u8 status_reg_0; + u8 status_reg_1; + u8 sdio_int_mask; + u32 data_port_mask; + u8 io_port_0_reg; + u8 io_port_1_reg; + u8 io_port_2_reg; + u8 max_mp_regs; + u8 rd_bitmap_l; + u8 rd_bitmap_u; + u8 rd_bitmap_1l; + u8 rd_bitmap_1u; + u8 wr_bitmap_l; + u8 wr_bitmap_u; + u8 wr_bitmap_1l; + u8 wr_bitmap_1u; + u8 rd_len_p0_l; + u8 rd_len_p0_u; + u8 card_misc_cfg_reg; + u8 card_cfg_2_1_reg; + u8 cmd_rd_len_0; + u8 cmd_rd_len_1; + u8 cmd_rd_len_2; + u8 cmd_rd_len_3; + u8 cmd_cfg_0; + u8 cmd_cfg_1; + u8 cmd_cfg_2; + u8 cmd_cfg_3; + u8 fw_dump_host_ready; + u8 fw_dump_ctrl; + u8 fw_dump_start; + u8 fw_dump_end; + u8 func1_dump_reg_start; + u8 func1_dump_reg_end; + u8 func1_scratch_reg; + u8 func1_spec_reg_num; + u8 func1_spec_reg_table[NXPWIFI_MAX_FUNC2_REG_NUM]; +}; + +struct sdio_mmc_card { + struct sdio_func *func; + struct nxpwifi_adapter *adapter; + + struct completion fw_done; + const char *firmware; + const char *firmware_sdiouart; + const struct nxpwifi_sdio_card_reg *reg; + u8 max_ports; + u8 mp_agg_pkt_limit; + u16 tx_buf_size; + u32 mp_tx_agg_buf_size; + u32 mp_rx_agg_buf_size; + + u32 mp_rd_bitmap; + u32 mp_wr_bitmap; + + u16 mp_end_port; + u32 mp_data_port_mask; + + u8 curr_rd_port; + u8 curr_wr_port; + + u8 *mp_regs; + bool can_dump_fw; + bool fw_dump_enh; + bool can_ext_scan; + + struct nxpwifi_sdio_mpa_tx mpa_tx; + struct nxpwifi_sdio_mpa_rx mpa_rx; + + struct work_struct work; + unsigned long work_flags; +}; + +struct nxpwifi_sdio_device { + const char *firmware; + const char *firmware_sdiouart; + const struct nxpwifi_sdio_card_reg *reg; + u8 max_ports; + u8 mp_agg_pkt_limit; + u16 tx_buf_size; + u32 mp_tx_agg_buf_size; + u32 mp_rx_agg_buf_size; + bool can_dump_fw; + bool fw_dump_enh; + bool can_ext_scan; +}; + +/* .cmdrsp_complete handler + */ +static inline int nxpwifi_sdio_cmdrsp_complete(struct nxpwifi_adapter *ada= pter, + struct sk_buff *skb) +{ + dev_kfree_skb_any(skb); + return 0; +} + +/* .event_complete handler + */ +static inline int nxpwifi_sdio_event_complete(struct nxpwifi_adapter *adap= ter, + struct sk_buff *skb) +{ + dev_kfree_skb_any(skb); + return 0; +} + +static inline bool +mp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card) +{ + u8 tmp; + + if (card->curr_rd_port < card->mpa_rx.start_port) { + tmp =3D card->mp_end_port >> 1; + + if (((card->max_ports - card->mpa_rx.start_port) + + card->curr_rd_port) >=3D tmp) + return true; + } + + if ((card->curr_rd_port - card->mpa_rx.start_port) >=3D + (card->mp_end_port >> 1)) + return true; + + return false; +} + +static inline bool +mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card) +{ + u16 tmp; + + if (card->curr_wr_port < card->mpa_tx.start_port) { + tmp =3D card->mp_end_port >> 1; + + if (((card->max_ports - card->mpa_tx.start_port) + + card->curr_wr_port) >=3D tmp) + return true; + } + + if ((card->curr_wr_port - card->mpa_tx.start_port) >=3D + (card->mp_end_port >> 1)) + return true; + + return false; +} + +/* Prepare to copy current packet from card to SDIO Rx aggregation buffer = */ +static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, + u16 rx_len, u8 port) +{ + card->mpa_rx.buf_len +=3D rx_len; + + if (!card->mpa_rx.pkt_cnt) + card->mpa_rx.start_port =3D port; + + card->mpa_rx.ports |=3D (1 << port); + card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] =3D rx_len; + card->mpa_rx.pkt_cnt++; +} +#endif /* _NXPWIFI_SDIO_H */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2046.outbound.protection.outlook.com [40.107.7.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AC44175544; Fri, 21 Jun 2024 07:54:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.7.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956462; cv=fail; b=D4jxp12MWfvo7VTd8gSugn7FqTIKr+M/Bpygumg9QqJcKJ8du+qWc1Jnc+CR/oITmBN164XiSj2Tc+VUhFNW/t1SQfa3Av93Z4ABI8rz2O/DYDqyJgRMoGjWAd5GUd8egC0QuzKUL3+UlgBtdpSA7Nuvy8XFVDC8zmyHO9eGvc0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956462; c=relaxed/simple; bh=w9Swskw55WRxphd35DDpFDzEHI3c3dLEkE69/oskWdg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=ADri6OvGzsOZ8jOP3FLKI/6xf3osSu/R3IUkuAWozrkuFeuVj3omFGMZ4/+f1qNUE85zRyZqTweDRluNqbWT8SVYgE890smScBbxn645u+zDXsdhr7dE/NI+R0K5udYOJVgiXUjLX/dFV2VcMAyH8J4aiMd59DgKDaF/GaVcdlk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=U4GE66YY; arc=fail smtp.client-ip=40.107.7.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="U4GE66YY" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Dm5aloEMi6ghLPTijTSbihZDf8N9W7JtXfdSy0aYUXONhJM+gi8IxCm0qOitox+cC0ObmJGwDIwtO4dtU3RJVPNHjy7+yG606e6UhstFq6ZUjCOeab9YNHoO8oFeAv6HXYdvbZsXus1OzNVAOnwUr75Qlveb8xzUf8J0NggZLx5RE2tSc+a6t5mV9ejXtydg/L9jaDiOf8rgDeeyP90nn/UYt4Ja35YlpihzZRFyVeHUj33gliGBfQUY0wWNAQEhZdcrHe+ZzIcdWjIyJ6BxzcrksidTpMuRo7pzH+ot/pW+aVF0g1n59ac/etSSy4IfMGJNlU4/oIQZ1kts46L0Cw== 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=IhQLQBzpGFgL9YDJdlqO0VaeQtvdZ7Rf66owXHkp9dA=; b=i7oH19qFix1X+3ogJ/TVVDw71WoQzoHnWl433YLkEU+yIWjeg++bc0KNAnSlcyQhUOHFCw57hkCqR4BGA8dBQQQ39tmuNcD4UomkB8LH1hW//BU7BALX1RDbZaRAgqRGAIA1elbmuOTgAZNobtZ1QwfFz9olA+0KdlEwkwuN0KgtDwXrOP4lWdDwy+3ePtaNFx6iQBScaCMVdthu24sI5XVBys2VnGnOX0R7Xm3h877RsJCQOe3prqex+xnHzUKyRf8A6wrX5E29E1kZTwyMNup9b2LHnXOWi5FLiM+Qb32IhVQZA5uMi6fnyApgTTwKckE/SpH9K3adMcHMzk8raw== 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=IhQLQBzpGFgL9YDJdlqO0VaeQtvdZ7Rf66owXHkp9dA=; b=U4GE66YYLslOR+YP3iCR/hV077HH/wegclmXUSkahgacMBLn/CrD75WvvH/ShWC7FnTfB55KzaYcYFFYkRuIdPefWP6aJ2FPVOFXa/pisv3kCkzqmH5L/LZ/KtgAO/okKnJUU7bChePBHYUzapNmL8vj3R9pgJKFDdVHQIn+Uno= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB9190.eurprd04.prod.outlook.com (2603:10a6:20b:44d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.22; Fri, 21 Jun 2024 07:54:09 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:08 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 28/43] wifi: nxpwifi: add sta_cmd.c Date: Fri, 21 Jun 2024 15:51:53 +0800 Message-Id: <20240621075208.513497-29-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB9190:EE_ X-MS-Office365-Filtering-Correlation-Id: 30986f49-3dd9-435f-c172-08dc91c75424 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|52116011|376011|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?97x45ac1TpWLnC5Lf0jlwvLSc1w9zYX45AgcQdhoW+1cPY0kF/Pq9bUQ08Cc?= =?us-ascii?Q?spxArHMWgMOOpDsaM2/EeKB3jHBVQjzX+p4lFRddCx5Gxn40oS8jiKEUSnTN?= =?us-ascii?Q?LA5Et5/kDE77U9haqGzSPrEjKQD6yPW5Zd8P0foVzMmFv6SDzYayOcjdzdB7?= =?us-ascii?Q?mibFEpe0veyfW+VXQ/EySvd3LoIHTqNDLelVdLOCxXieZRMT/Ca4oimFR/NC?= =?us-ascii?Q?J6FeB0wcnR8RD7RdReq8kA/UdJSyDeYLyB4Hbm5/JZHxmepB6LT0ImyE5zju?= =?us-ascii?Q?XVc12qA2cguhT2MXZlMzIpVLMKsohlr03PlPmrgdrWkdKb7PO/u2ALM3jOHY?= =?us-ascii?Q?virhXoYcmgLqMzcrXjvRfVlrp0L/0jI3wyDxWChodP4UK6yyv5e+SbEnnPrn?= =?us-ascii?Q?7IhhlXBaeA9H93hw4PvrXzl82a0KpckyV1y4PHGauCalmE0B2HMVERx8sOFH?= =?us-ascii?Q?cwb23XQ9sRe41TBrA76fDb804NflLuR/QGxHz1HsXp4133KBPiUwcE1LdH7v?= =?us-ascii?Q?n2FuYFWSKIdJCmN+oSeTDFXPv+JsKy8NHsTiqcyljWBTdoa1Gas+MroD4xkx?= =?us-ascii?Q?zHKOC0nDNBzJUnd/44OSSnNM/68wJf9BaOlsxcIFJK7bz5Cw2sQDjg6JGNZZ?= =?us-ascii?Q?hgyanGj1x16MRiimZRrzOrSjBYN2Ilvk/KHzCTfXVLpvlcRPG0R2yHVD/KBv?= =?us-ascii?Q?5zfi2UUkwDxsZ2s2e0ZgRRYDvg3PjmK4fpXL3g67VKOFTgZNYnYB74yg04hP?= =?us-ascii?Q?O+MzNZ2BTcdqLPd2HKCZmI7caek3BdJ/f+3H454D4Tmn9Uc1rwftJOVo1zfX?= =?us-ascii?Q?gXvZ0qbkKg5SHiBzlVE27Jy/Mw8XtlBhvfYoyvxSRIF3fAtTAbI/xcfE2/y3?= =?us-ascii?Q?nDfdhVGtfmPveBnXPbXwwPhiVDL9CyP2CDMZbhOapQ7YZavE3h17ukDT+OkS?= =?us-ascii?Q?HgnQmPocOdCNgvy5wvNivWTuOBp3mZAM7mZcHG6X/gq0RyB5V5B3T05sQRfp?= =?us-ascii?Q?vHpnUYlGS5Fx07L0ScdYqg9jiIlElBrdVX3mFbUabtP22yLNZcHUQcwmShc9?= =?us-ascii?Q?nbewS5ERXnbdvxpF/jXTUd9ecSuugR6jKWEoTPqxE6qMkfqkP6hRtT/63qWp?= =?us-ascii?Q?UxktGHNm9ydQPbg31Xl4oatycVVOBZla9Sij92i2Uf3FqUy/UJitXYsIijjO?= =?us-ascii?Q?9jJTeXoPtsjkQMHfUk/rtQL98azW40+7c5ipvMNzYBczBDfyWReoZpeaIi19?= =?us-ascii?Q?Pk85j6VRrmLj4aehECTNDklBsFpgSsFOG3vj1hfMQngLYyTxcWazy1aFj5hO?= =?us-ascii?Q?cUaezVBXjxkwZZ4CAY6DcJBN/lRnpUVmJWoUQRG+E+j4O1aQMZ2su+iA/AfY?= =?us-ascii?Q?N/CdcbU=3D?= 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:(13230037)(1800799021)(52116011)(376011)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?BoUL431MCBp9HPTEgZGR/FlL4RypwZrywxoNQ57llM3GmAXzXb/RUVzDi+HC?= =?us-ascii?Q?TuBoJp0qgyiSea7VWxG+/wfUT10yrwSglyBltLpkEfjnjXg/S9uIYNZtTEU0?= =?us-ascii?Q?nUnDK9c86ih7yj4fdHXkfA9YoM4gnXnyJ015YjaEyX7WGV41xpF7Od1k7eSX?= =?us-ascii?Q?PBYdCIcnYdvc79iMnHgqvFN5xj8audFDsqI00HtBf18xrm+FtBCJgo1X6bJs?= =?us-ascii?Q?cerNw/pkHnl3dnOTzVA/fjEQaxCTIQdOBEktn6ziInN11CCNjkJ9oyPcE9l5?= =?us-ascii?Q?mHOz85dYzpI3Hxzml8/jja2MKYEQn9GxfWEQ01L6zw/gpGHNiDGapgDpX4FF?= =?us-ascii?Q?X+FUDY2e+TzuvpVAuGn7zPJC7pXwTTd0PLYHaa+LLz5BaLVf65wviWKio5Ot?= =?us-ascii?Q?b3OisSwxHUUIqtsBGhgcANtFt2HvwgjJxeMEBxxkMCWtPDJHVpZ2fuWWrpWv?= =?us-ascii?Q?yIiTTcnRsF8cAp3TX4rjnc6bII/CyrhJg2+YOR41kTVS+LbuhAn7oU8m6q8X?= =?us-ascii?Q?RQFdjzC8PQGOkRxmu+3nVKqms6jFOl2bkMhe7qYqmi44tIknx1FkY2DeVbAf?= =?us-ascii?Q?jvDj+w/yVz9SyFNLn2rmWgwDje+o0b53OMhpkT7bwRAddKNuxKyP1rQkoofX?= =?us-ascii?Q?ABuyi8K976wzcpcABg1GbDxraRHcRdgBwZtP64ucduU9ItZUroX8UUesOCSQ?= =?us-ascii?Q?WmOE623fg7xFXDGOZRIcY3snQHL6deRkqS7q8sWc8qx1DHW8I19t/0fZqbjT?= =?us-ascii?Q?7+BaTmWqxQPSqNywdoRotsTjWqYgyYAKx6tztXo75twqoW0v9jCLwCVnt21b?= =?us-ascii?Q?URmFBboYAK5lefRhfZyTfImCUBz7dfL6/5ut48aykrUf1oyAvTukmvDx4FZ+?= =?us-ascii?Q?XAHR8HgoohFvhBrPc0IiGfuCgxUz7u9WfNKVWfJci+hBe/+XVQbDtFmQnXAR?= =?us-ascii?Q?8LTtY3nQgFK+nkzKLWlfCrFnW9OiIOTSaAAqldergGLE/w2QFym5c9AvoXDN?= =?us-ascii?Q?kKKCim1ZE54kWkdAS8Yhd0+GbdOgr6YDUJECBUQGRW9ZLtSrCdyu6bhSfIWx?= =?us-ascii?Q?WifwK9XBb+/lCWQtp2/maGQrax8rxH2zu3fUsuue87d+oxk6PJYn62st3rIr?= =?us-ascii?Q?2tmJHY5gx+4Bi2Ru/N6r5/RK6s+u8lXjF1PeW1b/H0SRSNbtx5FeKmkX+gXe?= =?us-ascii?Q?gSMTJx0kLRDcMHvABgP9zsPDgH8HtL5m0yFHtUGXvl8//347htwLF8Floq4m?= =?us-ascii?Q?O3xX1PBoGvIeeGSrBAljkc9pXoRWoPpCBv/EBZreJBBf3cMdsAgJv7i6ieUu?= =?us-ascii?Q?TeCPOyNfic7cJbLFry2CxqRM8eCZLQG0sN65SZbaH//ycfDo9lUN6twn8dzZ?= =?us-ascii?Q?uXOB6N0tyOGjfa4DkVataA3DZIZR9J72wLU19MmFvVAxv1pb6XXNnJP+t80W?= =?us-ascii?Q?+yJ0JYwtcL3R6rmjSKlw2inx/6JmdETXzpj/umnYzOR5wtZXoApmRJ3+7Lq6?= =?us-ascii?Q?8xDrUlQ/eHE7gL9mqzOyHAinDExrp/nqOlqOxLcEbKKr5Bwx9GcDvciYwlur?= =?us-ascii?Q?Dp2nXmnr6+so2m77zWbk1c/Pw4kogKXwlKZSwAjA?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 30986f49-3dd9-435f-c172-08dc91c75424 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:08.9365 (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: vFDWU/DYOwBLDGPbnclHq5valouckE82Zr9ZaWf3PrNRAeslVJ4xdZgrGbQP8uv0qQtJkA39/WZ9CrHpIzvM9A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB9190 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sta_cmd.c | 3229 ++++++++++++++++++++ 1 file changed, 3229 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sta_cmd.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c b/drivers/net/wirel= ess/nxp/nxpwifi/sta_cmd.c new file mode 100644 index 000000000000..a570949ceac5 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c @@ -0,0 +1,3229 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station command handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" +#include "11ac.h" + +static bool disable_auto_ds; + +static int +nxpwifi_cmd_sta_get_hw_spec(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_get_hw_spec *hw_spec =3D &cmd->params.hw_spec; + + cmd->command =3D cpu_to_le16(HOST_CMD_GET_HW_SPEC); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + + S_DS_GEN); + memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); + + return 0; +} + +static int +nxpwifi_ret_sta_get_hw_spec(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_get_hw_spec *hw_spec =3D &resp->params.hw_spec; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ie_types_header *tlv; + struct hw_spec_api_rev *api_rev; + struct hw_spec_max_conn *max_conn; + u16 resp_size, api_id; + int i, left_len, parsed_len =3D 0; + + adapter->fw_cap_info =3D le32_to_cpu(hw_spec->fw_cap_info); + + if (IS_SUPPORT_MULTI_BANDS(adapter)) + adapter->fw_bands =3D (u8)GET_FW_DEFAULT_BANDS(adapter); + else + adapter->fw_bands =3D BAND_B; + + adapter->config_bands =3D adapter->fw_bands; + + if (adapter->fw_bands & BAND_A) { + if (adapter->fw_bands & BAND_GN) { + adapter->config_bands |=3D BAND_AN; + adapter->fw_bands |=3D BAND_AN; + } + } + + adapter->fw_release_number =3D le32_to_cpu(hw_spec->fw_release_number); + adapter->fw_api_ver =3D (adapter->fw_release_number >> 16) & 0xff; + adapter->number_of_antenna =3D + le16_to_cpu(hw_spec->number_of_antenna) & 0xf; + + if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { + adapter->is_hw_11ac_capable =3D true; + + /* Copy 11AC cap */ + adapter->hw_dot_11ac_dev_cap =3D + le32_to_cpu(hw_spec->dot_11ac_dev_cap); + adapter->usr_dot_11ac_dev_cap_bg =3D adapter->hw_dot_11ac_dev_cap + & ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK; + adapter->usr_dot_11ac_dev_cap_a =3D adapter->hw_dot_11ac_dev_cap + & ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK; + + /* Copy 11AC mcs */ + adapter->hw_dot_11ac_mcs_support =3D + le32_to_cpu(hw_spec->dot_11ac_mcs_support); + adapter->usr_dot_11ac_mcs_support =3D + adapter->hw_dot_11ac_mcs_support; + } else { + adapter->is_hw_11ac_capable =3D false; + } + + resp_size =3D le16_to_cpu(resp->size) - S_DS_GEN; + if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) { + /* we have variable HW SPEC information */ + left_len =3D resp_size - sizeof(struct host_cmd_ds_get_hw_spec); + while (left_len > sizeof(struct nxpwifi_ie_types_header)) { + tlv =3D (void *)&hw_spec->tlvs + parsed_len; + switch (le16_to_cpu(tlv->type)) { + case TLV_TYPE_API_REV: + api_rev =3D (struct hw_spec_api_rev *)tlv; + api_id =3D le16_to_cpu(api_rev->api_id); + switch (api_id) { + case KEY_API_VER_ID: + adapter->key_api_major_ver =3D + api_rev->major_ver; + adapter->key_api_minor_ver =3D + api_rev->minor_ver; + nxpwifi_dbg(adapter, INFO, + "key_api v%d.%d\n", + adapter->key_api_major_ver, + adapter->key_api_minor_ver); + break; + case FW_API_VER_ID: + adapter->fw_api_ver =3D + api_rev->major_ver; + nxpwifi_dbg(adapter, INFO, + "Firmware api version %d.%d\n", + adapter->fw_api_ver, + api_rev->minor_ver); + break; + case UAP_FW_API_VER_ID: + nxpwifi_dbg(adapter, INFO, + "uAP api version %d.%d\n", + api_rev->major_ver, + api_rev->minor_ver); + break; + case CHANRPT_API_VER_ID: + nxpwifi_dbg(adapter, INFO, + "channel report api version %d.%d\n", + api_rev->major_ver, + api_rev->minor_ver); + break; + case FW_HOTFIX_VER_ID: + nxpwifi_dbg(adapter, INFO, + "Firmware hotfix version %d\n", + api_rev->major_ver); + break; + default: + nxpwifi_dbg(adapter, FATAL, + "Unknown api_id: %d\n", + api_id); + break; + } + break; + case TLV_TYPE_MAX_CONN: + max_conn =3D (struct hw_spec_max_conn *)tlv; + adapter->max_sta_conn =3D max_conn->max_sta_conn; + nxpwifi_dbg(adapter, INFO, + "max sta connections: %u\n", + adapter->max_sta_conn); + break; + default: + nxpwifi_dbg(adapter, FATAL, + "Unknown GET_HW_SPEC TLV type: %#x\n", + le16_to_cpu(tlv->type)); + break; + } + parsed_len +=3D le16_to_cpu(tlv->len) + + sizeof(struct nxpwifi_ie_types_header); + left_len -=3D le16_to_cpu(tlv->len) + + sizeof(struct nxpwifi_ie_types_header); + } + } + + if (adapter->key_api_major_ver < KEY_API_VER_MAJOR_V2) + return -EOPNOTSUPP; + + nxpwifi_dbg(adapter, INFO, + "info: GET_HW_SPEC: fw_release_number- %#x\n", + adapter->fw_release_number); + nxpwifi_dbg(adapter, INFO, + "info: GET_HW_SPEC: permanent addr: %pM\n", + hw_spec->permanent_addr); + nxpwifi_dbg(adapter, INFO, + "info: GET_HW_SPEC: hw_if_version=3D%#x version=3D%#x\n", + le16_to_cpu(hw_spec->hw_if_version), + le16_to_cpu(hw_spec->version)); + + ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr); + adapter->region_code =3D le16_to_cpu(hw_spec->region_code); + + for (i =3D 0; i < NXPWIFI_MAX_REGION_CODE; i++) + /* Use the region code to search for the index */ + if (adapter->region_code =3D=3D region_code_index[i]) + break; + + /* If it's unidentified region code, use the default (world) */ + if (i >=3D NXPWIFI_MAX_REGION_CODE) { + adapter->region_code =3D 0x00; + nxpwifi_dbg(adapter, WARN, + "cmd: unknown region code, use default (USA)\n"); + } + + adapter->hw_dot_11n_dev_cap =3D le32_to_cpu(hw_spec->dot_11n_dev_cap); + adapter->hw_dev_mcs_support =3D hw_spec->dev_mcs_support; + adapter->user_dev_mcs_support =3D adapter->hw_dev_mcs_support; + + if (adapter->if_ops.update_mp_end_port) { + u16 mp_end_port; + + mp_end_port =3D le16_to_cpu(hw_spec->mp_end_port); + adapter->if_ops.update_mp_end_port(adapter, mp_end_port); + } + + if (adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) + adapter->scan_chan_gap_enabled =3D true; + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_scan(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_802_11_scan(cmd, data_buf); +} + +static int +nxpwifi_ret_sta_802_11_scan(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + + ret =3D nxpwifi_ret_802_11_scan(priv, resp); + adapter->curr_cmd->wait_q_enabled =3D false; + + return ret; +} + +static int +nxpwifi_cmd_sta_802_11_get_log(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_GET_LOG); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_get_log(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11_get_log *get_log =3D + &resp->params.get_log; + struct nxpwifi_ds_get_stats *stats =3D + (struct nxpwifi_ds_get_stats *)data_buf; + + if (stats) { + stats->mcast_tx_frame =3D le32_to_cpu(get_log->mcast_tx_frame); + stats->failed =3D le32_to_cpu(get_log->failed); + stats->retry =3D le32_to_cpu(get_log->retry); + stats->multi_retry =3D le32_to_cpu(get_log->multi_retry); + stats->frame_dup =3D le32_to_cpu(get_log->frame_dup); + stats->rts_success =3D le32_to_cpu(get_log->rts_success); + stats->rts_failure =3D le32_to_cpu(get_log->rts_failure); + stats->ack_failure =3D le32_to_cpu(get_log->ack_failure); + stats->rx_frag =3D le32_to_cpu(get_log->rx_frag); + stats->mcast_rx_frame =3D le32_to_cpu(get_log->mcast_rx_frame); + stats->fcs_error =3D le32_to_cpu(get_log->fcs_error); + stats->tx_frame =3D le32_to_cpu(get_log->tx_frame); + stats->wep_icv_error[0] =3D + le32_to_cpu(get_log->wep_icv_err_cnt[0]); + stats->wep_icv_error[1] =3D + le32_to_cpu(get_log->wep_icv_err_cnt[1]); + stats->wep_icv_error[2] =3D + le32_to_cpu(get_log->wep_icv_err_cnt[2]); + stats->wep_icv_error[3] =3D + le32_to_cpu(get_log->wep_icv_err_cnt[3]); + stats->bcn_rcv_cnt =3D le32_to_cpu(get_log->bcn_rcv_cnt); + stats->bcn_miss_cnt =3D le32_to_cpu(get_log->bcn_miss_cnt); + } + + return 0; +} + +static int +nxpwifi_cmd_sta_mac_multicast_adr(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_mac_multicast_adr *mcast_addr =3D &cmd->params.mc_addr; + struct nxpwifi_multicast_list *mcast_list =3D + (struct nxpwifi_multicast_list *)data_buf; + + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + + S_DS_GEN); + cmd->command =3D cpu_to_le16(HOST_CMD_MAC_MULTICAST_ADR); + + mcast_addr->action =3D cpu_to_le16(cmd_action); + mcast_addr->num_of_adrs =3D + cpu_to_le16((u16)mcast_list->num_multicast_addr); + memcpy(mcast_addr->mac_list, mcast_list->mac_list, + mcast_list->num_multicast_addr * ETH_ALEN); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_associate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_802_11_associate(priv, cmd, data_buf); +} + +static int +nxpwifi_ret_sta_802_11_associate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + return nxpwifi_ret_802_11_associate(priv, resp); +} + +static int +nxpwifi_cmd_sta_802_11_snmp_mib(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_802_11_snmp_mib *snmp_mib =3D &cmd->params.smib; + u16 *ul_temp =3D (u16 *)data_buf; + + nxpwifi_dbg(priv->adapter, CMD, + "cmd: SNMP_CMD: cmd_oid =3D 0x%x\n", cmd_type); + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_SNMP_MIB); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) + + S_DS_GEN); + + snmp_mib->oid =3D cpu_to_le16((u16)cmd_type); + if (cmd_action =3D=3D HOST_ACT_GEN_GET) { + snmp_mib->query_type =3D cpu_to_le16(HOST_ACT_GEN_GET); + snmp_mib->buf_size =3D cpu_to_le16(MAX_SNMP_BUF_SIZE); + le16_unaligned_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE); + } else if (cmd_action =3D=3D HOST_ACT_GEN_SET) { + snmp_mib->query_type =3D cpu_to_le16(HOST_ACT_GEN_SET); + snmp_mib->buf_size =3D cpu_to_le16(sizeof(u16)); + put_unaligned_le16(*ul_temp, snmp_mib->value); + le16_unaligned_add_cpu(&cmd->size, sizeof(u16)); + } + + nxpwifi_dbg(priv->adapter, CMD, + "cmd: SNMP_CMD: Action=3D0x%x, OID=3D0x%x,\t" + "OIDSize=3D0x%x, Value=3D0x%x\n", + cmd_action, cmd_type, le16_to_cpu(snmp_mib->buf_size), + get_unaligned_le16(snmp_mib->value)); + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_snmp_mib(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11_snmp_mib *smib =3D &resp->params.smib; + u16 oid =3D le16_to_cpu(smib->oid); + u16 query_type =3D le16_to_cpu(smib->query_type); + u32 ul_temp; + + nxpwifi_dbg(priv->adapter, INFO, + "info: SNMP_RESP: oid value =3D %#x,\t" + "query_type =3D %#x, buf size =3D %#x\n", + oid, query_type, le16_to_cpu(smib->buf_size)); + if (query_type =3D=3D HOST_ACT_GEN_GET) { + ul_temp =3D get_unaligned_le16(smib->value); + if (data_buf) + *(u32 *)data_buf =3D ul_temp; + switch (oid) { + case FRAG_THRESH_I: + nxpwifi_dbg(priv->adapter, INFO, + "info: SNMP_RESP: FragThsd =3D%u\n", + ul_temp); + break; + case RTS_THRESH_I: + nxpwifi_dbg(priv->adapter, INFO, + "info: SNMP_RESP: RTSThsd =3D%u\n", + ul_temp); + break; + case SHORT_RETRY_LIM_I: + nxpwifi_dbg(priv->adapter, INFO, + "info: SNMP_RESP: TxRetryCount=3D%u\n", + ul_temp); + break; + case DTIM_PERIOD_I: + nxpwifi_dbg(priv->adapter, INFO, + "info: SNMP_RESP: DTIM period=3D%u\n", + ul_temp); + break; + default: + break; + } + } + + return 0; +} + +static int nxpwifi_cmd_sta_reg_access(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_ds_reg_rw *reg_rw =3D data_buf; + + cmd->command =3D cpu_to_le16(cmd_no); + + switch (cmd_no) { + case HOST_CMD_MAC_REG_ACCESS: + { + struct host_cmd_ds_mac_reg_access *mac_reg; + + cmd->size =3D cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); + mac_reg =3D &cmd->params.mac_reg; + mac_reg->action =3D cpu_to_le16(cmd_action); + mac_reg->offset =3D cpu_to_le16((u16)reg_rw->offset); + mac_reg->value =3D cpu_to_le32(reg_rw->value); + break; + } + case HOST_CMD_BBP_REG_ACCESS: + { + struct host_cmd_ds_bbp_reg_access *bbp_reg; + + cmd->size =3D cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); + bbp_reg =3D &cmd->params.bbp_reg; + bbp_reg->action =3D cpu_to_le16(cmd_action); + bbp_reg->offset =3D cpu_to_le16((u16)reg_rw->offset); + bbp_reg->value =3D (u8)reg_rw->value; + break; + } + case HOST_CMD_RF_REG_ACCESS: + { + struct host_cmd_ds_rf_reg_access *rf_reg; + + cmd->size =3D cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); + rf_reg =3D &cmd->params.rf_reg; + rf_reg->action =3D cpu_to_le16(cmd_action); + rf_reg->offset =3D cpu_to_le16((u16)reg_rw->offset); + rf_reg->value =3D (u8)reg_rw->value; + break; + } + case HOST_CMD_PMIC_REG_ACCESS: + { + struct host_cmd_ds_pmic_reg_access *pmic_reg; + + cmd->size =3D cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); + pmic_reg =3D &cmd->params.pmic_reg; + pmic_reg->action =3D cpu_to_le16(cmd_action); + pmic_reg->offset =3D cpu_to_le16((u16)reg_rw->offset); + pmic_reg->value =3D (u8)reg_rw->value; + break; + } + case HOST_CMD_CAU_REG_ACCESS: + { + struct host_cmd_ds_rf_reg_access *cau_reg; + + cmd->size =3D cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); + cau_reg =3D &cmd->params.rf_reg; + cau_reg->action =3D cpu_to_le16(cmd_action); + cau_reg->offset =3D cpu_to_le16((u16)reg_rw->offset); + cau_reg->value =3D (u8)reg_rw->value; + break; + } + case HOST_CMD_802_11_EEPROM_ACCESS: + { + struct nxpwifi_ds_read_eeprom *rd_eeprom =3D data_buf; + struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =3D + &cmd->params.eeprom; + + cmd->size =3D cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); + cmd_eeprom->action =3D cpu_to_le16(cmd_action); + cmd_eeprom->offset =3D cpu_to_le16(rd_eeprom->offset); + cmd_eeprom->byte_count =3D cpu_to_le16(rd_eeprom->byte_count); + cmd_eeprom->value =3D 0; + break; + } + default: + return -1; + } + + return 0; +} + +static int +nxpwifi_ret_sta_reg_access(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_ds_reg_rw *reg_rw; + struct nxpwifi_ds_read_eeprom *eeprom; + union reg { + struct host_cmd_ds_mac_reg_access *mac; + struct host_cmd_ds_bbp_reg_access *bbp; + struct host_cmd_ds_rf_reg_access *rf; + struct host_cmd_ds_pmic_reg_access *pmic; + struct host_cmd_ds_802_11_eeprom_access *eeprom; + } r; + + if (!data_buf) + return 0; + + reg_rw =3D data_buf; + eeprom =3D data_buf; + switch (cmdresp_no) { + case HOST_CMD_MAC_REG_ACCESS: + r.mac =3D &resp->params.mac_reg; + reg_rw->offset =3D (u32)le16_to_cpu(r.mac->offset); + reg_rw->value =3D le32_to_cpu(r.mac->value); + break; + case HOST_CMD_BBP_REG_ACCESS: + r.bbp =3D &resp->params.bbp_reg; + reg_rw->offset =3D (u32)le16_to_cpu(r.bbp->offset); + reg_rw->value =3D (u32)r.bbp->value; + break; + + case HOST_CMD_RF_REG_ACCESS: + r.rf =3D &resp->params.rf_reg; + reg_rw->offset =3D (u32)le16_to_cpu(r.rf->offset); + reg_rw->value =3D (u32)r.bbp->value; + break; + case HOST_CMD_PMIC_REG_ACCESS: + r.pmic =3D &resp->params.pmic_reg; + reg_rw->offset =3D (u32)le16_to_cpu(r.pmic->offset); + reg_rw->value =3D (u32)r.pmic->value; + break; + case HOST_CMD_CAU_REG_ACCESS: + r.rf =3D &resp->params.rf_reg; + reg_rw->offset =3D (u32)le16_to_cpu(r.rf->offset); + reg_rw->value =3D (u32)r.rf->value; + break; + case HOST_CMD_802_11_EEPROM_ACCESS: + r.eeprom =3D &resp->params.eeprom; + pr_debug("info: EEPROM read len=3D%x\n", + le16_to_cpu(r.eeprom->byte_count)); + if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) { + eeprom->byte_count =3D 0; + pr_debug("info: EEPROM read length is too big\n"); + return -1; + } + eeprom->offset =3D le16_to_cpu(r.eeprom->offset); + eeprom->byte_count =3D le16_to_cpu(r.eeprom->byte_count); + if (eeprom->byte_count > 0) + memcpy(&eeprom->value, &r.eeprom->value, + min((u16)MAX_EEPROM_DATA, eeprom->byte_count)); + break; + default: + return -1; + } + return 0; +} + +static int +nxpwifi_cmd_sta_rf_tx_pwr(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_rf_tx_pwr *txp =3D &cmd->params.txp; + + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr) + + S_DS_GEN); + cmd->command =3D cpu_to_le16(HOST_CMD_RF_TX_PWR); + txp->action =3D cpu_to_le16(cmd_action); + + return 0; +} + +static int +nxpwifi_ret_sta_rf_tx_pwr(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_rf_tx_pwr *txp =3D &resp->params.txp; + u16 action =3D le16_to_cpu(txp->action); + + priv->tx_power_level =3D le16_to_cpu(txp->cur_level); + + if (action =3D=3D HOST_ACT_GEN_GET) { + priv->max_tx_power_level =3D txp->max_power; + priv->min_tx_power_level =3D txp->min_power; + } + + nxpwifi_dbg(priv->adapter, INFO, + "Current TxPower Level=3D%d, Max Power=3D%d, Min Power=3D%d\n", + priv->tx_power_level, priv->max_tx_power_level, + priv->min_tx_power_level); + + return 0; +} + +static int +nxpwifi_cmd_sta_rf_antenna(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_rf_ant_mimo *ant_mimo =3D &cmd->params.ant_mimo; + struct host_cmd_ds_rf_ant_siso *ant_siso =3D &cmd->params.ant_siso; + struct nxpwifi_ds_ant_cfg *ant_cfg =3D + (struct nxpwifi_ds_ant_cfg *)data_buf; + + cmd->command =3D cpu_to_le16(HOST_CMD_RF_ANTENNA); + + switch (cmd_action) { + case HOST_ACT_GEN_SET: + if (priv->adapter->hw_dev_mcs_support =3D=3D HT_STREAM_2X2) { + cmd->size =3D cpu_to_le16(sizeof(struct + host_cmd_ds_rf_ant_mimo) + + S_DS_GEN); + ant_mimo->action_tx =3D cpu_to_le16(HOST_ACT_SET_TX); + ant_mimo->tx_ant_mode =3D + cpu_to_le16((u16)ant_cfg->tx_ant); + ant_mimo->action_rx =3D cpu_to_le16(HOST_ACT_SET_RX); + ant_mimo->rx_ant_mode =3D + cpu_to_le16((u16)ant_cfg->rx_ant); + } else { + cmd->size =3D cpu_to_le16(sizeof(struct + host_cmd_ds_rf_ant_siso) + + S_DS_GEN); + ant_siso->action =3D cpu_to_le16(HOST_ACT_SET_BOTH); + ant_siso->ant_mode =3D cpu_to_le16((u16)ant_cfg->tx_ant); + } + break; + case HOST_ACT_GEN_GET: + if (priv->adapter->hw_dev_mcs_support =3D=3D HT_STREAM_2X2) { + cmd->size =3D cpu_to_le16(sizeof(struct + host_cmd_ds_rf_ant_mimo) + + S_DS_GEN); + ant_mimo->action_tx =3D cpu_to_le16(HOST_ACT_GET_TX); + ant_mimo->action_rx =3D cpu_to_le16(HOST_ACT_GET_RX); + } else { + cmd->size =3D cpu_to_le16(sizeof(struct + host_cmd_ds_rf_ant_siso) + + S_DS_GEN); + ant_siso->action =3D cpu_to_le16(HOST_ACT_GET_BOTH); + } + break; + } + return 0; +} + +static int +nxpwifi_ret_sta_rf_antenna(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_rf_ant_mimo *ant_mimo =3D &resp->params.ant_mimo; + struct host_cmd_ds_rf_ant_siso *ant_siso =3D &resp->params.ant_siso; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (adapter->hw_dev_mcs_support =3D=3D HT_STREAM_2X2) { + priv->tx_ant =3D le16_to_cpu(ant_mimo->tx_ant_mode); + priv->rx_ant =3D le16_to_cpu(ant_mimo->rx_ant_mode); + nxpwifi_dbg(adapter, INFO, + "RF_ANT_RESP: Tx action =3D 0x%x, Tx Mode =3D 0x%04x\t" + "Rx action =3D 0x%x, Rx Mode =3D 0x%04x\n", + le16_to_cpu(ant_mimo->action_tx), + le16_to_cpu(ant_mimo->tx_ant_mode), + le16_to_cpu(ant_mimo->action_rx), + le16_to_cpu(ant_mimo->rx_ant_mode)); + } else { + priv->tx_ant =3D le16_to_cpu(ant_siso->ant_mode); + priv->rx_ant =3D le16_to_cpu(ant_siso->ant_mode); + nxpwifi_dbg(adapter, INFO, + "RF_ANT_RESP: action =3D 0x%x, Mode =3D 0x%04x\n", + le16_to_cpu(ant_siso->action), + le16_to_cpu(ant_siso->ant_mode)); + } + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_deauthenticate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_802_11_deauthenticate *deauth =3D &cmd->params.deauth; + u8 *mac =3D (u8 *)data_buf; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_DEAUTHENTICATE); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) + + S_DS_GEN); + + /* Set AP MAC address */ + memcpy(deauth->mac_addr, mac, ETH_ALEN); + + nxpwifi_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr); + + deauth->reason_code =3D cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_deauthenticate(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->dbg.num_cmd_deauth++; + if (!memcmp(resp->params.deauth.mac_addr, + &priv->curr_bss_params.bss_descriptor.mac_address, + sizeof(resp->params.deauth.mac_addr))) + nxpwifi_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING, + false); + + return 0; +} + +static int +nxpwifi_cmd_sta_mac_control(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_mac_control *mac_ctrl =3D &cmd->params.mac_ctrl; + u32 *action =3D (u32 *)data_buf; + + if (cmd_action !=3D HOST_ACT_GEN_SET) { + nxpwifi_dbg(priv->adapter, ERROR, + "mac_control: only support set cmd\n"); + return -1; + } + + cmd->command =3D cpu_to_le16(HOST_CMD_MAC_CONTROL); + cmd->size =3D + cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); + mac_ctrl->action =3D cpu_to_le32(*action); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_mac_address(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_MAC_ADDRESS); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + + S_DS_GEN); + cmd->result =3D 0; + + cmd->params.mac_addr.action =3D cpu_to_le16(cmd_action); + + if (cmd_action =3D=3D HOST_ACT_GEN_SET) + memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, + ETH_ALEN); + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_mac_address(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11_mac_address *cmd_mac_addr; + + cmd_mac_addr =3D &resp->params.mac_addr; + + memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); + + nxpwifi_dbg(priv->adapter, INFO, + "info: set mac address: %pM\n", priv->curr_addr); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11d_domain_info(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11d_domain_info *domain_info =3D + &cmd->params.domain_info; + struct nxpwifi_ietypes_domain_param_set *domain =3D + &domain_info->domain; + u8 no_of_triplet =3D adapter->domain_reg.no_of_triplet; + + nxpwifi_dbg(adapter, INFO, + "info: 11D: no_of_triplet=3D0x%x\n", no_of_triplet); + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11D_DOMAIN_INFO); + domain_info->action =3D cpu_to_le16(cmd_action); + if (cmd_action =3D=3D HOST_ACT_GEN_GET) { + cmd->size =3D cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); + return 0; + } + + /* Set domain info fields */ + domain->header.type =3D cpu_to_le16(WLAN_EID_COUNTRY); + memcpy(domain->country_code, adapter->domain_reg.country_code, + sizeof(domain->country_code)); + + domain->header.len =3D + cpu_to_le16((no_of_triplet * + sizeof(struct ieee80211_country_ie_triplet)) + + sizeof(domain->country_code)); + + if (no_of_triplet) { + memcpy(domain->triplet, adapter->domain_reg.triplet, + no_of_triplet * sizeof(struct + ieee80211_country_ie_triplet)); + + cmd->size =3D cpu_to_le16(sizeof(domain_info->action) + + le16_to_cpu(domain->header.len) + + sizeof(struct nxpwifi_ie_types_header) + + S_DS_GEN); + } else { + cmd->size =3D cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); + } + + return 0; +} + +static int +nxpwifi_ret_sta_802_11d_domain_info(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =3D + &resp->params.domain_info_resp; + struct nxpwifi_ietypes_domain_param_set *domain =3D &domain_info->domain; + u16 action =3D le16_to_cpu(domain_info->action); + u8 no_of_triplet; + + no_of_triplet =3D (u8)((le16_to_cpu(domain->header.len) + - IEEE80211_COUNTRY_STRING_LEN) + / sizeof(struct ieee80211_country_ie_triplet)); + + nxpwifi_dbg(priv->adapter, INFO, + "info: 11D Domain Info Resp: no_of_triplet=3D%d\n", + no_of_triplet); + + if (no_of_triplet > NXPWIFI_MAX_TRIPLET_802_11D) { + nxpwifi_dbg(priv->adapter, FATAL, + "11D: invalid number of triplets %d returned\n", + no_of_triplet); + return -1; + } + + switch (action) { + case HOST_ACT_GEN_SET: /* Proc Set Action */ + break; + case HOST_ACT_GEN_GET: + break; + default: + nxpwifi_dbg(priv->adapter, ERROR, + "11D: invalid action:%d\n", domain_info->action); + return -1; + } + + return 0; +} + +static int nxpwifi_set_aes_key(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + struct nxpwifi_ds_encrypt_key *enc_key, + struct host_cmd_ds_802_11_key_material *km) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 size, len =3D KEY_PARAMS_FIXED_LEN; + + if (enc_key->is_igtk_key) { + nxpwifi_dbg(adapter, INFO, + "%s: Set CMAC AES Key\n", __func__); + if (enc_key->is_rx_seq_valid) + memcpy(km->key_param_set.key_params.cmac_aes.ipn, + enc_key->pn, enc_key->pn_len); + km->key_param_set.key_info &=3D cpu_to_le16(~KEY_MCAST); + km->key_param_set.key_info |=3D cpu_to_le16(KEY_IGTK); + km->key_param_set.key_type =3D KEY_TYPE_ID_AES_CMAC; + km->key_param_set.key_params.cmac_aes.key_len =3D + cpu_to_le16(enc_key->key_len); + memcpy(km->key_param_set.key_params.cmac_aes.key, + enc_key->key_material, enc_key->key_len); + len +=3D sizeof(struct nxpwifi_cmac_aes_param); + } else if (enc_key->is_igtk_def_key) { + nxpwifi_dbg(adapter, INFO, + "%s: Set CMAC default Key index\n", __func__); + km->key_param_set.key_type =3D KEY_TYPE_ID_AES_CMAC_DEF; + km->key_param_set.key_idx =3D enc_key->key_index & KEY_INDEX_MASK; + } else { + nxpwifi_dbg(adapter, INFO, + "%s: Set AES Key\n", __func__); + if (enc_key->is_rx_seq_valid) + memcpy(km->key_param_set.key_params.aes.pn, + enc_key->pn, enc_key->pn_len); + km->key_param_set.key_type =3D KEY_TYPE_ID_AES; + km->key_param_set.key_params.aes.key_len =3D + cpu_to_le16(enc_key->key_len); + memcpy(km->key_param_set.key_params.aes.key, + enc_key->key_material, enc_key->key_len); + len +=3D sizeof(struct nxpwifi_aes_param); + } + + km->key_param_set.len =3D cpu_to_le16(len); + size =3D len + sizeof(struct nxpwifi_ie_types_header) + + sizeof(km->action) + S_DS_GEN; + cmd->size =3D cpu_to_le16(size); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_key_material(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ds_encrypt_key *enc_key =3D + (struct nxpwifi_ds_encrypt_key *)data_buf; + u8 *mac =3D enc_key->mac_addr; + u16 key_info, len =3D KEY_PARAMS_FIXED_LEN; + struct host_cmd_ds_802_11_key_material *km =3D + &cmd->params.key_material; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_KEY_MATERIAL); + km->action =3D cpu_to_le16(cmd_action); + + if (cmd_action =3D=3D HOST_ACT_GEN_GET) { + nxpwifi_dbg(adapter, INFO, "%s: Get key\n", __func__); + km->key_param_set.key_idx =3D + enc_key->key_index & KEY_INDEX_MASK; + km->key_param_set.type =3D cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + km->key_param_set.len =3D cpu_to_le16(KEY_PARAMS_FIXED_LEN); + memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); + + if (enc_key->key_index & NXPWIFI_KEY_INDEX_UNICAST) + key_info =3D KEY_UNICAST; + else + key_info =3D KEY_MCAST; + + if (enc_key->is_igtk_key) + key_info |=3D KEY_IGTK; + + km->key_param_set.key_info =3D cpu_to_le16(key_info); + + cmd->size =3D cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + + S_DS_GEN + KEY_PARAMS_FIXED_LEN + + sizeof(km->action)); + return 0; + } + + memset(&km->key_param_set, 0, + sizeof(struct nxpwifi_ie_type_key_param_set)); + + if (enc_key->key_disable) { + nxpwifi_dbg(adapter, INFO, "%s: Remove key\n", __func__); + km->action =3D cpu_to_le16(HOST_ACT_GEN_REMOVE); + km->key_param_set.type =3D cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + km->key_param_set.len =3D cpu_to_le16(KEY_PARAMS_FIXED_LEN); + km->key_param_set.key_idx =3D enc_key->key_index & KEY_INDEX_MASK; + key_info =3D KEY_MCAST | KEY_UNICAST; + km->key_param_set.key_info =3D cpu_to_le16(key_info); + memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); + cmd->size =3D cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + + S_DS_GEN + KEY_PARAMS_FIXED_LEN + + sizeof(km->action)); + return 0; + } + + km->action =3D cpu_to_le16(HOST_ACT_GEN_SET); + km->key_param_set.key_idx =3D enc_key->key_index & KEY_INDEX_MASK; + km->key_param_set.type =3D cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + key_info =3D KEY_ENABLED; + memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); + + if (enc_key->key_len <=3D WLAN_KEY_LEN_WEP104) { + nxpwifi_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__); + len +=3D sizeof(struct nxpwifi_wep_param); + km->key_param_set.len =3D cpu_to_le16(len); + km->key_param_set.key_type =3D KEY_TYPE_ID_WEP; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + key_info |=3D KEY_MCAST | KEY_UNICAST; + } else { + if (enc_key->is_current_wep_key) { + key_info |=3D KEY_MCAST | KEY_UNICAST; + if (km->key_param_set.key_idx =3D=3D + (priv->wep_key_curr_index & KEY_INDEX_MASK)) + key_info |=3D KEY_DEFAULT; + } else { + if (is_broadcast_ether_addr(mac)) + key_info |=3D KEY_MCAST; + else + key_info |=3D KEY_UNICAST | KEY_DEFAULT; + } + } + km->key_param_set.key_info =3D cpu_to_le16(key_info); + + km->key_param_set.key_params.wep.key_len =3D + cpu_to_le16(enc_key->key_len); + memcpy(km->key_param_set.key_params.wep.key, + enc_key->key_material, enc_key->key_len); + + cmd->size =3D cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + + len + sizeof(km->action) + S_DS_GEN); + return 0; + } + + if (is_broadcast_ether_addr(mac)) + key_info |=3D KEY_MCAST | KEY_RX_KEY; + else + key_info |=3D KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY; + + /* Enable default key for WPA/WPA2 */ + if (!priv->wpa_is_gtk_set) + key_info |=3D KEY_DEFAULT; + + km->key_param_set.key_info =3D cpu_to_le16(key_info); + + if (enc_key->key_len =3D=3D WLAN_KEY_LEN_CCMP) + return nxpwifi_set_aes_key(priv, cmd, enc_key, km); + + if (enc_key->key_len =3D=3D WLAN_KEY_LEN_TKIP) { + nxpwifi_dbg(adapter, INFO, + "%s: Set TKIP Key\n", __func__); + if (enc_key->is_rx_seq_valid) + memcpy(km->key_param_set.key_params.tkip.pn, + enc_key->pn, enc_key->pn_len); + km->key_param_set.key_type =3D KEY_TYPE_ID_TKIP; + km->key_param_set.key_params.tkip.key_len =3D + cpu_to_le16(enc_key->key_len); + memcpy(km->key_param_set.key_params.tkip.key, + enc_key->key_material, enc_key->key_len); + + len +=3D sizeof(struct nxpwifi_tkip_param); + km->key_param_set.len =3D cpu_to_le16(len); + cmd->size =3D cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + + len + sizeof(km->action) + S_DS_GEN); + } + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_key_material(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11_key_material *key; + int len; + + key =3D &resp->params.key_material; + + len =3D le16_to_cpu(key->key_param_set.key_params.aes.key_len); + if (len > sizeof(key->key_param_set.key_params.aes.key)) + return -EINVAL; + + if (le16_to_cpu(key->action) =3D=3D HOST_ACT_GEN_SET) { + if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { + nxpwifi_dbg(priv->adapter, INFO, + "info: key: GTK is set\n"); + priv->wpa_is_gtk_set =3D true; + priv->scan_block =3D false; + priv->port_open =3D true; + } + } + + if (key->key_param_set.key_type !=3D KEY_TYPE_ID_AES) + return 0; + + memset(priv->aes_key.key_param_set.key_params.aes.key, 0, + sizeof(key->key_param_set.key_params.aes.key)); + priv->aes_key.key_param_set.key_params.aes.key_len =3D cpu_to_le16(len); + memcpy(priv->aes_key.key_param_set.key_params.aes.key, + key->key_param_set.key_params.aes.key, len); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_bg_scan_config(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_802_11_bg_scan_config(priv, cmd, data_buf); +} + +static int +nxpwifi_cmd_sta_802_11_bg_scan_query(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_802_11_bg_scan_query(cmd); +} + +static int +nxpwifi_ret_sta_802_11_bg_scan_query(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + + ret =3D nxpwifi_ret_802_11_scan(priv, resp); + cfg80211_sched_scan_results(priv->wdev.wiphy, 0); + nxpwifi_dbg(adapter, CMD, + "info: CMD_RESP: BG_SCAN result is ready!\n"); + + return ret; +} + +static int +nxpwifi_cmd_sta_wmm_get_status(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(HOST_CMD_WMM_GET_STATUS); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_ret_sta_wmm_get_status(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + return nxpwifi_ret_wmm_get_status(priv, resp); +} + +static int +nxpwifi_cmd_sta_802_11_subsc_evt(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_802_11_subsc_evt *subsc_evt =3D &cmd->params.subsc_evt; + struct nxpwifi_ds_misc_subsc_evt *subsc_evt_cfg =3D + (struct nxpwifi_ds_misc_subsc_evt *)data_buf; + struct nxpwifi_ie_types_rssi_threshold *rssi_tlv; + u16 event_bitmap; + u8 *pos; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_SUBSCRIBE_EVENT); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) + + S_DS_GEN); + + subsc_evt->action =3D cpu_to_le16(subsc_evt_cfg->action); + nxpwifi_dbg(priv->adapter, CMD, + "cmd: action: %d\n", subsc_evt_cfg->action); + + /*For query requests, no configuration TLV structures are to be added.*/ + if (subsc_evt_cfg->action =3D=3D HOST_ACT_GEN_GET) + return 0; + + subsc_evt->events =3D cpu_to_le16(subsc_evt_cfg->events); + + event_bitmap =3D subsc_evt_cfg->events; + nxpwifi_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n", + event_bitmap); + + if ((subsc_evt_cfg->action =3D=3D HOST_ACT_BITWISE_CLR || + subsc_evt_cfg->action =3D=3D HOST_ACT_BITWISE_SET) && + event_bitmap =3D=3D 0) { + nxpwifi_dbg(priv->adapter, ERROR, + "Error: No event specified\t" + "for bitwise action type\n"); + return -EINVAL; + } + + /* Append TLV structures for each of the specified events for + * subscribing or re-configuring. This is not required for + * bitwise unsubscribing request. + */ + if (subsc_evt_cfg->action =3D=3D HOST_ACT_BITWISE_CLR) + return 0; + + pos =3D ((u8 *)subsc_evt) + + sizeof(struct host_cmd_ds_802_11_subsc_evt); + + if (event_bitmap & BITMASK_BCN_RSSI_LOW) { + rssi_tlv =3D (struct nxpwifi_ie_types_rssi_threshold *)pos; + + rssi_tlv->header.type =3D cpu_to_le16(TLV_TYPE_RSSI_LOW); + rssi_tlv->header.len =3D + cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) - + sizeof(struct nxpwifi_ie_types_header)); + rssi_tlv->abs_value =3D subsc_evt_cfg->bcn_l_rssi_cfg.abs_value; + rssi_tlv->evt_freq =3D subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq; + + nxpwifi_dbg(priv->adapter, EVENT, + "Cfg Beacon Low Rssi event,\t" + "RSSI:-%d dBm, Freq:%d\n", + subsc_evt_cfg->bcn_l_rssi_cfg.abs_value, + subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq); + + pos +=3D sizeof(struct nxpwifi_ie_types_rssi_threshold); + le16_unaligned_add_cpu + (&cmd->size, + sizeof(struct nxpwifi_ie_types_rssi_threshold)); + } + + if (event_bitmap & BITMASK_BCN_RSSI_HIGH) { + rssi_tlv =3D (struct nxpwifi_ie_types_rssi_threshold *)pos; + + rssi_tlv->header.type =3D cpu_to_le16(TLV_TYPE_RSSI_HIGH); + rssi_tlv->header.len =3D + cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) - + sizeof(struct nxpwifi_ie_types_header)); + rssi_tlv->abs_value =3D subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; + rssi_tlv->evt_freq =3D subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; + + nxpwifi_dbg(priv->adapter, EVENT, + "Cfg Beacon High Rssi event,\t" + "RSSI:-%d dBm, Freq:%d\n", + subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, + subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); + + pos +=3D sizeof(struct nxpwifi_ie_types_rssi_threshold); + le16_unaligned_add_cpu + (&cmd->size, + sizeof(struct nxpwifi_ie_types_rssi_threshold)); + } + + return 0; +} + +static int +nxpwifi_ret_sta_subsc_evt(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =3D + &resp->params.subsc_evt; + + /* For every subscribe event command (Get/Set/Clear), FW reports the + * current set of subscribed events + */ + nxpwifi_dbg(priv->adapter, EVENT, + "Bitmap of currently subscribed events: %16x\n", + le16_to_cpu(cmd_sub_event->events)); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_tx_rate_query(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_TX_RATE_QUERY); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + + S_DS_GEN); + priv->tx_rate =3D 0; + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_tx_rate_query(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + priv->tx_rate =3D resp->params.tx_rate.tx_rate; + priv->tx_htinfo =3D resp->params.tx_rate.ht_info; + if (!priv->is_data_rate_auto) + priv->data_rate =3D + nxpwifi_index_to_data_rate(priv, priv->tx_rate, + priv->tx_htinfo); + + return 0; +} + +static int +nxpwifi_cmd_sta_mem_access(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_ds_mem_rw *mem_rw =3D + (struct nxpwifi_ds_mem_rw *)data_buf; + struct host_cmd_ds_mem_access *mem_access =3D (void *)&cmd->params.mem; + + cmd->command =3D cpu_to_le16(HOST_CMD_MEM_ACCESS); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) + + S_DS_GEN); + + mem_access->action =3D cpu_to_le16(cmd_action); + mem_access->addr =3D cpu_to_le32(mem_rw->addr); + mem_access->value =3D cpu_to_le32(mem_rw->value); + + return 0; +} + +static int +nxpwifi_ret_sta_mem_access(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_mem_access *mem =3D (void *)&resp->params.mem; + + priv->mem_rw.addr =3D le32_to_cpu(mem->addr); + priv->mem_rw.value =3D le32_to_cpu(mem->value); + + return 0; +} + +static u32 nxpwifi_parse_cal_cfg(u8 *src, size_t len, u8 *dst) +{ + u8 *s =3D src, *d =3D dst; + + while (s - src < len) { + if (*s && (isspace(*s) || *s =3D=3D '\t')) { + s++; + continue; + } + if (isxdigit(*s)) { + if (kstrtou8(s, 16, d)) + return 0; + d++; + s +=3D 2; + } else { + s++; + } + } + + return d - dst; +} + +static int +nxpwifi_cmd_sta_cfg_data(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct property *prop =3D data_buf; + u32 len; + u8 *data =3D (u8 *)cmd + S_DS_GEN; + int ret; + + if (prop) { + len =3D prop->length; + ret =3D of_property_read_u8_array(adapter->dt_node, prop->name, + data, len); + if (ret) + return ret; + nxpwifi_dbg(adapter, INFO, + "download cfg_data from device tree: %s\n", + prop->name); + } else if (adapter->cal_data->data && adapter->cal_data->size > 0) { + len =3D nxpwifi_parse_cal_cfg((u8 *)adapter->cal_data->data, + adapter->cal_data->size, data); + nxpwifi_dbg(adapter, INFO, + "download cfg_data from config file\n"); + } else { + return -1; + } + + cmd->command =3D cpu_to_le16(HOST_CMD_CFG_DATA); + cmd->size =3D cpu_to_le16(S_DS_GEN + len); + + return 0; +} + +static int +nxpwifi_ret_sta_cfg_data(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + if (resp->result !=3D HOST_RESULT_OK) { + nxpwifi_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n"); + return -1; + } + + return 0; +} + +static int +nxpwifi_cmd_sta_ver_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(cmd_no); + cmd->params.verext.version_str_sel =3D + (u8)(get_unaligned((u32 *)data_buf)); + memcpy(&cmd->params, data_buf, sizeof(struct host_cmd_ds_version_ext)); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_ret_sta_ver_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_version_ext *ver_ext =3D &resp->params.verext; + struct host_cmd_ds_version_ext *version_ext =3D + (struct host_cmd_ds_version_ext *)data_buf; + + if (test_and_clear_bit(NXPWIFI_IS_REQUESTING_FW_VEREXT, &priv->adapter->w= ork_flags)) { + if (strncmp(ver_ext->version_str, "ChipRev:20, BB:9b(10.00), RF:40(21)", + NXPWIFI_VERSION_STR_LENGTH) =3D=3D 0) { + struct nxpwifi_ds_auto_ds auto_ds =3D { + .auto_ds =3D DEEP_SLEEP_OFF, + }; + + nxpwifi_dbg(priv->adapter, MSG, + "Bad HW revision detected, disabling deep sleep\n"); + + if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, + DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, false)) { + nxpwifi_dbg(priv->adapter, MSG, + "Disabling deep sleep failed.\n"); + } + } + + return 0; + } + + if (version_ext) { + version_ext->version_str_sel =3D ver_ext->version_str_sel; + memcpy(version_ext->version_str, ver_ext->version_str, + NXPWIFI_VERSION_STR_LENGTH); + memcpy(priv->version_str, ver_ext->version_str, + NXPWIFI_VERSION_STR_LENGTH); + + /* Ensure the version string from the firmware is 0-terminated */ + priv->version_str[NXPWIFI_VERSION_STR_LENGTH - 1] =3D '\0'; + } + return 0; +} + +static int +nxpwifi_cmd_append_rpn_expression(struct nxpwifi_private *priv, + struct nxpwifi_mef_entry *mef_entry, + u8 **buffer) +{ + struct nxpwifi_mef_filter *filter =3D mef_entry->filter; + int i, byte_len; + u8 *stack_ptr =3D *buffer; + + for (i =3D 0; i < NXPWIFI_MEF_MAX_FILTERS; i++) { + filter =3D &mef_entry->filter[i]; + if (!filter->filt_type) + break; + put_unaligned_le32((u32)filter->repeat, stack_ptr); + stack_ptr +=3D 4; + *stack_ptr =3D TYPE_DNUM; + stack_ptr +=3D 1; + + byte_len =3D filter->byte_seq[NXPWIFI_MEF_MAX_BYTESEQ]; + memcpy(stack_ptr, filter->byte_seq, byte_len); + stack_ptr +=3D byte_len; + *stack_ptr =3D byte_len; + stack_ptr +=3D 1; + *stack_ptr =3D TYPE_BYTESEQ; + stack_ptr +=3D 1; + put_unaligned_le32((u32)filter->offset, stack_ptr); + stack_ptr +=3D 4; + *stack_ptr =3D TYPE_DNUM; + stack_ptr +=3D 1; + + *stack_ptr =3D filter->filt_type; + stack_ptr +=3D 1; + + if (filter->filt_action) { + *stack_ptr =3D filter->filt_action; + stack_ptr +=3D 1; + } + + if (stack_ptr - *buffer > STACK_NBYTES) + return -1; + } + + *buffer =3D stack_ptr; + return 0; +} + +static int +nxpwifi_cmd_sta_mef_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_mef_cfg *mef_cfg =3D &cmd->params.mef_cfg; + struct nxpwifi_ds_mef_cfg *mef =3D + (struct nxpwifi_ds_mef_cfg *)data_buf; + struct nxpwifi_fw_mef_entry *mef_entry =3D NULL; + u8 *pos =3D (u8 *)mef_cfg; + u16 i; + + cmd->command =3D cpu_to_le16(HOST_CMD_MEF_CFG); + + mef_cfg->criteria =3D cpu_to_le32(mef->criteria); + mef_cfg->num_entries =3D cpu_to_le16(mef->num_entries); + pos +=3D sizeof(*mef_cfg); + + for (i =3D 0; i < mef->num_entries; i++) { + mef_entry =3D (struct nxpwifi_fw_mef_entry *)pos; + mef_entry->mode =3D mef->mef_entry[i].mode; + mef_entry->action =3D mef->mef_entry[i].action; + pos +=3D sizeof(*mef_entry); + + if (nxpwifi_cmd_append_rpn_expression(priv, + &mef->mef_entry[i], &pos)) + return -1; + + mef_entry->exprsize =3D + cpu_to_le16(pos - mef_entry->expr); + } + cmd->size =3D cpu_to_le16((u16)(pos - (u8 *)mef_cfg) + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_rssi_info(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(HOST_CMD_RSSI_INFO); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + + S_DS_GEN); + cmd->params.rssi_info.action =3D cpu_to_le16(cmd_action); + cmd->params.rssi_info.ndata =3D cpu_to_le16(priv->data_avg_factor); + cmd->params.rssi_info.nbcn =3D cpu_to_le16(priv->bcn_avg_factor); + + /* Reset SNR/NF/RSSI values in private structure */ + priv->data_rssi_last =3D 0; + priv->data_nf_last =3D 0; + priv->data_rssi_avg =3D 0; + priv->data_nf_avg =3D 0; + priv->bcn_rssi_last =3D 0; + priv->bcn_nf_last =3D 0; + priv->bcn_rssi_avg =3D 0; + priv->bcn_nf_avg =3D 0; + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_rssi_info(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =3D + &resp->params.rssi_info_rsp; + struct nxpwifi_ds_misc_subsc_evt *subsc_evt =3D + &priv->async_subsc_evt_storage; + + priv->data_rssi_last =3D le16_to_cpu(rssi_info_rsp->data_rssi_last); + priv->data_nf_last =3D le16_to_cpu(rssi_info_rsp->data_nf_last); + + priv->data_rssi_avg =3D le16_to_cpu(rssi_info_rsp->data_rssi_avg); + priv->data_nf_avg =3D le16_to_cpu(rssi_info_rsp->data_nf_avg); + + priv->bcn_rssi_last =3D le16_to_cpu(rssi_info_rsp->bcn_rssi_last); + priv->bcn_nf_last =3D le16_to_cpu(rssi_info_rsp->bcn_nf_last); + + priv->bcn_rssi_avg =3D le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); + priv->bcn_nf_avg =3D le16_to_cpu(rssi_info_rsp->bcn_nf_avg); + + if (priv->subsc_evt_rssi_state =3D=3D EVENT_HANDLED) + return 0; + + memset(subsc_evt, 0x00, sizeof(struct nxpwifi_ds_misc_subsc_evt)); + + /* Resubscribe low and high rssi events with new thresholds */ + subsc_evt->events =3D BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; + subsc_evt->action =3D HOST_ACT_BITWISE_SET; + if (priv->subsc_evt_rssi_state =3D=3D RSSI_LOW_RECVD) { + subsc_evt->bcn_l_rssi_cfg.abs_value =3D abs(priv->bcn_rssi_avg - + priv->cqm_rssi_hyst); + subsc_evt->bcn_h_rssi_cfg.abs_value =3D abs(priv->cqm_rssi_thold); + } else if (priv->subsc_evt_rssi_state =3D=3D RSSI_HIGH_RECVD) { + subsc_evt->bcn_l_rssi_cfg.abs_value =3D abs(priv->cqm_rssi_thold); + subsc_evt->bcn_h_rssi_cfg.abs_value =3D abs(priv->bcn_rssi_avg + + priv->cqm_rssi_hyst); + } + subsc_evt->bcn_l_rssi_cfg.evt_freq =3D 1; + subsc_evt->bcn_h_rssi_cfg.evt_freq =3D 1; + + priv->subsc_evt_rssi_state =3D EVENT_HANDLED; + + nxpwifi_send_cmd(priv, HOST_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, subsc_evt, false); + + return 0; +} + +static int +nxpwifi_cmd_sta_func_init(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + if (priv->adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_RESET) + priv->adapter->hw_status =3D NXPWIFI_HW_STATUS_READY; + cmd->command =3D cpu_to_le16(cmd_no); + cmd->size =3D cpu_to_le16(S_DS_GEN); + + return 0; +} + +static int +nxpwifi_cmd_sta_func_shutdown(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + priv->adapter->hw_status =3D NXPWIFI_HW_STATUS_RESET; + cmd->command =3D cpu_to_le16(cmd_no); + cmd->size =3D cpu_to_le16(S_DS_GEN); + + return 0; +} + +static int +nxpwifi_cmd_sta_11n_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_11n_cfg(priv, cmd, cmd_action, data_buf); +} + +static int +nxpwifi_cmd_sta_11n_addba_req(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_11n_addba_req(cmd, data_buf); +} + +static int +nxpwifi_ret_sta_11n_addba_req(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + return nxpwifi_ret_11n_addba_req(priv, resp); +} + +static int +nxpwifi_cmd_sta_11n_addba_rsp(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_11n_addba_rsp_gen(priv, cmd, data_buf); +} + +static int +nxpwifi_ret_sta_11n_addba_rsp(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + return nxpwifi_ret_11n_addba_resp(priv, resp); +} + +static int +nxpwifi_cmd_sta_11n_delba(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_11n_delba(cmd, data_buf); +} + +static int +nxpwifi_ret_sta_11n_delba(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + return nxpwifi_ret_11n_delba(priv, resp); +} + +static int +nxpwifi_cmd_sta_tx_power_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_types_power_group *pg_tlv; + struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg =3D &cmd->params.txp_cfg; + struct host_cmd_ds_txpwr_cfg *txp =3D + (struct host_cmd_ds_txpwr_cfg *)data_buf; + + cmd->command =3D cpu_to_le16(HOST_CMD_TXPWR_CFG); + cmd->size =3D + cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); + switch (cmd_action) { + case HOST_ACT_GEN_SET: + if (txp->mode) { + pg_tlv =3D (struct nxpwifi_types_power_group + *)((unsigned long)txp + + sizeof(struct host_cmd_ds_txpwr_cfg)); + memmove(cmd_txp_cfg, txp, + sizeof(struct host_cmd_ds_txpwr_cfg) + + sizeof(struct nxpwifi_types_power_group) + + le16_to_cpu(pg_tlv->length)); + + pg_tlv =3D (struct nxpwifi_types_power_group *)((u8 *) + cmd_txp_cfg + + sizeof(struct host_cmd_ds_txpwr_cfg)); + cmd->size =3D cpu_to_le16(le16_to_cpu(cmd->size) + + sizeof(struct nxpwifi_types_power_group) + + le16_to_cpu(pg_tlv->length)); + } else { + memmove(cmd_txp_cfg, txp, sizeof(*txp)); + } + cmd_txp_cfg->action =3D cpu_to_le16(cmd_action); + break; + case HOST_ACT_GEN_GET: + cmd_txp_cfg->action =3D cpu_to_le16(cmd_action); + break; + } + + return 0; +} + +static int nxpwifi_get_power_level(struct nxpwifi_private *priv, void *dat= a_buf) +{ + int length, max_power =3D -1, min_power =3D -1; + struct nxpwifi_types_power_group *pg_tlv_hdr; + struct nxpwifi_power_group *pg; + + if (!data_buf) + return -1; + + pg_tlv_hdr =3D (struct nxpwifi_types_power_group *)((u8 *)data_buf); + pg =3D (struct nxpwifi_power_group *) + ((u8 *)pg_tlv_hdr + sizeof(struct nxpwifi_types_power_group)); + length =3D le16_to_cpu(pg_tlv_hdr->length); + + /* At least one structure required to update power */ + if (length < sizeof(struct nxpwifi_power_group)) + return 0; + + max_power =3D pg->power_max; + min_power =3D pg->power_min; + length -=3D sizeof(struct nxpwifi_power_group); + + while (length >=3D sizeof(struct nxpwifi_power_group)) { + pg++; + if (max_power < pg->power_max) + max_power =3D pg->power_max; + + if (min_power > pg->power_min) + min_power =3D pg->power_min; + + length -=3D sizeof(struct nxpwifi_power_group); + } + priv->min_tx_power_level =3D (u8)min_power; + priv->max_tx_power_level =3D (u8)max_power; + + return 0; +} + +static int +nxpwifi_ret_sta_tx_power_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_txpwr_cfg *txp_cfg =3D &resp->params.txp_cfg; + struct nxpwifi_types_power_group *pg_tlv_hdr; + struct nxpwifi_power_group *pg; + u16 action =3D le16_to_cpu(txp_cfg->action); + u16 tlv_buf_left; + + pg_tlv_hdr =3D (struct nxpwifi_types_power_group *) + ((u8 *)txp_cfg + + sizeof(struct host_cmd_ds_txpwr_cfg)); + + pg =3D (struct nxpwifi_power_group *) + ((u8 *)pg_tlv_hdr + + sizeof(struct nxpwifi_types_power_group)); + + tlv_buf_left =3D le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg); + if (tlv_buf_left < + le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr)) + return 0; + + switch (action) { + case HOST_ACT_GEN_GET: + if (adapter->hw_status =3D=3D NXPWIFI_HW_STATUS_INITIALIZING) + nxpwifi_get_power_level(priv, pg_tlv_hdr); + + priv->tx_power_level =3D (u16)pg->power_min; + break; + + case HOST_ACT_GEN_SET: + if (!le32_to_cpu(txp_cfg->mode)) + break; + + if (pg->power_max =3D=3D pg->power_min) + priv->tx_power_level =3D (u16)pg->power_min; + break; + default: + nxpwifi_dbg(adapter, ERROR, + "CMD_RESP: unknown cmd action %d\n", + action); + return 0; + } + nxpwifi_dbg(adapter, INFO, + "info: Current TxPower Level =3D %d, Max Power=3D%d, Min Power=3D%d\= n", + priv->tx_power_level, priv->max_tx_power_level, + priv->min_tx_power_level); + + return 0; +} + +static int +nxpwifi_cmd_sta_tx_rate_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_tx_rate_cfg *rate_cfg =3D &cmd->params.tx_rate_cfg; + u16 *pbitmap_rates =3D (u16 *)data_buf; + struct nxpwifi_rate_scope *rate_scope; + struct nxpwifi_rate_drop_pattern *rate_drop; + u32 i; + + cmd->command =3D cpu_to_le16(HOST_CMD_TX_RATE_CFG); + + rate_cfg->action =3D cpu_to_le16(cmd_action); + rate_cfg->cfg_index =3D 0; + + rate_scope =3D (struct nxpwifi_rate_scope *)((u8 *)rate_cfg + + sizeof(struct host_cmd_ds_tx_rate_cfg)); + rate_scope->type =3D cpu_to_le16(TLV_TYPE_RATE_SCOPE); + rate_scope->length =3D cpu_to_le16 + (sizeof(*rate_scope) - sizeof(struct nxpwifi_ie_types_header)); + if (pbitmap_rates) { + rate_scope->hr_dsss_rate_bitmap =3D cpu_to_le16(pbitmap_rates[0]); + rate_scope->ofdm_rate_bitmap =3D cpu_to_le16(pbitmap_rates[1]); + for (i =3D 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) + rate_scope->ht_mcs_rate_bitmap[i] =3D + cpu_to_le16(pbitmap_rates[2 + i]); + if (priv->adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) { + for (i =3D 0; + i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); + i++) + rate_scope->vht_mcs_rate_bitmap[i] =3D + cpu_to_le16(pbitmap_rates[10 + i]); + } + } else { + rate_scope->hr_dsss_rate_bitmap =3D + cpu_to_le16(priv->bitmap_rates[0]); + rate_scope->ofdm_rate_bitmap =3D + cpu_to_le16(priv->bitmap_rates[1]); + for (i =3D 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) + rate_scope->ht_mcs_rate_bitmap[i] =3D + cpu_to_le16(priv->bitmap_rates[2 + i]); + if (priv->adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) { + for (i =3D 0; + i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); + i++) + rate_scope->vht_mcs_rate_bitmap[i] =3D + cpu_to_le16(priv->bitmap_rates[10 + i]); + } + } + + rate_drop =3D (struct nxpwifi_rate_drop_pattern *)((u8 *)rate_scope + + sizeof(struct nxpwifi_rate_scope)); + rate_drop->type =3D cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); + rate_drop->length =3D cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); + rate_drop->rate_drop_mode =3D 0; + + cmd->size =3D + cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + + sizeof(struct nxpwifi_rate_scope) + + sizeof(struct nxpwifi_rate_drop_pattern)); + + return 0; +} + +static void nxpwifi_ret_rate_scope(struct nxpwifi_private *priv, u8 *tlv_b= uf) +{ + struct nxpwifi_rate_scope *rate_scope; + int i; + + rate_scope =3D (struct nxpwifi_rate_scope *)tlv_buf; + priv->bitmap_rates[0] =3D + le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); + priv->bitmap_rates[1] =3D + le16_to_cpu(rate_scope->ofdm_rate_bitmap); + for (i =3D 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) + priv->bitmap_rates[2 + i] =3D + le16_to_cpu(rate_scope->ht_mcs_rate_bitmap[i]); + + if (priv->adapter->fw_api_ver =3D=3D NXPWIFI_FW_V15) { + for (i =3D 0; i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); + i++) + priv->bitmap_rates[10 + i] =3D + le16_to_cpu(rate_scope->vht_mcs_rate_bitmap[i]); + } +} + +static int +nxpwifi_ret_sta_tx_rate_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_tx_rate_cfg *rate_cfg =3D &resp->params.tx_rate_cfg; + struct nxpwifi_ie_types_header *head; + u16 tlv, tlv_buf_len, tlv_buf_left; + u8 *tlv_buf; + + tlv_buf =3D ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg); + tlv_buf_left =3D le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg); + + while (tlv_buf_left >=3D sizeof(*head)) { + head =3D (struct nxpwifi_ie_types_header *)tlv_buf; + tlv =3D le16_to_cpu(head->type); + tlv_buf_len =3D le16_to_cpu(head->len); + + if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) + break; + + switch (tlv) { + case TLV_TYPE_RATE_SCOPE: + nxpwifi_ret_rate_scope(priv, tlv_buf); + break; + /* Add RATE_DROP tlv here */ + } + + tlv_buf +=3D (sizeof(*head) + tlv_buf_len); + tlv_buf_left -=3D (sizeof(*head) + tlv_buf_len); + } + + priv->is_data_rate_auto =3D nxpwifi_is_rate_auto(priv); + + if (priv->is_data_rate_auto) + priv->data_rate =3D 0; + else + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_TX_RATE_QUERY, + HOST_ACT_GEN_GET, 0, NULL, false); + + return 0; +} + +static int +nxpwifi_cmd_sta_reconfigure_rx_buff(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_recfg_tx_buf(priv, cmd, cmd_action, data_buf); +} + +static int +nxpwifi_ret_sta_reconfigure_rx_buff(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (0xffff !=3D (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) { + adapter->tx_buf_size =3D + (u16)le16_to_cpu(resp->params.tx_buf.buff_size); + adapter->tx_buf_size =3D + (adapter->tx_buf_size / NXPWIFI_SDIO_BLOCK_SIZE) * + NXPWIFI_SDIO_BLOCK_SIZE; + adapter->curr_tx_buf_size =3D adapter->tx_buf_size; + nxpwifi_dbg(adapter, CMD, "cmd: curr_tx_buf_size=3D%d\n", + adapter->curr_tx_buf_size); + + if (adapter->if_ops.update_mp_end_port) { + u16 mp_end_port; + + mp_end_port =3D + le16_to_cpu(resp->params.tx_buf.mp_end_port); + adapter->if_ops.update_mp_end_port(adapter, + mp_end_port); + } + } + + return 0; +} + +static int +nxpwifi_cmd_sta_chan_report_request(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_issue_chan_report_request(priv, cmd, data_buf); +} + +static int +nxpwifi_cmf_sta_amsdu_aggr_ctrl(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_amsdu_aggr_ctrl(cmd, cmd_action, data_buf); +} + +static int +nxpwifi_cmd_sta_robust_coex(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_robust_coex *coex =3D &cmd->params.coex; + bool *is_timeshare =3D (bool *)data_buf; + struct nxpwifi_ie_types_robust_coex *coex_tlv; + + cmd->command =3D cpu_to_le16(HOST_CMD_ROBUST_COEX); + cmd->size =3D cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN); + + coex->action =3D cpu_to_le16(cmd_action); + coex_tlv =3D (struct nxpwifi_ie_types_robust_coex *) + ((u8 *)coex + sizeof(*coex)); + coex_tlv->header.type =3D cpu_to_le16(TLV_TYPE_ROBUST_COEX); + coex_tlv->header.len =3D cpu_to_le16(sizeof(coex_tlv->mode)); + + if (coex->action =3D=3D HOST_ACT_GEN_GET) + return 0; + + if (*is_timeshare) + coex_tlv->mode =3D cpu_to_le32(NXPWIFI_COEX_MODE_TIMESHARE); + else + coex_tlv->mode =3D cpu_to_le32(NXPWIFI_COEX_MODE_SPATIAL); + + return 0; +} + +static int +nxpwifi_ret_sta_robust_coex(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_robust_coex *coex =3D &resp->params.coex; + bool *is_timeshare =3D (bool *)data_buf; + struct nxpwifi_ie_types_robust_coex *coex_tlv; + u16 action =3D le16_to_cpu(coex->action); + u32 mode; + + coex_tlv =3D (struct nxpwifi_ie_types_robust_coex + *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex)); + if (action =3D=3D HOST_ACT_GEN_GET) { + mode =3D le32_to_cpu(coex_tlv->mode); + if (mode =3D=3D NXPWIFI_COEX_MODE_TIMESHARE) + *is_timeshare =3D true; + else + *is_timeshare =3D false; + } + + return 0; +} + +static int +nxpwifi_cmd_sta_enh_power_mode(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =3D + &cmd->params.psmode_enh; + u16 ps_bitmap =3D (u16)cmd_type; + struct nxpwifi_ds_auto_ds *auto_ds =3D + (struct nxpwifi_ds_auto_ds *)data_buf; + u8 *tlv; + u16 cmd_size =3D 0; + + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_PS_MODE_ENH); + if (cmd_action =3D=3D DIS_AUTO_PS) { + psmode_enh->action =3D cpu_to_le16(DIS_AUTO_PS); + psmode_enh->params.ps_bitmap =3D cpu_to_le16(ps_bitmap); + cmd->size =3D cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + + sizeof(psmode_enh->params.ps_bitmap)); + } else if (cmd_action =3D=3D GET_PS) { + psmode_enh->action =3D cpu_to_le16(GET_PS); + psmode_enh->params.ps_bitmap =3D cpu_to_le16(ps_bitmap); + cmd->size =3D cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + + sizeof(psmode_enh->params.ps_bitmap)); + } else if (cmd_action =3D=3D EN_AUTO_PS) { + psmode_enh->action =3D cpu_to_le16(EN_AUTO_PS); + psmode_enh->params.ps_bitmap =3D cpu_to_le16(ps_bitmap); + cmd_size =3D S_DS_GEN + sizeof(psmode_enh->action) + + sizeof(psmode_enh->params.ps_bitmap); + tlv =3D (u8 *)cmd + cmd_size; + if (ps_bitmap & BITMAP_STA_PS) { + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ie_types_ps_param *ps_tlv =3D + (struct nxpwifi_ie_types_ps_param *)tlv; + struct nxpwifi_ps_param *ps_mode =3D &ps_tlv->param; + + ps_tlv->header.type =3D cpu_to_le16(TLV_TYPE_PS_PARAM); + ps_tlv->header.len =3D cpu_to_le16(sizeof(*ps_tlv) - + sizeof(struct nxpwifi_ie_types_header)); + cmd_size +=3D sizeof(*ps_tlv); + tlv +=3D sizeof(*ps_tlv); + nxpwifi_dbg(priv->adapter, CMD, + "cmd: PS Command: Enter PS\n"); + ps_mode->null_pkt_interval =3D + cpu_to_le16(adapter->null_pkt_interval); + ps_mode->multiple_dtims =3D + cpu_to_le16(adapter->multiple_dtim); + ps_mode->bcn_miss_timeout =3D + cpu_to_le16(adapter->bcn_miss_time_out); + ps_mode->local_listen_interval =3D + cpu_to_le16(adapter->local_listen_interval); + ps_mode->delay_to_ps =3D + cpu_to_le16(adapter->delay_to_ps); + ps_mode->mode =3D cpu_to_le16(adapter->enhanced_ps_mode); + } + if (ps_bitmap & BITMAP_AUTO_DS) { + struct nxpwifi_ie_types_auto_ds_param *auto_ds_tlv =3D + (struct nxpwifi_ie_types_auto_ds_param *)tlv; + u16 idletime =3D 0; + + auto_ds_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); + auto_ds_tlv->header.len =3D + cpu_to_le16(sizeof(*auto_ds_tlv) - + sizeof(struct nxpwifi_ie_types_header)); + cmd_size +=3D sizeof(*auto_ds_tlv); + tlv +=3D sizeof(*auto_ds_tlv); + if (auto_ds) + idletime =3D auto_ds->idle_time; + nxpwifi_dbg(priv->adapter, CMD, + "cmd: PS Command: Enter Auto Deep Sleep\n"); + auto_ds_tlv->deep_sleep_timeout =3D cpu_to_le16(idletime); + } + cmd->size =3D cpu_to_le16(cmd_size); + } + return 0; +} + +static int +nxpwifi_ret_sta_enh_power_mode(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =3D + &resp->params.psmode_enh; + struct nxpwifi_ds_pm_cfg *pm_cfg =3D + (struct nxpwifi_ds_pm_cfg *)data_buf; + u16 action =3D le16_to_cpu(ps_mode->action); + u16 ps_bitmap =3D le16_to_cpu(ps_mode->params.ps_bitmap); + u16 auto_ps_bitmap =3D + le16_to_cpu(ps_mode->params.ps_bitmap); + + nxpwifi_dbg(adapter, INFO, + "info: %s: PS_MODE cmd reply result=3D%#x action=3D%#X\n", + __func__, resp->result, action); + if (action =3D=3D EN_AUTO_PS) { + if (auto_ps_bitmap & BITMAP_AUTO_DS) { + nxpwifi_dbg(adapter, CMD, + "cmd: Enabled auto deep sleep\n"); + priv->adapter->is_deep_sleep =3D true; + } + if (auto_ps_bitmap & BITMAP_STA_PS) { + nxpwifi_dbg(adapter, CMD, + "cmd: Enabled STA power save\n"); + if (adapter->sleep_period.period) + nxpwifi_dbg(adapter, CMD, + "cmd: set to uapsd/pps mode\n"); + } + } else if (action =3D=3D DIS_AUTO_PS) { + if (ps_bitmap & BITMAP_AUTO_DS) { + priv->adapter->is_deep_sleep =3D false; + nxpwifi_dbg(adapter, CMD, + "cmd: Disabled auto deep sleep\n"); + } + if (ps_bitmap & BITMAP_STA_PS) { + nxpwifi_dbg(adapter, CMD, + "cmd: Disabled STA power save\n"); + if (adapter->sleep_period.period) { + adapter->delay_null_pkt =3D false; + adapter->tx_lock_flag =3D false; + adapter->pps_uapsd_mode =3D false; + } + } + } else if (action =3D=3D GET_PS) { + if (ps_bitmap & BITMAP_STA_PS) + adapter->ps_mode =3D NXPWIFI_802_11_POWER_MODE_PSP; + else + adapter->ps_mode =3D NXPWIFI_802_11_POWER_MODE_CAM; + + nxpwifi_dbg(adapter, CMD, + "cmd: ps_bitmap=3D%#x\n", ps_bitmap); + + if (pm_cfg) { + /* This section is for get power save mode */ + if (ps_bitmap & BITMAP_STA_PS) + pm_cfg->param.ps_mode =3D 1; + else + pm_cfg->param.ps_mode =3D 0; + } + } + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_hs_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg =3D &cmd->params.opt_hs_cfg; + struct nxpwifi_hs_config_param *hscfg_param =3D + (struct nxpwifi_hs_config_param *)data_buf; + u8 *tlv =3D (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh); + struct nxpwifi_ps_param_in_hs *psparam_tlv =3D NULL; + bool hs_activate =3D false; + u16 size; + + if (!hscfg_param) + /* New Activate command */ + hs_activate =3D true; + cmd->command =3D cpu_to_le16(HOST_CMD_802_11_HS_CFG_ENH); + + if (!hs_activate && + hscfg_param->conditions !=3D cpu_to_le32(HS_CFG_CANCEL) && + (adapter->arp_filter_size > 0 && + adapter->arp_filter_size <=3D ARP_FILTER_MAX_BUF_SIZE)) { + nxpwifi_dbg(adapter, CMD, + "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", + adapter->arp_filter_size); + memcpy(((u8 *)hs_cfg) + + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), + adapter->arp_filter, adapter->arp_filter_size); + size =3D adapter->arp_filter_size + + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) + + S_DS_GEN; + tlv =3D (u8 *)hs_cfg + + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) + + adapter->arp_filter_size; + } else { + size =3D S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh); + } + if (hs_activate) { + hs_cfg->action =3D cpu_to_le16(HS_ACTIVATE); + hs_cfg->params.hs_activate.resp_ctrl =3D cpu_to_le16(RESP_NEEDED); + + adapter->hs_activated_manually =3D true; + nxpwifi_dbg(priv->adapter, CMD, + "cmd: Activating host sleep manually\n"); + } else { + hs_cfg->action =3D cpu_to_le16(HS_CONFIGURE); + hs_cfg->params.hs_config.conditions =3D hscfg_param->conditions; + hs_cfg->params.hs_config.gpio =3D hscfg_param->gpio; + hs_cfg->params.hs_config.gap =3D hscfg_param->gap; + + size +=3D sizeof(struct nxpwifi_ps_param_in_hs); + psparam_tlv =3D (struct nxpwifi_ps_param_in_hs *)tlv; + psparam_tlv->header.type =3D + cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS); + psparam_tlv->header.len =3D + cpu_to_le16(sizeof(struct nxpwifi_ps_param_in_hs) + - sizeof(struct nxpwifi_ie_types_header)); + psparam_tlv->hs_wake_int =3D cpu_to_le32(HS_DEF_WAKE_INTERVAL); + psparam_tlv->hs_inact_timeout =3D + cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT); + + nxpwifi_dbg(adapter, CMD, + "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", + hs_cfg->params.hs_config.conditions, + hs_cfg->params.hs_config.gpio, + hs_cfg->params.hs_config.gap); + } + cmd->size =3D cpu_to_le16(size); + + return 0; +} + +static int +nxpwifi_ret_sta_802_11_hs_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + return nxpwifi_ret_802_11_hs_cfg(priv, resp); +} + +static int +nxpwifi_cmd_sta_set_bss_mode(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(cmd_no); + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION) + cmd->params.bss_mode.con_type =3D CONNECTION_TYPE_INFRA; + else if (priv->bss_mode =3D=3D NL80211_IFTYPE_AP) + cmd->params.bss_mode.con_type =3D CONNECTION_TYPE_AP; + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_set_bss_mode) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_cmd_sta_802_11_scan_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_802_11_scan_ext(priv, cmd, data_buf); +} + +static int +nxpwifi_ret_sta_802_11_scan_ext(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + + ret =3D nxpwifi_ret_802_11_scan_ext(priv, resp); + adapter->curr_cmd->wait_q_enabled =3D false; + + return ret; +} + +static int +nxpwifi_cmd_sta_coalesce_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_coalesce_cfg *coalesce_cfg =3D + &cmd->params.coalesce_cfg; + struct nxpwifi_ds_coalesce_cfg *cfg =3D + (struct nxpwifi_ds_coalesce_cfg *)data_buf; + struct coalesce_filt_field_param *param; + u16 cnt, idx, length; + struct coalesce_receive_filt_rule *rule; + + cmd->command =3D cpu_to_le16(HOST_CMD_COALESCE_CFG); + cmd->size =3D cpu_to_le16(S_DS_GEN); + + coalesce_cfg->action =3D cpu_to_le16(cmd_action); + coalesce_cfg->num_of_rules =3D cpu_to_le16(cfg->num_of_rules); + rule =3D (void *)coalesce_cfg->rule_data; + + for (cnt =3D 0; cnt < cfg->num_of_rules; cnt++) { + rule->header.type =3D cpu_to_le16(TLV_TYPE_COALESCE_RULE); + rule->max_coalescing_delay =3D + cpu_to_le16(cfg->rule[cnt].max_coalescing_delay); + rule->pkt_type =3D cfg->rule[cnt].pkt_type; + rule->num_of_fields =3D cfg->rule[cnt].num_of_fields; + + length =3D 0; + + param =3D rule->params; + for (idx =3D 0; idx < cfg->rule[cnt].num_of_fields; idx++) { + param->operation =3D cfg->rule[cnt].params[idx].operation; + param->operand_len =3D + cfg->rule[cnt].params[idx].operand_len; + param->offset =3D + cpu_to_le16(cfg->rule[cnt].params[idx].offset); + memcpy(param->operand_byte_stream, + cfg->rule[cnt].params[idx].operand_byte_stream, + param->operand_len); + + length +=3D sizeof(struct coalesce_filt_field_param); + + param++; + } + + /* Total rule length is sizeof max_coalescing_delay(u16), + * num_of_fields(u8), pkt_type(u8) and total length of the all + * params + */ + rule->header.len =3D cpu_to_le16(length + sizeof(u16) + + sizeof(u8) + sizeof(u8)); + + /* Add the rule length to the command size*/ + le16_unaligned_add_cpu(&cmd->size, + le16_to_cpu(rule->header.len) + + sizeof(struct nxpwifi_ie_types_header)); + + rule =3D (void *)((u8 *)rule->params + length); + } + + /* Add sizeof action, num_of_rules to total command length */ + le16_unaligned_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16)); + + return 0; +} + +static int +nxpwifi_cmd_sta_mgmt_frame_reg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(cmd_no); + cmd->params.reg_mask.action =3D cpu_to_le16(cmd_action); + cmd->params.reg_mask.mask =3D + cpu_to_le32(get_unaligned((u32 *)data_buf)); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_cmd_sta_remain_on_chan(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(cmd_no); + memcpy(&cmd->params, data_buf, + sizeof(struct host_cmd_ds_remain_on_chan)); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_ret_sta_remain_on_chan(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_remain_on_chan *resp_cfg =3D &resp->params.roc_cfg; + struct host_cmd_ds_remain_on_chan *roc_cfg =3D + (struct host_cmd_ds_remain_on_chan *)data_buf; + + if (roc_cfg) + memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg)); + + return 0; +} + +static int +nxpwifi_cmd_sta_gtk_rekey_offload(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_gtk_rekey_params *rekey =3D &cmd->params.rekey; + struct cfg80211_gtk_rekey_data *data =3D + (struct cfg80211_gtk_rekey_data *)data_buf; + u64 rekey_ctr; + + cmd->command =3D cpu_to_le16(HOST_CMD_GTK_REKEY_OFFLOAD_CFG); + cmd->size =3D cpu_to_le16(sizeof(*rekey) + S_DS_GEN); + + rekey->action =3D cpu_to_le16(cmd_action); + if (cmd_action =3D=3D HOST_ACT_GEN_SET) { + memcpy(rekey->kek, data->kek, NL80211_KEK_LEN); + memcpy(rekey->kck, data->kck, NL80211_KCK_LEN); + rekey_ctr =3D be64_to_cpup((__be64 *)data->replay_ctr); + rekey->replay_ctr_low =3D cpu_to_le32((u32)rekey_ctr); + rekey->replay_ctr_high =3D + cpu_to_le32((u32)((u64)rekey_ctr >> 32)); + } + + return 0; +} + +static int +nxpwifi_cmd_sta_11ac_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_11ac_cfg(priv, cmd, cmd_action, data_buf); +} + +static int +nxpwifi_cmd_sta_hs_wakeup_reason(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(HOST_CMD_HS_WAKEUP_REASON); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_ret_sta_hs_wakeup_reason(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_wakeup_reason *wakeup_reason =3D + (struct host_cmd_ds_wakeup_reason *)data_buf; + wakeup_reason->wakeup_reason =3D + resp->params.hs_wakeup_reason.wakeup_reason; + + return 0; +} + +static int +nxpwifi_cmd_sta_mc_policy(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_multi_chan_policy *mc_pol =3D &cmd->params.mc_policy; + const u16 *drcs_info =3D data_buf; + + mc_pol->action =3D cpu_to_le16(cmd_action); + mc_pol->policy =3D cpu_to_le16(*drcs_info); + cmd->command =3D cpu_to_le16(HOST_CMD_MC_POLICY); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) + + S_DS_GEN); + return 0; +} + +static int +nxpwifi_cmd_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =3D + &cmd->params.sdio_rx_aggr_cfg; + + cmd->command =3D cpu_to_le16(HOST_CMD_SDIO_SP_RX_AGGR_CFG); + cmd->size =3D + cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) + + S_DS_GEN); + cfg->action =3D cmd_action; + if (cmd_action =3D=3D HOST_ACT_GEN_SET) + cfg->enable =3D *(u8 *)data_buf; + + return 0; +} + +static int +nxpwifi_ret_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =3D + &resp->params.sdio_rx_aggr_cfg; + + adapter->sdio_rx_aggr_enable =3D cfg->enable; + adapter->sdio_rx_block_size =3D le16_to_cpu(cfg->block_size); + + return 0; +} + +static int +nxpwifi_cmd_sta_get_chan_info(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_sta_configure *sta_cfg_cmd =3D &cmd->params.sta_cfg; + struct host_cmd_tlv_channel_band *tlv_band_channel =3D + (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer; + + cmd->command =3D cpu_to_le16(HOST_CMD_STA_CONFIGURE); + cmd->size =3D cpu_to_le16(sizeof(*sta_cfg_cmd) + + sizeof(*tlv_band_channel) + S_DS_GEN); + sta_cfg_cmd->action =3D cpu_to_le16(cmd_action); + memset(tlv_band_channel, 0, sizeof(*tlv_band_channel)); + tlv_band_channel->header.type =3D cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); + tlv_band_channel->header.len =3D cpu_to_le16(sizeof(*tlv_band_channel) - + sizeof(struct nxpwifi_ie_types_header)); + + return 0; +} + +static int +nxpwifi_ret_sta_get_chan_info(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_sta_configure *sta_cfg_cmd =3D &resp->params.sta_cfg; + struct nxpwifi_channel_band *channel_band =3D + (struct nxpwifi_channel_band *)data_buf; + struct host_cmd_tlv_channel_band *tlv_band_channel; + + tlv_band_channel =3D + (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer; + memcpy(&channel_band->band_config, &tlv_band_channel->band_config, + sizeof(struct nxpwifi_band_config)); + channel_band->channel =3D tlv_band_channel->channel; + + return 0; +} + +static int +nxpwifi_cmd_sta_chan_region_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_chan_region_cfg *reg =3D &cmd->params.reg_cfg; + + cmd->command =3D cpu_to_le16(HOST_CMD_CHAN_REGION_CFG); + cmd->size =3D cpu_to_le16(sizeof(*reg) + S_DS_GEN); + + if (cmd_action =3D=3D HOST_ACT_GEN_GET) + reg->action =3D cpu_to_le16(cmd_action); + + return 0; +} + +static struct ieee80211_regdomain * +nxpwifi_create_custom_regdomain(struct nxpwifi_private *priv, + u8 *buf, u16 buf_len) +{ + u16 num_chan =3D buf_len / 2; + struct ieee80211_regdomain *regd; + struct ieee80211_reg_rule *rule; + bool new_rule; + int idx, freq, prev_freq =3D 0; + u32 bw, prev_bw =3D 0; + u8 chflags, prev_chflags =3D 0, valid_rules =3D 0; + + if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES)) + return ERR_PTR(-EINVAL); + + regd =3D kzalloc(struct_size(regd, reg_rules, num_chan), GFP_KERNEL); + if (!regd) + return ERR_PTR(-ENOMEM); + + for (idx =3D 0; idx < num_chan; idx++) { + u8 chan; + enum nl80211_band band; + + chan =3D *buf++; + if (!chan) { + kfree(regd); + return NULL; + } + chflags =3D *buf++; + band =3D (chan <=3D 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; + freq =3D ieee80211_channel_to_frequency(chan, band); + new_rule =3D false; + + if (chflags & NXPWIFI_CHANNEL_DISABLED) + continue; + + if (band =3D=3D NL80211_BAND_5GHZ) { + if (!(chflags & NXPWIFI_CHANNEL_NOHT80)) + bw =3D MHZ_TO_KHZ(80); + else if (!(chflags & NXPWIFI_CHANNEL_NOHT40)) + bw =3D MHZ_TO_KHZ(40); + else + bw =3D MHZ_TO_KHZ(20); + } else { + if (!(chflags & NXPWIFI_CHANNEL_NOHT40)) + bw =3D MHZ_TO_KHZ(40); + else + bw =3D MHZ_TO_KHZ(20); + } + + if (idx =3D=3D 0 || prev_chflags !=3D chflags || prev_bw !=3D bw || + freq - prev_freq > 20) { + valid_rules++; + new_rule =3D true; + } + + rule =3D ®d->reg_rules[valid_rules - 1]; + + rule->freq_range.end_freq_khz =3D MHZ_TO_KHZ(freq + 10); + + prev_chflags =3D chflags; + prev_freq =3D freq; + prev_bw =3D bw; + + if (!new_rule) + continue; + + rule->freq_range.start_freq_khz =3D MHZ_TO_KHZ(freq - 10); + rule->power_rule.max_eirp =3D DBM_TO_MBM(19); + + if (chflags & NXPWIFI_CHANNEL_PASSIVE) + rule->flags =3D NL80211_RRF_NO_IR; + + if (chflags & NXPWIFI_CHANNEL_DFS) + rule->flags =3D NL80211_RRF_DFS; + + rule->freq_range.max_bandwidth_khz =3D bw; + } + + regd->n_reg_rules =3D valid_rules; + regd->alpha2[0] =3D '9'; + regd->alpha2[1] =3D '9'; + + return regd; +} + +static int +nxpwifi_ret_sta_chan_region_cfg(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_chan_region_cfg *reg =3D &resp->params.reg_cfg; + u16 action =3D le16_to_cpu(reg->action); + u16 tlv, tlv_buf_len, tlv_buf_left; + struct nxpwifi_ie_types_header *head; + struct ieee80211_regdomain *regd; + u8 *tlv_buf; + + if (action !=3D HOST_ACT_GEN_GET) + return 0; + + tlv_buf =3D (u8 *)reg + sizeof(*reg); + tlv_buf_left =3D le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg); + + while (tlv_buf_left >=3D sizeof(*head)) { + head =3D (struct nxpwifi_ie_types_header *)tlv_buf; + tlv =3D le16_to_cpu(head->type); + tlv_buf_len =3D le16_to_cpu(head->len); + + if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) + break; + + switch (tlv) { + case TLV_TYPE_CHAN_ATTR_CFG: + nxpwifi_dbg_dump(priv->adapter, CMD_D, "CHAN:", + (u8 *)head + sizeof(*head), + tlv_buf_len); + regd =3D nxpwifi_create_custom_regdomain(priv, (u8 *)head + + sizeof(*head), + tlv_buf_len); + if (!IS_ERR(regd)) + priv->adapter->regd =3D regd; + break; + } + + tlv_buf +=3D (sizeof(*head) + tlv_buf_len); + tlv_buf_left -=3D (sizeof(*head) + tlv_buf_len); + } + + return 0; +} + +static int +nxpwifi_cmd_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + cmd->command =3D cpu_to_le16(cmd_no); + cmd->params.pkt_aggr_ctrl.action =3D cpu_to_le16(cmd_action); + cmd->params.pkt_aggr_ctrl.enable =3D cpu_to_le16(*(u16 *)data_buf); + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) + + S_DS_GEN); + + return 0; +} + +static int +nxpwifi_ret_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =3D + &resp->params.pkt_aggr_ctrl; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->bus_aggr.enable =3D le16_to_cpu(pkt_aggr_ctrl->enable); + if (adapter->bus_aggr.enable) + adapter->intf_hdr_len =3D INTF_HEADER_LEN; + adapter->bus_aggr.mode =3D NXPWIFI_BUS_AGGR_MODE_LEN_V2; + adapter->bus_aggr.tx_aggr_max_size =3D + le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size); + adapter->bus_aggr.tx_aggr_max_num =3D + le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num); + adapter->bus_aggr.tx_aggr_align =3D + le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align); + + return 0; +} + +static const struct nxpwifi_cmd_entry cmd_table_sta[] =3D { + {.cmd_no =3D HOST_CMD_GET_HW_SPEC, + .prepare_cmd =3D nxpwifi_cmd_sta_get_hw_spec, + .cmd_resp =3D nxpwifi_ret_sta_get_hw_spec}, + {.cmd_no =3D HOST_CMD_802_11_SCAN, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_scan, + .cmd_resp =3D nxpwifi_ret_sta_802_11_scan}, + {.cmd_no =3D HOST_CMD_802_11_GET_LOG, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_get_log, + .cmd_resp =3D nxpwifi_ret_sta_802_11_get_log}, + {.cmd_no =3D HOST_CMD_MAC_MULTICAST_ADR, + .prepare_cmd =3D nxpwifi_cmd_sta_mac_multicast_adr, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_802_11_ASSOCIATE, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_associate, + .cmd_resp =3D nxpwifi_ret_sta_802_11_associate}, + {.cmd_no =3D HOST_CMD_802_11_SNMP_MIB, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_snmp_mib, + .cmd_resp =3D nxpwifi_ret_sta_802_11_snmp_mib}, + {.cmd_no =3D HOST_CMD_MAC_REG_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_reg_access, + .cmd_resp =3D nxpwifi_ret_sta_reg_access}, + {.cmd_no =3D HOST_CMD_BBP_REG_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_reg_access, + .cmd_resp =3D nxpwifi_ret_sta_reg_access}, + {.cmd_no =3D HOST_CMD_RF_REG_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_reg_access, + .cmd_resp =3D nxpwifi_ret_sta_reg_access}, + {.cmd_no =3D HOST_CMD_RF_TX_PWR, + .prepare_cmd =3D nxpwifi_cmd_sta_rf_tx_pwr, + .cmd_resp =3D nxpwifi_ret_sta_rf_tx_pwr}, + {.cmd_no =3D HOST_CMD_RF_ANTENNA, + .prepare_cmd =3D nxpwifi_cmd_sta_rf_antenna, + .cmd_resp =3D nxpwifi_ret_sta_rf_antenna}, + {.cmd_no =3D HOST_CMD_802_11_DEAUTHENTICATE, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_deauthenticate, + .cmd_resp =3D nxpwifi_ret_sta_802_11_deauthenticate}, + {.cmd_no =3D HOST_CMD_MAC_CONTROL, + .prepare_cmd =3D nxpwifi_cmd_sta_mac_control, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_802_11_MAC_ADDRESS, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_mac_address, + .cmd_resp =3D nxpwifi_ret_sta_802_11_mac_address}, + {.cmd_no =3D HOST_CMD_802_11_EEPROM_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_reg_access, + .cmd_resp =3D nxpwifi_ret_sta_reg_access}, + {.cmd_no =3D HOST_CMD_802_11D_DOMAIN_INFO, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11d_domain_info, + .cmd_resp =3D nxpwifi_ret_sta_802_11d_domain_info}, + {.cmd_no =3D HOST_CMD_802_11_KEY_MATERIAL, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_key_material, + .cmd_resp =3D nxpwifi_ret_sta_802_11_key_material}, + {.cmd_no =3D HOST_CMD_802_11_BG_SCAN_CONFIG, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_bg_scan_config, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_802_11_BG_SCAN_QUERY, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_bg_scan_query, + .cmd_resp =3D nxpwifi_ret_sta_802_11_bg_scan_query}, + {.cmd_no =3D HOST_CMD_WMM_GET_STATUS, + .prepare_cmd =3D nxpwifi_cmd_sta_wmm_get_status, + .cmd_resp =3D nxpwifi_ret_sta_wmm_get_status}, + {.cmd_no =3D HOST_CMD_802_11_SUBSCRIBE_EVENT, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_subsc_evt, + .cmd_resp =3D nxpwifi_ret_sta_subsc_evt}, + {.cmd_no =3D HOST_CMD_802_11_TX_RATE_QUERY, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_tx_rate_query, + .cmd_resp =3D nxpwifi_ret_sta_802_11_tx_rate_query}, + {.cmd_no =3D HOST_CMD_MEM_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_mem_access, + .cmd_resp =3D nxpwifi_ret_sta_mem_access}, + {.cmd_no =3D HOST_CMD_CFG_DATA, + .prepare_cmd =3D nxpwifi_cmd_sta_cfg_data, + .cmd_resp =3D nxpwifi_ret_sta_cfg_data}, + {.cmd_no =3D HOST_CMD_VERSION_EXT, + .prepare_cmd =3D nxpwifi_cmd_sta_ver_ext, + .cmd_resp =3D nxpwifi_ret_sta_ver_ext}, + {.cmd_no =3D HOST_CMD_MEF_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_mef_cfg, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_RSSI_INFO, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_rssi_info, + .cmd_resp =3D nxpwifi_ret_sta_802_11_rssi_info}, + {.cmd_no =3D HOST_CMD_FUNC_INIT, + .prepare_cmd =3D nxpwifi_cmd_sta_func_init, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_FUNC_SHUTDOWN, + .prepare_cmd =3D nxpwifi_cmd_sta_func_shutdown, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_PMIC_REG_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_reg_access, + .cmd_resp =3D nxpwifi_ret_sta_reg_access}, + {.cmd_no =3D HOST_CMD_11N_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_11n_cfg, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_11N_ADDBA_REQ, + .prepare_cmd =3D nxpwifi_cmd_sta_11n_addba_req, + .cmd_resp =3D nxpwifi_ret_sta_11n_addba_req}, + {.cmd_no =3D HOST_CMD_11N_ADDBA_RSP, + .prepare_cmd =3D nxpwifi_cmd_sta_11n_addba_rsp, + .cmd_resp =3D nxpwifi_ret_sta_11n_addba_rsp}, + {.cmd_no =3D HOST_CMD_11N_DELBA, + .prepare_cmd =3D nxpwifi_cmd_sta_11n_delba, + .cmd_resp =3D nxpwifi_ret_sta_11n_delba}, + {.cmd_no =3D HOST_CMD_TXPWR_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_tx_power_cfg, + .cmd_resp =3D nxpwifi_ret_sta_tx_power_cfg}, + {.cmd_no =3D HOST_CMD_TX_RATE_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_tx_rate_cfg, + .cmd_resp =3D nxpwifi_ret_sta_tx_rate_cfg}, + {.cmd_no =3D HOST_CMD_RECONFIGURE_TX_BUFF, + .prepare_cmd =3D nxpwifi_cmd_sta_reconfigure_rx_buff, + .cmd_resp =3D nxpwifi_ret_sta_reconfigure_rx_buff}, + {.cmd_no =3D HOST_CMD_CHAN_REPORT_REQUEST, + .prepare_cmd =3D nxpwifi_cmd_sta_chan_report_request, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_AMSDU_AGGR_CTRL, + .prepare_cmd =3D nxpwifi_cmf_sta_amsdu_aggr_ctrl, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_ROBUST_COEX, + .prepare_cmd =3D nxpwifi_cmd_sta_robust_coex, + .cmd_resp =3D nxpwifi_ret_sta_robust_coex}, + {.cmd_no =3D HOST_CMD_802_11_PS_MODE_ENH, + .prepare_cmd =3D nxpwifi_cmd_sta_enh_power_mode, + .cmd_resp =3D nxpwifi_ret_sta_enh_power_mode}, + {.cmd_no =3D HOST_CMD_802_11_HS_CFG_ENH, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_hs_cfg, + .cmd_resp =3D nxpwifi_ret_sta_802_11_hs_cfg}, + {.cmd_no =3D HOST_CMD_CAU_REG_ACCESS, + .prepare_cmd =3D nxpwifi_cmd_sta_reg_access, + .cmd_resp =3D nxpwifi_ret_sta_reg_access}, + {.cmd_no =3D HOST_CMD_SET_BSS_MODE, + .prepare_cmd =3D nxpwifi_cmd_sta_set_bss_mode, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_802_11_SCAN_EXT, + .prepare_cmd =3D nxpwifi_cmd_sta_802_11_scan_ext, + .cmd_resp =3D nxpwifi_ret_sta_802_11_scan_ext}, + {.cmd_no =3D HOST_CMD_COALESCE_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_coalesce_cfg, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_MGMT_FRAME_REG, + .prepare_cmd =3D nxpwifi_cmd_sta_mgmt_frame_reg, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_REMAIN_ON_CHAN, + .prepare_cmd =3D nxpwifi_cmd_sta_remain_on_chan, + .cmd_resp =3D nxpwifi_ret_sta_remain_on_chan}, + {.cmd_no =3D HOST_CMD_GTK_REKEY_OFFLOAD_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_gtk_rekey_offload, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_11AC_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_11ac_cfg, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_HS_WAKEUP_REASON, + .prepare_cmd =3D nxpwifi_cmd_sta_hs_wakeup_reason, + .cmd_resp =3D nxpwifi_ret_sta_hs_wakeup_reason}, + {.cmd_no =3D HOST_CMD_MC_POLICY, + .prepare_cmd =3D nxpwifi_cmd_sta_mc_policy, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_FW_DUMP_EVENT, + .prepare_cmd =3D nxpwifi_cmd_fill_head_only, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_SDIO_SP_RX_AGGR_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_sdio_rx_aggr_cfg, + .cmd_resp =3D nxpwifi_ret_sta_sdio_rx_aggr_cfg}, + {.cmd_no =3D HOST_CMD_STA_CONFIGURE, + .prepare_cmd =3D nxpwifi_cmd_sta_get_chan_info, + .cmd_resp =3D nxpwifi_ret_sta_get_chan_info}, + {.cmd_no =3D HOST_CMD_CHAN_REGION_CFG, + .prepare_cmd =3D nxpwifi_cmd_sta_chan_region_cfg, + .cmd_resp =3D nxpwifi_ret_sta_chan_region_cfg}, + {.cmd_no =3D HOST_CMD_PACKET_AGGR_CTRL, + .prepare_cmd =3D nxpwifi_cmd_sta_pkt_aggr_ctrl, + .cmd_resp =3D nxpwifi_ret_sta_pkt_aggr_ctrl}, +}; + +/* This function prepares the commands before sending them to the firmware. + * + * This is a generic function which calls specific command preparation + * routines based upon the command number. + */ +int nxpwifi_sta_prepare_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node, + u16 cmd_action, u32 cmd_oid) + +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 cmd_no =3D cmd_node->cmd_no; + struct host_cmd_ds_command *cmd =3D + (struct host_cmd_ds_command *)cmd_node->skb->data; + void *data_buf =3D cmd_node->data_buf; + int i, ret =3D -1; + + for (i =3D 0; i < ARRAY_SIZE(cmd_table_sta); i++) { + if (cmd_no =3D=3D cmd_table_sta[i].cmd_no) { + if (cmd_table_sta[i].prepare_cmd) + ret =3D cmd_table_sta[i].prepare_cmd(priv, cmd, + cmd_no, + data_buf, + cmd_action, + cmd_oid); + cmd_node->cmd_resp =3D cmd_table_sta[i].cmd_resp; + break; + } + } + + if (i =3D=3D ARRAY_SIZE(cmd_table_sta)) + nxpwifi_dbg(adapter, ERROR, + "%s: unknown command: %#x\n", + __func__, cmd_no); + else + nxpwifi_dbg(adapter, EVENT, + "%s: command: %#x\n", + __func__, cmd_no); + + return ret; +} + +int nxpwifi_dnld_dt_cfgdata(struct nxpwifi_private *priv, + struct device_node *node, const char *prefix) +{ +#ifdef CONFIG_OF + struct property *prop; + size_t len =3D strlen(prefix); + int ret; + + /* look for all matching property names */ + for_each_property_of_node(node, prop) { + if (len > strlen(prop->name) || + strncmp(prop->name, prefix, len)) + continue; + + /* property header is 6 bytes, data must fit in cmd buffer */ + if (prop->value && prop->length > 6 && + prop->length <=3D NXPWIFI_SIZE_OF_CMD_BUFFER - S_DS_GEN) { + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_CFG_DATA, + HOST_ACT_GEN_SET, 0, + prop, true); + if (ret) + return ret; + } + } +#endif + return 0; +} + +/* This function issues commands to initialize firmware. + * + * This is called after firmware download to bring the card to + * working state. + * Function is also called during reinitialization of virtual + * interfaces. + */ +int nxpwifi_sta_init_cmd(struct nxpwifi_private *priv, u8 first_sta, bool = init) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + struct nxpwifi_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; + struct nxpwifi_ds_auto_ds auto_ds; + enum state_11d_t state_11d; + struct nxpwifi_ds_11n_tx_cfg tx_cfg; + u8 sdio_sp_rx_aggr_enable; + int data; + + if (first_sta) { + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_FUNC_INIT, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) + return -1; + + /* Download calibration data to firmware. + * The cal-data can be read from device tree and/or + * a configuration file and downloaded to firmware. + */ + if (adapter->dt_node) { + if (of_property_read_u32(adapter->dt_node, + "nxp,wakeup-pin", + &data) =3D=3D 0) { + pr_debug("Wakeup pin =3D 0x%x\n", data); + adapter->hs_cfg.gpio =3D data; + } + + nxpwifi_dnld_dt_cfgdata(priv, adapter->dt_node, + "nxp,caldata"); + } + + if (adapter->cal_data) + nxpwifi_send_cmd(priv, HOST_CMD_CFG_DATA, + HOST_ACT_GEN_SET, 0, NULL, true); + + /* Read MAC address from HW */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_GET_HW_SPEC, + HOST_ACT_GEN_GET, 0, NULL, true); + if (ret) + return -1; + + /** Set SDIO Single Port RX Aggr Info */ + if (priv->adapter->iface_type =3D=3D NXPWIFI_SDIO && + ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) && + !priv->adapter->host_disable_sdio_rx_aggr) { + sdio_sp_rx_aggr_enable =3D true; + ret =3D nxpwifi_send_cmd(priv, + HOST_CMD_SDIO_SP_RX_AGGR_CFG, + HOST_ACT_GEN_SET, 0, + &sdio_sp_rx_aggr_enable, + true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "error while enabling SP aggregation..disable it"); + adapter->sdio_rx_aggr_enable =3D false; + } + } + + /* Reconfigure tx buf size */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_RECONFIGURE_TX_BUFF, + HOST_ACT_GEN_SET, 0, + &priv->adapter->tx_buf_size, true); + if (ret) + return -1; + + if (priv->bss_type !=3D NXPWIFI_BSS_TYPE_UAP) { + /* Enable IEEE PS by default */ + priv->adapter->ps_mode =3D NXPWIFI_802_11_POWER_MODE_PSP; + ret =3D nxpwifi_send_cmd(priv, + HOST_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_STA_PS, NULL, + true); + if (ret) + return -1; + } + + nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REGION_CFG, + HOST_ACT_GEN_GET, 0, NULL, true); + } + + /* get tx rate */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_TX_RATE_CFG, + HOST_ACT_GEN_GET, 0, NULL, true); + if (ret) + return -1; + priv->data_rate =3D 0; + + /* get tx power */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_RF_TX_PWR, + HOST_ACT_GEN_GET, 0, NULL, true); + if (ret) + return -1; + + memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); + amsdu_aggr_ctrl.enable =3D true; + /* Send request to firmware */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_AMSDU_AGGR_CTRL, + HOST_ACT_GEN_SET, 0, + &amsdu_aggr_ctrl, true); + if (ret) + return -1; + /* MAC Control must be the last command in init_fw */ + /* set MAC Control */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL, + HOST_ACT_GEN_SET, 0, + &priv->curr_pkt_filter, true); + if (ret) + return -1; + + if (!disable_auto_ds && first_sta && + priv->bss_type !=3D NXPWIFI_BSS_TYPE_UAP) { + /* Enable auto deep sleep */ + auto_ds.auto_ds =3D DEEP_SLEEP_ON; + auto_ds.idle_time =3D DEEP_SLEEP_IDLE_TIME; + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_AUTO_DS, + &auto_ds, true); + if (ret) + return -1; + } + + if (priv->bss_type !=3D NXPWIFI_BSS_TYPE_UAP) { + /* Send cmd to FW to enable/disable 11D function */ + state_11d =3D ENABLE_11D; + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_SET, DOT11D_I, + &state_11d, true); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "11D: failed to enable 11D\n"); + } + + /* Send cmd to FW to configure 11n specific configuration + * (Short GI, Channel BW, Green field support etc.) for transmit + */ + tx_cfg.tx_htcap =3D NXPWIFI_FW_DEF_HTTXCFG; + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_11N_CFG, + HOST_ACT_GEN_SET, 0, &tx_cfg, true); + + if (init) { + /* set last_init_cmd before sending the command */ + priv->adapter->last_init_cmd =3D HOST_CMD_11N_CFG; + ret =3D -EINPROGRESS; + } + + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2059.outbound.protection.outlook.com [40.107.8.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 635C916D9A5; Fri, 21 Jun 2024 07:54:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.59 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956458; cv=fail; b=FiBKJpiBo4PuNvGY9IGWzb3B6KLsGx4OxZIbe44ebVXmlvp6pwgYSeINqRevmFwm1T5fo4hURYQ6YUwFYHufL/3hFK+75fbD6JL0IWOz2OSo5cLGHgaY1V97OKXmbM5mOIi92DJdkZHB6urw+TFE5fopyVUspa99neaJpLKooI8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956458; c=relaxed/simple; bh=JGAlbiRm2yZv6EajNJ1AqCHbb0fI7brbgoFhI5HlOi8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=IuQnyPwnfFqIFbnJUKD2eRugBVj9LPEpFKgB55tFVD8yD6Qdyt9+S1/VvUhxnzMgvHPRgn+lGOWZbc9aMpJwf101RE15XznuRXfD/Jl4Z+LTEqJL8AIL+J4FnCWPlZ7SW6ua3moCZnToq4m99YWVQHD+11VAU1QuyThWgAFFvGE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=E1vsBQ5a; arc=fail smtp.client-ip=40.107.8.59 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="E1vsBQ5a" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WSWnQZKd2CedEI+2yg5T10gcyBVV/krbRPaOmCUeY5APwj8aW0sO616jOir0M6uO11uk9G4TAZ4P2coiYm/FdfYcIOzjTCXU2+AJQYd/9ClxjVF8iT/582tMTuvSGwvm3VQcp64J4FEEMDs/pMFcb0OshdvSXwGEYS4iaYpfbBYUDichhNl9+tEUBuwwQ8CjIlI8Dw6IVaidGSXYq1aDM9fim6D1OSFZtDjo1+1DCr/AW+k8X1MzevHurqXBf5WUlQ2rvwkiNn4boSa1/OdPjNz0/nRyxvAzwiGbBJ9T8dGDToBnghOuB0FCQJ+ori6QqqO1hsSHD4pumo19CbrEMg== 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=2g/7W8XVdfpqs5LDcvH+tMJU10S4PfowQSYUHGzgaWc=; b=Cy36RBKEj5jH8P6HLJB1QKOhjHmRlHfQXKwxB5EkXwdGhHSHTTvCVdArHU2isQeSXhTF10dzrcVlo59s28uETjJUV/H3VwyWj5BynxtAOEh/ha67jQ429fM66OQUyDRURs7bv7ybdFGNOUpAgrVqHDiv6CdiAcOM+VlI6bbBSITBGIi8hAOYm+BZ5d3oBdwvU9Cbx3PWJJoTzFLjBy2qTBuEwQ6Okh1+hjFethIq8kQLubzBn0GPsPc/WeK/PT+zG8ShRzoW0Udi6y70zZkPm0DJnHo5ZRtfwvSgtKbS4RZhfNlucDKBe1hnBnl4AA4l5yOBzA0qYqVdVbxzlQ9veA== 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=2g/7W8XVdfpqs5LDcvH+tMJU10S4PfowQSYUHGzgaWc=; b=E1vsBQ5acmPa3WyYTFsBC8f5lFgGpZVx5Xdgx7+mW7uIFyI6yuJXZp50hlX9/eR8SFAzPu7J2zU5gHjylXpMFkcW8m3mnlZjQqcGub89O1KERVcob4flXwIwhdgHrZMGKmctJKLGbyFdCx4V3n/nYj/KaR5naR32OvKxS56ipxM= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:12 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:12 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 29/43] wifi: nxpwifi: add sta_event.c Date: Fri, 21 Jun 2024 15:51:54 +0800 Message-Id: <20240621075208.513497-30-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: b3390469-2b02-416c-ab00-08dc91c75681 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?tNlu1Jd74UOkcqx1643U0og0c8+97opdTRVetin7E9BgQ/1rqOuqD9j5orUo?= =?us-ascii?Q?F4wu/Nszt7uj9/+ZNsttJePeW9BMUg+WnQu22XlpFHOWsKm8Z+DbCC/JGwNZ?= =?us-ascii?Q?ltMa9upyBIwCyREfnGWa+HCLNG2q4+EhY/B0IJGYV8MCAh8o/OjjCJmuv/9f?= =?us-ascii?Q?IFzKGw21iXQQipE34tPZpM780ODFhw8SYJTAGTAiA4HmwterSIK/h9haBxZX?= =?us-ascii?Q?jjO4mklmTlc/b0KBAL8ZmyM6/hT3bmEJIiwz384gkl4WZXpz+3pn72cEzPXE?= =?us-ascii?Q?Tw8TYYRKtKrAH+N8k+e6Dq8VZ7Z3MkTNBOkzsOsP+GcrjHIvNoofr7/hsmJO?= =?us-ascii?Q?/JZ5WQM1j/bUsYXOGtLBjHUmrRFdVZlVCgSdwe+3WB18jK/29OnoJYYHvnuL?= =?us-ascii?Q?a+9dre8uvsMLAAgHHNEtNEPk5pQrKWNoxftcGqEsRDBhN0AOe+1sd7w7l37J?= =?us-ascii?Q?cyjMNZXC3rKgKuRBVz7kxT4Ou9ilh/UIdvk5CTgpkhYgfHJh8kKu0ujjIDXa?= =?us-ascii?Q?lcY3kgpWBBwAqECTU77nXeR3ACWWb2TOgT8e+FIbNmMcsY39KxkYWvApO6Ov?= =?us-ascii?Q?OLVAepdy9pYzmHeulNmu1A9hK6bIdNGtFTchgVn/ozjEupObflt33yj4o5KK?= =?us-ascii?Q?j/hCGlvNh6oZQaVHMiQGxNi3eE4GCdo7NmdN5DufGOo+Du3CuaIEQF3ypcB5?= =?us-ascii?Q?f4tYh5u7qLM/0CoNgdxzCb8Ou87/4RMVzII7VDWCmvhOEe6jImRVwEDpTHv5?= =?us-ascii?Q?6fGQr4N9iRPyxMDUxN0BU8gKMcw76gEU+5giXxrvBxoHEJLvFx1KfnZLmbY1?= =?us-ascii?Q?1yPYM0gCgsaDurF/X6fi6aap78b/oXPXk9jvNdKWhWXT+heA9oxZ3aMy9mLS?= =?us-ascii?Q?l7JJNKciCzVe14WaHsKxi1iJEsUXpQt8ORTtI0XslmnQM4A0PM+NOr7dUrYo?= =?us-ascii?Q?OSfXK9n0fo8lk7fqN5wFFECiVVsydrE3W2xLVWljpBOj0uvd1ePU9O4X8mwU?= =?us-ascii?Q?ph/X1dgCYKPR4V97V3k6n9WVxxA3MLjAjxODQOfOvZlCLCHFa7Pr8+1GXPCg?= =?us-ascii?Q?rxaROySN/qED/fdLS81mE/Hn7XkU4sIqx8dmW6Tc/sbT99IEQ8mvnGo8OcKU?= =?us-ascii?Q?VSijt3nnHQ9hPov5l5ltg8hPEpBti0atGaKbFKGIFJb6iiwUaUEJZAy3lOq1?= =?us-ascii?Q?dEVU+0vFEKphI54SzRMIsRsO7G1YnlY+FXu24ejSVbRMzaPmtS296gKn7KQL?= =?us-ascii?Q?iUToLPsm7VBn2t5opv5BjWMlJt/AZESKqY/YkdhTZOSxHmMb1VavW/uY+/cW?= =?us-ascii?Q?ZubGzEYKSdkFzGuNNF/qpBC8DbY/hnF8hyqRsG1eo9hHmOXWHSfTcRDXaw7+?= =?us-ascii?Q?o3X10f0=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?9ZaKouJOdN7mrgwkBPSXjXU+Hvl89pGGY9a1ww/9Hf9nlRaI5vlpLWqvrDOw?= =?us-ascii?Q?6wYo7pwOGIA+5m0FRW/CvCv76LDLmSfNlLC7fT5NJIIcQB8dqLEsgqqo0N+d?= =?us-ascii?Q?o97bMRinSmJ+Vhmnw4+BpkAt0QQaGBnhL5Nnth+h+O27XJs08OooffvoG7+4?= =?us-ascii?Q?PbDEOtGyq/ZLm8VSw1MaXFzX2nrU0VPhGuZiYonm6Zc5HUl/YzsOjFEgf+Fq?= =?us-ascii?Q?uBF8ENMG8f17UN/ulihf25GBtmM6Id/WL0tdALLKSHt/Cbklrs2qt3/p8tqY?= =?us-ascii?Q?XNqPNOe55XeGUDIWmDGaq2iZvVWSZ4dbhMTo09y0ShC/6F5Mg4c8Ra0c1r0j?= =?us-ascii?Q?K/SiIYUFU/SzRr9LJ6fT7DVTdpviIL55kXzzJcq4oINoKQ6Hu5mIsuGI9sB/?= =?us-ascii?Q?Lyi5o8fg19gFEkfRx+OlXsdhTRze0yufTf16WB7yqWPPv3g6s18YXEvm++Lp?= =?us-ascii?Q?r30XxHL6wgbjB2Vipb6uV7b2VRPvprMvYRlhffYZoo1Qq7i86mGxpM0y6gmP?= =?us-ascii?Q?vxG9zFmUOkef2UjHYdD5GLrPFnu+SY5W+v5xiwubcRK60Q8+Q7Pu7fKnxBHO?= =?us-ascii?Q?sjYXID1nEPlukctfBsBBtWKt0FfpQH6KhMxl0rSAKIU9AFFLhm0asdgwsxGX?= =?us-ascii?Q?iOzFY/2SPEPLmifiDEr85iiTZIm9A6bmS/hT5emw/IiuW3CLRlGnShZ2/b/U?= =?us-ascii?Q?eo22NOD4Up9JE3VV1juyUqBYaa4oLVnXRvpkz4G2/H/vkZXc+eEPq93h5YB9?= =?us-ascii?Q?y0sG3C6EGl1qlZdreUMX7rU6m3uJELlML2pu7mtlLPoCjhaHXqZ5ys+2aeIZ?= =?us-ascii?Q?kImmJw9b5OTe9dkjTge1IHE0PPE0b1jbvnMMthMocsctpuAlDAc8JSmc1WTN?= =?us-ascii?Q?/esUQsGhoX1B1pUVlYUEjKmJD8IDF02zR+uhHLeLmS1dCN2Li+uOvJuTDIXG?= =?us-ascii?Q?Gk3SNp7LK9DPqFq/dSfjrFaj0imk4paBCB64kWVSbJf/czyNTBTgmweFVoFY?= =?us-ascii?Q?1i/F4Fp++yP+RSZamn2d+I89olUL7ZFMuPJOecghh9E6UU5aJl84+l7IHp+y?= =?us-ascii?Q?KEIpLi8YdrtTlfpxDidTQXzCmJfy7KVeY+GJCVyB/P9TmWFvEZX5wJfl4YIY?= =?us-ascii?Q?Xhjogp+WNUK6Ur5K3XPMesjBRrSdob6qtxsSLk/W2lq96a7+yZnUpYahePph?= =?us-ascii?Q?yYHuJdTkqW7zyR1enBIlirVc9IpGQkYOVmm82j8Ej6+FWRFXwS3zWGdg90zX?= =?us-ascii?Q?0vCrOE1Hea/gjvks3QfIvWNvXT/rw1hKCCuiYnfVfdp+aZ0okAyslBdCcU9p?= =?us-ascii?Q?hpsbQCXrgS6v6qc0oU6Z3zFe+tf8r+QhT6lx0lcH8TPG/kTCX2010cXAWAni?= =?us-ascii?Q?lsBPxtesDdh7X2lItSpWbOo0EsykphKVm8xtJdNW9HXdVKzyTFLltRd4MOQ2?= =?us-ascii?Q?XvCABcvbm0BDfM9PKP44vEFgEM97AK+FBp8KAUQzXW3mNkh0B4PODCqqO8rF?= =?us-ascii?Q?xmRldq8I5Rd7MIfI808xIhqSXGx+BCsgO4kxg0dgD1CPFhSuwW0UBWKFYV6b?= =?us-ascii?Q?uhdvD/jK3+Sy/vUyUzwTyNl2HCod7VmkzjbrZIBH?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: b3390469-2b02-416c-ab00-08dc91c75681 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:11.9488 (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: gQXxlWUGQbYeY6gOfWOVnfgEAhH4By9XvDc2I8bBUDd1kK6aear+hGcU1/FRAoi9J+CvRvQATjZHDSWKqDvPCA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sta_event.c | 858 +++++++++++++++++++ 1 file changed, 858 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sta_event.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_event.c b/drivers/net/wir= eless/nxp/nxpwifi/sta_event.c new file mode 100644 index 000000000000..61daec04665b --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_event.c @@ -0,0 +1,858 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station event handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" + +static int +nxpwifi_sta_event_link_lost(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 reason_code; + + adapter->dbg.num_event_link_lost++; + if (priv->media_connected) { + reason_code =3D get_unaligned_le16(adapter->event_body); + adapter->priv_link_lost =3D priv; + adapter->host_mlme_link_lost =3D true; + queue_work(adapter->host_mlme_workqueue, + &adapter->host_mlme_work); + } + + return 0; +} + +static int +nxpwifi_sta_event_link_sensed(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + nxpwifi_wake_up_net_dev_queue(priv->netdev, adapter); + + return 0; +} + +static int +nxpwifi_sta_event_deauthenticated(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 reason_code; + + if (priv->wps.session_enable) { + nxpwifi_dbg(adapter, INFO, + "info: receive deauth event in wps session\n"); + } else { + adapter->dbg.num_event_deauth++; + if (priv->media_connected) { + reason_code =3D + get_unaligned_le16(adapter->event_body); + nxpwifi_reset_connect_state(priv, reason_code, true); + } + } + + return 0; +} + +static int +nxpwifi_sta_event_disassociated(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 reason_code; + + if (priv->wps.session_enable) { + nxpwifi_dbg(adapter, INFO, + "info: receive disassoc event in wps session\n"); + } else { + adapter->dbg.num_event_disassoc++; + if (priv->media_connected) { + reason_code =3D + get_unaligned_le16(adapter->event_body); + nxpwifi_reset_connect_state(priv, reason_code, true); + } + } + + return 0; +} + +static int +nxpwifi_sta_event_ps_awake(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (!adapter->pps_uapsd_mode && + priv->port_open && + priv->media_connected && adapter->sleep_period.period) { + adapter->pps_uapsd_mode =3D true; + nxpwifi_dbg(adapter, EVENT, + "event: PPS/UAPSD mode activated\n"); + } + adapter->tx_lock_flag =3D false; + if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { + if (nxpwifi_check_last_packet_indication(priv)) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { + adapter->ps_state =3D PS_STATE_AWAKE; + adapter->pm_wakeup_card_req =3D false; + adapter->pm_wakeup_fw_try =3D false; + del_timer(&adapter->wakeup_timer); + } else { + if (!nxpwifi_send_null_packet + (priv, + NXPWIFI_TxPD_POWER_MGMT_NULL_PACKET | + NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET)) + adapter->ps_state =3D PS_STATE_SLEEP; + } + + return 0; + } + } + + adapter->ps_state =3D PS_STATE_AWAKE; + adapter->pm_wakeup_card_req =3D false; + adapter->pm_wakeup_fw_try =3D false; + del_timer(&adapter->wakeup_timer); + + return 0; +} + +static int +nxpwifi_sta_event_ps_sleep(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->ps_state =3D PS_STATE_PRE_SLEEP; + nxpwifi_check_ps_cond(adapter); + + return 0; +} + +static int +nxpwifi_sta_event_mic_err_multicast(struct nxpwifi_private *priv) +{ + cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, + NL80211_KEYTYPE_GROUP, + -1, NULL, GFP_KERNEL); + + return 0; +} + +static int +nxpwifi_sta_event_mic_err_unicast(struct nxpwifi_private *priv) +{ + cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, + NL80211_KEYTYPE_PAIRWISE, + -1, NULL, GFP_KERNEL); + + return 0; +} + +static int +nxpwifi_sta_event_deep_sleep_awake(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->if_ops.wakeup_complete(adapter); + if (adapter->is_deep_sleep) + adapter->is_deep_sleep =3D false; + + return 0; +} + +static int +nxpwifi_sta_event_wmm_status_change(struct nxpwifi_private *priv) +{ + return nxpwifi_send_cmd(priv, HOST_CMD_WMM_GET_STATUS, + 0, 0, NULL, false); +} + +static int +nxpwifi_sta_event_bs_scan_report(struct nxpwifi_private *priv) +{ + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_QUERY, + HOST_ACT_GEN_GET, 0, NULL, false); +} + +static int +nxpwifi_sta_event_rssi_low(struct nxpwifi_private *priv) +{ + cfg80211_cqm_rssi_notify(priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + 0, GFP_KERNEL); + priv->subsc_evt_rssi_state =3D RSSI_LOW_RECVD; + + return nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO, + HOST_ACT_GEN_GET, 0, NULL, false); +} + +static int +nxpwifi_sta_event_rssi_high(struct nxpwifi_private *priv) +{ + cfg80211_cqm_rssi_notify(priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + 0, GFP_KERNEL); + priv->subsc_evt_rssi_state =3D RSSI_HIGH_RECVD; + + return nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO, + HOST_ACT_GEN_GET, 0, NULL, false); +} + +static int +nxpwifi_sta_event_port_release(struct nxpwifi_private *priv) +{ + priv->port_open =3D true; + + return 0; +} + +static int +nxpwifi_sta_event_addba(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_send_cmd(priv, HOST_CMD_11N_ADDBA_RSP, + HOST_ACT_GEN_SET, 0, + adapter->event_body, false); +} + +static int +nxpwifi_sta_event_delba(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_11n_delete_ba_stream(priv, adapter->event_body); + + return 0; +} + +static int +nxpwifi_sta_event_bs_stream_timeout(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_11n_batimeout *event =3D + (struct host_cmd_ds_11n_batimeout *)adapter->event_body; + + nxpwifi_11n_ba_stream_timeout(priv, event); + + return 0; +} + +static int +nxpwifi_sta_event_amsdu_aggr_ctrl(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 ctrl; + + ctrl =3D get_unaligned_le16(adapter->event_body); + adapter->tx_buf_size =3D min_t(u16, adapter->curr_tx_buf_size, ctrl); + + return 0; +} + +static int +nxpwifi_sta_event_hs_act_req(struct nxpwifi_private *priv) +{ + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_HS_CFG_ENH, + 0, 0, NULL, false); +} + +static int +nxpwifi_sta_event_channel_switch_ann(struct nxpwifi_private *priv) +{ + struct nxpwifi_bssdescriptor *bss_desc; + + bss_desc =3D &priv->curr_bss_params.bss_descriptor; + priv->csa_expire_time =3D jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME); + priv->csa_chan =3D bss_desc->channel; + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_DEAUTHENTICATE, + HOST_ACT_GEN_SET, 0, + bss_desc->mac_address, false); +} + +static int +nxpwifi_sta_event_radar_detected(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_11h_handle_radar_detected(priv, adapter->event_skb); +} + +static int +nxpwifi_sta_event_channel_report_rdy(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_11h_handle_chanrpt_ready(priv, adapter->event_skb); +} + +static int +nxpwifi_sta_event_tx_data_pause(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_process_tx_pause_event(priv, adapter->event_skb); + + return 0; +} + +static int +nxpwifi_sta_event_ext_scan_report(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + void *buf =3D adapter->event_skb->data; + int ret =3D 0; + + /* We intend to skip this event during suspend, but handle + * it in interface disabled case + */ + if (adapter->ext_scan && (!priv->scan_aborting || + !netif_running(priv->netdev))) + ret =3D nxpwifi_handle_event_ext_scan_report(priv, buf); + + return ret; +} + +static int +nxpwifi_sta_event_rxba_sync(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_11n_rxba_sync_event(priv, adapter->event_body, + adapter->event_skb->len - + sizeof(adapter->event_cause)); + + return 0; +} + +static int +nxpwifi_sta_event_remain_on_chan_expired(struct nxpwifi_private *priv) +{ + if (priv->auth_flag & HOST_MLME_AUTH_PENDING) { + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + } 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 nxpwifi_roc_cfg)); + + return 0; +} + +static int +nxpwifi_sta_event_bg_scan_stopped(struct nxpwifi_private *priv) +{ + cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0); + if (priv->sched_scanning) + priv->sched_scanning =3D false; + + return 0; +} + +static int +nxpwifi_sta_event_multi_chan_info(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_process_multi_chan_event(priv, adapter->event_skb); + + return 0; +} + +static int +nxpwifi_sta_event_tx_status_report(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_parse_tx_status_event(priv, adapter->event_body); + + return 0; +} + +static int +nxpwifi_sta_event_bt_coex_wlan_para_change(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (!adapter->ignore_btcoex_events) + nxpwifi_bt_coex_wlan_param_update_event(priv, + adapter->event_skb); + + return 0; +} + +static const struct nxpwifi_evt_entry evt_table_sta[] =3D { + {.event_cause =3D EVENT_LINK_LOST, + .event_handler =3D nxpwifi_sta_event_link_lost}, + {.event_cause =3D EVENT_LINK_SENSED, + .event_handler =3D nxpwifi_sta_event_link_sensed}, + {.event_cause =3D EVENT_DEAUTHENTICATED, + .event_handler =3D nxpwifi_sta_event_deauthenticated}, + {.event_cause =3D EVENT_DISASSOCIATED, + .event_handler =3D nxpwifi_sta_event_disassociated}, + {.event_cause =3D EVENT_PS_AWAKE, + .event_handler =3D nxpwifi_sta_event_ps_awake}, + {.event_cause =3D EVENT_PS_SLEEP, + .event_handler =3D nxpwifi_sta_event_ps_sleep}, + {.event_cause =3D EVENT_MIC_ERR_MULTICAST, + .event_handler =3D nxpwifi_sta_event_mic_err_multicast}, + {.event_cause =3D EVENT_MIC_ERR_UNICAST, + .event_handler =3D nxpwifi_sta_event_mic_err_unicast}, + {.event_cause =3D EVENT_DEEP_SLEEP_AWAKE, + .event_handler =3D nxpwifi_sta_event_deep_sleep_awake}, + {.event_cause =3D EVENT_WMM_STATUS_CHANGE, + .event_handler =3D nxpwifi_sta_event_wmm_status_change}, + {.event_cause =3D EVENT_BG_SCAN_REPORT, + .event_handler =3D nxpwifi_sta_event_bs_scan_report}, + {.event_cause =3D EVENT_RSSI_LOW, + .event_handler =3D nxpwifi_sta_event_rssi_low}, + {.event_cause =3D EVENT_RSSI_HIGH, + .event_handler =3D nxpwifi_sta_event_rssi_high}, + {.event_cause =3D EVENT_PORT_RELEASE, + .event_handler =3D nxpwifi_sta_event_port_release}, + {.event_cause =3D EVENT_ADDBA, + .event_handler =3D nxpwifi_sta_event_addba}, + {.event_cause =3D EVENT_DELBA, + .event_handler =3D nxpwifi_sta_event_delba}, + {.event_cause =3D EVENT_BA_STREAM_TIEMOUT, + .event_handler =3D nxpwifi_sta_event_bs_stream_timeout}, + {.event_cause =3D EVENT_AMSDU_AGGR_CTRL, + .event_handler =3D nxpwifi_sta_event_amsdu_aggr_ctrl}, + {.event_cause =3D EVENT_HS_ACT_REQ, + .event_handler =3D nxpwifi_sta_event_hs_act_req}, + {.event_cause =3D EVENT_CHANNEL_SWITCH_ANN, + .event_handler =3D nxpwifi_sta_event_channel_switch_ann}, + {.event_cause =3D EVENT_RADAR_DETECTED, + .event_handler =3D nxpwifi_sta_event_radar_detected}, + {.event_cause =3D EVENT_CHANNEL_REPORT_RDY, + .event_handler =3D nxpwifi_sta_event_channel_report_rdy}, + {.event_cause =3D EVENT_TX_DATA_PAUSE, + .event_handler =3D nxpwifi_sta_event_tx_data_pause}, + {.event_cause =3D EVENT_EXT_SCAN_REPORT, + .event_handler =3D nxpwifi_sta_event_ext_scan_report}, + {.event_cause =3D EVENT_RXBA_SYNC, + .event_handler =3D nxpwifi_sta_event_rxba_sync}, + {.event_cause =3D EVENT_REMAIN_ON_CHAN_EXPIRED, + .event_handler =3D nxpwifi_sta_event_remain_on_chan_expired}, + {.event_cause =3D EVENT_BG_SCAN_STOPPED, + .event_handler =3D nxpwifi_sta_event_bg_scan_stopped}, + {.event_cause =3D EVENT_MULTI_CHAN_INFO, + .event_handler =3D nxpwifi_sta_event_multi_chan_info}, + {.event_cause =3D EVENT_TX_STATUS_REPORT, + .event_handler =3D nxpwifi_sta_event_tx_status_report}, + {.event_cause =3D EVENT_BT_COEX_WLAN_PARA_CHANGE, + .event_handler =3D nxpwifi_sta_event_bt_coex_wlan_para_change}, + {.event_cause =3D EVENT_DUMMY_HOST_WAKEUP_SIGNAL, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_MIB_CHANGED, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_INIT_DONE, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_SNR_LOW, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_MAX_FAIL, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_SNR_HIGH, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_DATA_RSSI_LOW, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_DATA_SNR_LOW, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_DATA_RSSI_HIGH, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_DATA_SNR_HIGH, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_LINK_QUALITY, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_PRE_BEACON_LOST, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_WEP_ICV_ERR, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_BW_CHANGE, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_HOSTWAKE_STAIE, + .event_handler =3D NULL}, + {.event_cause =3D EVENT_UNKNOWN_DEBUG, + .event_handler =3D NULL}, +}; + +static void nxpwifi_process_uap_tx_pause(struct nxpwifi_private *priv, + struct nxpwifi_ie_types_header *tlv) +{ + struct nxpwifi_tx_pause_tlv *tp; + struct nxpwifi_sta_node *sta_ptr; + + tp =3D (void *)tlv; + nxpwifi_dbg(priv->adapter, EVENT, + "uap tx_pause: %pM pause=3D%d, pkts=3D%d\n", + tp->peermac, tp->tx_pause, + tp->pkt_cnt); + + if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) { + if (tp->tx_pause) + priv->port_open =3D false; + else + priv->port_open =3D true; + } else if (is_multicast_ether_addr(tp->peermac)) { + nxpwifi_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause); + } else { + spin_lock_bh(&priv->sta_list_spinlock); + sta_ptr =3D nxpwifi_get_sta_entry(priv, tp->peermac); + if (sta_ptr && sta_ptr->tx_pause !=3D tp->tx_pause) { + sta_ptr->tx_pause =3D tp->tx_pause; + spin_unlock_bh(&priv->sta_list_spinlock); + nxpwifi_update_ralist_tx_pause(priv, tp->peermac, + tp->tx_pause); + } else { + spin_unlock_bh(&priv->sta_list_spinlock); + } + } +} + +static void nxpwifi_process_sta_tx_pause(struct nxpwifi_private *priv, + struct nxpwifi_ie_types_header *tlv) +{ + struct nxpwifi_tx_pause_tlv *tp; + + tp =3D (void *)tlv; + nxpwifi_dbg(priv->adapter, EVENT, + "sta tx_pause: %pM pause=3D%d, pkts=3D%d\n", + tp->peermac, tp->tx_pause, + tp->pkt_cnt); + + if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) { + if (tp->tx_pause) + priv->port_open =3D false; + else + priv->port_open =3D true; + } +} + +/* This function resets the connection state. + * + * The function is invoked after receiving a disconnect event from firmwar= e, + * and performs the following actions - + * - Set media status to disconnected + * - Clean up Tx and Rx packets + * - Resets SNR/NF/RSSI value in driver + * - Resets security configurations in driver + * - Enables auto data rate + * - Saves the previous SSID and BSSID so that they can + * be used for re-association, if required + * - Erases current SSID and BSSID information + * - Sends a disconnect event to upper layers/applications. + */ +void nxpwifi_reset_connect_state(struct nxpwifi_private *priv, u16 reason_= code, + bool from_ap) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (!priv->media_connected) + return; + + nxpwifi_dbg(adapter, INFO, + "info: handles disconnect event\n"); + + priv->media_connected =3D false; + + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + + priv->scan_block =3D false; + priv->port_open =3D false; + + /* Free Tx and Rx packets, report disconnect to upper layer */ + nxpwifi_clean_txrx(priv); + + /* Reset SNR/NF/RSSI values */ + priv->data_rssi_last =3D 0; + priv->data_nf_last =3D 0; + priv->data_rssi_avg =3D 0; + priv->data_nf_avg =3D 0; + priv->bcn_rssi_last =3D 0; + priv->bcn_nf_last =3D 0; + priv->bcn_rssi_avg =3D 0; + priv->bcn_nf_avg =3D 0; + priv->rxpd_rate =3D 0; + priv->rxpd_htinfo =3D 0; + priv->sec_info.wpa_enabled =3D false; + priv->sec_info.wpa2_enabled =3D false; + priv->wpa_ie_len =3D 0; + + priv->sec_info.encryption_mode =3D 0; + + /* Enable auto data rate */ + priv->is_data_rate_auto =3D true; + priv->data_rate =3D 0; + + priv->assoc_resp_ht_param =3D 0; + priv->ht_param_present =3D false; + + if ((GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA || + GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) && priv->hist_data) + nxpwifi_hist_data_reset(priv); + + /* Memorize the previous SSID and BSSID so + * it could be used for re-assoc + */ + + nxpwifi_dbg(adapter, INFO, + "info: previous SSID=3D%s, SSID len=3D%u\n", + priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); + + nxpwifi_dbg(adapter, INFO, + "info: current SSID=3D%s, SSID len=3D%u\n", + priv->curr_bss_params.bss_descriptor.ssid.ssid, + priv->curr_bss_params.bss_descriptor.ssid.ssid_len); + + memcpy(&priv->prev_ssid, + &priv->curr_bss_params.bss_descriptor.ssid, + sizeof(struct cfg80211_ssid)); + + memcpy(priv->prev_bssid, + priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); + + /* Need to erase the current SSID and BSSID info */ + memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); + + adapter->tx_lock_flag =3D false; + adapter->pps_uapsd_mode =3D false; + + if (test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags) && + adapter->curr_cmd) + return; + + priv->media_connected =3D false; + nxpwifi_dbg(adapter, MSG, + "info: successfully disconnected from %pM: reason code %d\n", + priv->cfg_bssid, reason_code); + + if (priv->bss_mode =3D=3D NL80211_IFTYPE_STATION) { + if (adapter->host_mlme_link_lost) + nxpwifi_host_mlme_disconnect(adapter->priv_link_lost, + reason_code, NULL); + else + cfg80211_disconnected(priv->netdev, reason_code, NULL, + 0, !from_ap, GFP_KERNEL); + } + eth_zero_addr(priv->cfg_bssid); + + nxpwifi_stop_net_dev_queue(priv->netdev, adapter); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + + if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info)) + return; + + nxpwifi_send_cmd(priv, HOST_CMD_GTK_REKEY_OFFLOAD_CFG, + HOST_ACT_GEN_REMOVE, 0, NULL, false); +} + +void nxpwifi_process_multi_chan_event(struct nxpwifi_private *priv, + struct sk_buff *event_skb) +{ + struct nxpwifi_ie_types_multi_chan_info *chan_info; + struct nxpwifi_ie_types_mc_group_info *grp_info; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ie_types_header *tlv; + u16 tlv_buf_left, tlv_type, tlv_len; + int intf_num, bss_type, bss_num, i; + struct nxpwifi_private *intf_priv; + + tlv_buf_left =3D event_skb->len - sizeof(u32); + chan_info =3D (void *)event_skb->data + sizeof(u32); + + if (le16_to_cpu(chan_info->header.type) !=3D TLV_TYPE_MULTI_CHAN_INFO || + tlv_buf_left < sizeof(struct nxpwifi_ie_types_multi_chan_info)) { + nxpwifi_dbg(adapter, ERROR, + "unknown TLV in chan_info event\n"); + return; + } + + adapter->usb_mc_status =3D le16_to_cpu(chan_info->status); + nxpwifi_dbg(adapter, EVENT, "multi chan operation %s\n", + adapter->usb_mc_status ? "started" : "over"); + + tlv_buf_left -=3D sizeof(struct nxpwifi_ie_types_multi_chan_info); + tlv =3D (struct nxpwifi_ie_types_header *)chan_info->tlv_buffer; + + while (tlv_buf_left >=3D (int)sizeof(struct nxpwifi_ie_types_header)) { + tlv_type =3D le16_to_cpu(tlv->type); + tlv_len =3D le16_to_cpu(tlv->len); + if ((sizeof(struct nxpwifi_ie_types_header) + tlv_len) > + tlv_buf_left) { + nxpwifi_dbg(adapter, ERROR, "wrong tlv: tlvLen=3D%d,\t" + "tlvBufLeft=3D%d\n", tlv_len, tlv_buf_left); + break; + } + if (tlv_type !=3D TLV_TYPE_MC_GROUP_INFO) { + nxpwifi_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n", + tlv_type); + break; + } + + grp_info =3D (struct nxpwifi_ie_types_mc_group_info *)tlv; + intf_num =3D grp_info->intf_num; + for (i =3D 0; i < intf_num; i++) { + bss_type =3D grp_info->bss_type_numlist[i] >> 4; + bss_num =3D grp_info->bss_type_numlist[i] & BSS_NUM_MASK; + intf_priv =3D nxpwifi_get_priv_by_id(adapter, bss_num, + bss_type); + if (!intf_priv) { + nxpwifi_dbg(adapter, ERROR, + "Invalid bss_type bss_num\t" + "in multi channel event\n"); + continue; + } + } + + tlv_buf_left -=3D sizeof(struct nxpwifi_ie_types_header) + + tlv_len; + tlv =3D (void *)((u8 *)tlv + tlv_len + + sizeof(struct nxpwifi_ie_types_header)); + } +} + +void nxpwifi_process_tx_pause_event(struct nxpwifi_private *priv, + struct sk_buff *event_skb) +{ + struct nxpwifi_ie_types_header *tlv; + u16 tlv_type, tlv_len; + int tlv_buf_left; + + if (!priv->media_connected) { + nxpwifi_dbg(priv->adapter, ERROR, + "tx_pause event while disconnected; bss_role=3D%d\n", + priv->bss_role); + return; + } + + tlv_buf_left =3D event_skb->len - sizeof(u32); + tlv =3D (void *)event_skb->data + sizeof(u32); + + while (tlv_buf_left >=3D (int)sizeof(struct nxpwifi_ie_types_header)) { + tlv_type =3D le16_to_cpu(tlv->type); + tlv_len =3D le16_to_cpu(tlv->len); + if ((sizeof(struct nxpwifi_ie_types_header) + tlv_len) > + tlv_buf_left) { + nxpwifi_dbg(priv->adapter, ERROR, + "wrong tlv: tlvLen=3D%d, tlvBufLeft=3D%d\n", + tlv_len, tlv_buf_left); + break; + } + if (tlv_type =3D=3D TLV_TYPE_TX_PAUSE) { + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) + nxpwifi_process_sta_tx_pause(priv, tlv); + else + nxpwifi_process_uap_tx_pause(priv, tlv); + } + + tlv_buf_left -=3D sizeof(struct nxpwifi_ie_types_header) + + tlv_len; + tlv =3D (void *)((u8 *)tlv + tlv_len + + sizeof(struct nxpwifi_ie_types_header)); + } +} + +/* This function handles coex events generated by firmware */ +void nxpwifi_bt_coex_wlan_param_update_event(struct nxpwifi_private *priv, + struct sk_buff *event_skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_ie_types_header *tlv; + struct nxpwifi_ie_types_btcoex_aggr_win_size *winsizetlv; + struct nxpwifi_ie_types_btcoex_scan_time *scantlv; + s32 len =3D event_skb->len - sizeof(u32); + u8 *cur_ptr =3D event_skb->data + sizeof(u32); + u16 tlv_type, tlv_len; + + while (len >=3D sizeof(struct nxpwifi_ie_types_header)) { + tlv =3D (struct nxpwifi_ie_types_header *)cur_ptr; + tlv_len =3D le16_to_cpu(tlv->len); + tlv_type =3D le16_to_cpu(tlv->type); + + if ((tlv_len + sizeof(struct nxpwifi_ie_types_header)) > len) + break; + switch (tlv_type) { + case TLV_BTCOEX_WL_AGGR_WINSIZE: + winsizetlv =3D + (struct nxpwifi_ie_types_btcoex_aggr_win_size *)tlv; + adapter->coex_win_size =3D winsizetlv->coex_win_size; + adapter->coex_tx_win_size =3D + winsizetlv->tx_win_size; + adapter->coex_rx_win_size =3D + winsizetlv->rx_win_size; + nxpwifi_coex_ampdu_rxwinsize(adapter); + nxpwifi_update_ampdu_txwinsize(adapter); + break; + + case TLV_BTCOEX_WL_SCANTIME: + scantlv =3D + (struct nxpwifi_ie_types_btcoex_scan_time *)tlv; + adapter->coex_scan =3D scantlv->coex_scan; + adapter->coex_min_scan_time =3D le16_to_cpu(scantlv->min_scan_time); + adapter->coex_max_scan_time =3D le16_to_cpu(scantlv->max_scan_time); + break; + + default: + break; + } + + len -=3D tlv_len + sizeof(struct nxpwifi_ie_types_header); + cur_ptr +=3D tlv_len + + sizeof(struct nxpwifi_ie_types_header); + } + + dev_dbg(adapter->dev, "coex_scan=3D%d min_scan=3D%d coex_win=3D%d, tx_win= =3D%d rx_win=3D%d\n", + adapter->coex_scan, adapter->coex_min_scan_time, + adapter->coex_win_size, adapter->coex_tx_win_size, + adapter->coex_rx_win_size); +} + +/* This function handles events generated by firmware. + * + * This is a generic function and handles all events. + * + * Event specific routines are called by this function based + * upon the generated event cause. + */ +int nxpwifi_process_sta_event(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u32 eventcause =3D adapter->event_cause; + int evt, ret =3D 0; + + for (evt =3D 0; evt < ARRAY_SIZE(evt_table_sta); evt++) { + if (eventcause =3D=3D evt_table_sta[evt].event_cause) { + if (evt_table_sta[evt].event_handler) + ret =3D evt_table_sta[evt].event_handler(priv); + break; + } + } + + if (evt =3D=3D ARRAY_SIZE(evt_table_sta)) + nxpwifi_dbg(adapter, EVENT, + "%s: unknown event id: %#x\n", + __func__, eventcause); + else + nxpwifi_dbg(adapter, EVENT, + "%s: event id: %#x\n", + __func__, eventcause); + + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2059.outbound.protection.outlook.com [40.107.8.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B453E175571; Fri, 21 Jun 2024 07:54:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.59 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956462; cv=fail; b=uP5daUIKEBUjfKyej9USjs8QRHG43S8CG78bAhMgRx3BZsjvClNHMQh33QyQVUA86Ox3ABxFKAn2UddDolXhIxI8lJ38GG4434B0IzNJ8T/pR0PDDQ5clelWXmrTyxcMiFhSNYi0J9UHmBNsMruTHNBsbO34a5veGZRkuq0zOno= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956462; c=relaxed/simple; bh=EjSTeUkNyFf0wCiQA2dw60tj3KT+sPGyA9ZZDERSt6g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=PAXM07poGWPC6C17kl7w2J31p+eLSxNHqogKpRNt0Wrj4uoGqN55WFS/OSHkA09lmRnoPler72MiAnJWvBHTymy8otKliQIovHvWDA3mfYbnFaOf/v1T8SgO4NWXx60ASj08c8IblNJA73SnM9q2bOLZQf3RgjInSro4lC71fG8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=d9BYbUAZ; arc=fail smtp.client-ip=40.107.8.59 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="d9BYbUAZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lM9iWPiC0svAxH/I5UnMhhzzPR9iLzkIK/BEtJFKwsA5kZi0g07q/pFThUKG1YD9J0dcFkQ7VRHPBLBuSRKQcYHg9fBMg0IMOvYC6DCXAfwutFIbZ6OSRu42k0BFygykm+R3zVrtUjZn20DAqLyh+/eWTEk+KlRVgrceWndsN+yIxATFPCpROtxAnNuwvWXHN0j8d9oQm0hosngq3tAbpZ19IMm1lKaaDX269vzzeGWhiEiqliSgpBZdNkxDnPRVoKbr6Eh3FBMerpLv6cA8gDHLQBN+fovaQF9hqJh/OK7ZH5KOpltpX48tfjZXQj5rJTdmGFWxbFOhI/0pnD3ecg== 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=kS0y2O3cyfSoZ6ARPgK0RuKjMQ4rxHwStYBYSaKTthk=; b=gfQ+ncwjeWiY3VfM1ITlGEdaCdmOP/73WG88gTZjrgQ4SH3tvZaLygcDgUnskDFxwl7gai1/SsvF4tMybRevYc8ihpUtKiGqW/n0j9OlgNMP+vpIsKAhFCGqGtUIj+IXrVmouDt1nRHq6613WTS4VOSEp6mWwyi5yWV/qs+CWpqaEPtEvY/1tp7LxnHc4iIVR8bkNLHHHP+UpJbquFfgAYlbati8Dx0CpDB8wYteZbOUaNjPEiLL36AeeftF6JXFpLvObyXCk7sal4aqxNs6dVTfaMticD6NzHm4xxFzZwKuC1NlA+T9JJqWqCCsJ0e3LhhELo2VJlYv/gXlZ89uQg== 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=kS0y2O3cyfSoZ6ARPgK0RuKjMQ4rxHwStYBYSaKTthk=; b=d9BYbUAZ33zTxjHCF2elyWVbLjFwNMWSUWFBIFkpMuhNvxugD0uMmVU5xsm08dNkw2lnPxmQiMNnOA8MYmQlAKmNjUVmGAmKKcGq5j6vr8egc7YANmOp1BXIiYqw45c7C0rkjhYW/O9DJOabqtDXzl9yf+lJ8w6+8mbF47+tr4I= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:15 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:15 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 30/43] wifi: nxpwifi: add sta_ioctl.c Date: Fri, 21 Jun 2024 15:51:55 +0800 Message-Id: <20240621075208.513497-31-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: e6a5bc90-aab4-4dab-a8ae-08dc91c75849 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?HgvPq2yUMFR1c0TyGCq50iTaSLN8g6Dsl/1m7DWaFBoVu++2WO6WccWweRT5?= =?us-ascii?Q?OW8vFWTIqJ/42kyTvNSmOAOHUqZdf4DyM9Xn19kX2a9jomlFnMUR52MpTNv0?= =?us-ascii?Q?/t88A6wbm2DJelXIxgCJpRz+87dmttZ2MXP7OS0GygT/Td+3XSx/IGnHwgyV?= =?us-ascii?Q?+DxCNApb+SPTiOU04goxn6zxtBkeSBDAu9mXqb5cr934vgAnC90nEetIsokO?= =?us-ascii?Q?kDimgVLFqq2l1N6biI6NCIYX6ELhNo2SoVjoX0+uEkCHxrrF3g8h0TC7It++?= =?us-ascii?Q?aDxIirRqc0IKXNbxncsOpPkpWnHiUhJhMz48z7uRx1OyHA2pEreOYm4AL6Mm?= =?us-ascii?Q?D8NvRYBDCVo+B4O5B0QPA2IndBRj7niH2WKQ/jqMgbyjzSDBQoA0GqQ7Y8G+?= =?us-ascii?Q?651RG359XwvUprPL7dZ9GU1GGGFeP02jcrHU4d+q+cd2xUF21n5VMixb5hnI?= =?us-ascii?Q?DX9HlxCM0DbMLgHlu/ggxr97gdhZpMJ+SHFcOMrTTg9bKk7hnpxni3jx6PfF?= =?us-ascii?Q?eCsQjiOtgxvs7ac6W00oz0sapdoxD6h312z2HBK/xyQAtf/pn7wcCSRSSqIe?= =?us-ascii?Q?qHcQ3OCYAKYMWNI/363sEyf+47z7xsNE0kra+FuUuEIYHogTWZw27upMUiTr?= =?us-ascii?Q?/W3cWKPaqSjhu3iGEG7FCAHX3WnUZqQvj6hFMm2b26PQgPwqkpKc77f7KlA2?= =?us-ascii?Q?XSdyDHWjYNQdwqHyu8OCpyB3EIcbDEqXfK7coUajUA78BhGxju5K5VTDVUYu?= =?us-ascii?Q?pHj+ADA6z0IdY+18WOEn4Ee1QOmKNV0tkT6l4XJEbwogAOXmQAThiGd46KHq?= =?us-ascii?Q?Z1E2gNE68bO87hnRurW7CjvB+E7ULS9FUgKrbxWOv+9FYCcMTR8eBWLjSYb6?= =?us-ascii?Q?mQNIIjapGuGb/Zau19/JPBmawwQkN26xGwbVRQ+NsHyed9Ehjclwni3FjZfy?= =?us-ascii?Q?z+U8PttEGPbwyLh+BhFYw4gDIB/XCDdUysRyauhRtwqsVRlCMJiBSqKvF4lq?= =?us-ascii?Q?RkEvDnsC6Usq+E8qnKfzgh9O8vN/QWvVn39z9BPVtDFEgnI4qL/UFyR3Jte/?= =?us-ascii?Q?UChwfpcNM3CxP0Ftf9W13T7XzCtjkKn+ZC2wjk7S1b1EL2Vd+pIofLk2UcA/?= =?us-ascii?Q?HYpjpdcsNJT6SZnkzWzeTIkD9i7O43krQWUYFirJvZRhEZkRkbm0oG/utHR5?= =?us-ascii?Q?jFGuP5Ag3JMNcCDaTwN6e7v0ebYtCjRFMgOoGlcGw7KikcIWO5S0CZ+RvSx0?= =?us-ascii?Q?3zPt7tFzdaUoW/i8HRgwmIiluIFGHojIt1cEx0tECWUf/n2Y2dBolQRv+z3B?= =?us-ascii?Q?JJLlJ5bBFLhTb6InkKt/+IpLBrzw/Y521J82ksbNufs9707gzVHAciy0/2Bz?= =?us-ascii?Q?6VEHanI=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?RHdgdEDAo3oCAZQJkfpGMyOPqizgHDX7oSCk41+Fb0YDNSWrqEasu0HugwXP?= =?us-ascii?Q?SontH+zRNt1jUJAzqzinCeMXn8uQ2wUkpdmHGCs9LPPiFYtwC970TdeuHasv?= =?us-ascii?Q?jxhrxYZGKQndLehS70Z58Uv8JCuNF46KHynuix6bQacdiGTayt4E6VT2envl?= =?us-ascii?Q?G0hZaCAmi50TzijhJi4Ox/06aQSECkX+YAaruEKcfo5WjbLQTqQs6ytyxCCl?= =?us-ascii?Q?fND/zEq3khkb86P45malk/8yLE/lZMt8jOQWLVs0W4FFUdoDxcijXzDQ+eXE?= =?us-ascii?Q?JridlL0efNepKEOciXavKSv6js2Es+Nev3ueEb+exjBsEx7zbwQJBFJHIMaR?= =?us-ascii?Q?5nq8rb45rfBL5FhJQXLj2s/ectSYY1Ht1DETFYA/k/ZMoPUF14FTly6PdOHA?= =?us-ascii?Q?xNJhlCenTdNgJrCWIltompuot1/DgWg8lYio96L9b+zkgejRvvlfTG+xLteM?= =?us-ascii?Q?76Ph/5hRdKC5MCDV2Re+EeHcPqJoUcrbEOUzaQME61q605mvf1oOoVk6r74u?= =?us-ascii?Q?gPCYNnHpR0tl272MXEV2QkcIzfpnFbJ8+R2pzidj4RcVf5wk/jZYQq/oV/X4?= =?us-ascii?Q?INl1GxvxoAx84cLn96YXeVJNiSxE8iAl35cxnnjbcPw2ovSyS2VWA2E5NbfK?= =?us-ascii?Q?y1LX3krTUZhicjsMEsDIhG5IwU68w8q2SoZN9swI+GgUfCaZw9DygYzxj5DI?= =?us-ascii?Q?u6cX8TVkpkKBzu+ztoBIz8796ZWdwkklubmWR/mNjyNWWPlnPLVx3WfHOQKK?= =?us-ascii?Q?OF6YglyxOo3mMcvz2DqjeHFKdGx/DdQLJJeNpAoHnFjhvc/ycWM2amgmT80Y?= =?us-ascii?Q?U1B/AX5jv0KMxiaVf+hS5+UEti5kES5u/zmhstatW6KVk+LIp5eFdpzi/kjU?= =?us-ascii?Q?z3XoBTgSNazwQTJ1KncWj/ij55FDK46OFZbnTOK8Ab6Ifq7hlkTwgxPVLHP8?= =?us-ascii?Q?pK+E9NXHXSTcHIcU8WpqFPQ+WSi/BHKYxF/tIDhtWuxGZngflf2HQCgqhBBX?= =?us-ascii?Q?Z251+83Rwp/5gAxmasDuejg6sYUvjPlj7Mozc+n7CMP1rlwYnkg7nAXYfmZo?= =?us-ascii?Q?t6gaKsq4gsSC1rlbKLOPsdPSnf9wC/GSD0FYosr+Z7avpZzXc6ml8wAw6VN6?= =?us-ascii?Q?5UFOFK7n6lPEjDoAz1eXHDOLtTSIZWqUWfNTd+eZVrJl2SsSXFmU64ML/Nfz?= =?us-ascii?Q?zHfJrLXxrOvmu5U7ZVT2rNjWPhDU6Xy/2OMVELpZx3RUux3RUklYyMod3bE6?= =?us-ascii?Q?VXlSD2DCpff/sUTNVryIAE9y6ChuLXglxiY+tAxTuiz1aiBkHa3l0YTxY5EL?= =?us-ascii?Q?xoBKhe7p+4LSTeZ9p9bdpAVChSYdjxE8YZk6pkyLJ0QLqZNZchQm8mnPZXgn?= =?us-ascii?Q?rgT6i1prnSVD1Ms+tNRm7xn/XGvfeiRDop4T2L1OIwclp5FHANOEGaLkSaAw?= =?us-ascii?Q?enA8H00iEbsINC8RY32R/f7/yBH/UYG05mJwQNdZtTRA+sS2L5zV9q1GpwBy?= =?us-ascii?Q?cLD4SNj3iN5TvWXpb3uXAhcaxfIwFO4CzouFUqYHNg7gbsVBKf3MN2oGTNCw?= =?us-ascii?Q?7bLfDeG8PCNzTPcUoAmFvdRZhyfvQ9Rtwp0BtJqH?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: e6a5bc90-aab4-4dab-a8ae-08dc91c75849 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:15.1543 (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: 6aEdVA8EQr2HWMpgz89p9Ceuvt9e8KFLPWOod5RJKYI5YRY7/kjGFo6lTIfUAJWY+1HsuD5FvA0W4BDFcBVFUw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sta_ioctl.c | 1320 ++++++++++++++++++ 1 file changed, 1320 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sta_ioctl.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_ioctl.c b/drivers/net/wir= eless/nxp/nxpwifi/sta_ioctl.c new file mode 100644 index 000000000000..00f4a2c6ac83 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_ioctl.c @@ -0,0 +1,1320 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: functions for station ioctl + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" +#include "cfg80211.h" + +static int disconnect_on_suspend; + +/* Copies the multicast address list from device to driver. + * + * This function does not validate the destination memory for + * size, and the calling function must ensure enough memory is + * available. + */ +int nxpwifi_copy_mcast_addr(struct nxpwifi_multicast_list *mlist, + struct net_device *dev) +{ + int i =3D 0; + struct netdev_hw_addr *ha; + + netdev_for_each_mc_addr(ha, dev) + memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN); + + return i; +} + +/* Wait queue completion handler. + * + * This function waits on a cmd wait queue. It also cancels the pending + * request after waking up, in case of errors. + */ +int nxpwifi_wait_queue_complete(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_queued) +{ + int status; + + /* Wait for completion */ + status =3D wait_event_interruptible_timeout(adapter->cmd_wait_q.wait, + *cmd_queued->condition, + (12 * HZ)); + if (status <=3D 0) { + if (status =3D=3D 0) + status =3D -ETIMEDOUT; + nxpwifi_dbg(adapter, ERROR, "cmd_wait_q terminated: %d\n", + status); + nxpwifi_cancel_all_pending_cmd(adapter); + return status; + } + + status =3D adapter->cmd_wait_q.status; + adapter->cmd_wait_q.status =3D 0; + + return status; +} + +/* This function prepares the correct firmware command and + * issues it to set the multicast list. + * + * This function can be used to enable promiscuous mode, or enable all + * multicast packets, or to enable selective multicast. + */ +int +nxpwifi_request_set_multicast_list(struct nxpwifi_private *priv, + struct nxpwifi_multicast_list *mcast_list) +{ + int ret =3D 0; + u16 old_pkt_filter; + + old_pkt_filter =3D priv->curr_pkt_filter; + + if (mcast_list->mode =3D=3D NXPWIFI_PROMISC_MODE) { + nxpwifi_dbg(priv->adapter, INFO, + "info: Enable Promiscuous mode\n"); + priv->curr_pkt_filter |=3D HOST_ACT_MAC_PROMISCUOUS_ENABLE; + priv->curr_pkt_filter &=3D + ~HOST_ACT_MAC_ALL_MULTICAST_ENABLE; + } else { + /* Multicast */ + priv->curr_pkt_filter &=3D ~HOST_ACT_MAC_PROMISCUOUS_ENABLE; + if (mcast_list->mode =3D=3D NXPWIFI_ALL_MULTI_MODE) { + nxpwifi_dbg(priv->adapter, INFO, + "info: Enabling All Multicast!\n"); + priv->curr_pkt_filter |=3D + HOST_ACT_MAC_ALL_MULTICAST_ENABLE; + } else { + priv->curr_pkt_filter &=3D + ~HOST_ACT_MAC_ALL_MULTICAST_ENABLE; + nxpwifi_dbg(priv->adapter, INFO, + "info: Set multicast list=3D%d\n", + mcast_list->num_multicast_addr); + /* Send multicast addresses to firmware */ + ret =3D nxpwifi_send_cmd(priv, + HOST_CMD_MAC_MULTICAST_ADR, + HOST_ACT_GEN_SET, 0, + mcast_list, false); + } + } + nxpwifi_dbg(priv->adapter, INFO, + "info: old_pkt_filter=3D%#x, curr_pkt_filter=3D%#x\n", + old_pkt_filter, priv->curr_pkt_filter); + if (old_pkt_filter !=3D priv->curr_pkt_filter) { + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL, + HOST_ACT_GEN_SET, + 0, &priv->curr_pkt_filter, false); + } + + return ret; +} + +/* This function fills bss descriptor structure using provided + * information. + * beacon_ie buffer is allocated in this function. It is caller's + * responsibility to free the memory. + */ +int nxpwifi_fill_new_bss_desc(struct nxpwifi_private *priv, + struct cfg80211_bss *bss, + struct nxpwifi_bssdescriptor *bss_desc) +{ + u8 *beacon_ie; + size_t beacon_ie_len; + struct nxpwifi_bss_priv *bss_priv =3D (void *)bss->priv; + const struct cfg80211_bss_ies *ies; + + rcu_read_lock(); + ies =3D rcu_dereference(bss->ies); + beacon_ie =3D kmemdup(ies->data, ies->len, GFP_ATOMIC); + beacon_ie_len =3D ies->len; + bss_desc->timestamp =3D ies->tsf; + rcu_read_unlock(); + + if (!beacon_ie) { + nxpwifi_dbg(priv->adapter, ERROR, + " failed to alloc beacon_ie\n"); + return -ENOMEM; + } + + memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); + bss_desc->rssi =3D bss->signal; + /* The caller of this function will free beacon_ie */ + bss_desc->beacon_buf =3D beacon_ie; + bss_desc->beacon_buf_size =3D beacon_ie_len; + bss_desc->beacon_period =3D bss->beacon_interval; + bss_desc->cap_info_bitmap =3D bss->capability; + bss_desc->bss_band =3D bss_priv->band; + bss_desc->fw_tsf =3D bss_priv->fw_tsf; + if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { + nxpwifi_dbg(priv->adapter, INFO, + "info: InterpretIE: AP WEP enabled\n"); + bss_desc->privacy =3D NXPWIFI_802_11_PRIV_FILTER_8021X_WEP; + } else { + bss_desc->privacy =3D NXPWIFI_802_11_PRIV_FILTER_ACCEPT_ALL; + } + bss_desc->bss_mode =3D NL80211_IFTYPE_STATION; + + /* Disable 11ac by default. Enable it only where there + * exist VHT_CAP IE in AP beacon + */ + bss_desc->disable_11ac =3D true; + + if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT) + bss_desc->sensed_11h =3D true; + + return nxpwifi_update_bss_desc_with_ie(priv->adapter, bss_desc); +} + +void nxpwifi_dnld_txpwr_table(struct nxpwifi_private *priv) +{ + if (priv->adapter->dt_node) { + char txpwr[] =3D {"nxp,00_txpwrlimit"}; + + memcpy(&txpwr[8], priv->adapter->country_code, 2); + nxpwifi_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); + } +} + +static int nxpwifi_process_country_ie(struct nxpwifi_private *priv, + struct cfg80211_bss *bss) +{ + const u8 *country_ie; + u8 country_ie_len; + struct nxpwifi_802_11d_domain_reg *domain_info =3D + &priv->adapter->domain_reg; + + rcu_read_lock(); + country_ie =3D ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); + if (!country_ie) { + rcu_read_unlock(); + return 0; + } + + country_ie_len =3D country_ie[1]; + if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) { + rcu_read_unlock(); + return 0; + } + + if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { + rcu_read_unlock(); + nxpwifi_dbg(priv->adapter, INFO, + "11D: skip setting domain info in FW\n"); + return 0; + } + + if (country_ie_len > + (IEEE80211_COUNTRY_STRING_LEN + NXPWIFI_MAX_TRIPLET_802_11D)) { + rcu_read_unlock(); + nxpwifi_dbg(priv->adapter, ERROR, + "11D: country_ie_len overflow!, deauth AP\n"); + return -EINVAL; + } + + memcpy(priv->adapter->country_code, &country_ie[2], 2); + + domain_info->country_code[0] =3D country_ie[2]; + domain_info->country_code[1] =3D country_ie[3]; + domain_info->country_code[2] =3D ' '; + + country_ie_len -=3D IEEE80211_COUNTRY_STRING_LEN; + + domain_info->no_of_triplet =3D + country_ie_len / sizeof(struct ieee80211_country_ie_triplet); + + memcpy((u8 *)domain_info->triplet, + &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); + + rcu_read_unlock(); + + if (nxpwifi_send_cmd(priv, HOST_CMD_802_11D_DOMAIN_INFO, + HOST_ACT_GEN_SET, 0, NULL, false)) { + nxpwifi_dbg(priv->adapter, ERROR, + "11D: setting domain info in FW fail\n"); + return -1; + } + + nxpwifi_dnld_txpwr_table(priv); + + return 0; +} + +/* In infra mode, an deauthentication is performed + * first. + */ +int nxpwifi_bss_start(struct nxpwifi_private *priv, struct cfg80211_bss *b= ss, + struct cfg80211_ssid *req_ssid) +{ + int ret; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_bssdescriptor *bss_desc =3D NULL; + u8 config_bands; + + priv->scan_block =3D false; + + if (adapter->region_code =3D=3D 0x00 && + nxpwifi_process_country_ie(priv, bss)) + return -EINVAL; + + /* Allocate and fill new bss descriptor */ + bss_desc =3D kzalloc(sizeof(*bss_desc), GFP_KERNEL); + if (!bss_desc) + return -ENOMEM; + + ret =3D nxpwifi_fill_new_bss_desc(priv, bss, bss_desc); + if (ret) + goto done; + + if (nxpwifi_band_to_radio_type(bss_desc->bss_band) =3D=3D + HOST_SCAN_RADIO_TYPE_BG) { + config_bands =3D BAND_B | BAND_G | BAND_GN; + } else { + config_bands =3D BAND_A | BAND_AN; + if (adapter->fw_bands & BAND_AAC) + config_bands |=3D BAND_AAC; + } + + if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) + adapter->config_bands =3D config_bands; + + ret =3D nxpwifi_check_network_compatibility(priv, bss_desc); + if (ret) + goto done; + + if (nxpwifi_11h_get_csa_closed_channel(priv) =3D=3D (u8)bss_desc->channel= ) { + nxpwifi_dbg(adapter, ERROR, + "Attempt to reconnect on csa closed chan(%d)\n", + bss_desc->channel); + ret =3D -1; + goto done; + } + + nxpwifi_stop_net_dev_queue(priv->netdev, adapter); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + + /* Clear any past association response stored for + * application retrieval + */ + priv->assoc_rsp_size =3D 0; + ret =3D nxpwifi_associate(priv, bss_desc); + + /* If auth type is auto and association fails using open mode, + * try to connect using shared mode + */ + if (ret =3D=3D WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG && + priv->sec_info.is_authtype_auto && + priv->sec_info.wep_enabled) { + priv->sec_info.authentication_mode =3D + NL80211_AUTHTYPE_SHARED_KEY; + ret =3D nxpwifi_associate(priv, bss_desc); + } + +done: + /* beacon_ie buffer was allocated in function + * nxpwifi_fill_new_bss_desc(). Free it now. + */ + if (bss_desc) + kfree(bss_desc->beacon_buf); + kfree(bss_desc); + + if (ret < 0) + priv->attempted_bss_desc =3D NULL; + + return ret; +} + +/* IOCTL request handler to set host sleep configuration. + * + * This function prepares the correct firmware command and + * issues it. + */ +int nxpwifi_set_hs_params(struct nxpwifi_private *priv, u16 action, + int cmd_type, struct nxpwifi_ds_hs_cfg *hs_cfg) + +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int status =3D 0; + u32 prev_cond =3D 0; + + if (!hs_cfg) + return -ENOMEM; + + switch (action) { + case HOST_ACT_GEN_SET: + if (adapter->pps_uapsd_mode) { + nxpwifi_dbg(adapter, INFO, + "info: Host Sleep IOCTL\t" + "is blocked in UAPSD/PPS mode\n"); + status =3D -1; + break; + } + if (hs_cfg->is_invoke_hostcmd) { + if (hs_cfg->conditions =3D=3D HS_CFG_CANCEL) { + if (!test_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags)) + /* Already cancelled */ + break; + /* Save previous condition */ + prev_cond =3D le32_to_cpu(adapter->hs_cfg + .conditions); + adapter->hs_cfg.conditions =3D + cpu_to_le32(hs_cfg->conditions); + } else if (hs_cfg->conditions) { + adapter->hs_cfg.conditions =3D + cpu_to_le32(hs_cfg->conditions); + adapter->hs_cfg.gpio =3D (u8)hs_cfg->gpio; + if (hs_cfg->gap) + adapter->hs_cfg.gap =3D (u8)hs_cfg->gap; + } else if (adapter->hs_cfg.conditions =3D=3D + cpu_to_le32(HS_CFG_CANCEL)) { + /* Return failure if no parameters for HS + * enable + */ + status =3D -1; + break; + } + + status =3D nxpwifi_send_cmd(priv, + HOST_CMD_802_11_HS_CFG_ENH, + HOST_ACT_GEN_SET, 0, + &adapter->hs_cfg, + cmd_type =3D=3D NXPWIFI_SYNC_CMD); + + if (hs_cfg->conditions =3D=3D HS_CFG_CANCEL) + /* Restore previous condition */ + adapter->hs_cfg.conditions =3D + cpu_to_le32(prev_cond); + } else { + adapter->hs_cfg.conditions =3D + cpu_to_le32(hs_cfg->conditions); + adapter->hs_cfg.gpio =3D (u8)hs_cfg->gpio; + adapter->hs_cfg.gap =3D (u8)hs_cfg->gap; + } + break; + case HOST_ACT_GEN_GET: + hs_cfg->conditions =3D le32_to_cpu(adapter->hs_cfg.conditions); + hs_cfg->gpio =3D adapter->hs_cfg.gpio; + hs_cfg->gap =3D adapter->hs_cfg.gap; + break; + default: + status =3D -1; + break; + } + + return status; +} + +/* Sends IOCTL request to cancel the existing Host Sleep configuration. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int nxpwifi_cancel_hs(struct nxpwifi_private *priv, int cmd_type) +{ + struct nxpwifi_ds_hs_cfg hscfg; + + hscfg.conditions =3D HS_CFG_CANCEL; + hscfg.is_invoke_hostcmd =3D true; + + return nxpwifi_set_hs_params(priv, HOST_ACT_GEN_SET, + cmd_type, &hscfg); +} +EXPORT_SYMBOL_GPL(nxpwifi_cancel_hs); + +/* Sends IOCTL request to cancel the existing Host Sleep configuration. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int nxpwifi_enable_hs(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_ds_hs_cfg hscfg; + struct nxpwifi_private *priv; + int i; + + if (disconnect_on_suspend) { + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (priv) + nxpwifi_deauthenticate(priv, NULL); + } + } + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA); + + if (priv && priv->sched_scanning) { +#ifdef CONFIG_PM + if (priv->wdev.wiphy->wowlan_config && + !priv->wdev.wiphy->wowlan_config->nd_config) { +#endif + nxpwifi_dbg(adapter, CMD, "aborting bgscan!\n"); + nxpwifi_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0); +#ifdef CONFIG_PM + } +#endif + } + + if (adapter->hs_activated) { + nxpwifi_dbg(adapter, CMD, + "cmd: HS Already activated\n"); + return true; + } + + adapter->hs_activate_wait_q_woken =3D false; + + memset(&hscfg, 0, sizeof(hscfg)); + hscfg.is_invoke_hostcmd =3D true; + + set_bit(NXPWIFI_IS_HS_ENABLING, &adapter->work_flags); + nxpwifi_cancel_all_pending_cmd(adapter); + + if (nxpwifi_set_hs_params(nxpwifi_get_priv(adapter, + NXPWIFI_BSS_ROLE_STA), + HOST_ACT_GEN_SET, NXPWIFI_SYNC_CMD, + &hscfg)) { + nxpwifi_dbg(adapter, ERROR, + "IOCTL request HS enable failed\n"); + return false; + } + + if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken, + (10 * HZ)) <=3D 0) { + nxpwifi_dbg(adapter, ERROR, + "hs_activate_wait_q terminated\n"); + return false; + } + + return true; +} +EXPORT_SYMBOL_GPL(nxpwifi_enable_hs); + +/* IOCTL request handler to get BSS information. + * + * This function collates the information from different driver structures + * to send to the user. + */ +int nxpwifi_get_bss_info(struct nxpwifi_private *priv, + struct nxpwifi_bss_info *info) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_bssdescriptor *bss_desc; + + if (!info) + return -1; + + bss_desc =3D &priv->curr_bss_params.bss_descriptor; + + info->bss_mode =3D priv->bss_mode; + + memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid)); + + memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); + + info->bss_chan =3D bss_desc->channel; + + memcpy(info->country_code, adapter->country_code, + IEEE80211_COUNTRY_STRING_LEN); + + info->media_connected =3D priv->media_connected; + + info->max_power_level =3D priv->max_tx_power_level; + info->min_power_level =3D priv->min_tx_power_level; + + info->bcn_nf_last =3D priv->bcn_nf_last; + + if (priv->sec_info.wep_enabled) + info->wep_status =3D true; + else + info->wep_status =3D false; + + info->is_hs_configured =3D test_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags); + info->is_deep_sleep =3D adapter->is_deep_sleep; + + return 0; +} + +/* The function disables auto deep sleep mode. + */ +int nxpwifi_disable_auto_ds(struct nxpwifi_private *priv) +{ + struct nxpwifi_ds_auto_ds auto_ds =3D { + .auto_ds =3D DEEP_SLEEP_OFF, + }; + + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, + DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, true); +} +EXPORT_SYMBOL_GPL(nxpwifi_disable_auto_ds); + +/* Sends IOCTL request to get the data rate. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int nxpwifi_drv_get_data_rate(struct nxpwifi_private *priv, u32 *rate) +{ + int ret; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_TX_RATE_QUERY, + HOST_ACT_GEN_GET, 0, NULL, true); + + if (!ret) { + if (priv->is_data_rate_auto) + *rate =3D nxpwifi_index_to_data_rate(priv, priv->tx_rate, + priv->tx_htinfo); + else + *rate =3D priv->data_rate; + } + + return ret; +} + +/* IOCTL request handler to set tx power configuration. + * + * This function prepares the correct firmware command and + * issues it. + * + * For non-auto power mode, all the following power groups are set - + * - Modulation class HR/DSSS + * - Modulation class OFDM + * - Modulation class HTBW20 + * - Modulation class HTBW40 + */ +int nxpwifi_set_tx_power(struct nxpwifi_private *priv, + struct nxpwifi_power_cfg *power_cfg) +{ + int ret; + struct host_cmd_ds_txpwr_cfg *txp_cfg; + struct nxpwifi_types_power_group *pg_tlv; + struct nxpwifi_power_group *pg; + u8 *buf; + u16 dbm =3D 0; + + if (!power_cfg->is_power_auto) { + dbm =3D (u16)power_cfg->power_level; + if (dbm < priv->min_tx_power_level || + dbm > priv->max_tx_power_level) { + nxpwifi_dbg(priv->adapter, ERROR, + "txpower value %d dBm\t" + "is out of range (%d dBm-%d dBm)\n", + dbm, priv->min_tx_power_level, + priv->max_tx_power_level); + return -1; + } + } + buf =3D kzalloc(NXPWIFI_SIZE_OF_CMD_BUFFER, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + txp_cfg =3D (struct host_cmd_ds_txpwr_cfg *)buf; + txp_cfg->action =3D cpu_to_le16(HOST_ACT_GEN_SET); + if (!power_cfg->is_power_auto) { + u16 dbm_min =3D power_cfg->is_power_fixed ? + dbm : priv->min_tx_power_level; + + txp_cfg->mode =3D cpu_to_le32(1); + pg_tlv =3D (struct nxpwifi_types_power_group *) + (buf + sizeof(struct host_cmd_ds_txpwr_cfg)); + pg_tlv->type =3D cpu_to_le16(TLV_TYPE_POWER_GROUP); + pg_tlv->length =3D + cpu_to_le16(4 * sizeof(struct nxpwifi_power_group)); + pg =3D (struct nxpwifi_power_group *) + (buf + sizeof(struct host_cmd_ds_txpwr_cfg) + + sizeof(struct nxpwifi_types_power_group)); + /* Power group for modulation class HR/DSSS */ + pg->first_rate_code =3D 0x00; + pg->last_rate_code =3D 0x03; + pg->modulation_class =3D MOD_CLASS_HR_DSSS; + pg->power_step =3D 0; + pg->power_min =3D (s8)dbm_min; + pg->power_max =3D (s8)dbm; + pg++; + /* Power group for modulation class OFDM */ + pg->first_rate_code =3D 0x00; + pg->last_rate_code =3D 0x07; + pg->modulation_class =3D MOD_CLASS_OFDM; + pg->power_step =3D 0; + pg->power_min =3D (s8)dbm_min; + pg->power_max =3D (s8)dbm; + pg++; + /* Power group for modulation class HTBW20 */ + pg->first_rate_code =3D 0x00; + pg->last_rate_code =3D 0x20; + pg->modulation_class =3D MOD_CLASS_HT; + pg->power_step =3D 0; + pg->power_min =3D (s8)dbm_min; + pg->power_max =3D (s8)dbm; + pg->ht_bandwidth =3D HT_BW_20; + pg++; + /* Power group for modulation class HTBW40 */ + pg->first_rate_code =3D 0x00; + pg->last_rate_code =3D 0x20; + pg->modulation_class =3D MOD_CLASS_HT; + pg->power_step =3D 0; + pg->power_min =3D (s8)dbm_min; + pg->power_max =3D (s8)dbm; + pg->ht_bandwidth =3D HT_BW_40; + } + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_TXPWR_CFG, + HOST_ACT_GEN_SET, 0, buf, true); + + kfree(buf); + return ret; +} + +/* IOCTL request handler to get power save mode. + * + * This function prepares the correct firmware command and + * issues it. + */ +int nxpwifi_drv_set_power(struct nxpwifi_private *priv, u32 *ps_mode) +{ + int ret; + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 sub_cmd; + + if (*ps_mode) + adapter->ps_mode =3D NXPWIFI_802_11_POWER_MODE_PSP; + else + adapter->ps_mode =3D NXPWIFI_802_11_POWER_MODE_CAM; + sub_cmd =3D (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, + sub_cmd, BITMAP_STA_PS, NULL, true); + if (!ret && sub_cmd =3D=3D DIS_AUTO_PS) + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, + GET_PS, 0, NULL, false); + + return ret; +} + +/* IOCTL request handler to set/reset WPA IE. + * + * The supplied WPA IE is treated as a opaque buffer. Only the first field + * is checked to determine WPA version. If buffer length is zero, the exis= ting + * WPA IE is reset. + */ +static int nxpwifi_set_wpa_ie(struct nxpwifi_private *priv, + u8 *ie_data_ptr, u16 ie_len) +{ + if (ie_len) { + if (ie_len > sizeof(priv->wpa_ie)) { + nxpwifi_dbg(priv->adapter, ERROR, + "failed to copy WPA IE, too big\n"); + return -1; + } + memcpy(priv->wpa_ie, ie_data_ptr, ie_len); + priv->wpa_ie_len =3D ie_len; + nxpwifi_dbg(priv->adapter, CMD, + "cmd: Set Wpa_ie_len=3D%d IE=3D%#x\n", + priv->wpa_ie_len, priv->wpa_ie[0]); + + if (priv->wpa_ie[0] =3D=3D WLAN_EID_VENDOR_SPECIFIC) { + priv->sec_info.wpa_enabled =3D true; + } else if (priv->wpa_ie[0] =3D=3D WLAN_EID_RSN) { + priv->sec_info.wpa2_enabled =3D true; + } else { + priv->sec_info.wpa_enabled =3D false; + priv->sec_info.wpa2_enabled =3D false; + } + } else { + memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie)); + priv->wpa_ie_len =3D 0; + nxpwifi_dbg(priv->adapter, INFO, + "info: reset wpa_ie_len=3D%d IE=3D%#x\n", + priv->wpa_ie_len, priv->wpa_ie[0]); + priv->sec_info.wpa_enabled =3D false; + priv->sec_info.wpa2_enabled =3D false; + } + + return 0; +} + +/* IOCTL request handler to set/reset WPS IE. + * + * The supplied WPS IE is treated as a opaque buffer. Only the first field + * is checked to internally enable WPS. If buffer length is zero, the exis= ting + * WPS IE is reset. + */ +static int nxpwifi_set_wps_ie(struct nxpwifi_private *priv, + u8 *ie_data_ptr, u16 ie_len) +{ + if (ie_len) { + if (ie_len > NXPWIFI_MAX_VSIE_LEN) { + nxpwifi_dbg(priv->adapter, ERROR, + "info: failed to copy WPS IE, too big\n"); + return -1; + } + + priv->wps_ie =3D kzalloc(NXPWIFI_MAX_VSIE_LEN, GFP_KERNEL); + if (!priv->wps_ie) + return -ENOMEM; + + memcpy(priv->wps_ie, ie_data_ptr, ie_len); + priv->wps_ie_len =3D ie_len; + nxpwifi_dbg(priv->adapter, CMD, + "cmd: Set wps_ie_len=3D%d IE=3D%#x\n", + priv->wps_ie_len, priv->wps_ie[0]); + } else { + kfree(priv->wps_ie); + priv->wps_ie_len =3D ie_len; + nxpwifi_dbg(priv->adapter, INFO, + "info: Reset wps_ie_len=3D%d\n", priv->wps_ie_len); + } + return 0; +} + +/* IOCTL request handler to set WEP network key. + * + * This function prepares the correct firmware command and + * issues it, after validation checks. + */ +static int +nxpwifi_sec_ioctl_set_wep_key(struct nxpwifi_private *priv, + struct nxpwifi_ds_encrypt_key *encrypt_key) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + struct nxpwifi_wep_key *wep_key; + int index; + + if (priv->wep_key_curr_index >=3D NUM_WEP_KEYS) + priv->wep_key_curr_index =3D 0; + wep_key =3D &priv->wep_key[priv->wep_key_curr_index]; + index =3D encrypt_key->key_index; + if (encrypt_key->key_disable) { + priv->sec_info.wep_enabled =3D 0; + } else if (!encrypt_key->key_len) { + /* Copy the required key as the current key */ + wep_key =3D &priv->wep_key[index]; + if (!wep_key->key_length) { + nxpwifi_dbg(adapter, ERROR, + "key not set, so cannot enable it\n"); + return -1; + } + + memcpy(encrypt_key->key_material, + wep_key->key_material, wep_key->key_length); + encrypt_key->key_len =3D wep_key->key_length; + + priv->wep_key_curr_index =3D (u16)index; + priv->sec_info.wep_enabled =3D 1; + } else { + wep_key =3D &priv->wep_key[index]; + memset(wep_key, 0, sizeof(struct nxpwifi_wep_key)); + /* Copy the key in the driver */ + memcpy(wep_key->key_material, + encrypt_key->key_material, + encrypt_key->key_len); + wep_key->key_index =3D index; + wep_key->key_length =3D encrypt_key->key_len; + priv->sec_info.wep_enabled =3D 1; + } + if (wep_key->key_length) { + void *enc_key; + + if (encrypt_key->key_disable) { + memset(&priv->wep_key[index], 0, + sizeof(struct nxpwifi_wep_key)); + goto done; + } + + enc_key =3D encrypt_key; + + /* Send request to firmware */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_KEY_MATERIAL, + HOST_ACT_GEN_SET, 0, enc_key, false); + if (ret) + return ret; + } + +done: + if (priv->sec_info.wep_enabled) + priv->curr_pkt_filter |=3D HOST_ACT_MAC_WEP_ENABLE; + else + priv->curr_pkt_filter &=3D ~HOST_ACT_MAC_WEP_ENABLE; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL, + HOST_ACT_GEN_SET, 0, + &priv->curr_pkt_filter, true); + + return ret; +} + +/* IOCTL request handler to set WPA key. + * + * This function prepares the correct firmware command and + * issues it, after validation checks. + * + * Current driver only supports key length of up to 32 bytes. + * + * This function can also be used to disable a currently set key. + */ +static int +nxpwifi_sec_ioctl_set_wpa_key(struct nxpwifi_private *priv, + struct nxpwifi_ds_encrypt_key *encrypt_key) +{ + int ret; + u8 remove_key =3D false; + + /* Current driver only supports key length of up to 32 bytes */ + if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) { + nxpwifi_dbg(priv->adapter, ERROR, + "key length too long\n"); + return -1; + } + + if (!encrypt_key->key_index) + encrypt_key->key_index =3D NXPWIFI_KEY_INDEX_UNICAST; + + if (remove_key) + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_KEY_MATERIAL, + HOST_ACT_GEN_SET, + !KEY_INFO_ENABLED, encrypt_key, true); + else + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_KEY_MATERIAL, + HOST_ACT_GEN_SET, + KEY_INFO_ENABLED, encrypt_key, true); + + return ret; +} + +/* IOCTL request handler to set/get network keys. + * + * This is a generic key handling function which supports WEP and WPA. + */ +static int +nxpwifi_sec_ioctl_encrypt_key(struct nxpwifi_private *priv, + struct nxpwifi_ds_encrypt_key *encrypt_key) +{ + int status; + + if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104) + status =3D nxpwifi_sec_ioctl_set_wpa_key(priv, encrypt_key); + else + status =3D nxpwifi_sec_ioctl_set_wep_key(priv, encrypt_key); + + return status; +} + +/* This function returns the driver version. + */ +int +nxpwifi_drv_get_driver_version(struct nxpwifi_adapter *adapter, char *vers= ion, + int max_len) +{ + union { + __le32 l; + u8 c[4]; + } ver; + char fw_ver[32]; + + ver.l =3D cpu_to_le32(adapter->fw_release_number); + sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); + + snprintf(version, max_len, driver_version, fw_ver); + + nxpwifi_dbg(adapter, MSG, "info: NXPWIFI VERSION: %s\n", version); + + return 0; +} + +/* Sends IOCTL request to set encoding parameters. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int nxpwifi_set_encode(struct nxpwifi_private *priv, struct key_params *kp, + const u8 *key, int key_len, u8 key_index, + const u8 *mac_addr, int disable) +{ + struct nxpwifi_ds_encrypt_key encrypt_key; + + memset(&encrypt_key, 0, sizeof(encrypt_key)); + encrypt_key.key_len =3D key_len; + encrypt_key.key_index =3D key_index; + + if (kp && kp->cipher =3D=3D WLAN_CIPHER_SUITE_AES_CMAC) + encrypt_key.is_igtk_key =3D true; + + if (!disable) { + if (key_len) + memcpy(encrypt_key.key_material, key, key_len); + else + encrypt_key.is_current_wep_key =3D true; + + if (mac_addr) + memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); + if (kp && kp->seq && kp->seq_len) { + memcpy(encrypt_key.pn, kp->seq, kp->seq_len); + encrypt_key.pn_len =3D kp->seq_len; + encrypt_key.is_rx_seq_valid =3D true; + } + } else { + encrypt_key.key_disable =3D true; + if (mac_addr) + memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); + } + + return nxpwifi_sec_ioctl_encrypt_key(priv, &encrypt_key); +} + +/* Sends IOCTL request to get extended version. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +nxpwifi_get_ver_ext(struct nxpwifi_private *priv, u32 version_str_sel) +{ + struct nxpwifi_ver_ext ver_ext; + + memset(&ver_ext, 0, sizeof(ver_ext)); + ver_ext.version_str_sel =3D version_str_sel; + if (nxpwifi_send_cmd(priv, HOST_CMD_VERSION_EXT, + HOST_ACT_GEN_GET, 0, &ver_ext, true)) + return -1; + + return 0; +} + +int +nxpwifi_remain_on_chan_cfg(struct nxpwifi_private *priv, u16 action, + struct ieee80211_channel *chan, + unsigned int duration) +{ + struct host_cmd_ds_remain_on_chan roc_cfg; + u8 sc; + + memset(&roc_cfg, 0, sizeof(roc_cfg)); + roc_cfg.action =3D cpu_to_le16(action); + if (action =3D=3D HOST_ACT_GEN_SET) { + roc_cfg.band_cfg =3D chan->band; + sc =3D nxpwifi_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT); + roc_cfg.band_cfg |=3D (sc << 2); + + roc_cfg.channel =3D + ieee80211_frequency_to_channel(chan->center_freq); + roc_cfg.duration =3D cpu_to_le32(duration); + } + if (nxpwifi_send_cmd(priv, HOST_CMD_REMAIN_ON_CHAN, + action, 0, &roc_cfg, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "failed to remain on channel\n"); + return -1; + } + + return roc_cfg.status; +} + +/* Sends IOCTL request to get statistics information. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +nxpwifi_get_stats_info(struct nxpwifi_private *priv, + struct nxpwifi_ds_get_stats *log) +{ + return nxpwifi_send_cmd(priv, HOST_CMD_802_11_GET_LOG, + HOST_ACT_GEN_GET, 0, log, true); +} + +/* IOCTL request handler to read/write register. + * + * This function prepares the correct firmware command and + * issues it. + * + * Access to the following registers are supported - + * - MAC + * - BBP + * - RF + * - PMIC + * - CAU + */ +static int nxpwifi_reg_mem_ioctl_reg_rw(struct nxpwifi_private *priv, + struct nxpwifi_ds_reg_rw *reg_rw, + u16 action) +{ + u16 cmd_no; + + switch (reg_rw->type) { + case NXPWIFI_REG_MAC: + cmd_no =3D HOST_CMD_MAC_REG_ACCESS; + break; + case NXPWIFI_REG_BBP: + cmd_no =3D HOST_CMD_BBP_REG_ACCESS; + break; + case NXPWIFI_REG_RF: + cmd_no =3D HOST_CMD_RF_REG_ACCESS; + break; + case NXPWIFI_REG_PMIC: + cmd_no =3D HOST_CMD_PMIC_REG_ACCESS; + break; + case NXPWIFI_REG_CAU: + cmd_no =3D HOST_CMD_CAU_REG_ACCESS; + break; + default: + return -1; + } + + return nxpwifi_send_cmd(priv, cmd_no, action, 0, reg_rw, true); +} + +/* Sends IOCTL request to write to a register. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +nxpwifi_reg_write(struct nxpwifi_private *priv, u32 reg_type, + u32 reg_offset, u32 reg_value) +{ + struct nxpwifi_ds_reg_rw reg_rw; + + reg_rw.type =3D reg_type; + reg_rw.offset =3D reg_offset; + reg_rw.value =3D reg_value; + + return nxpwifi_reg_mem_ioctl_reg_rw(priv, ®_rw, HOST_ACT_GEN_SET); +} + +/* Sends IOCTL request to read from a register. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +nxpwifi_reg_read(struct nxpwifi_private *priv, u32 reg_type, + u32 reg_offset, u32 *value) +{ + int ret; + struct nxpwifi_ds_reg_rw reg_rw; + + reg_rw.type =3D reg_type; + reg_rw.offset =3D reg_offset; + ret =3D nxpwifi_reg_mem_ioctl_reg_rw(priv, ®_rw, HOST_ACT_GEN_GET); + + if (ret) + goto done; + + *value =3D reg_rw.value; + +done: + return ret; +} + +/* Sends IOCTL request to read from EEPROM. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +nxpwifi_eeprom_read(struct nxpwifi_private *priv, u16 offset, u16 bytes, + u8 *value) +{ + int ret; + struct nxpwifi_ds_read_eeprom rd_eeprom; + + rd_eeprom.offset =3D offset; + rd_eeprom.byte_count =3D bytes; + + /* Send request to firmware */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_EEPROM_ACCESS, + HOST_ACT_GEN_GET, 0, &rd_eeprom, true); + + if (!ret) + memcpy(value, rd_eeprom.value, + min((u16)MAX_EEPROM_DATA, rd_eeprom.byte_count)); + return ret; +} + +/* This function sets a generic IE. In addition to generic IE, it can + * also handle WPA and WPA2 IEs. + */ +static int +nxpwifi_set_gen_ie_helper(struct nxpwifi_private *priv, u8 *ie_data_ptr, + u16 ie_len) +{ + struct ieee_types_vendor_header *pvendor_ie; + static const u8 wpa_oui[] =3D { 0x00, 0x50, 0xf2, 0x01 }; + static const u8 wps_oui[] =3D { 0x00, 0x50, 0xf2, 0x04 }; + u16 unparsed_len =3D ie_len, cur_ie_len; + + /* If the passed length is zero, reset the buffer */ + if (!ie_len) { + priv->gen_ie_buf_len =3D 0; + priv->wps.session_enable =3D false; + return 0; + } else if (!ie_data_ptr || + ie_len <=3D sizeof(struct ieee_types_header)) { + return -1; + } + pvendor_ie =3D (struct ieee_types_vendor_header *)ie_data_ptr; + + while (pvendor_ie) { + cur_ie_len =3D pvendor_ie->len + sizeof(struct ieee_types_header); + + if (pvendor_ie->element_id =3D=3D WLAN_EID_RSN) { + /* IE is a WPA/WPA2 IE so call set_wpa function */ + nxpwifi_set_wpa_ie(priv, (u8 *)pvendor_ie, cur_ie_len); + priv->wps.session_enable =3D false; + goto next_ie; + } + + if (pvendor_ie->element_id =3D=3D WLAN_EID_VENDOR_SPECIFIC) { + /* Test to see if it is a WPA IE, if not, then + * it is a gen IE + */ + if (!memcmp(&pvendor_ie->oui, wpa_oui, + sizeof(wpa_oui))) { + /* IE is a WPA/WPA2 IE so call set_wpa function + */ + nxpwifi_set_wpa_ie(priv, (u8 *)pvendor_ie, + cur_ie_len); + priv->wps.session_enable =3D false; + goto next_ie; + } + + if (!memcmp(&pvendor_ie->oui, wps_oui, + sizeof(wps_oui))) { + /* Test to see if it is a WPS IE, + * if so, enable wps session flag + */ + priv->wps.session_enable =3D true; + nxpwifi_dbg(priv->adapter, MSG, + "WPS Session Enabled.\n"); + nxpwifi_set_wps_ie(priv, (u8 *)pvendor_ie, + cur_ie_len); + goto next_ie; + } + } + + /* Verify that the passed length is not larger than the + * available space remaining in the buffer + */ + if (cur_ie_len < + (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) { + /* Append the passed data to the end + * of the genIeBuffer + */ + memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, + (u8 *)pvendor_ie, cur_ie_len); + /* Increment the stored buffer length by the + * size passed + */ + priv->gen_ie_buf_len +=3D cur_ie_len; + } + +next_ie: + unparsed_len -=3D cur_ie_len; + + if (unparsed_len <=3D sizeof(struct ieee_types_header)) + pvendor_ie =3D NULL; + else + pvendor_ie =3D (struct ieee_types_vendor_header *) + (((u8 *)pvendor_ie) + cur_ie_len); + } + + return 0; +} + +/* IOCTL request handler to set/get generic IE. + * + * In addition to various generic IEs, this function can also be + * used to set the ARP filter. + */ +static int nxpwifi_misc_ioctl_gen_ie(struct nxpwifi_private *priv, + struct nxpwifi_ds_misc_gen_ie *gen_ie, + u16 action) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + switch (gen_ie->type) { + case NXPWIFI_IE_TYPE_GEN_IE: + if (action =3D=3D HOST_ACT_GEN_GET) { + gen_ie->len =3D priv->wpa_ie_len; + memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len); + } else { + nxpwifi_set_gen_ie_helper(priv, gen_ie->ie_data, + (u16)gen_ie->len); + } + break; + case NXPWIFI_IE_TYPE_ARP_FILTER: + memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter)); + if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) { + adapter->arp_filter_size =3D 0; + nxpwifi_dbg(adapter, ERROR, + "invalid ARP filter size\n"); + return -1; + } + memcpy(adapter->arp_filter, gen_ie->ie_data, gen_ie->len); + adapter->arp_filter_size =3D gen_ie->len; + break; + default: + nxpwifi_dbg(adapter, ERROR, "invalid IE type\n"); + return -1; + } + return 0; +} + +/* Sends IOCTL request to set a generic IE. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +nxpwifi_set_gen_ie(struct nxpwifi_private *priv, const u8 *ie, int ie_len) +{ + struct nxpwifi_ds_misc_gen_ie gen_ie; + + if (ie_len > IEEE_MAX_IE_SIZE) + return -EFAULT; + + gen_ie.type =3D NXPWIFI_IE_TYPE_GEN_IE; + gen_ie.len =3D ie_len; + memcpy(gen_ie.ie_data, ie, ie_len); + if (nxpwifi_misc_ioctl_gen_ie(priv, &gen_ie, HOST_ACT_GEN_SET)) + return -EFAULT; + + return 0; +} + +/* This function get Host Sleep wake up reason. + */ +int nxpwifi_get_wakeup_reason(struct nxpwifi_private *priv, u16 action, + int cmd_type, + struct nxpwifi_ds_wakeup_reason *wakeup_reason) +{ + int status =3D 0; + + status =3D nxpwifi_send_cmd(priv, HOST_CMD_HS_WAKEUP_REASON, + HOST_ACT_GEN_GET, 0, wakeup_reason, + cmd_type =3D=3D NXPWIFI_SYNC_CMD); + + return status; +} + +int nxpwifi_get_chan_info(struct nxpwifi_private *priv, + struct nxpwifi_channel_band *channel_band) +{ + int status =3D 0; + + status =3D nxpwifi_send_cmd(priv, HOST_CMD_STA_CONFIGURE, + HOST_ACT_GEN_GET, 0, channel_band, + NXPWIFI_SYNC_CMD); + + return status; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2059.outbound.protection.outlook.com [40.107.8.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A516F16E88F; Fri, 21 Jun 2024 07:54:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.59 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956465; cv=fail; b=ZizT0Boha83xc8yP+QxWlT3J9E5BJjRw9XZ26w5D9NKZlSPgUBnyIH7hqdcrRQmcjJuQJVIoDmoapRQvkW7Wls86BS2o9NKzJwHMX5KQPtC4QM3tOkskpLpYtIajMKO/lCyAQudZJXEbZibcUYEtCGrRWZImsoTUNn78vtzFbdE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956465; c=relaxed/simple; bh=Djzln+3lGkZZ9EFjfSDXTbdRkq2+it4KTZpzuWitzPY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=KFXSQOEetZiSSNs6r8MiNeMwJ+qYMB7IilY4mu7tYsSuCj5Wsipl7/g6TGpSRNBxSjmxZUMpzcsf47LpSxgbVCoKKGJIjio0Dj5HqHCa9KfJwTeJwuMMoBBB7hCQXxzZqIciskzb3fm9hhyjeuLGYF5iuLRMe+1Zrr0lluDSVxU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=ctqRE9Mq; arc=fail smtp.client-ip=40.107.8.59 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="ctqRE9Mq" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KvDzc7EC093Fmsm8T8PkqJfAzujIEvKJYf+FvlCPpvcmCu8YUnLV7G7ali39VyGcVrcYtljaGIJVHeb8BsJ6+6acX2q4/ixNhxayw1ciHfB8QSjZkxraHFatIOj8e6DhI2oaC4cwkmlppB/rXTYXEgUERad9/MB/jj3swPeZj8RTKe/nYo1iRT8n/LY/9UowzQBY7UMpzeWBpzlXfLmE4nbDlgzCnhiooITfe1AAriH8k2YFcJIocUPHCHG7O4aQh23r/TQrQCx7B5f7JHkDX0WtoBsALKuaWumz6PXS6JiiQLbV0rRWAfg+alXGgkemMoMXGQGi1OeWm6gx6awUOg== 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=lLYvg+X4YphWukZS7QCqHGZLsN9xLcKOGLe4/faSvDs=; b=iUnbMGlPeAYF/9zoRzB7Lp6/hICnGilHMp31hJiZXFMHzttkQwbXTl8khLOvgzFoYaYtDx2f5zA7SWfkVX6FTWaJ2u3/R72X0orNqYzxlJLnmHXN4PAYZ8hGPhS86mpGAtQoIYHWgE9/83EvMlaw/5zN3j2RU1gFir7mFTZRB6ekwQ/Eg/psp/Xc3xE/iDg2PmFUCbA4Pl/+WSpp+pjslWoPCJ+QHy+AkULs6CVyrnBIFyHPB+t4g0mT41aPDpnrIjIw9aSwEK2KnB9YBx9zuauU3P5yewAn8x01ZmiVqbXnkEAoFdc1ITMnKVEsP9cQM8qjnZ5cK0m/TEBLr7LAHw== 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=lLYvg+X4YphWukZS7QCqHGZLsN9xLcKOGLe4/faSvDs=; b=ctqRE9Mqklyxeg4idAnJNre7NmcXWs3oEo6IZ6PYMPSXLgm4o4Ni+5VqvSxJKuI1UGCONEqMwrtSEB1WPnNghL59O0bsFG5yTmWFo2eOmSs0rFmXRgdChaz6YjJvT5r0r8j6G1pTNVQ1mQaY24lREW4ynmDmQPiIcg0YVswgMVU= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:18 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:18 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 31/43] wifi: nxpwifi: add sta_rx.c Date: Fri, 21 Jun 2024 15:51:56 +0800 Message-Id: <20240621075208.513497-32-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: 06f26854-1806-42f9-3ad5-08dc91c75a31 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?7hs5zqo8b3s4sQ7Rhg38UbeIozsTPH4axM0LZoppwbbD42nQntggThADzCvq?= =?us-ascii?Q?cgZJfLc59ZvIyNqPEohcD06SS6aDxYRlDPXKt8R9js0ACZn4KSqdJkDpgcuv?= =?us-ascii?Q?OjIIVE3laoQS7uqlmmf+AjNEjKeOzzVE03Z5pHEYWuzL/S7zho+wHv1MeXcg?= =?us-ascii?Q?uSYcs2/dhtYAfQ/mckKiOOk07KO3qQugYsnt8gUo8sCcDCXyHXuzGy2sF6la?= =?us-ascii?Q?133ERPffCF7rH/+lGtCAcXFe/YShVtQLylN8geYyWZ0dqMIf47jgK5woOxP9?= =?us-ascii?Q?0WHjjnhxcqUDZQ7I/iJDxRdgJvAtVcCfo9TrsJMQDfO/Z5IXVRifqFgSlt3P?= =?us-ascii?Q?OVbF2FV7F0t4ZwzpuSQmpz6xQOdsdUzXBTd+pzKblT9q6UeIxaTiKiCpQGQE?= =?us-ascii?Q?p3+NpQ8RaTCOE0EbKxNzOUv2Sg11xXVfS0Y0Ih7FflE0l3kHYZle+BNTYOfS?= =?us-ascii?Q?NLFAt3KSYx0Mm97fVsA3hh/dmoO2hGADErJrenDbJkCaqo3foWzvf3ZIa0jw?= =?us-ascii?Q?kuyLZnds1xRzsTl/eI6DYMgw6NuGgHmHk15GOgcVTO5cx86mVQGcEYnWXo0v?= =?us-ascii?Q?XFTL8SPGQTQK91xqRoOuuo0ToWnR6U6y8qUIXmHyUNZkZIbNgjKABUQpecss?= =?us-ascii?Q?ZzrQX7JpKRoSLu4p2SNGwXxMWkvxu5b5kz66RRq0v6N4UMwbaf/lHGk2pDHG?= =?us-ascii?Q?TErHiKG0w3MQGBhRtFFnc+qa9C6eR/Ji1nJfG+D4RLGxodp3e3qlfbCgCt72?= =?us-ascii?Q?sqvmy0hgtmZqa7+TkRAFKe959izwYkLvOAaWUlQjZ8+E8T/ViVH8HnsPNFsI?= =?us-ascii?Q?ueueJZoNwfWImI0phkjfUoC3Dp4n+iPVqO377w4XRP2acnTv4C/agdJ4810V?= =?us-ascii?Q?32FZa4M0XSJEvNiV83MwHd9gBfE4EqrxJw+8Id9sai8XuZHXQC2hZy0/Lx81?= =?us-ascii?Q?z/1QJEa1l7nUHLJ3z2ffWj1rDIWPcAIsaPIxXr4cJrCueGUN19WTIhc1I5dA?= =?us-ascii?Q?PATaM4lXRC4UQzrxaqUPa2FVUV2EiFShkiR0zIgl5FkDNpf1Vo1YZfpzWJCM?= =?us-ascii?Q?7kkspQlUzaZphuXXFDcXOQwD6qc55t4hgk9/dW92vHQdQvn7UpK/TanRLPxW?= =?us-ascii?Q?ME0sGXvxHpVQv8B/yVuva1VSpAcrpFDPgsnoqbs7lf7ZpOr1Ng6ANd/AarpS?= =?us-ascii?Q?Skb98QeXxxpcU9FADV3rV89+actsd8TS6cHqyrXRwHLmxDBupiFwYu2BxdcA?= =?us-ascii?Q?ExzWMrHAcFQ8cuVUSqqpC4z2kPJYFq9OrD7HvxMtm7T+Xol7FvSut/t2kecq?= =?us-ascii?Q?SZXr89Jo9/EvYI0Tmpg439ANWGqy1Jq22KVQYWzS44dmvXnR4riZqOJrXCXs?= =?us-ascii?Q?UI5MvPY=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?xbqic4xo3YzKe36Uy6bkz7mj+MN6iwHEJa1APnYhbUKaeD9ytCinJJWeP8Ra?= =?us-ascii?Q?/96984ashiqAh3MamxfyLpV4sMXZtCC5BUfI8PO1QvAzAlHyGM/kf3U9KvV3?= =?us-ascii?Q?HVb6gMVFfEJKrLwl4s0k1cHy1sGV0XsD+ENMF/UYbLdZ76r5BzX2dxu31r9U?= =?us-ascii?Q?4kQEqvFMTtCgBXMKbK4giJMG8cNd/ZH21QoXjyiHOMWWmJ9mComyqzrqCJ/h?= =?us-ascii?Q?Vcd8SZ0BDdxOYkSTAkgUmrFPdx3rypWqS9RpktefmufSV5X9aV+rcY7obndF?= =?us-ascii?Q?8SAO4mmg7IWZ4hXCk9FFRp7ollBITeqxVkf5IhicihD0JyUDsCUwhG/Z5m01?= =?us-ascii?Q?ZUSB3efrtMjVXeaetDe2m8BchEIuMOMFjhl5JTqEBsa0GjtmkT5l+AB81K5G?= =?us-ascii?Q?fVSr5BkAtaP2GLgYpvCzRIPjGMCurdJT4eQa18WXjulomIkoYR3B7EPpKetR?= =?us-ascii?Q?bV1ihcxxoWtxOGTTsx4+Omh3Go5ANpjkWhoqeofKO6WjMAx8SpbytNp0jDkc?= =?us-ascii?Q?cNY+mDPMl5OovaJRUzfvhyqrbav0clNnqPFfE7ex3GgZZV8x5GE2pq/PPT9K?= =?us-ascii?Q?ElPowbmi9fjBlmCzmMySB47s+c0WvvXxWGlBN6bpmhVacQJwOpuVXg8Xj4ve?= =?us-ascii?Q?xony8oehqm9C2D3sXN8lNaCn83cuKBVSJWZNbcS5t8fpcLpzfWiQRGZhBEBF?= =?us-ascii?Q?10RTKUYYshlb8kkFLKjfnxTHYb4kp/8WfXxs0QYJERta1aJ5mpEJTejGXZ8q?= =?us-ascii?Q?r0J8+oUTq/eazlZ2rxTpUSfDFSa1sFAPe+PSg1VuuNTF+nQKSSBriFDatoJ6?= =?us-ascii?Q?Jg1Bh3xj7QmnunMyaJhAWA//rLj9GLSP7+FRV916IvofI2HuWtqnY/1KGFYB?= =?us-ascii?Q?wBVpn8olhlE93AnsPieVZhepZfx77EFMig7U8ExQhyvZm2PWknOt7y5Sh0Hu?= =?us-ascii?Q?k9uDueVKiChi/uENa7nBmvZG50yiiFhy6R24TlLFiT7gxzz73IXR5qRIWCN6?= =?us-ascii?Q?Qq19EaMCJIfc7SfB/endOh2nrprWOkarQHz25dVr4Lgw+i0wkYtHLoXhRUT/?= =?us-ascii?Q?A3164GOJkWu9Iy5mznN8i7ZggbuLriwZTy3QWGHPcl4+tyV4pDivUa+5YZzQ?= =?us-ascii?Q?HjZZqKJ0MQNsa4p944+vB0zc/m9TMBzBq/INwqy0hLbnrfhw/ZKT5pO+xv/z?= =?us-ascii?Q?lKEymW2JiBC7zCcSZOUfBNk9c65DD+jENwhJfcENr43lfeqygRzUjjrB/D8V?= =?us-ascii?Q?1vCfODg3LIvUHSQwbI8PWLL/e3la/kUTAez5o6BlPh0C3jOS4OYb7HWAOyTg?= =?us-ascii?Q?5IsQ2tdX2Z3zPp4a6aecKohEHslzWjGYagXaZ3K5fgZGMqw8qPjPj7GPpnAA?= =?us-ascii?Q?v/vRgNDdFMcmEwdBTuqTI5lh1IF2IpW0yL9TNoNuIz6gAEvWWQwQKMVYqqdX?= =?us-ascii?Q?7XKIEdcfVIZcyJShm+CU7XNYjeXJdy1q9W3F1Xlf5OSnQ84kXzbEFSF5I0z5?= =?us-ascii?Q?DiFyYPypLb802lGz1XM6Vh04dWKpUAAsZY8OTga+s9sMYqJTwZTMiRXiV4U/?= =?us-ascii?Q?UINVNShwKr/wKP1BVPSI0t+UxTS7LJ9EerVt2ehs?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 06f26854-1806-42f9-3ad5-08dc91c75a31 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:18.0713 (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: gGjGJtRvjN8YLspmXNV2HmRWKoGFAI3ia3wCwdDnhk0+DcwAp0wbNT3UwBZzWU0ftWv1+BpGtRNhKLMTrjcaUA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sta_rx.c | 244 ++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sta_rx.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_rx.c b/drivers/net/wirele= ss/nxp/nxpwifi/sta_rx.c new file mode 100644 index 000000000000..9309ac510ac5 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_rx.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station RX data handling + * + * Copyright 2011-2024 NXP + */ + +#include +#include +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "11n_aggr.h" +#include "11n_rxreorder.h" + +/* This function checks if a frame is IPv4 ARP or IPv6 Neighbour advertise= ment + * frame. If frame has both source and destination mac address as same, th= is + * function drops such gratuitous frames. + */ +static bool +nxpwifi_discard_gratuitous_arp(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + const struct nxpwifi_arp_eth_header *arp; + struct ethhdr *eth; + struct ipv6hdr *ipv6; + struct icmp6hdr *icmpv6; + + eth =3D (struct ethhdr *)skb->data; + switch (ntohs(eth->h_proto)) { + case ETH_P_ARP: + arp =3D (void *)(skb->data + sizeof(struct ethhdr)); + if (arp->hdr.ar_op =3D=3D htons(ARPOP_REPLY) || + arp->hdr.ar_op =3D=3D htons(ARPOP_REQUEST)) { + if (!memcmp(arp->ar_sip, arp->ar_tip, 4)) + return true; + } + break; + case ETH_P_IPV6: + ipv6 =3D (void *)(skb->data + sizeof(struct ethhdr)); + icmpv6 =3D (void *)(skb->data + sizeof(struct ethhdr) + + sizeof(struct ipv6hdr)); + if (icmpv6->icmp6_type =3D=3D NDISC_NEIGHBOUR_ADVERTISEMENT) { + if (!memcmp(&ipv6->saddr, &ipv6->daddr, + sizeof(struct in6_addr))) + return true; + } + break; + default: + break; + } + + return false; +} + +/* This function processes the received packet and forwards it + * to kernel/upper layer. + * + * This function parses through the received packet and determines + * if it is a debug packet or normal packet. + * + * For non-debug packets, the function chops off unnecessary leading + * header bytes, reconstructs the packet as an ethernet frame or + * 802.2/llc/snap frame as required, and sends it to kernel/upper layer. + * + * The completion callback is called after processing in complete. + */ +int nxpwifi_process_rx_packet(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + int ret; + struct rx_packet_hdr *rx_pkt_hdr; + struct rxpd *local_rx_pd; + int hdr_chop; + struct ethhdr *eth; + u16 rx_pkt_off, rx_pkt_len; + u8 adj_rx_rate =3D 0; + + local_rx_pd =3D (struct rxpd *)(skb->data); + + rx_pkt_off =3D le16_to_cpu(local_rx_pd->rx_pkt_offset); + rx_pkt_len =3D le16_to_cpu(local_rx_pd->rx_pkt_length); + rx_pkt_hdr =3D (void *)local_rx_pd + rx_pkt_off; + + if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) + + rx_pkt_off > skb->len) { + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return -1; + } + + if (sizeof(*rx_pkt_hdr) + rx_pkt_off <=3D skb->len && + ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, + sizeof(bridge_tunnel_header))) || + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header)) && + rx_pkt_hdr->rfc1042_hdr.snap_type !=3D htons(ETH_P_AARP) && + rx_pkt_hdr->rfc1042_hdr.snap_type !=3D htons(ETH_P_IPX)))) { + /* Replace the 803 header and rfc1042 header (llc/snap) with an + * EthernetII header, keep the src/dst and snap_type + * (ethertype). + * The firmware only passes up SNAP frames converting + * all RX Data from 802.11 to 802.2/LLC/SNAP frames. + * To create the Ethernet II, just move the src, dst address + * right before the snap_type. + */ + eth =3D (struct ethhdr *) + ((u8 *)&rx_pkt_hdr->eth803_hdr + + sizeof(rx_pkt_hdr->eth803_hdr) + + sizeof(rx_pkt_hdr->rfc1042_hdr) + - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) + - sizeof(rx_pkt_hdr->eth803_hdr.h_source) + - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); + + memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source, + sizeof(eth->h_source)); + memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, + sizeof(eth->h_dest)); + + /* Chop off the rxpd + the excess memory from the 802.2/llc/snap + * header that was removed. + */ + hdr_chop =3D (u8 *)eth - (u8 *)local_rx_pd; + } else { + /* Chop off the rxpd */ + hdr_chop =3D (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)local_rx_pd; + } + + /* Chop off the leading header bytes so the it points to the start of + * either the reconstructed EthII frame or the 802.2/llc/snap frame + */ + skb_pull(skb, hdr_chop); + + if (priv->hs2_enabled && + nxpwifi_discard_gratuitous_arp(priv, skb)) { + nxpwifi_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n"); + dev_kfree_skb_any(skb); + return 0; + } + + /* Only stash RX bitrate for unicast packets. */ + if (likely(!is_multicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest))) { + priv->rxpd_rate =3D local_rx_pd->rx_rate; + priv->rxpd_htinfo =3D local_rx_pd->ht_info; + } + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA || + GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + adj_rx_rate =3D nxpwifi_adjust_data_rate(priv, + local_rx_pd->rx_rate, + local_rx_pd->ht_info); + nxpwifi_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr, + local_rx_pd->nf); + } + + ret =3D nxpwifi_recv_packet(priv, skb); + if (ret =3D=3D -1) + nxpwifi_dbg(priv->adapter, ERROR, + "recv packet failed\n"); + + return ret; +} + +/* This function processes the received buffer. + * + * The function looks into the RxPD and performs sanity tests on the + * received buffer to ensure its a valid packet, before processing it + * further. If the packet is determined to be aggregated, it is + * de-aggregated accordingly. Non-unicast packets are sent directly to + * the kernel/upper layers. Unicast packets are handed over to the + * Rx reordering routine if 11n is enabled. + * + * The completion callback is called after processing in complete. + */ +int nxpwifi_process_sta_rx_packet(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret =3D 0; + struct rxpd *local_rx_pd; + struct rx_packet_hdr *rx_pkt_hdr; + u8 ta[ETH_ALEN]; + u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; + + local_rx_pd =3D (struct rxpd *)(skb->data); + rx_pkt_type =3D le16_to_cpu(local_rx_pd->rx_pkt_type); + rx_pkt_offset =3D le16_to_cpu(local_rx_pd->rx_pkt_offset); + rx_pkt_length =3D le16_to_cpu(local_rx_pd->rx_pkt_length); + seq_num =3D le16_to_cpu(local_rx_pd->seq_num); + + rx_pkt_hdr =3D (void *)local_rx_pd + rx_pkt_offset; + + if ((rx_pkt_offset + rx_pkt_length) > skb->len || + sizeof(rx_pkt_hdr->eth803_hdr) + rx_pkt_offset > skb->len) { + nxpwifi_dbg(adapter, ERROR, + "wrong rx packet: len=3D%d, rx_pkt_offset=3D%d, rx_pkt_length=3D%d\= n", + skb->len, rx_pkt_offset, rx_pkt_length); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return ret; + } + + if (rx_pkt_type =3D=3D PKT_TYPE_MGMT) { + ret =3D nxpwifi_process_mgmt_packet(priv, skb); + if (ret) + nxpwifi_dbg(adapter, DATA, "Rx of mgmt packet failed"); + dev_kfree_skb_any(skb); + return ret; + } + + /* If the packet is not an unicast packet then send the packet + * directly to os. Don't pass thru rx reordering + */ + if (!IS_11N_ENABLED(priv) || + !ether_addr_equal_unaligned(priv->curr_addr, + rx_pkt_hdr->eth803_hdr.h_dest)) { + nxpwifi_process_rx_packet(priv, skb); + return ret; + } + + if (nxpwifi_queuing_ra_based(priv)) { + memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); + } else { + if (rx_pkt_type !=3D PKT_TYPE_BAR && + local_rx_pd->priority < MAX_NUM_TID) + priv->rx_seq[local_rx_pd->priority] =3D seq_num; + memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, + ETH_ALEN); + } + + /* Reorder and send to OS */ + ret =3D nxpwifi_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority, + ta, (u8)rx_pkt_type, skb); + + if (ret || rx_pkt_type =3D=3D PKT_TYPE_BAR) + dev_kfree_skb_any(skb); + + if (ret) + priv->stats.rx_dropped++; + + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04on2059.outbound.protection.outlook.com [40.107.8.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75606176AB5; Fri, 21 Jun 2024 07:54:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.8.59 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956468; cv=fail; b=CJl4kJnVRGBLw1gWmuknTCrauKFh2A2i/tiCFshNhxdK8WGh20Khwxl2up6j/vQwMMoc5dYcys5xQyRxnA0+2RTfzYbbHW6kYgdclkHXIow+IV7W4Lu/1CyAwz82pwiJp/KzkWL1UJKq+Tcbwj440X+CIFNSPePn41/MDqbKCgE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956468; c=relaxed/simple; bh=aklnOpT2v7W0jpVlAabJ6Fw02cxZKm5w7S0hayxQ0Z4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=gh+ye7vROsaY/LiRdAWD0LZ2xerIY6Ge5qXMl91sM/cC6gQZvl38ge4Cmi7JwqWtAVNp8XTugxTSinRadMOdWPLdmi07qrN0fSHnv5mO9hpVQIvEBBRjkObgOT0+8h0D4iRP9/SVzDHMKxzZ9lOKe8LluBETyXbjZ3Y5quVfb9U= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=VcyTi0Z3; arc=fail smtp.client-ip=40.107.8.59 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="VcyTi0Z3" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mwwKlW+OO2y0efjv7oH93nkTXvFc9FPKIcXbF0ccvHNeBPbbR6kNcSbC695oq/BNHDSfGday3U2JILRQzEM1+P73YTgtKWQ64PKfRHQRSac874uhbakOAqar69q0WcLeEWO3J045b/gla5votoNfzNkmyXAZEzOYAle9AbzkctEc5r5kWHBavUNjaJ30IHnDJ7uAP/Oan0yE7MGbrD4s9k/aGFxVj87XOC9dQWnuksbRJ7QY+Y6zab06z+NsSET2FJsGRZwPjV/3BL8T11+0nP/cDYJgMPCLfL286gHC6XQ6t7b7UgL4ZMNHKbIsrfRtXnWmaG+rRSZvydjiDdLyYw== 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=rtNF4CrZJxpN3HJymi7dgfcDvCQZ6LjMXc3Vxjl+j1Y=; b=oYP0lYNkr0nqyphVpxs4AhjfonnuREmCnHdJmWeSPaXQuvSOlA8FXhJt3lw+RhX8MxvJmBkOnbTWJfhJ2hrzSI7vnuCxylrTPcSH4LHGLqs6Bfk6C63frTx8Y5LmPpWMGs+8MKJdAn1/AgaStCECT4qxUPHbuwoY7XFoBge48jGlwQjdaOS1SMiLkXx5M0PWcPtLwF0S5u6cIPf8lzWoGgLa9pW0x+yQzPoc5aUlXiU8F+ZaByUIsCmpSwOOwWGZsPdmfW9Wrq4k/kdJzxQHflhF3DW0v9skwZj8cXJumD8UGVgnWg8BI4T6j/gkuWQuWz5Wqfd1b/a8gRXqMCVmBw== 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=rtNF4CrZJxpN3HJymi7dgfcDvCQZ6LjMXc3Vxjl+j1Y=; b=VcyTi0Z348zLPKYu6Zi6hKJnD3vRpJN85+ilbXbbAWvU2NGiggnQgNMiE0Dom9gRTEBxat358OnalNUWg/AehGITj2aGftm6pz3WWsALNFj0YFEXpsX3LNOC6QfDSs0UqLGJ3BHqT+swyXuTuKZ0iJixiAJIbQoWIcoO4x5zfe8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by AS8PR04MB8135.eurprd04.prod.outlook.com (2603:10a6:20b:3b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:21 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:21 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 32/43] wifi: nxpwifi: add sta_tx.c Date: Fri, 21 Jun 2024 15:51:57 +0800 Message-Id: <20240621075208.513497-33-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|AS8PR04MB8135:EE_ X-MS-Office365-Filtering-Correlation-Id: fb2177fd-61a5-4501-c3d1-08dc91c75beb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|52116011|376011|1800799021|366013|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?+Oqkd5ldoq8LRFJ57mNTNYCJJPWVyRSSvOjTxBNw3A/gdNucNFzdHkPmrzCB?= =?us-ascii?Q?0sW4LadNwiZAHCiDTk+Zt0wIHL2ut0Id1yk6bsrYnQHAKSQ8Xpxi2RsaWDI6?= =?us-ascii?Q?VtCulXSXz5TBKAc06Rr9lkcN4eqR1wElXAwAs9zMkpQ9tTqO87x6hwz3X7KB?= =?us-ascii?Q?qAwMu0HMydj6M47umiOvotBvzkENIaon5ZPOgSbrTeJN9P9lzuZfzXASUOHb?= =?us-ascii?Q?TDkSMM2+iT4f0+HwlwHmarcDpDaKJyVgJd5uzB1FzJTTh5M3wTo8wqGx/U8J?= =?us-ascii?Q?WIK0Fm3Cbo2DCADeBI3T1EqPggVk6l4hMcCEaINvdCfiBppGJ9dV5F5wu3uL?= =?us-ascii?Q?e4VFy3hOcU8EHENZrFazyxUUB2sicxiZUkceebeyvygdLMQxc2Tktrk2izv3?= =?us-ascii?Q?DwizRa1p0EQrN/ZGiGFuR+peibKqL6WGpkrf/UDoQ81fYxHX7w+MIqsFgCmz?= =?us-ascii?Q?pDsm9q32lDqP7fSZbvBPax1iPwowDXBty3j+XaAaGJiJXJwlYKDlzp1MV1KG?= =?us-ascii?Q?U43cZGDxGM2ONqlGA7ePINpPYsVjl/yk20MT0ggEt4LV0MLPaBZ2ya59t1Ko?= =?us-ascii?Q?K59c+HkZpgdR0pwPewH3DfNkc+w63MwDtQXFuJZvOhxv0YJn0nxoa+QR7xxb?= =?us-ascii?Q?BvmC4YQHNSoHr7NrHiyBntcC/qFzi6Qc/fh9X03BB/FDQbHWdyQcq4w1dIIB?= =?us-ascii?Q?s7PnqC6FI104M+wMJYqaOMSW3U3khYF5zS/rqiJcoddBWQOxStdGADvwACjE?= =?us-ascii?Q?glBAsTEVPr4ohug5GziG5Ax0tC2POKSRqgGbyVQPcRlViunZ4KJyXYwH1p0l?= =?us-ascii?Q?pMgyo/X9jLvV+YrEheEzTPPmHmBFKSu3lH4KOqKkhoMskyqhPYOmAROGwtI6?= =?us-ascii?Q?FOn97OZYEII6O4skIS0s8yT6Zec/7r0dRPXu9dX2rfoLlcLmZaqJoakQGyYO?= =?us-ascii?Q?65Ejd+YJk4EMh/L2zmTIcbkjsVbc5J/C+II29hxgrm5WYGa/E38Z2BYkuy+Y?= =?us-ascii?Q?3EoxyzNdykN9gBEv0Ii1YLGTtN5+JdnovX4vnE4OAM2dmjSf1ji16yLb4kQX?= =?us-ascii?Q?u8+Mt5tiTKJ2zCDb6Wh3Tflv812DLQC6W6l2HMxGnzhw4YnpNrSvY6PAuCMX?= =?us-ascii?Q?Y6TeAAIcrvop+abFgm2JmUrQQ7EqQZp2LcvYblUGk1RWLyjhjWnsc7eVKGYv?= =?us-ascii?Q?YihvWO51oyftNU++J7XZbJLDeVs/NT/L0Qbcnje2Y6UnttJdZFn7myFABGrR?= =?us-ascii?Q?0mXGYplmWTGpBRsxLUKlKawJN07yNVq7+hnc4yGlDimVilUGmz21Er5pASN6?= =?us-ascii?Q?rP/+wuwtdtJXUL9Z2s3NNtzVhkOx3DjUfDibECUp/IHVDXD1OXqmZ8htuvSV?= =?us-ascii?Q?XjLIXSg=3D?= 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:(13230037)(52116011)(376011)(1800799021)(366013)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?paeAXd/8nX3461HUShzI6S0gi1oZp6LXvY15fYNzM5Z6vfK8gqqjbvL+dz8B?= =?us-ascii?Q?on8zf/rQmUQgLGhjspMrZ5HHzTPpdoE6tShm8EdxGa2fEqX5LS8sCmVxAl/R?= =?us-ascii?Q?Hi56OH2aUfUWMfOV56Qaj28uJSysY1FhV8rGMYwoM5ndUkmOhc5biQuhCsIL?= =?us-ascii?Q?uKKou+2LfeIWGYBrYgYbepwv68Yg6/2KC30NwqNmIqg3J8gH85nttPPIi4la?= =?us-ascii?Q?CWU4mmDj5BdhgIF9tyCzkpa/EX5OlMhxhUGwer9eI5D1Tu9h9idiRnav8KS3?= =?us-ascii?Q?/NQ0vpatAWbB68DU2ZQRwyPAmiNm678Hpki+rUoBeQbTSegpHeGgFzANJ0fR?= =?us-ascii?Q?JvEdyiJSo4w8/dieKLCo2/hzvVwq0gpPPZbD8vnsIFVTsqQoyWcW8wACNuIQ?= =?us-ascii?Q?BizMz5Bd45HvHXj52S0NMkdyglNUH4gTsSS45y+WfIl/CxFZC8GBw4pI2zXw?= =?us-ascii?Q?OCX1e1ulcYVVX0PSm+wUcTecwB3aCpxJbpjvp7+fckf8MBM1K/CxmiNe/TNl?= =?us-ascii?Q?QCP8/tCLz8jngPjbL1Lnazyqzyv1aiPOYXoq/cujulFFu2+96CtkHBZNcMeC?= =?us-ascii?Q?sOQqwmugASli2zhRCFRcQCYZewBkdDsD9ECSIc0S9LuxlJ4JogEJZjznK8O+?= =?us-ascii?Q?zqSjb4YGVIpoei91OkM2ozCw7xMZOaQHM25P+7xdSgV6IiaS2S4vvE6eIXhJ?= =?us-ascii?Q?BzLHebLEOTZ8+/0PlY0lNtf9nazWDt3S47ytzNk4zOYp2WIdltMdXVNTc6F4?= =?us-ascii?Q?AfrvuYWdbX5LrOT49dcNJtR1kysd4jqNuykClpa8Fhid0Ag7L9OchpFuNVnx?= =?us-ascii?Q?nG3QyxEoR1KNcQEgodsseNh6vPeiT/eHXiOO1oSInIoKNSciBC1GKIB+sQjZ?= =?us-ascii?Q?VNzGqC+oANf42kKoMa1jPypBJ6M0FKSi6XH9mZZZ2A1+vg7spW68eAsgVldq?= =?us-ascii?Q?+xS1jM9sN5bwzvwGm7srL/WGv9YGIVu1SVuAbtGR3FYYb3pbjqsNT3xiD+E2?= =?us-ascii?Q?R+ExM9QaJmtTAh2XxL+woqyS8ECiqDPSJcTOu7BUr2KuEY0mcBwVA4GItipI?= =?us-ascii?Q?lgsyGLou67AuFJFphqbIw1sOCPaU3Ty5D9zCtXMaaQ01hZdAFwNx7Ie0Rcw4?= =?us-ascii?Q?buVvDn5/Hj8hZLjyGVAg/s3VWyAzDTaEXHE0B31zdNLAc7+tLWKepMheWxTH?= =?us-ascii?Q?uNabENryx1nesvd5RN8bILboPME3N7f81gWpSNqFvhUTGI9x/NfkB3xue8x9?= =?us-ascii?Q?OZgEK6MFjw7lHiVPU9adA25dRjOpg48VnDqUE/uRP6jC/i+DcwTT3bwIC5S8?= =?us-ascii?Q?zZq1WvSVfTDtnmmE0PT1Qp1PYXJpeg+RZ34oST7RmHHTp9oU/IlD2G3YeJm3?= =?us-ascii?Q?eW9Vjttp+gv/CDP7Nq2ZPP5NLy2XB7ansbhkATo8B1aOKA9RB/vEMGiG3Btl?= =?us-ascii?Q?Zr4unuNufGHoBH9p07C+HQpCDVJuoebd9c3BdPpRQySwgOLxDPgZgmi9eLQ8?= =?us-ascii?Q?ctKhqVETlb/Pf+9VxN96gI7Ss9nAECg2QC4+VsyNChYvlXU3At5WidJEssKT?= =?us-ascii?Q?Cn3u5qrXfAnvoKRF1V+hET4fiVK7S4zDnxsXrd9t?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: fb2177fd-61a5-4501-c3d1-08dc91c75beb X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:20.9806 (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: sl6UUNJIffsibSsDF/qSWGj1gWDuejm2Abezcu5VHfOP4JtBjGyUyTQ4NNB4rKHnJyRj3Bye0Bcm3FfBmPvt4A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR04MB8135 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/sta_tx.c | 215 ++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sta_tx.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_tx.c b/drivers/net/wirele= ss/nxp/nxpwifi/sta_tx.c new file mode 100644 index 000000000000..8fb3a146552d --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_tx.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station TX data handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" + +/* This function fills the TxPD for tx packets. + * + * The Tx buffer received by this function should already have the + * header space allocated for TxPD. + * + * This function inserts the TxPD in between interface header and actual + * data and adjusts the buffer pointers accordingly. + * + * The following TxPD fields are set by this function, as required - + * - BSS number + * - Tx packet length and offset + * - Priority + * - Packet delay + * - Priority specific Tx control + * - Flags + */ +void nxpwifi_process_sta_txpd(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct txpd *local_tx_pd; + struct nxpwifi_txinfo *tx_info =3D NXPWIFI_SKB_TXCB(skb); + unsigned int pad; + u16 pkt_type, pkt_length, pkt_offset; + int hroom =3D adapter->intf_hdr_len; + u32 tx_control; + + pkt_type =3D nxpwifi_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; + + pad =3D ((uintptr_t)skb->data - (sizeof(*local_tx_pd) + hroom)) & + (NXPWIFI_DMA_ALIGN_SZ - 1); + skb_push(skb, sizeof(*local_tx_pd) + pad); + + local_tx_pd =3D (struct txpd *)skb->data; + memset(local_tx_pd, 0, sizeof(struct txpd)); + local_tx_pd->bss_num =3D priv->bss_num; + local_tx_pd->bss_type =3D priv->bss_type; + + pkt_length =3D (u16)(skb->len - (sizeof(struct txpd) + pad)); + if (pkt_type =3D=3D PKT_TYPE_MGMT) + pkt_length -=3D NXPWIFI_MGMT_FRAME_HEADER_SIZE; + local_tx_pd->tx_pkt_length =3D cpu_to_le16(pkt_length); + + local_tx_pd->priority =3D (u8)skb->priority; + local_tx_pd->pkt_delay_2ms =3D + nxpwifi_wmm_compute_drv_pkt_delay(priv, skb); + + if (tx_info->flags & NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS || + tx_info->flags & NXPWIFI_BUF_FLAG_ACTION_TX_STATUS) { + local_tx_pd->tx_token_id =3D tx_info->ack_frame_id; + local_tx_pd->flags |=3D NXPWIFI_TXPD_FLAGS_REQ_TX_STATUS; + } + + if (local_tx_pd->priority < + ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) { + /* Set the priority specific tx_control field, setting of 0 will + * cause the default value to be used later in this function + */ + tx_control =3D + priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd->priority]; + local_tx_pd->tx_control =3D cpu_to_le32(tx_control); + } + + if (adapter->pps_uapsd_mode) { + if (nxpwifi_check_last_packet_indication(priv)) { + adapter->tx_lock_flag =3D true; + local_tx_pd->flags =3D + NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET; + } + } + + /* Offset of actual data */ + pkt_offset =3D sizeof(struct txpd) + pad; + if (pkt_type =3D=3D PKT_TYPE_MGMT) { + /* Set the packet type and add header for management frame */ + local_tx_pd->tx_pkt_type =3D cpu_to_le16(pkt_type); + pkt_offset +=3D NXPWIFI_MGMT_FRAME_HEADER_SIZE; + } + + local_tx_pd->tx_pkt_offset =3D cpu_to_le16(pkt_offset); + + /* make space for adapter->intf_hdr_len */ + skb_push(skb, hroom); + + if (!local_tx_pd->tx_control) + /* TxCtrl set by user or default */ + local_tx_pd->tx_control =3D cpu_to_le32(priv->pkt_tx_ctrl); +} + +/* This function tells firmware to send a NULL data packet. + * + * The function creates a NULL data packet with TxPD and sends to the + * firmware for transmission, with highest priority setting. + */ +int nxpwifi_send_null_packet(struct nxpwifi_private *priv, u8 flags) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct txpd *local_tx_pd; + struct nxpwifi_tx_param tx_param; +/* sizeof(struct txpd) + Interface specific header */ +#define NULL_PACKET_HDR 64 + u32 data_len =3D NULL_PACKET_HDR; + struct sk_buff *skb; + int ret; + struct nxpwifi_txinfo *tx_info =3D NULL; + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) + return -1; + + if (!priv->media_connected) + return -1; + + if (adapter->data_sent) + return -1; + + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + return -1; + + skb =3D dev_alloc_skb(data_len); + if (!skb) + return -1; + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num =3D priv->bss_num; + tx_info->bss_type =3D priv->bss_type; + tx_info->pkt_len =3D data_len - + (sizeof(struct txpd) + adapter->intf_hdr_len); + skb_reserve(skb, sizeof(struct txpd) + adapter->intf_hdr_len); + skb_push(skb, sizeof(struct txpd)); + + local_tx_pd =3D (struct txpd *)skb->data; + local_tx_pd->tx_control =3D cpu_to_le32(priv->pkt_tx_ctrl); + local_tx_pd->flags =3D flags; + local_tx_pd->priority =3D WMM_HIGHEST_PRIORITY; + local_tx_pd->tx_pkt_offset =3D cpu_to_le16(sizeof(struct txpd)); + local_tx_pd->bss_num =3D priv->bss_num; + local_tx_pd->bss_type =3D priv->bss_type; + + skb_push(skb, adapter->intf_hdr_len); + tx_param.next_pkt_len =3D 0; + ret =3D adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_DATA, + skb, &tx_param); + + switch (ret) { + case -EBUSY: + dev_kfree_skb_any(skb); + nxpwifi_dbg(adapter, ERROR, + "%s: host_to_card failed: ret=3D%d\n", + __func__, ret); + adapter->dbg.num_tx_host_to_card_failure++; + break; + case -1: + dev_kfree_skb_any(skb); + nxpwifi_dbg(adapter, ERROR, + "%s: host_to_card failed: ret=3D%d\n", + __func__, ret); + adapter->dbg.num_tx_host_to_card_failure++; + break; + case 0: + dev_kfree_skb_any(skb); + nxpwifi_dbg(adapter, DATA, + "data: %s: host_to_card succeeded\n", + __func__); + adapter->tx_lock_flag =3D true; + break; + case -EINPROGRESS: + adapter->tx_lock_flag =3D true; + break; + default: + break; + } + + return ret; +} + +/* This function checks if we need to send last packet indication. + */ +u8 +nxpwifi_check_last_packet_indication(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u8 ret =3D false; + + if (!adapter->sleep_period.period) + return ret; + if (nxpwifi_wmm_lists_empty(adapter)) + ret =3D true; + + if (ret && !adapter->cmd_sent && !adapter->curr_cmd && + !is_command_pending(adapter)) { + adapter->delay_null_pkt =3D false; + ret =3D true; + } else { + ret =3D false; + adapter->delay_null_pkt =3D true; + } + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96103176AD8; Fri, 21 Jun 2024 07:54:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956470; cv=fail; b=f8Bm84yfJTxW9adsxTQJkOCoqyELlonbvAQBNTAfiAYEIWbqigsCttnJzYTV+Ig+D9DUP7+riK/TUz8gjF/IAG6XdLy9Qomg5OO0O+bqRc+OrE6FU/jpnWpiy7o4E55fcellpzHSsE7rf16ivbxXqF/BkGQAFVjovMl7zBdMUUw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956470; c=relaxed/simple; bh=atFQDYbzT2WJ/LTP1cKQpuzTxVuvbeo5mjzghx9wblg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=POO6nfJvO4lhC29CZ956oyBcws9TbDb1/hD2gnJGGL4Ann7XjC3Aai5l9NZe0i02jH0ml484WHRK8b2v/s75f8F3kYwJjcCdXFUMiwWybBIIaBBTPJpactCK/C3qcqjNSGf2V2N9T2EHp6zFVeug1H5T2TaQlwwic+CzvvlIMr8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=VxaWSuFz; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="VxaWSuFz" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YuRy/wvSQsC4ASaJ7AxU0idekuPBtrfJGp3feVqkMdlRxEA+6OJT9OWfs7xxeqorzbKbWKrj7g6n9gNiL9atjxNVE1HURtuITYdwXoZzZaRVw412q0MW877FfEvoJ/jNXQFPerN/dMdEdQ09tCcKpbdUJ9b/zfNfVxL1itb+e2eHsi2T/BnyFo+wMaWbgm02sZWzucGGO2JHpu3fbDOnAdQSgnZudGt46IE/OquYUVTUcVgggcvRz8cu0sDH0WQzbUmsZPRu0wW5Y+Q7QYo4WvoWi2vNW8NB9OHbEiCYBI+zjO3iqrFIyNl5+xgt+300QrF0igUPWLGSBzcD7RRKCw== 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=qCoihKoL4wgcCd+is65bR+RLnTbXcmw3SKv5HMMmFCs=; b=khoHYcQh9Omec1zQ5xVMrsgc2d4USDzfAyFau5tGIKYo6W9fGL0njKqyG61GPSRMUPf8xOR3sGnZqP7IcFha5QMBGhC6bCXVl+druK9g+p2dnruO8DS1P4JxVLTxX9vki/etTu15bpVGP/fHoj99ELhaFMIXPpdRWsWfBlKGMutZ/Pqw8+rXoJC9kMGBJhxuTkpEcIDybgYJAH2jsbUFQweYZVfIdGAftjIxvuiPfptXVGUIdION65W+zFQTLzbVZmsH0BnFkmQd0QoFO6ssG5cyB6IDCIf4i4HY7OV1MpT3ZGtRGWpiRbO8v/7XSuKMxYpBMD8iuAqYV7AQ0qcFvQ== 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=qCoihKoL4wgcCd+is65bR+RLnTbXcmw3SKv5HMMmFCs=; b=VxaWSuFzfKlr+K2Rgyx1YU978wZ2zPiRmTNxZDWISIYB78JIOOOHrMRD4lQTQGJef3oYKTbl87gjHKQtuVBl8dD0UMByGh+of+QdUmEQh7g7Jt/xt0gJxHa8Q8MvtCEyUXAbPbuVapk8SbaM3xU8OFJftTo2Bu5c9NiAhea0z3U= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:24 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:24 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 33/43] wifi: nxpwifi: add txrx.c Date: Fri, 21 Jun 2024 15:51:58 +0800 Message-Id: <20240621075208.513497-34-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 7a289788-a376-4fd9-0328-08dc91c75de8 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?jbHYW8s36awGKSuGaZdS/02QNyQFDVaPGCL6VCfrBjlkoMi6B/iaz99wTyGi?= =?us-ascii?Q?aguhRjIBjpxV2ADTokf0kmthBT7h3uh83dFghFC3RbfyDXuO2qp0CFD1avoW?= =?us-ascii?Q?+g9bpCaYtV64SB+9/kLHsbFCSS9JyeJGLeqstLxakoQrHQFqaUtCbIg3NpW5?= =?us-ascii?Q?h9QORRU82wS3i1NI2qBMGsWBvgc+ZyrezGJK6HmOYn3NpfBkwiVUwLihgfW0?= =?us-ascii?Q?g+87SFprxvmGknzK/wwO1jNt+oYd04R6pPhgO7hADaDcx1iO9tQ45I0q+64u?= =?us-ascii?Q?dYRlYcMt/YWF1feAJgwLJa1zj6A+f6YuUQ0gu0vv3btVougT68aaxq20L51w?= =?us-ascii?Q?FTpIEtYxVcbhvIfzV0zYMlWec9yS0X6Fcm+XmjoTgcBiDhmoFPZEeJPW4/qd?= =?us-ascii?Q?KYfgXbvs6+RgOTFxQ2Q9Dk0Ox4uHUOi4Pt434DVZvZyyLcWWsvInBk/sPHEq?= =?us-ascii?Q?1EfatqvgMvUdm8nt4YzzO34jCPHl+PT74X+q2+/pgdKkoEiz93NiaO9XYSmK?= =?us-ascii?Q?YF0FK2WuN5dIzCdfQPzmVWtfy+abSXsv99pCW2p/gYsHemsSVSIh+HAP+9bR?= =?us-ascii?Q?FlxbG16feI+ZqMLZJgqi7WDLWHUqshb4hIzpz1LqM3y08x4H2PoA/eqRN1f8?= =?us-ascii?Q?1IhqYjwz7cCLvJAn00vnFD+YV99ANaY/wgkMz+i0eWU9RnjCFTJa8PNIrm/U?= =?us-ascii?Q?3yrmbQ9M22geZstwD4BgBNnuzphPc5tYm7733o3UgLt96cJlRPGZ4TjiE9gw?= =?us-ascii?Q?aTgnEcy0C/5vdmAaZa5GxOx/UGFzaQB7Zgh1In47k288lpPzxovaT7ftcqcY?= =?us-ascii?Q?XwqvxkNqynJy/FRpdk/3ZqtEWckCQaJWvTZ4O28ybT81Yls/WyhTIRb5/Npj?= =?us-ascii?Q?ff+VhHt17Pw4kebxUDCGVSgWLzY4GMxJFC8QOvG0OTwlqypkecNSm9lsMU+Q?= =?us-ascii?Q?kjunlDTLmJn2HNuddUtnRs1APlrNYSi7rLrAfpsRHBQe13dqX6Gp5+94k9Ci?= =?us-ascii?Q?bT2GZ+GF4OyUw6CBb6rn0JPpculYPID4hTRp3eVoToY2IN5Vnvpm3UgEQXJ6?= =?us-ascii?Q?GP+dSxdhMx0j+sHqzNGaxlMRk+6s0Cyjq2amw/2INytAr24p5mKTcz4FVb+i?= =?us-ascii?Q?aPcnAYnHcSl0fjbITs4xEXB8avliQu2rSt5HqZAvWHNI8xAQbq/qO6NOpPzC?= =?us-ascii?Q?9dxfIf/Qz/MuclcIDiLzP07UG65GBwLW6W/3M6GTq8jHmYQSsZRlJidsr0Gp?= =?us-ascii?Q?wGSUGE2fqaeE1ZTIlO4jJzkiWzSQE9XlCzMG57xXEFsCUWzrYtjDFOQnR4g3?= =?us-ascii?Q?B7Exv9ipguA5k9GAtwcO7ui08oH92b+RJO9BcWmMajFkv9QGd46EztAzh1JM?= =?us-ascii?Q?+j2vQJc=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?0Qg2YvJ/05YItBtFc7NHcAIts+3eiSGUBLQTP3AMbGd7VTw68WkFOzU8leP5?= =?us-ascii?Q?k/n70Kc8G1MWWVh0IPOF37uMf25fwt0wR1MqTQIcrpf502j6iSqypCzd9mWV?= =?us-ascii?Q?RU97QrBvqxvuxu9eYyIWgr8ufzguXLNhKqjgfAEmcKMdee8zHV2dRMUjCVJ2?= =?us-ascii?Q?1PAbIFARaIx00qfhnkOCBS06o22uI83NDacS/P3rEWuIaLyteyvBbfKt29R2?= =?us-ascii?Q?fekwdprYE5Q3XFfObK8uYqBsDy0Q00QWo1tUkZt2/MCnryREA9ChohyfrIsP?= =?us-ascii?Q?NAlCwMzJOcM57brYKvbuxvtmWCF9npYbCgBAgt2Zr/bO83T7GKpnJjDFzrYz?= =?us-ascii?Q?AMpE5+qlgtYLPWdyUCUQF/diNO6WVduAFbzC5KEPXwkv/RIYB6YC9W5RaM4f?= =?us-ascii?Q?CbxTo5WtywaP9Zu9YGQuA8E5sEuI37R+PILXbc2O5XGO4+sp1AFLwU9eoURY?= =?us-ascii?Q?lL9rH7wSKYpJCcyUl8nRrUgscLcgswhS0rKu1N5WgTxFHm8cidyspAzIp71e?= =?us-ascii?Q?QYpEjwGwYVRavC16RPLwy7QOiQHUDcquPCrTRnORLLc0K5n47rPiGngM0lFH?= =?us-ascii?Q?zGBhYNkfgckIxomJNRoqjPZa+t8ed6yNLO/y9PoFeHt3XQ/kb1FO9f9mTlVf?= =?us-ascii?Q?UNso2fZM+S+iMROBAr/aeL2wP/8CjCgqZ2scGq4Ig3LHFQDNIJ3zGj3jc+n4?= =?us-ascii?Q?iD9VsrdOoMzDlPC6xoV6S53eSt5ws9ocUSM+17LoDSZuNzoVOeF5nvZHE9nq?= =?us-ascii?Q?jUQMrzC2onGyNdKYm2vIZwcpTA/LkAudZWhm7E9OXLunP4NalCP0IvRY6m+Q?= =?us-ascii?Q?WvbQdGfksWtSXpGEoFP+ulWprlIcmyPhKeJp4RDid9E5JsOuMw5n9aVh0bWe?= =?us-ascii?Q?InoTqFHPb6ZuhwbrfGPrEfKYKaEjAwWbTxpBDBOCqbMW6hoTnLPugH0rNL30?= =?us-ascii?Q?+DsNQsEfHHQA2wuKfwPwl1vj1yWBCEk5UnaSMpg0YPk+AvG5WEZVuRCUdMtk?= =?us-ascii?Q?hnvUAZdqjPINYrH/rxeDnNnl3W2sm47CFGMI1ApnSMlegBOWlFXLAUV+bGrr?= =?us-ascii?Q?ayAjUApZJKRrEUnQEBLkYarnaGPG8XdyqJTXpQNPs0C78vgKJF8jgX6E1CvI?= =?us-ascii?Q?mL37M9iApuIqmzFpIiklpq5ybjCGuHduxZ5AYbPaNm81uV3fCTHb9sr3mE6i?= =?us-ascii?Q?sXMNjgorSICMMYkWPDTW4XMlHAgTpZUkWsme9XPUogaTDVN/ZJnEnYR1Q5DO?= =?us-ascii?Q?8f4sgCceCnMolbnbk7UE/ISpIWszTKF8dr/A9GahskIIYi7eJLjy77pFSdji?= =?us-ascii?Q?XRRpadB7JGBV9Rs1n9L3WR08pQ7YBUI8KhDEK0cAMXr9af4hl+CtXrpnMzrd?= =?us-ascii?Q?+rBXDpf/PeFmLvqdh9Bcu1AnfQXyz1jmaRKTASZXCiKXEl1WWWeiuCvC1Y3i?= =?us-ascii?Q?c05/qJg8yNWTfq/Axo7b73wMTyaOyhTKanOClkKxq5OntqsdHzAbghID7l/G?= =?us-ascii?Q?6uD/fag7Socraz2eWH9nmEqRFfdv2xV6f3i1RbppRVNjKuraI+JZqQpL4hAA?= =?us-ascii?Q?81Li5WhZ7gvzc/xWIGgmBRHzodoFQa5DEsAiy94D?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7a289788-a376-4fd9-0328-08dc91c75de8 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:24.3377 (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: ALmTL25Oa0TvAQ/PfoQPHIvgd2K/dYyjyCeJ3ExYL5SN/BiPkTokPppjwm7Laa91Xr8qFcDwZyFdO/rf2txE5Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/txrx.c | 362 ++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/txrx.c diff --git a/drivers/net/wireless/nxp/nxpwifi/txrx.c b/drivers/net/wireless= /nxp/nxpwifi/txrx.c new file mode 100644 index 000000000000..3fe1cbc880e2 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/txrx.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: generic TX/RX data handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" + +/* This function processes the received buffer. + * + * Main responsibility of this function is to parse the RxPD to + * identify the correct interface this packet is headed for and + * forwarding it to the associated handling function, where the + * packet will be further processed and sent to kernel/upper layer + * if required. + */ +int nxpwifi_handle_rx_packet(struct nxpwifi_adapter *adapter, + struct sk_buff *skb) +{ + struct nxpwifi_private *priv =3D + nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + struct rxpd *local_rx_pd; + struct nxpwifi_rxinfo *rx_info =3D NXPWIFI_SKB_RXCB(skb); + int ret; + + local_rx_pd =3D (struct rxpd *)(skb->data); + /* Get the BSS number from rxpd, get corresponding priv */ + priv =3D nxpwifi_get_priv_by_id(adapter, local_rx_pd->bss_num & + BSS_NUM_MASK, local_rx_pd->bss_type); + if (!priv) + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + if (!priv) { + nxpwifi_dbg(adapter, ERROR, + "data: priv not found. Drop RX packet\n"); + dev_kfree_skb_any(skb); + return -1; + } + + nxpwifi_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data, + min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN)); + + memset(rx_info, 0, sizeof(*rx_info)); + rx_info->bss_num =3D priv->bss_num; + rx_info->bss_type =3D priv->bss_type; + + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP) + ret =3D nxpwifi_process_uap_rx_packet(priv, skb); + else + ret =3D nxpwifi_process_sta_rx_packet(priv, skb); + + return ret; +} +EXPORT_SYMBOL_GPL(nxpwifi_handle_rx_packet); + +/* This function sends a packet to device. + * + * It processes the packet to add the TxPD, checks condition and + * sends the processed packet to firmware for transmission. + * + * On successful completion, the function calls the completion callback + * and logs the time. + */ +int nxpwifi_process_tx(struct nxpwifi_private *priv, struct sk_buff *skb, + struct nxpwifi_tx_param *tx_param) +{ + int hroom, ret; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct txpd *local_tx_pd =3D NULL; + struct nxpwifi_sta_node *dest_node; + struct ethhdr *hdr =3D (void *)skb->data; + + if (unlikely(!skb->len || + skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN)) { + ret =3D -EINVAL; + goto out; + } + + hroom =3D adapter->intf_hdr_len; + + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP) { + dest_node =3D nxpwifi_get_sta_entry(priv, hdr->h_dest); + if (dest_node) { + dest_node->stats.tx_bytes +=3D skb->len; + dest_node->stats.tx_packets++; + } + + nxpwifi_process_uap_txpd(priv, skb); + } else { + nxpwifi_process_sta_txpd(priv, skb); + } + + if ((adapter->data_sent || adapter->tx_lock_flag)) { + skb_queue_tail(&adapter->tx_data_q, skb); + atomic_inc(&adapter->tx_queued); + return 0; + } + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) + local_tx_pd =3D (struct txpd *)(skb->data + hroom); + ret =3D adapter->if_ops.host_to_card(adapter, + NXPWIFI_TYPE_DATA, + skb, tx_param); + nxpwifi_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data, + min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN)); + +out: + switch (ret) { + case -ENOSR: + nxpwifi_dbg(adapter, DATA, "data: -ENOSR is returned\n"); + break; + case -EBUSY: + if ((GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) && + adapter->pps_uapsd_mode && adapter->tx_lock_flag) { + priv->adapter->tx_lock_flag =3D false; + if (local_tx_pd) + local_tx_pd->flags =3D 0; + } + nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); + break; + case -1: + nxpwifi_dbg(adapter, ERROR, + "nxpwifi_write_data_async failed: 0x%X\n", + ret); + adapter->dbg.num_tx_host_to_card_failure++; + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + case -EINPROGRESS: + break; + case -EINVAL: + nxpwifi_dbg(adapter, ERROR, + "malformed skb (length: %u, headroom: %u)\n", + skb->len, skb_headroom(skb)); + fallthrough; + case 0: + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + default: + break; + } + + return ret; +} + +static int nxpwifi_host_to_card(struct nxpwifi_adapter *adapter, + struct sk_buff *skb, + struct nxpwifi_tx_param *tx_param) +{ + struct txpd *local_tx_pd =3D NULL; + u8 *head_ptr =3D skb->data; + int ret =3D 0; + struct nxpwifi_private *priv; + struct nxpwifi_txinfo *tx_info; + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + priv =3D nxpwifi_get_priv_by_id(adapter, tx_info->bss_num, + tx_info->bss_type); + if (!priv) { + nxpwifi_dbg(adapter, ERROR, + "data: priv not found. Drop TX packet\n"); + adapter->dbg.num_tx_host_to_card_failure++; + nxpwifi_write_data_complete(adapter, skb, 0, 0); + return ret; + } + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) + local_tx_pd =3D (struct txpd *)(head_ptr + adapter->intf_hdr_len); + + ret =3D adapter->if_ops.host_to_card(adapter, + NXPWIFI_TYPE_DATA, + skb, tx_param); + + switch (ret) { + case -ENOSR: + nxpwifi_dbg(adapter, ERROR, "data: -ENOSR is returned\n"); + break; + case -EBUSY: + if ((GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) && + adapter->pps_uapsd_mode && + adapter->tx_lock_flag) { + priv->adapter->tx_lock_flag =3D false; + if (local_tx_pd) + local_tx_pd->flags =3D 0; + } + skb_queue_head(&adapter->tx_data_q, skb); + if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT) + atomic_add(tx_info->aggr_num, &adapter->tx_queued); + else + atomic_inc(&adapter->tx_queued); + nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); + break; + case -1: + nxpwifi_dbg(adapter, ERROR, + "nxpwifi_write_data_async failed: 0x%X\n", ret); + adapter->dbg.num_tx_host_to_card_failure++; + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + case -EINPROGRESS: + break; + case 0: + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + default: + break; + } + return ret; +} + +static int +nxpwifi_dequeue_tx_queue(struct nxpwifi_adapter *adapter) +{ + struct sk_buff *skb, *skb_next; + struct nxpwifi_txinfo *tx_info; + struct nxpwifi_tx_param tx_param; + + skb =3D skb_dequeue(&adapter->tx_data_q); + if (!skb) + return -1; + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT) + atomic_sub(tx_info->aggr_num, &adapter->tx_queued); + else + atomic_dec(&adapter->tx_queued); + + if (!skb_queue_empty(&adapter->tx_data_q)) + skb_next =3D skb_peek(&adapter->tx_data_q); + else + skb_next =3D NULL; + tx_param.next_pkt_len =3D ((skb_next) ? skb_next->len : 0); + if (!tx_param.next_pkt_len) { + if (!nxpwifi_wmm_lists_empty(adapter)) + tx_param.next_pkt_len =3D 1; + } + return nxpwifi_host_to_card(adapter, skb, &tx_param); +} + +void +nxpwifi_process_tx_queue(struct nxpwifi_adapter *adapter) +{ + do { + if (adapter->data_sent || adapter->tx_lock_flag) + break; + if (nxpwifi_dequeue_tx_queue(adapter)) + break; + } while (!skb_queue_empty(&adapter->tx_data_q)); +} + +/* Packet send completion callback handler. + * + * It either frees the buffer directly or forwards it to another + * completion callback which checks conditions, updates statistics, + * wakes up stalled traffic queue if required, and then frees the buffer. + */ +int nxpwifi_write_data_complete(struct nxpwifi_adapter *adapter, + struct sk_buff *skb, int aggr, int status) +{ + struct nxpwifi_private *priv; + struct nxpwifi_txinfo *tx_info; + struct netdev_queue *txq; + int index; + + if (!skb) + return 0; + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + priv =3D nxpwifi_get_priv_by_id(adapter, tx_info->bss_num, + tx_info->bss_type); + if (!priv) + goto done; + + nxpwifi_set_trans_start(priv->netdev); + + if (tx_info->flags & NXPWIFI_BUF_FLAG_BRIDGED_PKT) + atomic_dec_return(&adapter->pending_bridged_pkts); + + if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT) + goto done; + + if (!status) { + priv->stats.tx_packets++; + priv->stats.tx_bytes +=3D tx_info->pkt_len; + if (priv->tx_timeout_cnt) + priv->tx_timeout_cnt =3D 0; + } else { + priv->stats.tx_errors++; + } + + if (aggr) + /* For skb_aggr, do not wake up tx queue */ + goto done; + + atomic_dec(&adapter->tx_pending); + + index =3D nxpwifi_1d_to_wmm_queue[skb->priority]; + if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) { + txq =3D netdev_get_tx_queue(priv->netdev, index); + if (netif_tx_queue_stopped(txq)) { + netif_tx_wake_queue(txq); + nxpwifi_dbg(adapter, DATA, "wake queue: %d\n", index); + } + } +done: + dev_kfree_skb_any(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(nxpwifi_write_data_complete); + +void nxpwifi_parse_tx_status_event(struct nxpwifi_private *priv, + void *event_body) +{ + struct tx_status_event *tx_status =3D (void *)priv->adapter->event_body; + struct sk_buff *ack_skb; + struct nxpwifi_txinfo *tx_info; + + if (!tx_status->tx_token_id) + return; + + spin_lock_bh(&priv->ack_status_lock); + ack_skb =3D idr_remove(&priv->ack_status_frames, tx_status->tx_token_id); + spin_unlock_bh(&priv->ack_status_lock); + + if (ack_skb) { + tx_info =3D NXPWIFI_SKB_TXCB(ack_skb); + + if (tx_info->flags & NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS) { + /* consumes ack_skb */ + skb_complete_wifi_ack(ack_skb, !tx_status->status); + } else { + /* Remove broadcast address which was added by driver */ + memmove(ack_skb->data + + sizeof(struct ieee80211_hdr_3addr) + + NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16), + ack_skb->data + + sizeof(struct ieee80211_hdr_3addr) + + NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16) + + ETH_ALEN, ack_skb->len - + (sizeof(struct ieee80211_hdr_3addr) + + NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16) + + ETH_ALEN)); + ack_skb->len =3D ack_skb->len - ETH_ALEN; + /* Remove driver's proprietary header including 2 bytes + * of packet length and pass actual management frame buffer + * to cfg80211. + */ + cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie, + ack_skb->data + + NXPWIFI_MGMT_FRAME_HEADER_SIZE + + sizeof(u16), ack_skb->len - + (NXPWIFI_MGMT_FRAME_HEADER_SIZE + + sizeof(u16)), + !tx_status->status, GFP_ATOMIC); + dev_kfree_skb_any(ack_skb); + } + } +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D44C017838C; Fri, 21 Jun 2024 07:54:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956474; cv=fail; b=ayCo2huLAzKKNnY6B6TwJoxP/ZXJaatSiqmAuIddHzwJ7200bxKirl7Fj8WxaXPELbVY3MuMfm+STGD60uCFx6IciSbfiItCOFyx+a7lbnha6jOp1IO+M9K7p0Fhlj0W/+Dkaf5voRYUcwe3UlTf29otFVHEanrmFvd7Rxl3ong= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956474; c=relaxed/simple; bh=6QuIkFo1cJd1bS7PT7mZ+oNzgE9qCe9iKcW27NER4jg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=r2pLKDq+LOftpsw2SF59+WwIFNpvh3TCtNKG+GaWRilWpClXzsHLG/W31yT8OJlMKG6z8hFupJ4i9gFlU9M5V0TqlzOn4wHOkPeWCkPO4omdvnAeuYY2VslITYWvpTttqxrKe05I5LlnUC5Fv7aUC28NfTT67K5/SwfFwRZbCF4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=qZycNwAz; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="qZycNwAz" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=MZ8IM3VEVfzE+MlUPvfUbsCbt20hLeQwu9ROa4w5UIkjJxWl/hvLfQfa7RUw7rMbPZrnCTKkopoLOWsAnXZP3uqRLKDSmaoqqBhblu0o0zQbbd1nZOch7WJs9mYQzRKuA2ys0SMSLO4BR7wuGg5m1GMlK/6qv//3IvNIhmHldh/i5uEiLOqCT2nUBYK7/WGfJLesIgNZgXx9l8qFF5B7zQL9wnMh3qd7lz2lQw3MBkYMii2G/JLPdJhGnfGAZUv+6smDqdj7W4RzCsORAI31/CQZesQ7EzkGDpYqNdY/+Thj1Caj1Ke1IJOHozwWor2LKbiTJAKHhHSWlE5hk8G/cw== 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=Z3BtbZEJ7Bn2OSgT1LSWHaBCbF5/KsPLRfmINqAKq0E=; b=bRgBk5vYNg7eUqsyEuA+u/RAH1vneuM1v8veLjJm2+oQHvmvmHX8QY0PmSOXctoJSDxGZht82VzWYp8Ulfu2Z7lhV8IyP97jHHyxmxc01CWLZNB5P19xro4OZH+xGIkzsDwx29JD9iJl2pcvKqiKgWZ1ChjizJ3hRGVpQNI906KKF8sUeI0YgzRuVaQQzeuKjZwP9OdqqEsejI2zT2OvzzIfQXcegSuuK9dWMAaDpdtd45ARVXrq+fTobFH2qL0uFDsUjZs6iud7UDzWT5CS9ABVKepWdV1fpKeOxEgUMV0fIvOPniU+ZOgKb4cjKWQ/Lb4Nm9rtOVknn7hf9D8XPw== 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=Z3BtbZEJ7Bn2OSgT1LSWHaBCbF5/KsPLRfmINqAKq0E=; b=qZycNwAz5McvIb3BmY/FV1nUGa5M7jCpsjtyYo9eYDuHkn97xBKa5xYnZeMCNg9e3ZtCZWUDH5dphbWYggFd4TRPB+AY2bRoJTLZxQkObqy7Dzam8ZtnKZ18dKyuKVGJtl2A0DiC3rPi8R9IEhx5xSgApNHBSsOeHcjKeRDagQI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:27 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:27 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 34/43] wifi: nxpwifi: add uap_cmd.c Date: Fri, 21 Jun 2024 15:51:59 +0800 Message-Id: <20240621075208.513497-35-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 2b179bce-e213-4416-3c7d-08dc91c75fb7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?7vYQOTiPFyaWUah+ykyFfy4RlpFssqtVC6v8TEzWPwfYlNYvSCnIhYI9C8+7?= =?us-ascii?Q?OkkTOiomKpGtDyoOkKk5juU6OHLtjS9YKGeXEzTXQ1S4vIFCO2AeGyrCAQXG?= =?us-ascii?Q?/W41jsbfKr9qat6/1Yk9Lq78Lu71N30BFU4PrhfBalCKZUuuryqW/YKYkeez?= =?us-ascii?Q?nQmT3+C5rtM9uwiZNAIwJegJYOdmD9HmMut1ne/OuFt+u8+TiZg5QwJN8Pif?= =?us-ascii?Q?475gJNYHCtTaJA1qU1BimqPbeV+YOH6ILRvwm8GcEGxmTDUoQNqqC0dOPkoK?= =?us-ascii?Q?WVo/1R0HrDOGCc6HSWdVOseuu4+tP8XNxPpwuJkfj1d0i4VNp6MiaWUX0W11?= =?us-ascii?Q?qhyRLlDJLJpmCAVAlNcIcpgcbPB5kyK0UfcN3qmcVn89J0WQ0tJDDielh6Fw?= =?us-ascii?Q?pxXDB62pmTReHSc3wgK+9F3ms8oF25uybN6nnKYAT+wTShTy2lkkj0x7MnHV?= =?us-ascii?Q?sxEb+RKJ4XTugesk9gd8r4K0cUuTrpgFnAK4f03JhZOr5g2wLJXALGd95b3T?= =?us-ascii?Q?6awhtE9juWPgdP7LVP3+f+0yvfs4mNYjSiZMgHE4hlR2KxC254wgo02XOQkj?= =?us-ascii?Q?UL2RPQNZ/rVRCZRPQIELluO0kNJYKkGRCyV83TiM+1lD2K1tzr85d0GG2QVP?= =?us-ascii?Q?SxuG1WWRgidoHIOrZ5Hq7wrjPXxv/nI478v/vPD1GO+l9532JdyAlWyyLrqo?= =?us-ascii?Q?OKjhdRIM3sY8VeWqJSrG8eSJ98nLKCVYudubTENPPLNlEgvK7fVp0Xh9lyNZ?= =?us-ascii?Q?BbIEGnu/9iBe83F171FoRqLz5SCH858L+ntuCsUWjBay0KaqGb6A7TSkjk5Y?= =?us-ascii?Q?O6p9QRKsUa6BoUuPQswqkWhGLJiuvpR5y6JNqILVJrI54xyrwYAueynAuE3e?= =?us-ascii?Q?5MUrLc+OQqn2oqEdVnqkdSokJjd2v8pWywkML7LNMD4wnRof/UPaLt7mEb02?= =?us-ascii?Q?1X4Slllb41Sc0iJe2T5GG3oE5WoVS1zZW7FSVBo1oSTjk251gdpK/cbW0xlQ?= =?us-ascii?Q?fGEw+PNXYRbPnVzFydCSyBI6x9jdT2+m0wmfteFFr5gr4f/Ws7irZeGbz0iU?= =?us-ascii?Q?Oalp4rKQR7UoIjraFJ9cHJGxTr5ah2D3g++glIWX3F0KcDIJ6FnpuUgkWxGK?= =?us-ascii?Q?PqML/HzNUhZuDKbbyDuZjPfJYZp5S11zQXQBYv5F/Fpm5aFRw0zSY9TAxKi8?= =?us-ascii?Q?tmYi6dTtMvklSa3zRBZUVnQCJwrxY+lXt4cfuWC9/KobHwxkkZGi7SLGJhtd?= =?us-ascii?Q?fQCW6lniOS4J2cpPPo73r+nJN2XtR+4c5KfslivTwJ0TqOlPnxHwZew7bfLB?= =?us-ascii?Q?tSOPjtr/lLMPh8iqTu+rIp7XqQ6LrMSWTBd/TqVv/HsBlhoVmdyDCbwuyVPP?= =?us-ascii?Q?+vs0Blw=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?iCb4qSIWkoJoQ7X4yU0DnxZGRK9jHv0KhKvdCk9u//cycnea+XWkFOROtNMf?= =?us-ascii?Q?1kLvtD1OYOmKN33Su9y5kmpOXscUwZZ0pozWkdMrln7HuB0WXuCPzMxjSPgJ?= =?us-ascii?Q?tvkACSKeYnwLhrMcTU3lfCRF4ZOsRw/XvoXRi7kKv4qh1osf5B8ytkgBVZa/?= =?us-ascii?Q?rbM26kAFcIRrTKoLPC9czn+P6BaaSd6WmlrqRZSAKCEI7flg/kV7R4Wl4uKQ?= =?us-ascii?Q?QEXPfKukhqh0ek1h9Sqv3Ry4VOXJUzCMJiTpzLSgDWcFck5z0r4frghqk0Wt?= =?us-ascii?Q?E5hZn0pHJuJL8mylGA8FXUk1XRunPcT/mw0vCF2bUJstJVLiZEdus1hbJt8f?= =?us-ascii?Q?UqGhQf8MX+9jKi+7Ne4ZEWJEdzMn7ZREaRt2wd1dl7Y4nE/EP0HUmfZrRi6B?= =?us-ascii?Q?AzgBoTFFUtct0Oeq/m6tnnIXJK+2npp9uSSa6ti13R1uZ7XE+az6DNxv+1hS?= =?us-ascii?Q?oh518JMLPA88H4iaGrMRUUcVEIA74LLJi8LIYuYBlTuGVPXY5/f3kq+Ag0U7?= =?us-ascii?Q?E6hi6UXBZyt5vHfS+bqSXNlX8TC9FMq/Qr3LVv0iqFA74kJDZfaRF/wgflKK?= =?us-ascii?Q?9Aod9HAKqp/K9vMOHHKWgG20j0doRj6gRLNz6hSCfvB0I06Tj4SM3I+evpKv?= =?us-ascii?Q?VeT7MQZUE+Lt9eTNwUROzGhECcix+wzlXApVLTkKFQX2BaAIK0JPA7teJn1r?= =?us-ascii?Q?OcA9J2W6gGdWd2WS4jlPQ25Cct+PY106+lAMhaDEkFkldA28wEYlKGwsiHol?= =?us-ascii?Q?m5Sn9unDvaOU2MA3tcmu4T0z2KliNue1Ibn3TEtZs/2VvZeQ0mqIt/MQHOC6?= =?us-ascii?Q?GsAnmH+0eL/iTToJtsy3BYGRbTczFXw7usda0t7ibpgxSQLRTuVyTUhC1c/w?= =?us-ascii?Q?6+Bve+yRwg1mNCK+TNG+pw0u0qhIOqHQvKHPdqMGzVnGy3JS/II8qpj3gd0Y?= =?us-ascii?Q?GFXNvdHi7RPUctCsaiUxO1LU2GFWc7H6+S/B0mf0bzzt0xpBrMEOzsaXvTzq?= =?us-ascii?Q?/Q2aErhl2PPuwqpetfMlg4AQtCb8OEvkR/i0nx6a7FOhQ0I1vof+auFwl8Qv?= =?us-ascii?Q?jC3VR57M4bPTlSFRZtmWEHjxA2RtBH6GfqJb3UIPvFqR3yO4OVXyfo1xCMB2?= =?us-ascii?Q?ssUMQuoihu9K28Jz/5oG2198LA/YldUUBWNzG2jKSvSr859KEoHTP8P239MI?= =?us-ascii?Q?IA4kz/yWwaRFrvGDaLKanh9V3ai8WVfOxG9jYwk7vPClVKTKfGxgX3KRUK+V?= =?us-ascii?Q?9/mcAjR65pGMl5Ut/7wW7guwFuy4N3oIe4jWtLErnTSdGfiVF5ECTE3gPuQ+?= =?us-ascii?Q?NTE+9anR2KJ3fffxccU/zectQ1NVPcuTJ5GMpMPR3u0PQ0MPbv2PKw89K5zP?= =?us-ascii?Q?sdjoc6F5Sm6UQBHnNl6Kdn4APZlLfAjr2mjH1t/0Mi3ZGaRpBV7s8t3iApS0?= =?us-ascii?Q?P0cJvqSbTp7RhDtOXzD7yQp3RQuNMgqUfrZD3cXtBnO76LzcLxv65afLHWrU?= =?us-ascii?Q?2bdFAO/nDfw6qrBNXtTs1DfJ7gtQ/9ElRx7DmlRM9WddaI0NGO9grkFTkovJ?= =?us-ascii?Q?mmrV2QxCqCja4EB/jvWkiH1EWJkYMUT698Rq8MZ0?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2b179bce-e213-4416-3c7d-08dc91c75fb7 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:27.6184 (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: JTqL6Fy6W7dQZR3iMUqfyohHcyj9hiE/Kwn7f1IQ9xUbUHd7A7Q9JKcfrXR8HxWlKDS5ngZbiJ0B8ob9sVuBdQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/uap_cmd.c | 1170 ++++++++++++++++++++ 1 file changed, 1170 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/uap_cmd.c diff --git a/drivers/net/wireless/nxp/nxpwifi/uap_cmd.c b/drivers/net/wirel= ess/nxp/nxpwifi/uap_cmd.c new file mode 100644 index 000000000000..ec89e8ba90fe --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/uap_cmd.c @@ -0,0 +1,1170 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: AP specific command handling + * + * Copyright 2011-2024 NXP + */ + +#include "main.h" +#include "cmdevt.h" +#include "11ac.h" +#include "11n.h" + +/* This function parses BSS related parameters from structure + * and prepares TLVs specific to WPA/WPA2 security. + * These TLVs are appended to command buffer. + */ +static void +nxpwifi_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size) +{ + struct host_cmd_tlv_pwk_cipher *pwk_cipher; + struct host_cmd_tlv_gwk_cipher *gwk_cipher; + struct host_cmd_tlv_passphrase *passphrase; + struct host_cmd_tlv_akmp *tlv_akmp; + struct nxpwifi_uap_bss_param *bss_cfg =3D cmd_buf; + u16 cmd_size =3D *param_size; + u8 *tlv =3D *tlv_buf; + + tlv_akmp =3D (struct host_cmd_tlv_akmp *)tlv; + tlv_akmp->header.type =3D cpu_to_le16(TLV_TYPE_UAP_AKMP); + tlv_akmp->header.len =3D cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - + sizeof(struct nxpwifi_ie_types_header)); + tlv_akmp->key_mgmt_operation =3D cpu_to_le16(bss_cfg->key_mgmt_operation); + tlv_akmp->key_mgmt =3D cpu_to_le16(bss_cfg->key_mgmt); + cmd_size +=3D sizeof(struct host_cmd_tlv_akmp); + tlv +=3D sizeof(struct host_cmd_tlv_akmp); + + if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) { + pwk_cipher =3D (struct host_cmd_tlv_pwk_cipher *)tlv; + pwk_cipher->header.type =3D cpu_to_le16(TLV_TYPE_PWK_CIPHER); + pwk_cipher->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - + sizeof(struct nxpwifi_ie_types_header)); + pwk_cipher->proto =3D cpu_to_le16(PROTOCOL_WPA); + pwk_cipher->cipher =3D bss_cfg->wpa_cfg.pairwise_cipher_wpa; + cmd_size +=3D sizeof(struct host_cmd_tlv_pwk_cipher); + tlv +=3D sizeof(struct host_cmd_tlv_pwk_cipher); + } + + if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) { + pwk_cipher =3D (struct host_cmd_tlv_pwk_cipher *)tlv; + pwk_cipher->header.type =3D cpu_to_le16(TLV_TYPE_PWK_CIPHER); + pwk_cipher->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - + sizeof(struct nxpwifi_ie_types_header)); + pwk_cipher->proto =3D cpu_to_le16(PROTOCOL_WPA2); + pwk_cipher->cipher =3D bss_cfg->wpa_cfg.pairwise_cipher_wpa2; + cmd_size +=3D sizeof(struct host_cmd_tlv_pwk_cipher); + tlv +=3D sizeof(struct host_cmd_tlv_pwk_cipher); + } + + if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { + gwk_cipher =3D (struct host_cmd_tlv_gwk_cipher *)tlv; + gwk_cipher->header.type =3D cpu_to_le16(TLV_TYPE_GWK_CIPHER); + gwk_cipher->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) - + sizeof(struct nxpwifi_ie_types_header)); + gwk_cipher->cipher =3D bss_cfg->wpa_cfg.group_cipher; + cmd_size +=3D sizeof(struct host_cmd_tlv_gwk_cipher); + tlv +=3D sizeof(struct host_cmd_tlv_gwk_cipher); + } + + if (bss_cfg->wpa_cfg.length) { + passphrase =3D (struct host_cmd_tlv_passphrase *)tlv; + passphrase->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); + passphrase->header.len =3D cpu_to_le16(bss_cfg->wpa_cfg.length); + memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase, + bss_cfg->wpa_cfg.length); + cmd_size +=3D sizeof(struct nxpwifi_ie_types_header) + + bss_cfg->wpa_cfg.length; + tlv +=3D sizeof(struct nxpwifi_ie_types_header) + + bss_cfg->wpa_cfg.length; + } + + *param_size =3D cmd_size; + *tlv_buf =3D tlv; +} + +/* This function parses BSS related parameters from structure + * and prepares TLVs specific to WEP encryption. + * These TLVs are appended to command buffer. + */ +static void +nxpwifi_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size) +{ + struct host_cmd_tlv_wep_key *wep_key; + u16 cmd_size =3D *param_size; + int i; + u8 *tlv =3D *tlv_buf; + struct nxpwifi_uap_bss_param *bss_cfg =3D cmd_buf; + + for (i =3D 0; i < NUM_WEP_KEYS; i++) { + if (bss_cfg->wep_cfg[i].length && + (bss_cfg->wep_cfg[i].length =3D=3D WLAN_KEY_LEN_WEP40 || + bss_cfg->wep_cfg[i].length =3D=3D WLAN_KEY_LEN_WEP104)) { + wep_key =3D (struct host_cmd_tlv_wep_key *)tlv; + wep_key->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); + wep_key->header.len =3D + cpu_to_le16(bss_cfg->wep_cfg[i].length + 2); + wep_key->key_index =3D bss_cfg->wep_cfg[i].key_index; + wep_key->is_default =3D bss_cfg->wep_cfg[i].is_default; + memcpy(wep_key->key, bss_cfg->wep_cfg[i].key, + bss_cfg->wep_cfg[i].length); + cmd_size +=3D sizeof(struct nxpwifi_ie_types_header) + 2 + + bss_cfg->wep_cfg[i].length; + tlv +=3D sizeof(struct nxpwifi_ie_types_header) + 2 + + bss_cfg->wep_cfg[i].length; + } + } + + *param_size =3D cmd_size; + *tlv_buf =3D tlv; +} + +/* This function parses BSS related parameters from structure + * and prepares TLVs. These TLVs are appended to command buffer. + */ +static int +nxpwifi_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) +{ + struct host_cmd_tlv_mac_addr *mac_tlv; + struct host_cmd_tlv_dtim_period *dtim_period; + struct host_cmd_tlv_beacon_period *beacon_period; + struct host_cmd_tlv_ssid *ssid; + struct host_cmd_tlv_bcast_ssid *bcast_ssid; + struct host_cmd_tlv_channel_band *chan_band; + struct host_cmd_tlv_frag_threshold *frag_threshold; + struct host_cmd_tlv_rts_threshold *rts_threshold; + struct host_cmd_tlv_retry_limit *retry_limit; + struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; + struct host_cmd_tlv_auth_type *auth_type; + struct host_cmd_tlv_rates *tlv_rates; + struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; + struct host_cmd_tlv_power_constraint *pwr_ct; + struct nxpwifi_ie_types_htcap *htcap; + struct nxpwifi_ie_types_wmmcap *wmm_cap; + struct nxpwifi_uap_bss_param *bss_cfg =3D cmd_buf; + int i; + u16 cmd_size =3D *param_size; + + mac_tlv =3D (struct host_cmd_tlv_mac_addr *)tlv; + mac_tlv->header.type =3D cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS); + mac_tlv->header.len =3D cpu_to_le16(ETH_ALEN); + memcpy(mac_tlv->mac_addr, bss_cfg->mac_addr, ETH_ALEN); + cmd_size +=3D sizeof(struct host_cmd_tlv_mac_addr); + tlv +=3D sizeof(struct host_cmd_tlv_mac_addr); + + if (bss_cfg->ssid.ssid_len) { + ssid =3D (struct host_cmd_tlv_ssid *)tlv; + ssid->header.type =3D cpu_to_le16(TLV_TYPE_UAP_SSID); + ssid->header.len =3D cpu_to_le16((u16)bss_cfg->ssid.ssid_len); + memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len); + cmd_size +=3D sizeof(struct nxpwifi_ie_types_header) + + bss_cfg->ssid.ssid_len; + tlv +=3D sizeof(struct nxpwifi_ie_types_header) + + bss_cfg->ssid.ssid_len; + + bcast_ssid =3D (struct host_cmd_tlv_bcast_ssid *)tlv; + bcast_ssid->header.type =3D cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID); + bcast_ssid->header.len =3D + cpu_to_le16(sizeof(bcast_ssid->bcast_ctl)); + bcast_ssid->bcast_ctl =3D bss_cfg->bcast_ssid_ctl; + cmd_size +=3D sizeof(struct host_cmd_tlv_bcast_ssid); + tlv +=3D sizeof(struct host_cmd_tlv_bcast_ssid); + } + if (bss_cfg->rates[0]) { + tlv_rates =3D (struct host_cmd_tlv_rates *)tlv; + tlv_rates->header.type =3D cpu_to_le16(TLV_TYPE_UAP_RATES); + + for (i =3D 0; i < NXPWIFI_SUPPORTED_RATES && bss_cfg->rates[i]; + i++) + tlv_rates->rates[i] =3D bss_cfg->rates[i]; + + tlv_rates->header.len =3D cpu_to_le16(i); + cmd_size +=3D sizeof(struct host_cmd_tlv_rates) + i; + tlv +=3D sizeof(struct host_cmd_tlv_rates) + i; + } + if (bss_cfg->channel && + (((bss_cfg->band_cfg & BIT(0)) =3D=3D BAND_CONFIG_BG && + bss_cfg->channel <=3D MAX_CHANNEL_BAND_BG) || + ((bss_cfg->band_cfg & BIT(0)) =3D=3D BAND_CONFIG_A && + bss_cfg->channel <=3D MAX_CHANNEL_BAND_A))) { + chan_band =3D (struct host_cmd_tlv_channel_band *)tlv; + chan_band->header.type =3D cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); + chan_band->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) - + sizeof(struct nxpwifi_ie_types_header)); + chan_band->band_config =3D bss_cfg->band_cfg; + chan_band->channel =3D bss_cfg->channel; + cmd_size +=3D sizeof(struct host_cmd_tlv_channel_band); + tlv +=3D sizeof(struct host_cmd_tlv_channel_band); + } + if (bss_cfg->beacon_period >=3D MIN_BEACON_PERIOD && + bss_cfg->beacon_period <=3D MAX_BEACON_PERIOD) { + beacon_period =3D (struct host_cmd_tlv_beacon_period *)tlv; + beacon_period->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); + beacon_period->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) - + sizeof(struct nxpwifi_ie_types_header)); + beacon_period->period =3D cpu_to_le16(bss_cfg->beacon_period); + cmd_size +=3D sizeof(struct host_cmd_tlv_beacon_period); + tlv +=3D sizeof(struct host_cmd_tlv_beacon_period); + } + if (bss_cfg->dtim_period >=3D MIN_DTIM_PERIOD && + bss_cfg->dtim_period <=3D MAX_DTIM_PERIOD) { + dtim_period =3D (struct host_cmd_tlv_dtim_period *)tlv; + dtim_period->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); + dtim_period->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) - + sizeof(struct nxpwifi_ie_types_header)); + dtim_period->period =3D bss_cfg->dtim_period; + cmd_size +=3D sizeof(struct host_cmd_tlv_dtim_period); + tlv +=3D sizeof(struct host_cmd_tlv_dtim_period); + } + if (bss_cfg->rts_threshold <=3D NXPWIFI_RTS_MAX_VALUE) { + rts_threshold =3D (struct host_cmd_tlv_rts_threshold *)tlv; + rts_threshold->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); + rts_threshold->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) - + sizeof(struct nxpwifi_ie_types_header)); + rts_threshold->rts_thr =3D cpu_to_le16(bss_cfg->rts_threshold); + cmd_size +=3D sizeof(struct host_cmd_tlv_frag_threshold); + tlv +=3D sizeof(struct host_cmd_tlv_frag_threshold); + } + if (bss_cfg->frag_threshold >=3D NXPWIFI_FRAG_MIN_VALUE && + bss_cfg->frag_threshold <=3D NXPWIFI_FRAG_MAX_VALUE) { + frag_threshold =3D (struct host_cmd_tlv_frag_threshold *)tlv; + frag_threshold->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); + frag_threshold->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) - + sizeof(struct nxpwifi_ie_types_header)); + frag_threshold->frag_thr =3D cpu_to_le16(bss_cfg->frag_threshold); + cmd_size +=3D sizeof(struct host_cmd_tlv_frag_threshold); + tlv +=3D sizeof(struct host_cmd_tlv_frag_threshold); + } + if (bss_cfg->retry_limit <=3D NXPWIFI_RETRY_LIMIT) { + retry_limit =3D (struct host_cmd_tlv_retry_limit *)tlv; + retry_limit->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); + retry_limit->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) - + sizeof(struct nxpwifi_ie_types_header)); + retry_limit->limit =3D (u8)bss_cfg->retry_limit; + cmd_size +=3D sizeof(struct host_cmd_tlv_retry_limit); + tlv +=3D sizeof(struct host_cmd_tlv_retry_limit); + } + if ((bss_cfg->protocol & PROTOCOL_WPA) || + (bss_cfg->protocol & PROTOCOL_WPA2) || + (bss_cfg->protocol & PROTOCOL_EAP)) + nxpwifi_uap_bss_wpa(&tlv, cmd_buf, &cmd_size); + else + nxpwifi_uap_bss_wep(&tlv, cmd_buf, &cmd_size); + + if (bss_cfg->auth_mode <=3D WLAN_AUTH_SHARED_KEY || + bss_cfg->auth_mode =3D=3D NXPWIFI_AUTH_MODE_AUTO) { + auth_type =3D (struct host_cmd_tlv_auth_type *)tlv; + auth_type->header.type =3D cpu_to_le16(TLV_TYPE_AUTH_TYPE); + auth_type->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) - + sizeof(struct nxpwifi_ie_types_header)); + auth_type->auth_type =3D (u8)bss_cfg->auth_mode; + auth_type->pwe_derivation =3D 0; + auth_type->transition_disable =3D 0; + cmd_size +=3D sizeof(struct host_cmd_tlv_auth_type); + tlv +=3D sizeof(struct host_cmd_tlv_auth_type); + } + if (bss_cfg->protocol) { + encrypt_protocol =3D (struct host_cmd_tlv_encrypt_protocol *)tlv; + encrypt_protocol->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL); + encrypt_protocol->header.len =3D + cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol) + - sizeof(struct nxpwifi_ie_types_header)); + encrypt_protocol->proto =3D cpu_to_le16(bss_cfg->protocol); + cmd_size +=3D sizeof(struct host_cmd_tlv_encrypt_protocol); + tlv +=3D sizeof(struct host_cmd_tlv_encrypt_protocol); + } + + if (bss_cfg->ht_cap.cap_info) { + htcap =3D (struct nxpwifi_ie_types_htcap *)tlv; + htcap->header.type =3D cpu_to_le16(WLAN_EID_HT_CAPABILITY); + htcap->header.len =3D + cpu_to_le16(sizeof(struct ieee80211_ht_cap)); + htcap->ht_cap.cap_info =3D bss_cfg->ht_cap.cap_info; + htcap->ht_cap.ampdu_params_info =3D + bss_cfg->ht_cap.ampdu_params_info; + memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs, + sizeof(struct ieee80211_mcs_info)); + htcap->ht_cap.extended_ht_cap_info =3D + bss_cfg->ht_cap.extended_ht_cap_info; + htcap->ht_cap.tx_BF_cap_info =3D bss_cfg->ht_cap.tx_BF_cap_info; + htcap->ht_cap.antenna_selection_info =3D + bss_cfg->ht_cap.antenna_selection_info; + cmd_size +=3D sizeof(struct nxpwifi_ie_types_htcap); + tlv +=3D sizeof(struct nxpwifi_ie_types_htcap); + } + + if (bss_cfg->wmm_info.qos_info !=3D 0xFF) { + wmm_cap =3D (struct nxpwifi_ie_types_wmmcap *)tlv; + wmm_cap->header.type =3D cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC); + wmm_cap->header.len =3D cpu_to_le16(sizeof(wmm_cap->wmm_info)); + memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info, + sizeof(wmm_cap->wmm_info)); + cmd_size +=3D sizeof(struct nxpwifi_ie_types_wmmcap); + tlv +=3D sizeof(struct nxpwifi_ie_types_wmmcap); + } + + if (bss_cfg->sta_ao_timer) { + ao_timer =3D (struct host_cmd_tlv_ageout_timer *)tlv; + ao_timer->header.type =3D cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); + ao_timer->header.len =3D cpu_to_le16(sizeof(*ao_timer) - + sizeof(struct nxpwifi_ie_types_header)); + ao_timer->sta_ao_timer =3D cpu_to_le32(bss_cfg->sta_ao_timer); + cmd_size +=3D sizeof(*ao_timer); + tlv +=3D sizeof(*ao_timer); + } + + if (bss_cfg->power_constraint) { + pwr_ct =3D (void *)tlv; + pwr_ct->header.type =3D cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT); + pwr_ct->header.len =3D cpu_to_le16(sizeof(u8)); + pwr_ct->constraint =3D bss_cfg->power_constraint; + cmd_size +=3D sizeof(*pwr_ct); + tlv +=3D sizeof(*pwr_ct); + } + + if (bss_cfg->ps_sta_ao_timer) { + ps_ao_timer =3D (struct host_cmd_tlv_ageout_timer *)tlv; + ps_ao_timer->header.type =3D + cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER); + ps_ao_timer->header.len =3D cpu_to_le16(sizeof(*ps_ao_timer) - + sizeof(struct nxpwifi_ie_types_header)); + ps_ao_timer->sta_ao_timer =3D + cpu_to_le32(bss_cfg->ps_sta_ao_timer); + cmd_size +=3D sizeof(*ps_ao_timer); + tlv +=3D sizeof(*ps_ao_timer); + } + + *param_size =3D cmd_size; + + return 0; +} + +/* This function parses custom IEs from IE list and prepares command buffe= r */ +static int nxpwifi_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_s= ize) +{ + struct nxpwifi_ie_list *ap_ie =3D cmd_buf; + struct nxpwifi_ie_types_header *tlv_ie =3D (void *)tlv; + + if (!ap_ie || !ap_ie->len) + return -1; + + *ie_size +=3D le16_to_cpu(ap_ie->len) + + sizeof(struct nxpwifi_ie_types_header); + + tlv_ie->type =3D cpu_to_le16(TLV_TYPE_MGMT_IE); + tlv_ie->len =3D ap_ie->len; + tlv +=3D sizeof(struct nxpwifi_ie_types_header); + + 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 + */ +static int +nxpwifi_cmd_uap_sys_config(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + u8 *tlv; + u16 cmd_size, param_size, ie_size; + struct host_cmd_ds_sys_config *sys_cfg; + + cmd->command =3D cpu_to_le16(HOST_CMD_UAP_SYS_CONFIG); + cmd_size =3D (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN); + sys_cfg =3D &cmd->params.uap_sys_config; + sys_cfg->action =3D cpu_to_le16(cmd_action); + tlv =3D sys_cfg->tlv; + + switch (cmd_type) { + case UAP_BSS_PARAMS_I: + param_size =3D cmd_size; + if (nxpwifi_uap_bss_param_prepare(tlv, data_buf, ¶m_size)) + return -1; + cmd->size =3D cpu_to_le16(param_size); + break; + case UAP_CUSTOM_IE_I: + ie_size =3D cmd_size; + if (nxpwifi_uap_custom_ie_prepare(tlv, data_buf, &ie_size)) + return -1; + cmd->size =3D cpu_to_le16(ie_size); + break; + default: + return -1; + } + + return 0; +} + +static int +nxpwifi_cmd_uap_bss_start(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct nxpwifi_ie_types_host_mlme *tlv; + int size; + + cmd->command =3D cpu_to_le16(HOST_CMD_UAP_BSS_START); + size =3D S_DS_GEN; + + tlv =3D (struct nxpwifi_ie_types_host_mlme *)((u8 *)cmd + size); + tlv->header.type =3D cpu_to_le16(TLV_TYPE_HOST_MLME); + tlv->header.len =3D cpu_to_le16(sizeof(tlv->host_mlme)); + tlv->host_mlme =3D 1; + size +=3D sizeof(struct nxpwifi_ie_types_host_mlme); + + cmd->size =3D cpu_to_le16(size); + + return 0; +} + +static int +nxpwifi_ret_uap_bss_start(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->tx_lock_flag =3D false; + adapter->pps_uapsd_mode =3D false; + adapter->delay_null_pkt =3D false; + priv->bss_started =3D 1; + + return 0; +} + +static int +nxpwifi_ret_uap_bss_stop(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + priv->bss_started =3D 0; + + return 0; +} + +static int +nxpwifi_ret_apcmd_sta_list(struct nxpwifi_private *priv, + struct host_cmd_ds_command *resp, + u16 cmdresp_no, + void *data_buf) +{ + struct host_cmd_ds_sta_list *sta_list =3D + &resp->params.sta_list; + struct nxpwifi_ie_types_sta_info *sta_info =3D (void *)&sta_list->tlv; + int i; + struct nxpwifi_sta_node *sta_node; + + for (i =3D 0; i < (le16_to_cpu(sta_list->sta_count)); i++) { + sta_node =3D nxpwifi_get_sta_entry(priv, sta_info->mac); + if (unlikely(!sta_node)) + continue; + + sta_node->stats.rssi =3D sta_info->rssi; + sta_info++; + } + + return 0; +} + +/* This function prepares AP specific deauth command with mac supplied in + * function parameter. + */ +static int nxpwifi_cmd_uap_sta_deauth(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_sta_deauth *sta_deauth =3D &cmd->params.sta_deauth; + u8 *mac =3D (u8 *)data_buf; + + cmd->command =3D cpu_to_le16(HOST_CMD_UAP_STA_DEAUTH); + memcpy(sta_deauth->mac, mac, ETH_ALEN); + sta_deauth->reason =3D cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); + + cmd->size =3D cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) + + S_DS_GEN); + return 0; +} + +static int +nxpwifi_cmd_uap_chan_report_request(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + return nxpwifi_cmd_issue_chan_report_request(priv, cmd, data_buf); +} + +/* This function prepares AP specific add station command. + */ +static int +nxpwifi_cmd_uap_add_new_station(struct nxpwifi_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_no, void *data_buf, + u16 cmd_action, u32 cmd_type) +{ + struct host_cmd_ds_add_station *new_sta =3D &cmd->params.sta_info; + struct nxpwifi_sta_info *add_sta =3D (struct nxpwifi_sta_info *)data_buf; + struct station_parameters *params =3D add_sta->params; + struct nxpwifi_sta_node *sta_ptr; + u8 *pos, *cmd_end; + u16 tlv_len; + struct nxpwifi_ie_types_sta_flag *sta_flag; + int i; + + cmd->command =3D cpu_to_le16(HOST_CMD_ADD_NEW_STATION); + new_sta->action =3D cpu_to_le16(cmd_action); + cmd->size =3D sizeof(struct host_cmd_ds_add_station) + S_DS_GEN; + + if (cmd_action =3D=3D HOST_ACT_ADD_STA) + sta_ptr =3D nxpwifi_add_sta_entry(priv, add_sta->peer_mac); + else + sta_ptr =3D nxpwifi_get_sta_entry(priv, add_sta->peer_mac); + + if (!sta_ptr) + return -1; + + memcpy(new_sta->peer_mac, add_sta->peer_mac, ETH_ALEN); + + if (cmd_action =3D=3D HOST_ACT_REMOVE_STA) { + cmd->size =3D cpu_to_le16(cmd->size); + return 0; + } + + new_sta->aid =3D cpu_to_le16(params->aid); + new_sta->listen_interval =3D cpu_to_le32(params->listen_interval); + new_sta->cap_info =3D cpu_to_le16(params->capability); + + pos =3D new_sta->tlv; + cmd_end =3D (u8 *)cmd; + cmd_end +=3D (NXPWIFI_SIZE_OF_CMD_BUFFER - 1); + + if (params->sta_flags_set & NL80211_STA_FLAG_WME) + sta_ptr->is_wmm_enabled =3D 1; + sta_flag =3D (struct nxpwifi_ie_types_sta_flag *)pos; + sta_flag->header.type =3D cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS); + sta_flag->header.len =3D cpu_to_le16(sizeof(__le32)); + sta_flag->sta_flags =3D cpu_to_le32(params->sta_flags_set); + pos +=3D sizeof(struct nxpwifi_ie_types_sta_flag); + cmd->size +=3D sizeof(struct nxpwifi_ie_types_sta_flag); + + if (params->ext_capab_len) { + u8 *data =3D (u8 *)params->ext_capab; + u16 len =3D params->ext_capab_len; + + tlv_len =3D nxpwifi_append_data_tlv(WLAN_EID_EXT_CAPABILITY, + data, len, pos, cmd_end); + if (!tlv_len) + return -1; + pos +=3D tlv_len; + cmd->size +=3D tlv_len; + } + + if (params->link_sta_params.supported_rates_len) { + u8 *data =3D (u8 *)params->link_sta_params.supported_rates; + u16 len =3D params->link_sta_params.supported_rates_len; + + tlv_len =3D nxpwifi_append_data_tlv(WLAN_EID_SUPP_RATES, + data, len, pos, cmd_end); + if (!tlv_len) + return -1; + pos +=3D tlv_len; + cmd->size +=3D tlv_len; + } + + if (params->uapsd_queues || params->max_sp) { + u8 qos_capability =3D params->uapsd_queues | (params->max_sp << 5); + u8 *data =3D &qos_capability; + u16 len =3D sizeof(u8); + + tlv_len =3D nxpwifi_append_data_tlv(WLAN_EID_QOS_CAPA, + data, len, pos, cmd_end); + if (!tlv_len) + return -1; + pos +=3D tlv_len; + cmd->size +=3D tlv_len; + sta_ptr->is_wmm_enabled =3D 1; + } + + if (params->link_sta_params.ht_capa) { + u8 *data =3D (u8 *)params->link_sta_params.ht_capa; + u16 len =3D sizeof(struct ieee80211_ht_cap); + + tlv_len =3D nxpwifi_append_data_tlv(WLAN_EID_HT_CAPABILITY, + data, len, pos, cmd_end); + if (!tlv_len) + return -1; + pos +=3D tlv_len; + cmd->size +=3D tlv_len; + sta_ptr->is_11n_enabled =3D 1; + sta_ptr->max_amsdu =3D + le16_to_cpu(params->link_sta_params.ht_capa->cap_info) & + IEEE80211_HT_CAP_MAX_AMSDU ? + NXPWIFI_TX_DATA_BUF_SIZE_8K : + NXPWIFI_TX_DATA_BUF_SIZE_4K; + } + + if (params->link_sta_params.vht_capa) { + u8 *data =3D (u8 *)params->link_sta_params.vht_capa; + u16 len =3D sizeof(struct ieee80211_vht_cap); + + tlv_len =3D nxpwifi_append_data_tlv(WLAN_EID_VHT_CAPABILITY, + data, len, pos, cmd_end); + if (!tlv_len) + return -1; + pos +=3D tlv_len; + cmd->size +=3D tlv_len; + sta_ptr->is_11ac_enabled =3D 1; + } + + if (params->link_sta_params.opmode_notif_used) { + u8 *data =3D ¶ms->link_sta_params.opmode_notif; + u16 len =3D sizeof(u8); + + tlv_len =3D nxpwifi_append_data_tlv(WLAN_EID_OPMODE_NOTIF, + data, len, pos, cmd_end); + if (!tlv_len) + return -1; + pos +=3D tlv_len; + cmd->size +=3D tlv_len; + } + + for (i =3D 0; i < MAX_NUM_TID; i++) { + if (sta_ptr->is_11n_enabled) + sta_ptr->ampdu_sta[i] =3D + priv->aggr_prio_tbl[i].ampdu_user; + else + sta_ptr->ampdu_sta[i] =3D BA_STREAM_NOT_ALLOWED; + } + + memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); + + cmd->size =3D cpu_to_le16(cmd->size); + + return 0; +} + +static const struct nxpwifi_cmd_entry cmd_table_uap[] =3D { + {.cmd_no =3D HOST_CMD_APCMD_SYS_RESET, + .prepare_cmd =3D nxpwifi_cmd_fill_head_only, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_UAP_SYS_CONFIG, + .prepare_cmd =3D nxpwifi_cmd_uap_sys_config, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_UAP_BSS_START, + .prepare_cmd =3D nxpwifi_cmd_uap_bss_start, + .cmd_resp =3D nxpwifi_ret_uap_bss_start}, + {.cmd_no =3D HOST_CMD_UAP_BSS_STOP, + .prepare_cmd =3D nxpwifi_cmd_fill_head_only, + .cmd_resp =3D nxpwifi_ret_uap_bss_stop}, + {.cmd_no =3D HOST_CMD_APCMD_STA_LIST, + .prepare_cmd =3D nxpwifi_cmd_fill_head_only, + .cmd_resp =3D nxpwifi_ret_apcmd_sta_list}, + {.cmd_no =3D HOST_CMD_UAP_STA_DEAUTH, + .prepare_cmd =3D nxpwifi_cmd_uap_sta_deauth, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_CHAN_REPORT_REQUEST, + .prepare_cmd =3D nxpwifi_cmd_uap_chan_report_request, + .cmd_resp =3D NULL}, + {.cmd_no =3D HOST_CMD_ADD_NEW_STATION, + .prepare_cmd =3D nxpwifi_cmd_uap_add_new_station, + .cmd_resp =3D NULL}, +}; + +/* This function prepares the AP specific commands before sending them + * to the firmware. + * This is a generic function which calls specific command preparation + * routines based upon the command number. + */ +int nxpwifi_uap_prepare_cmd(struct nxpwifi_private *priv, + struct cmd_ctrl_node *cmd_node, + u16 cmd_action, u32 type) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 cmd_no =3D cmd_node->cmd_no; + struct host_cmd_ds_command *cmd =3D + (struct host_cmd_ds_command *)cmd_node->skb->data; + void *data_buf =3D cmd_node->data_buf; + int i, ret =3D -1; + + for (i =3D 0; i < ARRAY_SIZE(cmd_table_uap); i++) { + if (cmd_no =3D=3D cmd_table_uap[i].cmd_no) { + if (cmd_table_uap[i].prepare_cmd) + ret =3D cmd_table_uap[i].prepare_cmd(priv, cmd, + cmd_no, + data_buf, + cmd_action, + type); + cmd_node->cmd_resp =3D cmd_table_uap[i].cmd_resp; + break; + } + } + + if (i =3D=3D ARRAY_SIZE(cmd_table_uap)) + nxpwifi_dbg(adapter, ERROR, + "%s: unknown command: %#x\n", + __func__, cmd_no); + else + nxpwifi_dbg(adapter, EVENT, + "%s: command: %#x\n", + __func__, cmd_no); + + return ret; +} + +/* This function parses security related parameters from cfg80211_ap_setti= ngs + * and sets into FW understandable bss_config structure. + */ +int nxpwifi_set_secure_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_config, + struct cfg80211_ap_settings *params) +{ + int i; + struct nxpwifi_wep_key wep_key; + + if (!params->privacy) { + bss_config->protocol =3D PROTOCOL_NO_SECURITY; + bss_config->key_mgmt =3D KEY_MGMT_NONE; + bss_config->wpa_cfg.length =3D 0; + priv->sec_info.wep_enabled =3D 0; + priv->sec_info.wpa_enabled =3D 0; + priv->sec_info.wpa2_enabled =3D 0; + + return 0; + } + + switch (params->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + bss_config->auth_mode =3D WLAN_AUTH_OPEN; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + bss_config->auth_mode =3D WLAN_AUTH_SHARED_KEY; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + bss_config->auth_mode =3D WLAN_AUTH_LEAP; + break; + default: + bss_config->auth_mode =3D NXPWIFI_AUTH_MODE_AUTO; + break; + } + + bss_config->key_mgmt_operation |=3D KEY_MGMT_ON_HOST; + + for (i =3D 0; i < params->crypto.n_akm_suites; i++) { + switch (params->crypto.akm_suites[i]) { + case WLAN_AKM_SUITE_8021X: + if (params->crypto.wpa_versions & + NL80211_WPA_VERSION_1) { + bss_config->protocol =3D PROTOCOL_WPA; + bss_config->key_mgmt =3D KEY_MGMT_EAP; + } + if (params->crypto.wpa_versions & + NL80211_WPA_VERSION_2) { + bss_config->protocol |=3D PROTOCOL_WPA2; + bss_config->key_mgmt =3D KEY_MGMT_EAP; + } + break; + case WLAN_AKM_SUITE_PSK: + if (params->crypto.wpa_versions & + NL80211_WPA_VERSION_1) { + bss_config->protocol =3D PROTOCOL_WPA; + bss_config->key_mgmt =3D KEY_MGMT_PSK; + } + if (params->crypto.wpa_versions & + NL80211_WPA_VERSION_2) { + bss_config->protocol |=3D PROTOCOL_WPA2; + bss_config->key_mgmt =3D KEY_MGMT_PSK; + } + break; + case WLAN_AKM_SUITE_SAE: + bss_config->protocol =3D PROTOCOL_WPA2; + bss_config->key_mgmt =3D KEY_MGMT_SAE; + break; + case WLAN_AKM_SUITE_OWE: + bss_config->protocol =3D PROTOCOL_WPA2; + bss_config->key_mgmt =3D KEY_MGMT_OWE; + break; + default: + break; + } + } + for (i =3D 0; i < params->crypto.n_ciphers_pairwise; i++) { + switch (params->crypto.ciphers_pairwise[i]) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + break; + case WLAN_CIPHER_SUITE_TKIP: + if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) + bss_config->wpa_cfg.pairwise_cipher_wpa |=3D + CIPHER_TKIP; + if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) + bss_config->wpa_cfg.pairwise_cipher_wpa2 |=3D + CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) + bss_config->wpa_cfg.pairwise_cipher_wpa |=3D + CIPHER_AES_CCMP; + if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) + bss_config->wpa_cfg.pairwise_cipher_wpa2 |=3D + CIPHER_AES_CCMP; + break; + default: + break; + } + } + + switch (params->crypto.cipher_group) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + if (priv->sec_info.wep_enabled) { + bss_config->protocol =3D PROTOCOL_STATIC_WEP; + bss_config->key_mgmt =3D KEY_MGMT_NONE; + bss_config->wpa_cfg.length =3D 0; + + for (i =3D 0; i < NUM_WEP_KEYS; i++) { + wep_key =3D priv->wep_key[i]; + bss_config->wep_cfg[i].key_index =3D i; + + if (priv->wep_key_curr_index =3D=3D i) + bss_config->wep_cfg[i].is_default =3D 1; + else + bss_config->wep_cfg[i].is_default =3D 0; + + bss_config->wep_cfg[i].length =3D + wep_key.key_length; + memcpy(&bss_config->wep_cfg[i].key, + &wep_key.key_material, + wep_key.key_length); + } + } + break; + case WLAN_CIPHER_SUITE_TKIP: + bss_config->wpa_cfg.group_cipher =3D CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + bss_config->wpa_cfg.group_cipher =3D CIPHER_AES_CCMP; + break; + default: + break; + } + + return 0; +} + +/* This function updates 11n related parameters from IE and sets them into + * bss_config structure. + */ +void +nxpwifi_set_ht_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params) +{ + const u8 *ht_ie; + + if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) + return; + + ht_ie =3D cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, + params->beacon.tail_len); + if (ht_ie) { + memcpy(&bss_cfg->ht_cap, ht_ie + 2, + sizeof(struct ieee80211_ht_cap)); + if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap)) + bss_cfg->ht_cap.tx_BF_cap_info =3D + cpu_to_le32(NXPWIFI_DEF_11N_TX_BF_CAP); + priv->ap_11n_enabled =3D 1; + } else { + memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap)); + bss_cfg->ht_cap.cap_info =3D cpu_to_le16(NXPWIFI_DEF_HT_CAP); + bss_cfg->ht_cap.ampdu_params_info =3D NXPWIFI_DEF_AMPDU; + } +} + +/* This function updates 11ac related parameters from IE + * and sets them into bss_config structure. + */ +void nxpwifi_set_vht_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params) +{ + const u8 *vht_ie; + + vht_ie =3D cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail, + params->beacon.tail_len); + if (vht_ie) { + memcpy(&bss_cfg->vht_cap, vht_ie + 2, + sizeof(struct ieee80211_vht_cap)); + priv->ap_11ac_enabled =3D 1; + } else { + priv->ap_11ac_enabled =3D 0; + } +} + +/* This function updates 11ac related parameters from IE + * and sets them into bss_config structure. + */ +void nxpwifi_set_tpc_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params) +{ + const u8 *tpc_ie; + + tpc_ie =3D cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail, + params->beacon.tail_len); + if (tpc_ie) + bss_cfg->power_constraint =3D *(tpc_ie + 2); + else + bss_cfg->power_constraint =3D 0; +} + +/* Enable VHT only when cfg80211_ap_settings has VHT IE. + * Otherwise disable VHT. + */ +void nxpwifi_set_vht_width(struct nxpwifi_private *priv, + enum nl80211_chan_width width, + bool ap_11ac_enable) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_11ac_vht_cfg vht_cfg; + + vht_cfg.band_config =3D VHT_CFG_5GHZ; + vht_cfg.cap_info =3D adapter->hw_dot_11ac_dev_cap; + + if (!ap_11ac_enable) { + vht_cfg.mcs_tx_set =3D DISABLE_VHT_MCS_SET; + vht_cfg.mcs_rx_set =3D DISABLE_VHT_MCS_SET; + } else { + vht_cfg.mcs_tx_set =3D DEFAULT_VHT_MCS_SET; + vht_cfg.mcs_rx_set =3D DEFAULT_VHT_MCS_SET; + } + + vht_cfg.misc_config =3D VHT_CAP_UAP_ONLY; + + if (ap_11ac_enable && width >=3D NL80211_CHAN_WIDTH_80) + vht_cfg.misc_config |=3D VHT_BW_80_160_80P80; + + nxpwifi_send_cmd(priv, HOST_CMD_11AC_CFG, + HOST_ACT_GEN_SET, 0, &vht_cfg, true); +} + +/* This function finds supported rates IE from beacon parameter and sets + * these rates into bss_config structure. + */ +void +nxpwifi_set_uap_rates(struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params) +{ + struct ieee_types_header *rate_ie; + int var_offset =3D offsetof(struct ieee80211_mgmt, u.beacon.variable); + const u8 *var_pos =3D params->beacon.head + var_offset; + int len =3D params->beacon.head_len - var_offset; + u8 rate_len =3D 0; + + rate_ie =3D (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); + if (rate_ie) { + if (rate_ie->len > NXPWIFI_SUPPORTED_RATES) + return; + memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); + rate_len =3D rate_ie->len; + } + + rate_ie =3D (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, + params->beacon.tail, + params->beacon.tail_len); + if (rate_ie) { + if (rate_ie->len > NXPWIFI_SUPPORTED_RATES - rate_len) + return; + memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len); + } +} + +/* This function initializes some of nxpwifi_uap_bss_param variables. + * This helps FW in ignoring invalid values. These values may or may not + * be get updated to valid ones at later stage. + */ +void nxpwifi_set_sys_config_invalid_data(struct nxpwifi_uap_bss_param *con= fig) +{ + config->bcast_ssid_ctl =3D 0x7F; + config->radio_ctl =3D 0x7F; + config->dtim_period =3D 0x7F; + config->beacon_period =3D 0x7FFF; + config->auth_mode =3D 0x7F; + config->rts_threshold =3D 0x7FFF; + config->frag_threshold =3D 0x7FFF; + config->retry_limit =3D 0x7F; + config->qos_info =3D 0xFF; +} + +/* This function parses WMM related parameters from cfg80211_ap_settings + * structure and updates bss_config structure. + */ +void +nxpwifi_set_wmm_params(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params) +{ + const u8 *vendor_ie; + const u8 *wmm_ie; + static const u8 wmm_oui[] =3D {0x00, 0x50, 0xf2, 0x02}; + + vendor_ie =3D cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WMM, + params->beacon.tail, + params->beacon.tail_len); + if (vendor_ie) { + wmm_ie =3D vendor_ie; + if (*(wmm_ie + 1) > sizeof(struct nxpwifi_types_wmm_info)) + return; + memcpy(&bss_cfg->wmm_info, wmm_ie + + sizeof(struct ieee_types_header), *(wmm_ie + 1)); + priv->wmm_enabled =3D 1; + } else { + memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info)); + memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui)); + bss_cfg->wmm_info.subtype =3D NXPWIFI_WMM_SUBTYPE; + bss_cfg->wmm_info.version =3D NXPWIFI_WMM_VERSION; + priv->wmm_enabled =3D 0; + } + + bss_cfg->qos_info =3D 0x00; +} + +/* This function enable 11D if userspace set the country IE. + */ +void nxpwifi_config_uap_11d(struct nxpwifi_private *priv, + struct cfg80211_beacon_data *beacon_data) +{ + enum state_11d_t state_11d; + const u8 *country_ie; + + country_ie =3D cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_data->tail, + beacon_data->tail_len); + if (country_ie) { + /* Send cmd to FW to enable 11D function */ + state_11d =3D ENABLE_11D; + if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, + HOST_ACT_GEN_SET, DOT11D_I, + &state_11d, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "11D: failed to enable 11D\n"); + } + } +} + +void nxpwifi_uap_set_channel(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg, + struct cfg80211_chan_def chandef) +{ + u8 config_bands =3D 0, old_bands =3D priv->adapter->config_bands; + + priv->bss_chandef =3D chandef; + + bss_cfg->channel =3D + ieee80211_frequency_to_channel(chandef.chan->center_freq); + + /* Set appropriate bands */ + if (chandef.chan->band =3D=3D NL80211_BAND_2GHZ) { + bss_cfg->band_cfg =3D BAND_CONFIG_BG; + config_bands =3D BAND_B | BAND_G; + + if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) + config_bands |=3D BAND_GN; + } else { + bss_cfg->band_cfg =3D BAND_CONFIG_A; + config_bands =3D BAND_A; + + if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) + config_bands |=3D BAND_AN; + + if (chandef.width > NL80211_CHAN_WIDTH_40) + config_bands |=3D BAND_AAC; + } + + switch (chandef.width) { + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + break; + case NL80211_CHAN_WIDTH_40: + if (chandef.center_freq1 < chandef.chan->center_freq) + bss_cfg->band_cfg |=3D NXPWIFI_SEC_CHAN_BELOW; + else + bss_cfg->band_cfg |=3D NXPWIFI_SEC_CHAN_ABOVE; + break; + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + case NL80211_CHAN_WIDTH_160: + bss_cfg->band_cfg |=3D + nxpwifi_get_sec_chan_offset(bss_cfg->channel) << 4; + break; + default: + nxpwifi_dbg(priv->adapter, + WARN, "Unknown channel width: %d\n", + chandef.width); + break; + } + + priv->adapter->config_bands =3D config_bands; + + if (old_bands !=3D config_bands) { + nxpwifi_send_domain_info_cmd_fw(priv->adapter->wiphy); + nxpwifi_dnld_txpwr_table(priv); + } +} + +int nxpwifi_config_start_uap(struct nxpwifi_private *priv, + struct nxpwifi_uap_bss_param *bss_cfg) +{ + if (nxpwifi_send_cmd(priv, HOST_CMD_UAP_SYS_CONFIG, + HOST_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to set AP configuration\n"); + return -1; + } + + if (nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_START, + HOST_ACT_GEN_SET, 0, NULL, true)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to start the BSS\n"); + return -1; + } + + if (priv->sec_info.wep_enabled) + priv->curr_pkt_filter |=3D HOST_ACT_MAC_WEP_ENABLE; + else + priv->curr_pkt_filter &=3D ~HOST_ACT_MAC_WEP_ENABLE; + + if (nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL, + HOST_ACT_GEN_SET, 0, + &priv->curr_pkt_filter, true)) + return -1; + + return 0; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18D2D17B410; Fri, 21 Jun 2024 07:54:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956477; cv=fail; b=oBRV9w/SgiAds9Sq3YcMfnOGqeq4YEzX1QdqeUTaQuzhwQuWJGVWpsPiDerzSCOEfyCZV75xkQjYgiPgKk4Um2/TWaWW39v5ZjBt7kVpYgh187t5mNazxc1hfLYpmEcLVVy1ZEeZG11WhdWx/MPCRBZ2AA36EEwmsz5fdX+dwG8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956477; c=relaxed/simple; bh=YoSlgN26Bdqe/2KvCNAIsfpJ7Z26bb0vqxd0YI6CVqs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=pbRf5Kgsuy96BF3+s7CPa7jymZt5zWc15uHV7HCFO4ANHxW1h3jyOofQMbA1A/TTF2sBdlSWSjf6k/gru4F/Ue+3U/DJnBCK12xu0v6tpG7dTxPov1ZzAC3bpfyi0tUIhU1HAyz05sLr6xFu/mlagW7wPDnJfH/zpRp3lBlRHc4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=oWEaoRkK; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="oWEaoRkK" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=guNATDMld1Y2zAAkkeCpw8EszXMksF23xfj4GTUhpjD2pUOk+ruOhl/NTIYDPi93OakeU/Le6GHceujdR7aLgTX/7VZi7uOL5uHiKhmWCK7JRaN8bmeqybQJEa2feeOWSouumpblORQEvZf5JQvAnWXVF0gZBh2Vt7z1r1BdvxM82JbG4pYR/xhoAP42KeyvtbVi3Mnvjk+IjfGIGpOSkQuSHr5/sEtnGGpuAGvlbtSiOMd4aRLqydZgdOVmQKUBwgGbE5kk/1zDVRcaNvz+t4cWrTgu7MYLsNz6V8mRJvqe6sIfcP0CREYlQTGyXcbwDv6OVfDE25C7D+mk0Jt9iA== 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=hbCjsVVT6y3+92l4US55cLejzoVFTytHoQxx10eDZLw=; b=Po630c+kPHJ8UXoSIje4F78kw8eriLhWglsZfeXOtEjh24VhD/ChiO1OBMKaTwYODCxjp8DGtx7yoI0lo3kriSEOQaN9qwxhW/XM1fo5F/jKOdhu6ElU5vxDzQc0wN3/E6R1i5M9uUsghMggvIQDwnWHwg9lOoBzy+a+BMKOF0b550oJZaiExjXF2NfiqHRJExHpwppkG3dzSYf1adrc/m2VgOsyIazerxIUJ+SzWaduqcUfYq9E1uHfd4v44Wl4nkl6ArRL2tRjPSPX0YfWFqbS3ep3dj6bv/M3aUDwL6+1daZlwDYXargF+nxdJPQ4OGIuMC3SLUvWyn2bh6en8A== 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=hbCjsVVT6y3+92l4US55cLejzoVFTytHoQxx10eDZLw=; b=oWEaoRkKCMCnrAA2Ed/x4EMKdQAtZlaYDcatrx/McR0Fe4MpYpiCcbQ+rtSX2+24WcAduJ4VSrW5ILJSwxfxoGczO3v/IDNiVuLuSPq0+1chLUUGb38ojFGwV103RfaQ7swrSdwWxa7aSY8FP7JOe3S0blmp+KQvy1ojLFVYH+w= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:30 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:30 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 35/43] wifi: nxpwifi: add uap_event.c Date: Fri, 21 Jun 2024 15:52:00 +0800 Message-Id: <20240621075208.513497-36-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 9d5ff4f6-ce74-4893-0e0d-08dc91c761a2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?1YKviy65OFGVx0Obik/IId4EeXyFBfsqkuY+63yRygrePRIx00bgZqTBg4f4?= =?us-ascii?Q?zUHyhyCGVFIiV3wWMWp2jkLeT2Oe4nNhpNPU1uE6sO96GN/Y2HrJJ5AaCafj?= =?us-ascii?Q?VhwUVLU5zJwvjiEKtP/PFfgu2GVtsvV97pdGdwF5H6Y/y6T35RCJuhx62AHT?= =?us-ascii?Q?FbtMOkJz0Q+rK/+J1TLXZdt8WxN6nvQVhl1gpoMWs2dYTyLSH+Z2l45V6WrQ?= =?us-ascii?Q?/gJ3Q/uKIhCHN1ZmOlG5daHsM34RdF3PZro3GXPxj0mMe4glcbG88jCCeixD?= =?us-ascii?Q?4QKOesYr9LI5rTzjcupXY6YDUNBsBnvrY9o+X8hg6k9HRvq7qEPlIaMBbnjO?= =?us-ascii?Q?votlrkmUZ+7allJL8JTMtNQ03zTurvpsxhfNRnOIDTBLYir9G5tm2WBfG9jF?= =?us-ascii?Q?lIFo10ajyUxMbGDRSK5nCbyAUpf4uNJilDP9aXQuP3/+L1sSD2BeVyh8VgE1?= =?us-ascii?Q?0wxbqbRyhHsVWdsGsaJS8Xo/nnt5iVYCf2KgoWtFTQ7csImBtPL+4bqTbOB6?= =?us-ascii?Q?X4eah8yjGNhwjuFdsc2SEk6Uu3xmmatpYsPRE4AyGhVnfv9Nu/sXR5U3LeXu?= =?us-ascii?Q?ImgQEBslb9dAchWlKSly8/y/M4HOvh47qm+GSnOZ61Is0MYTDah6cOwNRJbE?= =?us-ascii?Q?qhWZs4mJwAcIcp9HMyP2dxje+KhggUarNTQ25Z18S2Qo9erxk+bxBVcM47zK?= =?us-ascii?Q?pB4EY07NPeMtZgGEPBzDMpIW8ah+Bfw9gFN7CI/YDVnyVZ6iCUGKjtyOy0nq?= =?us-ascii?Q?HqyUt8XSZ0BlQv1+fMezz1SwZRTzeOdhlGisbuQLffvkYRdsqgQB/6OOhC3H?= =?us-ascii?Q?dc5nqI2pLNQPEPWv6iIEa/E1l7V9pvGJ7mmjMzJLdo6KW25OYEvVL2V2wb/c?= =?us-ascii?Q?mqUGYFmG35AWouQXvwqGgqXIGAiZK18YoFkNYGZhtWSmDAl/HYWAy6f/Uhtl?= =?us-ascii?Q?JTbmoPhDGTxlyKrqSxJoB43A+3N2U/AbxBXZYpCd4RYT95U07Qt0ij+yhMID?= =?us-ascii?Q?glHr/jzxczNWFKBztv0RNek1huBxDfpv8ocb/TTq6oo+WYWqeIisGFtTnElH?= =?us-ascii?Q?6vk+AXSaOVJH/m0V0lvZlKwtZClug8p+enpjlHEq1cxB5AWxN10jtcfRMpmZ?= =?us-ascii?Q?MKOn/VIs3lbAdJQ0ExRO0GM9ScZUKb/Njw/F51Fs5UaWejFo9+/Q+uvfemQS?= =?us-ascii?Q?hOxFTr/HVyErMBayYa+5AO5DE32/0SjBWHNf1iX6b99GGO5bUbG7AI+ZkbwT?= =?us-ascii?Q?BG6AnZBfm1fXgMqi3mYRIqO5rYQFmHZRtlM5zyqwkEeuCMQeg4j50RhRWui5?= =?us-ascii?Q?gkEoXFujzBHcUg5j0JcdfFL7uGtRhvvqXtekFsWmm7aDwxDw5ytK9OPHgTjE?= =?us-ascii?Q?6TDUYHw=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Ptq9KkUMY+pLdloRmIqpik5tE2LBkPKK6LXdCVD2ZscrkTtHeI1sc2XJHVLN?= =?us-ascii?Q?M/FSOcJhYmbfpAX9Jqe9XC55FeiE/hHLgGZmaZvdqMfnRQJ2JfCEcYN2T5b1?= =?us-ascii?Q?75UDZoxSzz5/8uVCxYt/WZG3Jez97hCYtB9luNase4PmyYmP6v/vwyHnBv8c?= =?us-ascii?Q?fNzc6mi/nSayfvKewIYd0Cg+pad0NTj8Pm1+ffrsl/AUnfLMk1Hq9MfiTagR?= =?us-ascii?Q?9BrLcjWiJQrsUNWSEARiY//xpmgrOxY+iGivsdcM4W2zQbOmSr9RAJ8miUCL?= =?us-ascii?Q?gE2jgIoh32trvGcKLn14ObXRK4bS+YzkzPubm5+hcmVcyAsjTQKPmF+afzdU?= =?us-ascii?Q?WdcGBFv262YNrrItcT9KRR63JFV9K+q56/fHJl0elY0p7sTNNIVOWVBF7tF8?= =?us-ascii?Q?SqdrvYZwIzjZLLSlSFnRzlqkRxpE3hw6PfZ0O8y1bAPMcEqKzjl2LsTO9XOH?= =?us-ascii?Q?juV/FlxYZSzPDSLiYJZ8kvr86fUcVkEpTgdDTf+nf47a3wzvNQchdWgHplZC?= =?us-ascii?Q?vL2bCpGEcXEPtF/sOxtJqNCy1PilpYq98G/37m69snQNtgFCufrYk9/bGOqo?= =?us-ascii?Q?WbSmosTmmITVZGKFHTjm/ycAR2A6/RYPs+YmRJHFL/iC6VyFIuvd+gwJvtSk?= =?us-ascii?Q?JS1INv2I7S4Ku3FROMspWCzqIcaKdLiG4uWCOsRxmzhLOfMh1Cq+wdR1DMYl?= =?us-ascii?Q?R4apqiLVZrzDyi0wsIxm1EJ6A2d0mIBC6SfTY44g7SFT/nlEITnf/0/PxlEz?= =?us-ascii?Q?RmpYifR5wtLvEcneP2zxXnV0cKevmGmCvzOQQJZAVqcsyFMBvY54wNhGXWlz?= =?us-ascii?Q?LNMxKSBMKuqHBbgyMw1ZahCib9Uv2x03t4gQYOCVregeBhvrZDaJXCRFXGxb?= =?us-ascii?Q?uXMRQm/prQD+TfGylXBbgRpU0tyVm5JPxQVD08Ia+JSBKJlOYsa/qw3GJ998?= =?us-ascii?Q?lH9soRGbP/bGJ9Z2gkroCZqvUYfpKYiapKyWjlKAl4Fw+GT0xs3htDVMEetB?= =?us-ascii?Q?ir9rkaZwaLwwe8FnbXVWbHdMV370ffahzppm+pBGeB6UaXh6pnxesuUJ4e9j?= =?us-ascii?Q?ZMhjgm9Wb8jWPaIzM5aUYSS58Jbcgo7P6P1ABfVSb8L2qyYmHxGK6u/TnnQL?= =?us-ascii?Q?5xbW5ssSeTPYMWl68jtyjVz4t85Ov0S+0m51l7lGw9XKH8rNY1LQq9m/Y+Qy?= =?us-ascii?Q?gZdL0t3VVt8qiuZHRYltNXyFsvl9XEl0NPEAQMP3qcvgwQRkbYWrohlqIpHM?= =?us-ascii?Q?cpcWFXm5+gnJCDS0iAWYRdsVP5fPUwT6QxSibODIsTd8RUMF5Xp//JnzuF7G?= =?us-ascii?Q?EV1ninHHGJ6WrQ4rtI9D254bmJRxm2VLdWtPdRcaZ/t0F3Zd4u6+f7Zxn6+U?= =?us-ascii?Q?UjMNk04AUaJyK3uiOiO562AZHKIVNa0VjhPcv7CE/v8E1xhqWG0HwcfkmL89?= =?us-ascii?Q?ToYKS7BdpwJz0sbRUQPw4A8BvoOkmZ81WfAu2OCtQz8SbgT3y6M6EXbsw9Sh?= =?us-ascii?Q?C5Vlit+/DtOm66TQgL3sQCzbG7lWGQJFssxwnDGRu+wdvjyWk5rKgdepOahd?= =?us-ascii?Q?CxxpnDy7hC8W2j/B/H0Xjdk/U5hVXqNZNgb8FaKk?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9d5ff4f6-ce74-4893-0e0d-08dc91c761a2 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:30.5778 (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: iZ5zAHBCCiPIEd1HOJyiQ/OrMav4lo2XiBPnrR47CH9XAMOssi5hwngFR44jE5OMt2hu4FvAKUgaGOu+ziQGnw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/uap_event.c | 483 +++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/uap_event.c diff --git a/drivers/net/wireless/nxp/nxpwifi/uap_event.c b/drivers/net/wir= eless/nxp/nxpwifi/uap_event.c new file mode 100644 index 000000000000..2c15b01ec018 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/uap_event.c @@ -0,0 +1,483 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: AP event handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "main.h" +#include "cmdevt.h" +#include "11n.h" + +#define NXPWIFI_BSS_START_EVT_FIX_SIZE 12 + +static int +nxpwifi_uap_event_ps_awake(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (!adapter->pps_uapsd_mode && + priv->media_connected && adapter->sleep_period.period) { + adapter->pps_uapsd_mode =3D true; + nxpwifi_dbg(adapter, EVENT, + "event: PPS/UAPSD mode activated\n"); + } + adapter->tx_lock_flag =3D false; + if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { + if (nxpwifi_check_last_packet_indication(priv)) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { + adapter->ps_state =3D PS_STATE_AWAKE; + adapter->pm_wakeup_card_req =3D false; + adapter->pm_wakeup_fw_try =3D false; + } else { + if (!nxpwifi_send_null_packet + (priv, + NXPWIFI_TxPD_POWER_MGMT_NULL_PACKET | + NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET)) + adapter->ps_state =3D PS_STATE_SLEEP; + } + + return 0; + } + } + + adapter->ps_state =3D PS_STATE_AWAKE; + adapter->pm_wakeup_card_req =3D false; + adapter->pm_wakeup_fw_try =3D false; + + return 0; +} + +static int +nxpwifi_uap_event_ps_sleep(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + adapter->ps_state =3D PS_STATE_PRE_SLEEP; + nxpwifi_check_ps_cond(adapter); + + return 0; +} + +static int +nxpwifi_uap_event_sta_deauth(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u8 *deauth_mac; + + deauth_mac =3D adapter->event_body + + NXPWIFI_UAP_EVENT_EXTRA_HEADER; + cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL); + + if (priv->ap_11n_enabled) { + nxpwifi_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac); + nxpwifi_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac); + } + nxpwifi_wmm_del_peer_ra_list(priv, deauth_mac); + nxpwifi_del_sta_entry(priv, deauth_mac); + + return 0; +} + +static int +nxpwifi_uap_event_sta_assoc(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct station_info *sinfo; + struct nxpwifi_assoc_event *event; + struct nxpwifi_sta_node *node; + int len, i; + + sinfo =3D kzalloc(sizeof(*sinfo), GFP_KERNEL); + if (!sinfo) + return -ENOMEM; + + event =3D (struct nxpwifi_assoc_event *) + (adapter->event_body + NXPWIFI_UAP_EVENT_EXTRA_HEADER); + if (le16_to_cpu(event->type) =3D=3D TLV_TYPE_UAP_MGMT_FRAME) { + len =3D -1; + + if (ieee80211_is_assoc_req(event->frame_control)) + len =3D 0; + else if (ieee80211_is_reassoc_req(event->frame_control)) + /* There will be ETH_ALEN bytes of + * current_ap_addr before the re-assoc ies. + */ + len =3D ETH_ALEN; + + if (len !=3D -1) { + sinfo->assoc_req_ies =3D &event->data[len]; + len =3D (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len =3D + le16_to_cpu(event->len) - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, + GFP_KERNEL); + + node =3D nxpwifi_add_sta_entry(priv, event->sta_addr); + if (!node) { + nxpwifi_dbg(adapter, ERROR, + "could not create station entry!\n"); + kfree(sinfo); + return -1; + } + + if (!priv->ap_11n_enabled) { + kfree(sinfo); + return 0; + } + + nxpwifi_set_sta_ht_cap(priv, sinfo->assoc_req_ies, + sinfo->assoc_req_ies_len, node); + + for (i =3D 0; i < MAX_NUM_TID; i++) { + if (node->is_11n_enabled) + node->ampdu_sta[i] =3D + priv->aggr_prio_tbl[i].ampdu_user; + else + node->ampdu_sta[i] =3D BA_STREAM_NOT_ALLOWED; + } + memset(node->rx_seq, 0xff, sizeof(node->rx_seq)); + kfree(sinfo); + + return 0; +} + +static int +nxpwifi_check_uap_capabilities(struct nxpwifi_private *priv, + struct sk_buff *event) +{ + int evt_len; + u8 *curr; + u16 tlv_len; + struct nxpwifi_ie_types_data *tlv_hdr; + struct ieee_types_wmm_parameter *wmm_param_ie =3D NULL; + int mask =3D IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK; + + priv->wmm_enabled =3D false; + skb_pull(event, NXPWIFI_BSS_START_EVT_FIX_SIZE); + evt_len =3D event->len; + curr =3D event->data; + + nxpwifi_dbg_dump(priv->adapter, EVT_D, "uap capabilities:", + event->data, event->len); + + skb_push(event, NXPWIFI_BSS_START_EVT_FIX_SIZE); + + while ((evt_len >=3D sizeof(tlv_hdr->header))) { + tlv_hdr =3D (struct nxpwifi_ie_types_data *)curr; + tlv_len =3D le16_to_cpu(tlv_hdr->header.len); + + if (evt_len < tlv_len + sizeof(tlv_hdr->header)) + break; + + switch (le16_to_cpu(tlv_hdr->header.type)) { + case WLAN_EID_HT_CAPABILITY: + priv->ap_11n_enabled =3D true; + break; + + case WLAN_EID_VHT_CAPABILITY: + priv->ap_11ac_enabled =3D true; + break; + + case WLAN_EID_VENDOR_SPECIFIC: + /* Point the regular IEEE IE 2 bytes into the NXP IE + * and setup the IEEE IE type and length byte fields + */ + wmm_param_ie =3D (void *)(curr + 2); + wmm_param_ie->vend_hdr.len =3D (u8)tlv_len; + wmm_param_ie->vend_hdr.element_id =3D + WLAN_EID_VENDOR_SPECIFIC; + nxpwifi_dbg(priv->adapter, EVENT, + "info: check uap capabilities:\t" + "wmm parameter set count: %d\n", + wmm_param_ie->qos_info_bitmap & mask); + + nxpwifi_wmm_setup_ac_downgrade(priv); + priv->wmm_enabled =3D true; + nxpwifi_wmm_setup_queue_priorities(priv, wmm_param_ie); + break; + + default: + break; + } + + curr +=3D (tlv_len + sizeof(tlv_hdr->header)); + evt_len -=3D (tlv_len + sizeof(tlv_hdr->header)); + } + + return 0; +} + +static int +nxpwifi_uap_event_bss_start(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + priv->port_open =3D false; + eth_hw_addr_set(priv->netdev, adapter->event_body + 2); + if (priv->hist_data) + nxpwifi_hist_data_reset(priv); + return nxpwifi_check_uap_capabilities(priv, adapter->event_skb); +} + +static int +nxpwifi_uap_event_addba(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (priv->media_connected) + nxpwifi_send_cmd(priv, HOST_CMD_11N_ADDBA_RSP, + HOST_ACT_GEN_SET, 0, + adapter->event_body, false); + + return 0; +} + +static int +nxpwifi_uap_event_delba(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (priv->media_connected) + nxpwifi_11n_delete_ba_stream(priv, adapter->event_body); + + return 0; +} + +static int +nxpwifi_uap_event_ba_stream_timeout(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct host_cmd_ds_11n_batimeout *ba_timeout; + + if (priv->media_connected) { + ba_timeout =3D (void *)adapter->event_body; + nxpwifi_11n_ba_stream_timeout(priv, ba_timeout); + } + + return 0; +} + +static int +nxpwifi_uap_event_amsdu_aggr_ctrl(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u16 ctrl; + + ctrl =3D get_unaligned_le16(adapter->event_body); + nxpwifi_dbg(adapter, EVENT, + "event: AMSDU_AGGR_CTRL %d\n", ctrl); + + if (priv->media_connected) { + adapter->tx_buf_size =3D + min_t(u16, adapter->curr_tx_buf_size, ctrl); + nxpwifi_dbg(adapter, EVENT, + "event: tx_buf_size %d\n", + adapter->tx_buf_size); + } + + return 0; +} + +static int +nxpwifi_uap_event_bss_idle(struct nxpwifi_private *priv) +{ + priv->media_connected =3D false; + priv->port_open =3D false; + nxpwifi_clean_txrx(priv); + nxpwifi_del_all_sta_list(priv); + + return 0; +} + +static int +nxpwifi_uap_event_bss_active(struct nxpwifi_private *priv) +{ + priv->media_connected =3D true; + priv->port_open =3D true; + + return 0; +} + +static int +nxpwifi_uap_event_mic_countermeasures(struct nxpwifi_private *priv) +{ + /* For future development */ + + return 0; +} + +static int +nxpwifi_uap_event_radar_detected(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_11h_handle_radar_detected(priv, adapter->event_skb); +} + +static int +nxpwifi_uap_event_channel_report_rdy(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_11h_handle_chanrpt_ready(priv, adapter->event_skb); +} + +static int +nxpwifi_uap_event_tx_data_pause(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_process_tx_pause_event(priv, adapter->event_skb); + + return 0; +} + +static int +nxpwifi_uap_event_ext_scan_report(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + void *buf =3D adapter->event_skb->data; + int ret =3D 0; + + if (adapter->ext_scan) + ret =3D nxpwifi_handle_event_ext_scan_report(priv, buf); + + return ret; +} + +static int +nxpwifi_uap_event_rxba_sync(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_11n_rxba_sync_event(priv, adapter->event_body, + adapter->event_skb->len - + sizeof(adapter->event_cause)); + + return 0; +} + +static int +nxpwifi_uap_event_remain_on_chan_expired(struct nxpwifi_private *priv) +{ + cfg80211_remain_on_channel_expired(&priv->wdev, + priv->roc_cfg.cookie, + &priv->roc_cfg.chan, + GFP_ATOMIC); + memset(&priv->roc_cfg, 0x00, sizeof(struct nxpwifi_roc_cfg)); + + return 0; +} + +static int +nxpwifi_uap_event_multi_chan_info(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_process_multi_chan_event(priv, adapter->event_skb); + + return 0; +} + +static int +nxpwifi_uap_event_tx_status_report(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_parse_tx_status_event(priv, adapter->event_body); + + return 0; +} + +static int +nxpwifi_uap_event_bt_coex_wlan_para_change(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + nxpwifi_bt_coex_wlan_param_update_event(priv, adapter->event_skb); + + return 0; +} + +static const struct nxpwifi_evt_entry evt_table_uap[] =3D { + {.event_cause =3D EVENT_PS_AWAKE, + .event_handler =3D nxpwifi_uap_event_ps_awake}, + {.event_cause =3D EVENT_PS_SLEEP, + .event_handler =3D nxpwifi_uap_event_ps_sleep}, + {.event_cause =3D EVENT_UAP_STA_DEAUTH, + .event_handler =3D nxpwifi_uap_event_sta_deauth}, + {.event_cause =3D EVENT_UAP_STA_ASSOC, + .event_handler =3D nxpwifi_uap_event_sta_assoc}, + {.event_cause =3D EVENT_UAP_BSS_START, + .event_handler =3D nxpwifi_uap_event_bss_start}, + {.event_cause =3D EVENT_ADDBA, + .event_handler =3D nxpwifi_uap_event_addba}, + {.event_cause =3D EVENT_DELBA, + .event_handler =3D nxpwifi_uap_event_delba}, + {.event_cause =3D EVENT_BA_STREAM_TIEMOUT, + .event_handler =3D nxpwifi_uap_event_ba_stream_timeout}, + {.event_cause =3D EVENT_AMSDU_AGGR_CTRL, + .event_handler =3D nxpwifi_uap_event_amsdu_aggr_ctrl}, + {.event_cause =3D EVENT_UAP_BSS_IDLE, + .event_handler =3D nxpwifi_uap_event_bss_idle}, + {.event_cause =3D EVENT_UAP_BSS_ACTIVE, + .event_handler =3D nxpwifi_uap_event_bss_active}, + {.event_cause =3D EVENT_UAP_MIC_COUNTERMEASURES, + .event_handler =3D nxpwifi_uap_event_mic_countermeasures}, + {.event_cause =3D EVENT_RADAR_DETECTED, + .event_handler =3D nxpwifi_uap_event_radar_detected}, + {.event_cause =3D EVENT_CHANNEL_REPORT_RDY, + .event_handler =3D nxpwifi_uap_event_channel_report_rdy}, + {.event_cause =3D EVENT_TX_DATA_PAUSE, + .event_handler =3D nxpwifi_uap_event_tx_data_pause}, + {.event_cause =3D EVENT_EXT_SCAN_REPORT, + .event_handler =3D nxpwifi_uap_event_ext_scan_report}, + {.event_cause =3D EVENT_RXBA_SYNC, + .event_handler =3D nxpwifi_uap_event_rxba_sync}, + {.event_cause =3D EVENT_REMAIN_ON_CHAN_EXPIRED, + .event_handler =3D nxpwifi_uap_event_remain_on_chan_expired}, + {.event_cause =3D EVENT_MULTI_CHAN_INFO, + .event_handler =3D nxpwifi_uap_event_multi_chan_info}, + {.event_cause =3D EVENT_TX_STATUS_REPORT, + .event_handler =3D nxpwifi_uap_event_tx_status_report}, + {.event_cause =3D EVENT_BT_COEX_WLAN_PARA_CHANGE, + .event_handler =3D nxpwifi_uap_event_bt_coex_wlan_para_change}, +}; + +/* This function handles AP interface specific events generated by firmwar= e. + * + * Event specific routines are called by this function based + * upon the generated event cause. + */ +int nxpwifi_process_uap_event(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u32 eventcause =3D adapter->event_cause; + int evt, ret =3D 0; + + for (evt =3D 0; evt < ARRAY_SIZE(evt_table_uap); evt++) { + if (eventcause =3D=3D evt_table_uap[evt].event_cause) { + if (evt_table_uap[evt].event_handler) + ret =3D evt_table_uap[evt].event_handler(priv); + break; + } + } + + if (evt =3D=3D ARRAY_SIZE(evt_table_uap)) + nxpwifi_dbg(adapter, EVENT, + "%s: unknown event id: %#x\n", + __func__, eventcause); + else + nxpwifi_dbg(adapter, EVENT, + "%s: event id: %#x\n", + __func__, eventcause); + + return ret; +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECB5817B43A; Fri, 21 Jun 2024 07:54:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956481; cv=fail; b=u8nnEo8+D2NMUsE6R+PiUHzVd89iFZ4OkuCyVgSb3fyrAOQxZwnsfgX9xzvOyTlvm1VErb1Usg5ujZlzPKj1LtDp6NUoDYEzgKXF+mnrsN4N+QE8A9UmojD3O2AT7vB+PtYNjdUNbsVhsBnPOd4fK4wp2kX/vOSBGR2xTJtyd6Y= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956481; c=relaxed/simple; bh=3LGnFwNTz6B6JbUwqdVOpd6H/T6IXTEBSr4nWWQO5RU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=ei/FQpgC9EM+qk+48CC/3Uvo9eJtFUgqhDlOrThLau3ArfcAOZzBJZ+M7X16R4QGW2pYNYgecBziGK4lDNt6fTHWBc9bKgJI5swGgLWPFS/lldLP6KEhRtdYh4L43ywgZ2Sfb0CfHSwIpHC2K+qF+R/9UPQbXymjwDBn6cOa6PE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=ZW2xmgR8; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="ZW2xmgR8" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hO2Z04mXNH+mkxdInkWCY3t5/EQz0j5vfrSCGv/s+2W+SbuqoF4xLuiClkALlajkcy3YgSZ5eLjv2Ho+Af3flMbAEm/pq0JIXkHRTGr+3AOoB/Ub63/zYonNqGStiLVAerBMUAN3edCrRgKrIN3LQLbosoJb9RaHQR0lmoz48VaR03S4lIRrNw96Y2F3PdaxrH6OVXYW4MRe+nCDPvBuaUQJay7Qx3W0jWtXNShwhQKB9cne5BnKdytzB4l6xdUYNescItBUQKcmtpqyRAF4BuqUoe2h8fpqH+m9DXE2YdOpM8d0ReGICXKz/riFl4k2b9UuW7NzQ5CZWW52uCeRBw== 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=WvQpSlbULY4Zcc3iELEuL0i00AQ5LgeF9Sccc0po37A=; b=M8nla2FzHHXoiYikDY1AgZG7oHpgI/YzgKw6ENKm6LyVu1CkByyaMtWWwVr9BHACc7vZbaMz161SNB+5xqRAP9nxgfqavTWiHXOkEkLtf7JBFsiRvmu7A1hezIgXaCU1dlg5DWE5OnB6ajb20r/v3irraYpMDVvHnJdTgRoKf/QbCPrOAe3AuwiTlorA0mQUDuLJ/kzrRA6crptGL9bJsYVgunPl4MZDCsBIaQqhaIiqpE4hK74C7NrcnFesOQ4n+i57gmzJT2thtn8y7j26ND4X60EJ4pa5B97olIZO/+JXGoxn9AeNvr5ZBMZN3cxDqnhE4vFXE5MYJGanl0pX9Q== 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=WvQpSlbULY4Zcc3iELEuL0i00AQ5LgeF9Sccc0po37A=; b=ZW2xmgR8WKj3kBNk6TCxXaALK//Y5j3qot6JCGncRwslmZh+edyJZ43L3RfwOmikzdnCm+s3k77Ociy/eXgHIDE5BTHunVlay3KQgU+AUyi+zdy2q+awU3XNh01YiXH6zXQdhL2VkAmsN2sXLjF7ujKIMEfQzyrI9AbIYscPJdg= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:33 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:33 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 36/43] wifi: nxpwifi: add uap_txrx.c Date: Fri, 21 Jun 2024 15:52:01 +0800 Message-Id: <20240621075208.513497-37-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: bd4d53bb-7e65-4afd-5d40-08dc91c76363 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?/+RreziID+45MBsvfk+t0nAuejFFkHpfhn7IMWalWC4deMrs9ZVoi0Mx+iMm?= =?us-ascii?Q?T93N+SIdOMzMvy262ILNtG690/a/cwOrUYAXwnDRvWIwlvUtquBuMF3O8JIJ?= =?us-ascii?Q?mR4iU2uwHltfVy2zjd3k69xdXDdWER6WiarhUdgEvvte6GoyRto7AjdxZjRD?= =?us-ascii?Q?gi18shuxXaqOxpZ6eznrJmgv1/ugcQdcOf6HIMmm8nkomhYERCIoNYQZZErp?= =?us-ascii?Q?MKQxieGq/Nl5M9XhbN8uceFnZagKelnkjw55NtOUI1gGBuMv757mmDJTUUKQ?= =?us-ascii?Q?kWqJYrNVCfBRMia9fkVXA36QNK4/iy7ww2Fl5IFdXaBOtkgP+Bzw7NbOCKJm?= =?us-ascii?Q?gds/rHwvenGgxWI5YTE/aHpEaN1kH8EmRFtv96AO5Z2CLiBXvW17wYQdkxYl?= =?us-ascii?Q?GBEA5YPRkOsV1ORqWLqcE5I8lDzXy/9GiGBvwer1d706DlmrZFNTnW2KwfPU?= =?us-ascii?Q?fcL79Ui+/ybeGtIdnrHV0MmK3Z5WQYbkdW4825bao5mWedvu1Rah7ElJw+hD?= =?us-ascii?Q?h7z7LnUn92qLUMmmrc6Po7eKJH2GeGwoKn0bm5Qyiz+nPHUHMWnTLKZ5Bgw2?= =?us-ascii?Q?e+JZsh5JC3nfNAIn7uFR29AkCte5m1OHDX6dxHWqEm61KH5Dcg/WZXb82ltl?= =?us-ascii?Q?0QnxTyknQCrj80H6lWfsa/W2l0tiPdUnzNL6du2VhjhBhICurX5c5eMI7D2L?= =?us-ascii?Q?BWSqjYQCjiHdKfOUPC6MnIpTeVwtsojU+Avd7+FCSLwcceBHuROX+t4fcpSp?= =?us-ascii?Q?TH16XpPSdS6ZHzHdaKJlPz291E/ut1hCJUe1rOcKAEHPbDOZNoO+YW/aRRwZ?= =?us-ascii?Q?uu7GSnBYYEshpttfOr2ej2ToYD7TuSjQf5fm+FDZchgxfnxCnNb+vtTi0qW+?= =?us-ascii?Q?GPWLllIz/XDQfFoaiY9QJmPnt3M3+TY4zSyyP+2ZhSDadCxLHRN1MuIPpZjG?= =?us-ascii?Q?RuRUt2ZGxElyMXqjbgJLK+q+Jiz6FZXYyJpkke0BmmHRMUAjfE/UYhcPmDsk?= =?us-ascii?Q?YHdfPdjyYqcc4vls/rcmcY4sjYAS3s2AUc/KDAo9oqGwhEt3TbXvw06hGKg7?= =?us-ascii?Q?7lm0JVNBTaIG6PZ2sjET9r09Vas3KMXHYKi0M1sCqKvLO6QQ/AlQebvkqUyl?= =?us-ascii?Q?O717uAxKG3eHs7uFquoA221yj7iXC4O88eH8x0mnV4+15ksPDU/+O89AyJnt?= =?us-ascii?Q?KSWcK7BGO+eZVuegPnSZTn0y/B9y6kWOdw2FqRdRpaxeVaWEnIDFtluTiOEX?= =?us-ascii?Q?nqrQ0NP4SMkJnMpgeTIyVvjH9brDV7xzUdo1wUcX3qgWblj9qL1rNOFqG5Nr?= =?us-ascii?Q?EMY1OLfIrlOOD96DhM3IAWBM3/9lZoUbuDb+QgeoC0g3KSAtcwBcJ7UyqXWe?= =?us-ascii?Q?FqQqsnw=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?7O6Uvv/TjHzdrjK7adxEU2yEC6ltXQuhc5ckoLXVylOCuTIClCUjQ1IPej3z?= =?us-ascii?Q?b1XQp3zmESidfxD0nNjulzwYxHLBw/M+n8RnZmWCIq/C+rZI6Ib8U/WTFyLv?= =?us-ascii?Q?ML9sYeoScwdcCAbbEazjyMGQl4lMtzy3kmc6s6kT5ekoyUoVIIUuQdKyd0Mg?= =?us-ascii?Q?0CDQXMskJh1YFGpfGtQtkCvSeb96PYlrhfm6F6+L52HDk6evgjCCkeanlZGR?= =?us-ascii?Q?D2OjTieLtp/n/O8UUK7cHwfENvaBiaLbXEchnx2B5bWPgjE4bqIC43yIjv0J?= =?us-ascii?Q?CP0FDUs1kHpmogoc4FlrFrMh+H2zdpDCn7keg33C6CWlawVmV2zD4z7q1aiJ?= =?us-ascii?Q?66gUN5ilWSDn6OxPbZE4UZlSRJQdYN1MZb/yng6YY9ULXs0pT5WsTk1QKKeb?= =?us-ascii?Q?YM1tPcJ6CWhHj4kNKe1WKrXHgQqRAW/IrA4jSjWtgHZx3ZlIFd5gZnKiErcB?= =?us-ascii?Q?ze4KqumbUBOnFBysrETqFKkRZISmieRMb0pdDt2sgj+4Fz434Ycydx6XsqIm?= =?us-ascii?Q?PpUmMQAKM2FO4zeYbfgak+TBzu8aLzUp56Pgv7ecVu0DeuJpRS9Rr7ORgJ2E?= =?us-ascii?Q?HGSUuGf3uqBwztGTTFS/94rGSAjAuAtf82JwR8xxLfKwcG0bmFWFtiaGohw3?= =?us-ascii?Q?u5FAq0YWCUiO9qxTejwOin4WCMDzHLXaKHUxsO16F73U9531aOAPQWfEqS3A?= =?us-ascii?Q?YZP6wcuQIwnRIBVHqOW+Wt+Oo2uELpS+IZgedQR1geEwhHcjwuPIQ7eq6hIa?= =?us-ascii?Q?eXu437vYPr/W4s12xoukd5/SBn/PzE+torwgmPpfv304ZO/nlKGPVKUNYCbH?= =?us-ascii?Q?SUGg0TXh/a/jSqPXq2AhH+Q1/Dl6NvfvlcIxtFf3IFevP1Rt/m+jK4bCLzcI?= =?us-ascii?Q?RZLTkxriRA2OWztiMC62nKhiH6poVEAoLOSDJZ0CA66Lq8gcuaS23jY3YWKx?= =?us-ascii?Q?6UgRXvvJFEs0G3tMp34yIyMNNU0eqEPeQvYbSNwj/2j+hHQ45bWn/sl5uWgh?= =?us-ascii?Q?nWv5gpu9wf7sIjPm1yCdEyQvMYc6x1KkY0xvn980jKXIPXXJKa3QtpakABOC?= =?us-ascii?Q?6zamPMEIYARY66Kv6SQrS6XqBPJ9b8r7nokU/Lxz4Nmsnx/qKwwAdQIuyNxD?= =?us-ascii?Q?SRN7mJCZ+sdqeRAkNiFA2dOIm41t/aC8jOGYKXyJMjPYed/memOrLL5YnIMm?= =?us-ascii?Q?oDySQQQrhWi7+jJI6K417Hb+WpfkDq968eUQlYekSfoBABufm91Co8PtbN/X?= =?us-ascii?Q?b5A6ha6rSQCrHuSQQzfEtB7VEGBXm1J9nFxCwOb+m64FlXOxfhL7expIu02V?= =?us-ascii?Q?mSBbL9b8bfux8pKmK+LtT6M8+hbciGILI9gMBQNyQ28dkVKUFC2V1pgl71VC?= =?us-ascii?Q?bsB5cfQm8NtxavljOTaYo7PDG9gX+43tKn+BMoUwgMfrZZQZV49C8mD9v6T9?= =?us-ascii?Q?LOGBzaaGBSAZ75Uq3jThk4HuFTfhc/y0Lc8UV1YmLnW3RTSOzHWVEPKfMVbd?= =?us-ascii?Q?YzH2tuOZVpWu1d0zWZRWRt1WCtnPxCW8gw0EcM0xyZRIATeC3gJ9okL9a4g4?= =?us-ascii?Q?3bETLTB/HkQSBwJPqpfFeGoaOdMWqu+e2WLd7w3Q?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: bd4d53bb-7e65-4afd-5d40-08dc91c76363 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:33.5394 (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: q9rVG7tXuSU4nKyAUFxM4yA1eXV79Px4dDv+COtiihbEVCgNr794KOyFFyVIr6PKufeLbx6UCNeXoyftuhBe8Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/uap_txrx.c | 498 ++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/uap_txrx.c diff --git a/drivers/net/wireless/nxp/nxpwifi/uap_txrx.c b/drivers/net/wire= less/nxp/nxpwifi/uap_txrx.c new file mode 100644 index 000000000000..055d59cb942f --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/uap_txrx.c @@ -0,0 +1,498 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: AP TX and RX data handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "main.h" +#include "wmm.h" +#include "11n_aggr.h" +#include "11n_rxreorder.h" + +/* This function checks if particular RA list has packets more than low br= idge + * packet threshold and then deletes packet from this RA list. + * Function deletes packets from such RA list and returns true. If no such= list + * is found, false is returned. + */ +static bool +nxpwifi_uap_del_tx_pkts_in_ralist(struct nxpwifi_private *priv, + struct list_head *ra_list_head, + int tid) +{ + struct nxpwifi_ra_list_tbl *ra_list; + struct sk_buff *skb, *tmp; + bool pkt_deleted =3D false; + struct nxpwifi_txinfo *tx_info; + struct nxpwifi_adapter *adapter =3D priv->adapter; + + list_for_each_entry(ra_list, ra_list_head, list) { + if (skb_queue_empty(&ra_list->skb_head)) + continue; + + skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) { + tx_info =3D NXPWIFI_SKB_TXCB(skb); + if (tx_info->flags & NXPWIFI_BUF_FLAG_BRIDGED_PKT) { + __skb_unlink(skb, &ra_list->skb_head); + nxpwifi_write_data_complete(adapter, skb, 0, + -1); + if (ra_list->tx_paused) + priv->wmm.pkts_paused[tid]--; + else + atomic_dec(&priv->wmm.tx_pkts_queued); + pkt_deleted =3D true; + } + if ((atomic_read(&adapter->pending_bridged_pkts) <=3D + NXPWIFI_BRIDGED_PKTS_THR_LOW)) + break; + } + } + + return pkt_deleted; +} + +/* This function deletes packets from particular RA List. RA list index + * from which packets are deleted is preserved so that packets from next RA + * list are deleted upon subsequent call thus maintaining fairness. + */ +static void nxpwifi_uap_cleanup_tx_queues(struct nxpwifi_private *priv) +{ + struct list_head *ra_list; + int i; + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + for (i =3D 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) { + if (priv->del_list_idx =3D=3D MAX_NUM_TID) + priv->del_list_idx =3D 0; + ra_list =3D &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list; + if (nxpwifi_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) { + priv->del_list_idx++; + break; + } + } + + spin_unlock_bh(&priv->wmm.ra_list_spinlock); +} + +static void +nxpwifi_uap_queue_bridged_pkt(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct uap_rxpd *uap_rx_pd; + struct rx_packet_hdr *rx_pkt_hdr; + struct sk_buff *new_skb; + struct nxpwifi_txinfo *tx_info; + int hdr_chop; + struct ethhdr *p_ethhdr; + struct nxpwifi_sta_node *src_node; + int index; + + uap_rx_pd =3D (struct uap_rxpd *)(skb->data); + rx_pkt_hdr =3D (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + + if ((atomic_read(&adapter->pending_bridged_pkts) >=3D + NXPWIFI_BRIDGED_PKTS_THR_HIGH)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Tx: Bridge packet limit reached. Drop packet!\n"); + kfree_skb(skb); + nxpwifi_uap_cleanup_tx_queues(priv); + return; + } + + if (sizeof(*rx_pkt_hdr) + + le16_to_cpu(uap_rx_pd->rx_pkt_offset) > skb->len) { + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return; + } + + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, + sizeof(bridge_tunnel_header))) || + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header)) && + rx_pkt_hdr->rfc1042_hdr.snap_type !=3D htons(ETH_P_AARP) && + rx_pkt_hdr->rfc1042_hdr.snap_type !=3D htons(ETH_P_IPX))) { + /* Replace the 803 header and rfc1042 header (llc/snap) with + * an Ethernet II header, keep the src/dst and snap_type + * (ethertype). + * + * The firmware only passes up SNAP frames converting all RX + * data from 802.11 to 802.2/LLC/SNAP frames. + * + * To create the Ethernet II, just move the src, dst address + * right before the snap_type. + */ + p_ethhdr =3D (struct ethhdr *) + ((u8 *)(&rx_pkt_hdr->eth803_hdr) + + sizeof(rx_pkt_hdr->eth803_hdr) + + sizeof(rx_pkt_hdr->rfc1042_hdr) + - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) + - sizeof(rx_pkt_hdr->eth803_hdr.h_source) + - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); + memcpy(p_ethhdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, + sizeof(p_ethhdr->h_source)); + memcpy(p_ethhdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, + sizeof(p_ethhdr->h_dest)); + /* Chop off the rxpd + the excess memory from + * 802.2/llc/snap header that was removed. + */ + hdr_chop =3D (u8 *)p_ethhdr - (u8 *)uap_rx_pd; + } else { + /* Chop off the rxpd */ + hdr_chop =3D (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd; + } + + /* Chop off the leading header bytes so that it points + * to the start of either the reconstructed EthII frame + * or the 802.2/llc/snap frame. + */ + skb_pull(skb, hdr_chop); + + if (skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN) { + nxpwifi_dbg(priv->adapter, ERROR, + "data: Tx: insufficient skb headroom %d\n", + skb_headroom(skb)); + /* Insufficient skb headroom - allocate a new skb */ + new_skb =3D + skb_realloc_headroom(skb, NXPWIFI_MIN_DATA_HEADER_LEN); + if (unlikely(!new_skb)) { + nxpwifi_dbg(priv->adapter, ERROR, + "Tx: cannot allocate new_skb\n"); + kfree_skb(skb); + priv->stats.tx_dropped++; + return; + } + + kfree_skb(skb); + skb =3D new_skb; + nxpwifi_dbg(priv->adapter, INFO, + "info: new skb headroom %d\n", + skb_headroom(skb)); + } + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num =3D priv->bss_num; + tx_info->bss_type =3D priv->bss_type; + tx_info->flags |=3D NXPWIFI_BUF_FLAG_BRIDGED_PKT; + + src_node =3D nxpwifi_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source); + if (src_node) { + src_node->stats.last_rx =3D jiffies; + src_node->stats.rx_bytes +=3D skb->len; + src_node->stats.rx_packets++; + src_node->stats.last_tx_rate =3D uap_rx_pd->rx_rate; + src_node->stats.last_tx_htinfo =3D uap_rx_pd->ht_info; + } + + if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) { + /* Update bridge packet statistics as the + * packet is not going to kernel/upper layer. + */ + priv->stats.rx_bytes +=3D skb->len; + priv->stats.rx_packets++; + + /* Sending bridge packet to TX queue, so save the packet + * length in TXCB to update statistics in TX complete. + */ + tx_info->pkt_len =3D skb->len; + } + + __net_timestamp(skb); + + index =3D nxpwifi_1d_to_wmm_queue[skb->priority]; + atomic_inc(&priv->wmm_tx_pending[index]); + nxpwifi_wmm_add_buf_txqueue(priv, skb); + atomic_inc(&adapter->tx_pending); + atomic_inc(&adapter->pending_bridged_pkts); + + nxpwifi_queue_main_work(priv->adapter); +} + +/* This function contains logic for AP packet forwarding. + * + * If a packet is multicast/broadcast, it is sent to kernel/upper layer + * as well as queued back to AP TX queue so that it can be sent to other + * associated stations. + * If a packet is unicast and RA is present in associated station list, + * it is again requeued into AP TX queue. + * If a packet is unicast and RA is not in associated station list, + * packet is forwarded to kernel to handle routing logic. + */ +int nxpwifi_handle_uap_rx_forward(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct uap_rxpd *uap_rx_pd; + struct rx_packet_hdr *rx_pkt_hdr; + u8 ra[ETH_ALEN]; + struct sk_buff *skb_uap; + + uap_rx_pd =3D (struct uap_rxpd *)(skb->data); + rx_pkt_hdr =3D (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + + /* don't do packet forwarding in disconnected state */ + if (!priv->media_connected) { + nxpwifi_dbg(adapter, ERROR, + "drop packet in disconnected state.\n"); + dev_kfree_skb_any(skb); + return 0; + } + + memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN); + + if (is_multicast_ether_addr(ra)) { + skb_uap =3D skb_copy(skb, GFP_ATOMIC); + if (likely(skb_uap)) { + nxpwifi_uap_queue_bridged_pkt(priv, skb_uap); + } else { + nxpwifi_dbg(adapter, ERROR, + "failed to copy skb for uAP\n"); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return -1; + } + } else { + if (nxpwifi_get_sta_entry(priv, ra)) { + /* Requeue Intra-BSS packet */ + nxpwifi_uap_queue_bridged_pkt(priv, skb); + return 0; + } + } + + /* Forward unicat/Inter-BSS packets to kernel. */ + return nxpwifi_process_rx_packet(priv, skb); +} + +int nxpwifi_uap_recv_packet(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_sta_node *src_node; + struct ethhdr *p_ethhdr; + struct sk_buff *skb_uap; + struct nxpwifi_txinfo *tx_info; + + if (!skb) + return -1; + + p_ethhdr =3D (void *)skb->data; + src_node =3D nxpwifi_get_sta_entry(priv, p_ethhdr->h_source); + if (src_node) { + src_node->stats.last_rx =3D jiffies; + src_node->stats.rx_bytes +=3D skb->len; + src_node->stats.rx_packets++; + } + + if (is_multicast_ether_addr(p_ethhdr->h_dest) || + nxpwifi_get_sta_entry(priv, p_ethhdr->h_dest)) { + if (skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN) + skb_uap =3D + skb_realloc_headroom(skb, NXPWIFI_MIN_DATA_HEADER_LEN); + else + skb_uap =3D skb_copy(skb, GFP_ATOMIC); + + if (likely(skb_uap)) { + tx_info =3D NXPWIFI_SKB_TXCB(skb_uap); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num =3D priv->bss_num; + tx_info->bss_type =3D priv->bss_type; + tx_info->flags |=3D NXPWIFI_BUF_FLAG_BRIDGED_PKT; + __net_timestamp(skb_uap); + nxpwifi_wmm_add_buf_txqueue(priv, skb_uap); + atomic_inc(&adapter->tx_pending); + atomic_inc(&adapter->pending_bridged_pkts); + if ((atomic_read(&adapter->pending_bridged_pkts) >=3D + NXPWIFI_BRIDGED_PKTS_THR_HIGH)) { + nxpwifi_dbg(adapter, ERROR, + "Tx: Bridge packet limit reached. Drop packet!\n"); + nxpwifi_uap_cleanup_tx_queues(priv); + } + + } else { + nxpwifi_dbg(adapter, ERROR, "failed to allocate skb_uap"); + } + + nxpwifi_queue_main_work(adapter); + /* Don't forward Intra-BSS unicast packet to upper layer*/ + if (nxpwifi_get_sta_entry(priv, p_ethhdr->h_dest)) + return 0; + } + + skb->dev =3D priv->netdev; + skb->protocol =3D eth_type_trans(skb, priv->netdev); + skb->ip_summed =3D CHECKSUM_NONE; + + /* Forward multicast/broadcast packet to upper layer*/ + netif_rx(skb); + return 0; +} + +/* This function processes the packet received on AP interface. + * + * The function looks into the RxPD and performs sanity tests on the + * received buffer to ensure its a valid packet before processing it + * further. If the packet is determined to be aggregated, it is + * de-aggregated accordingly. Then skb is passed to AP packet forwarding l= ogic. + * + * The completion callback is called after processing is complete. + */ +int nxpwifi_process_uap_rx_packet(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + struct uap_rxpd *uap_rx_pd; + struct rx_packet_hdr *rx_pkt_hdr; + u16 rx_pkt_type; + u8 ta[ETH_ALEN], pkt_type; + struct nxpwifi_sta_node *node; + + uap_rx_pd =3D (struct uap_rxpd *)(skb->data); + rx_pkt_type =3D le16_to_cpu(uap_rx_pd->rx_pkt_type); + rx_pkt_hdr =3D (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + + if (le16_to_cpu(uap_rx_pd->rx_pkt_offset) + + sizeof(rx_pkt_hdr->eth803_hdr) > skb->len) { + nxpwifi_dbg(adapter, ERROR, + "wrong rx packet for struct ethhdr: len=3D%d, offset=3D%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return 0; + } + + ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source); + + if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + + le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16)skb->len) { + nxpwifi_dbg(adapter, ERROR, + "wrong rx packet: len=3D%d, offset=3D%d, length=3D%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset), + le16_to_cpu(uap_rx_pd->rx_pkt_length)); + priv->stats.rx_dropped++; + + node =3D nxpwifi_get_sta_entry(priv, ta); + if (node) + node->stats.tx_failed++; + + dev_kfree_skb_any(skb); + return 0; + } + + if (rx_pkt_type =3D=3D PKT_TYPE_MGMT) { + ret =3D nxpwifi_process_mgmt_packet(priv, skb); + if (ret) + nxpwifi_dbg(adapter, DATA, "Rx of mgmt packet failed"); + dev_kfree_skb_any(skb); + return ret; + } + + if (rx_pkt_type !=3D PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) { + spin_lock_bh(&priv->sta_list_spinlock); + node =3D nxpwifi_get_sta_entry(priv, ta); + if (node) + node->rx_seq[uap_rx_pd->priority] =3D + le16_to_cpu(uap_rx_pd->seq_num); + spin_unlock_bh(&priv->sta_list_spinlock); + } + + if (!priv->ap_11n_enabled || + (!nxpwifi_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) && + (le16_to_cpu(uap_rx_pd->rx_pkt_type) !=3D PKT_TYPE_AMSDU))) { + ret =3D nxpwifi_handle_uap_rx_forward(priv, skb); + return ret; + } + + /* Reorder and send to kernel */ + pkt_type =3D (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type); + ret =3D nxpwifi_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num), + uap_rx_pd->priority, ta, pkt_type, + skb); + + if (ret || rx_pkt_type =3D=3D PKT_TYPE_BAR) + dev_kfree_skb_any(skb); + + if (ret) + priv->stats.rx_dropped++; + + return ret; +} + +/* This function fills the TxPD for AP tx packets. + * + * The Tx buffer received by this function should already have the + * header space allocated for TxPD. + * + * This function inserts the TxPD in between interface header and actual + * data and adjusts the buffer pointers accordingly. + * + * The following TxPD fields are set by this function, as required - + * - BSS number + * - Tx packet length and offset + * - Priority + * - Packet delay + * - Priority specific Tx control + * - Flags + */ +void nxpwifi_process_uap_txpd(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct uap_txpd *txpd; + struct nxpwifi_txinfo *tx_info =3D NXPWIFI_SKB_TXCB(skb); + int pad; + u16 pkt_type, pkt_offset; + int hroom =3D adapter->intf_hdr_len; + + pkt_type =3D nxpwifi_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; + + pad =3D ((uintptr_t)skb->data - (sizeof(*txpd) + hroom)) & + (NXPWIFI_DMA_ALIGN_SZ - 1); + + skb_push(skb, sizeof(*txpd) + pad); + + txpd =3D (struct uap_txpd *)skb->data; + memset(txpd, 0, sizeof(*txpd)); + txpd->bss_num =3D priv->bss_num; + txpd->bss_type =3D priv->bss_type; + txpd->tx_pkt_length =3D cpu_to_le16((u16)(skb->len - (sizeof(*txpd) + + pad))); + txpd->priority =3D (u8)skb->priority; + + txpd->pkt_delay_2ms =3D nxpwifi_wmm_compute_drv_pkt_delay(priv, skb); + + if (tx_info->flags & NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS || + tx_info->flags & NXPWIFI_BUF_FLAG_ACTION_TX_STATUS) { + txpd->tx_token_id =3D tx_info->ack_frame_id; + txpd->flags |=3D NXPWIFI_TXPD_FLAGS_REQ_TX_STATUS; + } + + if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) + /* Set the priority specific tx_control field, setting of 0 will + * cause the default value to be used later in this function. + */ + txpd->tx_control =3D + cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]); + + /* Offset of actual data */ + pkt_offset =3D sizeof(*txpd) + pad; + if (pkt_type =3D=3D PKT_TYPE_MGMT) { + /* Set the packet type and add header for management frame */ + txpd->tx_pkt_type =3D cpu_to_le16(pkt_type); + pkt_offset +=3D NXPWIFI_MGMT_FRAME_HEADER_SIZE; + } + + txpd->tx_pkt_offset =3D cpu_to_le16(pkt_offset); + + /* make space for adapter->intf_hdr_len */ + skb_push(skb, hroom); + + if (!txpd->tx_control) + /* TxCtrl set by user or default */ + txpd->tx_control =3D cpu_to_le32(priv->pkt_tx_ctrl); +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8185E17B4FA; Fri, 21 Jun 2024 07:54:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956484; cv=fail; b=lrPj+mQ9aesZxSBG2gvrDG3uRbJr8MCaqjVD/8dF1dnC8M6LQMY8vdcZjXb9qUGGu9bf3r6e7cEPSfJ00OJYWpsybBc+tZhG+YW5Nmhban8xjUWLlOuJICgBz6WmXgFOYjBSMc1tC0XQ1qHTQfMEj6IDf/j1D4u8HngDd/DDpuw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956484; c=relaxed/simple; bh=0HmNn4+BBR+bbJl+s7+BXYsdw22IJn/TF52d5VGlEOo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=fGHoViTX8x+l82OOY0lRxUfmH04NE0jNM1PU1bPzJ264/kv72zY97eO9yyDP03c52N7VY8RD3nMBa9RIvnogWMKfYaXWMP99ehvz6Zko5nDdnFaDkQ9BR1424QB0drvzQ8I8LuRoWo9q8RHK9v/ugd3cuyKngcz8ICk+6x3e2VA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=mlBegltU; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="mlBegltU" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nivpXUaPhDKxSaYUj3gm1UdDC+KilS2nPpaXtywL9oEjWS5z6EtdY8XWRxOGjbW8X6Q2QoyW1plGbm81CWQMDtpXEvU/sMNlYmpjdqnLJDA9JXR9XWc+UhF0SNpsUs754yg9I8Vit7fpIdewqmb7ZQJkmP2xmpAf7zMxzIuhiD56lIY9/ja/aGgE682v1yGAi87lPFPNXQwax96dGID5tMZg/+T1eKfCLG0SYcVXlWSrsDX1XupQlP72Myrj8fJLxnV1X1zfp1LuQC9/g1ein+oV8qwvmMBMN9vuIWgGhCuNiHW3Ej+a3ZQiiu7GkBhv35lmHyZ57Mp6IRKSZ/+DHQ== 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=rL6583ppDCL0yprVKFEyzZB01x8k9nUBxB/isQa77oE=; b=EiYFNGJ/8klcohrDmgeI1klrJrRBk5yd/5o77yW2ZJvZAKu78MdVJEZTdT0GFj1KEG2sm7GcDghYCoIEi47lk+qTcVSkJMu0bRnSDIfMPIZlx3vHE5EIoOd68/Ys3wqwrvvjDY7vkLOHC4UjZOR+Wsn4PVbGMh5YP4L6KZg8MFd2MmradODNzouKw/STGcDL8uMxVbaO/hvgGo79pu6pZHGHirwskzbDkTMyvVUJ6ycK9AhNN1skcUPiGvl/F71L0Sn9GLWZonwnZg0H2qfhL+JAiWjKdiMkDFqQOXmEIS4ZB70/D/6+qJEx5NAxSbjTsDJ1VN8+Jd+KwuRon2DQig== 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=rL6583ppDCL0yprVKFEyzZB01x8k9nUBxB/isQa77oE=; b=mlBegltUfhbkvZ7aB8s8vw9UWOnk8XPyy3u1LbmEzBniABS30vNRvrC3+8StU7kF7qNqrnKOH6i+LM8dmdm4r00KCkR5L7I3+xBw8IWQoSv+BHrEQL5eSyAE0m1k5yJz1XERd54Ah5zypJAkrH4kX7XWJy7us+aUMBFus7h88GM= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:36 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:36 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 37/43] wifi: nxpwifi: add util.c Date: Fri, 21 Jun 2024 15:52:02 +0800 Message-Id: <20240621075208.513497-38-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: ed2183c5-f93d-42d5-18f6-08dc91c76525 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?5J+8BA51plYsvYDkmjxZ8e9ZE/8FjoDycLYrV5FDfqowDWoZwPLwEbeLHCkU?= =?us-ascii?Q?LudUtfAIGCgpy+/ywQ45G1FE40ZdVkmFbK7G0KfBuBNxHoPV5y9tUoVQUJxJ?= =?us-ascii?Q?7qKUlPo2VLPJnZUrQSNXZE2blVyOocTI7NINXLCWa7Ia+rCSQzZ9AUZJjKUx?= =?us-ascii?Q?6wcgzgWBbM7BrRWk6QSoctXirqqiWXdxJuMWrAOdI9Uza+/ygFKBDVpZLq6H?= =?us-ascii?Q?LeNsb0OeVxbT6J//gKp6BKTsFc3vlX1g5HSPhJLRr7qQQS5eP+oSvHZvHYzN?= =?us-ascii?Q?lfAPVJ42XSvPJOGIKcGMLxAv+v15u78XoDm52YHFyM+ItHlfTn5ZmTh00qW+?= =?us-ascii?Q?/dosMAP18Ib9xPuRqY9yCJ3QSkjIf/KUZerB5k3MYuPNn4xKc8q4COnwt+En?= =?us-ascii?Q?upd5a1kkLWhKi2HZLLa6KGXRTsuuiYQcoWKZzuJtpqPQA/n7wOgvfAh+BGgu?= =?us-ascii?Q?A7fa1V0y+q7a27tEmXwQuwwfFBes+4uedqUE/N0uGnv+3xQGobJvCwL2pm5M?= =?us-ascii?Q?zncGJ6B06h8QxeloZezRUPFGizsN++zrV62SFWx/kuEixDmODvc4F9MwNkJv?= =?us-ascii?Q?Vfb4CJVG+H7OMmKDE+0AzjA3Zje2Nn/nxROstOq1uHIxLfpPHq6TQyRePmZd?= =?us-ascii?Q?qjJdKmvMIFM1bur7M5fkyK02WkEUJvXQfTkB9gRLXOyEqjh8tkbWQOgYRDWl?= =?us-ascii?Q?iyrjQC9xSkyNrllCBvUCFDLbB26Swm0Wuz9aWoizXDbTvQnOlxfegQVoLNlD?= =?us-ascii?Q?qDbvajW+Z9H6jb9YOWgQqhlU2jnwebBUbjsfqYy9yWO5hYSTgS7TyNVNsbdk?= =?us-ascii?Q?1WSgWNoLca5w0ZmYR9B1KG+ozUrYSX2reJfePsoYauoprYP3Pke1KIqe+L3X?= =?us-ascii?Q?9EjKz8dGYBLjL21tnTqlH3unaiBqTRiiP5ca8uNCW85sI12r7OljmIM4joMj?= =?us-ascii?Q?LwCYUwmB2Gwxn7mhOYC6CbUVKAs5UNgZ69Exy+IjqIzVgN/wPxCPGi5B6OYU?= =?us-ascii?Q?9SNW8/pQRnfIuWSGwKsxFzjocbVQfGBAFcubLMSPQc8u+NEwFPeANqCZ+GYc?= =?us-ascii?Q?us09mDTTUFge+WGDvdehYsT6dChIw1AuCmhT/0uxybn9pj97rPO4DoffKO8V?= =?us-ascii?Q?Jr4S1qc8hEwVdYCGAqaBPwadVaG3XEL25ozs4QHmlRR/AgSWhd/Ly3az2yoT?= =?us-ascii?Q?Ooj876iTkt1seAYVhZiuZU0FzFbSwQIyNNaGRrHWRh0QjiCyc1I914sVgwOW?= =?us-ascii?Q?qhuZmMjLMzUI6jwOoN+kQAU44Pq8vylCFLTVZyA7Z/GsF8Eyw8S/22KID73y?= =?us-ascii?Q?Ig4ta/fMWS+WNmdYgLcqu2L/QV94vIZumbJKkkUBuRbEzrOzm3UOiyAQzPPp?= =?us-ascii?Q?gm4rY70=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?cyyQzEwXMDjY/ej7BvCj8CDg4cGI7rjig0dBstlOIz//TfaU32JlRK0xit8K?= =?us-ascii?Q?CGjfXqYmLl35png63P66FUT3Fa/zCWkVSzCR3i1w5M/rGOwyoz/huixUJkpv?= =?us-ascii?Q?HywGshvhUplq4MyjtqHHSRJhcSAd67/aDDNyCqDg7D0isiNoiaBqAajTQEqH?= =?us-ascii?Q?iVuqjDOQ1Xb0nLBBFcFBYb+5K/PnkdB4MNCRmwQoucXoDYDT+G8IhYxCl5yU?= =?us-ascii?Q?dnNSbbRx+anptEzIkXBhoTTXwKWPFKd1iD4zVGzLJ4yRWXIt+HD1j7knYlek?= =?us-ascii?Q?V0T0YfS+O//KBlJOLDvzKF5fXCdfPkCExn4o3HIKdnOWsEmKuKjLEfMfZIA3?= =?us-ascii?Q?z3zezsm6aMHRKB9ArOs8RoqQ9IDfD7Z+Ub8LAXmTbMG+ttOq3WqvpTpmXi8A?= =?us-ascii?Q?L0f7VFQ0Ez8yvQT77Dqr5xFD12dXMnfI5WuAJCAirTNMJXffloIEkdBMl9Co?= =?us-ascii?Q?qcfHLfMqOXVt332d7DtcWu1Mk9l47ZzPKYFGrEEAxzYJGXWcl2OXEXDqlW+/?= =?us-ascii?Q?sDGMPmFWXYlYiv0QB3JXITIEOvt2quJfdn9HYn1Cu/f5HIlulT/FvCNIt48f?= =?us-ascii?Q?F1Wb9Y9JlWCOpvNawMjrlZVWrTkWw+e5fTkeI5LGNOpT0LKXcXBpy7Cd8ZPT?= =?us-ascii?Q?uJkTH5PfDTiuUpuGM9/pQFoaqo3gg7fFYEan2CY1ZcLBSYKqgddHuE+3PfW0?= =?us-ascii?Q?hgmgYC4TpTbCUbdh/XRbraP2eFLq/FmuujJ+5hfef8BxLhW9dxBcw0fEDro+?= =?us-ascii?Q?SI5kbDEN3oB9p4JoJYXLF2aiz1b8cB37MBpMNncA3K0Jn3lqF0vjAr2taJd9?= =?us-ascii?Q?WU6yiVkdGKjdDCzWDw8CxClFKpST3QzUIAEkPowlXoma0EVnHmv3Fp9yUln+?= =?us-ascii?Q?lI0TFgSrETDRhIDbEZt5cVPrkp5gwprnHG+qH8YMetR+mjlByCZomi/6CqJB?= =?us-ascii?Q?BVd52sgtNL4Dp8OgYDNUv56mHwZxbwRBhaep7L968DjD4TiNBi8MSkaWX2qB?= =?us-ascii?Q?BWwewOwKom3zpmOQRAKS738kthd/37HYUmMX2eT2N4z1S1Cu72J9QU36wtEa?= =?us-ascii?Q?sF4njDXeuZkvtVHVqDD3Y5SO+hE3R5oxWtsRG3tg8rkU5AdKUGzm8ejviPUZ?= =?us-ascii?Q?GIEViFGwGxYOUsG6b/Ci++SI2NzI3BX8Lnl8AoOvhSelgpwyJd3xIw+AYFaQ?= =?us-ascii?Q?w9UIprMFIC9jv757+x/q7QX8PYNyx23MPoITXfZGYH7J4K+hlV98kvZMc3s8?= =?us-ascii?Q?4/sraO/wQ/tTfdOyPfyJopo4uEYjfallHI1Iod7pURoD1diXnRCVhGPFvIDx?= =?us-ascii?Q?0dhDdpGUEZqEc5wCIQ/HXzLCXfKns0f/3Ngny5tChuEQpppuRlQ1HOwt2eKR?= =?us-ascii?Q?5pvpMjg+YU/+zmNLPaLxdlhLGNwUCYuFLlXf1RX9uJxqMiVDBezp0+SV8Ezt?= =?us-ascii?Q?rx8y6y7qEMl7RWhr0T3VNi2nbuIDmw7Xn40jZhPnRHCaAYEGqdJ+UzR5BzAk?= =?us-ascii?Q?ghQzucAwfAnUxZmIzxnqc3uuhoMGWLYFbom4z/tYn2+cn5iklmGiveEShof6?= =?us-ascii?Q?U6oFMZ0nh08YVcJhPgVOQ+ixJve1ELP1vTZUFPwI?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: ed2183c5-f93d-42d5-18f6-08dc91c76525 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:36.4876 (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: NtdaYG6h49oMdxsbKhRRAt/LAUK/ImlKU+BvwI6ZVe0a5wypI3Btp0PdRrvBO3aMSXyxY9bddmdMQ2PzzqD1cA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/util.c | 751 ++++++++++++++++++++++++ 1 file changed, 751 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/util.c diff --git a/drivers/net/wireless/nxp/nxpwifi/util.c b/drivers/net/wireless= /nxp/nxpwifi/util.c new file mode 100644 index 000000000000..bae1216e7599 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/util.c @@ -0,0 +1,751 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: utility functions + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cmdevt.h" +#include "wmm.h" +#include "11n.h" + +static struct nxpwifi_debug_data items[] =3D { + {"debug_mask", item_size(debug_mask), + item_addr(debug_mask), 1}, + {"int_counter", item_size(int_counter), + item_addr(int_counter), 1}, + {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]), + item_addr(packets_out[WMM_AC_VO]), 1}, + {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]), + item_addr(packets_out[WMM_AC_VI]), 1}, + {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]), + item_addr(packets_out[WMM_AC_BE]), 1}, + {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]), + item_addr(packets_out[WMM_AC_BK]), 1}, + {"tx_buf_size", item_size(tx_buf_size), + item_addr(tx_buf_size), 1}, + {"curr_tx_buf_size", item_size(curr_tx_buf_size), + item_addr(curr_tx_buf_size), 1}, + {"ps_mode", item_size(ps_mode), + item_addr(ps_mode), 1}, + {"ps_state", item_size(ps_state), + item_addr(ps_state), 1}, + {"is_deep_sleep", item_size(is_deep_sleep), + item_addr(is_deep_sleep), 1}, + {"wakeup_dev_req", item_size(pm_wakeup_card_req), + item_addr(pm_wakeup_card_req), 1}, + {"wakeup_tries", item_size(pm_wakeup_fw_try), + item_addr(pm_wakeup_fw_try), 1}, + {"hs_configured", item_size(is_hs_configured), + item_addr(is_hs_configured), 1}, + {"hs_activated", item_size(hs_activated), + item_addr(hs_activated), 1}, + {"num_tx_timeout", item_size(num_tx_timeout), + item_addr(num_tx_timeout), 1}, + {"is_cmd_timedout", item_size(is_cmd_timedout), + item_addr(is_cmd_timedout), 1}, + {"timeout_cmd_id", item_size(timeout_cmd_id), + item_addr(timeout_cmd_id), 1}, + {"timeout_cmd_act", item_size(timeout_cmd_act), + item_addr(timeout_cmd_act), 1}, + {"last_cmd_id", item_size(last_cmd_id), + item_addr(last_cmd_id), DBG_CMD_NUM}, + {"last_cmd_act", item_size(last_cmd_act), + item_addr(last_cmd_act), DBG_CMD_NUM}, + {"last_cmd_index", item_size(last_cmd_index), + item_addr(last_cmd_index), 1}, + {"last_cmd_resp_id", item_size(last_cmd_resp_id), + item_addr(last_cmd_resp_id), DBG_CMD_NUM}, + {"last_cmd_resp_index", item_size(last_cmd_resp_index), + item_addr(last_cmd_resp_index), 1}, + {"last_event", item_size(last_event), + item_addr(last_event), DBG_CMD_NUM}, + {"last_event_index", item_size(last_event_index), + item_addr(last_event_index), 1}, + {"last_mp_wr_bitmap", item_size(last_mp_wr_bitmap), + item_addr(last_mp_wr_bitmap), NXPWIFI_DBG_SDIO_MP_NUM}, + {"last_mp_wr_ports", item_size(last_mp_wr_ports), + item_addr(last_mp_wr_ports), NXPWIFI_DBG_SDIO_MP_NUM}, + {"last_mp_wr_len", item_size(last_mp_wr_len), + item_addr(last_mp_wr_len), NXPWIFI_DBG_SDIO_MP_NUM}, + {"last_mp_curr_wr_port", item_size(last_mp_curr_wr_port), + item_addr(last_mp_curr_wr_port), NXPWIFI_DBG_SDIO_MP_NUM}, + {"last_sdio_mp_index", item_size(last_sdio_mp_index), + item_addr(last_sdio_mp_index), 1}, + {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), + item_addr(num_cmd_host_to_card_failure), 1}, + {"num_cmd_sleep_cfm_fail", + item_size(num_cmd_sleep_cfm_host_to_card_failure), + item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1}, + {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure), + item_addr(num_tx_host_to_card_failure), 1}, + {"num_evt_deauth", item_size(num_event_deauth), + item_addr(num_event_deauth), 1}, + {"num_evt_disassoc", item_size(num_event_disassoc), + item_addr(num_event_disassoc), 1}, + {"num_evt_link_lost", item_size(num_event_link_lost), + item_addr(num_event_link_lost), 1}, + {"num_cmd_deauth", item_size(num_cmd_deauth), + item_addr(num_cmd_deauth), 1}, + {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success), + item_addr(num_cmd_assoc_success), 1}, + {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure), + item_addr(num_cmd_assoc_failure), 1}, + {"cmd_sent", item_size(cmd_sent), + item_addr(cmd_sent), 1}, + {"data_sent", item_size(data_sent), + item_addr(data_sent), 1}, + {"cmd_resp_received", item_size(cmd_resp_received), + item_addr(cmd_resp_received), 1}, + {"event_received", item_size(event_received), + item_addr(event_received), 1}, + + /* variables defined in struct nxpwifi_adapter */ + {"cmd_pending", adapter_item_size(cmd_pending), + adapter_item_addr(cmd_pending), 1}, + {"tx_pending", adapter_item_size(tx_pending), + adapter_item_addr(tx_pending), 1}, + {"rx_pending", adapter_item_size(rx_pending), + adapter_item_addr(rx_pending), 1}, +}; + +static int num_of_items =3D ARRAY_SIZE(items); + +/* Firmware initialization complete callback handler. + * + * This function wakes up the function waiting on the init + * wait queue for the firmware initialization to complete. + */ +int nxpwifi_init_fw_complete(struct nxpwifi_adapter *adapter) +{ + adapter->init_wait_q_woken =3D true; + wake_up_interruptible(&adapter->init_wait_q); + return 0; +} + +/* This function sends init/shutdown command + * to firmware. + */ +int nxpwifi_init_shutdown_fw(struct nxpwifi_private *priv, + u32 func_init_shutdown) +{ + u16 cmd; + + if (func_init_shutdown =3D=3D NXPWIFI_FUNC_INIT) { + cmd =3D HOST_CMD_FUNC_INIT; + } else if (func_init_shutdown =3D=3D NXPWIFI_FUNC_SHUTDOWN) { + cmd =3D HOST_CMD_FUNC_SHUTDOWN; + } else { + nxpwifi_dbg(priv->adapter, ERROR, + "unsupported parameter\n"); + return -1; + } + + return nxpwifi_send_cmd(priv, cmd, HOST_ACT_GEN_SET, 0, NULL, true); +} +EXPORT_SYMBOL_GPL(nxpwifi_init_shutdown_fw); + +/* IOCTL request handler to set/get debug information. + * + * This function collates/sets the information from/to different driver + * structures. + */ +int nxpwifi_get_debug_info(struct nxpwifi_private *priv, + struct nxpwifi_debug_info *info) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + if (info) { + info->debug_mask =3D adapter->debug_mask; + memcpy(info->packets_out, + priv->wmm.packets_out, + sizeof(priv->wmm.packets_out)); + info->curr_tx_buf_size =3D (u32)adapter->curr_tx_buf_size; + info->tx_buf_size =3D (u32)adapter->tx_buf_size; + info->rx_tbl_num =3D nxpwifi_get_rx_reorder_tbl(priv, + info->rx_tbl); + info->tx_tbl_num =3D nxpwifi_get_tx_ba_stream_tbl(priv, + info->tx_tbl); + info->ps_mode =3D adapter->ps_mode; + info->ps_state =3D adapter->ps_state; + info->is_deep_sleep =3D adapter->is_deep_sleep; + info->pm_wakeup_card_req =3D adapter->pm_wakeup_card_req; + info->pm_wakeup_fw_try =3D adapter->pm_wakeup_fw_try; + info->is_hs_configured =3D test_bit(NXPWIFI_IS_HS_CONFIGURED, + &adapter->work_flags); + info->hs_activated =3D adapter->hs_activated; + info->is_cmd_timedout =3D test_bit(NXPWIFI_IS_CMD_TIMEDOUT, + &adapter->work_flags); + info->num_cmd_host_to_card_failure =3D + adapter->dbg.num_cmd_host_to_card_failure; + info->num_cmd_sleep_cfm_host_to_card_failure =3D + adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure; + info->num_tx_host_to_card_failure =3D + adapter->dbg.num_tx_host_to_card_failure; + info->num_event_deauth =3D adapter->dbg.num_event_deauth; + info->num_event_disassoc =3D adapter->dbg.num_event_disassoc; + info->num_event_link_lost =3D adapter->dbg.num_event_link_lost; + info->num_cmd_deauth =3D adapter->dbg.num_cmd_deauth; + info->num_cmd_assoc_success =3D + adapter->dbg.num_cmd_assoc_success; + info->num_cmd_assoc_failure =3D + adapter->dbg.num_cmd_assoc_failure; + info->num_tx_timeout =3D adapter->dbg.num_tx_timeout; + info->timeout_cmd_id =3D adapter->dbg.timeout_cmd_id; + info->timeout_cmd_act =3D adapter->dbg.timeout_cmd_act; + memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, + sizeof(adapter->dbg.last_cmd_id)); + memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act, + sizeof(adapter->dbg.last_cmd_act)); + info->last_cmd_index =3D adapter->dbg.last_cmd_index; + memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id, + sizeof(adapter->dbg.last_cmd_resp_id)); + info->last_cmd_resp_index =3D adapter->dbg.last_cmd_resp_index; + memcpy(info->last_event, adapter->dbg.last_event, + sizeof(adapter->dbg.last_event)); + info->last_event_index =3D adapter->dbg.last_event_index; + memcpy(info->last_mp_wr_bitmap, adapter->dbg.last_mp_wr_bitmap, + sizeof(adapter->dbg.last_mp_wr_bitmap)); + memcpy(info->last_mp_wr_ports, adapter->dbg.last_mp_wr_ports, + sizeof(adapter->dbg.last_mp_wr_ports)); + memcpy(info->last_mp_curr_wr_port, + adapter->dbg.last_mp_curr_wr_port, + sizeof(adapter->dbg.last_mp_curr_wr_port)); + memcpy(info->last_mp_wr_len, adapter->dbg.last_mp_wr_len, + sizeof(adapter->dbg.last_mp_wr_len)); + info->last_sdio_mp_index =3D adapter->dbg.last_sdio_mp_index; + info->data_sent =3D adapter->data_sent; + info->cmd_sent =3D adapter->cmd_sent; + info->cmd_resp_received =3D adapter->cmd_resp_received; + } + + return 0; +} + +int nxpwifi_debug_info_to_buffer(struct nxpwifi_private *priv, char *buf, + struct nxpwifi_debug_info *info) +{ + char *p =3D buf; + struct nxpwifi_debug_data *d =3D &items[0]; + size_t size, addr; + long val; + int i, j; + + if (!info) + return 0; + + for (i =3D 0; i < num_of_items; i++) { + p +=3D sprintf(p, "%s=3D", d[i].name); + + size =3D d[i].size / d[i].num; + + if (i < (num_of_items - 3)) + addr =3D d[i].addr + (size_t)info; + else /* The last 3 items are struct nxpwifi_adapter variables */ + addr =3D d[i].addr + (size_t)priv->adapter; + + for (j =3D 0; j < d[i].num; j++) { + switch (size) { + case 1: + val =3D *((u8 *)addr); + break; + case 2: + val =3D get_unaligned((u16 *)addr); + break; + case 4: + val =3D get_unaligned((u32 *)addr); + break; + case 8: + val =3D get_unaligned((long long *)addr); + break; + default: + val =3D -1; + break; + } + + p +=3D sprintf(p, "%#lx ", val); + addr +=3D size; + } + + p +=3D sprintf(p, "\n"); + } + + if (info->tx_tbl_num) { + p +=3D sprintf(p, "Tx BA stream table:\n"); + for (i =3D 0; i < info->tx_tbl_num; i++) + p +=3D sprintf(p, "tid =3D %d, ra =3D %pM\n", + info->tx_tbl[i].tid, info->tx_tbl[i].ra); + } + + if (info->rx_tbl_num) { + p +=3D sprintf(p, "Rx reorder table:\n"); + for (i =3D 0; i < info->rx_tbl_num; i++) { + p +=3D sprintf(p, "tid =3D %d, ta =3D %pM, ", + info->rx_tbl[i].tid, + info->rx_tbl[i].ta); + p +=3D sprintf(p, "start_win =3D %d, ", + info->rx_tbl[i].start_win); + p +=3D sprintf(p, "win_size =3D %d, buffer: ", + info->rx_tbl[i].win_size); + + for (j =3D 0; j < info->rx_tbl[i].win_size; j++) + p +=3D sprintf(p, "%c ", + info->rx_tbl[i].buffer[j] ? + '1' : '0'); + + p +=3D sprintf(p, "\n"); + } + } + + return p - buf; +} + +static int +nxpwifi_parse_mgmt_packet(struct nxpwifi_private *priv, u8 *payload, u16 l= en, + struct rxpd *rx_pd) +{ + u16 stype; + u8 category; + struct ieee80211_hdr *ieee_hdr =3D (void *)payload; + + stype =3D (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE); + + switch (stype) { + case IEEE80211_STYPE_ACTION: + category =3D *(payload + sizeof(struct ieee80211_hdr)); + switch (category) { + case WLAN_CATEGORY_BACK: + /*we dont indicate BACK action frames to cfg80211*/ + nxpwifi_dbg(priv->adapter, INFO, + "drop BACK action frames"); + return -1; + default: + nxpwifi_dbg(priv->adapter, INFO, + "unknown public action frame category %d\n", + category); + } + break; + default: + nxpwifi_dbg(priv->adapter, INFO, + "unknown mgmt frame subtype %#x\n", stype); + return 0; + } + + return 0; +} + +/* This function sends deauth packet to the kernel. */ +void nxpwifi_host_mlme_disconnect(struct nxpwifi_private *priv, + u16 reason_code, u8 *sa) +{ + u8 frame_buf[100]; + struct ieee80211_mgmt *mgmt =3D (struct ieee80211_mgmt *)frame_buf; + + memset(frame_buf, 0, sizeof(frame_buf)); + mgmt->frame_control =3D cpu_to_le16(IEEE80211_STYPE_DEAUTH); + mgmt->duration =3D 0; + mgmt->seq_ctrl =3D 0; + mgmt->u.deauth.reason_code =3D cpu_to_le16(reason_code); + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_STA) { + eth_broadcast_addr(mgmt->da); + memcpy(mgmt->sa, + priv->curr_bss_params.bss_descriptor.mac_address, + ETH_ALEN); + memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN); + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + } 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) !=3D NXPWIFI_BSS_ROLE_UAP) { + wiphy_lock(priv->wdev.wiphy); + cfg80211_rx_mlme_mgmt(priv->netdev, frame_buf, 26); + wiphy_unlock(priv->wdev.wiphy); + } 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. + */ +int +nxpwifi_process_mgmt_packet(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct rxpd *rx_pd; + u16 pkt_len; + struct ieee80211_hdr *ieee_hdr; + + if (!skb) + return -1; + + if (!priv->mgmt_frame_mask || + priv->wdev.iftype =3D=3D NL80211_IFTYPE_UNSPECIFIED) { + nxpwifi_dbg(priv->adapter, ERROR, + "do not receive mgmt frames on uninitialized intf"); + return -1; + } + + rx_pd =3D (struct rxpd *)skb->data; + pkt_len =3D le16_to_cpu(rx_pd->rx_pkt_length); + if (pkt_len < sizeof(struct ieee80211_hdr) + sizeof(pkt_len)) { + nxpwifi_dbg(priv->adapter, ERROR, "invalid rx_pkt_length"); + return -1; + } + + skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); + skb_pull(skb, sizeof(pkt_len)); + pkt_len -=3D sizeof(pkt_len); + + ieee_hdr =3D (void *)skb->data; + if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { + if (nxpwifi_parse_mgmt_packet(priv, (u8 *)ieee_hdr, + pkt_len, rx_pd)) + return -1; + } + /* Remove address4 */ + memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), + skb->data + sizeof(struct ieee80211_hdr), + pkt_len - sizeof(struct ieee80211_hdr)); + + pkt_len -=3D ETH_ALEN; + rx_pd->rx_pkt_length =3D cpu_to_le16(pkt_len); + + if (priv->host_mlme_reg && + (GET_BSS_ROLE(priv) !=3D NXPWIFI_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 !=3D WLAN_AUTH_SAE) { + priv->auth_flag &=3D + ~HOST_MLME_AUTH_PENDING; + priv->auth_flag |=3D + HOST_MLME_AUTH_DONE; + } + } else { + return 0; + } + + nxpwifi_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)) { + nxpwifi_dbg(priv->adapter, MSG, + "auth: receive deauth from %pM\n", + ieee_hdr->addr3); + priv->auth_flag =3D 0; + priv->auth_alg =3D WLAN_AUTH_NONE; + } else { + nxpwifi_dbg(priv->adapter, MSG, + "assoc: receive disassoc from %pM\n", + ieee_hdr->addr3); + } + } + + cfg80211_rx_mlme_mgmt(priv->netdev, skb->data, pkt_len); + } + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + if (ieee80211_is_auth(ieee_hdr->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "auth: receive auth from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_deauth(ieee_hdr->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "auth: receive deauth from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_disassoc(ieee_hdr->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "assoc: receive disassoc from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_assoc_req(ieee_hdr->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "assoc: receive assoc req from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_reassoc_req(ieee_hdr->frame_control)) + nxpwifi_dbg(priv->adapter, MSG, + "assoc: receive reassoc req from %pM\n", + ieee_hdr->addr2); + } + + cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq, + CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, + 0); + + return 0; +} + +/* This function processes the received packet before sending it to the + * kernel. + * + * It extracts the SKB from the received buffer and sends it to kernel. + * In case the received buffer does not contain the data in SKB format, + * the function creates a blank SKB, fills it with the data from the + * received buffer and then sends this new SKB to the kernel. + */ +int nxpwifi_recv_packet(struct nxpwifi_private *priv, struct sk_buff *skb) +{ + struct nxpwifi_sta_node *src_node; + struct ethhdr *p_ethhdr; + + if (!skb) + return -1; + + priv->stats.rx_bytes +=3D skb->len; + priv->stats.rx_packets++; + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + p_ethhdr =3D (void *)skb->data; + src_node =3D nxpwifi_get_sta_entry(priv, p_ethhdr->h_source); + if (src_node) { + src_node->stats.last_rx =3D jiffies; + src_node->stats.rx_bytes +=3D skb->len; + src_node->stats.rx_packets++; + } + } + + skb->dev =3D priv->netdev; + skb->protocol =3D eth_type_trans(skb, priv->netdev); + skb->ip_summed =3D CHECKSUM_NONE; + + netif_rx(skb); + return 0; +} + +/* IOCTL completion callback handler. + * + * This function is called when a pending IOCTL is completed. + * + * If work queue support is enabled, the function wakes up the + * corresponding waiting function. Otherwise, it processes the + * IOCTL response and frees the response buffer. + */ +int nxpwifi_complete_cmd(struct nxpwifi_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + WARN_ON(!cmd_node->wait_q_enabled); + nxpwifi_dbg(adapter, CMD, "cmd completed: status=3D%d\n", + adapter->cmd_wait_q.status); + + *cmd_node->condition =3D true; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + + return 0; +} + +/* This function will return the pointer to station entry in station list + * table which matches specified mac address. + * This function should be called after acquiring RA list spinlock. + * NULL is returned if station entry is not found in associated STA list. + */ +struct nxpwifi_sta_node * +nxpwifi_get_sta_entry(struct nxpwifi_private *priv, const u8 *mac) +{ + struct nxpwifi_sta_node *node; + + if (!mac) + return NULL; + + list_for_each_entry(node, &priv->sta_list, list) { + if (!memcmp(node->mac_addr, mac, ETH_ALEN)) + return node; + } + + return NULL; +} + +/* This function will add a sta_node entry to associated station list + * table with the given mac address. + * If entry exist already, existing entry is returned. + * If received mac address is NULL, NULL is returned. + */ +struct nxpwifi_sta_node * +nxpwifi_add_sta_entry(struct nxpwifi_private *priv, const u8 *mac) +{ + struct nxpwifi_sta_node *node; + + if (!mac) + return NULL; + + spin_lock_bh(&priv->sta_list_spinlock); + node =3D nxpwifi_get_sta_entry(priv, mac); + if (node) + goto done; + + node =3D kzalloc(sizeof(*node), GFP_ATOMIC); + if (!node) + goto done; + + memcpy(node->mac_addr, mac, ETH_ALEN); + list_add_tail(&node->list, &priv->sta_list); + +done: + spin_unlock_bh(&priv->sta_list_spinlock); + return node; +} + +/* This function will search for HT IE in association request IEs + * and set station HT parameters accordingly. + */ +void +nxpwifi_set_sta_ht_cap(struct nxpwifi_private *priv, const u8 *ies, + int ies_len, struct nxpwifi_sta_node *node) +{ + struct ieee_types_header *ht_cap_ie; + const struct ieee80211_ht_cap *ht_cap; + + if (!ies) + return; + + ht_cap_ie =3D (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, + ies_len); + if (ht_cap_ie) { + ht_cap =3D (void *)(ht_cap_ie + 1); + node->is_11n_enabled =3D 1; + node->max_amsdu =3D le16_to_cpu(ht_cap->cap_info) & + IEEE80211_HT_CAP_MAX_AMSDU ? + NXPWIFI_TX_DATA_BUF_SIZE_8K : + NXPWIFI_TX_DATA_BUF_SIZE_4K; + } else { + node->is_11n_enabled =3D 0; + } +} + +/* This function will delete a station entry from station list */ +void nxpwifi_del_sta_entry(struct nxpwifi_private *priv, const u8 *mac) +{ + struct nxpwifi_sta_node *node; + + spin_lock_bh(&priv->sta_list_spinlock); + + node =3D nxpwifi_get_sta_entry(priv, mac); + if (node) { + list_del(&node->list); + kfree(node); + } + + spin_unlock_bh(&priv->sta_list_spinlock); +} + +/* This function will delete all stations from associated station list. */ +void nxpwifi_del_all_sta_list(struct nxpwifi_private *priv) +{ + struct nxpwifi_sta_node *node, *tmp; + + spin_lock_bh(&priv->sta_list_spinlock); + + list_for_each_entry_safe(node, tmp, &priv->sta_list, list) { + list_del(&node->list); + kfree(node); + } + + INIT_LIST_HEAD(&priv->sta_list); + spin_unlock_bh(&priv->sta_list_spinlock); +} + +/* This function adds histogram data to histogram array*/ +void nxpwifi_hist_data_add(struct nxpwifi_private *priv, + u8 rx_rate, s8 snr, s8 nflr) +{ + struct nxpwifi_histogram_data *phist_data =3D priv->hist_data; + + if (atomic_read(&phist_data->num_samples) > NXPWIFI_HIST_MAX_SAMPLES) + nxpwifi_hist_data_reset(priv); + nxpwifi_hist_data_set(priv, rx_rate, snr, nflr); +} + +/* function to add histogram record */ +void nxpwifi_hist_data_set(struct nxpwifi_private *priv, u8 rx_rate, s8 sn= r, + s8 nflr) +{ + struct nxpwifi_histogram_data *phist_data =3D priv->hist_data; + s8 nf =3D -nflr; + s8 rssi =3D snr - nflr; + + atomic_inc(&phist_data->num_samples); + atomic_inc(&phist_data->rx_rate[rx_rate]); + atomic_inc(&phist_data->snr[snr + 128]); + atomic_inc(&phist_data->noise_flr[nf + 128]); + atomic_inc(&phist_data->sig_str[rssi + 128]); +} + +/* function to reset histogram data during init/reset */ +void nxpwifi_hist_data_reset(struct nxpwifi_private *priv) +{ + int ix; + struct nxpwifi_histogram_data *phist_data =3D priv->hist_data; + + atomic_set(&phist_data->num_samples, 0); + for (ix =3D 0; ix < NXPWIFI_MAX_AC_RX_RATES; ix++) + atomic_set(&phist_data->rx_rate[ix], 0); + for (ix =3D 0; ix < NXPWIFI_MAX_SNR; ix++) + atomic_set(&phist_data->snr[ix], 0); + for (ix =3D 0; ix < NXPWIFI_MAX_NOISE_FLR; ix++) + atomic_set(&phist_data->noise_flr[ix], 0); + for (ix =3D 0; ix < NXPWIFI_MAX_SIG_STRENGTH; ix++) + atomic_set(&phist_data->sig_str[ix], 0); +} + +void *nxpwifi_alloc_dma_align_buf(int rx_len, gfp_t flags) +{ + struct sk_buff *skb; + int buf_len, pad; + + buf_len =3D rx_len + NXPWIFI_RX_HEADROOM + NXPWIFI_DMA_ALIGN_SZ; + + skb =3D __dev_alloc_skb(buf_len, flags); + + if (!skb) + return NULL; + + skb_reserve(skb, NXPWIFI_RX_HEADROOM); + + pad =3D NXPWIFI_ALIGN_ADDR(skb->data, NXPWIFI_DMA_ALIGN_SZ) - + (long)skb->data; + + skb_reserve(skb, pad); + + return skb; +} +EXPORT_SYMBOL_GPL(nxpwifi_alloc_dma_align_buf); + +void nxpwifi_fw_dump_event(struct nxpwifi_private *priv) +{ + nxpwifi_send_cmd(priv, HOST_CMD_FW_DUMP_EVENT, HOST_ACT_GEN_SET, + 0, NULL, true); +} +EXPORT_SYMBOL_GPL(nxpwifi_fw_dump_event); + +int nxpwifi_append_data_tlv(u16 id, u8 *data, int len, u8 *pos, u8 *cmd_en= d) +{ + struct nxpwifi_ie_types_data *tlv; + u16 header_len =3D sizeof(struct nxpwifi_ie_types_header); + + if (pos + len > cmd_end) + return 0; + + tlv =3D (struct nxpwifi_ie_types_data *)pos; + tlv->header.type =3D cpu_to_le16(id); + tlv->header.len =3D cpu_to_le16(len); + memcpy(tlv->data, data, len); + + return (header_len + len); +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9CD4017BB08; Fri, 21 Jun 2024 07:54:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956486; cv=fail; b=FQMGOfR16ESm3pe8Wg/q7aT1OPt1yq4IJIMRb0RPUnSYK5TqEMuItDBO+/pxOBELuIAu8B3D5or1sAKlzW/mLRWb65KwtqNEGhxpZgPJNMZsMDxuMwCl6E+cRdGW0ySZis7uaFLSEj/ae0WrFwH1606E+tQIIoy5hElYzEpck4I= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956486; c=relaxed/simple; bh=nGAYl9p0ukgl9GAscW0O1woUwz9Lx9h1HW8yx74dqsQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=d+VixSZZL7VQoi5UIdyztmOY06qb+3BSKzNk0xFKD4Q8KrlJp/sZV6Wk34qxsuNQVd3coKgS90ZjtzyqgAlSFV9lgN7u+Se2F1fWQA8W0gBBkNC70JN8MbpZoG7kQ4saoCpp25NgcZbE+mNAJSSEDF6jORnHBl/oRjBvAluJPkI= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=Umxayas0; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="Umxayas0" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UWe1zdVYf67cJmDFIFfYsYNMvn9Ez3oiY8pDezydrM2rp9dpEkCv+yzoTZAhv9S83OOT7pVgwGONwOSXbOGJ5h2KrhPGfcU1f+y9Gq6YVEc2v650RQe45UosY+zXKX6CxlV5IxzZ3Hj27S0MF/39Vq5TNM11i8Tu9dgmRfozsfCdE2GfDjtAkpqOvJ6dOYKactZE3PB8d3rsjCL5rxd5G+Fz3+T3Y2lUSKFzcw/sQOJNA6AxzFlKOkSSIRrr576AzMeUrtdC2S5aqq9atwyYZHIKB40MwDz7MC777We6oVbF6idl6lBemHzKW3BfqAxA8e1sOEGF7qwwOjbXYR/MVQ== 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=JuhOydKWuHZgMBC03Swx3VgXDJPXQEtyZoJJQkEVy5c=; b=hRK+MQhLyf16NvPXOMfQdZ/YS0pOYR6fTtZWeJzZHzBT6mu5PguqrGQIQfwRB6+AhG2yxqB7MbcRDa+1y43GZ60xsG5wrzQKxb0Nd3U/zJUEljiLYL3P0QeWnBe7gskNHl2U5bULdJZoy2m3x8QuwQ/9WyEjYYSKkFjaXlPOAG+wm5gdfmB5vhsyPF4RQ3VhA/DM2JtobkWZtstCEXaqHImkLJ6OnF2kTGE9CUQBiqysHkpmtczZDLw/XlSz4vFljgdsASfEepJWPnA59DfsEqys5cb0n+nH0XhWKpShbDPpOFaD8qoQcNCyjPCQ6eRXXc9w0bbedbsk7tZTBKt5nA== 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=JuhOydKWuHZgMBC03Swx3VgXDJPXQEtyZoJJQkEVy5c=; b=Umxayas0CynCyz7hnA/uW9/qzk27Pl3ZBf5kD9zrJ1YkMaq0WVFlliJcBw9pFx9dgKmD0OtEgcsfEggon6nzxmxuc5bJB+jEPrX8+HP8G1AqtctgxcKKf8ScpXBRFLIiNJN2mXCpmE+kVhMEVx6NPD2PKt1dDevmXFo+GSxNVPQ= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:39 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:39 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 38/43] wifi: nxpwifi: add util.h Date: Fri, 21 Jun 2024 15:52:03 +0800 Message-Id: <20240621075208.513497-39-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: fab89f7f-bfa6-476b-7c96-08dc91c766f3 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?wgPSQmbtLvgYhRfcXtI1S3N0rHZL9eLH41g6ZHqga992EeiT5URzpv8rMic2?= =?us-ascii?Q?5TvUPpzXw75qK1+wdz4IMvjg+dcthxpclGjaiFu+uo0SzwJKKbZQxSKqT3e5?= =?us-ascii?Q?a/H3eiEsKRl0oy2oC8A6SFVwtgCtlftyFiATlJk8FvEcw+FH9z5j4dNPV3GM?= =?us-ascii?Q?tW2OqoMlf5u/3fNhKcyyIUPTwxj1F2t8ylXYzd9CwRSKXDCcJq6sAAgYv/34?= =?us-ascii?Q?BgEmIrY48eTZaBLfJiPoeJhTFtKcNjrzV5AFp30miaqNj5gt368jBkF44d3e?= =?us-ascii?Q?EUQEnen7+9SA+wH6K6P8q+2X+JQDFj2UEwybFgPtrJzZDlDQLiDO+7jPUn5K?= =?us-ascii?Q?fdUplM72FI3IfcYNLET7uLXg82xJ4ccCYPDs+aQlZPBMPpMI6UPvFpwPADRn?= =?us-ascii?Q?ME3xGp8asdRcovOU3m7ud4VEpBX1Jwd6UBnU566PvMLl4QF4INKU+XHd0uXm?= =?us-ascii?Q?Tqbg7Zu1X+azLmkL7jYJyNR39T+Ir7wy1bWvlvBteaRPSaQAMCh/PRtslO8I?= =?us-ascii?Q?u3SuG4dVtwNN3niEDF21cS8diTKgzdjq+/dVs/OGm9Dg8MhL7bjzLhV/rqhE?= =?us-ascii?Q?Xr0l1YXxj5FnDwX2bzBqGwIs5LAqT6LflXvDs8O9pJtg4S2b8YTDqwfKmlZU?= =?us-ascii?Q?C6FHxvccv4XiwkNFW2uH0mridW8kqGP+mpnQfQ80bwaoS1oBg4nvCQBoBY5X?= =?us-ascii?Q?6kjQH0kdd8D4h1HP0xTfqaIM5HcGIdCHDAUWaQwhkhqVV0yxKrVTEdKf481e?= =?us-ascii?Q?J7ITHOOhnCcHDXxlSHiv0KRBiMZQvLU9YmXW2IjZ8iPPW6wL4D/ZkKFJL1Xb?= =?us-ascii?Q?4/K53uUt+kQwkP2eG5UITk+6gqIiuGqtVYc419FWoOSxlmONMCbj5zFBLous?= =?us-ascii?Q?xftduDt0sZWB48E4/Tm8Djj2XdyGk9qpwmhSpPjbsxt8rtb0sG+9YGUVFoAA?= =?us-ascii?Q?CBdRmRarXJSUktW8vjSH1IXcTCP8nHaErBJ7wsYHgM2nCf5dfH/xhdEUjko6?= =?us-ascii?Q?zMO2vm/Ar4KsJGE1oG+U3Eu9VASysFixSER2PGZTqBYj60ghBtVVQUnwF3GB?= =?us-ascii?Q?RJdtkS+BsGyE2GI3ptRtQQ4McktMKrATmR748tpUSYQThMf2L6vXLuThSnPG?= =?us-ascii?Q?2TqLD4QcU75+Kwk3DrmEaEl2cEmXD9vARMRGvk0v+8N26rqJWkQUFSUELkRk?= =?us-ascii?Q?6FkAmep5T8z3wmAynxNbrWjrc0faJCS4iSpuAJIfnuiA3c5+Nsp6LL3/i1DB?= =?us-ascii?Q?ey0lBdNQF/Ep6Y32tKWGSpFqw2VRQquF92ivyEgR6aCfLNiQNiFaMwGpv4Wt?= =?us-ascii?Q?W2djisbzJiskGVa3kLEJPMYC45WE3ubXUIePfCPFkNkCKQi7pM/xjCDI11gI?= =?us-ascii?Q?u4qGFG4=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?TzWws+6pQIb+7T1wSAD2fK4MxURcyWbUqXICbyrPhnoGbNv1X/trAsC7RBPL?= =?us-ascii?Q?pDncIxbMcCJdJ57wNmxxPq1HqzwtrPKOdvPuns8d4YXmoFDL2mJuWsdIUEq/?= =?us-ascii?Q?s6vtQZKPaEcuI8eAj7hCx312GksiZyMYC1GQGdpOjLYk5P0fnCROF0o9dKzH?= =?us-ascii?Q?nTmLmBVNq1fJHSUoBXRa4IabfU4hIU+V2SZ5zzj5OTysUGXnEHX9GaKWUMwC?= =?us-ascii?Q?W4PSqhckYS6OpUA4MMX4P3lznVQRFZhsz//BgaIStiibyjxkhV9cZl3ToPm5?= =?us-ascii?Q?Kt8eFTGRGjbr/ZRRuzCqFGbOLECnDtkVpfsuzU80c5g5JYb514nfZNV0Cgqr?= =?us-ascii?Q?gPeZT9gAZXiv+oksrxT8A8Tt+JoEab91ipB/fzpWsqx/ywgg3qdOldGkgEru?= =?us-ascii?Q?U0ia9Nr5QhexyhDkFaBMUK5bDG/8Koo2OFk0niTgZwU8P2ibbRn/sLnyJsBm?= =?us-ascii?Q?rOA0LBmMf7IWgHK7eBWEr2eCBKufOKYQhiq2jYBw7hFu/vF03+SudOEeWuGe?= =?us-ascii?Q?VHKejsfilGHlEWDwVIa4LHeUJq3g6MgUilv8mKRWyBC5Lmh2Vp/Nq3Gbe8OA?= =?us-ascii?Q?02M8xGi3QLAn2uv1gWJcgfvaobgC9U7sd9WIjThEc1UWOIfi+EwqtgV1nQrG?= =?us-ascii?Q?kf/BlgnHbKH4NyFSLPj7qt/h3TxyjfeNRWHpWce5jV6yW9Lkm5qLYZE86SFa?= =?us-ascii?Q?pyzZ1dycdFLqWcpLhrrq4W+9blGtPjAOMr/qKaPZiT2QmYh6byQEg90/aZGs?= =?us-ascii?Q?JkPdsut8cDkcERDfgoPf2mCR4LSCaklm+/ucsVsjl1ZoGO1Ksad+h9M5yk9I?= =?us-ascii?Q?RJIyAM3vkTbiIH3EGZcwwGIiD9ow+HWgWq/ECdDaVDvh/1i7QiYJk+jbKmkU?= =?us-ascii?Q?iexPC3C9lh9cY2vvQjDMB6W+bZktAgmfxk3Ctu5Do6Ib+Xf1ggAaN3yTtDYl?= =?us-ascii?Q?3v+B2Q9/lJAkZKSCME9tRyEJJ8uiastH37fFOSCxLFdWmzcm6d8Xpnhucngf?= =?us-ascii?Q?UxtNlAeL7d5/F2DBAynGkjrnRl5bOeoKpNdSiDec92CEfSUvozdZdIN7yaAf?= =?us-ascii?Q?RBQUCDAUlXyy94Y/KHfcZUhE/ev+iVC7XJtHnWAjyeDsCFh2MXAhTj3xioad?= =?us-ascii?Q?5noyoHFhdjpopSO7komefor8wCHpe3V448eV/2sF2/l0YdxPPqi3YDZ3JGng?= =?us-ascii?Q?6i3JIzLRSIEBS7dmNx+j17AA1qy9MxG9S+9GT7DzHJ/cPb2LG4uH/Z0JVt7h?= =?us-ascii?Q?UGt+Nhlj9OC8XFGG+rAmG7HOWw7dlNQRn9HJUlhJxJ0osd9v7lZiUXJJhVgW?= =?us-ascii?Q?lcIhe+wXDQ64fiqQkMb7UYKRIpzY/7J4lHwfuKL/KgJ7sHqZazMKC5nDqrMK?= =?us-ascii?Q?YKwKhRxuju3tZboyUeTnUvisvCLm3cuYus9Hq+hjmEl58zKCilD3O2doMkWE?= =?us-ascii?Q?0F9iKmbfg27sfweIL3E67caOKnzOjAR4I9UaAcVEirGQBYUtZ8uQ+trPbEAY?= =?us-ascii?Q?GcrhylxR5LDTsH7zTcRkLO91a1CVdojGCHkz4ee2CHQwNKu52k7MBlvzcuq9?= =?us-ascii?Q?VMgqEs6iSVGbWGmDqrPlghg/mf35MJ0G+MlsNHp4?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: fab89f7f-bfa6-476b-7c96-08dc91c766f3 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:39.4965 (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: LGO/djVC7K9Ay9GmJ+MLezuhCIoihhgtqh4zxvHMnHb6F1w8PjpJbsPew+NAqT5iyl2+WRoRUw1QxGu7RpkuPg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/util.h | 90 +++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/util.h diff --git a/drivers/net/wireless/nxp/nxpwifi/util.h b/drivers/net/wireless= /nxp/nxpwifi/util.h new file mode 100644 index 000000000000..b9cccb340933 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/util.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: utility functions + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_UTIL_H_ +#define _NXPWIFI_UTIL_H_ + +struct nxpwifi_private; + +struct nxpwifi_dma_mapping { + dma_addr_t addr; + size_t len; +}; + +struct nxpwifi_cb { + struct nxpwifi_dma_mapping dma_mapping; + union { + struct nxpwifi_rxinfo rx_info; + struct nxpwifi_txinfo tx_info; + }; +}; + +/* size/addr for nxpwifi_debug_info */ +#define item_size(n) (sizeof_field(struct nxpwifi_debug_info, n)) +#define item_addr(n) (offsetof(struct nxpwifi_debug_info, n)) + +/* size/addr for struct nxpwifi_adapter */ +#define adapter_item_size(n) (sizeof_field(struct nxpwifi_adapter, n)) +#define adapter_item_addr(n) (offsetof(struct nxpwifi_adapter, n)) + +struct nxpwifi_debug_data { + char name[32]; /* variable/array name */ + u32 size; /* size of the variable/array */ + size_t addr; /* address of the variable/array */ + int num; /* number of variables in an array */ +}; + +static inline struct nxpwifi_rxinfo *NXPWIFI_SKB_RXCB(struct sk_buff *skb) +{ + struct nxpwifi_cb *cb =3D (struct nxpwifi_cb *)skb->cb; + + BUILD_BUG_ON(sizeof(struct nxpwifi_cb) > sizeof(skb->cb)); + return &cb->rx_info; +} + +static inline struct nxpwifi_txinfo *NXPWIFI_SKB_TXCB(struct sk_buff *skb) +{ + struct nxpwifi_cb *cb =3D (struct nxpwifi_cb *)skb->cb; + + return &cb->tx_info; +} + +static inline void nxpwifi_store_mapping(struct sk_buff *skb, + struct nxpwifi_dma_mapping *mapping) +{ + struct nxpwifi_cb *cb =3D (struct nxpwifi_cb *)skb->cb; + + memcpy(&cb->dma_mapping, mapping, sizeof(*mapping)); +} + +static inline void nxpwifi_get_mapping(struct sk_buff *skb, + struct nxpwifi_dma_mapping *mapping) +{ + struct nxpwifi_cb *cb =3D (struct nxpwifi_cb *)skb->cb; + + memcpy(mapping, &cb->dma_mapping, sizeof(*mapping)); +} + +static inline dma_addr_t NXPWIFI_SKB_DMA_ADDR(struct sk_buff *skb) +{ + struct nxpwifi_dma_mapping mapping; + + nxpwifi_get_mapping(skb, &mapping); + + return mapping.addr; +} + +int nxpwifi_debug_info_to_buffer(struct nxpwifi_private *priv, char *buf, + struct nxpwifi_debug_info *info); + +static inline void le16_unaligned_add_cpu(__le16 *var, u16 val) +{ + put_unaligned_le16(get_unaligned_le16(var) + val, var); +} + +int nxpwifi_append_data_tlv(u16 id, u8 *data, int len, u8 *pos, u8 *cmd_en= d); +#endif /* !_NXPWIFI_UTIL_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB5F617BB31; Fri, 21 Jun 2024 07:54:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956490; cv=fail; b=hee4gYkZvckpxY9ZDVxSGpM6z3mbMAhhlSTdytYvydgDBQDELIsEFcvYV3iZv1pEWbFtuIqwEosOB8Lmyx1Uxa0771U7Lkk79m00DBe/ephHZmrfYQOcF/pEOxAt5hX44WxFMpz3TuHXysi5nLOAMcXLKyAkhPfLM3zjtEFqnIA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956490; c=relaxed/simple; bh=93foPBJH1ELpl6HrIsWXZtNnIjQfPiYr3vK2PIsQJ0k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Xf7q99abPtcCT9s01BAU4LLJ0dZPItZtPDDLTVT/ER6/h51uMMzSFpqQQG/2HEFU0YUPZmik3rvBY6h+XCoyl1RiLpfOdTSluoW+cha855cayptZBeBJsMoFXUJ0y+Lb3WDfFihQkFowzY6aaDENOPnh3a9uxp3QfIi/vdDmnwM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=T/X+f0NK; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="T/X+f0NK" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YVrnpx2QQQUNOb7nrtobbBWbherhr8Y8wpoUflaFbBIoSQxQ/E3AqVjooce8qloPeFvZD2iChulmrCazKyBZNKQgkdA+iBkeuf+scHOIqI3xmdO9N1KD8RWwHkiESKC+gSqYHol/7rFa1Wq917STyHzSQuygn6rXQa1YH+Uz1Rbx2/8VU6D+6ZS8T08fru+g3XIAAS/K3l4D85jV6j+kwRNXVPf5hWHtqulI/P7YCjQAP/x6iNMM8Yz20MYtOe1mBXcFlRQ71/fmEeUp1lpxbsHgUsJPJQBV0RmipzVYfyh8IZRJj7xEYbrLrMQ+E4RPRN7e0FotML68m+aQHr+kxQ== 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=CZjMiFYT/x3qzufV/iViBqtv4dQYSIt+DXfjl41liio=; b=oXAEN6k8t5SMh8Bh52ES/F1WeC+TksC0PHepMH4A72oQm/2mJqKMI7zSJxkwbgsitgaJjvC8AwHIylUPFWqNF0hXJz5MgqKymg9IParRm0rhmnGHGXzkb/+zNPqs32Hj1gSsFC1+OJe30tuJIqI2i+DT6Lf7m5K2IVsumYEo7kqbMns/zYVDVLK75fi1Thy29k1Bn/PvAbSWmmiHEZMaY/Hh8xJp324eAtXowa3YCkoj5GBQmGEab0YC+DBes8RPsnmqM4DJktejaWHh0JAVv783cIbVQUA2gY0DMwDlSmEhWJd0cSlAkGYuMOidjMHmlrjBn1F1mJchepDUBq+VRw== 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=CZjMiFYT/x3qzufV/iViBqtv4dQYSIt+DXfjl41liio=; b=T/X+f0NK1udBHpJNDvGRz5/OxYpnTxn5P4uWYbjIjzQhHuzil4Dx+YYa1IZ7WkxbqX4RC0PLiqqZdWLVmxf/mmB27NMRw56ektWWcZbxrXIM+Td+oZV+DshB9QJbGgRB9lwvumw8so9v1gzYwnO1ZaAHB0QP0YcjDHb6r6PflDE= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:42 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:42 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 39/43] wifi: nxpwifi: add wmm.c Date: Fri, 21 Jun 2024 15:52:04 +0800 Message-Id: <20240621075208.513497-40-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 42f0aa33-c109-40d3-6d8b-08dc91c768be X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?O5hWDwyNIvL02r98j3jGqsquAUGzbusH9+iAGoGklNH9I2B3hNVYw9xA472j?= =?us-ascii?Q?X5jG1UKOUO+WOwY2F9Iyr5/gblVRQPxqCpkUn389ltXu6ZCaLBSMzcxSdYlz?= =?us-ascii?Q?lc5xxIocHFVozkTk6iOqeumyx/zeeFPkJ2pDb+J0xv1TgpEBDqeOAlkR+c3z?= =?us-ascii?Q?s2yz4PeVqu9TkNC1w/jkGz1cIUVnGK/bSe55cNHRKEI+WRupw5LNPN8rY0Bt?= =?us-ascii?Q?eFdImcTyfpLlP/YBTWiJJKaGmyH3YLLidPNP4MqY4ecU0upI5mA/2P8DL2ic?= =?us-ascii?Q?YbHIf9AEXy9+pkHEOa9OmhD9FH23Hr4Nv9Te/nbGWl+v12Eh7oR8OozHMG+o?= =?us-ascii?Q?GFOgxtlMfHQc1b39M5qfEEKTxGTAn6SMVyPKBpNg5Hsuj05wNboDW7coQayu?= =?us-ascii?Q?tvlv3l45cYf9ydBgS7H9vBMtojhJiK6ITTcxq8iO+9vBHXFpJ/nq9iSDZZGi?= =?us-ascii?Q?dCbU7nfz8AsHojrEk7YKtK8Wksi9VM66v6GHqvYfLuGIDgYBiJoxaFWoA7Bp?= =?us-ascii?Q?nJHuGnpIDJ19LszX+5AUF/bOtcbtPi36PdOxVV/TGN2LxqcjcvssRiR5qgyQ?= =?us-ascii?Q?53ydhIOOOGV38Qz2vY/mgYrS4zFtBEQ5WAvwXp9EbpCpbfk4NAXwLPYKaUW+?= =?us-ascii?Q?r9mwbn9irWvnvLdMeYYPcVsLbz08fZU9uUyuG/AMFQg0AgnnbjY3ORwlPsHE?= =?us-ascii?Q?bZ8CBrtoz1Pj5AM21qZ82oVQCGm+dYAMr2WVUut/YZNjAlLw35zq0vdHLWzV?= =?us-ascii?Q?jzlmurT8eZgYzUHdvw+vi+46AP42sKXCtVwGZqly7SuiZmCkWn+vEXVV63CR?= =?us-ascii?Q?Xrm7zQxKv+Ih11FLsjP0ajY3uQjktZ2mt0r4l0FZEjFZ7M1WIJFvGGdy7B3z?= =?us-ascii?Q?j0rAp9+zwHSoIdfZDNVKg/ek7r5Hc2vYAdFPcD+x1zB38PhrSWDIXK6DPKKD?= =?us-ascii?Q?mEMBIf/lAutpNxV9kXHtfrKXeTJTgODkO+TW6wUHInmwJICNY/mgBr2uZGvy?= =?us-ascii?Q?b+gSUOk1heDRxGs9Pf7d3mzs4yplZEFxnJDLgXykacNfWl2BbhopH44S6wY4?= =?us-ascii?Q?KjU9euDZGHtCdtFlQKQwFoCiAZqYJRbEw43sWG3OnobhL8rx+fffMMqcMNLz?= =?us-ascii?Q?lGhOpBt6H3XFG1lLRlnLlJFSYHZHCApefA3pigmFMB7y4AsJTwoxV5+MBxry?= =?us-ascii?Q?bs67n1X4ZHQ3rUvfZDjP98a2sA+qpraDz2FGsTu/NPf+x8CovERpMKqjx1le?= =?us-ascii?Q?b4Q9WWhVrYZEbhFluxybHE8IRleAcnxBj+uiSLClxcmbAxcrEwFUZLs2plQN?= =?us-ascii?Q?C64UibBqWhJUAPLuyqRZTMgnTkyTQNKbWe9OqrLhF67fiSb7FzEvZQS1/RzI?= =?us-ascii?Q?jU6yaYw=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?YLcstZ3Tcf2SAt9BPS6lmImjvj8XmhlOxE96lA0h8AMESjMHIMAGaxl3ycdE?= =?us-ascii?Q?YKxqLkj2Uua37FEVocQPHMM3NDEMbu3uR0Xa201Z1OlqmO293XXvyCs+VsFc?= =?us-ascii?Q?Kgh67DToKd6ItPpwrx9CtGNlmkFQxQJAJ73MRN4J25aWFVeMQWUcB6f1MFH3?= =?us-ascii?Q?lDI4W62V6yBf8SbA+g+6tGckLUJ2/LFxHVaql1OhxRbSbLh6sgImzC3CUe/M?= =?us-ascii?Q?lPHxPK7bS/f+m3NyCPOiEkUPZpWRc98sVV0YO/h3WQCAeg+rdFMGVlNK7WeZ?= =?us-ascii?Q?u6NdQym4mDsCuaSwJhtCOfN37bScHIdzWwdkaD5dGvh81GzWecjl1ygeBOGD?= =?us-ascii?Q?rooATIUj5D5ta6TN4JWh7mPQWOvBrVKTreGPh36xO5zw7tSljryiSiseLboZ?= =?us-ascii?Q?yNNK4oio560dGLzsnq/+La/G71tu2jmlNTg+S1NVYvPEEFihf5wxe41gV6aL?= =?us-ascii?Q?NhIRsFDypKFVhUI2ylcNbMmGXKShQSr6H9SoK8dhapp/42jfohJkmX0z9Yfw?= =?us-ascii?Q?1mPKg9zCpKpdOL4zXtqod+h1ghA/odpVzcijNSfNZlgNPnqfW+9CQ7gYGcQa?= =?us-ascii?Q?M5i2ICZoF4zBuJD3DXlBO7Lo6k2A0fRZX2XNo9rZNfNUu5mBcPOEYSlV6iaj?= =?us-ascii?Q?OqY0f6ilPl7FbrV7CNRH2qpdYnqA3mz0thJdJR461QUulXoIKDcYemRxvzdC?= =?us-ascii?Q?8Z/XfCKYQV+ckd5qiDS3YT9+eTr+2C09Js+KKxMqOK4MhewalFAjaSUzP8ie?= =?us-ascii?Q?0gznlhVSq83urU0RZaLw0TIc1hEYqml8j6xeOVvN4pCUEzD4A17HnfCj/fhV?= =?us-ascii?Q?uHcGYSec6Ilsk/I4RUsWEWAU3Zza3vTq/z8iy7OE152uNT7A3C9onz/QGa5S?= =?us-ascii?Q?vzPWVennkLuLf7/QLBt63KQh6wyhgVW7gJHcISW+240aesvVNCGGL7TusPVS?= =?us-ascii?Q?kYFtTK0u3cxH1C+5o1eu+VoK9i76YDbzeuxSGFawW87UITWxiVO5ZpvwZvK2?= =?us-ascii?Q?4MCCDSGyXyRMZjRwmRCJXPSLtaLg8IwZ0nw9uZ6Zw47hzB5/+tciacsKaoha?= =?us-ascii?Q?rFwZ8ZnHn6qUpk3qvKRYV+7U0tqoSDNs6zBpDg3MHQEG3kARh8e9aYSUDfnO?= =?us-ascii?Q?stZidXfQMGkh+wA8lx0LPfZt/4aG0URZuHmp7mOeAnF2EUCfRWHDTY+PHIrO?= =?us-ascii?Q?V3qyMT92FnjBFGaWU117KJc09E0yprZM4/x4jVxlYTxnyHpmBMOG4zjHS19A?= =?us-ascii?Q?BZTyL5QDfPvFfJTqO/bbUhAskUKtHJGB5Wf74AxIhMa7RSrqk0h4Jwscxjoj?= =?us-ascii?Q?0QPqm8QQGjBFNr1KmJkax/S1NmNQC0biAGGyz5GbrFqAXtQ0GLVYz8LDB5ri?= =?us-ascii?Q?XFd3h7xXn7DMeKELsOGNDT+dB0ZzUu3bHDKTfR20Nvxz2GeOuKe9s+7r3hMK?= =?us-ascii?Q?TYiFt9/Ka6xA/f552G66XMV/+QJclTYDjvOfEUp7FdUMG6Jp04AEquZE8piz?= =?us-ascii?Q?/qimLov8vOR0TAdtK42vM6rPtyxZiYTbV2Yjkx1kGOC7mQOgouEEZWe2D7ZG?= =?us-ascii?Q?gtGEVB89fK8e8E8rpSg14sLNQlONfC+i9N8mSv/R?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 42f0aa33-c109-40d3-6d8b-08dc91c768be X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:42.7966 (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: yZ5Y6Vg01/rj8zx+oMU5QUusNdF+KtAIHFY7AZoZpxx+/T8FvxTCbPKsaHT/nMSZJgfwQGvGEGUzI5jtoZ3/gA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/wmm.c | 1397 ++++++++++++++++++++++++ 1 file changed, 1397 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/wmm.c diff --git a/drivers/net/wireless/nxp/nxpwifi/wmm.c b/drivers/net/wireless/= nxp/nxpwifi/wmm.c new file mode 100644 index 000000000000..1d90e52f447d --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/wmm.c @@ -0,0 +1,1397 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: WMM + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* Maximum value FW can accept for driver delay in packet transmission */ +#define DRV_PKT_DELAY_TO_FW_MAX 512 + +#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 + +#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 + +/* Offset for TOS field in the IP header */ +#define IPTOS_OFFSET 5 + +static bool disable_tx_amsdu; + +/* This table inverses the tos_to_tid operation to get a priority + * which is in sequential order, and can be compared. + * Use this to compare the priority of two different TIDs. + */ +const u8 tos_to_tid_inv[] =3D { + 0x02, /* from tos_to_tid[2] =3D 0 */ + 0x00, /* from tos_to_tid[0] =3D 1 */ + 0x01, /* from tos_to_tid[1] =3D 2 */ + 0x03, + 0x04, + 0x05, + 0x06, + 0x07 +}; + +/* WMM information IE */ +static const u8 wmm_info_ie[] =3D { WLAN_EID_VENDOR_SPECIFIC, 0x07, + 0x00, 0x50, 0xf2, 0x02, + 0x00, 0x01, 0x00 +}; + +static const u8 wmm_aci_to_qidx_map[] =3D { WMM_AC_BE, + WMM_AC_BK, + WMM_AC_VI, + WMM_AC_VO +}; + +static u8 tos_to_tid[] =3D { + /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ + 0x01, /* 0 1 0 AC_BK */ + 0x02, /* 0 0 0 AC_BK */ + 0x00, /* 0 0 1 AC_BE */ + 0x03, /* 0 1 1 AC_BE */ + 0x04, /* 1 0 0 AC_VI */ + 0x05, /* 1 0 1 AC_VI */ + 0x06, /* 1 1 0 AC_VO */ + 0x07 /* 1 1 1 AC_VO */ +}; + +static u8 ac_to_tid[4][2] =3D { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; + +/* This function debug prints the priority parameters for a WMM AC. + */ +static void +nxpwifi_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_p= aram) +{ + static const char * const ac_str[] =3D { "BK", "BE", "VI", "VO" }; + + pr_debug("info: WMM AC_%s: ACI=3D%d, ACM=3D%d, Aifsn=3D%d, ", + ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap + & NXPWIFI_ACI) >> 5]], + (ac_param->aci_aifsn_bitmap & NXPWIFI_ACI) >> 5, + (ac_param->aci_aifsn_bitmap & NXPWIFI_ACM) >> 4, + ac_param->aci_aifsn_bitmap & NXPWIFI_AIFSN); + pr_debug("EcwMin=3D%d, EcwMax=3D%d, TxopLimit=3D%d\n", + ac_param->ecw_bitmap & NXPWIFI_ECW_MIN, + (ac_param->ecw_bitmap & NXPWIFI_ECW_MAX) >> 4, + le16_to_cpu(ac_param->tx_op_limit)); +} + +/* This function allocates a route address list. + * + * The function also initializes the list with the provided RA. + */ +static struct nxpwifi_ra_list_tbl * +nxpwifi_wmm_allocate_ralist_node(struct nxpwifi_adapter *adapter, const u8= *ra) +{ + struct nxpwifi_ra_list_tbl *ra_list; + + ra_list =3D kzalloc(sizeof(*ra_list), GFP_ATOMIC); + if (!ra_list) + return NULL; + + INIT_LIST_HEAD(&ra_list->list); + skb_queue_head_init(&ra_list->skb_head); + + memcpy(ra_list->ra, ra, ETH_ALEN); + + ra_list->total_pkt_count =3D 0; + + nxpwifi_dbg(adapter, INFO, "info: allocated ra_list %p\n", ra_list); + + return ra_list; +} + +/* This function returns random no between 16 and 32 to be used as thresho= ld + * for no of packets after which BA setup is initiated. + */ +static u8 nxpwifi_get_random_ba_threshold(void) +{ + u64 ns; + /* setup ba_packet_threshold here random number between + * [BA_SETUP_PACKET_OFFSET, + * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] + */ + ns =3D ktime_get_ns(); + ns +=3D (ns >> 32) + (ns >> 16); + + return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET; +} + +/* This function allocates and adds a RA list for all TIDs + * with the given RA. + */ +void nxpwifi_ralist_add(struct nxpwifi_private *priv, const u8 *ra) +{ + int i; + struct nxpwifi_ra_list_tbl *ra_list; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_sta_node *node; + + for (i =3D 0; i < MAX_NUM_TID; ++i) { + ra_list =3D nxpwifi_wmm_allocate_ralist_node(adapter, ra); + nxpwifi_dbg(adapter, INFO, + "info: created ra_list %p\n", ra_list); + + if (!ra_list) + break; + + ra_list->is_11n_enabled =3D 0; + ra_list->ba_status =3D BA_SETUP_NONE; + ra_list->amsdu_in_ampdu =3D false; + if (!nxpwifi_queuing_ra_based(priv)) { + ra_list->is_11n_enabled =3D IS_11N_ENABLED(priv); + } else { + spin_lock_bh(&priv->sta_list_spinlock); + node =3D nxpwifi_get_sta_entry(priv, ra); + if (node) + ra_list->tx_paused =3D node->tx_pause; + ra_list->is_11n_enabled =3D + nxpwifi_is_sta_11n_enabled(priv, node); + if (ra_list->is_11n_enabled) + ra_list->max_amsdu =3D node->max_amsdu; + spin_unlock_bh(&priv->sta_list_spinlock); + } + + nxpwifi_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=3D%d\n", + ra_list, ra_list->is_11n_enabled); + + if (ra_list->is_11n_enabled) { + ra_list->ba_pkt_count =3D 0; + ra_list->ba_packet_thr =3D + nxpwifi_get_random_ba_threshold(); + } + list_add_tail(&ra_list->list, + &priv->wmm.tid_tbl_ptr[i].ra_list); + } +} + +/* This function sets the WMM queue priorities to their default values. + */ +static void nxpwifi_wmm_default_queue_priorities(struct nxpwifi_private *p= riv) +{ + /* Default queue priorities: VO->VI->BE->BK */ + priv->wmm.queue_priority[0] =3D WMM_AC_VO; + priv->wmm.queue_priority[1] =3D WMM_AC_VI; + priv->wmm.queue_priority[2] =3D WMM_AC_BE; + priv->wmm.queue_priority[3] =3D WMM_AC_BK; +} + +/* This function map ACs to TIDs. + */ +static void +nxpwifi_wmm_queue_priorities_tid(struct nxpwifi_private *priv) +{ + struct nxpwifi_wmm_desc *wmm =3D &priv->wmm; + u8 *queue_priority =3D wmm->queue_priority; + int i; + + for (i =3D 0; i < 4; ++i) { + tos_to_tid[7 - (i * 2)] =3D ac_to_tid[queue_priority[i]][1]; + tos_to_tid[6 - (i * 2)] =3D ac_to_tid[queue_priority[i]][0]; + } + + for (i =3D 0; i < MAX_NUM_TID; ++i) + priv->tos_to_tid_inv[tos_to_tid[i]] =3D (u8)i; + + atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); +} + +/* This function initializes WMM priority queues. + */ +void +nxpwifi_wmm_setup_queue_priorities(struct nxpwifi_private *priv, + struct ieee_types_wmm_parameter *wmm_ie) +{ + u16 cw_min, avg_back_off, tmp[4]; + u32 i, j, num_ac; + u8 ac_idx; + + if (!wmm_ie || !priv->wmm_enabled) { + /* WMM is not enabled, just set the defaults and return */ + nxpwifi_wmm_default_queue_priorities(priv); + return; + } + + nxpwifi_dbg(priv->adapter, INFO, + "info: WMM Parameter IE: version=3D%d,\t" + "qos_info Parameter Set Count=3D%d, Reserved=3D%#x\n", + wmm_ie->version, wmm_ie->qos_info_bitmap & + IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, + wmm_ie->reserved); + + for (num_ac =3D 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { + u8 ecw =3D wmm_ie->ac_params[num_ac].ecw_bitmap; + u8 aci_aifsn =3D wmm_ie->ac_params[num_ac].aci_aifsn_bitmap; + + cw_min =3D (1 << (ecw & NXPWIFI_ECW_MIN)) - 1; + avg_back_off =3D (cw_min >> 1) + (aci_aifsn & NXPWIFI_AIFSN); + + ac_idx =3D wmm_aci_to_qidx_map[(aci_aifsn & NXPWIFI_ACI) >> 5]; + priv->wmm.queue_priority[ac_idx] =3D ac_idx; + tmp[ac_idx] =3D avg_back_off; + + nxpwifi_dbg(priv->adapter, INFO, + "info: WMM: CWmax=3D%d CWmin=3D%d Avg Back-off=3D%d\n", + (1 << ((ecw & NXPWIFI_ECW_MAX) >> 4)) - 1, + cw_min, avg_back_off); + nxpwifi_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); + } + + /* Bubble sort */ + for (i =3D 0; i < num_ac; i++) { + for (j =3D 1; j < num_ac - i; j++) { + if (tmp[j - 1] > tmp[j]) { + swap(tmp[j - 1], tmp[j]); + swap(priv->wmm.queue_priority[j - 1], + priv->wmm.queue_priority[j]); + } else if (tmp[j - 1] =3D=3D tmp[j]) { + if (priv->wmm.queue_priority[j - 1] + < priv->wmm.queue_priority[j]) + swap(priv->wmm.queue_priority[j - 1], + priv->wmm.queue_priority[j]); + } + } + } + + nxpwifi_wmm_queue_priorities_tid(priv); +} + +/* This function evaluates whether or not an AC is to be downgraded. + * + * In case the AC is not enabled, the highest AC is returned that is + * enabled and does not require admission control. + */ +static enum nxpwifi_wmm_ac_e +nxpwifi_wmm_eval_downgrade_ac(struct nxpwifi_private *priv, + enum nxpwifi_wmm_ac_e eval_ac) +{ + int down_ac; + enum nxpwifi_wmm_ac_e ret_ac; + struct nxpwifi_wmm_ac_status *ac_status; + + ac_status =3D &priv->wmm.ac_status[eval_ac]; + + if (!ac_status->disabled) + /* Okay to use this AC, its enabled */ + return eval_ac; + + /* Setup a default return value of the lowest priority */ + ret_ac =3D WMM_AC_BK; + + /* Find the highest AC that is enabled and does not require + * admission control. The spec disallows downgrading to an AC, + * which is enabled due to a completed admission control. + * Unadmitted traffic is not to be sent on an AC with admitted + * traffic. + */ + for (down_ac =3D WMM_AC_BK; down_ac < eval_ac; down_ac++) { + ac_status =3D &priv->wmm.ac_status[down_ac]; + + if (!ac_status->disabled && !ac_status->flow_required) + /* AC is enabled and does not require admission + * control + */ + ret_ac =3D (enum nxpwifi_wmm_ac_e)down_ac; + } + + return ret_ac; +} + +/* This function downgrades WMM priority queue. + */ +void +nxpwifi_wmm_setup_ac_downgrade(struct nxpwifi_private *priv) +{ + int ac_val; + + nxpwifi_dbg(priv->adapter, INFO, "info: WMM: AC Priorities:\t" + "BK(0), BE(1), VI(2), VO(3)\n"); + + if (!priv->wmm_enabled) { + /* WMM is not enabled, default priorities */ + for (ac_val =3D WMM_AC_BK; ac_val <=3D WMM_AC_VO; ac_val++) + priv->wmm.ac_down_graded_vals[ac_val] =3D + (enum nxpwifi_wmm_ac_e)ac_val; + } else { + for (ac_val =3D WMM_AC_BK; ac_val <=3D WMM_AC_VO; ac_val++) { + priv->wmm.ac_down_graded_vals[ac_val] =3D + nxpwifi_wmm_eval_downgrade_ac + (priv, (enum nxpwifi_wmm_ac_e)ac_val); + nxpwifi_dbg(priv->adapter, INFO, + "info: WMM: AC PRIO %d maps to %d\n", + ac_val, + priv->wmm.ac_down_graded_vals[ac_val]); + } + } +} + +/* This function converts the IP TOS field to an WMM AC + * Queue assignment. + */ +static enum nxpwifi_wmm_ac_e +nxpwifi_wmm_convert_tos_to_ac(struct nxpwifi_adapter *adapter, u32 tos) +{ + /* Map of TOS UP values to WMM AC */ + static const enum nxpwifi_wmm_ac_e tos_to_ac[] =3D { + WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO + }; + + if (tos >=3D ARRAY_SIZE(tos_to_ac)) + return WMM_AC_BE; + + return tos_to_ac[tos]; +} + +/* This function evaluates a given TID and downgrades it to a lower + * TID if the WMM Parameter IE received from the AP indicates that the + * AP is disabled (due to call admission control (ACM bit). Mapping + * of TID to AC is taken care of internally. + */ +u8 nxpwifi_wmm_downgrade_tid(struct nxpwifi_private *priv, u32 tid) +{ + enum nxpwifi_wmm_ac_e ac, ac_down; + u8 new_tid; + + ac =3D nxpwifi_wmm_convert_tos_to_ac(priv->adapter, tid); + ac_down =3D priv->wmm.ac_down_graded_vals[ac]; + + /* Send the index to tid array, picking from the array will be + * taken care by dequeuing function + */ + new_tid =3D ac_to_tid[ac_down][tid % 2]; + + return new_tid; +} + +/* This function initializes the WMM state information and the + * WMM data path queues. + */ +void +nxpwifi_wmm_init(struct nxpwifi_adapter *adapter) +{ + int i, j; + struct nxpwifi_private *priv; + + for (j =3D 0; j < adapter->priv_num; ++j) { + priv =3D adapter->priv[j]; + if (!priv) + continue; + + for (i =3D 0; i < MAX_NUM_TID; ++i) { + if (!disable_tx_amsdu && + adapter->tx_buf_size > NXPWIFI_TX_DATA_BUF_SIZE_2K) + priv->aggr_prio_tbl[i].amsdu =3D + priv->tos_to_tid_inv[i]; + else + priv->aggr_prio_tbl[i].amsdu =3D + BA_STREAM_NOT_ALLOWED; + priv->aggr_prio_tbl[i].ampdu_ap =3D + priv->tos_to_tid_inv[i]; + priv->aggr_prio_tbl[i].ampdu_user =3D + priv->tos_to_tid_inv[i]; + } + + priv->aggr_prio_tbl[6].amsdu =3D + priv->aggr_prio_tbl[6].ampdu_ap =3D + priv->aggr_prio_tbl[6].ampdu_user =3D + BA_STREAM_NOT_ALLOWED; + + priv->aggr_prio_tbl[7].amsdu =3D + priv->aggr_prio_tbl[7].ampdu_ap =3D + priv->aggr_prio_tbl[7].ampdu_user =3D + BA_STREAM_NOT_ALLOWED; + + nxpwifi_set_ba_params(priv); + nxpwifi_reset_11n_rx_seq_num(priv); + + priv->wmm.drv_pkt_delay_max =3D NXPWIFI_WMM_DRV_DELAY_MAX; + atomic_set(&priv->wmm.tx_pkts_queued, 0); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); + } +} + +int nxpwifi_bypass_txlist_empty(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + int i; + + for (i =3D 0; i < adapter->priv_num; i++) { + priv =3D adapter->priv[i]; + if (!priv) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (!skb_queue_empty(&priv->bypass_txq)) + return false; + } + + return true; +} + +/* This function checks if WMM Tx queue is empty. + */ +int +nxpwifi_wmm_lists_empty(struct nxpwifi_adapter *adapter) +{ + int i; + struct nxpwifi_private *priv; + + for (i =3D 0; i < adapter->priv_num; ++i) { + priv =3D adapter->priv[i]; + if (!priv) + continue; + if (!priv->port_open) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (atomic_read(&priv->wmm.tx_pkts_queued)) + return false; + } + + return true; +} + +/* This function deletes all packets in an RA list node. + * + * The packet sent completion callback handler are called with + * status failure, after they are dequeued to ensure proper + * cleanup. The RA list node itself is freed at the end. + */ +static void +nxpwifi_wmm_del_pkts_in_ralist_node(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ra_list) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) { + skb_unlink(skb, &ra_list->skb_head); + nxpwifi_write_data_complete(adapter, skb, 0, -1); + } +} + +/* This function deletes all packets in an RA list. + * + * Each nodes in the RA list are freed individually first, and then + * the RA list itself is freed. + */ +static void +nxpwifi_wmm_del_pkts_in_ralist(struct nxpwifi_private *priv, + struct list_head *ra_list_head) +{ + struct nxpwifi_ra_list_tbl *ra_list; + + list_for_each_entry(ra_list, ra_list_head, list) + nxpwifi_wmm_del_pkts_in_ralist_node(priv, ra_list); +} + +/* This function deletes all packets in all RA lists. + */ +static void nxpwifi_wmm_cleanup_queues(struct nxpwifi_private *priv) +{ + int i; + + for (i =3D 0; i < MAX_NUM_TID; i++) + nxpwifi_wmm_del_pkts_in_ralist + (priv, &priv->wmm.tid_tbl_ptr[i].ra_list); + + atomic_set(&priv->wmm.tx_pkts_queued, 0); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); +} + +/* This function deletes all route addresses from all RA lists. + */ +static void nxpwifi_wmm_delete_all_ralist(struct nxpwifi_private *priv) +{ + struct nxpwifi_ra_list_tbl *ra_list, *tmp_node; + int i; + + for (i =3D 0; i < MAX_NUM_TID; ++i) { + nxpwifi_dbg(priv->adapter, INFO, + "info: ra_list: freeing buf for tid %d\n", i); + list_for_each_entry_safe(ra_list, tmp_node, + &priv->wmm.tid_tbl_ptr[i].ra_list, + list) { + list_del(&ra_list->list); + kfree(ra_list); + } + + INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); + } +} + +static int nxpwifi_free_ack_frame(int id, void *p, void *data) +{ + pr_warn("Have pending ack frames!\n"); + kfree_skb(p); + return 0; +} + +/* This function cleans up the Tx and Rx queues. + * + * Cleanup includes - + * - All packets in RA lists + * - All entries in Rx reorder table + * - All entries in Tx BA stream table + * - MPA buffer (if required) + * - All RA lists + */ +void +nxpwifi_clean_txrx(struct nxpwifi_private *priv) +{ + struct sk_buff *skb, *tmp; + + nxpwifi_11n_cleanup_reorder_tbl(priv); + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + nxpwifi_wmm_cleanup_queues(priv); + nxpwifi_11n_delete_all_tx_ba_stream_tbl(priv); + + if (priv->adapter->if_ops.cleanup_mpa_buf) + priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); + + nxpwifi_wmm_delete_all_ralist(priv); + memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); + + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + + skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) { + skb_unlink(skb, &priv->bypass_txq); + nxpwifi_write_data_complete(priv->adapter, skb, 0, -1); + } + atomic_set(&priv->adapter->bypass_tx_pending, 0); + + idr_for_each(&priv->ack_status_frames, nxpwifi_free_ack_frame, NULL); + idr_destroy(&priv->ack_status_frames); +} + +/* This function retrieves a particular RA list node, matching with the + * given TID and RA address. + */ +struct nxpwifi_ra_list_tbl * +nxpwifi_wmm_get_ralist_node(struct nxpwifi_private *priv, u8 tid, + const u8 *ra_addr) +{ + struct nxpwifi_ra_list_tbl *ra_list; + + list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, + list) { + if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) + return ra_list; + } + + return NULL; +} + +void nxpwifi_update_ralist_tx_pause(struct nxpwifi_private *priv, u8 *mac, + u8 tx_pause) +{ + struct nxpwifi_ra_list_tbl *ra_list; + u32 pkt_cnt =3D 0, tx_pkts_queued; + int i; + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + for (i =3D 0; i < MAX_NUM_TID; ++i) { + ra_list =3D nxpwifi_wmm_get_ralist_node(priv, i, mac); + if (ra_list && ra_list->tx_paused !=3D tx_pause) { + pkt_cnt +=3D ra_list->total_pkt_count; + ra_list->tx_paused =3D tx_pause; + if (tx_pause) + priv->wmm.pkts_paused[i] +=3D + ra_list->total_pkt_count; + else + priv->wmm.pkts_paused[i] -=3D + ra_list->total_pkt_count; + } + } + + if (pkt_cnt) { + tx_pkts_queued =3D atomic_read(&priv->wmm.tx_pkts_queued); + if (tx_pause) + tx_pkts_queued -=3D pkt_cnt; + else + tx_pkts_queued +=3D pkt_cnt; + + atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); + } + spin_unlock_bh(&priv->wmm.ra_list_spinlock); +} + +/* This function retrieves an RA list node for a given TID and + * RA address pair. + * + * If no such node is found, a new node is added first and then + * retrieved. + */ +struct nxpwifi_ra_list_tbl * +nxpwifi_wmm_get_queue_raptr(struct nxpwifi_private *priv, u8 tid, + const u8 *ra_addr) +{ + struct nxpwifi_ra_list_tbl *ra_list; + + ra_list =3D nxpwifi_wmm_get_ralist_node(priv, tid, ra_addr); + if (ra_list) + return ra_list; + nxpwifi_ralist_add(priv, ra_addr); + + return nxpwifi_wmm_get_ralist_node(priv, tid, ra_addr); +} + +/* This function deletes RA list nodes for given mac for all TIDs. + * Function also decrements TX pending count accordingly. + */ +void +nxpwifi_wmm_del_peer_ra_list(struct nxpwifi_private *priv, const u8 *ra_ad= dr) +{ + struct nxpwifi_ra_list_tbl *ra_list; + int i; + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + for (i =3D 0; i < MAX_NUM_TID; ++i) { + ra_list =3D nxpwifi_wmm_get_ralist_node(priv, i, ra_addr); + + if (!ra_list) + continue; + nxpwifi_wmm_del_pkts_in_ralist_node(priv, ra_list); + if (ra_list->tx_paused) + priv->wmm.pkts_paused[i] -=3D ra_list->total_pkt_count; + else + atomic_sub(ra_list->total_pkt_count, + &priv->wmm.tx_pkts_queued); + list_del(&ra_list->list); + kfree(ra_list); + } + spin_unlock_bh(&priv->wmm.ra_list_spinlock); +} + +/* This function checks if a particular RA list node exists in a given TID + * table index. + */ +int +nxpwifi_is_ralist_valid(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ra_list, int ptr_index) +{ + struct nxpwifi_ra_list_tbl *rlist; + + list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, + list) { + if (rlist =3D=3D ra_list) + return true; + } + + return false; +} + +/* This function adds a packet to bypass TX queue. + * This is special TX queue for packets which can be sent even when port_o= pen + * is false. + */ +void +nxpwifi_wmm_add_buf_bypass_txqueue(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + skb_queue_tail(&priv->bypass_txq, skb); +} + +/* This function adds a packet to WMM queue. + * + * In disconnected state the packet is immediately dropped and the + * packet send completion callback is called with status failure. + * + * Otherwise, the correct RA list node is located and the packet + * is queued at the list tail. + */ +void +nxpwifi_wmm_add_buf_txqueue(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + u32 tid; + struct nxpwifi_ra_list_tbl *ra_list; + u8 ra[ETH_ALEN], tid_down; + struct ethhdr *eth_hdr =3D (struct ethhdr *)skb->data; + + memcpy(ra, eth_hdr->h_dest, ETH_ALEN); + + if (!priv->media_connected && !nxpwifi_is_skb_mgmt_frame(skb)) { + nxpwifi_dbg(adapter, DATA, "data: drop packet in disconnect\n"); + nxpwifi_write_data_complete(adapter, skb, 0, -1); + return; + } + + tid =3D skb->priority; + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + tid_down =3D nxpwifi_wmm_downgrade_tid(priv, tid); + + /* In case of infra as we have already created the list during + * association we just don't have to call get_queue_raptr, we will + * have only 1 raptr for a tid in case of infra + */ + memcpy(ra, skb->data, ETH_ALEN); + if (is_multicast_ether_addr(ra) || nxpwifi_is_skb_mgmt_frame(skb)) + eth_broadcast_addr(ra); + ra_list =3D nxpwifi_wmm_get_queue_raptr(priv, tid_down, ra); + + if (!ra_list) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_write_data_complete(adapter, skb, 0, -1); + return; + } + + skb_queue_tail(&ra_list->skb_head, skb); + + ra_list->ba_pkt_count++; + ra_list->total_pkt_count++; + + if (atomic_read(&priv->wmm.highest_queued_prio) < + priv->tos_to_tid_inv[tid_down]) + atomic_set(&priv->wmm.highest_queued_prio, + priv->tos_to_tid_inv[tid_down]); + + if (ra_list->tx_paused) + priv->wmm.pkts_paused[tid_down]++; + else + atomic_inc(&priv->wmm.tx_pkts_queued); + + spin_unlock_bh(&priv->wmm.ra_list_spinlock); +} + +/* This function processes the get WMM status command response from firmwa= re. + * + * The response may contain multiple TLVs - + * - AC Queue status TLVs + * - Current WMM Parameter IE TLV + * - Admission Control action frame TLVs + * + * This function parses the TLVs and then calls further specific functions + * to process any changes in the queue prioritize or state. + */ +int nxpwifi_ret_wmm_get_status(struct nxpwifi_private *priv, + const struct host_cmd_ds_command *resp) +{ + u8 *curr =3D (u8 *)&resp->params.get_wmm_status; + u16 resp_len =3D le16_to_cpu(resp->size), tlv_len; + int mask =3D IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK; + bool valid =3D true; + + struct nxpwifi_ie_types_data *tlv_hdr; + struct nxpwifi_ie_types_wmm_queue_status *wmm_qs; + struct ieee_types_wmm_parameter *wmm_param_ie =3D NULL; + struct nxpwifi_wmm_ac_status *ac_status; + + nxpwifi_dbg(priv->adapter, INFO, + "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", + resp_len); + + while ((resp_len >=3D sizeof(tlv_hdr->header)) && valid) { + tlv_hdr =3D (struct nxpwifi_ie_types_data *)curr; + tlv_len =3D le16_to_cpu(tlv_hdr->header.len); + + if (resp_len < tlv_len + sizeof(tlv_hdr->header)) + break; + + switch (le16_to_cpu(tlv_hdr->header.type)) { + case TLV_TYPE_WMMQSTATUS: + wmm_qs =3D (struct nxpwifi_ie_types_wmm_queue_status *) + tlv_hdr; + nxpwifi_dbg(priv->adapter, CMD, + "info: CMD_RESP: WMM_GET_STATUS:\t" + "QSTATUS TLV: %d, %d, %d\n", + wmm_qs->queue_index, + wmm_qs->flow_required, + wmm_qs->disabled); + + ac_status =3D &priv->wmm.ac_status[wmm_qs->queue_index]; + ac_status->disabled =3D wmm_qs->disabled; + ac_status->flow_required =3D wmm_qs->flow_required; + ac_status->flow_created =3D wmm_qs->flow_created; + break; + + case WLAN_EID_VENDOR_SPECIFIC: + /* Point the regular IEEE IE 2 bytes into the NXP IE + * and setup the IEEE IE type and length byte fields + */ + + wmm_param_ie =3D + (struct ieee_types_wmm_parameter *)(curr + 2); + wmm_param_ie->vend_hdr.len =3D (u8)tlv_len; + wmm_param_ie->vend_hdr.element_id =3D + WLAN_EID_VENDOR_SPECIFIC; + + nxpwifi_dbg(priv->adapter, CMD, + "info: CMD_RESP: WMM_GET_STATUS:\t" + "WMM Parameter Set Count: %d\n", + wmm_param_ie->qos_info_bitmap & mask); + + if (wmm_param_ie->vend_hdr.len + 2 > + sizeof(struct ieee_types_wmm_parameter)) + break; + + memcpy(&priv->curr_bss_params.bss_descriptor.wmm_ie, + wmm_param_ie, wmm_param_ie->vend_hdr.len + 2); + + break; + + default: + valid =3D false; + break; + } + + curr +=3D (tlv_len + sizeof(tlv_hdr->header)); + resp_len -=3D (tlv_len + sizeof(tlv_hdr->header)); + } + + nxpwifi_wmm_setup_queue_priorities(priv, wmm_param_ie); + nxpwifi_wmm_setup_ac_downgrade(priv); + + return 0; +} + +/* Callback handler from the command module to allow insertion of a WMM TL= V. + * + * If the BSS we are associating to supports WMM, this function adds the + * required WMM Information IE to the association request command buffer in + * the form of a NXP extended IEEE IE. + */ +u32 +nxpwifi_wmm_process_association_req(struct nxpwifi_private *priv, + u8 **assoc_buf, + struct ieee_types_wmm_parameter *wmm_ie, + struct ieee80211_ht_cap *ht_cap) +{ + struct nxpwifi_ie_types_wmm_param_set *wmm_tlv; + u32 ret_len =3D 0; + + /* Null checks */ + if (!assoc_buf) + return 0; + if (!(*assoc_buf)) + return 0; + + if (!wmm_ie) + return 0; + + nxpwifi_dbg(priv->adapter, INFO, + "info: WMM: process assoc req: bss->wmm_ie=3D%#x\n", + wmm_ie->vend_hdr.element_id); + + if ((priv->wmm_required || + (ht_cap && (priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN))) && + wmm_ie->vend_hdr.element_id =3D=3D WLAN_EID_VENDOR_SPECIFIC) { + wmm_tlv =3D (struct nxpwifi_ie_types_wmm_param_set *)*assoc_buf; + wmm_tlv->header.type =3D cpu_to_le16((u16)wmm_info_ie[0]); + wmm_tlv->header.len =3D cpu_to_le16((u16)wmm_info_ie[1]); + memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], + le16_to_cpu(wmm_tlv->header.len)); + if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) + memcpy((u8 *)(wmm_tlv->wmm_ie + + le16_to_cpu(wmm_tlv->header.len) + - sizeof(priv->wmm_qosinfo)), + &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo)); + + ret_len =3D sizeof(wmm_tlv->header) + + le16_to_cpu(wmm_tlv->header.len); + + *assoc_buf +=3D ret_len; + } + + return ret_len; +} + +/* This function computes the time delay in the driver queues for a + * given packet. + * + * When the packet is received at the OS/Driver interface, the current + * time is set in the packet structure. The difference between the present + * time and that received time is computed in this function and limited + * based on pre-compiled limits in the driver. + */ +u8 +nxpwifi_wmm_compute_drv_pkt_delay(struct nxpwifi_private *priv, + const struct sk_buff *skb) +{ + u32 queue_delay =3D ktime_to_ms(net_timedelta(skb->tstamp)); + u8 ret_val; + + /* Queue delay is passed as a uint8 in units of 2ms (ms shifted + * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. + * + * Pass max value if queue_delay is beyond the uint8 range + */ + ret_val =3D (u8)(min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); + + nxpwifi_dbg(priv->adapter, DATA, "data: WMM: Pkt Delay: %d ms,\t" + "%d ms sent to FW\n", queue_delay, ret_val); + + return ret_val; +} + +/* This function retrieves the highest priority RA list table pointer. + */ +static struct nxpwifi_ra_list_tbl * +nxpwifi_wmm_get_highest_priolist_ptr(struct nxpwifi_adapter *adapter, + struct nxpwifi_private **priv, int *tid) +{ + struct nxpwifi_private *priv_tmp; + struct nxpwifi_ra_list_tbl *ptr; + struct nxpwifi_tid_tbl *tid_ptr; + atomic_t *hqp; + int i, j; + u8 to_tid; + + /* check the BSS with highest priority first */ + for (j =3D adapter->priv_num - 1; j >=3D 0; --j) { + /* iterate over BSS with the equal priority */ + list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur, + &adapter->bss_prio_tbl[j].bss_prio_head, + list) { +try_again: + priv_tmp =3D adapter->bss_prio_tbl[j].bss_prio_cur->priv; + + if (!priv_tmp->port_open || + (atomic_read(&priv_tmp->wmm.tx_pkts_queued) =3D=3D 0)) + continue; + + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv_tmp)) + continue; + + /* iterate over the WMM queues of the BSS */ + hqp =3D &priv_tmp->wmm.highest_queued_prio; + for (i =3D atomic_read(hqp); i >=3D LOW_PRIO_TID; --i) { + spin_lock_bh(&priv_tmp->wmm.ra_list_spinlock); + + to_tid =3D tos_to_tid[i]; + tid_ptr =3D &(priv_tmp)->wmm.tid_tbl_ptr[to_tid]; + + /* iterate over receiver addresses */ + list_for_each_entry(ptr, &tid_ptr->ra_list, + list) { + if (!ptr->tx_paused && + !skb_queue_empty(&ptr->skb_head)) + /* holds both locks */ + goto found; + } + + spin_unlock_bh(&priv_tmp->wmm.ra_list_spinlock); + } + + if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) !=3D 0) { + atomic_set(&priv_tmp->wmm.highest_queued_prio, + HIGH_PRIO_TID); + /* Iterate current private once more, since + * there still exist packets in data queue + */ + goto try_again; + } else { + atomic_set(&priv_tmp->wmm.highest_queued_prio, + NO_PKT_PRIO_TID); + } + } + } + + return NULL; + +found: + /* holds ra_list_spinlock */ + if (atomic_read(hqp) > i) + atomic_set(hqp, i); + spin_unlock_bh(&priv_tmp->wmm.ra_list_spinlock); + + *priv =3D priv_tmp; + *tid =3D tos_to_tid[i]; + + return ptr; +} + +/* This functions rotates ra and bss lists so packets are picked round rob= in. + * + * After a packet is successfully transmitted, rotate the ra list, so the = ra + * next to the one transmitted, will come first in the list. This way we p= ick + * the ra' in a round robin fashion. Same applies to bss nodes of equal + * priority. + * + * Function also increments wmm.packets_out counter. + */ +void nxpwifi_rotate_priolists(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ra, + int tid) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_bss_prio_tbl *tbl =3D adapter->bss_prio_tbl; + struct nxpwifi_tid_tbl *tid_ptr =3D &priv->wmm.tid_tbl_ptr[tid]; + + spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock); + /* dirty trick: we remove 'head' temporarily and reinsert it after + * curr bss node. imagine list to stay fixed while head is moved + */ + list_move(&tbl[priv->bss_priority].bss_prio_head, + &tbl[priv->bss_priority].bss_prio_cur->list); + spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock); + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + if (nxpwifi_is_ralist_valid(priv, ra, tid)) { + priv->wmm.packets_out[tid]++; + /* same as above */ + list_move(&tid_ptr->ra_list, &ra->list); + } + spin_unlock_bh(&priv->wmm.ra_list_spinlock); +} + +/* This function checks if 11n aggregation is possible. + */ +static int +nxpwifi_is_11n_aggragation_possible(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr, + int max_buf_size) +{ + int count =3D 0, total_size =3D 0; + struct sk_buff *skb, *tmp; + int max_amsdu_size; + + if (priv->bss_role =3D=3D NXPWIFI_BSS_ROLE_UAP && priv->ap_11n_enabled && + ptr->is_11n_enabled) + max_amsdu_size =3D min_t(int, ptr->max_amsdu, max_buf_size); + else + max_amsdu_size =3D max_buf_size; + + skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { + total_size +=3D skb->len; + if (total_size >=3D max_amsdu_size) + break; + if (++count >=3D MIN_NUM_AMSDU) + return true; + } + + return false; +} + +/* This function sends a single packet to firmware for transmission. + */ +static void +nxpwifi_send_single_packet(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr, int ptr_index) +__releases(&priv->wmm.ra_list_spinlock) +{ + struct sk_buff *skb, *skb_next; + struct nxpwifi_tx_param tx_param; + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct nxpwifi_txinfo *tx_info; + + if (skb_queue_empty(&ptr->skb_head)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_dbg(adapter, DATA, "data: nothing to send\n"); + return; + } + + skb =3D skb_dequeue(&ptr->skb_head); + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + nxpwifi_dbg(adapter, DATA, + "data: dequeuing the packet %p %p\n", ptr, skb); + + ptr->total_pkt_count--; + + if (!skb_queue_empty(&ptr->skb_head)) + skb_next =3D skb_peek(&ptr->skb_head); + else + skb_next =3D NULL; + + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + + tx_param.next_pkt_len =3D ((skb_next) ? skb_next->len + + sizeof(struct txpd) : 0); + + if (nxpwifi_process_tx(priv, skb, &tx_param) =3D=3D -EBUSY) { + /* Queue the packet back at the head */ + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + if (!nxpwifi_is_ralist_valid(priv, ptr, ptr_index)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_write_data_complete(adapter, skb, 0, -1); + return; + } + + skb_queue_tail(&ptr->skb_head, skb); + + ptr->total_pkt_count++; + ptr->ba_pkt_count++; + tx_info->flags |=3D NXPWIFI_BUF_FLAG_REQUEUED_PKT; + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + } else { + nxpwifi_rotate_priolists(priv, ptr, ptr_index); + atomic_dec(&priv->wmm.tx_pkts_queued); + } +} + +/* This function checks if the first packet in the given RA list + * is already processed or not. + */ +static int +nxpwifi_is_ptr_processed(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr) +{ + struct sk_buff *skb; + struct nxpwifi_txinfo *tx_info; + + if (skb_queue_empty(&ptr->skb_head)) + return false; + + skb =3D skb_peek(&ptr->skb_head); + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + if (tx_info->flags & NXPWIFI_BUF_FLAG_REQUEUED_PKT) + return true; + + return false; +} + +/* This function sends a single processed packet to firmware for + * transmission. + */ +static void +nxpwifi_send_processed_packet(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ptr, int ptr_index) + __releases(&priv->wmm.ra_list_spinlock) +{ + struct nxpwifi_tx_param tx_param; + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret =3D -1; + struct sk_buff *skb, *skb_next; + struct nxpwifi_txinfo *tx_info; + + if (skb_queue_empty(&ptr->skb_head)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + return; + } + + skb =3D skb_dequeue(&ptr->skb_head); + + if (adapter->data_sent || adapter->tx_lock_flag) { + ptr->total_pkt_count--; + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + skb_queue_tail(&adapter->tx_data_q, skb); + atomic_dec(&priv->wmm.tx_pkts_queued); + atomic_inc(&adapter->tx_queued); + return; + } + + if (!skb_queue_empty(&ptr->skb_head)) + skb_next =3D skb_peek(&ptr->skb_head); + else + skb_next =3D NULL; + + tx_info =3D NXPWIFI_SKB_TXCB(skb); + + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + + tx_param.next_pkt_len =3D + ((skb_next) ? skb_next->len + + sizeof(struct txpd) : 0); + + ret =3D adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_DATA, + skb, &tx_param); + + switch (ret) { + case -EBUSY: + nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); + spin_lock_bh(&priv->wmm.ra_list_spinlock); + + if (!nxpwifi_is_ralist_valid(priv, ptr, ptr_index)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + nxpwifi_write_data_complete(adapter, skb, 0, -1); + return; + } + + skb_queue_tail(&ptr->skb_head, skb); + + tx_info->flags |=3D NXPWIFI_BUF_FLAG_REQUEUED_PKT; + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + break; + case -1: + nxpwifi_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret); + adapter->dbg.num_tx_host_to_card_failure++; + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + case -EINPROGRESS: + break; + case 0: + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + default: + break; + } + if (ret !=3D -EBUSY) { + nxpwifi_rotate_priolists(priv, ptr, ptr_index); + atomic_dec(&priv->wmm.tx_pkts_queued); + spin_lock_bh(&priv->wmm.ra_list_spinlock); + ptr->total_pkt_count--; + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + } +} + +/* This function dequeues a packet from the highest priority list + * and transmits it. + */ +static int +nxpwifi_dequeue_tx_packet(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_ra_list_tbl *ptr; + struct nxpwifi_private *priv =3D NULL; + int ptr_index =3D 0; + u8 ra[ETH_ALEN]; + int tid_del =3D 0, tid =3D 0; + + ptr =3D nxpwifi_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); + if (!ptr) + return -1; + + tid =3D nxpwifi_get_tid(ptr); + + nxpwifi_dbg(adapter, DATA, "data: tid=3D%d\n", tid); + + spin_lock_bh(&priv->wmm.ra_list_spinlock); + if (!nxpwifi_is_ralist_valid(priv, ptr, ptr_index)) { + spin_unlock_bh(&priv->wmm.ra_list_spinlock); + return -1; + } + + if (nxpwifi_is_ptr_processed(priv, ptr)) { + nxpwifi_send_processed_packet(priv, ptr, ptr_index); + /* ra_list_spinlock has been freed in + * nxpwifi_send_processed_packet() + */ + return 0; + } + + if (!ptr->is_11n_enabled || + ptr->ba_status || + priv->wps.session_enable) { + if (ptr->is_11n_enabled && + ptr->ba_status && + ptr->amsdu_in_ampdu && + nxpwifi_is_amsdu_allowed(priv, tid) && + nxpwifi_is_11n_aggragation_possible(priv, ptr, + adapter->tx_buf_size)) + nxpwifi_11n_aggregate_pkt(priv, ptr, ptr_index); + /* ra_list_spinlock has been freed in + * nxpwifi_11n_aggregate_pkt() + */ + else + nxpwifi_send_single_packet(priv, ptr, ptr_index); + /* ra_list_spinlock has been freed in + * nxpwifi_send_single_packet() + */ + } else { + if (nxpwifi_is_ampdu_allowed(priv, ptr, tid) && + ptr->ba_pkt_count > ptr->ba_packet_thr) { + if (nxpwifi_space_avail_for_new_ba_stream(adapter)) { + nxpwifi_create_ba_tbl(priv, ptr->ra, tid, + BA_SETUP_INPROGRESS); + nxpwifi_send_addba(priv, tid, ptr->ra); + } else if (nxpwifi_find_stream_to_delete + (priv, tid, &tid_del, ra)) { + nxpwifi_create_ba_tbl(priv, ptr->ra, tid, + BA_SETUP_INPROGRESS); + nxpwifi_send_delba(priv, tid_del, ra, 1); + } + } + if (nxpwifi_is_amsdu_allowed(priv, tid) && + nxpwifi_is_11n_aggragation_possible(priv, ptr, + adapter->tx_buf_size)) + nxpwifi_11n_aggregate_pkt(priv, ptr, ptr_index); + /* ra_list_spinlock has been freed in + * nxpwifi_11n_aggregate_pkt() + */ + else + nxpwifi_send_single_packet(priv, ptr, ptr_index); + /* ra_list_spinlock has been freed in + * nxpwifi_send_single_packet() + */ + } + return 0; +} + +void nxpwifi_process_bypass_tx(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_tx_param tx_param; + struct sk_buff *skb; + struct nxpwifi_txinfo *tx_info; + struct nxpwifi_private *priv; + int i; + + if (adapter->data_sent || adapter->tx_lock_flag) + return; + + for (i =3D 0; i < adapter->priv_num; ++i) { + priv =3D adapter->priv[i]; + + if (!priv) + continue; + + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + + if (skb_queue_empty(&priv->bypass_txq)) + continue; + + skb =3D skb_dequeue(&priv->bypass_txq); + tx_info =3D NXPWIFI_SKB_TXCB(skb); + + /* no aggregation for bypass packets */ + tx_param.next_pkt_len =3D 0; + + if (nxpwifi_process_tx(priv, skb, &tx_param) =3D=3D -EBUSY) { + skb_queue_head(&priv->bypass_txq, skb); + tx_info->flags |=3D NXPWIFI_BUF_FLAG_REQUEUED_PKT; + } else { + atomic_dec(&adapter->bypass_tx_pending); + } + } +} + +/* This function transmits the highest priority packet awaiting in the + * WMM Queues. + */ +void +nxpwifi_wmm_process_tx(struct nxpwifi_adapter *adapter) +{ + do { + if (nxpwifi_dequeue_tx_packet(adapter)) + break; + if (adapter->iface_type !=3D NXPWIFI_SDIO) { + if (adapter->data_sent || + adapter->tx_lock_flag) + break; + } else { + if (atomic_read(&adapter->tx_queued) >=3D + NXPWIFI_MAX_PKTS_TXQ) + break; + } + } while (!nxpwifi_wmm_lists_empty(adapter)); +} --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E51C17C231; Fri, 21 Jun 2024 07:54:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956492; cv=fail; b=Qa4Ku++9SSpSjpJc6xLMhriyfXTsoNZbQtbwOd0Xzbrg2avaT7tYzj0ikQEQ3Q3r/w2GnsavfiywR+XpGHmUmgzHltcd9BxZGl56YuVbrdj6LrT+RYxE+4SASYsBAInB1Ad/PSdrmhja65MrInwvg3I5H0dvccl04BQcwfcxn0E= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956492; c=relaxed/simple; bh=6kz0dAR7s+4BKduwOOZeVo52NyWSIIA1RC0qWf817/0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Rrs/CbctGnPXyVPD0oXIc7i3ObZnlz8zGCiWzV4DdXkEjekHD+c0pgPZtm1kq6F5fv5PBgthhkYVWVujGGE/O9F6xUSXfqnKWluiVq7r0RlYfKBWQpmXZGRTItbzu18vR/Vr8lKxkgMRYdw8hUmL1PvKs5PIicd3vVWdfBgTFqY= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=l7U1rQMG; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="l7U1rQMG" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YrhJs5xYKZPdvqt1kl/NbVZXZciMPAUzLkREUB38kWEuXoLYViSGroWsXUu8YUI9bjfi9FVLul6vJ5l6XDmbXsbG3IM3ehvGAWpOa8mDVqNfe3zBMzQ8ybA9rBsS8Exmsz/gvtjq40GKf7DiUkNjNL4rBFyMCrJcgH1iY0JA/q6RnTnqzRttAbPKLdundEoL6Kq0fiUe7RMMHFLXPEMKvIu4cuDst8703uzlRA+sYlsIMQ1GxbaQY23UzeO0c/hY/uwlm9njzkVqadcJ1LsVAZy1MqAeCxamXG52DPJYpHigBZom1VtzuBzI+IO8ts/YNYd8hZ1clgg7FLk2U3bSPg== 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=z6Ig7070qJrDsRlIbUuyG6Lpe4pP3AavFpuqyDJICvA=; b=Eih9zTeMEsya9FZS2BiK76hV9OWabKa26j5F9bXAq9eR1QThOIPBcUMsGRlbgVPdpjt9iWUw5T6uhubDZFMP8C0yGUvr5TvzOzSe91ibvPLVyFbZtM2WilZZU9xFc6LQCRI2f8Z2o45EecsljfuYgwmEQwZlG615TvO0RyAZsMJwcpngtzt2agInAbj+hlZWC9/8IoG0fXkGyCuGFVUGDoeqrk79K4sp3WcKFBU7TL6hBd54WkSXKINDfB32q21U3/S3y2T/xvp0+jSWkcNK+awOmqGNc6UvTC0XGp+PD1SNzj7bSPD/rZcm58iLujDNEKu6OxDKGyNx3AiXPZvm2A== 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=z6Ig7070qJrDsRlIbUuyG6Lpe4pP3AavFpuqyDJICvA=; b=l7U1rQMGjIiQV0fHvwEGalclUVFwoGdcZfDpiAXA1STrPwQdsqN4tYrJVyeXKTQvOkRgEMwQPSxhZRl1F4szQ+LARt+M0hGfGzTvPzJb1a3Qn0kNSTjTnHhz+m5NA20ILBeqsQlskhapJGrcpqI6A7p5fsAbMqfY+Q90Jj+UgFc= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:45 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:45 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 40/43] wifi: nxpwifi: add wmm.h Date: Fri, 21 Jun 2024 15:52:05 +0800 Message-Id: <20240621075208.513497-41-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 91503985-3dc1-47df-ab51-08dc91c76ab2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?wpY9iqHD8IpcL+JHYnacArJx1s7SBcRx4HEDvgjkxKKkqKs2FjX8oMQCIz7N?= =?us-ascii?Q?KqtOybVp2pJGCpRpmt+qstdbphhRUNwASOE3KSmwGEBcIz3UvQp4YKWde1Dq?= =?us-ascii?Q?qxsSu0e1VPBYwIs+D4xJGzWvdHpfhHDwc1+0hKvOPIp+EDaRGnKPUjEcxJG3?= =?us-ascii?Q?U+1by6A49Pinc39G6mXbLBSKpjB3eskR2UhdxtO5ylZrwiBFvuwWeMpJYD5t?= =?us-ascii?Q?s92566Gx9Ny4PBpq9iIL4OliT/yxzVrYL3q1feBymW4XvBQwjSm7qmWNlE+B?= =?us-ascii?Q?lbmspYomvucdYEwhQ0qEv8YgFkei+3AvYswpT673MvZAaNDxJ919Bq72c2Vk?= =?us-ascii?Q?Gm0wFxWGvJ/vSLYDoR/xLDuTRjIwuTxbdd7N8wDSJIHvXIBLxyTzppEb3Ezx?= =?us-ascii?Q?Dz3e2UeyjkefXP69FfyKlqriquL9puGRRmKEhkhCgEMesQ7dnhVhLBDP4a4U?= =?us-ascii?Q?U0HOihYISR4FhcU2g4G6xpd+4uKD6ldTrXplc3iwx8j+mi6Dc0txu6jElD+j?= =?us-ascii?Q?y6tqZkIwugHrEs8C/Lt6nnlYUcSBfhiGMy5Irl/5+7eAppwpLhbD6l2VvkxS?= =?us-ascii?Q?0GuWDrUB46VhjilJZDcwrXs3OIKLr61k2YY2dggvBK1l93oYPfvmQd+ODZNy?= =?us-ascii?Q?bClDJqosBpsK66zKfSDzKHVnCddEJxXEX8q64p0UniudML7CpXfQyB/r9g/V?= =?us-ascii?Q?QN2HX5ZAKx2szq4HqQTXmxdpy56nrazM7l+2Vby6EW6hgd8PQyX8cQNmO992?= =?us-ascii?Q?TVx9vtfPu3JLZbkrJv7stSTA59YlAStnaDRMX81Tp/EAdINu66GXK0sopkt5?= =?us-ascii?Q?3Hbdyk1H9IAellb2PpsPIMYKUoFn+8RVKLQiylApWMVC4XrPLzbi2WEEE6PO?= =?us-ascii?Q?ZLzxY+JrncFYxoLkziOqVqprWalQOKX+ylZ13raGH/Zy3hTj3vgjRemnaDMx?= =?us-ascii?Q?pcV0mOA+YYX1+kSt9shG+q8Dqv4IM8mK19qO/t0PXaynxGvh/BcBwus1P1R6?= =?us-ascii?Q?K5GeAH9Mwown4C32moLe+JNE/cpxk9F/MnswXKEmgkE+C3R+tZ2zUd+Mgm+X?= =?us-ascii?Q?LICauGSlJTnWOkxPUfc6K/k1thKx1itk0f5LwwWVO7HtQavn9LvMJcIhqQ43?= =?us-ascii?Q?h+F6hVSgVqVdcVob0Q1iQPa0Y47q7HljDkHqtl0ChIdTjChF9plA4nH5FEQd?= =?us-ascii?Q?gpBQ1KH6QcrxKsP8iKDcaqrXXGp7TJYU3NZ5CvuAXmWeOA4A3kq7UnCO5jcG?= =?us-ascii?Q?4Zt4xrnuXXWV+ep37fSq8J0LdJ90iDd2s0TouvIClUojuIHiwuXWwp5DbbgU?= =?us-ascii?Q?awDQoK15wWZSA+WKdWYHi7stO334/GZhBbfUth8dkpBqmsw3lCDLBEnNq5d3?= =?us-ascii?Q?xlNdZEA=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?dpEkJEOHPqIZm3T8xlZdYBMOxwbWvgAl/Zd0UdXz7ceg1VKcwDiGEyHp/fu7?= =?us-ascii?Q?7p1CYmKztZuvugL0gi2hEOghYZ2riocxOl/rq+9M/E1DZHstq4QaUIpmF4NR?= =?us-ascii?Q?/7PHefsqxHhfCwj9JTv3BLDAj78Vp6R6Lz0okSV0DdOkCGdLaA3snNLsycWB?= =?us-ascii?Q?WM4QaPYEueqYolcdnocGBi0FlA/ZkkG6kxz2U1XN0fO0o4YXt132ar/oNcUE?= =?us-ascii?Q?eF3mcHnr2wKjighE8+tWPiwMFGqYoShaMtc+F5M8w8ZmXeUnVuOARzBdbpDc?= =?us-ascii?Q?UJqntLqeF4Ff0RTZgU0O51A6x8NJGBuvHAU1D5rVcgSiRoND0HSSSwCnnUo9?= =?us-ascii?Q?iCc8+zW844q/UY4tnWeHTipgZEhK48hMxMBcupocUvSQ+flAxnkbxCJm9ZEQ?= =?us-ascii?Q?jJ/AbapNIePyBUIPvnS/xY6TuJbJ0CXMzgPeWujrIAl/W6rlcdmHm0s2YdGP?= =?us-ascii?Q?uI5VsqyzNkpuusDCOqIPn/OjgpHAQ5ADOvq6OXHrmcJmPXacoeR/gj0L6Zrh?= =?us-ascii?Q?b1Jueq645Vc6puRiJC4reulhpN7JaVbfczpwVatppaL1vX/0PVqgaZ3yxOi0?= =?us-ascii?Q?KpP9PKe3M83Li8IagORI9Hk4wR+7Voz4/9Id0+FovfqxBpyITKJt7EV3gFnd?= =?us-ascii?Q?kjk1LC/P4pnKrTI9cborklB0/LaljvCp385OlHV4bBtZmvhw9ZQUK2JazzKE?= =?us-ascii?Q?ao4XmLu/tdODgAoUHF4zTjwx9ptp2RZ3be1FqLqMpf01UTV0GX+k3jTh83b+?= =?us-ascii?Q?GNf2iub0beuwUww7JYgoH7s8nTCo8bHbINDUKk8gYVLErBTdyXl+7ZYvMoN8?= =?us-ascii?Q?YY/uij8/Jp7B4ynctP1JIaWAxS0Oj8RdzL9QUn1LQYBH3T6juH98BE++Eeiv?= =?us-ascii?Q?ZImlgNzEy9hj0mtX2VaVFSOB1IK0BVt0T4+IpppUADq5FNsvvm4d6AEhQL/3?= =?us-ascii?Q?u54C3FiLHTUXpOVZ4YvfZg9NFz7VMdCvmYKSnpcZHTPhznLYwvHhb3VYTbgj?= =?us-ascii?Q?rRKlQtM+HBVsIC53d1Nvgdr1vTf5NNxoSgvnNtInBD6HTrF9OSzxYR+9SObr?= =?us-ascii?Q?CUmD7A6D612miyOkrYX0H12a85VLVzGR1RhjesN4WIcyKZZPGs/guOt5EvGa?= =?us-ascii?Q?JJJ5xXtudBNA6EWF7T5SFfizfjDUn3eBMUFv8C0naFsHsnzY+YbZ68Q24wHK?= =?us-ascii?Q?/RuT3s7KJZeRTpPcCaJoGzWQ2TvFZ6rQyCuG0R2uDDhPrT/5b+frz0YPfESD?= =?us-ascii?Q?gMBdX8+IG7jEdvtxsz8xfdmmtTOtJVXs7QNXOt6Trkfw5c+U0yDs8CqWpnFk?= =?us-ascii?Q?mFIFCMZcyeYKKoxqAI8UqMSz8QzwUJKiYrmZAV/8P9rTitXwMsmkAeh/yjFL?= =?us-ascii?Q?IHS0WaiXvoPUtImhXUDEXJCCiuSdcxj38DnRYXe3otBVPfBbNAf6xJzpjH9t?= =?us-ascii?Q?L/4ebWGoFLEWRhswFPd+USHF7s7+FlWzQCojIW38C+1YbSctWPMMyq3aA5jP?= =?us-ascii?Q?+ttZYC/Zf2lcsAw9uwmeZ48ni8uBAXxZ/UCYkm4/IpXWiENXArle6oKg0cHN?= =?us-ascii?Q?V2/cknbf3PBndyTZzIG1STgPtDFV6wLKsLVV4wVQ?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 91503985-3dc1-47df-ab51-08dc91c76ab2 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:45.7762 (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: Ft0bSUvDbiG8EA05aAbuXIzRsMIIBxDZZJgc88SwEANh6vyrrwMfP3SkRnWewmgG7eXzjv6JKNJ/Cn9TxdzcXg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/nxp/nxpwifi/wmm.h | 95 ++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/wmm.h diff --git a/drivers/net/wireless/nxp/nxpwifi/wmm.h b/drivers/net/wireless/= nxp/nxpwifi/wmm.h new file mode 100644 index 000000000000..e1f8a1c80a2f --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/wmm.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NXP Wireless LAN device driver: WMM + * + * Copyright 2011-2024 NXP + */ + +#ifndef _NXPWIFI_WMM_H_ +#define _NXPWIFI_WMM_H_ + +enum ieee_types_wmm_aciaifsn_bitmasks { + NXPWIFI_AIFSN =3D (BIT(0) | BIT(1) | BIT(2) | BIT(3)), + NXPWIFI_ACM =3D BIT(4), + NXPWIFI_ACI =3D (BIT(5) | BIT(6)), +}; + +enum ieee_types_wmm_ecw_bitmasks { + NXPWIFI_ECW_MIN =3D (BIT(0) | BIT(1) | BIT(2) | BIT(3)), + NXPWIFI_ECW_MAX =3D (BIT(4) | BIT(5) | BIT(6) | BIT(7)), +}; + +extern const u16 nxpwifi_1d_to_wmm_queue[]; +extern const u8 tos_to_tid_inv[]; + +/* This function retrieves the TID of the given RA list. + */ +static inline int +nxpwifi_get_tid(struct nxpwifi_ra_list_tbl *ptr) +{ + struct sk_buff *skb; + + if (skb_queue_empty(&ptr->skb_head)) + return 0; + + skb =3D skb_peek(&ptr->skb_head); + + return skb->priority; +} + +/* This function checks if a RA list is empty or not. + */ +static inline u8 +nxpwifi_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) +{ + struct nxpwifi_ra_list_tbl *ra_list; + int is_list_empty; + + list_for_each_entry(ra_list, ra_list_hhead, list) { + is_list_empty =3D skb_queue_empty(&ra_list->skb_head); + if (!is_list_empty) + return false; + } + + return true; +} + +void nxpwifi_wmm_add_buf_txqueue(struct nxpwifi_private *priv, + struct sk_buff *skb); +void nxpwifi_wmm_add_buf_bypass_txqueue(struct nxpwifi_private *priv, + struct sk_buff *skb); +void nxpwifi_ralist_add(struct nxpwifi_private *priv, const u8 *ra); +void nxpwifi_rotate_priolists(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ra, int tid); + +int nxpwifi_wmm_lists_empty(struct nxpwifi_adapter *adapter); +int nxpwifi_bypass_txlist_empty(struct nxpwifi_adapter *adapter); +void nxpwifi_wmm_process_tx(struct nxpwifi_adapter *adapter); +void nxpwifi_process_bypass_tx(struct nxpwifi_adapter *adapter); +int nxpwifi_is_ralist_valid(struct nxpwifi_private *priv, + struct nxpwifi_ra_list_tbl *ra_list, int tid); + +u8 nxpwifi_wmm_compute_drv_pkt_delay(struct nxpwifi_private *priv, + const struct sk_buff *skb); +void nxpwifi_wmm_init(struct nxpwifi_adapter *adapter); + +u32 nxpwifi_wmm_process_association_req(struct nxpwifi_private *priv, + u8 **assoc_buf, + struct ieee_types_wmm_parameter *wmmie, + struct ieee80211_ht_cap *htcap); + +void nxpwifi_wmm_setup_queue_priorities(struct nxpwifi_private *priv, + struct ieee_types_wmm_parameter *wmm_ie); +void nxpwifi_wmm_setup_ac_downgrade(struct nxpwifi_private *priv); +int nxpwifi_ret_wmm_get_status(struct nxpwifi_private *priv, + const struct host_cmd_ds_command *resp); +struct nxpwifi_ra_list_tbl * +nxpwifi_wmm_get_queue_raptr(struct nxpwifi_private *priv, u8 tid, + const u8 *ra_addr); +u8 nxpwifi_wmm_downgrade_tid(struct nxpwifi_private *priv, u32 tid); +void nxpwifi_update_ralist_tx_pause(struct nxpwifi_private *priv, u8 *mac, + u8 tx_pause); + +struct nxpwifi_ra_list_tbl *nxpwifi_wmm_get_ralist_node(struct nxpwifi_pri= vate + *priv, u8 tid, const u8 *ra_addr); +#endif /* !_NXPWIFI_WMM_H_ */ --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F32EA17C7AB; Fri, 21 Jun 2024 07:54:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956494; cv=fail; b=a78n9755VEbNrHmqsDSKzJ2b/GTzUuZrDCx+QolZMRQvtbD18dgREkQAXN7bpe+SRuckkILji14s3woV0lfr3BEUqyCK5XWCrckmAf0+rw9//6O7kGx5+zxzZ2fGKmeYAfs6qhsUiv8QdSmY/7iPLyEcuCP4Wx+amK8BECZU2JY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956494; c=relaxed/simple; bh=n17QDADJXrjc3wuFOUIEeEJWZL+PpjoYbwMv0BO0H3I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=pFEVj+zR3Ysbx5yAm0bYPuz5v3IpxkEOBjCu5IcOy9IBc1Kp/xl1QLIxUla8CTShLe9IKfQwHKPTXFfAk2E7kfjMzQcNQ29BYnKmci07EyyTkSUMz8mQCW773XNGQn37GiHLF6dt9/8dBoofRO+dcy3wtuTt9K08v2GcY1VcnlU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=pJrAaHch; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="pJrAaHch" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YZV2AqoQrW9xM+65tgzdMDPGn3Np8JvvKzrbe/x0SuXHsomg85aIkRWCAJTMhRze+YsOi7dZiJ2FuqnSZ6zjDtI7qOIa5C8oVn15Y5q25zH9Y1y0hZm/10v9ju5PHGLonv+LYE1H3hHRWWvl5KLdfrrNhmvaNt/8CGNDKwnpN/n1x5Wbr+KvyLmbKiQAdNObTwzF2TSVQtSkGKSugvZWhjKZf/VJn8EigWwY0Wf/zgECu2voSu8jCWXdWUWQXJI2rDKJHAFLYoZtxJjeJHTVqbJCv7ZfazUX/q3qw4+0cDiTgHzvcVh/D+SesSy6kMAIzgGE+kE13xFvAqyy9f9tVw== 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=Z7MeuOgQrbSP0BuVj0rjMFxdtU8YgEfcffhYnh1ojkU=; b=dL43LMxs3J9ScDLmRbCIzKS2Li//wE4WeFzp5RHZsi6BTSk6ZAuCdrwCgdrgkhJQc/Y0SRZqtcKEZOacfa/vdOTmvKYPRo7HXtuDENUICM11moZowGJUEwX5Yl2n+ZV+fn8uerv1KzUUKX7ZxsC0FS3pnMfK5HPivDvRL953Y0l9fZtXo6qoG8P5j+8Ckc69gr+tjQYY8UI3fFKePM6jsFfV5u82aQrnFEDakHx9jmtHP23EC5bG0axYPhfg4G1fin1xE2YmvWONJhUX8G+x3hhk48XnT/HxupcVqCC/fEV+Hzlur2ilN8cV8jQo/rv5JBTgru9s+kEKJyMelrY8Vg== 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=Z7MeuOgQrbSP0BuVj0rjMFxdtU8YgEfcffhYnh1ojkU=; b=pJrAaHchrhzxM1xLNyzs0VyMP95dyIsnb5hXvODaylX+7RE7tJkxyosKgVt1Iy5gJdNfGHvNT5tXG7dakG4NwpZnSh8ksfTLTccRMX0OBrifG0GL22kfPtmyzL8o1dOYY+lt0TE8biFh+RhFHIwbtPLYfFM3/mcJqpi77P1vwoA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:49 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:49 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 41/43] wifi: nxpwifi: add nxp sdio vendor id and iw61x device id Date: Fri, 21 Jun 2024 15:52:06 +0800 Message-Id: <20240621075208.513497-42-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 49007c16-0564-4ba5-5a25-08dc91c76c72 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?P26wOFSNUr/S4E+3uuTNO2RFqL//kvNOWu0cd4zAh2KqWSiBBWdMh+PKnOIW?= =?us-ascii?Q?ilAOxtvNdhOP2ZcSeP48IhItChQzy47EPqs+r6TRhNMYc5M8vxzY6vdxwEHC?= =?us-ascii?Q?owNvOmTCAj8slRXcpG9HTuZ3PzAVxMt97YLYOxHjZImlaFGbgnU/mwwt6/CX?= =?us-ascii?Q?ypHJB3W/IU/aM7nipjpQ2vbyEh7oE65SjNSv3+VMHaeNJegrD5/cgGzqm7Bx?= =?us-ascii?Q?sQB3IvfgAMjhg5rRto6qpK+cHRzZZt9l2F1xYIqZxkFaj2u/QCpEBp70YHDC?= =?us-ascii?Q?czm0xzgQ3+hhemeCPafnf6tQwiMqvq+2LWLeDhcFRYH3WbKKPX0v4SqpYYSy?= =?us-ascii?Q?LjFkjYBW8D2A3woMmfQG+9JaOkjuQ3sJKjwCFhEMKlY1xvyJaFbciWWFQbjH?= =?us-ascii?Q?lofLcSdAve7WcixcgRUWJxO0/y0gsvFkuxv7ZGUwTIeokAT6G/IIA69JclKB?= =?us-ascii?Q?R+pUcHQfSq34noqWw8zuaRFixigHbIwOvWCoG3wNgI5w4rtg9PJKTTt4cJzT?= =?us-ascii?Q?I4GrAVAlhJCOuXnviPmxUDYscumd609XFWaalL3dEnYFhqW5fpQX4FHXWkQk?= =?us-ascii?Q?bBXiWf9uq/kKV7dbhLWMHBX3ZSS+uZuaLktaZoM4ZcXzUDEM7+tQREQvhHHb?= =?us-ascii?Q?oHNZbHkNO4Rb0FnPZWfq5fsyQI1DeCO4mS/bq4i6XpY5ZFIdnPLceZtEXgii?= =?us-ascii?Q?n17Axh6kX/SvAffDkCaNyUyoINkTERajgzrHFNcg+g6JKZZZqNqic5ef74eQ?= =?us-ascii?Q?1ZyiLiGSkInhkJAPMPRIlfnr9KNoIUDyujUsOZNHaB0msLj6uSD0JIaO0yy8?= =?us-ascii?Q?2jpkswphESGV4btoeoetsn6udxxxYjqM3FIa1sh4J8IQ8pRjir4vWV/vWPtk?= =?us-ascii?Q?jYI6UxAjHMQUM6f7TVaWb3uiZ9SeUYt+ABfULl41Iz9txRXHqIz82jK8Ka/l?= =?us-ascii?Q?NRh97TWdbHUYLvBLPVoF44UIWa9DsSQ+M8WWohRUkw9h7RoeoM7tflErENDD?= =?us-ascii?Q?yKy5RCBWFAIm5IPIAgQNUbevBlAJVyM2NYgi5brTCccSZs1AxDBxNXZ37XTJ?= =?us-ascii?Q?bpYXK0pERHXCgbGYsjj2ADBeLpWFrsKmXvv4Q4JVhNgbr2pgvVEnDFSfejGP?= =?us-ascii?Q?D8ks/shs6x+tnvm274Oisw+u1SrOpJ3CwOlBDmtHiv7ieHJ0IKpEP/dYY0kV?= =?us-ascii?Q?cZUeTfUbUCnFizprgfVzE7MtbyfkBW5zwYSfwxC0HdgPzV5KVl9g+yM0uKxy?= =?us-ascii?Q?+RYgfC+PcMEaCJxhMoofFGhA9shMND/a4MrqSXCKrSSbiXH1ol+fpPSIkz0R?= =?us-ascii?Q?Pmn4f/cA6rXTvCgl6ddVhbTHvjXCvPAu76HH7sa6q9TKBOaP9RwWtNjUtbkY?= =?us-ascii?Q?E2v9HBI=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?B9IX8oTw6tVRTbyuXg4EDaIdECW+4IW75cOehRBXheDU4dyiYBVAUwlxEgKb?= =?us-ascii?Q?phdAuKeLCpR0/qVYUxzbC3bcU/QJfP47f4NDwdsPfTjTSt3isJDOWEppw9uE?= =?us-ascii?Q?lyRIR9xbT0kQWS9uqcTgVmDFMcZ/7w1IbbvUHSE4BOdi+KiZGOjesCjB1/x8?= =?us-ascii?Q?P3/PkXlATp5PkMC65iiDgQI6o31U/HVn958TjaV1YyxnYlP2E9TfMzMXgiyR?= =?us-ascii?Q?n6X8MyRq4KkdxcApyJ+1E4RW68tq8hqCCZ1ltm3MclQV4nmLZv7Kk6DuyMv2?= =?us-ascii?Q?lBZyFXErjwxKBFle8/iX8+0gZQ7QCCXhkwNjfPebME1Y5cT7+YqywIlp7grr?= =?us-ascii?Q?xRfM63qjmVqc5/kfjmt0ZuEqDzPPDWdLqVpTTncBrwK8Ws0JOKdKR5vUWjmK?= =?us-ascii?Q?ZESJ6ZiXgmtKJvkamM8u8rSdVntX+ysylcLuomd71/kRUj4WL1AG+lPY3WvJ?= =?us-ascii?Q?mEPTKeSOn8P1Ef0A4hUOKu8NM878DI3QK93XpE6dhfK3GP/EXQk9zKq6Zv1b?= =?us-ascii?Q?TQAL4/Ih5XvSydtHc70iCI9t/3YG/bySFB6+2xzLLLcJmWpvfcamofu2vwiX?= =?us-ascii?Q?9GPjm8jm1lVGPH9Pl/Jg/NgMKEq7ALTVyi3U++pL/NCHidZrBw6Y4s4+uugv?= =?us-ascii?Q?0YpJ/n+f3bPFa/NK0DMU8Gc+4Bv+WN6hb3gQyt5kGlU1ce/IUaujAtjB7T8x?= =?us-ascii?Q?bWGNJ2YBHAvgiCu/lNJ1X/mzcBhAVIb0N9xyIOoVlfU/+EzqIqbTBvdJDtAG?= =?us-ascii?Q?I0WXR9xgfkeb3qYkabupk/GR8uCs8JIjWiH6+CoK179nwyY2nc25HphYtS4J?= =?us-ascii?Q?oDYX4NFfcCmBy6RKO0AhVvKSSoi3IfvsmTzO6h2T+4hSsCb3TK0hPznHF2+1?= =?us-ascii?Q?gnCHkLt0VMLw88zN+9Hqy34ZnjTg5RjBL+zwbboRTs2g3F8Qtgj3iC9g/yvS?= =?us-ascii?Q?/Cj8IliVqJOC3ohIUxYHPQKWTqNSVP/pwIj6G9+jz5UGYM4J0977GWWS7wJf?= =?us-ascii?Q?zsNNrNQb/5DaLdwzp/cGsvuMRcFb+NveKhPO5Afa+H0f7euWsKu5peoTND1/?= =?us-ascii?Q?BKdCMffvo8RQMb1HKGQpK6chP7RcSvwhwR97tufLYlBpL+md//MxVus0OZXJ?= =?us-ascii?Q?KnQ8fdRR1AOjBlZlRTPnj5D7h+YEcP5F61/fw+cNPR6AyyE89Mnlv+j5eOaZ?= =?us-ascii?Q?aDi5DOUH9kBUEtcxR8EhD7rSCN0eAZdH15xJ21GvDyDOgxikydbQwbVOfYUH?= =?us-ascii?Q?quLd2n9vhFHdCn+DPV+ECjIb6BlbIMQUTw+zpKSroj24cvTFXW/s7qUr4AeR?= =?us-ascii?Q?a+ItMInhnAWS+HFhCU6jHN6I+wGtTEDKrqBaHcafxlky0DxGJtl/bXwRS8Ni?= =?us-ascii?Q?pEYpCsj1CJuPFDT7ZRxzQRBt5vunc1Y8tfCtWbgR9Jjw4arGkw/+huShdeGt?= =?us-ascii?Q?nzo5Tnu5TONBPoS1gVQdaEPC9rEcLGFowUbzzPVKRrMQ8jzPFZ60xJc6V50p?= =?us-ascii?Q?PyzyudBTzxw8XRja9+vX5KSGf+Io+jcH1pYFKd5WPDV7n0TAtALgXFtSX6Kb?= =?us-ascii?Q?MJSJLxx6s9eQ5UJ5cUMnZynLxuHG2ac3bKLBTeCF?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 49007c16-0564-4ba5-5a25-08dc91c76c72 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:49.0341 (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: ZmmWHbVuJchHdgNnqBNNFsMJM3GfLRuH5COmcsyhr6qc9Str/+pIZIvaOZGa+opXv1wOvflqlA/be+cRphV33w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- include/linux/mmc/sdio_ids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index 7cddfdac2f57..8446841d62ef 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -115,6 +115,9 @@ #define SDIO_VENDOR_ID_MICROCHIP_WILC 0x0296 #define SDIO_DEVICE_ID_MICROCHIP_WILC1000 0x5347 =20 +#define SDIO_VENDOR_ID_NXP 0x0471 +#define SDIO_DEVICE_ID_NXP_IW61X 0x0205 + #define SDIO_VENDOR_ID_REALTEK 0x024c #define SDIO_DEVICE_ID_REALTEK_RTW8723BS 0xb723 #define SDIO_DEVICE_ID_REALTEK_RTW8821BS 0xb821 --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0272217C7CB; Fri, 21 Jun 2024 07:54:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956497; cv=fail; b=stYZyzb1tPhDLzi3sfWcr/W3nAhrL2WdRB8SFhtZo2/SCA9hHkVTsDLj33mIzW2eff99CexInk4dv3t905rz1hBYBOK004Qa766e/1auKSz+F16j8jLy/gX8LndEQCs5vAuYTPptCqDByQ4EfGmOx9T+gMOtQMcvhcdbBxLJAaA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956497; c=relaxed/simple; bh=OWLLOg9zNviDBy1PpaLIuGUJXKqg+tFm6JSElyxo7sA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Sm8jYKDF3wZBKFlBr8Hesl1oHqDRk4jjrmRW0o8OxMI2WTQj1ODXj2Q/Tdq43sSJkV3j8wShbUHPjXXy+RC0FhNNQSZWdVY9L5W/RyzUHlXFqgDamCwgaAlVdgHgDK3b7Nqx9RYcYKHj7zJwuFRxYUvjev9QD10KjRNaLc70640= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=I3Xjr5zp; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="I3Xjr5zp" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gq8Bas/ZE8nxGTdxWNotva0Rfck3EjLaLFvZzv3vRgDaHyvSlEfUbir6u99jZZB93M/Vv5KvbKbgYLoHdAtv6SFPPeJQ9VwKdv8nhuKUmV2ld+Fd0ZactJUyp+r2Sqyifsb/DiYZTGTU0NXqOAobGGxZvodiZ85gB2JwcXJs3PGrS++h9l8afGPF2pc47BHv2i70Lh/EmV6CEuZ0enXESWXWms+rOPv7VAjqS3H/xHbZR4+F7/JeCRsDVlJoiYnz9x/+7jD0m13jHZBpBTl3E3hrJNAhLdEZfrpudAKzHyz/XFKv/10VJJ7pAv5IRFrtminpoo902MobBXQ7OUGbBA== 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=PuuA7mCk2j/GPV0d3IBmmbNL0aQrroJhtLXnB92XVno=; b=ZMz2PCQLo9QNusTaWeJ1FnREAhg+a64jmuaoWEllT7QWvG6c8hl+Oy0Euo73zoiPiaWlr4fCDQjpjFIjuRcAyzf4lQ+xYYDiTukbme6bYsP4yKfKabPq9aEfGWD5XxXFZpx/XhjQcZdk7C2ldRqKqmkr0HuAwx72XueD9muWCVoC7U961paCQuf/yJX3eWxh0BysExk+9Y5SUm7VvCcdpwPQdIqpz98ZCcWSvU/hkUE8zMwAKayGp86AyF5I7ZfvwycE8iTBtX4qp64m+a5+Y90/1bohcIQIh9y7DliplzcmVvQH8gGKOA0vxV0bCveAq9bPoe1239yBIspFfGoDlA== 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=PuuA7mCk2j/GPV0d3IBmmbNL0aQrroJhtLXnB92XVno=; b=I3Xjr5zpA2oI6f6SqC8atU9ppP4oPQ2r6uylDGVfXdsz2oJSk3YXqfp4C46gTYQKoqPZGdspt/Fty3Xe3rmKVMDtBJxhC6H50qTtl7dvNjowZd/mDkJqQWtxRI/grcDEhJLum2DlmJiBSPrq7pH0kroY/4rhEDD/SO+k4xiWr6I= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:52 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:52 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 42/43] wifi: nxpwifi: add Makefile and Kconfig files for nxpwifi compilation Date: Fri, 21 Jun 2024 15:52:07 +0800 Message-Id: <20240621075208.513497-43-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 4c60d90d-022c-4074-cd82-08dc91c76e5f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?M7QPBl9ThJ3D1H+8Ru3OFFkPTBhJRLgcOaOP8VC7etVyPIZ1f/tL9lmUvO8m?= =?us-ascii?Q?gyWXO8QX4cmZNzvMn7NdeMBdC3ZMlqgWBrcx/BzcLHl5wglWBMQaDmMbyFo+?= =?us-ascii?Q?HEkeIJP7NmaiOI8TWMyeDypdMquHj0+gdLIhcd/r0eTUGC9iCUG0Mwm8C7Ed?= =?us-ascii?Q?BG3zoq+HQWTqnRM3GP/pLZ0MT29qiN7j4umlxfwJDQgFanEs4jEEH7xYM47N?= =?us-ascii?Q?PfiknrRE6SfQckT3ZDO8y9YDvr0Y8Y636Jl6kEcVpKEBq/OeJ6gr+1IR/1qE?= =?us-ascii?Q?WkQm40Ko80oIVMYOIZUvKyphJZ59+bbVQhUggKyD5UjHLlXnSf3KSQOXHjZZ?= =?us-ascii?Q?SM+wPdXhl2Ikba0IBMhVagtekajVOttVRV09lz25/hJoKcK+WQlWZGEw8HJt?= =?us-ascii?Q?ql9pXQoGE31Gx1USm0IVFH0pUJTb6mlw0hf1Z4l9eGMYLjA6pH0njpKaj+H7?= =?us-ascii?Q?Mbou4CEaandPWCeIR4F5nWGfm3MeA7gLzqPwAIDsh5FRzKhRdwDVsCFL1kow?= =?us-ascii?Q?tr4R31P741fl/91El3sauYgXJrqM5FTCClllX6Ul36pte1pj4tmSg1qYPqfw?= =?us-ascii?Q?4FczWIiGawRdfGMsIRKfDX0yqWxvrzJrTPp9KcMbhI8l3hyTnhddstw1WBM3?= =?us-ascii?Q?ACreQ8cR9PMlPTldLdQnk6ON6a/6QAA/SUaXDUBFRHdBEpR7PH2JXIPxzJXx?= =?us-ascii?Q?JQtPT4ZO0NKL1Q03uxCZ/90MZg4NCNbmavF7V20ff04+qBzDAfXLcEXIEvb8?= =?us-ascii?Q?/1aolvroxMSZzYF/h6RY+xOJWthBIuBgPlyEoMWvxFfR5rwu0B9EWFhqImD6?= =?us-ascii?Q?Ii6IjKO2uBiLCxM54ehGPVOd+y59byoDAmykG+J3SFntOK+vIU3PxT735LOV?= =?us-ascii?Q?dPLy6oGoHA/MardkzpKo3OvKG8QRHYvNUxxt10PwBoDeg0FAHdlZG61RFVtt?= =?us-ascii?Q?NM/1HZuH7ixm5X0CE4QTZjQyt7hKIgFp+HeaV3L+rva/YQ5FDqGva+od9udo?= =?us-ascii?Q?0PgpkOR+7ttN8g8qwiZlgocfWoueVHOisPpb8iuW1E65S1lOWuYtej+Ap+FP?= =?us-ascii?Q?Cr18CFWOuKahxe4NZkVlBwK6kzGLSfaLrL+oY8llJEEqXwRGMSJUq5MhtScB?= =?us-ascii?Q?ZiFLj3b3fXtXaWfCxqcQDTaMjW9MMze8OEToBeA5FiQkQEKgo/6MH1iDF8R+?= =?us-ascii?Q?IjBKxH3Bn6o8Zp/FOTpSg+XOUwXxQm8q9cZbLxBGG9VK5FPpJ7EwUKk/gEq/?= =?us-ascii?Q?2d7bkvxG59P6lANCPHaqMI8HnzllO05oKSMa3w+q51V/+GSK/+3tlJUnSou8?= =?us-ascii?Q?q3VA40tWENDEZOtxNgNboAHza8YoxOaSM9bWE92Znab2JdZUqAjPQa4LEkZR?= =?us-ascii?Q?IKRITIU=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?0pU4LyDblX+uZ66zuMv/6GRV1Oo+04PCdTV4R9gQEqrSj06Caf4p0u3w8qaE?= =?us-ascii?Q?HdFF+r40CTTADj67FrBfyUHsoFJyr+BrtbqWIQw4h5tWUwF5czSYcoeKRtKw?= =?us-ascii?Q?t3or/GTxDIvrjyrYs7Qp3HOQAeP2qUWRHscHKaraVkbXDBpSXBGZheZBDB2C?= =?us-ascii?Q?VgUPMgHdFdKHApYtNub3jjvLZOFreA2XwYHTpdmaOTIscwxZQsDIVPH46uOF?= =?us-ascii?Q?PHLy3UzWDcjpjHy4Lja0c2kGgrEBt00O5tTEFmIQEY9KzkQcbewzSGDQ0sKh?= =?us-ascii?Q?UbxfK6qS/PTbARVCBUQ+kYGjRVM4ct7DWw15KYLrZoktI9yzgIbZJDF7DD8+?= =?us-ascii?Q?3CVTyifuL8sDM1VgljXP5IOUknucg+B1Tawg1aANF12F8jY1oUjhhOpKf9pY?= =?us-ascii?Q?P4K2ib++bDcFxxGhBaF1NQEpXt4PPJqJKZkfV9HOdJwTw5aoQ416B9ICX/hC?= =?us-ascii?Q?/jP8Eds/ESYYmq8Di+S5DpjOOZRv1rLChnwrkVzulXNWNI4OzPisYINytVyg?= =?us-ascii?Q?N4JeTwLVOaGSYooSDZ7dwth+mnDAJAB7WKOx/9vlEPHZZsBMtWfd8kr0JMv8?= =?us-ascii?Q?8CzH2SWQUehWO9O/vFZCqR7pxT0+v/0N4pE6W1PGGbdvFwbVm2LWOgM61aMb?= =?us-ascii?Q?zkO9YW6uMwWTIxtHbRCGVUzhDHDq36xlqCdBpOXlS7ZCzdN0ET6xcvyT9cYK?= =?us-ascii?Q?ivhkpz+Ht5VSe0HydDUi7B/ZGeP+Jg0DEd/3510OZUX61FOMmtTC6tmRYGps?= =?us-ascii?Q?WQhMT8tVRQrvOmDExPWm2bdQCFCKcaMIjwyFkJSNnnvfVN5vyiw39EHzLNe1?= =?us-ascii?Q?eRL21FCJVaNk/rYWZOssswZVDwBwGZtlN7MOzkSUYi6fMbczvZrYslXsiH5T?= =?us-ascii?Q?29frKkYF+TVoXzXuvDD+k0ftzo9cDENnTzE3ZRw19pWSaIcI0feKQHQ1E1Af?= =?us-ascii?Q?e8nKpBxMq+XOpUdT5R5ePUuyYYyXgiQNCav+6QkVaFSE7Iz6+YSbf19vs3TF?= =?us-ascii?Q?RjMkUQl6TzZTN2eO6Cm7NIbrYFdxoxE4Plq5DBR1Xpj74kT83afsoP+563hZ?= =?us-ascii?Q?DjJ/xUIhwQwd+U1E9uBdvZwoLqekh4s4+/UR+CXyc2Dqh8yXqYZGokjr0slC?= =?us-ascii?Q?K7+OtEdc3Ddx9IFQYsPQtZsr8JR+zpIidlG+FPhHMuEFkLOV8eEYzfWzKDfv?= =?us-ascii?Q?r7/CQ84Ogk+95t2+DvZ5z7Jsy8U2qyQ2Ppm+umQGIHtowaTQb/xVr70hlzEf?= =?us-ascii?Q?UH69KjZExQXbt4vxuFb08ilDf4caxA8lg8cqKs6BoY8z3kYmDPmp40c74tiz?= =?us-ascii?Q?4nCIRr08W3vzIgqK5VxGVVK5pE+kXtIeqK0SUzvQ3iASR8Wol36iSX816HEK?= =?us-ascii?Q?QoPPsL6fo4z7kcsOjf0CZrNMmKESw88kvEaocK6row8I33A/CGBr96o6WKNG?= =?us-ascii?Q?DZ9qEu3ttJA/aqCFfYYfkOGPwZ+deFxkSLKwyXYKA6lOsi6sCHsN55BmfwGF?= =?us-ascii?Q?Gq0yaV81gBziFEAlhRDoLz4ZiT0oXAZJOCpWJ0Ci4H0dX9Soo/1suU7rN1rr?= =?us-ascii?Q?YGeytvR2ljoqTiVrdmMB/xhnejI/K3n7ykhzsBB8?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4c60d90d-022c-4074-cd82-08dc91c76e5f X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:51.9330 (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: HY8MAbM9Yvcubvk6yShLbfgHdrvi8U6lka6Q1QQ19c1iK5EsrYCNR+Im6N/7/0EzJ1Qdxgg2WOIItY3Ntvj9dg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 1 + drivers/net/wireless/nxp/Kconfig | 17 ++++++++++ drivers/net/wireless/nxp/Makefile | 3 ++ drivers/net/wireless/nxp/nxpwifi/Kconfig | 22 +++++++++++++ drivers/net/wireless/nxp/nxpwifi/Makefile | 38 +++++++++++++++++++++++ 6 files changed, 82 insertions(+) create mode 100644 drivers/net/wireless/nxp/Kconfig create mode 100644 drivers/net/wireless/nxp/Makefile create mode 100644 drivers/net/wireless/nxp/nxpwifi/Kconfig create mode 100644 drivers/net/wireless/nxp/nxpwifi/Makefile diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index c6599594dc99..4d7b81182925 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -27,6 +27,7 @@ source "drivers/net/wireless/intersil/Kconfig" source "drivers/net/wireless/marvell/Kconfig" source "drivers/net/wireless/mediatek/Kconfig" source "drivers/net/wireless/microchip/Kconfig" +source "drivers/net/wireless/nxp/Kconfig" source "drivers/net/wireless/purelifi/Kconfig" source "drivers/net/wireless/ralink/Kconfig" source "drivers/net/wireless/realtek/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index e1c4141c6004..0c6b3cc719db 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_WLAN_VENDOR_INTERSIL) +=3D intersil/ obj-$(CONFIG_WLAN_VENDOR_MARVELL) +=3D marvell/ obj-$(CONFIG_WLAN_VENDOR_MEDIATEK) +=3D mediatek/ obj-$(CONFIG_WLAN_VENDOR_MICROCHIP) +=3D microchip/ +obj-$(CONFIG_WLAN_VENDOR_NXP) +=3D nxp/ obj-$(CONFIG_WLAN_VENDOR_PURELIFI) +=3D purelifi/ obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) +=3D quantenna/ obj-$(CONFIG_WLAN_VENDOR_RALINK) +=3D ralink/ diff --git a/drivers/net/wireless/nxp/Kconfig b/drivers/net/wireless/nxp/Kc= onfig new file mode 100644 index 000000000000..68b32d4536e5 --- /dev/null +++ b/drivers/net/wireless/nxp/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +config WLAN_VENDOR_NXP + bool "NXP devices" + default y + help + If you have a wireless card belonging to this class, say Y. + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all the + questions about these cards. If you say Y, you will be asked for + your specific card in the following questions. + +if WLAN_VENDOR_NXP + +source "drivers/net/wireless/nxp/nxpwifi/Kconfig" + +endif # WLAN_VENDOR_NXP diff --git a/drivers/net/wireless/nxp/Makefile b/drivers/net/wireless/nxp/M= akefile new file mode 100644 index 000000000000..27b41a0afdd2 --- /dev/null +++ b/drivers/net/wireless/nxp/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_NXPWIFI) +=3D nxpwifi/ diff --git a/drivers/net/wireless/nxp/nxpwifi/Kconfig b/drivers/net/wireles= s/nxp/nxpwifi/Kconfig new file mode 100644 index 000000000000..3637068574b8 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/Kconfig @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-only +config NXPWIFI + tristate "NXP WiFi Driver" + depends on CFG80211 + help + This adds support for wireless adapters based on NXP + 802.11n/ac chipsets. + + If you choose to build it as a module, it will be called + nxpwifi. + +config NXPWIFI_SDIO + tristate "NXP WiFi Driver for IW61x" + depends on NXPWIFI && MMC + select FW_LOADER + select WANT_DEV_COREDUMP + help + This adds support for wireless adapters based on NXP + IW61x interface. + + If you choose to build it as a module, it will be called + nxpwifi_sdio. diff --git a/drivers/net/wireless/nxp/nxpwifi/Makefile b/drivers/net/wirele= ss/nxp/nxpwifi/Makefile new file mode 100644 index 000000000000..a9e5a528324b --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/Makefile @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright 2011-2020 NXP +# + + +nxpwifi-y +=3D main.o +nxpwifi-y +=3D init.o +nxpwifi-y +=3D cfp.o +nxpwifi-y +=3D cmdevt.o +nxpwifi-y +=3D util.o +nxpwifi-y +=3D txrx.o +nxpwifi-y +=3D wmm.o +nxpwifi-y +=3D 11n.o +nxpwifi-y +=3D 11ac.o +nxpwifi-y +=3D 11n_aggr.o +nxpwifi-y +=3D 11n_rxreorder.o +nxpwifi-y +=3D scan.o +nxpwifi-y +=3D join.o +nxpwifi-y +=3D sta_ioctl.o +nxpwifi-y +=3D sta_cmd.o +nxpwifi-y +=3D uap_cmd.o +nxpwifi-y +=3D ie.o +nxpwifi-y +=3D sta_event.o +nxpwifi-y +=3D uap_event.o +nxpwifi-y +=3D sta_tx.o +nxpwifi-y +=3D sta_rx.o +nxpwifi-y +=3D uap_txrx.o +nxpwifi-y +=3D cfg80211.o +nxpwifi-y +=3D ethtool.o +nxpwifi-y +=3D 11h.o +nxpwifi-$(CONFIG_DEBUG_FS) +=3D debugfs.o +obj-$(CONFIG_NXPWIFI) +=3D nxpwifi.o + +nxpwifi_sdio-y +=3D sdio.o +obj-$(CONFIG_NXPWIFI_SDIO) +=3D nxpwifi_sdio.o + +ccflags-y +=3D -D__CHECK_ENDIAN --=20 2.34.1 From nobody Tue Dec 16 19:40:03 2025 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2050.outbound.protection.outlook.com [40.107.21.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D7E517C9FA; Fri, 21 Jun 2024 07:54:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.21.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956499; cv=fail; b=KzFvMI2VAKmGVfe2FJ4dHFIDWhV2f8N+KHulNbWJsGegEM+5W29EgP3jxrVXem/qWUdPByUsLHPGfYRze5IfaR817l4QhOAQIws2lBcZIzBMwIXWDfl07N4LUAed83DN36FXhhDC5Git45mFFaVEuHprVIOsZ1kO2d8xDtXTyAc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718956499; c=relaxed/simple; bh=87vnGicA1bMCdwQ2qCbwfvXbwJghdo6PWPqoN0A3jx4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=O6sGQxszZ9ywxKz2FQNGgpLa0rfDVZ0J6+5qFSkiZ0HglM7cJxiMevXr26Z/8h+Rixns+p9Y+fGwCFHzKK6kEDSsnmLxL/JAJQMzO69ozMC8j5ZEMbiGtP0HpqvGSovvZfti0HjMp19bPXYYOX0/ZKwbLrgpnapGQKKc9NrU1MM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com; spf=pass smtp.mailfrom=nxp.com; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b=BQx62HD6; arc=fail smtp.client-ip=40.107.21.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nxp.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=nxp.com header.i=@nxp.com header.b="BQx62HD6" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=C6M6FloMIX0kBjjhpQTYXymCSC7KkLtqOhIq3hk/IEY7RNfC19eHN5OFXKESBPu00ez0eBbpRZLfzcyTPv2zIJf5sQsMcY9j/a74DuzVo0PT/8Zt7S79UDdmdBqg8MSJxBnfti1kmgx3ElATN+DNB6LA36nlNPXXxJjcOnp+YrGttUrUE1L78Sio/ajG6F6P1UTgCPDIPGrjTfONz4a1hTyXUDgWV5kFEBr5HTDj2MAitBI89IyqP2gGX7sMDEz0KfGhS9pXzXiRvz9GrBasxyH6lJVcGEgymRIQZ2E7jp+88yBMif//w6B8fnDvdNmZcZob2GUVwsndA5Hzemv3gg== 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=XGyOOhSIruRZcNnNHvocxfzf8w9E1T0P16IvnfcoeEQ=; b=MuTnsSZ91pKUqicqfFIMyne/OfrrggYi29F6R7SyK51GUcevdvy+Mn8uC3c80D0Segc+A89A8R5z987zViwxNXEjmZfw5nyM/CRekby7QCmpD8TiF/lnvv+xclH3Psc0IiNVlJ7VFwS8Luyw1mEmUPLk6jQAFMORi8H/SbuY6QKnN7bAeTQySCgDv4KuHdh92JKvcC1G3J6qU5OKunkZcBff+iT7Yx48fAD9AphlqGe5figsTDAjLt7Zlcj9dh4zZhHY5CHmuhu+6aexnbrAgtYbyEz3R8Xk/pYpv2wY/1bRiXSdOjW8ztqCZbykEzh18KVocgtBZ0qu+5/duP94lA== 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=XGyOOhSIruRZcNnNHvocxfzf8w9E1T0P16IvnfcoeEQ=; b=BQx62HD6uF7CofVWNIEkwxwo10xUdmsBDDsva+mAvW323nuaYk7YDN1XJUnTUjnC3vi3FZvLg65lwPe0b7TfISeBS5dgq3v4ROVWPjJBqgLy0P1S0sUgIahpZmeBZ810CHta0+1Rja54I26mxkuIoVPVAu8aA4vNU+jFWoxI7mg= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) by VI0PR04MB10464.eurprd04.prod.outlook.com (2603:10a6:800:218::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.21; Fri, 21 Jun 2024 07:54:54 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%4]) with mapi id 15.20.7677.030; Fri, 21 Jun 2024 07:54:54 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, briannorris@chromium.org, kvalo@kernel.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH 43/43] wifi: nxpwifi: add nxpwifi related information to MAINTAINERS Date: Fri, 21 Jun 2024 15:52:08 +0800 Message-Id: <20240621075208.513497-44-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240621075208.513497-1-yu-hao.lin@nxp.com> References: <20240621075208.513497-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: AM0PR02CA0115.eurprd02.prod.outlook.com (2603:10a6:20b:28c::12) To PA4PR04MB9638.eurprd04.prod.outlook.com (2603:10a6:102:273::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PA4PR04MB9638:EE_|VI0PR04MB10464:EE_ X-MS-Office365-Filtering-Correlation-Id: 6bb4b048-c878-4949-7d34-08dc91c7701c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230037|1800799021|366013|376011|52116011|38350700011; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?9JzF7FKKoxrgVos2LB8jHGKI47qeFrAks8/mn5DIOx/UoD89qrPWeSMYRizp?= =?us-ascii?Q?ju49spHOgYd77z+Ruvr0f/aQ7wX6EbQPLUWILEGGtPl8ThXKEVpHE5AtJAgt?= =?us-ascii?Q?tXn8RVDKKcHx1gS40Z0kLhxNVkL5MiRjagl4uiiNS2hCSslW05Sjzrs6VCMt?= =?us-ascii?Q?zQVJxA+ah7apeuXEamc9OcOjGudXD9RF7WKm/krMeVT6tXNd4MRepNv9AKYZ?= =?us-ascii?Q?9RCntjXC18OTX6uXkXPb+sXS0apsrCdXpvNQ5dRBMM0E8cA0JahQnMy9KoXU?= =?us-ascii?Q?VWIAcmCfAtEHcGiwqMrRfA4uLW4iHeLNCh0J62+ZHblQfqeroNIHOWkXv/op?= =?us-ascii?Q?Ao5qh9Xp3OljWvC/5g6LA/Ng9/wZDMI2RSG8kxA++8AO1tF8OU34idH2g0cS?= =?us-ascii?Q?o35lEB60tO3hBw6MhKF4P5NO5c50Vqkia6kJhCq+5JsUM0mxduVHxlivj2eu?= =?us-ascii?Q?57Niv/hhREnYw/ryvm7Ykbo/6mU0X+0j2xvNv2XnqjZ3J1B6Li3oXIWMUf0o?= =?us-ascii?Q?5sM5wR5rKMkacPmHFxF+SJQfZ/PdXgjpp3mdlK5AA1c7t7KVrhfit08bUox4?= =?us-ascii?Q?aS0ovXVs+7IrP/P5YiHGvCkva8gMyP2r/2zLeAbeaTW+ANIKQznVmwu4Rfag?= =?us-ascii?Q?0+xwx88HAuZg7SyZhCDyezEUTZcl6i0mXPgstnsCcvMCDGlFb6bqpyqlw+w7?= =?us-ascii?Q?33JU8m1JU77jh+cc/p5jkskw8QE73aNy8mJMbWFHbUTwMu6Rr+/IXixglP0t?= =?us-ascii?Q?cXiLKkdccEiBcYpHIhQjxCnEGJXNZ2M5tdujTIZcdSdjBzh+EzQRtEBh8uvg?= =?us-ascii?Q?m+MoKSYLC5COnKpaGd1YI8iUYEkxz0hNmr1p0DXFNtLGUvF2w0epm90JVzir?= =?us-ascii?Q?FTGS809MpFc7RMaJWWAcBO927RhJuYPc2KnEB0DqG+qD45qvLR+zg60MDwvg?= =?us-ascii?Q?HXx484tbNR5ZVM81a3oG0jRGxG7IV53uGQ3LMKWCCbPTk4ZeQtUDcmArws1G?= =?us-ascii?Q?ybaaQAVXVaiVY+4vQW/OaDUmaNS+sZxGW/jZB6WPvv7INqfbV82EnpcLowIH?= =?us-ascii?Q?YTmuwbTLm70sjs/oEn03nbKrCgBuAr4AME2hfQPb+upaw2Uuw3TVkQK47u1i?= =?us-ascii?Q?SrzOmnRLeLv/QANQzDB2Yh4wBGk0YZ6og2IQa9E5mSO31WDizH+u9kmRtTTD?= =?us-ascii?Q?J5YdvUupZnf+MzMmyL9xIxpr16EC/Ul1y4kszVub+GX6tZNe7KLl49BhTuRu?= =?us-ascii?Q?7A/J2az3SQgEc1v9s7qTrPDYIBZ6Oukz4dI7cNSWbbGuZoYeMpUreLHP6w6i?= =?us-ascii?Q?QBV+LU2rKUAOrRfThviA0NoXHivWNo6g4OSxVry7NQ1EF0h6R+jMcXAcad2C?= =?us-ascii?Q?UT1W8Bk=3D?= 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:(13230037)(1800799021)(366013)(376011)(52116011)(38350700011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Rm7a+ywh8e6/rU9bYw+srYQe49NofQqTqD07EMuUGZfSTH68Qqh9ypTzbtgn?= =?us-ascii?Q?AS2dB0MKWDpbZ5QTP1q2osuPnBZpO7NJ5JxnRaN/CAvmiIExCgMwkQIMItXc?= =?us-ascii?Q?jqYTvrpqjBFU1ZRMUzCKBLXtLXww5xaV5yTsA1x3u59r5kaj9h3an2yhD8lL?= =?us-ascii?Q?clEnCOk9XIlb42LVImELQCvhY9hvZhS+bEv2YElDE/oNNFPkYkjYlWBJsM2D?= =?us-ascii?Q?y7GnwQkdvVqL35qp9+0TdT19y3JNEZIiYG4ZDj7d7WM25vHjz0cv6k1J3Utb?= =?us-ascii?Q?I74DmF7f33LueortxySqr0DW1hxYzL6PzJpWJg9ZvfiB0dYq3ARq8uUDvYs9?= =?us-ascii?Q?5QdlfM9I/Ufzj/A7YxDP46lRaze8lNexil4T8XMZHsVFeKTHnlQK/acivEnb?= =?us-ascii?Q?De208cZjMVjTHkCPu7Oc70mSEooErq6DkocIZ5CFj/RTzaTmx+OZ3BIXBNwb?= =?us-ascii?Q?nLIIDl8ROKl/Jr8K/QVn0hVCchSRP+gmp6jBUzD+Ke/fHMGOwGPazMM/3Msi?= =?us-ascii?Q?zoQqqtlgWHW23ZIolFz83Fy3JhkTFoDnTxWRx+Cx8VCIP2y/EHrIGAaehLa7?= =?us-ascii?Q?qzMcyl0K/GWzc5iP4TVI/8yfiM/awYY4T4xdd+cLiEpqdDJ+dmrSFE9BX0QG?= =?us-ascii?Q?XSQO+WRLI9OrGObMikOCTsDVIXbWm2tL62qhxeMMyemLEtjqbO63PArMCsmd?= =?us-ascii?Q?0bI/fkoxEMqtLW/H+p0MNmIdvVa8A8Yl2PJIYGbSBSbBxp3Jy1lwLxOCtdlp?= =?us-ascii?Q?XSNBW9a9i3+HUSPSeos+5Vk3X89lNmGgxYYSmqQKX7ZGPK397vJUUM3pHVYo?= =?us-ascii?Q?bTCBVIM45OBnAEL3u9PCrI/S5RtFN7Imt3KXMjq6JcuB/lh6PS7sTkYORFIo?= =?us-ascii?Q?piQBx94PwUWXGSvX34CWa2snHgRf0A/GZ7R+nBP5JZ0JR2vxofe5eJ0RJrFd?= =?us-ascii?Q?VZRiHCSC+poJmhMlpjd2IgxZa83q8BOrQXiKEPp32CJL1Z38DZ15zMy25KzS?= =?us-ascii?Q?F3/oQEm2CShiWTe1YMo1Q0zqjxx/xStMgDSHSJpmj6fGxf0rWkBxBy2hDHUI?= =?us-ascii?Q?9pMgBrvn9OpZNAFopmr+2U+NM0HLXltuTUkbjBWhF6ivUgvpGjrmggFItdsY?= =?us-ascii?Q?22q5t17BwFQYb9neHXH2KGIjnG2QjTVjZu53FP6h/FtUi/j0xe13vr8Whi0S?= =?us-ascii?Q?kMa+ysyju3+Z99simi+SJ2rxLNPMi8Oe1DrcLqifaWGIP5/osCHS8tHYXV6Q?= =?us-ascii?Q?tAsgo909w7WCOiRxF1YQejYOiJY96uKVYwjQ55yD2mC5QF7C9y4li3LkLSpE?= =?us-ascii?Q?aVS666KdMDy0tDAD7q0TstLonLCNWAqPbXxi6P9TxYMQxdPOV/zn17yIqVpP?= =?us-ascii?Q?MgIm6nsfW6KaGfonQHTw1o5N/e0vKfBFM3+k68P3SHKak/pvb6SHQDDKKdeY?= =?us-ascii?Q?ehjCcTo/FCaIZQ4i3vFfC7wNs3D2bbX4VtiIglLuVntA92QJ8dE0Nex+f779?= =?us-ascii?Q?PTn21q43N2jkLuWnRQbX8VkG+xzYqkryR66RKSONdyUzo9MvsGjaNwzKagBz?= =?us-ascii?Q?BiydTWkI5KgBwdTznNpS5oIJKudB6K0mtfbTYpMo?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6bb4b048-c878-4949-7d34-08dc91c7701c X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2024 07:54:54.9094 (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: 4rxm8RMKg68tYg0QH4iPkuM1D4Ong7GH2M0plDuXEjAZUmborl3b1E9s08MqlR25MnDiMP3MeGJNqZP3Nx12Hg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR04MB10464 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Lin --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 92ad1d545690..847051340c91 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16178,6 +16178,13 @@ F: Documentation/devicetree/bindings/clock/imx* F: drivers/clk/imx/ F: include/dt-bindings/clock/imx* =20 +NXP NXPWIFI WIRELESS DRIVER +M: David Lin +R: Pete Hsieh +L: linux-wireless@vger.kernel.org +S: Maintained +F: drivers/net/wireless/nxp/nxpwifi + NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER M: Jagan Teki S: Maintained --=20 2.34.1