From nobody Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011004.outbound.protection.outlook.com [52.101.70.4]) (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 ACF54190686; Fri, 9 Aug 2024 09:45:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.4 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196760; cv=fail; b=FK3mip7XHB2/fSD32Hjf7EWws+DoMWqKTW1KfxanWrKhwuLW+bys5ogYPJlxuo9sCrT+LcigqtFhelW5Np5AGIOGeGVgc+WchaJuvEzPgMz8bJFYA7SpMFpad9XeBkZczns16nsfOoOYDDR/+m/kjDNWwWIPn2p/w5vvyri6vYg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196760; c=relaxed/simple; bh=9E2BYEfAdC67ORWe04zygWegf4t9949M8HjL+v3qQQs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=WjrDvrorSbbgz9jjJeIgIlNVja2EJxk05b+P6t3RNlfuFXby/Q3ntqEO709/tdmUuohi/X18J860Zt9QrEYEuzviBaoQGoeKCryiMCGgxd56r0amDQrE+nlo3rVfbDzH0eNcibodrtikwg1PRODWfaSqCgB9ZsvvzZnFd3AjrJ4= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=h6ztb8Om; arc=fail smtp.client-ip=52.101.70.4 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="h6ztb8Om" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=bLJDIrISAl+IoN0D/n3ppgYZpWrpI/8VvychYJDzM0DazpWVFSf5xVtpbSAZeAiV7DDEwPfxbcvmckgkEoBmzBSlceBP8/K7+5TXRkF8Gu2v4tEG+T3H6gIr7bjgTmMXPLaOKABLcwSuJ0ZRsN86VjB883d1Lak3/YP4+iHTl06xB0XILpn9TOfAYjLuFRkbatYLnoDc4PFeh4qNn6TWKqOUxgI/7y9Spi+3vbubS/tpqUnu+hfhnZaBU840Iicp0BSd/YRYamL7JLzhmbr5oFYn6bp3b6HsL+sT0bmd6UIk+rzrWC2NbUdS3Ca/U7TlEOJvQ+YSmIBEyse92poevw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=s+uZVJH/d2Oae4ido2ZVWKaRgeVGcwCwV3uhdGhhGKA=; b=HqqwvmIIUtiBnmkvvWkWVNo8PnMKP53UTgY61A1bgV+JBqR8jVoenwl/1tiOlXtREijtvI/WRkonq35KwHGra/Zit42ySL0VfCSoKtwYqZ8SBQH66nMj2Ktv3CD2U7Ht5t0jKedzaR/KHas28MWV+jhOm1HbCcPfBcE2Lrn+ANAlNnjqlT0ubSE8nbfL69LgL6zSSsV9wR7G5V801ExBIk9U42tXme9Rtujk9TbVX9/Rs1Sn5OdR/9xa0m4enc+uqdY2b+cLHMRTqR/76Cuk/Hpcb62DQKB3/X503POvd7Q0xYRCTgVAibBmrZE/9Zx+Q5Tsz/8TornqAObtdeAKqw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=s+uZVJH/d2Oae4ido2ZVWKaRgeVGcwCwV3uhdGhhGKA=; b=h6ztb8Om0zbofPsBPStiDw9J5xgDoxvZiG6MwxrRq+wwMzRs93apDXwavda0OtXY/Nda6b2Er02u+xtszePQxrZBzFJyi19Q3RZqrfh4izhcM+4vI9HMZiNVnhncP59W58WKQ5+GB73MpZMX3iXLlTCOeGmdd7G7fdh0FBCY+98nq21cibKhxgMD4817b5bazn9DmbdJ1hk84tTfzYz4/NYrNYsn1UP+c+R61QrX5eCSVPY7zwl6uvaBrdR2Q/y6MXzvw3TZbIglNllDQF0PdretHxXTeIFLdWLpa2BijBpSzbyWCrNx0kZpUbfWBWBDX5OyM0VzcB1loE5vm05+GA== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:45:53 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:45:53 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 01/43] wifi: nxpwifi: add 11ac.c Date: Fri, 9 Aug 2024 17:44:51 +0800 Message-Id: <20240809094533.1660-2-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 01753177-e374-4cf0-2a00-08dcb8580f39 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?xWW0ShU3mmPEkM4NFSnLH/2Vmt432U8UagqUeaARQeWEq1hnmvfNDlTUDzyk?= =?us-ascii?Q?kK++RAsyDqtiKk34AjgZ5JeROOhirUBivxE62Zw97CKnGa80ZV1myz7H90e5?= =?us-ascii?Q?gsTNXhQS/VEYvdT+WI0zTTIZC68bLpNgSlxKbYh0Khvcms+q10IkT+/ZiX30?= =?us-ascii?Q?bBQxtyxDfqgeMQhS1QOsfAURlSQVqKgyFH2S8i2wfobsUpECR8CBQqxrqJD0?= =?us-ascii?Q?28UoC+KAkPazD9+XYccN7oE89H2gRFMDhv+rEEj88kEbh9g4Yxt2ZvgXS3si?= =?us-ascii?Q?EJVLthTvgkdd3IaAuIaJQQoOGMUCX/s645A6RHzJrJKKeKsmrOUo8WmaB3Lr?= =?us-ascii?Q?kMbtQVRjRkSNKH2Fcc7iaAQ3tQoxxToA5aKgfO4y/WPzTBHMJzAp1900g0xW?= =?us-ascii?Q?/EHKj4JlUI1+FHLWrwapmIqN/6vvhbSVuIRABoo/tDXjc0Qb/LwXVmZWD+7S?= =?us-ascii?Q?SOEFsizzyHhIgOqwDIzU4K7Q5wl2u0ubwl6+q9E30H3N5dURu6mlQfiQxRwF?= =?us-ascii?Q?on2v7q0mHY/L86PqqojD/KwHi17g2JONErIQonrElNBbd/ukT0JYYDfw5SLl?= =?us-ascii?Q?Xp2tX2TTydb4ZMp9s5xOlB2KnshkHTIL0ahb6kj40KZxMU2lkg9XZv8wFwrH?= =?us-ascii?Q?8VIoA3NemaNV9o/sZ3WFmHinty4BIypFiQ/72wWFGtGky6Fg98zStniv4qg7?= =?us-ascii?Q?YIfjp/97lQOtr7L3GME3EjS8hp/18Tq3yZgEmXzpoTnXz77hDj7yse9lrR4p?= =?us-ascii?Q?ICk0mb2nUo7w8xy8RuX/UZqLW+yg6VFpqcW/T83jhmHX8pxR6RfipH5YJCSR?= =?us-ascii?Q?2BXuaYoKYna+3pjMloXPpgsnngXWi9lAxodX573eTFdQM0JPNGi8MqWpMMZn?= =?us-ascii?Q?oWBlOlOElbCW+OVfV/xVOIzKWgd/WY199/UM9AZ49XUh9/2r1Pk8ep4GUnm/?= =?us-ascii?Q?Pne4CRkOtWpFkKC5lYlTVMroqGhmdQ0ri7Lz37aQp2/k9Ua+evzExiigCFHw?= =?us-ascii?Q?PLJSBW6BoNRkDP+s6ClFGigb+C5tJa+uG95qoJ7PuxDWhoWrgDnTVwEfDtQf?= =?us-ascii?Q?XZcLiXz6IhPaPth0okLFz5Zz0Ifo3f/mkGVrKGGHrB6iJAJFc54i1r+g/D6C?= =?us-ascii?Q?IItoV6SBXxmkFGDpiA9cV4eVXTSwnpDpdKmYgdFYwPar1inWlTGjjuzz1aI8?= =?us-ascii?Q?wIXdfmr1qfv8zSSkQfU1yGcL7g8fIfuA4krqOvgO9XWWo8Uu5JXbfEKT6/dt?= =?us-ascii?Q?jXjrkIYcDU7NEhHrgtJh6oHB6wv7He70tZ7zIVy7+ufQoKOyuR/CJVfZfPvx?= =?us-ascii?Q?rvmaMYb0h57fyGTZL63L1PR76dVlhDvdNOKM8dOTaFRcMg=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?ETFzIwb3k12bpzWFaRV/zkP5864rXe2yjhSW1GfG07xlagEuBb5U3t7Rex5o?= =?us-ascii?Q?IuvfmSGoV3iR+W2JqKgD8UvunRQlkSfvbwcL7szp68LjEzVQ7hmXBdATUZ9O?= =?us-ascii?Q?dV5ezb0PNlbqoKHG4dcA67Ksv+cWFTwsQ40Iy+BBuvQrlROI35OhhjvqblX5?= =?us-ascii?Q?U1OwLEUzz2rIUlUTVb2u8gsttQD0CMBjsUcbfGHbYgB3LKWaHQS+gVQjvlri?= =?us-ascii?Q?7DZSrW6aV7HaqPlI/SfBU3403i7BRBecxFzrEHj85iZw8TBzTr7VwndEzMYO?= =?us-ascii?Q?PX4N4046PZjTbDq0PTWqcqhd56uQJMfxJWhSY4KaP8cvJ3ge74Mo3T5ZlA83?= =?us-ascii?Q?1LKVVAa+aOMdmrFMQlAXq3tf+G4RD4dKru1c8sCRnibcVndTeT+2UMyQixVd?= =?us-ascii?Q?EDBEdYTZDkOFtPeW1CQz0O/0129Aafmp+xhvsyLpQsz2iFh9nk4Jlbp8cvhv?= =?us-ascii?Q?EOClmfSOvWlgcjacj/kuNsTHwSSbv7aN8gVZ/AH74JvGwgXm/CsWijgTZUsM?= =?us-ascii?Q?kgbRp5LZVZWd0EdqM1CiLxUsNfbcJspD5vqRllB5L1s992MOOQoj6sRVIHAY?= =?us-ascii?Q?D9wHiCFrCcFEwFASGTYUvxtOiKAa6u0spvsIH7lWCbmhJC030U6XpvYOStwc?= =?us-ascii?Q?LYjcr6lmiPeEcgAzqHVldAEx4bvyH/DuGUqQTxgBkmlHBptdZdsQoFQzY1wq?= =?us-ascii?Q?ujRmuF0Atda/XxZsHOSLa+s08Y8zVzf8ctb10vteBZpafBd5Yg2vjZs2V9vF?= =?us-ascii?Q?pZDMNLiCOKl81iK/UNPH05dPNwLd4Le9ikSH/rXjHc/M9CbsIv8nF4C9Mdtz?= =?us-ascii?Q?2QFhR3GuTXLGly0MJ4WyPl3szYR5bXJIdGC4Ux9g9cACnJSwksnYOwwKeQy5?= =?us-ascii?Q?NKlp8odPh6UIZAPPHfuZqgixgTH3BFVniOTHbhUUMuS69eX7bXO8fete41qT?= =?us-ascii?Q?x2ACLlOZJjwZA8cCUjJoDT4am5LVg4SJIFvlO4aenWvoQ35Yy6WgtdthvwF9?= =?us-ascii?Q?hLyVh08lRim17GjNzztfWQQSs8aLsSkHBfFbmegUZB4+W/7UXf08/No03lRa?= =?us-ascii?Q?LW2Aw0bjR15SxtSs97jUBTk2uW/leFzSU0ptKzqiSklXCVsOGROtegisUss4?= =?us-ascii?Q?kB7skfqs4W6vsYc1Hzo+Bl4aYnnH94RJX8BVHjTMTq8apr8ZCVo0px/14u8q?= =?us-ascii?Q?y85DAHxVZq2GMueUWfEqNz/b0/n0AFVO7pHLB8euOPHyN2UHPNXBMGbQaqEu?= =?us-ascii?Q?UwN9AZGibAzOA0ZtmEe2vguJEZqUVsGSD6Udut63yybSyv0ZSWqbPedP5Jq7?= =?us-ascii?Q?7x5YBLP6SnI72IzwYDLTRi85eTz1cDzS3x5o/iQMvQuMgInqGuyhgsjJbTfQ?= =?us-ascii?Q?1qI2O90ow+dHIneiodwewPOfDFGYXTn8Zr8gazZ223qRxwRtvsSgQkTIM7Fh?= =?us-ascii?Q?f6L/o4czV0LLMGj2kXRk9Ek+UGfWe44neQnSYefZwPgi0QWQ6yIJR8lsmLo/?= =?us-ascii?Q?QFaVvAwNJuV9GaYqx/amxd6EAaelkjgB1cyz0kRBDHp4EwJlf981QO7bj5Ff?= =?us-ascii?Q?4Y50HzcnwfiwFdF99BZiG6ep2zhZhJrVAQKYc7b/+dcT0kG7ZBu9eyWS5LrC?= =?us-ascii?Q?f1HgcnWy3s00JfwuyKFT2mKwIgTvyiGavpJwTgO8Qlzh?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 01753177-e374-4cf0-2a00-08dcb8580f39 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:45:53.5275 (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: lyzzIMIE6MWjg34lkuij/ovDu4OwUZGxKuRst94zXcCnPBvtufFE3rIGEmCusYnicQjV9+DB+nJ4E5jWvyI4JQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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..514af3b92dd4 --- /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 "cfg.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 Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011004.outbound.protection.outlook.com [52.101.70.4]) (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 5C3D0191F9E; Fri, 9 Aug 2024 09:46:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.4 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196762; cv=fail; b=CIAmyfr4sIkmnJtjFkmx9fXPiJ+lCM90yZLrJ7GhE165NG5PGzfUuwsERycHXUc3VoG9ClaZBz2wI/oVWD1SgnlUcDZ1QeQ5LYBk6Kb6CMP1iXomcyvIYDeiD6LnDkHSP0VvXiWSg+ZmVDzdTPMOsb+Mdn32kXKPdAD+deBiA9o= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196762; c=relaxed/simple; bh=E0s9X8Wne6kBEfKe+YOuimdOpYWMPmKTD97YtRAWrPg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=H2SXg/6AqNqidxM01Wd5UtibPzs6CA5/FJrzJduqGrycsJwbplHNDgTL0RIKFCRwxEkdUJk9BAA4yTrAQSqy8tMqO9Aqmmxm02XZAM+LGY4Z6wzP38Lw+xR+gbyL94oApa0qMqu7qAX8v2P1bjhMbSlkEWpWIiRhFiEbLLc85zI= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=di2PvT7g; arc=fail smtp.client-ip=52.101.70.4 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="di2PvT7g" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=fMwP/Hgqf2ea0+/8NlWZ7o/1FsnVdQr4eISldNDBG9tAhZEM7sMMuC9SXdsuk/3tsKu93WVwp9RCzR+6l85rr/XpLwXtSqo/jZ3OTo6nCXzG8S8Ro9fJhTVn83XKZ4xBsw9EScluV4FlOrRXj8PSJgL1f+jptySfLgY6BkwfNHiyh04KJzyBv5p9dD2qgN4BugKq9PcJlLP05zjxyGiRWKCQ34bd805iSpS8zp6Gcwc6C/4twYmsJkwUWwk8S7zttt+OI4NoqWU0WX2tC12ztXa1NoVQsVbuEN+hBCHHs9kMhc0dGfyXXexHLmhWRrHReLOGF6RI0CiLlRg4EOFSdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=IkabV74wYLnFDDb0iIkfEcSeLsp3BNYusGNRq5Q+q4Y=; b=dmGx783JyIesGxnEcehaC7GY97vlxdHYbQ/ipH9gIz04+3jfEPmqCeQJYC98s3H1IPQGWRcRFoRbxiPKYJ0Moil1btudjjxK/ZotJEYeWRnZsa+QaY9nsLpf7Ks8O4PalyQkQUc0A+Xr21R2YXSSnMZsjOJjzNmLPe59UOsmpSzfSwUWHOt+8fxVLJJJkrKHPkFSU3MQDqJCXgjeE9Z6U6V05uip2qK8uWvYOovsE/GNxFoD/pA0mcQm0TkkL3nXLMvEwYlQaB/4dCs1AKvd2gEZvGpWgxbuew6cNagTm5tynowwQot9RKbv0g8mqO3ZWOmy7VZAYaIS80JbFqSTHg== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IkabV74wYLnFDDb0iIkfEcSeLsp3BNYusGNRq5Q+q4Y=; b=di2PvT7gZugnX5lyaTTXQgZHU99mkRgCkDNIlwSkGiSn+pBEy/y2YKOXfkmU0Bljs/P12hb9RK733abyUhhJItNpk802S5fwGPX76PhTA3bMUlE4dDKlU1BbXdmcgMR6ltYYYRH7tg4lWEU7ZQs7JZwQ6k522rJOjEzl8jH4+woSuZdH3zM8gR9AA4JtWlS1+m5WIO+XZ/aggiq47fmf+LLQbPIWLgO0QEvwLaDno/c10INI6RBxmEkrEpFlUiCbxG7SwYyTr4dX2rWG0hl0Olie9q9uO1mWySh/+ItJ1ORGYkRN2hqy3t5St9OQYKYFdr8+qnqx5oTOhRRmjVyTLw== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:45:57 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:45:56 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 02/43] wifi: nxpwifi: add 11ac.h Date: Fri, 9 Aug 2024 17:44:52 +0800 Message-Id: <20240809094533.1660-3-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 4fbc0fae-b2c0-44dc-5941-08dcb8581142 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?cLac36fooA30zzQXK4YedOm1xPuqKnOSJmBYWBKF/gVcBi6hD5Sl3KsuEZiD?= =?us-ascii?Q?3TSpvHQVz6XdnagCvJLkCtlZgb/NJWTkwLr+Lm1TMVJx0Rgo5Ub2ZXWFEULt?= =?us-ascii?Q?O8xQRRV70CFpEbh9moTJOcPtj3KixrOtnVsqYP2aWbv5ypBURYif/NSa16F9?= =?us-ascii?Q?uzoS/1f+ZmUVTB6g9I69XIbjpTVNvdxKAV8A0Z1IBEB7vizmw0usSi3NfEv0?= =?us-ascii?Q?khL/IRvfaH9IsKR/Z0R4hP4lGyP+H+9p+Vzl+Cbn9j8zeRKl5JQN2RhD2UCQ?= =?us-ascii?Q?3AQ7VnLPOZUexUMw86lEd+jIOXjW4oOwiiT5ZJNk1CUUEsM8svLH3CpFep7t?= =?us-ascii?Q?zMctyGwZbf9j0TLTzpRunIKcaEVGisMYK5zU6zgHwS+g8wIaYImF2BTxuw/w?= =?us-ascii?Q?XCf/aKyqSbtKj3RRE4qnNYDlT4d2WfhgqTQKnBKKhL0XWSLmtGX28tIxcUF3?= =?us-ascii?Q?pjktCeQNroA3S9ZjKU4jKly9dWvymYCf4f8J8k4gFesT4Y32w3SE4xvRbdYI?= =?us-ascii?Q?N9vLxaaie/hdsf9JsiaaQMqzkFjlXfPwrr8F8BqwecIVvjPj2F5uYqoAUWuv?= =?us-ascii?Q?2Y6YnDcVH2MmHCwiw12RfreZkU0DfF/Y8TEho5Y/LIqWLPen5HArDdENHcMl?= =?us-ascii?Q?11VUBvyW+N1uNzM7+5qWG1oVxdh+UpUUoMbP4z5xVILJ4so0Mbk/uUHCoNWQ?= =?us-ascii?Q?LDlDzDV23/9qzQ9ux0jSLsc2XwR+HS3fQE9EN3VIHFKEOZf6iqP5ponoD74t?= =?us-ascii?Q?0A2rG5AkqqQXoP2tNw0L12PcJBilg6HjMN7FhjsD73YBLmlsn6h9OJ1XstZw?= =?us-ascii?Q?hwSH5+qnyOqCRSsAi6b5GFcTn4tjZRo+OTVJMfZzEA6G6dR6gRQRZZwXU8sL?= =?us-ascii?Q?est3qxiUu3/4Tdc4DnaTqWQZn2cUl1EfvTHBbAvt7NX60J1ay9PjlRbIE1wY?= =?us-ascii?Q?uOi+isaUHRuJbjy6PzW4gJbwDE9WLaKF1NBs3ZRPGmUXMtWXFl6WZQ53IUo7?= =?us-ascii?Q?mzEhx1Kksex3lJwm3ZfELYz0R/L8ImIBC1ScV3Ld1x7CtDGoC/RGHbZQMRwB?= =?us-ascii?Q?R60/MdffPX6XpDJRivRXOli0G+xC0NUYnbIR1MSjPzW4hiYT5S0qpVVNFf4v?= =?us-ascii?Q?7U/fhVs6x0F29rlg7t0UL6vKyNSkcIdkdNCtf0Q/R96YjnmGWZ3NEOeSx1XA?= =?us-ascii?Q?W6TEwKyQv8AC7pmKb87UyUWURljQvc3XdiZZBtgB5/71EgqOdht6MzEKsbnC?= =?us-ascii?Q?HfcPRqfa9749oAELyCEOk8HiHUPDM36DHmsJ9h61U99hno9p9F2qmJIbfCT1?= =?us-ascii?Q?AsbUSQpnLC6HCmXcOY7ac+FwFfB4uge7EJ5kpnU+flZRNg=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?zTOWEVgDKdgfJkC8iY+s3HrsOQcwLT7GoozJTlQPt5aaWWsWa8xZACB5Sr2T?= =?us-ascii?Q?8DAfe8N3RfveGCy3/mDLDRIngwGPtQKTQ4NN11S6n92QOFq9Dlzc2Re306UE?= =?us-ascii?Q?IdLLIU+h3ayhrVrnv6MupZFOho2/u72YFSzufLQ0W1piO342RE9LCBFa2pLw?= =?us-ascii?Q?VJxZb2M0lR7RZot/GVNl0G0xo7CPgvOSHjJo7n8BwpX5eCL6veXbeOugntUp?= =?us-ascii?Q?Qs6BjJkixBdPb6E2QdMpgv6firIafl88JMYO5LVjWrFrz3rCcN2spMkQTEm4?= =?us-ascii?Q?q5B4rh4v450aEe3MvPwx2cPrl0gQUH/Yt0EnQHrmz5slgR81UhOXqKoqve8g?= =?us-ascii?Q?HmlkG65vUHz4aMcdO8h5yBjyjeX8xjCaXjPVr5qhDpB4quYxKWtRfQmtD0ko?= =?us-ascii?Q?ytgkBSC5oMjeign3v5oeEmgtBHzxaUDX9w0Gjyh76PpVl35quPcJbAi4TFDM?= =?us-ascii?Q?+MYyb/amkM3bOxAz+Ts/W9jurzJrU5HAPeBruCMPLKS2zZc0jx0arauZ+OaF?= =?us-ascii?Q?lUYo/BF2/efvze8t4ZJ5+B0NFyg4dJXLRb83P6cdYvo4N3J7sCORgCYPU/DP?= =?us-ascii?Q?SZJrWuRL9MBIeZhYnbiB8I+Rs6rBmC9tXjsxoPl3CCHHKb6K2CWr46uQ4HqO?= =?us-ascii?Q?RVZUK1cuk2xfcTtiIrnB5OMZYj1uH6yVGoXVu9Gq4yjNtTlSWHjGGT+K25V4?= =?us-ascii?Q?M1OBG/UeVdxPEQzk3qbTHtahNdiWGX4qSrj6JgpGoUaMO25BUQjzdjM/J5nh?= =?us-ascii?Q?qlTQYGocCtzeQpw8op/YCp9FkzxzWhlEEk5nQeoyYGJvE5ci2d7f1sFgDhgC?= =?us-ascii?Q?sqLHVbw1piRFw3eX1r2rqvsuZ1X8/L8IY33aCqY9Sw12uz5CC1XOmCHV9Aos?= =?us-ascii?Q?Y1P1Rq1P5EdTYFF2/hGK5OpVDeEj9pPIBHu888OpF/fmUqh0GFDgkhyAVwWK?= =?us-ascii?Q?k/sM6I/Xs0LAkx5HpgIZ0PoCKJUh4t8D9pGb44GsuzrV6aNz/xpYoe2ldMBD?= =?us-ascii?Q?btdfcNmeECLvewNJaq+A+Bcuh0cUM0oS3hQUSZmFDjUQk5KBdvZUpQj79oE8?= =?us-ascii?Q?WfRFm+ePvqDdX8esDpFW7Td7PBTMms6BqjMNLxI08P8u+ZoEeyk9QWWkFmKJ?= =?us-ascii?Q?6io2iBxQjvg+AEnvDpoSpjQ72woUfBbbYC/lKj1ashX+O5htnYZCxqCkXjD2?= =?us-ascii?Q?8Wi/p9pzLHTzp4GGaxkMFTob5YMJp8cDkS6sFGXmF8G7un+uL19kJcbegL0w?= =?us-ascii?Q?Gs1JUXaB/kuoen2yQRwFJYe0RFAN8G5+AVYF2ynVdMFSwxHc5rX2/iARxi1X?= =?us-ascii?Q?qQpXTumQQkKxNIV0qUdwN1oXOAWHB5aoLTdWmFi22PECmYCeaVVgQPsuJ2MZ?= =?us-ascii?Q?BtzFhBdYeSFmWtReD7NM91p5GvpPrkNbQ8Ryzdhs6t+j0gTnDes9Z8aVMiYl?= =?us-ascii?Q?i25IxPZA2wK5RsJLfbF3fM0A+S8KpVwuTJiChqHc+KuciZGnVSzn8jwwg5WC?= =?us-ascii?Q?UaHkDNsZE8Rs4NAzlBUax2Clf2l6j4t/zIROtqsk8m5hwXuAt2+lYOil/agX?= =?us-ascii?Q?u/TzvKoH7jN3Eiof4xsS1EgEyCRrVgy5Uzxh+lstuTnGk9tnUZo6NdyuNKVo?= =?us-ascii?Q?ZjAcTPZUnz1wWui88QJPd8euGPJI/X7h9IDfLxET5ex8?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4fbc0fae-b2c0-44dc-5941-08dcb8581142 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:45:56.9388 (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: Mvj+tq5MaNa7b53TiYutDH9z8FFvkSfktwI7cE28ACAgJ+wzvAJekrPKFIWGpS4pSf+e2IOUWiezx/Xg+LBUEA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011004.outbound.protection.outlook.com [52.101.70.4]) (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 224B21922EF; Fri, 9 Aug 2024 09:46:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.4 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196765; cv=fail; b=e0KMFkwTarcfUPzoGYNw+Ew2B+F1IsnvcGgaarADyPvxJNDkZVdP9MEmA/Viuw4TfEucMsrRfVcL2a+dWnM3QhvkymqaOGEoI24sebL0zlL+AgoCWUFPzXWSD1oxh7osBrMucvapeiMtgbcW6k5T+YbEhPs7IYqk6JijgtgYC+E= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196765; c=relaxed/simple; bh=GgaKPoPlrHgrzHO0t8ngKmKKqPQwHU5uQ5IIBRevfgk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=ipruKcBivv0LB/6tiVCtWsXNRYJlPdgoW7SICQRekisFD0IkTBP9Di0Ne2YWo7vArY8eznWh+m0CkBSDHfEGgBpWtbizRG0+VAkAsCVbDv1LgwSHOHIGBVxtrZll+LIbq9I1QuyD1unXmblye6ptfdw4qnS2A8oZeblDTrWcRcw= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=D2MR9Bnm; arc=fail smtp.client-ip=52.101.70.4 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="D2MR9Bnm" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=PLhf+HRudi9owxFIoXEIGbMjlw5Jo/DKg7fzxvyQrz6kkV8ZyziYNtIvWhrwVO0m2DDDqprbFqqUslOFu8N0dxa6ySIlgseQPYX1ZsWH6sQDK/a66HjyDb+J1x5Mh4UN8KPzM5TqSuSuCTjtthQpbHYR2ndcU94x65OzR9vZLjFRHzXGZveKO4CQlg00SUVB/AcWJpt6SIe92y8ragKiXiGOwee15XJhE74ygaC6BBGzCEexDHXMSSn1MtLBiZ/FXqg1iuPbenD0QKCz28ymvIvZa2pHplqrWyR//yQGLuyka2KW7o2IORWy7aItJ+52uomi0TTLu9zSbMM1kCY2sQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=/5fmHESFm0OpZJJtiuZv0GbuylV9Y2S0aS5AQa1v2Zc=; b=fD2NQe7DlRURE6rN5Ej2Ld41C2ZQiOiQxQNFZ0gIYOOQa3J9PeVVhIALtR0FCEYqey748kWDEmIviL5Xh/K9XwSlkunXdK+EBaQcnMetAL68x5Pt3hK2e1WmsnM9ZMl3zFNP2092bi8ePk1kw6dUu5KVkMfYxt6vWoM6kwBSqtNCMwh5uHHvDVhmyfutA1kODj3UDgqKuTgq8RYOLFc9D+qMaZ+ArED0YaiVr4fJGenOIrMZylTYftbAHq9XEb4D9jO24wnQk6EqjVsFUzfHwMhJh5tM6jDwvt8GcXQ2lq1YVyyeftjWp28RzAsEoKUiq5Rz2cKAxGwfvIjXta0ylw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/5fmHESFm0OpZJJtiuZv0GbuylV9Y2S0aS5AQa1v2Zc=; b=D2MR9BnmhJ9KPPjphKxMZJOsddwu03YANic7RjdCM1pPB9p8IvjPJeH44aYn9dl77WQ94rV/KY0XfDujXd5Qs/seCXvOeecfi8vd5lfaBFpMYSnMHs6Pg2r4sa1T1349bG4IQIbcrsIcRxndPxrfjjjMhZ1sxf+1/xH45v65sEW2mP8xWVCA3g5YDa80Yr3LhLRxdYVGv2hoeY2oR2rjIjyLHFd1xwK/G1xrXoAY0Sc/PiRJrh3FROikxbmuuWimfw1qn7NufAbOFFQgJdKhTsSxoWH6tNYecVeC1HKtK3s7KBhNAEMEmq0SBEAYQ7GS0q6nve1Hq9CuABXxlltSng== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46:00 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:00 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 03/43] wifi: nxpwifi: add 11h.c Date: Fri, 9 Aug 2024 17:44:53 +0800 Message-Id: <20240809094533.1660-4-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: f35bf027-12ba-46b3-58fe-08dcb858134a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?+wekley2HDAIgj83k4bEJZqD+pAhzsCw2ceOOwmc5n0MhW99ivKAGRSgJlLr?= =?us-ascii?Q?lMgA8KtZvqjrCdYlBkOsa5B2/y3XjNp8388c10UTwQWL7EcS67vPO2LBaKK3?= =?us-ascii?Q?FIx0/+WoiZuEumaNyAugY3gKyCDJg0cCD42hfvNwBjT1rKzTmIa82ZFAz9P2?= =?us-ascii?Q?FN9JiMYT9tfnE+mk22AGyiu1q3jVovGfdEhkIRp0pNe9GJD8lPmeAG25HaAG?= =?us-ascii?Q?fPI1uaxW7zR9u8wbEzgvEwQcx2uoj/0euGWFJCnBGv+E0GD95lyFCxMVZMlk?= =?us-ascii?Q?b3IjMIrDdDsweSivDCsmLx/NiSQFgAm3e/s1C4ZKkZxqZoTheswPihUGrPYT?= =?us-ascii?Q?JPZ8M0NVBlqQWGEtY09WEZ2ZAYmmrY3z9IQp1ttda/usHZRZJBoJfJSfh415?= =?us-ascii?Q?kNg8c04XxvIqaQWkqw4pcDtK+DC3IZsEagj+MMSarzllvYPspsBMQY1QB6PA?= =?us-ascii?Q?4Yyzt3qdT5ammR2smHe0aCYmn8sQrgBep1v8kg2pP1BOodho5lwimNVRCztl?= =?us-ascii?Q?hiobmcCRhi36EDcktaDguNd2j6mv/4yllzd9f8Bu78t2w/q25gW4vcSjDAD8?= =?us-ascii?Q?eBGoTuLvwk8OZHCwcI+CetlDXiNwVGOe7XHedvSNKYsWoax6KAzzHT+ixO/C?= =?us-ascii?Q?9sbjx9ZSkmtttYYiwMsgH395agqwYjwIa14aGJ4vsH/Ssv+Qzfy7Rdeo2wt+?= =?us-ascii?Q?AAxJk/hZ3IWWoB64sD4OTyyUB4nvUcGi5x/VNwh/BALv7sp7oph7BBLUQ/ls?= =?us-ascii?Q?S8qw3WpnV8NpseKRIM5N3LXkmtf1mDJy45Qwgx1Cvlxd6If2zKYLjJT4aFMx?= =?us-ascii?Q?pRRW8br7dm5RALWd0/62/pBJ5aKxVzKpCsMFcZQP18kFBbseBqq1EalqHwEi?= =?us-ascii?Q?o5SG6e1noPqFJf/2MOasBLBLuiL9ScOvy6/si4lVVLYCAN/XbftENGtRSdjV?= =?us-ascii?Q?lMbTJPJ9anJAFkTTq2NPCyvvMmibfS6/T3dWuTQS8C04i2slyTPONAAUkxko?= =?us-ascii?Q?lO1oTb3PjGqIYSztn+ujLwc3oaGioDIzuoNYMVnzv0otuCm9btNZbU2rC4nM?= =?us-ascii?Q?OZaLduzAupwMdZu87JOUk2J30Fdm+cctvTz1FU1VvrCDxBbsYSzJcElhzf5q?= =?us-ascii?Q?kwz7MCrddpFixdkdb/uskRDE4k8RvaIXpIApFnBXYkHPU7uu0xHV77xbJJ7+?= =?us-ascii?Q?NblaKbTMFVt8SA520NkZPWWurawMDiH1kvm4geJooRwKhJekBkfP9CZp/BPJ?= =?us-ascii?Q?u/tD038sPgXy/Egw6Xe1qOJ6Q5vZ4ppXahrejXo/Nj0JRwOtGW55leSlBVJ5?= =?us-ascii?Q?dI/5RxgVWrNssh79ckrgLO8I9q5KlLEKUZRgZ1YpfinC1g=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?nEUayJID/jcznK//dQOtXx8a/D9Ah/wuks6HJLM+4gQKP+RiG0SeS9Gmh6Tj?= =?us-ascii?Q?R7sL0CStZ7OX8X2P0NrPQEttH+GnkZimq1NR9GBgAgWBdhMgj+pa+KMNCL8R?= =?us-ascii?Q?Jphp6XeBZG3TOxpq38Mcdi7s8iXYatBokJqW/wgQ22GfD+QHnwT0toiHWRMc?= =?us-ascii?Q?l9WWthNUwA88u4slG39MkPKMSSwN5kVbhLVcN7ww3EsaSmZT2I8KqxNm41yV?= =?us-ascii?Q?KddQRupnGb73UmkToOiakvZbqZeaCrDo5yuEVEfMtlhXV0woYZwDibaOZImU?= =?us-ascii?Q?9YQPZkdwvii0pX1D4I+1ZXBIJsba0ysIPi204piJa7yd17q6eOg20jQe0Bjv?= =?us-ascii?Q?WHZFaQYcpQcwCaQrZvf6y9CSvEqwljGgzEgz/Pnu3Z6fXHL80u5HNRvVyTcF?= =?us-ascii?Q?rddJgh8usS3BRVuBh8c+16RFcO/YXK77jhxxyP9n1RUFayAFZ/XrqwMbYeoX?= =?us-ascii?Q?dAuNTS5CCQmBW7mIHLeVon5FoVbBLeegPBQqOqEPs1/jHTXDR9Mw2W/Biraq?= =?us-ascii?Q?jV/dI1rC5MQ8FK7eTwFtcusZTe/VFAiOcgl3+R6pXYXkcmbsmXfLFsQgIcpB?= =?us-ascii?Q?fCT5MvfHFk+k3hx0xf32KBmQYgrOorM9CtQgQv3CSCW8EE7U9SsLZW18IIBF?= =?us-ascii?Q?CKy1gC4a+jbu+/RvXwre1Wm8DL2qKqFzw4D3K3DwcppzG0P127ku9li1xgqK?= =?us-ascii?Q?kDdHZw8bBFn4OfXFnEpT+8eP4V3M905wFxnoowi3VNDR2YpgyRCeDihkDk94?= =?us-ascii?Q?PAZlLAES6xBDGYaT9UAtiS6GFim5HG273c2AUyFTpNmutIv0U1sFnPICA81w?= =?us-ascii?Q?VFjvUhsqCvXpKinAVTicwwN/2MkcCGS38HuiP1/y+IKrJw2jOAAQvpMezes5?= =?us-ascii?Q?Zf1tnl0Pg5aYyCQNxA+sjPyjkeH5CheCK/I68Z50M93Nqko7MjQcAk8V39qJ?= =?us-ascii?Q?TDt/Z91LycNaRNpntcgbnTcJgaOFDYzAn4UyrG9ZIpTMdMuBB1RxlG7L72Lz?= =?us-ascii?Q?QSa3jzy+Jg9hFOOR7S7nxYwIRyMVfB85qbn0cTC6ONYh6h7yoc32yvCMzsPR?= =?us-ascii?Q?hmkoeKkkjmlNzgzsLmL3c1qvPMRWuSQkq+gebVlPTo30hvz+Ib4pjggtDZ4c?= =?us-ascii?Q?MHm90cnD0zY+OHegbxNBQoFfcILmIW+zMjTAp/wxpKHqVjE8Fz8yRLVU6fME?= =?us-ascii?Q?RBUxeV5hwm4KDM4LZhejpFfxWk08euG/Z8MRELd51AbVou20oVs1ojeZkltG?= =?us-ascii?Q?fLEzuGEx1R2nyViyDVEU1//8q3ybhG1sxR4QHcSBmspDOYTEMRPRMqLxYMTs?= =?us-ascii?Q?JDkRV4eIZtUk9kv+EsHvllZfCfRGqTrA1w2BS5btIuT06kejIuvYUbDd31Dn?= =?us-ascii?Q?N5p5comOrouKvWGIGeSv17g7orAyP5AqNIYqarmHaN9BygI1ag3tU1zClnnG?= =?us-ascii?Q?VFBsBeGkz1REDIAhYoA5hGrF8kLkQ5I0a3tft1p8m3vMDaEGJUoFKMIjVokl?= =?us-ascii?Q?fkv9xAKVAW34ANqp0ilg6oegnx4zHwSwv875nKNdndmb4ElHUAfm89we49R5?= =?us-ascii?Q?tN8ixTO02Md+WKM1QvDtCQuEY3xlleRXsuor1OKZD1QQQTu+VfhU2yWn3vhP?= =?us-ascii?Q?BLtMbUvzuX7MwVC1mrfxvzXKpZGKocWyu9etsjmBDyC1?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: f35bf027-12ba-46b3-58fe-08dcb858134a X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:00.3841 (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: EDyNeJI9S7luREuMhNo+w9jdyI8AROQLEaMUV6c706M/VhswzKKu1X4YvUNYEbFKFglSJ2GyAymkCvd6ZHCJhw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/11h.c | 433 +++++++++++++++++++++++++ 1 file changed, 433 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..b8f41b304510 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11h.c @@ -0,0 +1,433 @@ +// 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 function. + * This delayed work emits CAC finished event for cfg80211 if + * CAC was started earlier. + */ +void nxpwifi_dfs_cac_work(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 =3D 0, chan_width =3D 0, chan2_offset =3D 0; + + 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 -EINVAL; + } + + 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 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(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 Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011004.outbound.protection.outlook.com [52.101.70.4]) (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 E6E9D192B74; Fri, 9 Aug 2024 09:46:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.4 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196768; cv=fail; b=QJJkNC71ieI0YOELEpfnqEcg6A1aytjosEwYBfLhx+s+uSQZrkcLEWcPDvA3fy/OwCCf5TQehMpZ1OhVv5BIbCSNqwNs4AilQAqiw1hgjtg1XRT6hCuwUounrbJnagPp7B67b1UFRdHxgbw2xjKntO5CPxGzVk014O38tRwuLek= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196768; c=relaxed/simple; bh=7P/LnuSYSLdNtiA2kaRD2ylmDoBGn0TwKl7rF6BuZGA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=nf7LwmI4cOxrwaq809KFnXq7sBj0AnnQAqgOa8G8kG0f5gNykrTwukrxewo7NakajkLvJX1+bUH09Xm6KPG3kwGrRxJeCapPQVNTcB8IEE0m/pFcpO9mbhXl27IC+ZhwE9BZ7CL5/S0u6QmjWaVNSbbjRWMcncZiVF2HwD5Bpdc= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=NKJINOM1; arc=fail smtp.client-ip=52.101.70.4 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="NKJINOM1" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Yj5QNB9Z6n9nCZ2hTQb+NVeiymN/X7tTAJa5VCD82ypyMBSSNzlvnEoA1oVRfw94tlhtKnsJp60V/c3spsMYWHpGgvnBWwgsrcMZnll3iwAywbtUt5tBbXE6EPuNJH0bffWFqbfIgyJ6kIXSkqeqanAiWfEKpAt3ilp72ANEeP+jmvtfpFtfUSrTbKoNTzQOrU5dzLnvhpri4RDqUMstkYm+sXhYOq3WfvCUFhMoicl1lHUELW7M0Bd1X44CYYXaUAaZzUJ/zIKoggUybd4pqSCW85Om+ENZ0dqgkeVZ0Fj4qd33k+g1zOTHMvIqAwddx8649PQHrwuRXYolh5lsJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=x8/p8snz+4NkzgjaCyakojmj4QeDZLgn/yHswc5j4zE=; b=nIYFPr3cCjlHxOF2iLdrnH1f01USJkXZLfv1YnmWbO9E3Okly7qvo7hkY+bm5gKYKr21SLPaGK9EYZAvLGq4wweb6I9knpPBSwBemM7gcKqm0BrjF1ma7LvjawcevWgqUNrcnbk4Ub1OAVboMTe5lOmER7zxBxy3pDwn87DOfdO887WCZwp9QhjLL6zI2NT9S6eOnKDuBbcRAH8GQlZv6ZG58rhBFtktx0Gqpe2aojxoMtLSBzg2jYcGXv8QulTx9y/GaStIooNVcbb+RlELGYePB+X2iv0QBDqAm58xjrF2CuE00ZY/bwbcaKuk52WxtwrUy/c3UdcJw8zlrX0v1g== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=x8/p8snz+4NkzgjaCyakojmj4QeDZLgn/yHswc5j4zE=; b=NKJINOM1H9a3jzTkGTlsX8hKodUvFe1qte6kcbgcMZToAUfijWXP17RBqnbwHePevyWiRPKFyr8fvPyX6d1u/XYwKHt5v6o+f0WQqtQC3Ibv/w9gSNQLst+v4wraJG0Q2SWoQxOCr/4niexAs5HBVSO07pW1jjxrL3PpvrzMFqOVoGrR4aLaxiYj48gyloh7ZHo+4kbirTKdW/HQcemAFHOo3TIxs4niXoogHuG0KGe2SdkABQaqagrUbkfIcq2Zni2Trd7z7n/s4dLCrhEH1UdpbUgloC+YhNj+ehhSwXhRAqTlh2nhI4kOCFfsI69MaXh31pFIuvubP0XMrUNI/g== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46:03 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:03 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 04/43] wifi: nxpwifi: add 11n_aggr.c Date: Fri, 9 Aug 2024 17:44:54 +0800 Message-Id: <20240809094533.1660-5-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: ce9899f8-fea8-4b6c-f4ed-08dcb858155e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?QnxDJsNTaR0E0KfCnx4NREDrx2G7lhQiJdM5WdC/5RpLm0GaUYVtekP9MROW?= =?us-ascii?Q?w1NL7TfZxWhwSLCPVWB2oI6nwP1EBXRB6Ae22w/lraXqCLvzlwvd5jzHaj+G?= =?us-ascii?Q?Z+5Ayj1VOO3kphEzpM+I2wiuEAf9DhpVFbuoh76vy2nLlzu1uhtqH2Tskcd4?= =?us-ascii?Q?o7AD5/SN9MDTGhOsen0sqMm+mSf5xiSWlR14wtmsOqjuOaxyGyGnwiVujhOp?= =?us-ascii?Q?nI7iBr3g8MwdKvtSzYL2C4cq9h4q1fDRuqLn9S5KD6KaNIw08bvkK2jkaigH?= =?us-ascii?Q?6vrYuznchI4hFyh25vVbgM/itahUXPL/+gX4ROqRwc8NAhQvXPCSL+4qkEcH?= =?us-ascii?Q?VEXXvtf4fUP2WfK0K3DgbS2m8Y4waMTAddfdjY/Ro/ojSIXjD9Bx/RImiTH/?= =?us-ascii?Q?1wr4uLlEt7F7qUBOGv80BsNZ+61WlgEvvvIuvr7WyCpK8zZFmn9yISsaoCWx?= =?us-ascii?Q?JtVux+ZeK52vpnUGsCrWKTChy4QYfXtv6fwRfj307F5fdg6Ff1EOA1B3aG8v?= =?us-ascii?Q?LqJi2ZxAZJpFc0mns/2wH7955qEE0hYT4EiAIevf9gdj26sb/CRX4t0tc1xE?= =?us-ascii?Q?0DohQCQuGxouZ5jUUN9f0L48UgZv4OPiPo/mpOVktcklMriVhD//f9s7pcwa?= =?us-ascii?Q?i9fiVevFKsz/bEq6ACu/QMo18YX6V/qaL5Ur6R56XB7PblcQgNCgYV2S78wr?= =?us-ascii?Q?prdtNyhvQkj8q3UjVb9oP+8xEEcIydSYLJQu7kMeZl4pg8TdGkBC80vofVsY?= =?us-ascii?Q?+8Is3E/JJc08Yc7kwiKepOvwdXGqcyvcVKcWFOE4FC+qh08K70R9iq6qoVyD?= =?us-ascii?Q?rSIi2f5SmV0qKWx7/iRSA6KNidd4RxZr7oDs7I4YpAJLOmWC/Xmjl2+vMej0?= =?us-ascii?Q?y9SKW3n7aWkCjDaUbHwGpLDN1aCp/qSUVa8M7LTQgChfDslr7GpLgC8Yz7kC?= =?us-ascii?Q?ox/DFY2NWU29fm5W0zw3RO/TQZh+kdd+luYrlyHIt+Edtekwcy2E+CL7cMbE?= =?us-ascii?Q?4ST/1Fw+v6YeDGZTbsLwsIhTSVNmjQAc9a96kI/RjNPIM70oJvBn9Oj9dkBb?= =?us-ascii?Q?IfNmsAy2zpRPpcSG/AKqWmUuNfpeFjlq3vPt/zY9hlu/Eo2hocSjDAmeXDGU?= =?us-ascii?Q?6jmEzVCBV4C+5sMjZDb0mJbO449FSDjkJBHR1A5rxvq+HkLwiEpNHulXNdCa?= =?us-ascii?Q?5/A/VKICMMdxz2LHQYXyiUzd77FE4qOTelTAwCT2tG3vyff4BLqlqtLOHkJu?= =?us-ascii?Q?ug9gGxPcpjggQkLNuWXCHER1yRlECY0fW7i8pg+NW/bRtW7bRj4+Gyd0n87O?= =?us-ascii?Q?R517c1jBp4VVLSDRmfmbI002by9a8oYGd9KoLP/NpF3VzA=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Pme9FG2rqvXDKVH/Z/vN820uMXkFJm73VuzQOSUJlZ6RSxl+gtaSS2Zqxgi3?= =?us-ascii?Q?KhMISKGxIfHv7b2SBq1lukPokOgbx6lTFW7zYjHqbYJXnEpsUMR7Q09379Aw?= =?us-ascii?Q?QXxWHeUGIpmW0Rml3jIswjo509zY7oBFGMuaMt76Jrt/sJQ1YGgTJuTFmpEz?= =?us-ascii?Q?CCY74DZpADkOzohiDG9ciqiMYeq2u73stBXDH0NpeiFu2yBJj2RFpqM667Rm?= =?us-ascii?Q?k5lG2OxGJUM+iIOu/tl4EuzqHK0pzmXPbTmoQBo5NXYqygVKDehrg+twJVoj?= =?us-ascii?Q?Kfzii0LfN8UZoaDisBmQl4t4G2Ac0ul6dvaQi5YqHpGAfAEb8mncx+YBIw64?= =?us-ascii?Q?7gyO6++R/0K8GkXUDTSm10oSHiL/Ek7Mo/CgGS5fco1r/KfTQDP39DtO/csA?= =?us-ascii?Q?WWzgRjNAPmgn6Ec+mvo4MhpfY5cyw4ZZWL5ZsknHDVcwjFp5KZstWCPrNt4/?= =?us-ascii?Q?BRSnl7CcSA2FQ9cc4FCFdIFvE7/rro0eEr0R09czp4yJiq2ASD8WxUO6hyv+?= =?us-ascii?Q?6wETwFKglw06ej0dKSV2pscemk7dzMVntXxVgCFprwdIwZnuIDQjh+7U+Kft?= =?us-ascii?Q?9F7GfsTEXFmKYyRjMChOgiW7UpPcvQnRCtj+3GL0GTI7MMCN2qpydMy7DjiA?= =?us-ascii?Q?lde2PwDWwPzIT31WdC4j63qsmZvqh/aGCCjDB7pNZsMCjTmXWvO6e3DuxtGo?= =?us-ascii?Q?lYz2HmLNwG3e7Dnt10Z9FKMsBtB2J2QHh66yD2aja9kiWZ5bI8gUHSUGBwsB?= =?us-ascii?Q?FZlaSu8C37gWm5yo8qRMS7DG8WMxVqQMQE2ZfNrgMN/cBYikLa3z/bPwq4jK?= =?us-ascii?Q?Kzn1AzyZEU2rqmb1OW1pF5owxNbA2sUeccrRPQvfR5tkqPSU/RBP+3YeNc/v?= =?us-ascii?Q?Gpcr91afbuhsyjU6mKzF64tmMKnOb+2aDhUH3HDLlt385j/khuGmFQzAuCI1?= =?us-ascii?Q?pkZIqD4ttMH/vLRnQsman14vZb3h81Fo70SUQvSoss/qbC8p07Z4VVjx1BnP?= =?us-ascii?Q?L7mir5nNiIcjiYAz9FTuoPp71gtTDBPzy7fQ7E39Yx73O0DFczo+T9EcLcCd?= =?us-ascii?Q?aTgu2w1vX9CXReQI7jsV6+35y4yjoDj2a9besaut/2RrxSE4ElIoaCXw2jYZ?= =?us-ascii?Q?BC7mIyR3+le2DCnC1kyKc/8ZONoWhXlSjukoXDnpMsrLi3AVUq8hFalyp/YD?= =?us-ascii?Q?OzEZ7KFLnytaGBR7GUu9akcl3If9goSw16bdLPVXv1sEZOKJ6fExB2tgeaE3?= =?us-ascii?Q?Iu1EyEBAZXL7zOaERLwaErI3EV+9uh5lc5vYPKPyQtefqCRcIwM+FT9Q2VDa?= =?us-ascii?Q?OSmGhY3v1DwUJRsewHG6aGozQFICYI/1mrcfQYrdPXKtI9tUIY0XAZ9eq+vW?= =?us-ascii?Q?xvOLUofOt6BDv9QS3OMZvuMnvjD8t5+5U7oJODC8HMAsJENX/M2FS5jAUw5C?= =?us-ascii?Q?jRS6LVu/YaHypU2ucNcF7zGNfuwnSTOIrqPcPXJtfvpi+ZKStRhsQ7aiZC5d?= =?us-ascii?Q?g/4Cfl5jmZm7F0LUvthl6AyCpPYsCKd9l2UoIGvLq/PKMaURV0gEUSAwKSJP?= =?us-ascii?Q?OqDRZPmAbTr3mLbjyKZR2SIjFjHRDbEJmyOluDy5K2NUqOm4FjIGUff04bPH?= =?us-ascii?Q?XJ2tHd+ahqM4hykm/VLgscLGcOCTwqGD7BDhAjAKyv+M?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: ce9899f8-fea8-4b6c-f4ed-08dcb858155e X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:03.6329 (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: X6Y3Wy+bVr1pLwEVdHnfyaymPcaKKxqK/8cs6F51JmbBdGITD9GZy5XfwFlb4w4mjslI1kXo4nksfnea9n2OOQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/11n_aggr.c | 276 ++++++++++++++++++++ 1 file changed, 276 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..85ea840e6e91 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n_aggr.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: 802.11n Aggregation + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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 -ENOMEM; + } + + /* 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 -ENOENT; + } + + 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 -EINVAL; + } + 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 -EINPROGRESS: + break; + case 0: + nxpwifi_write_data_complete(adapter, skb_aggr, 1, ret); + break; + default: + 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); + break; + } + if (ret !=3D -EBUSY) + nxpwifi_rotate_priolists(priv, pra_list, ptrindex); + + return 0; +} --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010012.outbound.protection.outlook.com [52.101.69.12]) (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 6AE67193073; Fri, 9 Aug 2024 09:46:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196772; cv=fail; b=WL/dOZfzm2W9J9IdV7KKSDPi1bEXlRNdbpfe+p4b0+pZUXHVSq1Rn8Y7h0WmBfIoaF6Oy42dMVtX9gfelkDzay+Zo/VGq34thsXmNzdyfWZRdKl6xgKp+DrCL2poskALJi3mK8Zfb4EpLC8f3XYqdCzyGIt2U82uUobNqwQ4wgI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196772; c=relaxed/simple; bh=1PYHA52R/1nqpCMGwdQLlFvxUwx/4pnaicj2K/AnL0M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=tG+0RQ5v60KEKtMBpwWszQktnXUFDGiyn2TZzYxlFunCU6GpL59JjegAdY8z5MuSr32OFxosHQzTo1nvlyIHCe55Yilq0nWzb2l5m0CFM7Dh7TjXKp4B4psHpLU8RAB12YUTDetwKMaX0MTlZM2CjCTYoAlqNLHoj3UHJf3HsTI= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=c4NwyK7q; arc=fail smtp.client-ip=52.101.69.12 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="c4NwyK7q" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=XKLWnG0GLd+ctBpycvoh8cjI2gBbTFcy0uQlcEaR5Gt7qOn0QCve6WQ37i/tuiloE08r0ZKFE5e7vtKq4QHcuOrAu0l4NcKZIZSjivA0ujfSEv/g7kQEVgjnccVImnj0459qmSUTFj0kbwr7sSyUOCh8fEY3HUDpp5nz3wW2GfJxR/0qjAB87lvbBtyoW8jzfwHyKi/ryMUbK+S/bmgQRZ8qs1lai1R2Te4StkOruyUGoM/tEfgArKEozqsES5oXvHOWQ6HkNIUlQEcBoxgWGAfvlQHv2x4YPM1t8BB2KKXn/hu4BBxK8T0l9IEZ68BKnBjrnDXUn3Am/B2K0XIt1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=v2JYIEZb85X9tKSGLC0rFm03ywjVIAcFU04p57FJP7Q=; b=LNW0onlzqyUW1qWcdA3rV6gW6ElZ7yGy1j9Jdo8SafG8VGuf+t4MkixUqePI0pvJ3nq9PytXwIDn+ixJJdijzNT3YLCvfRGXZRWHrOTocsSBtF+/hXFzwNzbcMbVoZRk32OsyV/Vg8kxe4zr288WhUnuXqY2W1Tq8hwq4AnlFLkMy5zUnUV/u7yNlyAYXNbqaAKwc6XBiU+escASFSfl4A5nzp7TCwphz1KLRRD1ip/dynem0qLfDbo50VnHe9MdWSoq2noQ/6JVDZ+ibhbnH212qKcjQ+DOp7A2PbZLbXt4OqfqbKJur1q0TudaZf1tEgnRZxuMgbu96bHKBeXJ0w== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=v2JYIEZb85X9tKSGLC0rFm03ywjVIAcFU04p57FJP7Q=; b=c4NwyK7q1FP6OUaJHzLgmMR1ah+DfDeXBm2/PE6/7QC+tqw1xjWHi/RAUyn8S69pjOKAKJ823cAtPewzwzD0axreYspALbEFsA7Fa3mU/stXcjjwqzzuTYDzgp3lpH06GrsDHrncRhh3X1yqak0cSGzxqVPpLCeRHvnV1ViDdseubjcFTBXXrVS/q+fvPJK15fMNfQ00tuMaOxgVCuEMm9d5Yd/4aKMfaTghFYqnDxgsrkST9MD0NBPA7X8TX435UKGSwehMIB8u3mGvLELjnuOXIBaTrlJWvgeXhzcUnq28XKiICQ2YxYBHVzMc4KIXFRuty6Q265G94lCeBLsvRg== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46:07 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:07 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 05/43] wifi: nxpwifi: add 11n_aggr.h Date: Fri, 9 Aug 2024 17:44:55 +0800 Message-Id: <20240809094533.1660-6-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: b5f62cda-65cf-4ba1-f207-08dcb858175a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?nhv+EPUR94wZbO76TK9UV/l266aCKVyD4+TBEPOBex79k9EkQ4ncFkie2U1P?= =?us-ascii?Q?DDB8FuFD2+7/z2hDqaSRvDQ6/L/xZhpc5rO9Wu4xKMom7KgiGfOVoSuwngrD?= =?us-ascii?Q?pcmraG4LkzXa4NYw9MyL0xeHMfFVhfsfx2yKcR6jOp6YA2PBTRSR0T+ef6Y1?= =?us-ascii?Q?nPvOiwmMUcLz4pB9leWhuJEX4V1VElTGk5CjSBw6eJf/X0Jacp14fppQ0SPS?= =?us-ascii?Q?tXUldXm2nAFCPprNjFYfazE/YS+APhQClQXi+9U611U2SbY3wer6aVP9hM4d?= =?us-ascii?Q?I5wOCTy1Dcjiz41D8snQIn7iQToccazBEV97/jNYxRHOQ/EYJxzZ+xHCswue?= =?us-ascii?Q?ZxGcFDN3JRsrOVZTky1A+vglsCHbLY7yWldb4HLajiLyNWWx25v69VjPleRv?= =?us-ascii?Q?RikfjfAXhI5hKKZHA/z5FGlvha8hiiHAhudKjQt24uuEJoAd9llakXs73tLy?= =?us-ascii?Q?45mbxs3eHBoo6Rbc9vYKZphgBsQbKucW5yiWqtMeLB0lZM54QUP5i3yg8dCy?= =?us-ascii?Q?qsqb6D+PgADY1F/P8SxzedwPfiAdVouC6fF+UPuxgYvxDK8MuRtOZd/HsEw+?= =?us-ascii?Q?/KEYX3gQyiGuFK7oO0S18GwwFmv7QFO+SckySuztcy+t9tEQVhqNrch5zUE6?= =?us-ascii?Q?7zTc07cPsoUK7nkUvBLCg/RB5dXITHW+Mu27tfduBM9nTbyKqDkNztcAIzdj?= =?us-ascii?Q?punxXupxLZb8suEwpOKJ+/dtGcTyo5xUnlbTESEAXHzd8ATa5YnaqLNh49/G?= =?us-ascii?Q?vVODg53/8xxQzmwzuA7BLIjuR9H5dkDQ1V+3ST6sISDsnXFiKDGToSge4OT+?= =?us-ascii?Q?hvKZKGF5ZsBZQ/FVrMT5jXr0ZqJPK4BlZpZCwXriD0TKCz6dpgUSeDFByhNy?= =?us-ascii?Q?R5zmvtCd0RfM0p/o0U1i3KnkPSF6mB9Yb0F50TdkgPfZLsiRw4bDiNPTa7kc?= =?us-ascii?Q?IrteuP2uTCWW+hp+tkt+W7Jc3Xhv+rJYasZZXDSboLlN+Z0USe6LSpNf7NM2?= =?us-ascii?Q?eTZWIvPIQCylCOXOFQbUKPTun9oYQVhJu71GC9DkIXVjhyEUMbmvGZtg0Qju?= =?us-ascii?Q?YfSWRSj432ucHtuIL+xOPwPics+hFVRfO5T6+qBPA3tK65xYJFxxV8riEBUZ?= =?us-ascii?Q?t9J4OC5J8WlIT7GWrgiYS9mIrrxH9aWeLgq0RyxqMP4uqTVEp6FZqH5K4eOQ?= =?us-ascii?Q?WKcV0jbYX+l0BEfSqjvVb2UMKCotxcXYH/uHEzpt914o8Xc6nCWbUbAJicln?= =?us-ascii?Q?NDfKR/5nPke9s/0pdIIbhKZ2peL+bH+2ay5eLbYrt03Rf5NblRpLYMY8kO4i?= =?us-ascii?Q?/x6LqdXyeZzKlFm1u7f5oMDLrGjy8Pd6hoMGcoEWpxeUMA=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?GmGMDYK5ZfaVUqgHspHnZBdDcuUwQTmrMcDo8aO4eIIp/4HyGSeHa+VIm+Pj?= =?us-ascii?Q?qhuygpQpVNbF3GRwFW0deuA7pzv2dIYeZNuYEm8rWFzxCoOoNOO+e78VUxuy?= =?us-ascii?Q?6C9XSvDUzqgUg+ftuRMTtXVrOO4dCIHKdgbTweDbnild964nPmJ/sN7otxdX?= =?us-ascii?Q?2wDFghFvD3brSc341JdTdujdpoGGtB4AS1TTkxV/lyIw8wPmCuUafk9pTLSy?= =?us-ascii?Q?FjzDz8wDz5r0fJcrKe4qcTvk5pv8PrOBP/QmC02Q2dBsJmfturxwPmpwHy3z?= =?us-ascii?Q?ocaBOtwiFgUDWp1N91aQrkODtHTK3snDy5TbK5Zo0SaMUXfuDLnXfjr2s+tD?= =?us-ascii?Q?laKkAu3aT36FJGhH4xGLLivR3rLZFvovmB+F7gJTIurmU/p9Es7PZ1ntB8Yq?= =?us-ascii?Q?7AtZrJJIsw+TVXEeJY1encLkZHwuXhcPXpjet9LPxcKtozar0gS3putHP6RM?= =?us-ascii?Q?QoBW4FPTKn6ErykNYVE/9ulc+Bm12djmn62XHwJ2mLg6IFoS2u0W5j4w73wh?= =?us-ascii?Q?XQsIyi4tmuWvXMYwoQCSjzsTzs21yQuYmBw4FRZak/2qMfwJl3cMCuP5vxqr?= =?us-ascii?Q?AJuY9X4HRDpSjJhX5QU+G031GCGuCvSq9arm3nVEQsyAkZ9RZytEPxQfZRc9?= =?us-ascii?Q?+mrwO3q+yCSp+OWbBi1Tath/8vrATRiOj9dUKUJHNu5RzCVqzuKFZfAVbFWB?= =?us-ascii?Q?W3fI+w5Fxct7uTT0zQcBfzsGmyVbglaYY1Fop4yK+A6NYwqmU4fTjXZiq1C1?= =?us-ascii?Q?4M+C2Mn8XFvrkdlHGSpNemneP8Sp2tVoYCNBrHrEzTHijL7IMK+xEGofrfIw?= =?us-ascii?Q?mpoydmt2fkE+ymBF1obyei+wPw7r6vIqdwZW6DT+dm0oR83Et2F/GDAf2krw?= =?us-ascii?Q?/eK1bSQUruoFI3VPnrnr3y8BOzrrRaqsEFEn1qlbh61n+L1eQazEwzXHEntE?= =?us-ascii?Q?znUbPiBWU6O0TwrVsuhy9kSGU5wuwWH++s7Qqp40Z9ZCUCluxHf6jqDuTmxP?= =?us-ascii?Q?eS7v0u0aJyD0yOPbATyq1LrGm8Y6tuas19Su7vP/Q58tnS44GM1C7w5eyOEb?= =?us-ascii?Q?ev8UlwSoBS8FabySwBM6Vn6XWg768Xcqmh2sa0c+c1Wj/5YXaRAH+r2NRWpt?= =?us-ascii?Q?L3a6fwIic1LFME4EYjuJghTYzZ7sGPhL2orclTOzkkagBe6/CduF68k3nYFE?= =?us-ascii?Q?Uap5hL4nqxAiCKjyU7rBtUKduWbMjAx8IQZxhKRCsjQdM6aRw1Thy//LGNQF?= =?us-ascii?Q?5+N2nMfFNhWUHUkEDS2GrUBWK8nuDtqg5wtXE974plBHpBpTTUNfAjq10DFe?= =?us-ascii?Q?/KIfDcQPOQIO+JmY5UqR40X6AAoWtJ/XX4Bgo/pzyd/FzCLuGEUk+P4BEfco?= =?us-ascii?Q?Srnjq6Mq6gd/ejCNEtD8wCBi+p1T+5lEw2M27lB0PC2wW1dyGuNjUZah/9cU?= =?us-ascii?Q?v2oxEAwy/MXudmf52NQ09rSKLOgn9bo5C9nlUFW9sXSADVboiR1KDAa4Qp6S?= =?us-ascii?Q?AqLZmE6rKIdU4iPGsDu8OZmZnBKObWVHsKzsaafKSWGykvrgv8aCfHME+tSY?= =?us-ascii?Q?Ao9Wh1Tjt5WQ5BXovzr1J+D5J1xQ+jXjJQ2p2LXtEypoX4t+D8EufkTrZMnd?= =?us-ascii?Q?K0R5kvlw4+wuAR10VQG/HDLWndCW5aucJeGFTjfiDGXM?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: b5f62cda-65cf-4ba1-f207-08dcb858175a X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:07.1558 (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: ClL5zfgT1eaLwHURsHJhAcB60zt9q6ng/n8775Z9GPXpnpPINd6lL/6pNQ+dfzNqVc4k9rsC1ebiZd8SoadcZw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012047.outbound.protection.outlook.com [52.101.66.47]) (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 6559A194135; Fri, 9 Aug 2024 09:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.47 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196779; cv=fail; b=Fo+js+MTQohEgOZFeDgsjRqWUXjW0BD9qAGwhD9JtTYGTHnX7u9VErOb8WYglpk9DYj+AEVxQlGowc3eEq/DblRKfsGi4vsD5vfCDnspTPqo5vJcXZM4H4rzXzto9QonZfE7yOVb9vqoEwrv5qA+UHJwICHRSbkf1jsA2+9e56Q= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196779; c=relaxed/simple; bh=IgQwABwWD/eu7KzBEmzkXs5MzlOaBsjw05X3ZG1JSps=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=NRyK0SriNRwXMvbUGZcBkUsEw96GKtkzmEaDiafkkI1/vuy1LjmWOyXuBtckN67IefJGH5x5RPh3RkkHnpvyj2LK8I8KAQUMt5LUuZy662LthDNWhwNf+gUYuh7rnh7VlnE6a55ytFjADpeBEIBjw0VGArDp68OvPZ7s5dVstoc= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=K33wSdNE; arc=fail smtp.client-ip=52.101.66.47 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="K33wSdNE" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=eq5OAhCQaUuM8Em9vTtcRnqxgRnNVrzpJtGJTioKiT3zC2NfqWjLAZVikFgumQsiDWUnzerSm0q6HpPscTzmdGc+JvzJsEQIbYQu8wTt7TmPoewaTo/mifKEKC9nAH2rQxo9Xo9ww8kuToewWQcgkpgvLQia+6XbBYJsU1zdDxDF6V6tCB6MsCMKTb1H0E74k0y4g3QMEbEBFzyMNFYOmrF7SdTd278evNexWV1rUVpJYSbwdy0xDGnZDQqACxWmnD+lnTQTbV2MgCmImfR9Yy+w7cRXuKI25s7wVhmX2inoE6QLeudD+pzdHKNh84un1NYTba0l5+n/SYoEmwZ7DQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=XQfv//rczM5vqo7lFkvCTnYNPan1lIL3rpMVGRSMens=; b=oiTmptT/NGlZ3VJ2RF56Ro+8oR/NwuVMTm2gKCnrMK2ZLqYWxQ9Zdr657Hd/GaW/RRL9sU5f9nYB4DjqDT4sqU4BhQ/UsecsZQmUjCyjq1vH9gK6BroAbwLC6MH8dkA7C72wG6LWxB1m5I5bZdsfKHd6u19uebWPOVsqjMs4Qzuir3moqsby3VKZcd4b66TfM4msWfjyIQ7KznmwKyzrS8VEQqZpKFzYBFqrSghu9QKctHDDhkVCqdhfqYAeQEVm7oWnpOLS7k6y1Udv+M6y25LGVVNXb98bCo7ZgyL3thGXaE4XfFVkb7yc/lCRmP4JIlO9m7pWeCQiZqX3ZqxPWQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XQfv//rczM5vqo7lFkvCTnYNPan1lIL3rpMVGRSMens=; b=K33wSdNE/vWIXWoc+71HN4Z9GCWOrj/49lI8wIF0Uub4RcbZIgO+r4+HGLHfZ46mXxu1gS2ZcvgHqtin9Ew9/h33+siIbgPQL6641zbUv4wtrVSIVJ6WLtHPpM3AaDuXxM2jG4fHB5Z1oQyYSc2+Fhg9JDjvzWaBGPE/A+QxaduNbZPLz9hHTCAp9IMedmjeaKchm32P5FaqoVevuQqHVKs36kvcnV06LCoFfSxVE0YcauXlpXbcA2yz0zKuJP6TOqJCdrlK9KHscGvnQBYUizxCqWTtu9bY0h41ufQPUl3hoRlknO3fSAQ+QSXZ3l0NXc+kHViO1FJ33fwRnYClCw== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46:10 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:10 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 06/43] wifi: nxpwifi: add 11n.c Date: Fri, 9 Aug 2024 17:44:56 +0800 Message-Id: <20240809094533.1660-7-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 93663ea9-5709-4315-2619-08dcb858197d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?fq7lwUeJt3FeWTQ7po2AnBeHrnhZUtM0cQOGrMdkye1Vc4vu4E5SR7EMGyLu?= =?us-ascii?Q?FZM7K5oHNnmKn9yR1zqgHW2EJNEKN+w54Nix5neLxcpijgZAYoCleNtNP8Ps?= =?us-ascii?Q?NjYPItBc1OM0FoxG1YqNcksW6xFD+q/yKALdeFZKKtc219e66jZpYoeYGMDm?= =?us-ascii?Q?n3MQx6MxPBP9gHifeSJZ7yEYG4hUYBGp99L9EvOQADTAJ/FSvl0qLRxgWp83?= =?us-ascii?Q?rPbZYZUYRlUDqJvFSDaVJs7HQtRkyZu9X5kKPZgLBIvUNCTsGAlnbsBvTR0B?= =?us-ascii?Q?rCeF54y6A7cDwcEQnk1VMLyZHx18M5jU4H7erKRPK519RGqd2m9UEEmWmU5x?= =?us-ascii?Q?mWPQ9NtJsdKXxle4dmWSs7rbYI/xD52KPtsuWxMh0gOhLOxkRTn/eSxRNLRi?= =?us-ascii?Q?0fBA5zg8FQ64LcpLyt4xImHdWhuySJlDitIm6Fz4uI5LdBnzu+Z5Jc0IUaw+?= =?us-ascii?Q?s0ODSMYGRwihD4FWlbHx7/58bBsR9cfQ5upf+GVNsRsYJLWV1SCs50zFaQNX?= =?us-ascii?Q?MKwGwXm3yAK7O8XGPzykPv9yHexJMZbFC9Eze33GjGvrtEjHdVL/Y3AB4CIE?= =?us-ascii?Q?q69xjrSz7V56eJI46J9XLj17m7p0JYqJtOB9ZNHp2AhnJaeOGJJsfea56kFl?= =?us-ascii?Q?0+XWWpXyGboR/Xb57yCOicxFpDYBkEYq2ZiO2/nZuBiJhy68AlSOhfxVitfa?= =?us-ascii?Q?yNuIe/54GEbwYJaUmho9LJK8Phm/2bcm4iDh/VxT0OBFK6xlO/d3HhmjCKDj?= =?us-ascii?Q?BMCVzve237IujawuUSv6qEq2Bkysc+Ty9me72qhiF+yDIPINFjAykWkCn6//?= =?us-ascii?Q?GzNTQRPhVE6KQWwZnLdo7qGX7Et2Fg0foQ3ebWZn+j7ulWJ7CPHtbA09kANe?= =?us-ascii?Q?MpVe8pegVgAWlofe0qAw7kFgAc1R91lfG/uTk3vBT80pfQWhWR8Jqj4t6ln5?= =?us-ascii?Q?+hUW1MLq6+OXT40GzErcy46KhIA6hNQn2+hnGwC3/hAFKPAdYOso8D1EplYJ?= =?us-ascii?Q?vPnz9cDCxZEic6VQYErhv3E7Eus7UA2u81q+gSnmOMumpc0As/SkjuxLbeH6?= =?us-ascii?Q?wcz2GGbwsL2PYK7e5L/lDdOVW3FHY+IvRkg3LleN72wBZbDAZswceGnaTDRD?= =?us-ascii?Q?WPlALF46KEj9dPaFO9Cg1aukZ22E2Hk0uZ3+NLuEOf/95WMfv6kQE0UVBx+6?= =?us-ascii?Q?Ao3RWnQqDIKSLf+2zGrRt910UfzjAbhNh79b4SqI8S1jrBD7aE/hPM4JZl/k?= =?us-ascii?Q?TQRp2SwCzKoA4k0Jylj6TbDUyS1nZVzk9NOKxOoOnGlubTMBBq1W+zi4ZPdl?= =?us-ascii?Q?lW+hxQYUjNQzrfpNa+01GWMhX2KT0K0nR6ZkbBWRRsOw1A=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Ac6UBPLT5wn0EVc3WyXDGBLe7f35U1pgbQQlC91H3/+wBUNZMyvd/l+dF/Fd?= =?us-ascii?Q?gUmPbvKZOrs+PxbRWLh6iDkRzxhllTJhV3VDLDuwiv42jxCS6V8/VsK7TcXH?= =?us-ascii?Q?aE1y4Ep7xl5NVrLLLzmkv4FrZvujyXPhzg6xL/EQNYFUcpn0aCqW9Yfbt8mU?= =?us-ascii?Q?KUIkveFl8Y3a8bQcnfleFFOKIIM4DSIF4ityTBO+ib49zmK3tPMq/Pvls7yi?= =?us-ascii?Q?vTShDUCw+YTp1ewA6qKVOJfO7PsCbitZJ3eeDMqbesNTsfnbfJ3OiJVtNNDh?= =?us-ascii?Q?z9I68zy/ZtdirTogjmb7ctXFKPNOpTF4xInkH9vlHTNLYBCiCLmrs5WJ2i26?= =?us-ascii?Q?BpLrOkYv/Lbs/agHuD5tp4KXlU9A1QIE8Yk9DPLNAXp3LVz0BO95vH0ZhSPS?= =?us-ascii?Q?1evumYoubgDC3Il0N6QXhbJEStKF8C0USOCbbVZs4skkoko6reTIjHXVRFA9?= =?us-ascii?Q?CxmmWuRs4+wj8aZ0ywz3KCbydUzEg5JAUjQOk/3V98EdArbLSGCjtctvEcpk?= =?us-ascii?Q?RrtcNGbzqEaMTk/Z9TUS6ZUSiWHwNtvmjtUY0gnIyc96pVvAwI5LHrIfLbTY?= =?us-ascii?Q?4bx1b94NSNBSaFiLDqzNqnmoz5lqEkHCAxaUcaw5pOKhH7BfgvgTOE5Z4EsG?= =?us-ascii?Q?miWZb1oMaC+4A41Pk2wvH4DVR4TAQOIh6ywBD2WGleSLjHCXQOOqqcKuKvfr?= =?us-ascii?Q?jLjB8YcAT3F07P8JKL5KUGTvxwzEEWjEs/fbSamfAT5uJ2NFXUGFOLR/BR+1?= =?us-ascii?Q?N2DED2GHeE1tyxbHzLH7fRBASo5umxVWJI2bIKHulHKAI9Q9WCp1y5enOELC?= =?us-ascii?Q?5aAnOSe5EytxZLCXe4Dp+uNBQNTFRk5SNHb9JtkP69Y8YzHDpGLo8koQODPA?= =?us-ascii?Q?cVbTOcJpNuohTNpzCZhuq2eolAArsST3ULfBDNDPaGDtA41SRx7rVZ/BCdMe?= =?us-ascii?Q?iX+lOAEI/SRKl6Q5o+fTkPrJgkO58AV7+kgTqMuSIDv2meBqBJh7XgA1v6AU?= =?us-ascii?Q?Pip9k2hg/vQRF9HOVx0VxH27M6NQ7vTcjQQ9gHUDDNV5s9T0vSY+3AagQFmz?= =?us-ascii?Q?PAPx1h/DHkUEl7Osm+XpYyT4P2UA0PBaUbyDEEvB15jtCf7w3mF8YzNa02vx?= =?us-ascii?Q?VicHoX+hG6nuDQ9Xr80Q8RjPcc85fYhJebuIBKTNzE+rjjza/PficojgdrWf?= =?us-ascii?Q?DMozDPqfC5ufkWhLGCX1boyJXWjwKlZvXFxrCzM56Ck1soyJGEo/XjIceebd?= =?us-ascii?Q?m2kWl/AQ5/Vdk6Utl0wR+UB0kei42KSZj8krtMOk/G7Ifhsr/uqtsJswWRIM?= =?us-ascii?Q?f7OEM/YNI6ixoGJ41ZHpiZ7Wug6rkGUhix3+n0zZg5Z98GW2Rdb9K5WXQ81a?= =?us-ascii?Q?XRgDHWUIC7wcTVO/OS7ibmuvfQVZZh1g664jnBjf3HIwyov/PBRSAiKHGKKP?= =?us-ascii?Q?Qrk8sYCuBMRYHrRe540B8dh/yaZ2qEBeDX/oepzsUh5SC3FTMER3tbgKUjHJ?= =?us-ascii?Q?sRMVZjUNOlWtU9rq2taifcGgXzTM9IEx+3eyy4abx4wlUJftn7eUPok1Nx7Q?= =?us-ascii?Q?BaFz6WJN3t1uscQx5v6piJW57XJH0qkEQlr5DgWGF738l9NMfh0gBuJ4k1Fl?= =?us-ascii?Q?XZk4plMzhFKCgaOJ3iuaQnVWbmLOslC4B05U89MmEUE8?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 93663ea9-5709-4315-2619-08dcb858197d X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:10.5886 (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: C0UQKyQuUmWWJA+HONDBaaoew8ua82DSbaYOQiehdOquXkXds5E8iLRpHWnr9lz2jxJ5rUQlKKB5nM1pCxrxzA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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..b33d4ade184c --- /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 "cfg.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 element *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 element), + 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->datalen); + + memcpy((u8 *)ext_cap->ext_capab, + bss_desc->bcn_ext_cap + sizeof(struct element), + le16_to_cpu(ext_cap->header.len)); + + if (hdr->datalen > 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->datalen; + ret_len +=3D sizeof(struct nxpwifi_ie_types_extcap) + hdr->datalen; + } + + 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012047.outbound.protection.outlook.com [52.101.66.47]) (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 9A0281922DC; Fri, 9 Aug 2024 09:46:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.47 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196781; cv=fail; b=CQfSnJC4qjwb5G/b8TvEvw+5vId4W7H6/kRxD+EV9vSK84hGTKW6Kcn2fh8BQsyjKIoVznGydDpVXDAMEuLlP1oB5MexjQ1NQBIhHFiFN6/i1678vAwxf195gSWXYziYrXfno7xwcPGIi+6leVcDF5jtz3lO20NAQvRyz/Qu50g= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196781; c=relaxed/simple; bh=HmCvO/h8f91FB38TkMqSXKC1ZLseN1Fu2LSi9ffWw30=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=q9ccwiQdtRroQujlX+6kXlTwNbWfrWlUWbAUpB94288na0AfIlsDZqNMWkleo/eqaC4jnX7AHOjreVJyaz4pG2EHtXK6LPeVt+fs140h3mQfSv2ycXRmetZPrqui/SjV6mdp1e/cF4bXnBp6kSPT02OeeoFN/IABIXH/tWfyZJc= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=IERCpAIE; arc=fail smtp.client-ip=52.101.66.47 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="IERCpAIE" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=BKNyefCRETeGx9A1Ss/OTQT0B+L9MZuGuBMCyjzhjvF42jIioD9G7zIEoIbcLkzO90k/VJB6Ie43e7gDd22TqEwM+qALSuudNdyhPSNsZ5Ra1QgVCJsCRSeXyKBL2icQLfmKGZ8cexUeK9xkCF0DLvWq0R30EHzJsBe/sn04fesifD8K+MELpLD2FS4kdMRpvAGQmx7SotgzbJJpqrP0W75ciiU6ed3uAPokK/M+bxVMIX3OSeoq9UZ4pXU11HME/HIqynqkk61DcaJeIlInpn2uPWI4u50EUTBTpowTx6Iwu8Lp9tLjVjDzi5HvShshIBJI3W6EFDD6cSyJ6uUEWg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=pnoqNv9SsjBuB8ksFnZAg7FWy8hlM2Jgzz2zuFH81bM=; b=k422csFsSjuwiA5NX371907ybXT1BnNgJWvuvhJtYm09cVtKKGErdrC4yYWf7L/bCS6BMQKdbofpoRuX5FfhVHp0Hu/JINuXGcoNISlVw8/2LjxBxCYWYx2l75FP4ukhsNX1TifH53z+R/ObHd7tl0LlKvOdf/7MALvxv1J4Yehek2uaKQlZ0NGvJWhyaz7u/1WLdd4ZyEo6k2ubqMhtaWHU3HHdk2d13b4FgR6leJw6an1rL9leTNOlf+MBFpJVQxscUqAxQ9YJv51TOv3J/Q8nJXw7K1hOfrU1RI69u3hWwL1L5RrWBjL/rKhd+lOFY1+glkO9OkqmDIXY1/L3Sw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pnoqNv9SsjBuB8ksFnZAg7FWy8hlM2Jgzz2zuFH81bM=; b=IERCpAIEIDqhS1FybAp8ageh1udhdGidN+vPmK6qnYS7EJP6NYiedYXovVlSQ+ljNS1ZEWn5So4tTRWypclW113rQO6/ViGHNBCcBASY1mo6u6VrWT51xfEq7oXB6DQUpG0PC/04SkwwfZW4XPBz8LOYQBEoErV0xf5o9GHSGy+uXYl2YMUyn7pL4I/fa+mT0JcHmGxoVSHKjG7kieti0BeAhYlovVaZo3r43HVg3n7GiceI12Kmd7bnE37l4vgHmGvJary9b4SU8Zcoc7HHTSurUr3QlpFySY4SHNnGbbhoILIRBfpul/hWg+fJ3ONrQ1iMhEVPlFmRluy4LCMY1w== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:14 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 07/43] wifi: nxpwifi: add 11n.h Date: Fri, 9 Aug 2024 17:44:57 +0800 Message-Id: <20240809094533.1660-8-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 90bb5ae2-1267-46e4-bfd2-08dcb8581bac X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?lI1pzkn3f9HQs6DQwlhtSsZqMVwp8h9birE4g4mvi+whTYbEfXoqSH2ajCdN?= =?us-ascii?Q?63KUg3W0ItlmprKDeyV010l9s6B3wV46SOBxWwj1ogLpafEYJ7lAC3mPApNy?= =?us-ascii?Q?jjUyoUOuPnelPSFvDDo0bCskuWHrjkZICjOql5uWMNw+4NTMc5el2C+qmR8+?= =?us-ascii?Q?G5nhiEAnYuW/Z8AvsqfVi3o/bQ2wnYZkCVOWELlgQ78Us0xBMioavC2apGqx?= =?us-ascii?Q?L5f6lZpwNpxZeM5WcVseXLrxFtcWh7IXYiwIpyMnFnjNjYQ7ut/nS25IvmVh?= =?us-ascii?Q?9sTC+Jg3qjOI9/6Zf+vTd3/WaAcrMuRbuFoguEqDDELdclmNQ3RHr7CInIP3?= =?us-ascii?Q?gMXaINtWUgwOb25/LvVTy99S4k/it7vyooFf9czcYOdgcpOfcr/GngrpyYch?= =?us-ascii?Q?cosAWk6WF9IWV08USW7h+KMcyUm/idFWfXNTQtNjRwum+GlNzKDQ2/n4BiZ6?= =?us-ascii?Q?QbZ1Yv2+VYSWj9pwD5UcHaBcmOjEzDyOGEfE24qacoTX3f2JeWohYV9XBtWl?= =?us-ascii?Q?yimwJge1S3ivfqWjzzPtOhxrzshKz/5NA+RMNsEmzVvhDC+FleTB/flodCr4?= =?us-ascii?Q?QxdmK7z9hvRZp4iqY8VHDbGIcGxBPgURWp73k8Yi+EYW9igubWvkVNScOqDL?= =?us-ascii?Q?DqT/pFY4bdt+tja/jQCDwf9V6mYr2uWi6jueOXmAOtW+sac4aR+5QkiB0SEf?= =?us-ascii?Q?VdA5hVGbb501IZ9BjGVgEOsjnoDf435jA4cRCfVX/dkCqDBXJGbZ/jV2PS8C?= =?us-ascii?Q?g/7OvHJlhEAarFx7rfUPZgfmD8eYKI8AUNvG9LwRTPaZbiG7CThDk7ssjsuo?= =?us-ascii?Q?rMgsTopNYmxYwazJASTEf67HIwppHEapICDcM4SJedm8t96kKGtkHopftI7u?= =?us-ascii?Q?p9Cs5H/ZheaB3RtjZHUwZAUtyYhECiQbZvmYGSdWNeYhAGZRX274T1uCRcZF?= =?us-ascii?Q?Db8GpFnu4ZfvewwxeBjw7Y+Xi9NRMmOVq8dpuqW/pQuhjwVWfRBqgjzgKGka?= =?us-ascii?Q?XGFefsrSxOLV9jbk0bSraiPrHb58bQsEHVrC0AQVUKabraGteHjjomU4iCBc?= =?us-ascii?Q?k3zpNbKn2Y7fZKBYpTWTJ2rYcDcmrh6jQN1Y4350QyhWvFVQiaSQzIcigp7N?= =?us-ascii?Q?uzv2XNZueY+yVBKqRDR9tp94CiXs8RwNNkqYce9UxDTbK+r8ACw/m4oxFkcu?= =?us-ascii?Q?kYqAzzKKBIJjK8UNYJzcJaHZJNIrObP0CRbif6cni0YH3PARo35V2BGFOqyJ?= =?us-ascii?Q?2kf3K24PMcRDmW3JWDaw/kfJp/XttgqEBHNxsN+g4dTFenqWpIX/GWs6dbi2?= =?us-ascii?Q?65mF0TnHeckYbIh0IiTf7y+uyYyiS/1LSLjNUn+hDvAyxQ=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?YCMXDcHdJWqv+eXzs8u4b45wGnQmWIDafjWQ6fIi0eu7mLQciHWKqUzFojUW?= =?us-ascii?Q?pJbj+HpyKidCuP3qlH7gS2uW3dY1VIY7qXiG2uvbDN3U+iHfUiQGXH11ardb?= =?us-ascii?Q?katUiIZaP6orWYvAB1ncpaC73BCdp6eT/sm9v7QCo6DNLWrKkphrE4KzBLOq?= =?us-ascii?Q?THrIcvH+Kb8Xn7m1SjfSTy6AtMlt+PuueEXRGuPa5TTzaTHeLLGqnEinxXRM?= =?us-ascii?Q?rkkkj1sXXTZc0S3KfypQJq1uIqItb6iFE8OEMmYrhnZwJISu7JQo64V7dC9e?= =?us-ascii?Q?7Aj0Swtz+okUibVn3Kj/etlTApmGPuc33o4+DlwZ/9LVTRkaPGJvK1W2XmRM?= =?us-ascii?Q?6O3X3Wo0GUYjRxmMWagy1xS8lMXMg5LFcPvOcdHyYbdsOu+HFIpB6XhCrr4w?= =?us-ascii?Q?gYuRva6iYiarEHxUtmlMuIhF7Vckhe8ZK+uK036MAtBbkh93Yc9VAxQcCFKd?= =?us-ascii?Q?PrthjWnqt0bQ0/hX18Nkb9iWB4/D7FI7ZwAFDX4k+55MUkBWnkuwEIvwoMDr?= =?us-ascii?Q?m774kC/NZkouefImMnQyg3vVsEZ0W9rxdkW8FMsvuLV8xcjSY6KWY8ugRo/Q?= =?us-ascii?Q?mHA6bQBIaWm08JB1iqqCRTtkxNyWLwAmLNrOJCm8T0I40djxszMq/7GWToAB?= =?us-ascii?Q?A4LkpbWOKWTV3A+nN4LSNKXNIWMrlXhAZPWufj//kkpXKpqwACxtx5SGcwga?= =?us-ascii?Q?6Q2hFugkLZ/YylU7QA0L3Oiz+EJxda4T25LAeE6BTmEcjiIx+cfUIQ1OJqCi?= =?us-ascii?Q?fcsnBpCkO5s+3ioQPR8/bQgmgKM7YJJ7zNrSXlg11351x6I/K3dxv3E/z1fR?= =?us-ascii?Q?LJC7TcPUN+Jji05E+dk7Zmn+z3DQDvgw3gIVhnP5WTPoLqoDOwhC/YjxhpS3?= =?us-ascii?Q?BurqluAFAQ7SFuS+FeW3bBaK4f1jFqswtNe4rw7ALyGOm4f/DCvBJ1VcE9wA?= =?us-ascii?Q?lof4HVf4z5eRwLi3n/qnZjV0lebZsahldNLzE0fz6uCkjDXQ2P4OqbqMbzW9?= =?us-ascii?Q?+9TXdDdkJO7SA90BEsbfIwaTX0CXWCKyfCy2jl/bo3rTgp5x0L4NS854hwqO?= =?us-ascii?Q?veGgl0NGK6CRpGHFoXXVYYVEe6lonFt/OnHXhU7xR94ksgJpGRWWfzakUOs7?= =?us-ascii?Q?0ntpiFbj3FCXxmw3ephOd3HyUvfilnto/7VSDFGj9YvGtOf9QTYaoB1kQEiW?= =?us-ascii?Q?KXOfd8b+XxPvuW7jmwP7hIXFKmRayIUJ9DeBsNuCAapK2f/RfjimWflgxz+0?= =?us-ascii?Q?C66X41LnmcCC6HiUgrRU88X8Qg73Da/AYKzf0dVurFE1H5/fz3KbmKlsI6pw?= =?us-ascii?Q?56eDu5EU6wPOXjdvDk7850iCP1xrnUHOc3J0LjygCtzogoh3oCiHFNYoroBC?= =?us-ascii?Q?W1AKSJJrzgh+i9yHjLyuwFEXpgGnZKynI3MO77jQ1tDdZ1rwYGTAl6OqSCHY?= =?us-ascii?Q?082jDYNuPzrGUm9VYqCR9N5I3gDAfNJ5YB2L/fsm+jC846nhjtb4d8Ad7Stx?= =?us-ascii?Q?lv/fim/Tg9+RhIA3moxJ7+nQxz/QsKmSc9w+fyxYD3SOofnAll745rSmHxiX?= =?us-ascii?Q?8jFxhi3bTUi8DHf4sJgPU8sx0SuZTXx2qEaZ+ok+Jnu8KjuwJbuzpXoKz9IW?= =?us-ascii?Q?a6rJE2e4lhLsdagqFhhUhDMY/6kZIpcb4a2pryIy5Iv/?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 90bb5ae2-1267-46e4-bfd2-08dcb8581bac X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:14.2151 (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: 0ZzDcDq+//xsCa/xNSsj1N8XJmVdPBWbOkc0igpcQDVxqPFIZxJjHemv9A5qlE6v46jdatHLuILaSmyL0ltIqg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013064.outbound.protection.outlook.com [52.101.67.64]) (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 5207C1946B0; Fri, 9 Aug 2024 09:46:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.64 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196786; cv=fail; b=RsnuwvPFXXeGGiNYBgeK0zikwEyyhouJ1P1swkNZSZMzk4mctOXUT6RPaKcUZ3sx7eFQnk1ISaE4iqYK2oYELi8bDIP4/pDhBCmVU/4xzM0KtuJH8e9/2Bncy7YLwakAnhX1udb+F386lLWGvaceSeDomGsb+MhKHWbebS8+gfw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196786; c=relaxed/simple; bh=0CNz/25GMEbYYcYQxFZMmI2LMbIHPk/SDKijvl7H7ZU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=YLaQTaimMKYgQ5xiMUG8zIgMhzSQN42wwJ56p3pYz9qDM8oAlPerklw13lg12R9XXgh+fiKlBBtKOPdEbMO6NHvUUSCTGowSuFg0CZDIJU3D8ZrtKdZOIU+sSbXdIv0gSNmpddTb1xBw1T1tG45gF2IcYsfnSuSPtzzXOZ1xySw= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=V4HgpJie; arc=fail smtp.client-ip=52.101.67.64 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="V4HgpJie" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=j31oXp1EHB0NpFv3KFnWv3MuOgIGKK1Z2u6pUrJqqtoyJoJgZkwrGYvvT6/urM+MlA69BAYQVi1iBjo+nOJAwot88Gqy7/pUJvmjxEq2fjT2hFkShbja7paI4AxyEqkb1gy4Nc+tPgFLInNHWHj9FhqVmYwoRvN9biSj/xzNxZ9Cd+H7rtckPfzK8wUf8qvocQVO7Xjv4xXIu4zG2jXbfxdsUV82QaHSOXDIN5uY4iIhJAsGyJEznRkNI0mbQvM2+8IuYHstNDL7Ht6Qofu5kAwNvPRzHl9n8XJflt31cx2oWIpnI5yORYEEBRPTkt9zS5cCYZrcS7Cnepw2hfEbeA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=J2DXrpx9hmOlKQwsxF0BPP2XgillHI6sHEcm28UpmPo=; b=R9XeDCh1eFUrpAC8j0N4ThLdS25KYVNeKfnOCCAh9GEyO2Oezq2U5rp5UmTbh2lSHTBnM3u1fkdGi+sd7UwG2Ea5KNHARyo8yvRqVxyfmYuioSOxkPQqdhbs3rq1h3Ysc2ALbK3O0Tv+dB5bZ5u0tOzFCI0bZRXZs2T/f14eOosUHgohiyLuO2PtSk8QJG/B2MuosYLJsappwWJ7H6S4MhDyWmHPlrmWHKtPsNi0+k4WPZWEm/qRh8cGI2ERVX/Gkqc3Cza+fWIdtJxSdiI1ngameCDdsDXFzL5Nu5IWIlVpyXR4+zR5Lw6OeUKvDyUPfZcTNvMd3swmgJVt0iZn7A== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=J2DXrpx9hmOlKQwsxF0BPP2XgillHI6sHEcm28UpmPo=; b=V4HgpJie310fFThknTLq6d/aD1nNh7zvimA3SvCikc6f7uLtql5HScpPyBBWDnkCBgMsI6qZnm82EBAfhzPwloDm/OizZRe/WS9zoqapaLNmsl7YImOBZjRSZz3+GaMOQB7xx9e22ky4F2jj7FcYatacs3J5Omfhm8ljBy2esnLkrXKKAPXb7V4ey70+eNErDYmNxkb3cqRR1tuXOulkdU+v+BzUEVfC4Jx88v0aXJPIQOtlQYIdQ0bIinLAnI8JcrlTZiR45w/VuYvxu9ivmV9Ys8nGjm72gzOPqDj3vJkKdL6rh70tyC+jORCuJXjz0DXORxwZzvSeYIHSBQfL+g== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46:17 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:17 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 08/43] wifi: nxpwifi: add 11n_rxreorder.c Date: Fri, 9 Aug 2024 17:44:58 +0800 Message-Id: <20240809094533.1660-9-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 38994b04-bec0-42ef-7893-08dcb8581dac X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?88jhYau1FLkjX3Hdb7RPrBTumypvtzLVbxU3CtizH4+ewgmYCbMitOX3tJ+P?= =?us-ascii?Q?3aW+Wt0nLjYFwKKHYvDvrFo+BmqHbyau3SxH44Pi80d7g6w1jJOw6zAOzocq?= =?us-ascii?Q?XO3pcWaio5wIF2ijkX8RogFIv7QjzfwAdOv5bUKKNGvN/guxhp10oKhyGKsG?= =?us-ascii?Q?PbJPMHlbSpR9xmGU40xsBNJ+ZBOGsfTnvkNlgE0t0dyqbjtHfClZXfl2lM3K?= =?us-ascii?Q?INZVXZcJH4l53LuKfrdB7uIea09JbsACqozQ7s/XVQN7ohN8WaKAUWiss8fA?= =?us-ascii?Q?IknhcdLH5EJemIJ3GpF0UxVXSSAFx2L6n+lQ1r+ZHtwUDeK62Qvx2Dd9y66m?= =?us-ascii?Q?+vSjNibWTlgJo/MyGlivHqkVQ7cyTgm8Ylszq2avXi2qOTsjk12nn2UjBod7?= =?us-ascii?Q?kxULOd+T5x5RPdCCmjdHty971yG4kVlemvmpevaotoPMhWO6O1WO5MzUBvyN?= =?us-ascii?Q?DoiHttTNu0wA5LeTUkXXhQuAz3CSnmpACrq/aIt+6vH34Hs8uL8LUzFftdUi?= =?us-ascii?Q?QMwZkzKHWBAMhbm1YQfC7CR4dmc43juzjXp3hPJPVS5Gn0rpY726NsMMra+s?= =?us-ascii?Q?+52KeaKbq2Vnqhm/ogz3tH4odh+4mKPDZj33W0YlWvW+9OsxBi1SwoHyHyRv?= =?us-ascii?Q?1wsiIx/Iy8RKnjCRU7emjDMDSloLIwMjaBj+KEQTD0SFLq1epopy4AWHg/tW?= =?us-ascii?Q?II3jGVYzRllbVoxtX4VqOrTNlyYEyh5Vi8SkTAjlZwOmxVbblVmsYYCdYBdk?= =?us-ascii?Q?hqDE0SvEfSzuCup9oKs2+2mhDi2Z1QbDMTz+nOezf3w06D1hxVEZsTNyGEb0?= =?us-ascii?Q?guWOCQ834ZU6Pj6xKop4mkYNp3VvbJWOWWg9X94a/OT7Yte+0WSSeG6UXlki?= =?us-ascii?Q?8lhMvWNtX1nbEGQRVR6c/ARXj6DdSpoWOdhJSvZWU3jAtNmHSDeVoaTSRX6j?= =?us-ascii?Q?xmP5mdL60JbkSWhZFY60vG/C6X7iAaCVMl6uimR2TJ0drA2ICz1rfkJ3mVMJ?= =?us-ascii?Q?dqgv589KBHKSdcHNuHSUOHCwwCU0J6dhI9RjY9ojE2n4xh9MkV92PpzUHvb5?= =?us-ascii?Q?/KREimDaG7ePTXY9VivOxIO4Fd2gPf8qz6u7pUwaq9jjx4I2BiwFMtHC7Bv4?= =?us-ascii?Q?F5o8GsNNV83nwnAcI8dgPDxyhyODPeJeGSYJFK/6GM1KJJRp27bIIpmhIt1+?= =?us-ascii?Q?qMTygZCgBFkJzJfLv3VhEH0OnzARJsxJRUj65G+o8/z30ySYy0bcpSvspW/1?= =?us-ascii?Q?eH8AsUaMtj47AU3/RWVIqKIZJgCeI8/S3TLrIP8JqZghmGA9yVWBjuERcXbl?= =?us-ascii?Q?02kj4QLKm5yo6K+e0IT1+TDAv7QMt90DIPuD6uafJTkS/g=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?wmWkmjwR+10DkQFXpyHZRSXEuzzsHEM6X1fSP0gGRa1NULAr1LovU7KqH6KP?= =?us-ascii?Q?hshPYttVwSFvnnIMpVL7mSc32eE6J3gb5O1RPYTaOYb7b0MBhI8pQySOdpoJ?= =?us-ascii?Q?haE3JgHfyjOcQUjlPXhjV2A15JmsK3YQUrziCpqKwTS/JMMIDRfUV2I2DawC?= =?us-ascii?Q?hQRJI4X0bWUyi9AoFOqryS8Kj44e/z32qnIbp2xAZJHCozts1TuBeLHkqsTp?= =?us-ascii?Q?qrP9r5e995VBjSrex7oS3u4bV3IeWGbS6ZZtNeC1SQHIMF/FZGd/Vle2GyS/?= =?us-ascii?Q?53NaWmDcyJJnsRlhuHPUC+iS2svWQ31Rz0o3xR6VQkdCBwX/fPvZbUug+2Qd?= =?us-ascii?Q?Ixzm454qvuNsIQozSfJs9n1Y697Xx0XPaYMrf5q97HnouPHh+l1cjU4yZRPj?= =?us-ascii?Q?172OdfAtauw1A9ivasrTQdKMqkypfTlSfL6qeKj5OQBLkfZQC+a3CXRK+YZo?= =?us-ascii?Q?c0dOQvNjxGYzHaiLIS1QBG0kwNEMcPfGT/+UEkA/1CeHWfTqxD4ARDejmDQq?= =?us-ascii?Q?BhFvP9gZLJiM5pjWLrXqkRQjW44nnKQ/R3gVgxWJduYtpXk1cAvFj+CUlhrf?= =?us-ascii?Q?ggkXo1UoKNliqgHAyheh3xaHH0b4DbIXgiDNxF9CF+oruSSq9ZOk0RAlgbyk?= =?us-ascii?Q?5oHmHDuCOdjaz829CVlutFed7Achec/FB1jDilCRuphTluWs4UZABj2ynKf/?= =?us-ascii?Q?hDd+3W84N08HVY3ZR/y+hWHnGbG7qWFfAXdqKy2xuYVFSG9uKaSltkz5r9Tg?= =?us-ascii?Q?edu7FUzmjSiuVIxnKmJJ/BJOTyNtounA5VY7v4nxU75B9EFOU9bOl7QsoZHB?= =?us-ascii?Q?usoDEl2oxczdGUC8d3RvMTKrj3GT8Qwd/c9jq1uPslXsypIdEfL1YfbJsNIm?= =?us-ascii?Q?KQAsueeY+GY6hcgVPgFmE7ZXB81AnULzPSc/jtHuYsEIsHbuf1s5gheJhtAR?= =?us-ascii?Q?WPjgKICemQE7xOZSbTtdB1xJsNBKts8IIqO3BW3J6pOiUnSs+ukx130MqP/J?= =?us-ascii?Q?H+FrR8soY715SHvaCnklkV5OCmEeiLhpaA1IpuPJfvjGemUHuNYjwej93ZgV?= =?us-ascii?Q?yVzbyYrPs7CHx+Lg/T3A/PQfjfRzubPl0m/oITnMdWs63AmJaHOvvL1SCgtw?= =?us-ascii?Q?+ZAlLFYW6p+zRhIFJsTmkSfV3n1VQQUEw5eRB1bc/JCOt1rOtccVK4uLCykW?= =?us-ascii?Q?ypFx/ctpKFD+3MQzw5XyZJOhbjfxZrvV3i1w26JV+eyNHu+8b7YgrlIIWPLy?= =?us-ascii?Q?bmNp3+tB8X2ghUxqmQjiAUBDMPrZuuTZh1756qI4OtyQxFZuO09FJ0Qg7lak?= =?us-ascii?Q?NMW0OdtmzaLZKuyR93+7XzkXoHt8xgIt4ouD7eJdi8KCoIvl8VyZtu+Tw36o?= =?us-ascii?Q?lB2W/6urM4KosmeyKng0Qq0doOZV890Vo97uKwjCbkPJEzIoRqaE9ks32cFO?= =?us-ascii?Q?jHezr0CsEzup2HuMFh9VJ7R+y4mgqad/ozeX2sSd35SZMI6Xx6Lp9psRumNw?= =?us-ascii?Q?tk8xrMvoQ5AL2KLFmRPIkgluuywi7yGLfPc6QQ+YxV/1Lu8Jwc5om5wy2drW?= =?us-ascii?Q?Yq2z/0zC+UhDu6Aipo+Mna9RY2CEPGyFEYEJb+uxmm7M3OyzxYtwcVxX3q9o?= =?us-ascii?Q?dkYTTSp1VSGd3Jfixp3mOfOBnrjv3KuX4/iLBHstDuKp?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 38994b04-bec0-42ef-7893-08dcb8581dac X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:17.7702 (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: w1g/fVQb+GWBeLxoVNzQywbI3VXNNeZpxPNe9iiWHurM/EBcxY/wA5eoTPeXy5SgpdQPHQxGonoEyVaZDWbqCw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- .../net/wireless/nxp/nxpwifi/11n_rxreorder.c | 917 ++++++++++++++++++ 1 file changed, 917 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..f0407269942c --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c @@ -0,0 +1,917 @@ +// 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 "cfg.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)) { + rx_skb =3D __skb_dequeue(&list); + + 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) + nxpwifi_dbg(priv->adapter, ERROR, + "Rx of A-MSDU failed"); + } + return 0; + } + + return -EINVAL; +} + +/* 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) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + int start_win; + + if (!tbl) + return; + + tasklet_disable(&adapter->rx_task); + + 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); + + tasklet_enable(&adapter->rx_task); +} + +/* 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 -EINVAL; +} + +/* 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 -EINVAL; + goto done; + } + } else if ((seq_num < start_win) || + (seq_num >=3D (start_win + TWOPOW11))) { + ret =3D -EINVAL; + 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 -EINVAL; + 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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013064.outbound.protection.outlook.com [52.101.67.64]) (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 A039F194A42; Fri, 9 Aug 2024 09:46:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.64 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196788; cv=fail; b=PYtgj0BwSunGoQrAr606c/YrvcLf6enAN1TLWIWvbaeWUmM05tOA1k79AGNwaFTNKO/9F2onrUyHaJaddE/u9L/yy1qOSfZfvstauypRDkSGDjC9/HVWnFtmtR0Knde4tVlnxO6N9YCJg+OUczCnukAzYRw56ELucpyBLToe820= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196788; c=relaxed/simple; bh=znWLtTkFM76wGBuVsUdfZMDp40n4XqPUorbBvxwHMzQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=i/qTn164bIOYqyzejsmszXJkAJEQdZGvvrQdtuDz7k+K+4IB1Akbr7KRT7igCcf0xGJGVixIurJS8V1pUV9nWySRCuVkXXBIhf0OuvZ/bNoCX0Ebup5SQQHyHknbjarpmtC5zy1v7wKwCTQiYbGurrtmLHZ0AzWK+zY5UhH+HLU= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=Sz2o6YZY; arc=fail smtp.client-ip=52.101.67.64 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="Sz2o6YZY" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=FbonYZ7ke312MdB/NtTbYwZ8+n5d35Y2EmOdWHxlfjdQpDTkUvil0IEd2dxvurLjY67bSj1F0htx2fPHGNqGACP+0GY8nR4BEN3xjS8tg3tfmsiIpTWimImBbRHMfgbm/kjjXOFmPxDhoOQwrtizLirRImwU+btd3HKmsWa1jXNrEeTvOje9Htf8mQGZPElC4+qN64Ix9jn2jS0H/cePLC9SkihY1iAbI3ZXk9/X20yUYToFu1cE8zzq92vMg12xltSIXQ2FoRg9P4hdWlvTFkMpykT2mqpSCwvO3yBuvQzpD2TQQB0LpX5GSTNO5fNCQi5uBC5jZfSEU4qGZcFgOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=D3boSOwEh0i1qO6vUWvAJ9pNPb0xhMcSZHsWqmugtc8=; b=dMruA+ySyZLbajpAsoeTM9OgU+om5hyxWSkVNenb+jZ8daCSpFZ8yXPvBd0Xoio5bbWxgMYoQo6d7AXsmd1dq+iDkssd4zdem7/YIEtYRDoAeVNJDZKOcZwngeazcQC4w6nVnOmuAna0cQ22b6xwsv3kyNp9D+zKWXEvBlHx3yt+oKY1SQc6PomZtGvj4ovgdTK9Sgofeovg13mmi4sioUKket8I93EKu8rJU+BRpQhbAcc6SGXHb1ZYXSB+UZHFTMAFJCG9zw4Bp9IUnjmjHPI/6Yd49/SWbNgHh/w7ZGHgQWevg1hEyOqhenT+W51FDEPayhJtIvTphwGZkNBU2Q== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=D3boSOwEh0i1qO6vUWvAJ9pNPb0xhMcSZHsWqmugtc8=; b=Sz2o6YZYm/9g/K5ITQfyIEwLcHPo+LOs0EhdpbAfYNG0GJk5yiMybxy/wYd8Y9a5dw1meU5+33yfb869NjLEyjrWwrd0HEKebOIhvhxcJNuBlZS/1HYJmzZbu8CeHSpcYmSKb4L9MorNAPNEMshGtxMvkNMoWzPfA7PZfJfN0cnhCmvlFXJ7+sv9b2jqoc7KCLdBOjRJ5C55NK6oBx+kI0GETzrdeh2e8UOiVMn59P7/grY6DRZf0Yh8Ewk1T6teTLhwYDnorwYGZ3e7xu4f12SqGvDpWam+39gmV7B50LFRrWN3CLua1fWLncrYerFa3iD6TPvng4qLkUSt8nUGFw== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:21 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 09/43] wifi: nxpwifi: add 11n_rxreorder.h Date: Fri, 9 Aug 2024 17:44:59 +0800 Message-Id: <20240809094533.1660-10-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: db09b283-f7b6-451d-76e5-08dcb8581fc6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?VwTNdyct9c6w4Q/e6lhNSwtSnZCQjGsNkJlFmXbSkZw+5x1if4TgfhqxXvhZ?= =?us-ascii?Q?FeugWE/PxG5l05qKRhCklHO7+YgiA5v4c9jACSoLZnq7i3dc1AzN6irAUG37?= =?us-ascii?Q?GzXXTMq1MYCcsVK/rFeZ4+zjrIZKo7RCKhDIM0bhZRD6FqKpr3k6oHawUc2x?= =?us-ascii?Q?oHkILPdYsv0bvEFyxif8hOBbdH12lPEOqfILJtirUNaxa642qdkTcV6seB0K?= =?us-ascii?Q?0a3tqBChqWinKwq23KMMGSrdI2ZV6b9/P2+J/fhxMP0eFSuPdNbop2+WiDvX?= =?us-ascii?Q?1C1JEoFHFLKg4GsuGg3mm4Y1eDcd485pH8ASyQBKqjXmTv1YvOEWf21hIrmC?= =?us-ascii?Q?vrR+9k2PUe++Mh9Xd+Kqn6AoYHN9EGRsrHMt26mTqM3+C7YycZdJIDe+9uoK?= =?us-ascii?Q?rmAzAgZ/eUHkYSP42+GNFzRJXOoZZYDVlFE6KeHYpOdv6I8FFNAG1ZXWht1Q?= =?us-ascii?Q?P5mf6JCb+eNaJ7BEERZ390S7c3YLCyhEqNjVel2TvWjQz8dIGBJnKbiaFI9O?= =?us-ascii?Q?xJmWIIqC2tqgy/tYBSoMdrGPGWhMhj8wkDhrzbZkjJ5UesLkhFZxSxZDinir?= =?us-ascii?Q?0StcUZQjz+n0CZbY1frnxjzkL6qthPWP2AtbLOILBfH6+tbE3Z/hCgUPzkqo?= =?us-ascii?Q?61/WUX5E59EhX6eDYfGXNN3KAW4C3n1MeeeyZCHmhpDV8wjESwAYmqoAQTjT?= =?us-ascii?Q?WRXq5UPf96Z+krnrblWDnXYyXbbRsrX29E7F3OkQdJe2fJiAzoNh5Q+zntMd?= =?us-ascii?Q?+IkA+Wq9GS0n8+zCPm9ZHByj6urrkYvzF/u3DNZqiKqLFF0ey4SsnDjx7YB3?= =?us-ascii?Q?BBttgJ9ghF9jTsRrULoIWPNNTZdhaYSme5g+Hb4g9gWFroPJPRJHSyMXxj+W?= =?us-ascii?Q?NUbVof7NdCCdAo+/ypfKZU3WsqXj5D5rKvdav4nhasIyIOdJMECDZWEzkSHi?= =?us-ascii?Q?otT8MFYho2/9tz9fpb6XeLqLmMO9QKQOB39ScR4OwyluKPam1pbxM0VNrY05?= =?us-ascii?Q?uiGi42xVj43TpefP8cFK8wG/ESWzbDq9mKRTnbbcHDLB7bCqndEUZbdNBBBM?= =?us-ascii?Q?q5N+z6vxa+O76qKUXVBzwRqYd/ADyEh59/6kwlOdFcIqOcIGyZ5o6z4GVO/k?= =?us-ascii?Q?wguFwbm3BanIZTnAMAVX9t5OYgDMArzUp2NNNeGK3fqJ+gHtODQ6Ee1CKAYJ?= =?us-ascii?Q?4PlauXRitqr08393BA9umyodWPIOhLwvXF2jQBx4oNgcxBvjT/kQtlIzUuXE?= =?us-ascii?Q?VA5DmOjrRXlh52m3LQkWuUQliSyOYTfW5LyVA7RyLTC7WEfaDXuT/QgoqIzV?= =?us-ascii?Q?3NgL74kntG/v+G9ImiroXxJctJR8TMIC6BToKZtP9LDgWA=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?YW7VxbQSYrl6bC1s5FWN0I8CwvfUI34ig/xPfmTosJcokBhg/3P7DguUVkI3?= =?us-ascii?Q?uNw8Cio2QHD/4ZOcjfNH3Qm04zXcZWkr1awv8fXvhVCupd1b+M87oR50dXty?= =?us-ascii?Q?+9//ZuqTCdpAnzJ7qpvR43oVv9Qq7bSntBk5HU939tFHzgkc1CYmx/EcWVdX?= =?us-ascii?Q?ewrR3AVyei9/LwMpbeCGDQcSOqX0MAcXFufq3af3MOYAWo2nvbfsFkAEfTid?= =?us-ascii?Q?YG3xrTJ+mZvwEJsxK6aRezdrnlzFidSBd5Fp1i1qGAhPlC19w//eV4Qw0wQy?= =?us-ascii?Q?W5/fE7FFN+VJRcA/jqJtuQAiDJUHWSTq4e6lY0RLmiMLWkkdX14RVdjOqWSn?= =?us-ascii?Q?0DYOoyqr0tqhA94wQnJiT7twtYPdL5NJ/YLx9M5oKbtZIwOoCZNBsxHGPBxk?= =?us-ascii?Q?dyS4XHyl+DbIii+k199LAiiDfkplqbsmzmtMdQRdXwxOQIy1XlTqrQL1DqFB?= =?us-ascii?Q?a0EN5KEPj2if65K6zBMetsEHZGc60Bw6XEk6AZ8Gva35KU05p0ax4LduKclj?= =?us-ascii?Q?WAVBSOiUD9Ga4li+WWVN1lxxY6+VQJFjkKcqI3S+GpesMn1zSg9tg0NVczZw?= =?us-ascii?Q?8n0OXNiAm0lZQ3pXELTevEm07c8Z0wMLFNCGYL8GojUceHpQNr0cxy6A5YBQ?= =?us-ascii?Q?TLjo5tlRIWkePkWI0QJ9c2IZiiLVr7s1hdi+zy65++hIbJKWKP/n6BMJjYO0?= =?us-ascii?Q?rzeCbQ0c3oEKh3wBEmkQzPDtZXd537BiCGZnopPtSEAqKihHOUh5YEKbOp6+?= =?us-ascii?Q?SA4IwPoHwOMdxhbqjBTI6Kg+Brold/vta9qtd84gO9Vj7lHsN93w311oZ88E?= =?us-ascii?Q?D+Gec56bQq8fZuIndJD6myys0vHECnLG9Uyz868FIJ8KJc4h5RbXLGYcs59H?= =?us-ascii?Q?qBUC36iWlMeMToVxc+jbZW96ASrUvCepTzuhv47mfSbqpt9DzbAlUJYQEl1O?= =?us-ascii?Q?pwERRpAAVYIr5f0KwUnBNH3aOZYRTi+FPCV0iGuZSiP620KfA7ZJpgvCGRH1?= =?us-ascii?Q?GEuH3AQLi49YhG7a6fXnJhinbNc5r2LHWgx5Yrwn5eXIeJnM4QO7fGblFWM2?= =?us-ascii?Q?zQ0uJOBfGZ5JsBKjl40R8MHjPoIYZDKhhAOKFAsjxigD7/MWTDszCf+EspmN?= =?us-ascii?Q?rBmf2xLKACZVhBWADwHGVZWCACqzzJoSj69XQ2a1xDVDDHmdziE2BtChvz8K?= =?us-ascii?Q?4vmZOjZzLEV9ADBfCwJPhPPmfJxFHeK5sYRd5yFuvbKg6CDX7H2D7L5ubxB/?= =?us-ascii?Q?MScuTGszlbUslBnUJ59fkD9XE+LL+CrMLdeBeSYRmqSaK6apHi2blfQkf4sT?= =?us-ascii?Q?N9tU1kvm3UEQ1O/uVXENKbly5HWqZZY9OV7+kyifJHw1AWk4HNszQWzC5n+e?= =?us-ascii?Q?vbOdx/Zp3GZw8CQJEZAgliIhkzRsZ5MSbL6UUS3vLdaBi+UTa502uOAdMJLX?= =?us-ascii?Q?xRL+y+nwbtjYkTgTgny8EJ/Qb5PhTHFcgeNv6o3geK7XCzD296+wBDyJa27o?= =?us-ascii?Q?w3ySmCzHObi6WsjNRdxIoX78Arfa/v7sC688qr+aYF9ZyyvK1UhYpeNIqLMg?= =?us-ascii?Q?V5H0C4OC8lQ2uh1Q94Y86bU9VQcbZImf+q5AOrf+2vFUbJZpiIh50RlCNPd+?= =?us-ascii?Q?xOgvl2i+FHPUOvaR8znpf0oIEW42hJn0TiLiQA8ZvyRx?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: db09b283-f7b6-451d-76e5-08dcb8581fc6 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:21.0877 (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: qwuax0rLl98o3pkjBx/D2u+qPW7EQuQwk9O8SzjX+Dl9W8qqPT+jDoMbjxA8Nkm+lL7C0320zLajqH//GnI1NA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- .../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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013064.outbound.protection.outlook.com [52.101.67.64]) (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 B02CD194A67; Fri, 9 Aug 2024 09:46:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.64 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196794; cv=fail; b=AS/FI94gfWPw0PPhTprxAEy/tIqX9BHHwXJCwNlQu3rSTZBwpZeUOxNuFHsE/DgPzx/62Mvg4PPPMeCQZs3ST2DPFkOcRLk92HJpkNsrFrnB8/DN1i4CEtPxVINLcCLU9NuhrwJYqdAiwVY1gS5h2YKqGPmXREnoGN2tmti5Org= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196794; c=relaxed/simple; bh=w6YhEyz3Ft4ZQHVGcN+11qn34mpD6bt/upb0H/fPero=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=NXOkKUI8ExKZhnVeL1uQDceO/X4pEh2/KJeLsbyDMX4JDYth8tUxJaTKy0w+4cjaiuEH0qr8psUuY4N+FqunL9urQ/e76nuAep/xqKyxHOcUpqlyXuX8wy4W/P4sDZvq4s1wikkVsqd5eYZjFRIu5V3MDD9dN/uDQldv1lofaFw= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=Ev853usb; arc=fail smtp.client-ip=52.101.67.64 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="Ev853usb" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ET+Px1zt4/3aDoFK6HHS82lOvWg0Uwjl5h5Uh2dX/kA3xSJg+o9kePcU+T9FIoTE07V+lY2ViuesILVJmPhepoPDelYZb7rePXmAEnoam6P0VA0iv6rXLKgwHDf+C7hoe6RrwOG/9VET1slK0EFejy9nuEfnUYLHVri3XZZDLoXVYSQz3Pro/jozx0N86IM/c4ycv5RJKJsJV2Mcf2zk0S21ixe7OSVpZH3y5aWCVVOjtAcueBsm4blP0Doqdc+eQnXtz7JtagW9Qd8zl6MRUYJOFymQg+3MaLagUqwTmAkPclOB2uZRXge0TeELOoA+hoTc0U/G1Z1XwZyGL/EQVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=wivINtag3c2Zhzz4gjuDvJiZyVcnQCTZaQnMb/2D8xc=; b=OPpeBk1/HSXMCXeA0k0CjEaiqxgHwis+WbQb5G8ILF6vclYPjCNAjPH/Ft25jASZAMpBTe6j999JdzvYShOgy1RKDYBTQTGo98REL2v0Aq7T+4kLSgNtFgFFjsbrZJsl8VQNxx9XYd1uvHYekA0WC5rsbBTTUuuab2aAjsp+duUF9eSYuJQcezpfBgBO1lFmhuPVwPQLAKBAbwj4QUNfJvSBoan4uhqqUCzBKxdu5GzN4eugqet2CvHH8vAfyUFavDS4i+v1q9PGF6q9b5GOUcws2Elxvc7451PEPJeSyC4E2zNAIec9GuLMI7cb7B7VjXN+NuiwJXcsTXCXC1AE4A== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wivINtag3c2Zhzz4gjuDvJiZyVcnQCTZaQnMb/2D8xc=; b=Ev853usbY+yO0xSC3vvBlNT2PFPIcJG4bqDBJ1xNDjjaZYpWdROl26QHxtNpN8jQugX1yJtfcIbSz6KwrUCv2WyJg67m0hfvBrvbpVXoVFswWUg4oVyNEcLFFGcBIFw8YjgL9nTRSQvCrRt3lltUVnyyHQ7Ib7Ir9gKHD+Jzs6F8B2oXlp0q5/EpN9/aA3mBsFhgINQHGpKwFjHktxWtgqxH23jmPQeOC0h3ozTeI+fn8wkZMNpxJeue3yP+vxPREFdzU6128NvY2eacVEC4sINAE5YGnB1ZLpNYOccsKju3YwM12pmpxiseL55xucSuqs2Hi3OpjbLt8IGLwIKFsQ== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:24 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 10/43] wifi: nxpwifi: add cfg80211.c Date: Fri, 9 Aug 2024 17:45:00 +0800 Message-Id: <20240809094533.1660-11-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 558c299d-c73c-4b76-93da-08dcb85821b4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|4022899009|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?IqEwbDJ15kZuhp1CYPuskKypJmuOEbrsTJ31pm/HIbvYWZe04YyhQ23WrRMZ?= =?us-ascii?Q?UDfjiIu0ODubAkSh/JgZTuWlOHZkVeM1STQDiMBx7QdzKzytdxnSrSqHAEAJ?= =?us-ascii?Q?C13+2aEF/KpjNHnfqYiXLjDmTGX50pkVpvccO9g5GgYeyJp7mbob8NB5KTTr?= =?us-ascii?Q?IDpj2qJNVyoK9m3WYSvuFrow668cxAJcWf1dnqiRasKVBlVWaUz6R3bVzcp3?= =?us-ascii?Q?D9FT7iZzmnVGXx184GJLFOtHNTdcBBJ+25BZ56g5iCFdVceK1rZ6Zx+PpVkw?= =?us-ascii?Q?qFgpphBN6YRFSasoYh6dLyGOdBRC1oGHY0KIZJwYxGNjprwej83dDzgq6WGU?= =?us-ascii?Q?pOejjPEViWvpaa7obwI0HVQxo/EOlHflSxpf1zw4OW63QWR/nCoh0YhUxLOn?= =?us-ascii?Q?MUvPDH76hiRRKftxio8qdkHS3eld3LW6QTSaAguHA9ejDQWtQkMPKKRs3U4a?= =?us-ascii?Q?2pEwREc+BmHtzrN8rZleBecAATzaXOAjGqFFRKKtJFRBItd3LrDK9vMp1nZ3?= =?us-ascii?Q?br7up/uJFQaAmo1epXqpv0dqCsydh4d9gjhM8O+BSNqiqmvAX/UEsRyMtbqX?= =?us-ascii?Q?c6tJlr0mL9ZPtxLisVCMiEUYCp0DT2dNZMp7DzApZ78MF9/CvBzS414ans4J?= =?us-ascii?Q?BFp3Om5ntFdVhqL+4AekIW5gblRmcnQizyLxq9+TBZJdoLg3cY/hQqaWcPEb?= =?us-ascii?Q?6QtS8+3HVuGs/QkhB5e8GlPzz1GN7yhXC4TdPlWwqnqCcEjRL0eZBZEu3tZM?= =?us-ascii?Q?ogB3IpcrkjEjotPU6/qmuWEWWZyJ9uBjhmpAfveZ7h0ekUrBPsCunhaIfz2v?= =?us-ascii?Q?yr2vtgti7uKBtpGy09PJwTQ4ftv6QIAnBfjtlUw1jbDLwHBOuSnA1YlhdQyi?= =?us-ascii?Q?2xnTfEEHfr8VRbeSGGIcCaP3rv5BWmIYg0InOlf1E7H2x7pO5L0QW7lq6B8C?= =?us-ascii?Q?eYhYyc2kmc0BhGkfaS08AZGBMxUcTkCWZucOJWVVJU465RUwAU7qDb8SnE7x?= =?us-ascii?Q?Qfx67VdBgF3+X9j//i9eptE6GVl0islz081z/Qc2rec3gnMC6reHXKsA1j9T?= =?us-ascii?Q?OyF4habaUlJTtJyr60GDu0mOJWK0LzILhYkC6eCsqPH3yxXz1KOyHIaucwUT?= =?us-ascii?Q?uBXnJJ1M0NyNffGkXHljtDt4y+VPDWcFkL5JAQRZX+qYpDmVvi921JW29yeg?= =?us-ascii?Q?0Nd6PhMJz18V7STQQ3lSQfOU8NUF7iUR5vOjN+G2U2tjpDSopsuoC64JzMpl?= =?us-ascii?Q?sGuTVNp4ktumk8t85bgkeCVeszmygTB3vXHL5sntlyI09JkRoUirWDu1KROG?= =?us-ascii?Q?dnr9sDzfNPzzdqiEGt1wxfM6QsGYLhN9ohKzHK7KZRrB9Q=3D=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:(13230040)(376014)(366016)(1800799024)(4022899009)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?x6pZBvCn0O8Anakgc7axAL+QpFO29G/+PsJdpZdbi/TDeEpihATK31tRWf0i?= =?us-ascii?Q?XUQZwnrPDW/xfo5lMOyR03+59V4KJXOY7DsIm94EFrWfxLO455KtSwIEh62x?= =?us-ascii?Q?4XiYXusuGt1iKEWHBN+OlUszoNNkvPBBa0w3K9mJsXobm64Ib2Wiw/t7b+De?= =?us-ascii?Q?umPPDkpuR7OOubA0m/ElkCfr7cVBCyQvB0BO0qAeJvSt8Rcq6K3SHaRI72am?= =?us-ascii?Q?UxG3kAedSW8xnQ/6rrrw83L0wVjIXamStlk7MYeISwoN7LC5rju8chxEETyc?= =?us-ascii?Q?7ESlk49k6r3ZK2NN9W7ig66bAp8WEb6HJ6iKK0z/SDzvdIhc2+Vj6xjQEc03?= =?us-ascii?Q?0JzP1XCdcy5fmiuAn95cGFqx+fxfFnTsNf68CrFgOETFzZPEW0M5XsqccWVL?= =?us-ascii?Q?r3s7db0snI7qW0gItGWlH3vM0EhX+dAQqKGlPlKDWK+KVszRjfRfDDwPLsbA?= =?us-ascii?Q?9xLquELh09XOXjJhV6h5A/bWuZ4JHq57brpdl0b8tx/fBXKQExY+KA6GR3rT?= =?us-ascii?Q?xVUyFYSa2oHVndwMb2GLeBTJURmk2pMtjRFvqC9JBpf1F9yQhT+GmyJRmOvE?= =?us-ascii?Q?6GmtCFBB8JnwVGfHMqDZAQYKvHt6Ccip9nH0JJh+HyGGiLxe3CIM/JDG9wjK?= =?us-ascii?Q?NF/H/QE/ShadFDw7wi/hkFuCvIiIQFcDg0GCjXKyahJG8xljtthmS3it2Yve?= =?us-ascii?Q?rejH6psDybm3HAbHv4BVoGuGxCgf91YCLxPrpO1x8qvpisUi/Q0JF1cKA6Bd?= =?us-ascii?Q?obsZrJPFFXJYF963pg8/TjQFihivL3XRtuTC/jb9rv4CQcxUu6BeJ7pTRm32?= =?us-ascii?Q?rCStRGBvxDDboCzw8YMYhAbi//Q8wpgDyXB/4kX6IcjS8LUeFWONcwS9WKVn?= =?us-ascii?Q?1NlKNiwlrRyDaMiLUcYmfaWr1wYizi4lR+Ik1a5LS8Lhv42TIrjhYfpnTovU?= =?us-ascii?Q?WIdf8fBQk5jolY0UsjOQo//8dfabMzv0Lg/33xYq1aj/YH7LBdL6d+wQwrFz?= =?us-ascii?Q?BB56ClMl9C7GnAC+p/XTXuh4ppaUjNWw61A/QjFulN4iFYigAYstn9ok5iC5?= =?us-ascii?Q?uuCT4BZgC4cf0dNTz/vMamr17tcU00kWx3YGmPT4RWUoxinvd5gmvYgNQBU9?= =?us-ascii?Q?qJcWc2s3qKD2PPbtwnut3QFRGZyebpMpinFwIONSJY1036eOslaPKSKcjppV?= =?us-ascii?Q?U6V1YYGPKJ2fGKThDrdX9qv0EBC3NPrIcy/qj3h2YwVa3ca2rLdFyBVuFf8W?= =?us-ascii?Q?HAXjOYrDcxBlrGLvrhTfX1R6urT1hLr2muyEyqONSUKbRhoUxl6M8FVWbZF+?= =?us-ascii?Q?ZQV/k5dO8zZpYnakMrRADWn+79OUGeaVXIyKaHWfhqK2Elc6Q+DGT5zlKy+t?= =?us-ascii?Q?EVOrmEeCjHTxBdaVX4OfzyTwsjzWBaAxOnEG/m+9tKCloWktFr2FmuNUpib+?= =?us-ascii?Q?PRnj7XTOmMsEXtOQSC9GA0Cw8UCVzxpWp9SC3C0DvaeskEaL7WerInCktOsf?= =?us-ascii?Q?q5Y2B6xJNAkFien2Z6IOMLaw1L4d21a/x3NOxqxk5o8d9OWPiDDiJBv7hkL0?= =?us-ascii?Q?p3V65LwZYtthw3IcvikzOEydLdnka2fyjAzsh9e5FRmp/dPeri5xedP/KOrb?= =?us-ascii?Q?0HRuqoPYQ6k9kDc7eVO0PaRz0kp/AmJ3VzyJqxVFfLWB?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 558c299d-c73c-4b76-93da-08dcb85821b4 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:24.5055 (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: h+udXknpFOcdq1+ta/jeS2jKKEdz/Wd4YjL5+L8Bw2WR2SL7aSLqkK61TPO/OA3Eq+xGKhY10fG0Tyb1j+Ov1A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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..f099d51eac9a --- /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; + int ret; + + ret =3D nxpwifi_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "crypto keys deleted failed %d\n", ret); + else + nxpwifi_dbg(priv->adapter, INFO, "info: crypto keys deleted\n"); + + return ret; +} + +/* This function forms an skb for management frame. + */ +static void +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); +} + +/* 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 -EINVAL; + } + + 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 nxpwifi_roc_cookie(priv->adapter); + + 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); + struct nxpwifi_adapter *adapter =3D priv->adapter; + int ret; + + if (!chan || !cookie) { + nxpwifi_dbg(adapter, ERROR, "Invalid parameter for ROC\n"); + return -EINVAL; + } + + if (priv->roc_cfg.cookie) { + nxpwifi_dbg(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 nxpwifi_roc_cookie(adapter); + priv->roc_cfg.cookie =3D *cookie; + priv->roc_cfg.chan =3D *chan; + + cfg80211_ready_on_channel(wdev, *cookie, chan, + duration, GFP_ATOMIC); + + nxpwifi_dbg(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); + int ret =3D 0; + + /* 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 { + ret =3D nxpwifi_set_encode(priv, NULL, NULL, 0, key_index, + NULL, 0); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "failed to set default Tx key index\n"); + } + + return ret; +} + +/* 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; + int ret; + + 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; + } + + ret =3D nxpwifi_set_encode(priv, params, params->key, params->key_len, + key_index, peer_mac, 0); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "failed to add crypto keys\n"); + + return ret; +} + +/* 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; + int ret; + + domain_info->dfs_region =3D adapter->dfs_region; + + /* 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 -EINVAL; + } + + 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); + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11D_DOMAIN_INFO, + HOST_ACT_GEN_SET, 0, NULL, false); + + if (ret) + nxpwifi_dbg(adapter, INFO, + "11D: failed to set domain info in FW\n"); + + return ret; +} + +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)); + adapter->dfs_region =3D request->dfs_region; + 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 =3D 0; + + priv =3D nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); + + switch (priv->bss_role) { + case NXPWIFI_BSS_ROLE_UAP: + if (priv->bss_started) + break; + + bss_cfg =3D kzalloc(sizeof(*bss_cfg), GFP_KERNEL); + if (!bss_cfg) { + ret =3D -ENOMEM; + break; + } + + 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"); + break; + + case NXPWIFI_BSS_ROLE_STA: + if (priv->media_connected) + break; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + ret =3D nxpwifi_set_rts(priv, + wiphy->rts_threshold); + if (ret) + break; + } + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + ret =3D nxpwifi_set_frag(priv, + wiphy->frag_threshold); + break; + } + + return ret; +} + +static int nxpwifi_deinit_priv_params(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + unsigned long flags; + int ret; + + priv->host_mlme_reg =3D false; + priv->mgmt_frame_mask =3D 0; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, + HOST_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false); + if (ret) { + nxpwifi_dbg(adapter, ERROR, + "could not unregister mgmt frame rx\n"); + return ret; + } + + 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); + } + + tasklet_disable(&adapter->rx_task); + + 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 ret; +} + +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); + + tasklet_enable(&adapter->rx_task); + + 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; + int ret; + + priv =3D nxpwifi_netdev_get_priv(dev); + + if (!priv) + return -EINVAL; + + adapter =3D priv->adapter; + + nxpwifi_dbg(adapter, INFO, + "%s: changing role to station\n", dev->name); + + ret =3D nxpwifi_deinit_priv_params(priv); + if (ret) + goto done; + ret =3D nxpwifi_init_new_priv_params(priv, dev, type); + if (ret) + goto done; + + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, 1); + dev->ieee80211_ptr->iftype =3D type; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_SET_BSS_MODE, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) + goto done; + + ret =3D nxpwifi_sta_init_cmd(priv, false, false); + +done: + return ret; +} + +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; + int ret; + + priv =3D nxpwifi_netdev_get_priv(dev); + + if (!priv) + return -EINVAL; + + adapter =3D priv->adapter; + + nxpwifi_dbg(adapter, INFO, + "%s: changing role to AP\n", dev->name); + + ret =3D nxpwifi_deinit_priv_params(priv); + if (ret) + goto done; + + ret =3D nxpwifi_init_new_priv_params(priv, dev, type); + if (ret) + goto done; + + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, 1); + dev->ieee80211_ptr->iftype =3D type; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_SET_BSS_MODE, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) + goto done; + + ret =3D nxpwifi_sta_init_cmd(priv, false, false); + +done: + return ret; +} + +/* 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; + int ret; + + 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 */ + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO, + HOST_ACT_GEN_GET, 0, NULL, true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "failed to get signal information\n"); + goto done; + } + + ret =3D nxpwifi_drv_get_data_rate(priv, &rate); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "getting data rate error\n"); + goto done; + } + + /* 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; + } + +done: + return ret; +} + +/* 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; + int ret =3D 0; + + 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; + ret =3D nxpwifi_send_cmd(priv, + HOST_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, &subsc_evt, true); + } else { + subsc_evt.action =3D HOST_ACT_BITWISE_CLR; + ret =3D nxpwifi_send_cmd(priv, + HOST_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, &subsc_evt, true); + } + + return ret; +} + +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; + int ret; + + 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; + } + + ret =3D nxpwifi_set_mgmt_ies(priv, data); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "%s: setting mgmt ies failed\n", __func__); + + return ret; +} + +/* 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]; + int ret =3D 0; + + 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)) + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_UAP_STA_DEAUTH, + HOST_ACT_GEN_SET, 0, + deauth_mac, true); + + return ret; +} + +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); + int ret; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_RF_ANTENNA, + HOST_ACT_GEN_GET, 0, NULL, true); + + if (!ret) { + *tx_ant =3D priv->tx_ant; + *rx_ant =3D priv->rx_ant; + } + + return ret; +} + +/* 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); + int ret; + + 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)); + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_STOP, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to stop the BSS\n"); + goto done; + } + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to reset BSS\n"); + goto done; + } + + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + nxpwifi_stop_net_dev_queue(priv->netdev, priv->adapter); + +done: + return ret; +} + +/* 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; + int ret; + + if (GET_BSS_ROLE(priv) !=3D NXPWIFI_BSS_ROLE_UAP) + 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_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); + + ret =3D nxpwifi_set_secure_params(priv, bss_cfg, params); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to parse security parameters!\n"); + goto done; + } + + 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"); + ret =3D nxpwifi_11h_activate(priv, false); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to disable 11h extensions!!"); + goto done; + } + priv->state_11h.is_11h_active =3D false; + } + + nxpwifi_config_uap_11d(priv, ¶ms->beacon); + + ret =3D nxpwifi_config_start_uap(priv, bss_cfg); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to start AP\n"); + goto done; + } + + ret =3D nxpwifi_set_mgmt_ies(priv, ¶ms->beacon); + if (ret) + goto done; + + 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)); + +done: + kfree(bss_cfg); + return ret; +} + +/* 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 element *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 element *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, + sizeof(*ie) + ie->datalen); + offset +=3D sizeof(*ie) + ie->datalen; + + 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 element *ie; + int ret; + + 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 element *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, + sizeof(*ie) + ie->datalen); + offset +=3D sizeof(*ie) + ie->datalen; + + 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; + } + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_CONFIG, + HOST_ACT_GEN_SET, 0, bgscan_cfg, true); + + if (!ret) + priv->sched_scanning =3D true; + + kfree(bgscan_cfg); + return ret; +} + +/* 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!"); + return nxpwifi_stop_bg_scan(priv); +} + +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); + + INIT_DELAYED_WORK(&priv->dfs_cac_work, nxpwifi_dfs_cac_work); + + INIT_DELAYED_WORK(&priv->dfs_chan_sw_work, nxpwifi_dfs_chan_sw_work); + + /* 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: + 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); + + /* 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 done; + } + + 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); + +done: + 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; + int ret; + + 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; + } + + ret =3D nxpwifi_del_mgmt_ies(priv); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to delete mgmt IEs!\n"); + + ret =3D nxpwifi_set_mgmt_ies(priv, ¶ms->beacon_csa); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "%s: setting mgmt ies failed\n", __func__); + goto done; + } + + 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); + nxpwifi_queue_delayed_work(priv->adapter, &priv->dfs_chan_sw_work, + msecs_to_jiffies(chsw_msec)); + +done: + return ret; +} + +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; + int ret; + + 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 -EPERM; + } + 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)); + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REPORT_REQUEST, + HOST_ACT_GEN_SET, 0, &radar_params, true); + if (!ret) + nxpwifi_queue_delayed_work(priv->adapter, + &priv->dfs_cac_work, + msecs_to_jiffies(cac_time_ms)); + + return ret; +} + +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(adapter, ERROR, "Interface role is AP\n"); + return -EINVAL; + } + + if (priv->wdev.iftype !=3D NL80211_IFTYPE_STATION) { + nxpwifi_dbg(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(adapter, MSG, + "STA/AP must on the same channel\n"); + return -EOPNOTSUPP; + } + } + } + + if (priv->auth_alg !=3D WLAN_AUTH_SAE && + (priv->auth_flag & HOST_MLME_AUTH_PENDING)) { + nxpwifi_dbg(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(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 + nxpwifi_roc_cookie(adapter); + priv->roc_cfg.chan =3D *req->bss->channel; + } else { + return -EPERM; + } + } + + 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(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(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 -EPERM; + } + + 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 ret; + } + + 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); + } else { + if (priv->assoc_rsp_size) { + priv->req_bss =3D req->bss; + adapter->assoc_resp_received =3D true; + nxpwifi_queue_work(adapter, + &adapter->host_mlme_work); + } + } + + cfg80211_put_bss(priv->adapter->wiphy, req->bss); + + return ret; + +ssid_err: + + rcu_read_unlock(); + return -EINVAL; +} + +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); + int ret; + + if (!nxpwifi_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); + + ret =3D nxpwifi_deauthenticate(priv, NULL); + if (!ret) { + eth_zero_addr(priv->cfg_bssid); + priv->hs2_enabled =3D false; + } + + return ret; +} + +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) +{ + /* hostapd looks for NL80211_CMD_PROBE_CLIENT support; otherwise, + * it requires monitor-mode support (which mwifiex doesn't support). + * Provide fake probe_client support to work around this. + */ + 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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013064.outbound.protection.outlook.com [52.101.67.64]) (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 45020194C69; Fri, 9 Aug 2024 09:46:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.64 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196796; cv=fail; b=XZldeSxVIwTy0ETVvwt3RAEmCwlUn1HWZAXSgrA29WKBE6yx+BjP8osINYg/CrrsQeNx1Rk22/gre1zo4ASvMph7HRijl/q6BcCa1KUoshYJFP8Zob4gP+lTQuyKqY1hZK6avLWg/bkEi1sOd/2hLR8fkOIqPmO+oxNaO0mUefY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196796; c=relaxed/simple; bh=QWKbkaSaNbaVtbJQGMeEXDCm8ELfLEM6Au7R9BuXTdo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=DJi5yAjQIrUWAmMEgOVGqKzHy626iwNgNnB72UTEYTbi1+WwTO8owkAxXd1Z57YyTVDCdXW5TnNQFlA3JyfcbOtPM2M78L2RxGBjRb80NZNbh/+8jgI9ESj8iBJt2Ng/7PFzzm53dI/4hR+1Ufamihv4SxQo9Bockc3g8Wzl3HA= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=gvJrmTit; arc=fail smtp.client-ip=52.101.67.64 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="gvJrmTit" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=p0Zu7GewcLK0qn8KdcGQg1FTts0e4c4Mi2hr48E6ZrXntgkncgjYTRaRBzxKkPrIwrvmOL/y07Wqxu1PZXr7swCApRCwPsFBx0RZuTEYcJcWdoUDUY6OyWTicOKVg5e8HuUUTyn1L2oTB6ooYBfXjj7ai2Wj/P/+d0ToTg7DY5nYC0uOi8hMqNNVWH+1IZtrQzZp7qzBntfy+QFF4N7rLErho+1tXwiszMqkPmD6COMSGoVTYrduzQ/+6/8utt6q2PbfMA06ILNr1Ach/FFMOyI7JZdrmQOsO0lv++au2mJJ0zWaJvkn6mAMvwH4MprfoLYPIH7KAH8wLTxxtLOFjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=XBHjJCVxDsSzN5UzZKlN8f1WBHZH5bXsLg2QpNX+dRo=; b=CEz2O4EAlOehXj2xdTzNiBTSiUWxnVtVLkMCNcllJZejfsBan2NZWpyAmTxIvSmp8gox8WddrRLZJHKkqwYsM2+BiF13Cb/Rux0h4Z8BIqbRh679PuvfzwJ+omA+BXeCI7Z/c0gn1uOe5H2doVuy4r3qtp4HC6MyzF5yRlc+vQBdE7sb8jCtlzqYFjdhP4TXmaVUHofvGgkxfrAsShmwqLCAI24xla8SIewekLc0tgiVJvnYzItRcEIpodBCr/yuz7eM5ZnWKZutCn58Vlhwv1tb92nFgVAkMDMkTYSaW/wPjdDVpJCa5kr9AMTV5BhN/6kgncDt7V3W9+GxWmk5pQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XBHjJCVxDsSzN5UzZKlN8f1WBHZH5bXsLg2QpNX+dRo=; b=gvJrmTitx31z4YrF/UbFytPixVJFaak2Krg1L5c+s1rS9+pDxm0VGBnZfQheoUcROB7nSEz/X9TLu3qowoz8bVmqASPfGqPYB6eVoayx/M9dmvtAqY7otjedhoVH5Ic4DPd32lt90k7dAyRK4bz+Cre2QHVbnUQOBx0uxh+bHKI9uSm/MK7T43+yGxfKmhR3sNVY852/iHY36ljcm3PK2m+NS5MR0v277hAQYx7q/YGirihLjQ4s7IrkbcyqtXrbHxOAPAQgGbObrIaF7XNPbvfwmK5s4PTcvPtq6BkapZJGPHs4Fzuc2PQ8wLvuG2T3RaF5hXiP4HdSNXEIllpeEA== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46:28 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:28 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 11/43] wifi: nxpwifi: add cfg80211.h Date: Fri, 9 Aug 2024 17:45:01 +0800 Message-Id: <20240809094533.1660-12-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: dfc2d294-ed02-4b39-9448-08dcb85823d6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?XJcsIJO2tqCFBc1VFaE4Q/aT6C15VES6pZXyK9yXYdVD9su9UvqlBSnaOGmL?= =?us-ascii?Q?trhtwOpvX4nNf/2fpj4q9QCZFlThg8ZBhOgYHmQFOIPr/fOYjK9neuY8Mm7c?= =?us-ascii?Q?lWw7VKp/uyBmaUX0TFPLhsS1umc3jvrG5lAf/rfCq6XcVPhyZVna2BXErvDm?= =?us-ascii?Q?iocXmqCWaeXRg8TGxZze/Tta79/A2Wx28qCzxdKHp29P97xLHfCm2UVI/YPj?= =?us-ascii?Q?Fb6t1mP4idxKKoYck2k2fuu5cKQeQUw9pbM4shm3y2Mgxz/VZb+2dng1LbbJ?= =?us-ascii?Q?WDubEQ4W1O5wP5n70PKq6/Qr7e2gSJ/0/h2MI98RRa17mrpyJqIlu7TuZ5U8?= =?us-ascii?Q?dKVvQJ9Z8ms2mUTwbvzcSoxVWzBokxb9L3xHznZyXS9wLoutz1ewQi0aI6BY?= =?us-ascii?Q?AvYvoQRvrqkXdYUbgx+6ERsaUgb03fqpwIXtRN/Jq2w+y6IAEJyMaRqMFAxo?= =?us-ascii?Q?Yz4Wd5gIOAM8ZBeUzEcV4Old/xzB+wJqUu56f6HJ0BmlPvCLz/Uv430K+eUq?= =?us-ascii?Q?eV81ETfF5tGaHcjKtINMcOiREmfALF8gE3CYuY/p8Uuz1psWV1xNXNqN6t0s?= =?us-ascii?Q?Sv3SzCjMqEkO+NmY4PcdbT8OTIMMQfYczt+emsrG5ekzUSJqjTyF/yfFdjx2?= =?us-ascii?Q?xbOI+I0PDDNIAKgnFHcXI0s6HDA9awLQ63ulJAKsutgGXNflMDUEQqi+kew6?= =?us-ascii?Q?VyZVpJC4AfCAjtVhKbzI/U2U+jeWagRE3hzuaOk4FWZPojblG1VlZVdzZGFr?= =?us-ascii?Q?bQlMcOeA1OF97rZHsmnA72eOC/s2JsyXbzfawXTrH3q7rgvpfuYysx5XfamT?= =?us-ascii?Q?7mVqF/7OC5Imh6tY+eCT3OtAaLXDO2bQbw38V+e92Xl6LjxbWs/gg4sXS7rP?= =?us-ascii?Q?v/QbDBtzcDVnokzG4iEtz2xEw0vvEyPBLifMueKxfCJEZLH/xBUWePBNJ6s5?= =?us-ascii?Q?z451Kj9u65UiraGD5JwpbEvIFdU9neofIvRVG8JcBqo34BEHLLssFxFWiImG?= =?us-ascii?Q?MFQJYU7w09YqMai3J313XYwjpIp3I2niLgg05yhHM2+qhnfAvM9eBGye0VpC?= =?us-ascii?Q?pqsOpUXkNicHdh+HAfSFDAJXYs7uRrefysG17+1n5cDgHuoxgJv7q4iG1ETI?= =?us-ascii?Q?ryfexdnIWMtY6E3gIBn1YPkK6VeViB9LLzj0fz4rOtsKcGaG/E9sa1OboLGi?= =?us-ascii?Q?PwxNww34fkwbJMEJ/hM+9I0xwMaXM+ygiSBXeeQOzCVQYO5nU8wgriIQl/kF?= =?us-ascii?Q?o0ZvjIPz9UvgamQFf0La19ur/f/AGwpPD0FQPloS83Opt95ttm8m+/nQL4yK?= =?us-ascii?Q?g/0XL1alQ4fT0hFjagDLwM5HYI846lfCjgyS64Sb7UcVEg=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Clk2AgKDDJHpuYMiAeUJEiJ2REPBql8N7uMKWg3gpi15LcVu9ADyJIRTduwJ?= =?us-ascii?Q?WfeOmtoN7rHqk9S305VvAChLIPJSgp5BxiRze8mqwHIYh9DV//u3ZtL1jtuj?= =?us-ascii?Q?79cSyQMYgJgEX1UwzDQlGX9cyn0tgRrb2V4Xrrj3/LW1C53V7AutrZ25PtQ4?= =?us-ascii?Q?Zq0Ni/Y+GjsvzY2thabOSRF0gD8Z5ejeUC2vRE9hxtcXOeFRbtzwN47gB6Yh?= =?us-ascii?Q?e6ML9o1hzp3BXketu24Rkb0wkLrHuONYnjzhcMaZSGtaDFbcebgwzsD4nf8S?= =?us-ascii?Q?Zu1+RSMIo7ypMHSRq5rRvbdjLtGIfzC9UJOvr5wcvQT0nXRp7bUvpfBRX5MG?= =?us-ascii?Q?GVYQKiLUlo4t8kuhMjJGUeGpPSThHkF0ScwZO1mt6ygQ6OsB1sNd1TgiK9+C?= =?us-ascii?Q?M6v3Aso/a4IaAFdxBFgyioo8u5wXizCFBTDrgmSqbk6WmrG2kYnlkiFxByiJ?= =?us-ascii?Q?1bRa5/v01yBRB6Poa8immEdharFkKua/NnF9e2xbnxH7nkKAS3g/u0CPxPoe?= =?us-ascii?Q?imNLyV5IAy6ObzFh2aJOKbM1hT9F248GaE4xgxeRZnhd16ug5P8CrJUugUPo?= =?us-ascii?Q?BULpE60tpY4XRvngKX0adaq58Wsl4rqXRQmai5vjZv6QWkqOAYNV1epglrOJ?= =?us-ascii?Q?UUI0Ppi4BTEknxqMpK1RX+ENlarOy4t4qlW/ewss+D2Sg8iEShRtSYxpbVEP?= =?us-ascii?Q?iqTOYRGi5y2jvA3nQBfHqyDHmGyYbeJwFM5PmXEyL5M7sC4murVOEIu9JJDH?= =?us-ascii?Q?kRMaZo+VR7cp/MI+I2iQ44t2B1rAkMxcTUgNNLsy2slz/rqIucMrE6FgNM0d?= =?us-ascii?Q?aRyGneVZ60kthYwRBrdYXl2ihHwHQb3GEKBUDmjRRpOnmJoWfOJ39bQztzMQ?= =?us-ascii?Q?ORoiCmspN4r7abxJXjJIrMxUO6iUtiC9Ur1KFciO/eNtMOdcdh/r0nDq6XNn?= =?us-ascii?Q?aFe3sex5RImLaxDt4xGi0vSKYGtKXJebEm5DaUH5yvrCiF1Dpu+sZZ+uWqms?= =?us-ascii?Q?nvILYbA2okPpwf6HQicgJhlVSXMaTDFPO5H4X8gtOJVUipy6pC5sXVmDUxbN?= =?us-ascii?Q?hAVBSe+T7wnw1heVEsNMUY5nV1coIn/PgKUnL80kHSTAXj9EbT0uiB9Z5Dh7?= =?us-ascii?Q?NwjgtI+6HCA6qOPPA0JJFEeIlTa5Ev70g3fOkXn9O2C+zu2xhOulvvbmQKlB?= =?us-ascii?Q?u0blhFqm8HjAuWJe7kc2qdKCr7qF3vIXQnJeTlgLjScWslklSy7lfvyRk31V?= =?us-ascii?Q?JZCh3YkwXYlWIZLNNbaju6yM1cSvz7E0Ac7Di5+g9VXOM5enjoaTNZzqow2X?= =?us-ascii?Q?gF1m0WMHdOG5IkI0UNEvvtnpIMgVzczMAcwXuK6BUcZs3IcpHZDCKD5/ki+n?= =?us-ascii?Q?0GwaIJfTShyN5JA3M7IoAvSAm2eAQLGI1pSEVxFjXACDJ2B6HoMzUIb+Rkt+?= =?us-ascii?Q?t7+cJAvUPFqX1ErInjOIRrbbLG38vgmO1/0KuY0QEX69dUTeCIUykkzw/Ued?= =?us-ascii?Q?k1iKKjdRxRab8W21AUox/32F4miWVTC8LfoE8CAKPZGlWO2+7TqSk9Rhgp66?= =?us-ascii?Q?LHe3cm7/yZnki3OfTjZ7u9uEr0KIKtYvnml0El94N6NyaJCjH2A9Q8NQgGFl?= =?us-ascii?Q?k/2c9zjQ6GvfApoTyBHvj17TDEDm2ixQ7fGI2rltiuJH?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: dfc2d294-ed02-4b39-9448-08dcb85823d6 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:28.1575 (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: cOi3Y8rvhfS7Sftrbqnck3M54iVtuuKb0aYipPr9Q4qq7LW9u0LhESZUu4lvEwsjCj6mDi4T/9UAQw8P5hIc6g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010009.outbound.protection.outlook.com [52.101.69.9]) (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 4385B194C7A; Fri, 9 Aug 2024 09:46:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.9 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196801; cv=fail; b=RE9oPTeUA7wtzM45czdOSOVyc2IRmefpDgoEHEMVuoRi03bZ2cfvvhb++6/gpT8BPNDRsV95fMhtgV6alCQNPTjAcT72azn+g57vmAdFoh//FyqtSRlt8+Wr93u9dXZmbJo0uqOYY2H32e9+ChPv/WE9x5ufUD5Vr4Qdy0d0V14= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196801; c=relaxed/simple; bh=k+6zGxyVG1oHfEMaZJ1tZmZPn1aVqjrQTSlzPkuQNeM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Ftt+p+ZtxISYKhTboYLBDbJTKxFitGrq5nI8WJIIaX44NjKi1i7R+C6dsi95hrnC0SxpjNPp2n+XIyyIn4FaVE3oNGXYk/sJsuoUeNqM4sfcxDIag5wsdN76jVSkIj8m5NkpemVeFFmJCjBGbp71wJLMQb8U1/SdTKxkKGdAXB0= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=iyzyz+dZ; arc=fail smtp.client-ip=52.101.69.9 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="iyzyz+dZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=eublVJg7prreQ0DHPvggGDRUFkzR4U/9tvxkuucjuYCM+rv9qBIFyKutceNkOePDq3y0xSIEupB27M3aGCXMbP3iK52imrTeMBnoaNYwFSf13G4kSL+vgrrCUVIpTQZN9ArlYKlJVDRbceY3YXJLIHeYguNatT/IvbIekMmF8yJNQ0RPugLvO/PYDnJQ6kB3XxlFkI0LKHIkEB0ClGuxEymunX+CWtJWaJp3LSiFtAZEKT4BNtZufDObE20jrs3neOZxTzCxeymbQBsc3VX6e8Hcnlgqk4DI3wzbb7giSucYtNqu13Z5ERkx09h/Me/VelDu/67sCVD2WVRIy1bVMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=WHAERgpawj6urAJBLMjMifC6Z4ESZURpTzU16XE03EY=; b=Uc7Ig7NqcsCQdtGxsVxZlqCWv+C2v5Dpo3+Gm2u/j/s7NYj4eNGjSfe2noY6z1t6UUoaPRXERk1mmomSL9iGi56mngCa6w38blTertD/qbctmhRh6vHqeJs8nxnND036X6VKflZ0pwb6PHFdjsXkcdjso8s5xse2isChUBQtLQt0pX4/lY08flqNBdOruSrJLbz+KQqejXe4IKtwhaiCPuBmD9lcOZikSN6SJYRcJcPXFcbbBQiQtRpbaThXmtN/XfhniguYMTZ/DPb8btmWEMQjArgfvqcTD8pmaQny2p3Crxh+Sj69rRHH980nD+wT3Digbx4LRuViGfAEKLbsTQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=WHAERgpawj6urAJBLMjMifC6Z4ESZURpTzU16XE03EY=; b=iyzyz+dZF2wMQj2E21fNfC8f5UBBYNpmfPg9l+TLxOm1j5Lif2Z9HFZcVpXSW3mTbybk4+XSbrXYApCr8Go3oOQ8aG4Q3S8H8+mwOf3pe9/PJbKkMrXRVE845FFDR2s78y57dRNnGOMPD3jhKmoneh+j9pvcSIsvSwGHzrncoNVlNpLpuTkUUE0/6ChHhLm8WYDfmdR4PRN3xXIYxyCZ6kpWcIZKLPP3N5ZdBdGgsrW0zCWcIL8FMaDINJKgps1UKhIQk8hpIP2Q199lx7j83v5BztfYD+ynR1Ku02oSErglByKgczULSZMu8x90z4rafgytUQLwlFlHlFP7WqPMSQ== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:31 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 12/43] wifi: nxpwifi: add cfg.h Date: Fri, 9 Aug 2024 17:45:02 +0800 Message-Id: <20240809094533.1660-13-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: 1cdf206a-d532-4063-9e58-08dcb85825cf X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?8ZO6+0q4Lm1uIvU42kOdHNBN/7wOYmd93rwOdVG4Qm+mFvUexS64y3OB3Ghk?= =?us-ascii?Q?8fQ+phm2Onyh+zGsw0WrFuTKQxXMQV75/vbKZ6g52fPDBTuodlpRhzwPm7ii?= =?us-ascii?Q?H4u0RNbkxojKVShrrrVuC/4YauZfZtPbQES/F6Q5dVYJN3uFQanG9kwQ80Ew?= =?us-ascii?Q?kIWe7HcevegpgZZKcZSpIBUYrZbsr+/e4E053JMCnUKotDnLgxJ9acE9VT7P?= =?us-ascii?Q?53AHn+OVNoSnnnTZHBLWRcEzgS1aTmk1TQ2C7y/0CVC52imV5lVkCXhb/6Ni?= =?us-ascii?Q?lnPt9sxkMG15F/t8s26hDpSuHwgHwASUR2K6UYWNRxtkrlhrHWDNtMBoVqzj?= =?us-ascii?Q?aAzYjSy2z1Wg0zKwVBuWEBIHAQqkqGaftd+N+ywJvJHmZKmUIKsoDhaQIbI6?= =?us-ascii?Q?bgoA1bLE42d7kuRZxv4M6PPI7myUlXCwG9GamYbcfuK/uCD1Bpte55+hUcPM?= =?us-ascii?Q?cFSaPQu3EjcLFgZIl9ro8BOS9MF1ozoqE8xena2dLQFVP1aQoXNzCPhhIxcc?= =?us-ascii?Q?cl3s2fk45XVwVVVeaz0fj2t9LwAWNabS6mkb2VC9jaQGc7WoA0k7Rg9k7dzF?= =?us-ascii?Q?4QNn+aC6cXDo1ZKGiB2TYENUTIlTUjqVNc/Zf1Wmk579rAKfTThqUoKTFN81?= =?us-ascii?Q?X9xEO1ovBPLeqtwVtonnRqtGCgJidw7QFBPwG3+yMFcalUF0b0ek03aANiCk?= =?us-ascii?Q?6FipWJ5ZqDoPHa+jWh79CbFEFfeJLylrdwSXnstO9kG8kJgdhcU3jlIBYUnl?= =?us-ascii?Q?0tt447fQQ/2s/UAHsVx9I+EzMElsoTApMTNdwnWyxrXtA/xeznKTUf7FfNb1?= =?us-ascii?Q?yd/+x7Yl06/UoUQPibpERJrFgfjZKrpa6xFifX3650hgKXHPuV9QmBWHsyMP?= =?us-ascii?Q?9MhOH5o+nV79KTDRSvRZ23wl9DnLgO3pitOwvP9jrj80xv01/oUZUHreHU96?= =?us-ascii?Q?6UuaA2tNAJ65fQl2onJHanBYDyWrvNLbblP8PQO+mW+wCO+4BJ0AygJJitZG?= =?us-ascii?Q?LgBZ7+HPcaEEviKLFnRtfblUgiJgeeteM11rj+3z/iGGPN2nN+PEsD0dGZyC?= =?us-ascii?Q?Q0N10e+7u+s10IdiiZEyavMIxRWk/l4iME2uBGtsFs/d07bcJd1HoidJartT?= =?us-ascii?Q?ZGr2zZbl9y/YK1ra/rMX5vvyWncsDeD9mxHBzjbNoWIx22WjUiMGPEpDL3Mx?= =?us-ascii?Q?21++BOpJXwIyTKyTJ371PX1zaOACHYzw1lEtJpw9xOP+eRBvG56/fB2R33aD?= =?us-ascii?Q?GSRiQIvXODIsOVIiZQbb6p13Jd2xbmB4lfcTXL2+suk+9SJFS8vxRiUwIVnm?= =?us-ascii?Q?f/UTsb3eBG+7jPQJx/erHSN2TnzCFgqyZHWxCy6CC0e7Rw=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?8ma8NFNfBcwNFKnpkqiJz2uz9sX3N6HuvJnwplnFR8dIZi3QZhlscJb1GKsd?= =?us-ascii?Q?IBmozcz2GcxtHk5g6bTmTsTetY1MkOY3UJDjaNoD/YOqBztghqIP3jI2E9is?= =?us-ascii?Q?95cWiqsRWwjP0MTciGkGGyrrTTQ+V0j1gcJyrCk6uqXSzWQog9+aUvxQlaTn?= =?us-ascii?Q?timPM34lgNzbUWUKuTg9zBwWylO6na0gU2RrY9LpDSxwF5RzS9bf88kAQB0P?= =?us-ascii?Q?NyAS/bEgTqHVYNX99mbZVkNOByPEa+l+ZoXYS9d50eFe4YPA1o0BIKpVlL8p?= =?us-ascii?Q?eoucUyL8BR2W5t0Ne/tXHUmo1GA5l9wtrCuX8bucFRHjFnshlAO72QygYLI5?= =?us-ascii?Q?gzebyPNkQCsuoKPhzrxbq+913vFlmT2c5cCRbohPbaq+IFDmeYUPXOksDIgj?= =?us-ascii?Q?UC5FYd0SjmkTYuo0hbw8Or+vsVeO6LYAvDg6S74+BsN9t9FLPb9Qn8kVyn7N?= =?us-ascii?Q?vTxr2JpMntw+73cQdFAQg4SSg9t5SSRLzcUyXHryKrnrBFRlTMb1ttyT7u6x?= =?us-ascii?Q?w8bo5xMSuKgrrleZykSIPhwCe07mml43kTesAQaG+xOaeyoCN2Db0MqaRYj1?= =?us-ascii?Q?/1ngxPz82/RMpcg/XtrjZsC4hRvMJWZxqazq9aKyrj/MmPqCRsLaX+CrCn0M?= =?us-ascii?Q?D0TLOcvbmIbZtU4H9XEwib2awlbrTn+JVXaWpHWkZA8UoDf5gsJS0hqp2PbG?= =?us-ascii?Q?8EDIWByM2lHTll+Ar5NwVyb1k0lg6tEsJgSMDeqtvK9FYKBNQ8CcvPNVClEg?= =?us-ascii?Q?vGf7Eoq19ABnNCMqyMb8vzn7CbUu4ymOGnTpv6cNkIx1y8uVmrWyrnieq7Pj?= =?us-ascii?Q?8bFYfzAJn8+9K+zz5r9uN73Cpg5obn8Ygotp/bC9szDFz3sz9kvGfyqqfUZJ?= =?us-ascii?Q?mewb4xKX7xI4MO7lHUD07I2bMgefL129OB564KyO9D5ilbHeIQuL7yzNghSy?= =?us-ascii?Q?XKC1NVfzFLXmeBDHxn7iKG/B0wZfSBqV9p8PqipPkFYiwdQoKPLh7mRAR/TL?= =?us-ascii?Q?ZN4QCmelRGkRTZTMTFlbO5MT78bSCoUElIJOQMRQoq/oIYvtSPS22uiIGJND?= =?us-ascii?Q?n3nwLlTLzk1Ojj/sztjRA2uOK9eCdm5pqIrFC0pWPNSz9Mkt/OcKiZHaX+mq?= =?us-ascii?Q?LcucEJ/C99Fuf6TCyurLaWdJAuWOYrJ1Ttv1a3UfU3abcNz0/ri/5ono+05i?= =?us-ascii?Q?JadkbV5itGv0HPlNuHoAfl1UJnl9EpR1amsUW7DTu3+glgCgoz4m/fqPCcNI?= =?us-ascii?Q?VGvvwO5D47E4mB8j7d8PVJ9mH/+eg+7LX+ECUc7ok8tcLl6MwokFwV6NfOke?= =?us-ascii?Q?kSFyObFgZOckK0W5SxMGXUryNLfjoD+YIXLdUMYA/dtPADO/gRids+vTObVe?= =?us-ascii?Q?5uw2Fm032YcXgKKIUI2T6JTwBugBlQPS9U4piC4XbrRPHYf6j4nT04jOzKkV?= =?us-ascii?Q?Le1Z9nDSMrcVMteko7/DpZuFyyaYJhF+6KI2R2GbYYTOADCzAhKOdzMS4879?= =?us-ascii?Q?gF+WQlRBelMHSkdeN7vTZhipbsNkbmJZodu8y2OrSdpPDPyc0TLk+OHLdfHE?= =?us-ascii?Q?TNzGZn0+kQk/bPgojFPx9NeLfqvgp3yVq2Q8ylRxprceKaGOJRHS1Vx/HMF5?= =?us-ascii?Q?TalTJj8QTSO1hf+ITqjS39FXGeuWBhd1yGQDZeVWN24p?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1cdf206a-d532-4063-9e58-08dcb85825cf X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:31.2098 (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: uKQjyv0BZe1pgyE1wyURf5g9+R+CFquKWik/xJboKd00EnJx1rB+tEgcyxfggvvifIMCAGIfb50I6Gxi+FK1Yw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/cfg.h | 445 +++++++++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/cfg.h diff --git a/drivers/net/wireless/nxp/nxpwifi/cfg.h b/drivers/net/wireless/= nxp/nxpwifi/cfg.h new file mode 100644 index 000000000000..b55dfb872b76 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/cfg.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 Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010009.outbound.protection.outlook.com [52.101.69.9]) (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 B79531957E2; Fri, 9 Aug 2024 09:46:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.9 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196804; cv=fail; b=GO6Q+YWuLAwnZVLjbKAgbgXNebpUtueSA3dR+h5N8MU27ndc1pXnpDsrLVTLb4m47VN/ytH5fGDfCiiM4Mt0evgpZ9ugRbKvZ5zVLNtR0KR5Oov0hxUuQ7Ujpz56jhZOcN4QXs534ftZPfblgyKrpKQE8mIWUhm6mvSLjQ7hokA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196804; c=relaxed/simple; bh=00hCiK7/BwzQH7lN+WBpRr1iRn+cvYeOJz/CFU9NVnU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=nUQKS8EvTnbkKJbQd8XQdh58MDO7E7i9hf2SjA17dKJQ4F0JAOoydVz5hUwVz3UZJBLHfQSGxbt2c6iYEOXVg96rvLb0RvV+8aqw9I95XLq4DkhpDNBteaDdUp4xFeqBHxauUTE25CwGvkC8LPnUW2W6Ts0VaKmO/Oi5EGZC+cs= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=hFroGAFq; arc=fail smtp.client-ip=52.101.69.9 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="hFroGAFq" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UWN6S+Ny5Cav10kbqqrEjbe0uabZu7HueraaPvl7x+UxpUja3z4oiGD1HQzNOfW3rOpK7cWx7jjEn+HJFUhItrAbb7T9iVPZg5n0QlQs39HHgrPEf9MtWz5wNAf1gsKSVFPNN/enAkqylziMZ5PNIbJeOcH1+Bq3JVk/QK6d1frEaALwucmsdQ3MK5TqvER788QHBeAfh7jEzlwAPf+uUTSRDw02aHiYBVIgzS8p+N+ucpMJ6RoiFi4F/Zc7tcga2p5BBWx591OnGnHgOR+2PhHeT0micSjFD9ymS5HBl2Bn34Z1OuiKaIClaSDGD+yGQD3qwMIEoxOsTaeM7IbqNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=eoBZLoCW4gBLbF736lnajcCz9D8aqYRFhv/UaE1f27c=; b=lWmblhIp52SRI6p/tfFouZKlW2oO7HG+iykakcF2pQbOVkVDyVs0jY8GLLUcEHpWiGUZwZW6ycH5veNJmasQKR7SXo5OdDyP8XN9bLZF8NgJN6QxL+iqxC49y8CGyDqVTmzmIPgsNFJqH91/U6ew1L7+dS+Y54F/WKreSghjPUiCF1zaNQMuk5ui1jtmYD8zdyeJRt1kUh++z4cm05Ym+e0N2T8IWtz2RKRwFP5pydjPDThWnRvIjkNVUbMY+969iqiUlauuixOR+DIq0A/k13JCZxtjDHFA0JKGIWaUL80J4EsdtZZZX+iItQXeYNTlC4ii+ne70VbUow+eaMBZaw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=eoBZLoCW4gBLbF736lnajcCz9D8aqYRFhv/UaE1f27c=; b=hFroGAFqCox6JmPpkPZ0iiWye3jwHOW0YwSifvK60/HQIuOb3u1NL8FSq/2awpsFqxfh5CZN8n/5y8w7Re+Zkvv8yIpFtlSaERjuHmjDaNVyd5WgPXWkMAByaylOryb+LLaQOj5ZYnZGRn8wKE3gsfm20OB7f+ruwlaNMCbQfm73PYNpxbvG+wIQvIzVuo9QT+Qb7NVZLcoeKYWQ/AtMO7DDXhSO36XTxxzMM3oxuE8mFR+4P/0AQrHVQ11fvnOAeSsbC3f2cJ5MGmZ6pk64R1zrfYGVAVHYO17VXa0FCTTtWuJpsEv1wfX0yLcVY9poKAXDQI4ragoQjxFh34dMBQ== 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 PAXPR04MB9229.eurprd04.prod.outlook.com (2603:10a6:102:2bd::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.26; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:34 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 13/43] wifi: nxpwifi: add cfp.c Date: Fri, 9 Aug 2024 17:45:03 +0800 Message-Id: <20240809094533.1660-14-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|PAXPR04MB9229:EE_ X-MS-Office365-Filtering-Correlation-Id: f2b5dde3-d03f-4329-baeb-08dcb858279f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?Y9rTmQ5HFrh1/8G/A/sVhvYgI/LC38Qpur0fEfTP4nFBmP7tgzTKZh4ST0Sc?= =?us-ascii?Q?vSF8HK8x4m5g5XX/c4YnYrMHn18AWD5nfs8aMLac65PwTE7HZvUowIIfMFDS?= =?us-ascii?Q?Z25DO9o5nEE/uiiSgJZ6wEbKaUlVDiW+lBL8wujU5kaUnrWGia3YBsgwuaqR?= =?us-ascii?Q?5+wAo7eiQWUpbhXHYBul95C5wTnwibXVfKsDktyTFFRQX07JqUFFucp6f2nq?= =?us-ascii?Q?iAYsX0O6L8n6juOBZ9CeY3aaCJtyiaqQ3TRB6cGHbRgG8Cs3xeiqwQKLUWIN?= =?us-ascii?Q?wl7TErCNvPcMoqQJ0YNeRrJ6et+Lt7nj47Dra83YNaSYiCt9bbE7fvURSEw3?= =?us-ascii?Q?8a2bJFF5wUZLBUVe9ViC+zIq5OAjwN6lh0iphXaBS/0PWO82SCeDFy2iUQd8?= =?us-ascii?Q?3auzTEkMveeKD8Ku1zEd4gXr+DwJmougJHo0cnhYbwDRRYs1xVEl9OWmQqw7?= =?us-ascii?Q?b8Sp88Da1fqqIrV5ny+964EEcxBJHHyZj2FVMaa9vakrdYLk+61b2Mkfxvwv?= =?us-ascii?Q?Qm7UtiqBMDFKwkiPw6in0n5oS6WCmrYY1fpIn7bC1j9iJH5HzLdwDMDn7XBs?= =?us-ascii?Q?9pvIg+3FRAbRE2OqBB48YeYm1yJudQaGgDtlmeE/GyGPhkf5k1NxW7CDdruw?= =?us-ascii?Q?lKkhyrVvM056MYnU6KcL70gZOD03iKUvTD+g0P1CMiLmR4Z4P6A7/tawY+yI?= =?us-ascii?Q?Q7vSLC63qQfbjiovJ66WmffDvgdtnNDiZSkCCLFAFm4UMJKIKJqr8AgDVcEV?= =?us-ascii?Q?cc66JDu1OAbDeQbP02wgpgSljGJSCdjGkGW7EtOuoSFVzbcuwsKQWl4/x8G9?= =?us-ascii?Q?myCOOb6Vu/x1rDyQOG+N+JlrO4Ob7PSEjw29xFKcsrW2oqDtQ7bTh/ZOryFz?= =?us-ascii?Q?mO0uBsN+36XZZs5KmCADnLp71cQIBf4/GwaFgJ9x3LOJnLPJqWL88gEBpw1U?= =?us-ascii?Q?VtrNJ/IdqosiJ3+/LkbmRLFKhORFZ6N58lpLFUZd+ZXX5hbuGej7csSB5JGW?= =?us-ascii?Q?7f/L3ZxDV1BEfPvudycJzO4wuUeMFjgZmcCGDpNTM7IS17eLNEb4/4qZ4n1z?= =?us-ascii?Q?CN7J5bblGiwfPl5kl2NEIla8glA7yGqAP+N2gAsM3sEf1HGGCzULNeOHBM2X?= =?us-ascii?Q?NEpc07UTgS2U0Amsr1Fvce2thTt9TApnZ+J7oZUfQKgkwb3MvqRGsXtjSK/D?= =?us-ascii?Q?Cn43y5m3jtX91H9tUIFkgWfUyKjZyzGS79tb2WW4alWIXST9Q9q6fZWbt3nB?= =?us-ascii?Q?EwHHCO4J8deYt6k/bTIF4vPt/tmZgYDlHOmH0+mU4WQe4/cSwpyAUP4+492Y?= =?us-ascii?Q?L52rQlQPNy8xbo07ykG51gHLcHawqIaLcgf+UOUx2RJVkQ=3D=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:(13230040)(376014)(366016)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?2gxsdBAjUhU5Z30XW2Gy89QmtpaQuzmLy14+dLwrsIpP7QzprbtvxXUGVZ5N?= =?us-ascii?Q?RtQ6sO7fDTtXtDMRGtqhNS6hwdc9t30s+agjdjgKurJzkpNE0TDE6K1HfRkr?= =?us-ascii?Q?CT1yPJKL4YjxDFK5vzNgi7eGO8HiR0Pp56tDbL5BV63HQJjrDk6fy2lc4vhS?= =?us-ascii?Q?Z+Px+7JWVGURLDLPKgHrzn6SILoI2T3Asm7ZhJRnEvPwLT0YmQkPYhojjqQg?= =?us-ascii?Q?Fk0FpEsjoN4m37D816oPggzh+nI169rPvaxbK/BvK3YaJ/DvJJp9V7nibHxH?= =?us-ascii?Q?ceBL8ixrd7bOh/uEoA2nlSaqwctspnPObhXopFsyGOPHsUtQI6PPxPvlv3uB?= =?us-ascii?Q?HOrwZlCrWUOA36+gGT8pncFH+4FGo8O+XPh36lLOqHocVrf8D220jikr4ggV?= =?us-ascii?Q?wK0ztys48AMiNIBCW5DmXywwlNQpjNG1VGfQS5Ahi1qWMRdp3GMDiFfyiY4h?= =?us-ascii?Q?SqEGHTzRSpOh4u+PqlO196+4gdzfo1/vuj8WGsqQTWkx0HVHj5f+HlZMEvS6?= =?us-ascii?Q?RZfub9CzPvz4SsFl7mLnN7I49cdQnRytMEiBYrbI0Ei57Ux6LKnyk7v4dzQm?= =?us-ascii?Q?R+5f69h4Vho0XCTbcUReGuEtw2tpuRYJVYwUR1+1PSpVhfJCA5ceCqveb+HZ?= =?us-ascii?Q?DlxpoBJoYdakj4diZzcZPq6lP//WI74xWDjviC5wy7QKuHLp+qC8+u7hkG6S?= =?us-ascii?Q?Ac0xFcTlCeD+frWAFNi5u50RE+l/wKkAedetkLbASprYYxng1+IbagfLihu7?= =?us-ascii?Q?FOoe7Q8wWSEcCb2fvH/phznPTY8exytn+gsKL+4d4ddtPtyyaMuMWWOtLnk8?= =?us-ascii?Q?urtVdM5MedbGTq0QE76w8iF8i7vrDT7Yzo99FXeZSsnkqCyXm7DeoIePyH1a?= =?us-ascii?Q?m1RuUDxe8J/oD5Z1D08ikoZtrMj4WXpiHcGTY+6Oj7qCQQWbVJZdoUfWKaYr?= =?us-ascii?Q?E7L++hPppSuz1xbNOKx0FqAZG6DAGVSV407HVR2wQcleemmNRmt4ebTlXE6X?= =?us-ascii?Q?u47/YR9Wv4V+kD1gINBuRrbgpwvGFie6ypKU+Anl4FVveEvW3r2sxYkiofLg?= =?us-ascii?Q?053NAUO+0uaSZOhpR7T60zh+nSROiN23yxfcRaWgyoJhYnOJznLHRLK+lVZT?= =?us-ascii?Q?4FWChIExNuQUqHdXsZBjJatxdOwS63yGPaq5ZXpm1FLNQdPxIKkIqfMK+b4p?= =?us-ascii?Q?FcvV8h83VZEOn22BE0zzpS78WOdKcNiiMqCC/+wig//DFYYCs1ph5lHhKaIH?= =?us-ascii?Q?QZMjJ4OfRNWrskG4Emfi8aYHtjwBet6Zd1BrT76Y5V6/AFkvCSwhnMY6pqiu?= =?us-ascii?Q?VsA7z5hIUgKXiJFc2h5kbmcm0KZAWYdKnWZk2vsg0tEq7ln/1etYEwjGP9B2?= =?us-ascii?Q?/h9uGCNy9jTt+5d2tSdxIISyCwe+qtIguZuSGEYzqY8+8y8i+KU59tYPMYNF?= =?us-ascii?Q?T0ordVcx2Vj/drxQZ25N/slXoeoWaHWd9e9qYSwuZ9WLf8tDnCt2kAp5gpfp?= =?us-ascii?Q?rL3smb6z8s/CAzjhd2ZiPfnkWWCedrcFyNNwmgS4g2ehoo0dFZ1uhh1Z1YMo?= =?us-ascii?Q?Wh5/vwi6jzdIK8pm+X7tB5FFhiB44kvs7N1ChvC4TkWtgEP265Lkm3bFBeL8?= =?us-ascii?Q?iceMv9jtje5kQ2FKWX95fwF991IZW1+gYPNgWQGUDJs3?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: f2b5dde3-d03f-4329-baeb-08dcb858279f X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:34.4546 (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: 6JdXg4B7bJO2rR72Z4HP9qP2o9L8J9aLIQs/m+XiiDEYHOvnOBV1NgpwdTwchewjfoecuspaCOK8liXHVDEHrg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB9229 Content-Type: text/plain; charset="utf-8" --- 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..249aa31c2d4c --- /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 "cfg.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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 C2DB11953AB; Fri, 9 Aug 2024 09:46:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196807; cv=fail; b=JxI1zv8FE2aqmvN5EoYhKVy/5O37O+53iRB/d0FKjNuXEroo9Hzd3WH3/SeNxjgfamnhY1uwOXPyoYaRX4a/RRQ6LDnYM9YdXmOn/GE+Vd8jvJXmHH2+PGPgYQNSvZFrIIeYx2OHQlCEocB1fzm3r149OF3kaJTKMnT55wRchA4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196807; c=relaxed/simple; bh=LXDdCRj9OEnPIIam9+U10SRlYIvuO8JO2dHajdTFSSQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Svy8KB+DieljPIwf353ghr3TX0CX0Hi2cJV5hnPYzyAy07WFVscrFKcJ66ogIn/L//xmFevuYwLLrWjagsXuq+0o0wC07eN6X32mxHPVg1J3MG9lWPMWF0Jgt9dy4g7beHDn2G0xcrFF1MEKhN0/WArX+Mjl+JPi/uGKMkZtveI= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=c4VyDLoW; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="c4VyDLoW" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ue4cb+4YBDNjILB2upWwfCJHhy8+wYRwWl4usiMWgyXqG0Xj63mPmq7qfizlaMPv8xlPEUm8uN4caxz9Fhpo+zacEyC6+vuWL5ehY5kzh/OMJ2Lf0w9qzT4BPrctKORXm+ImbAnGl9kOebkrMuKvtO8jyNE33En98Y7M1qu8hr4xv5Rp/IfeIU+Sqqap+On3rlMlk8fuAdiJpSguMiCKKZmGYAECXguEDNS4ZNzhnEd6+g8pgNkAcNtkXlmenKD/uaLY24sYOPeaZrK+URZbAIeRqpxJT/m59xpzz0JdYZUCAoc0QDTvVe+ofaK6tu7DQNDjDPn1Wn524qhEMCNfIQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=lGz3rcEW7ipnH4iSmWgfTBqyk9kLlySd+an4cp9rWxI=; b=g3VMRXoll87QrZQGcT4QwzlC0YHp9ckBBtDqqOqcaEbF0RxbS+Qv2Xi0tNVz7m6Hd0w4tSB68n+SXv4WTNkvcjhTcKPmqwVw3ECXlNwgVXn51VsFsRN9Afikb83tL17B162r+A9gvm9bw+UMzmj2teSGhJyrq4bJY3CEXfklPkqBg/vZOmc+wr/LoLmoI9bjT2gtPEQwaJladUeupD5G+mz7uOBRNWbEV5C9fwJa0UuEvqHsXNcbXgB8BuAC3tV6K5r1q/Vw5nShOZqp7MRV18p0OMpF7ZNG4Y5nBLCFXAiMWhoZYqe/zcKOHgqcSgU+he3QbZO/l/yOm+tFMnKIHA== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=lGz3rcEW7ipnH4iSmWgfTBqyk9kLlySd+an4cp9rWxI=; b=c4VyDLoWRyHtgvmuCrXlquOLVmDqUT7syig76UpWd9iysVkZdilNXCi2ajSt+JcUdRVtMfAmNmIPT56nE8JmV0cp6YvSo02ba7CUcVYhk9b/ImdtAELg7vjTx1WRkXPiHF0PfJKKa8iI+fQj6HsInCv/FL8uQUgnXKUPUUrenEP1XXE8NChb95lq1npvR5/D9IqKKAoBX2yJs+ZtH+HcIw6dsJoa7sYx6OtS3j65F2WYfhpxuU8FZ8FC40VmYHjb4RofwNsy76eVgGsRb35AOkVDHCVUKOrU4ipiEgSZVMd2o7q2p2quYKsj6qentgqGaajWKjqqyXqB8itFa3CIHg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46:38 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:37 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 14/43] wifi: nxpwifi: add cmdevt.c Date: Fri, 9 Aug 2024 17:45:04 +0800 Message-Id: <20240809094533.1660-15-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: bca3ad69-4960-4ca4-0343-08dcb8582992 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?iZfnl3SXX0WyR5wuSMfXJspodzLiaCNprOX/wEOMu4ZtMZdTvd4TpHo++ePi?= =?us-ascii?Q?1+HwwssDSBR1OSuLE9O82TNPqP4b/fIWmtaJtrDEaqNXw9b16+srIszwAVdk?= =?us-ascii?Q?7xCt83gmimeyhVqUNNGo1yBUbMgkVhgbU+dqpstbqGqHRHZgwt/tQc2u09DB?= =?us-ascii?Q?IN6tTqPrNsaHN0EfddwNvUIzYds1DxIElKetpiIHOypdFYzGOl6QX4JKcwZX?= =?us-ascii?Q?W38Ij/gbXrE+w83HlmZ2Z5FiyVeXSIK1DstZXNllE4nrJ8WjdFDbSs1WF7z9?= =?us-ascii?Q?B3CIG/l85b6u2ETWuyIYif97tFXjuLikvtjZVp9ThbQO7BDs6ZjaFbokr90C?= =?us-ascii?Q?1wXcKb8t7NcwKwUeaLstrFSbOhqA8PpYLjT5EScGkmj8fTEDYIa/jLVuAv5N?= =?us-ascii?Q?H5MS6Nsak25y111JPPcR+cj5uo3KggoWyU/bxzG80tv76XQ4YdKbk8FNxgWe?= =?us-ascii?Q?tdESqKSjAXxqhC92QgdgKPS+y/ViWmFB99zLLetVsWKXKet9AIzx86zOjPIi?= =?us-ascii?Q?p2odqzhwvx+1I+CWTA8MZs5fYn2O16j4m2SlheSkB6BETKcct0RKbukWg9uH?= =?us-ascii?Q?FoofjZkUDkcgnwqrHbmjwx2jcBxy482u1PKl9Vhg4x3HRjpTVOpq18l59mGJ?= =?us-ascii?Q?NhweF0Ts++QzB5OEGWJWLQhpt+rwL37XCIb016U8IgqcBhqTAF4yjtavUx44?= =?us-ascii?Q?ipjdyYs/JLZhZ97mCt/rRNLRv+ilaFf1lFRxmTxMSQTv7MaJypXnptZkbVWz?= =?us-ascii?Q?lBu7J2ps85cj5xI1z9ghXDeKY103KG0PZH9IlRX04UMMVOq2An0yg8DC0vzf?= =?us-ascii?Q?gwvuQeuenxjAN9aEmIWbvQZTGVokk4K3ElttENM7Idh5GeRXBHwlbE5nEKRM?= =?us-ascii?Q?GT+ffwtiuq1JTeT1lbeV0RG3ORLoQggbnwGUaH1BO8+iu3zTz+d6pmm8iD7t?= =?us-ascii?Q?Etrejqi8Um8P/0e9rg6lwJpg2KPw6ZLCf6drUmDCuVo2lN+p0+UDfAwmzJFB?= =?us-ascii?Q?l8WouRrSwXQaRiKH0gPYLI5XTEXlaCmpUaqhqEBqnbXX8ZztJuIhTkCjMVQw?= =?us-ascii?Q?goK4vs4ECypm7bldsWTVnOGkADNTWSMtuzWZeqx0BtnTPxFwyDeWXjpsj8/d?= =?us-ascii?Q?MCvnD5evZMBAWlYo4yk1yOixblc1t3vzooNnk8KDvxvBa+YEFoyhKnYZIUur?= =?us-ascii?Q?s4t4urkqIX3XibmDKfUaFPCgS/geQT7/35vaIgHg2LY2ck8QJ8KjE91EtELf?= =?us-ascii?Q?iWG4Cj68zVpRxFQVEUAebMMsuLkjU7YURx1NjPTOh9bKKzPGo5n0f2K0Rpor?= =?us-ascii?Q?aB6V9oF1mlisAoz8pkcpni2LrwjiJqB6PKwQXObz2AL+8A=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?FCIV5MhGCo9IrAnoXF075Th0YNkwPZA6bRdsF4IaYimUD6AMq5E3xWa483YN?= =?us-ascii?Q?9d9P8DXFDNJDiizqwE9PNKbpRyY+TAtv6eQCaV6C6GqEYp7445bDTUqc33IQ?= =?us-ascii?Q?z9bOzI+EeOtKoYsbuj/1LctsOgKRSXZHQbA2hvPshr1V48jzvaP8TOjKtH/s?= =?us-ascii?Q?pWsIkoQLg1fucR2SXjI/Yxp9ZidzV6YOK6OO5N5hi0PeX2a9NmzG/g9yypO3?= =?us-ascii?Q?++leKT0bq7Kg2ezbJsup8CCHgOb7AjIp8sUvmal4gARizLNIgzdiyT8i3v5W?= =?us-ascii?Q?9pAye1r/rVZBMq+X1LzIOJJ7upWjXJv5KcnyaVix/7GLOWPdLgAOnG/Skzsx?= =?us-ascii?Q?ItYXEbKy5qyqtYlpKoftNMdlBZsRBkF2lpk3tmJFpWwq8nyk9qv0zyzMMFJW?= =?us-ascii?Q?drlRtFyfQxPL9uW8OcVsrZUrrOVkAibQMqV96yaX+cE3wSJnAdGK+3HRNqnI?= =?us-ascii?Q?tpB6yYjoqifSXoQo3a5kwprD9wXR7ebiCxtUa1uhNokCadRLTFBbFW2KWEoh?= =?us-ascii?Q?8jCN/EsKnRWfDCpwiHt9cncqHJURqI3e++VqEt135IGDXVdOykvAjadOLh7j?= =?us-ascii?Q?B0CE8KnBdsRd7kyZOlnRPY3LzpLo64OF4bBeqUZtp1qF6NME+BwVBaE+6l5o?= =?us-ascii?Q?3kOgZJfta+bJ4h9QerOHBRomlb56TBiqDT5iZuMiGcETgf6d1riQ70u+dzi+?= =?us-ascii?Q?Q0rsFtzMLzlwQBLmac/I74+27vQYtiBtSqsjBXDodfGw0mLjIevBEPf9rcro?= =?us-ascii?Q?oloIIusAAs+gZ4Nv5kjrABJPqT+plstqwnHVP2xeNUHL/osc2wnCbY4+D1w3?= =?us-ascii?Q?8vHjcVr9l7nkSA3juUUKt7+JQR3DfdChC9x+8PsCG+pB1SylFHw4iru0wQyN?= =?us-ascii?Q?NEFbKAoTEq/i5weJyIcJ3n0ESaofOPbkGiZXpPT14W1Npgu50j9C4B+COcj4?= =?us-ascii?Q?qA/uAYB5oCuKFYAhgyRGvYDIzniDEFTrUlc/8zcx8gYawK1fAt8lMYbYzI7m?= =?us-ascii?Q?H5HdsvjMiEooDvl18ueai2nXyNObfSV8xLja9ppElG0rSKYXg7nnRm8TMCxm?= =?us-ascii?Q?81wBgYbGcAU5WrAxshcP/8g+ei4L4o+j+OMkzm1LgubOYAnp+7+hO6fNuCaz?= =?us-ascii?Q?IobB5rBAENJjjIsliuBmqFqqQpdUjlySCzKtOPD8ub2ORDg807pvgFlKV24j?= =?us-ascii?Q?O5mS+LIZvw8B+xr2m7jqspQDsvcOvOPm+4SMhL7eNO+8mfj08i0+W9kR/BpB?= =?us-ascii?Q?Kmuzct8k+urNKLzB4lVxZbOm4HJhaCZ3z8WRQ15THiyY/qjWhrMpB9I4zlZ+?= =?us-ascii?Q?aiXH45sFo44OBVNDziD8RSxu/drduPOACfJzevK7DtOXTKhmqg8b4XaNQNiW?= =?us-ascii?Q?T7fgHeORZQvoNOjkl2DA1KRCmM4h4UeCderF+m1ubb5EtEx+Fwu51SwEZ55M?= =?us-ascii?Q?BiUcNIPni6/utgC+D8r91GDOv8kvlCYW8i2uPuH4T7L646/4ta64eDrJ60UM?= =?us-ascii?Q?weHf9VKgp6RXairXgn1A+vmuKRPA7rM5LrGl7vVcJOk0hE+2vr5W4+ZdSOXQ?= =?us-ascii?Q?hYTsoVeZsWPivfbrn7quFUrgRFJgut+zzVNbwsGCEr5OhfqEdOmPUp6m2d8d?= =?us-ascii?Q?9GoBBVcokMgeXUtpqdA7w488fQCxgmPLsuH0SGKMnEXJ?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: bca3ad69-4960-4ca4-0343-08dcb8582992 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:37.7355 (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: q1qMnrcN24QAmzN18ykDaPRWwV6CLk0XS3l8DSuIY81G8qSanqnG2XM9Lj9eRFL6Vi/fracsUHBsi0vAjzVo8g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- 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..8bd1cdb39e91 --- /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 "cfg.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 -EINVAL; + + 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 -EINVAL; + } + + 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); + nxpwifi_queue_work(adapter, &adapter->main_work); + return -EPERM; + } + + /* 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) { + 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 ret; + } + + /* 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) { + nxpwifi_dbg(adapter, ERROR, "SLEEP_CFM: failed\n"); + adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; + return ret; + } + + 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 -EINVAL; + } + + if (test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: device in suspended state\n"); + return -EPERM; + } + + 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 -EPERM; + } + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: card is removed\n"); + return -EPERM; + } + + if (test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags)) { + nxpwifi_dbg(adapter, ERROR, + "PREP_CMD: FW is in bad state\n"); + return -EPERM; + } + + 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 -EPERM; + } + } + + 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 -ENOMEM; + } + + /* 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 -ENOMEM; + } + + 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 ret; + } + + /* 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); + nxpwifi_queue_work(adapter, &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 -EBUSY; + } + + 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 -EINVAL; + } + + 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 -EINVAL; + } + /* 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 -EINVAL; + } + + 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 -EFAULT; + } + 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 ret; + } 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 3E13C195FD1; Fri, 9 Aug 2024 09:46:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196812; cv=fail; b=hAcZxJmoqBEpM8pniAYttQwix02kvxImLuFVT+vrOBbDF83TcnEFU5jlFKFbG7OWSZw5oBXofPD4nbQLrMKRk0sFtb4aQT0kJ4uFgKOawO1PfGhIaqssVpbylfWR7MInc9OoqG5Jognf8W2NmUdskAIcxZ2UNi3N6/gvDetMwzw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196812; c=relaxed/simple; bh=sByoiV5NuBr0ysCpf+1cJYFnV3SLEXnzmkAnOe4dkWA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=jDRGqAtVMCpbbTpze8+ZCd79Nv8vAk7VSvmJu9Im04A8RbiuOYhm3TlbgvMgyF2Oq7zJ8QRL0XmHSZR6rLFUUU4OJF4HpzfaMwf6wcQXACUdD5UogFtzXxorZAiZq9sxct4+LUL+WMaYlQHcBRMBS5aHB/L6Xnc68Iw2fIKLPY4= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=QXHs0eM9; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="QXHs0eM9" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=rKL8LRqNbW8d+pK4RE7GKxbyhZ/C7murC1/vP9u1so9LXuNFJACzLGXPH+gWg+Sgx7dF21jHp/idsguLxIaU6HEW1heTJa90mgBHAamznnAVi3OBsclxOMYWkMBI+cWCGxhML5krAwhJXehKpCp9rb3j0rvoxjpWTrkJqT1vrRyOhOyIUj3EgmbzRVRQLmh4b4ACkLgmODqEtpqlyHqa/LbPgNA5F0QUXzoTd/ysTHJnOOjEuTJnBMpYlCxxMtVfPsivknApjwK6hlemxVdmyT+LQ63fHIF4o+1opOBQ9vhPSB0lPAzi/z+XiySer60CGYQUJo4roZEnVVA58JAJVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=WGvR0ke1v2oz4HbFeWbRfJE+qQcT48Bau5a3yFnvMvI=; b=rpBUCGhSkLdZnldI2jxJrd270TFPmHLnKfuqXPR5p1iEzHJxZ08K3WXG1twchYQc0XHb58v3msXU+EVlBtWE+WObZ/2/edrOsP+4VeH5v5VBC1G9RhC6jwa+XLFJDqgoOkTVYY89buiQDcOgB2dunwwzhcPmq/fwYnogDNOxPPj7NmGuadvJWvdZZU9fja8IsfVcuMoB5fxJuyp1H+xik7nHjFG6DwySJOpG6VQ/gjPqpaBzTLVMcRHgSP7Q2EdW9nS2tzDR6o49+Y3K8eRKRAHgy6WSB6YjQVzM7Iiv0m29qt86jse+/+Q/1dY8CZn/gD0AYlVsYSqTX+vxLrgqOQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=WGvR0ke1v2oz4HbFeWbRfJE+qQcT48Bau5a3yFnvMvI=; b=QXHs0eM9Lfw+dJFKpOP0QhCwveB9/XxL1wksVI1gkLs4OR8xhPN1kJVhRoWGQNdFbQXW4NHda1rL6v6waBBfrdEgYnw16AcqENdpqmXXwt45e1kH+1LFryoSx/hqUpS9y7KrYJ0ZlblwD3IW7PNRiYVh65/v0Nu+elI7iUowO1ajZj9u6KkLTTB+LyEseGjctxBqqywn69TzcVxzTZ/+slkHFo0PUmuC+FZ8TZDkgowhck4xvoDQaoK7Lp3fq61/yao2L/s0Knp/cPFSkOqjRc9w7ZNRl3Kegj6tgPSFibKi95MdWJKLY+7kLoyfnKBVWkrJfUJ3TzjTyWIaoLVsrQ== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46:40 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:40 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 15/43] wifi: nxpwifi: add cmdevt.h Date: Fri, 9 Aug 2024 17:45:05 +0800 Message-Id: <20240809094533.1660-16-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 1223687d-3b3c-43c3-48ae-08dcb8582b82 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?vn7QgSK4FTTpuCYxU30O9Zr1DRrnasqQUhzGn163yFGiwAUC7ZJQmf97XilV?= =?us-ascii?Q?wp/tHQbnJzB5VaoLn6+Y50mItvjBjwMzpFcmh+qcYvNMcmCGNabJX72gcgH9?= =?us-ascii?Q?WiOuOFzE/p+TcKMyUZFu7q/2gwpwY7drBO2jQb6LvpQs8z6EpWgzoMI2PT9D?= =?us-ascii?Q?4sQz02L0gmU6gQZ0PSZVSnpNvCfGNurp5J/NE9jD1KI1PPipdj25aRJwLwQK?= =?us-ascii?Q?ajqvH5Ge8RRlCUU5mpCNGPpo63/VANoRM1pn1oLqK1KZ0t81lbEY8GCxOjn6?= =?us-ascii?Q?r258FZX++QbRYS8oI5PKm5PJqZ2E5HATk2F/NmbZ/tf2FVT0Wfek4lo543TT?= =?us-ascii?Q?anojkU2k+EZ0jqvDkwl4zxOpRZY2YGwiZmp+Tfz8JwwmHczpf8WtIlvQFIml?= =?us-ascii?Q?AM3SDMu/ST6lUh+E89vnsT3RQN7yvkWCVSq4NJv+3DndDJBqpOE80zJBzPdL?= =?us-ascii?Q?BfNaXyiZqaFvMk9EJrU+OROY8byFH+03pIPAbfRera5pz1nsHRU3eFBEQZFR?= =?us-ascii?Q?Z/Q3QX+scGkzRKd+y4dFFtt6yde9fLpuzNUarDcvlGYVv7cA80Gx3XFqKPHr?= =?us-ascii?Q?Dyu3JcJzj2caRlVOyNk49AeymTIeXvb/M3IuIHFqk6dgrHiym+tUuc8M1YCO?= =?us-ascii?Q?yLb1+6415TrNbghZ2F0+z8Z5LpyuaLRdcThx2wFAMPh6jIfpfhlz/mZyLok+?= =?us-ascii?Q?9Q5egd4uLZB8CTR8dXAO7KWWSorhu0U3FC3Y1Qp6QwOrKBXDS3Ll7DPTsurh?= =?us-ascii?Q?qfk35b43/mcRgtuGCmOKW6t1KDfdTlDxkt/6YJ9UJR9CYYjdBGmINFIDeopU?= =?us-ascii?Q?3I8pNcrIAbz2NwWOAnfiyehlw5980V03+Cctjkbkv0JAzAzn7LepexdR4Za/?= =?us-ascii?Q?AatIlSKWfXOdazzm1MDucZwRvLFDSIJBcyGU/LOvWvBbPLiapzS9GQha56Tb?= =?us-ascii?Q?QueJkZGwLRYZQj3llvSDWtI0hqqhM9k13XGcQnIKSWo3KRehf2BC+T9Wwrhu?= =?us-ascii?Q?4JSgV0cRTBEryjxW0kR+2sWkge7m7UqfHFm8hSjZIE+BE8cX3znBj3h2h6Yl?= =?us-ascii?Q?Y7lY1CM/YihAFIzxpSYZY6/RzSpwcB+SUi7JIzWc/szdWOaY2iRtduxf/GL+?= =?us-ascii?Q?P24hUGn0VBwCCDJR2sR39u4rhUetZ+AtFyU0k3W+7bv4KVzgpc+1ncqk6Pvs?= =?us-ascii?Q?3hOEkLDxhVxapd+aNleeYEiZ8t40tzuTpf9HWIE83lik8vjzKuCsCQ+yBQ4T?= =?us-ascii?Q?7s9LK9DIObu0G4KAGomQ/U4ncDlOPwpIXqVtMRwM3wBQCsg8cqRclyf23yzT?= =?us-ascii?Q?soyX/Xeqx+0ZjuFSrRrIT3i4hfXZVpfssWDPbFqpZDlqfw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?cfpJc6JF4Y1wbEpSSJXuGRfLbDS+7V+qeok8gV5Le71q7JZ00xSsWRcvHYAM?= =?us-ascii?Q?wZMLONvfcs9sYkTCbwbzx14ZrSbYvmfNVhrJ+/yWgDimnXuYzvHWsqmhz0Ex?= =?us-ascii?Q?NXwrcoRXmieRlGlBXQI7KCo1W2i42o965UGVdsSdIKUwM2PpbmyPqtEkFpRo?= =?us-ascii?Q?JldjMrO1pPpdF2Gue+TEhCk8mVZxpB1Cz+g1RkYUvuX5CNSCOAFF1dWfcgCB?= =?us-ascii?Q?BTXKtJ+66gmV2i5oeCUulm2JmE5qlOamlpnyTavTo1VuKH0UUQZzWG/he+bp?= =?us-ascii?Q?9eOY3JuDaGqI0qqs76Qu4EIvk9aiO/c8TbjndTXQhOlbLWvnL66Rez225IZ5?= =?us-ascii?Q?Wh1+JLr6skKWdXHl2BFsHOs4WZ7x3boGaa8cNiKP/hARyg0wH6H4+STTIsuZ?= =?us-ascii?Q?Bgh88dylB3WJi7AslMn4OA2lN6g33VAtMAzzkK8pyQRp64H3MPMt0mCHwCZq?= =?us-ascii?Q?eXwP7V4eD4sld/XQydJgIrGifObNww30T5FliLL/SjYqlO6tdJOf3TnGveBm?= =?us-ascii?Q?Bq4qwtIzxWWr3LqXBOaaSKLgr8ffJTTOj/qUy6/FtQ2kgnrG+Aj/NGsNCLnV?= =?us-ascii?Q?Fd2Xjtl8lWa6HohgK+vbUXwiTS5I4BzlPoG3/LeIy/wxNeA7UKwxmNHwgMYI?= =?us-ascii?Q?iF06hZJ65LUhg1dcdWVnEnpMrMZcu/QQs45xG7rt14L9R14cgRFuYGtA75hW?= =?us-ascii?Q?OcNWYXM4MbtrCgacJXhvXx1x2OJzFo6efFVj/SajeaLoTi24o5TTTlw7janb?= =?us-ascii?Q?VVPV2j0yTWvNQtbdJNF09LpWvBCsKzCOUwDwL+jkpUCzuDBFT06WN/uurd9f?= =?us-ascii?Q?4h029WSfyZ8yI27X39wE64TPyb+DrYM5enXyRixzZpNl2nBGm5iYEtq9MZhM?= =?us-ascii?Q?HGEgaFvi+f/X8aT3xjvAF6T+nKQqy286NueOpSfjyFp0DPSChsNUU+MMB0dB?= =?us-ascii?Q?OhD+y46a3Xb2v0hinBC64yCPhj47vKxSoo2HCeG6j8bVG3IMUvq3+o+anfet?= =?us-ascii?Q?ZL3myXOIEVVP93eP8RrPqgo6jINp6yHrSMJxfQWbsVW+x3rpaZjlv8+rpuun?= =?us-ascii?Q?QEH7xuypzkUHOfXlT9FLAfH/j4PixvuW521SXTPC0T0Yjf45E+sUPP3EMKUV?= =?us-ascii?Q?p7h7dVE20kNIB7DOaB5lPvXavWWk4CuQ/jOfPIVO+wBCpni19mXKZZKYQxM1?= =?us-ascii?Q?7DYNKz3I4+tu10nFPSj65u690yD+jOA4M4CF4MjN4PaExD1kWi/qSd4+GedY?= =?us-ascii?Q?IVcmzUZ+agVngS3BPI8NTuk+jczo5KXybOpNT/h8nTjnahHVV3Mns3Lapbry?= =?us-ascii?Q?g9YeuEozbJeBoy84RUYX12b379ShH0DyDhQJp5NANuQ0w6j9jzskhoy1tD4S?= =?us-ascii?Q?7m+oCpxkFLPVE/XKcYTKlUxfXNeqUy4s6VNMWKAfSwAuQI5nvjh0VH07JrQl?= =?us-ascii?Q?8SkLniLe3MwXLfWSGZeeaSP3RDHVXR9ZeICIKV+YxbMtvNVFHG+YlphTZoHl?= =?us-ascii?Q?FMk+BfvtpdNr4uusIDyhSK+mSDgwODVvsA8HSkK+ZcTheVecyH3cKvYHdPYf?= =?us-ascii?Q?0SzZtONZsM3sxsTdZ/d+Dk6ABqvHNH77H2eG188VlephQeAqVA5kXECERDqQ?= =?us-ascii?Q?9aoCEjhx9DLb0dFV2Elav/2+l7iLUNJQASo9yFVU4q7h?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1223687d-3b3c-43c3-48ae-08dcb8582b82 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:40.7761 (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: IgTsWdsRO/dpL8cDoeaAK6MkzQ32HsPOBzwXCqfVwH46Nk2WbsYmbIP/si6TrWABOz4r+o4mDuvCp5iPPLV4KA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 2A25A1974FE; Fri, 9 Aug 2024 09:46:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196815; cv=fail; b=qfGY2yx6K2qVXIKRjlwi6ZbDcQxs4M3SZrtfipgsWNEDk+lCnXdaH83qcVvnzCuR2GIDNL78d0Ws5npy18bv2GazNP1jOXkxNZQ2j/d78+22nQmEhHPAIJNKJV/vvA5Qjstmm1G5VHIouDN24aLCWPJlNN50YHJ1CeM7+pq/hQk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196815; c=relaxed/simple; bh=rCuRIgysCkC8jmUYDplCaucoyYkXkw9glgGZxByP5Lk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=cJO8kcx9b+OSLCjuaJu0FOiq7NnIRoR/aULHJxWqIRgl0VfC6kuWYB2DA0UJr4n8iCb3NI+bVl//4+Rigz6LMsueDr5Kk9Mv6zZOdDGNWVt5ByU5NIO4WaenLzcnzR7dcWFYuJBfSZ7T7qUI4YsJf+xl/BAAGjAPnzfzdnd3J4g= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=FGinxDfo; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="FGinxDfo" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=KdgobPyAiEZ8UiYekprT2NFkqFIgEfjcJAbnI0nzOfFydsMYQn8FNAJVKBMdDInEvbqMLXu96qt1x91nh3d8vAbLHxoNf4rhUSmf4jgdPfCvKmGCMD1cT/xyBR8QNhOPG+I2nMxUOYttDqNq9OtJR/kM89F83r8LDkvR4W+n1O5x/le3g1DVH3x+Iev9bHUFds6RB02xxGT3V/rX8z0+AU7hw8RcgfhPaWhGidkA6Y872P23e7I8LPOIgwuR9FhHE8PvWpDXqBAH1SlbE0sjfpReF+dIlqcC8rXYKIrwsEtp9EII1OSDbT9zTUQcMD/U9yQTNU0MPbEYa7NdqSGaJQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=dPFrIYLL82q+pqGXLwMyp/wE9AFpwXImrMeLmKCD9t4=; b=ufnZPuhog7MW8BHZWvB4VGXsZBTXO9xuL8Q7Cw5wI/ktgvQBxP1J9YpnZDAhP+tchysHa8Qv1dOWJTpESbmVmaIfqw4/8Zet7ciasc4MMsbyHIDUIk7OGayOS7IYzKVxyVi80X1NZbRh1m5BwaDEn4KJ4XveQe/t5bkXr3hC68iQ596pQ/4NibI56OWyhfMhnZohzWsfRTE2eZCec7C6ibdmylGtWHfm7HS0eXlEg7eHho1JWJInTx+u5NOyr9TSsznp68H4lf3vz6P2an4VQHc/KjmDZdeRhiutcZdd9wXO/Ca+wYghTt9f0R2cHKVzLinGymzGF6GFXWScLIKKCQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dPFrIYLL82q+pqGXLwMyp/wE9AFpwXImrMeLmKCD9t4=; b=FGinxDfogfxsfWjb/qo5RwaDtBLpxZzs/nllTw5F4hE9ByLMXyuCoj3jm2Rk4VGvgluYtMaC3DuJW2L82hary4m3Jeh2OYAqbw2aUn//EvCsiYZInOJIu8C5xb0OObmf0Gh5K142gWcNj0DrIzUh1VPQY9c/cG8W9oSxlj7PxoYTAEFN91snTnzKxrTI0S+K5KAs8zaqiTe2wkYdydC1Vt2qAl8Osh+iUu/6dEvjU+FiCsUWqGKtSHHC+lJLdlbDdM9rX8S70lpKYVwcd9puZPekeXe64LfXZZXsvx4UbxbW7H8acnH9RZltLu1qswAal3V7BR/5gxTxU8PGlruJYw== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:44 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 16/43] wifi: nxpwifi: add debugfs.c Date: Fri, 9 Aug 2024 17:45:06 +0800 Message-Id: <20240809094533.1660-17-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: da044a13-78ac-4199-6abb-08dcb8582d5e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?dD84lBPtIPMhU3WFX/Qwlb/5qY4VaRFvpLaPbqqrYctPgX65mgUGC2rk3Q6v?= =?us-ascii?Q?/NmFMKUofrTQdHKxsvTHrzd85IJOIcCbQinvCMJT+k6/VAT7qRRe94IKc+fk?= =?us-ascii?Q?3hBkooJj4xEqfHiKaDpqfp5cLTeOdjccXvk1UEI1B6UC42TZBVtj1B8dcmTY?= =?us-ascii?Q?cLaUNWpwWZdR0/b9OORa3M4+gOri+UXWnjfLs1Jg7bGBWKhGm+VQlYwvuVJg?= =?us-ascii?Q?YVFg0DhDESUFXrXi2Js4dGzMNRY3mTzReABBPpd1i9vprd8JVj42EQU8haVO?= =?us-ascii?Q?PJ6cxQJczuAo5GR23J9WY9PU71SS1voa8HSDkvEBaokOJLWgxgLmHCECJZel?= =?us-ascii?Q?tfZvez76re7VdhNXlNmhTOQ43DTI5qJcGTxSPb7WArxZ7+V4D5z02pX/bTmq?= =?us-ascii?Q?vpnuHCuMe8OKjzknGVmpx3sHvyTESnYIyqQtc7ybq5/1SUkXfWSah61ToCuF?= =?us-ascii?Q?Mzd5tzZ/3semwcAEDIfNsmW4HGOELtRkvEuiFIW570Pqv2GI53aThfDoxmi+?= =?us-ascii?Q?EZS3Y5t1eNbwOA98ItJQjTbnQJDgNFY4TrPPAHSYnlN358FWEKBqQ9qfkaoR?= =?us-ascii?Q?nwfZ5STbmyTmVbrN4PtNACR3N83Cyst3p0P2P+X3PzUYZ2N6O3oNIBKmEe7Y?= =?us-ascii?Q?6NTYWe9wRHnraOCmmNc1wX5RwBkp2fuwG8L+2yAmnPOVNhNNxAfgcwMfRQNO?= =?us-ascii?Q?T9Z2v27qZkjREvoRFs6V93h+f4IGWAbcvyi4rioxr5hW+GPWicFCQmgLuja/?= =?us-ascii?Q?bW+iVB0nrXklo92+KAqUvGXq1KVrfBXTubNsjWdB/mUS4p/J/4uVOgk+FZUO?= =?us-ascii?Q?YpHEvwhWUoceZsi1elo4GFJYh3vAXEVcrXrMU7yHFwLsGcCC6OM/RQeuuYmt?= =?us-ascii?Q?aUX1R+fRmtY1cnwwHnA1GfXmP1u6ujm4Y6AJ+J/WWve+YuOm4Cv8bkN+WtBa?= =?us-ascii?Q?7s8YK2dXfHCSjp2GzAMLFhyxkR/HWYjXG63aAtH2XIj9bro51HvgK4kizb0F?= =?us-ascii?Q?ButwPAIc3pHc6FcrrMU2I5ynk5sDbbTx+IU6i631NzptXhKyPoIjXVMvUiG0?= =?us-ascii?Q?XRCqg1Z+R3uhOY2hFjRi5MjNjxui81Gcb2+cVGpwuy5HPPhfDyvX1fSa2xGG?= =?us-ascii?Q?uRIslmQfd6cYFOQBd6wacaGSnGrIhyG5ZTUqyOBYudT8udacO/Vqz7ZCgG0v?= =?us-ascii?Q?N6EPZuWwQ02pW0z7dlS/Foy9rENDM+ZHc5xccKjsmX51PXXiuHvq1TNjmDa/?= =?us-ascii?Q?+ZpJFv+9Dp2q2jNBlOC4IdLoUfCa1EOF0c/UyPCGTAWn+b3lQ1a8WTNK8gez?= =?us-ascii?Q?p45SyjRu5d7vmB6YSP9I3FPA0hiIXWH5NZnjAOgqEM5Lbg=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?L4t7M7EM24DI/OzUlSW3KoRJ+Zxo5cLTvy9F6EhqpF3yHEswv7jns1nJOBEZ?= =?us-ascii?Q?uQAN4wGUksttUWba+OV2MgqoXV4rS0N3j6xgQjErVUx2uJsqgBDfP0+Fuedk?= =?us-ascii?Q?TxyaamcwyCkWko2pV8q5bhXVbQrqQ4A9miVdxVobbenZdPMyUrE1MaBYfIYf?= =?us-ascii?Q?QL4SB9FLSZzKJyBBBruuDVaKzOQozJ1n9elaHiITj6+y9U8lFqYPtoTtzkGQ?= =?us-ascii?Q?y/jfT5kCFDpyTXiy8xUGOH8/0kIczwWjULx+spo5IZhJk6WWHK01jbsaFu+2?= =?us-ascii?Q?E/F5FLtQ8aoTxY09t6CjEFylB6jr1e4hRAsTSV9sYxNDNTp651xqwgbu0Jnq?= =?us-ascii?Q?+Rx4m4eQa1ArIMB1pir2XqJ/FWFvucjsvK3BDNUkHLPAGCJL45I8cmIcxr73?= =?us-ascii?Q?Kt+ZQcz3ehq0acMT6uui1wMsV/0/7oFA1Kza+CO7M64Fzy9umhP3W2rZoFPB?= =?us-ascii?Q?Mh0nF60px/X8XzF77Jr7j/NgZJpOEe6vCu4oxiO8cH2Xf9Gj29NNDlTgg7vV?= =?us-ascii?Q?8m0u7JX/AwI7BDawDEYHgWPr7nZBmADQJkoxxuU8/7Y0EBbXqAe4hDEeh7cY?= =?us-ascii?Q?SObqlAMModHX6v7syzfpnkYNw/Pe+3QsXPGasobN91v/kGRiouJx3Jmb80u8?= =?us-ascii?Q?DWAdyqqdk2sW6aYoN8K91V8a+LvLbYF8GE4e1EiJknRmLqRBo+hSCnGBPin1?= =?us-ascii?Q?Z7LJ0HPl31dh2jAKWGKG91ihJ4fYdhdm6QFoAck8Ceal0kQrMXgCf+//IXkN?= =?us-ascii?Q?E6k42h55akPmw+5nSPCSjdrdwMEpuWfUv83i0uk3tOtK/4vV9cFUWQpuMtjD?= =?us-ascii?Q?0rzIXFubHADMOZjLagPNu3VX/YB6bLv4n9cuvLd79Eyf7mtwDxcpYMT9SOLO?= =?us-ascii?Q?umqwFn3Q79kHWCUcribcj9MSNJCpeIGfAzuuuSta9XKa83EgC5d+2O+nCHhB?= =?us-ascii?Q?riANMaAXOUpXQkbPVFpxr1PE6JwOB7jmU6fjEBU1qnnqVnyNxEx87q2+/KC1?= =?us-ascii?Q?IRJhMYJRfO/q/rxt08BXU0tW+5Me7srzGx/OrF564mZv2rxoxdXYByu3HeOP?= =?us-ascii?Q?ZIr3b84T4E3zQDDgPSRvD2U99fFGX9MuieI0AyrdY2rcx93p3wOF1fPt9l3F?= =?us-ascii?Q?Qpa/aiD8w7oJxg9f9cbAHw/Xlva9MQZ52JnAl2s4Rkzwdmd6DsRX08kRNKND?= =?us-ascii?Q?bNAM5J6pTUZwA1lANuQ277kiHD37Z9GjvbL9fwJSAL/8BRBEqK9ZCgRttUbo?= =?us-ascii?Q?GazfJ3sxtMQdBoDDMryTo+VKV9qt+fOkELjaam0Ex5TeMWQY397jmKDlVfD0?= =?us-ascii?Q?RRW83KUXklPexr5sQprijRdO93CQ/zpZauA8545MUwAuzVmapjNlef2AfaZU?= =?us-ascii?Q?1ID0RrUNFZp+3E3DEDzPJW9SE0AqgAO4zprcMMGN1EEfdwq1hA60bFbVbgxW?= =?us-ascii?Q?VgJl+wq+fOXFvqm93g3ecyOI1FAySOMsVa7dWEwQDEaI6+MrA59CSafTjmxf?= =?us-ascii?Q?XvMNPjvlv2Mk3/LrkDEX8nWj/FQEMbWb3Oe+RlwaQm33TdHR/l79Nmg+ES7n?= =?us-ascii?Q?AXJ30dbbh8pdg/Qx7ViwJXqdwppf2e80vwaJkKemso3jgFtIspCVY68L1Oft?= =?us-ascii?Q?IPjr8wskL0adXW4MsNCOCTZMYh3PYVPvinnjQpDE25kf?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: da044a13-78ac-4199-6abb-08dcb8582d5e X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:43.9589 (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: VuKHy6ApfbTQDQzWJEWFwpwz5KwdwsXQXjDqSphl2B/mQhKvvcVuF72D4/XUq3wnlgUL+wvowuDzH6UpkbagxA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/debugfs.c | 1041 ++++++++++++++++++++ 1 file changed, 1041 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..a8a5f815f7fa --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/debugfs.c @@ -0,0 +1,1041 @@ +// 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)); + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MEM_ACCESS, cmd_action, 0, + &mem_rw, true); + if (!ret) + 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 2A427192B87; Fri, 9 Aug 2024 09:46:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196818; cv=fail; b=lJ/4R1b2tNpdgd5XHSbD7d9n8xznvwZkEOw8dyLJXzbPdixEFmbu4ScBMR6f8/sW4z+N7Nx4kOxjTwbYLQOabEBEh28zpKfIbbOoPusSs4qQab4jB1ZVAERM4wedQcpk7C8eas34fHEoL/3WLqstRQVmvEufMaKb5zlhgtxVoNE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196818; c=relaxed/simple; bh=4jneY9QPHv+/KYl3GvjaaIAsVBkH1CncQL74fk8/1a4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=pTS/zpBrx9CPddVmJw/WQcM0PQJcivX4zVQveygPpq5wDo65q75xwdoyIrxKslRjjFTBzU2pli3tBYxn6uNzkro3zS94hl2BR/TfWrlF8akUOqvjSCzkIqn3nqrHt9NKsPketCAJeg2fzG+uVIcWh0DVbevE17pgSXb4ShnNt/k= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=JV8E0KLJ; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="JV8E0KLJ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ClYYBGGKwo2f3FePuv41N1mwVjZNfk2assR6zoiKZONtNkm3HMhVQjDo2lzgbx8liaBIkSDKFeEhDPdZ3bhDG+LLF+AgMT7p9Dbua4VK4Wf4CgMGEbgzwYbExNRyROGpK6255y/G/7/uwZejAmOHnxmEi7PXu5elLlg9ZD4gVlTwztFuJCQ8mQnggDGp56V6nSQh8vRuOC0Q7N9HeX076NwoyTEXBQGXYJVYHhWty984T8BWjQ9ZWXjA1NZuU0UdSqdgZlmXvI34vhuen0W3os550Hv+G4ZW0fMYGAQtqWjIEnOR3ZIFLpKwzRTHFQhcD07b8was3Vj3O4rN4p8/fg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=0+9PUGqbaRn9zMe5jATArZOPJPjoi0ukRVI0tRimJfM=; b=y9LKuNZON1uO6odCHQUCSFQClTsthEAQg5pcX0I6CWr8zBz28XPrbEGihz/DOH+lzOvzKbBPsDRrT5uf4HnHthPaDe2P3m6Qiz5YWgiT0aNfbx8trgMzDKifpwZ3HPU6Rn0a8d4Uew191zKTdBDJHnF/u/kTlMSdDgaB5Dtr83LEyV5pvxsJiiNop0oM/vspfiKjGTk7jQGeWZgxXlEPplO3ZjbDVtumNrVzHYKoKcgI9F4GgII5j59Ez1qDXsRqZWNpYV3UyIAt/wddxSxq/PsQDY6aJK7YKpcBf8oftveQB/q0LMIGf37XIklUc/ekSRG/7RB0LOaB1rWAFLCewA== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0+9PUGqbaRn9zMe5jATArZOPJPjoi0ukRVI0tRimJfM=; b=JV8E0KLJC2cSVG+p3BV2Ku5YrSH4n58ZUjNOpbHJME2ngl5m2etEYItEzYwf9G3FsZG38pFH+gf1xTqiCDlFFqPkfF9QDHo6VcxzQWi8Xgnao5OfwnuK0bQKxtvhqOlmNPh5OGFx0h6P7Wo9pGKg2M+fEfp53/YrPf2V60TOLjhfGNnW5M4tEdiIcNA64BsuWLfqBgTtRkmu6p1vT7FNR/jIkI610jSBrl5iw9x6KUYVziDqFVUeQfNR2nEPqquYk+Ym3/3m3RhCOyBi9Ica0yX5E0Hj/Y9IIvDEDFVjmTdw+k5j697axXnsEAOYQyBg+IY6RK6P+fqH7AP8YB3RhQ== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:47 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 17/43] wifi: nxpwifi: add decl.h Date: Fri, 9 Aug 2024 17:45:07 +0800 Message-Id: <20240809094533.1660-18-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: c37f16b2-f20a-49eb-0c5c-08dcb8582f45 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?BjWGqmRi3nheJPT1L5LRzgYpDgSqsjOtYygViRzPTENVxElMkwHlQyTVqDqZ?= =?us-ascii?Q?JhbZ6cSZm738sSRmU62dBc4zJCnwaNeV52/ISz8vDVBa5SjNV4/Z6V5aEnrV?= =?us-ascii?Q?aLCoCTUqzUTBML9CixFujV9zSt2shQMd7MGUH7vRIUVk8sMWagHSwuulKTQW?= =?us-ascii?Q?lDOqVcRVx0b8RHF6joEZBJayrHJHSgBsn8b3OrcXZnHPOf8iL+c+S8169tU2?= =?us-ascii?Q?g63c4CvUFnonr1CliUCv+aOgdrQZEjFZPD9icZayU3OBYbuSrmH3tFZXLXEA?= =?us-ascii?Q?OwsN6jn3oHUylgspe8sZNND7yzG1hEd/rbWpDw797REun67fPY3Pstq3rIuf?= =?us-ascii?Q?Gz5FT65gd9h+6Jnd5savGpah3d9/ykeiwNZ384cdRJyyT91eSaFgPshRYo8T?= =?us-ascii?Q?A1YBf1c/t2FncGVyuq4LKiN+qKdxTK+dZcyabUDnGzbqd0T47iCB0d4iQNa4?= =?us-ascii?Q?bJrnS+OYjYwwGktWAeg3UVCbyDAqeXMs7TGBIl5Sw55AqLqUf5i4eRo+Ov5v?= =?us-ascii?Q?TK/vRZFCY13T/cbDemL9PwqWxtjmIygr9qOwCc5uRaV/NJxnmy9im2BEjzHb?= =?us-ascii?Q?/6PdMeGvwRyD40+opw51kt8w5l0QGtKQPQSsl4kFv83z5ZBrrABk1zliVIyp?= =?us-ascii?Q?f467cQqhJf5vJ3ySJhUCn/Gunm8zdcBPzR3bPnL9ra4lRUENt1d6YNi/o/27?= =?us-ascii?Q?dr3Vl9uVkpBI0PP4IvxsiuqN3yDsGlal53o7n+gRO8KgYpIzqx40Cwi+cREW?= =?us-ascii?Q?VOUgRLbFcZz1i0bjqmA/Be7luTMLg9b4jR37nqumddBYFx4bMixuHgVmUrS6?= =?us-ascii?Q?tQQSQajjewCAwEHibk5O5pgbssEMQSX9z9tkrG97aD5xlHVhD9hK3QEV44MH?= =?us-ascii?Q?gsRlwHmjTnoT3Mw4cUNbPhe9WOp2dORkwp5izrN5gUbziy/4bHq4x2WGTKAV?= =?us-ascii?Q?Vn3xqMwiw6t9pYWyHO6zhevADD8XyeWWVn8qjY2SQbMrVKF1kazNcBR5VGaZ?= =?us-ascii?Q?D/yjwhBx7LAl1z//8Q7Cl0OkkmT2JcRnCYk2vrbGJO4boVdGFD6yrueWKnYl?= =?us-ascii?Q?eKnT9btrjkrVpWDZEpZpu5LQINDrHL1TP/HqR541iiTM71ccS+ZwdMnzMCXs?= =?us-ascii?Q?OdFWeiVJS/WvO3wtLX4n/qeRLUFQUTZ2BHF3OwDbnGieARL6JmUCmqVqgRJv?= =?us-ascii?Q?ZNCLRLP87/ZU8YngeHOoZEKMSCeSN6ht+UqAz3UlMj0uLIZvVSjhT0e1L1lR?= =?us-ascii?Q?HJ6vjFMUyjj+a/6DRbKLI728Bripj7zMvIom68Xo3aCIR4UH5WG6qbvun6id?= =?us-ascii?Q?ZMaknBUFWwoMBdYTqoyZCOrczaejqnlxkS+2TZHUnICjVw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?z2UmRLwNd/7P4/qvFkiDzUFmXo6cNmWCzglgKhUKqGqtv1V1RcMF6vEcIzEm?= =?us-ascii?Q?P70aS2tZ9grYWzAdTh2y9uf0gryi8ZjI2OHAK+sbwADaxVxlpbZkQAHDCkC8?= =?us-ascii?Q?QS1jRMFSxgimTAnVWLGmzB6gkDIzIvZL15ysrK0kbzq5SgYWfFTgpp7dbpej?= =?us-ascii?Q?8RvxfKDovF+bsYvULsaudD6cBIHFf8J3QStU8YRFqvQFho1l8VH5pASFcBIJ?= =?us-ascii?Q?DzLL4cxjyMQUG3IYDlihhrtC6UYu0/2Ifn4SMH0AYe1GjMn37+09XqPG3KrT?= =?us-ascii?Q?IZO2eGRkbQcW6/ehq32FYSzv7pUKThz49ydgOKezqzjeUOuLAxuD+SqqOvpT?= =?us-ascii?Q?4eg5xNDTeLPotMZOCqOoMxI8TAEZP3chcPUYObGkk3X20zoCO4NlxdwA5FYi?= =?us-ascii?Q?uD27NBcznr6UYbaGUDzcM2mWlZ/qRzXRp/2RDBV0CsdtdfWo+fITgwid6yvT?= =?us-ascii?Q?OSLaF4DIzk1fViN2Zrp0TAmy/RYuk83xfd8mCWR/yVBzsrIFw+tsaIReNFyj?= =?us-ascii?Q?pml9o6lAWG9DnAbZkks0RpTu0Fqnw+0N20S/K9r/f1WlzGv5I99yfbEK0+L9?= =?us-ascii?Q?q09SyX2CzRhoGFplWZDmc9LMvw4CZgmTEmeJ4HKqI09ZhEiaEQQx1bptyBLQ?= =?us-ascii?Q?ZfCoE5eG1DcIWS/AZ+9Qm5XUGZETNoPW/hyCiavqXqkWiqsHx3vgJUDcEKnk?= =?us-ascii?Q?Uw70pG5xzmF8KLxxneGu0drh7oYGTi/I404AeHg7E6E99aeqqTZZ5/U7aY8e?= =?us-ascii?Q?j1Nf9Nb3ypuGhYbSqshsZTyAIrtTVuaP7NvrEdaCdvsO9kawVyX6vsUPgkxn?= =?us-ascii?Q?zNpJgKhhBd0NBvk+7Ab/D5ilYkLXZTkuo6b2qdFvFPhMhgba3PulVfc44oQ7?= =?us-ascii?Q?IGg9ru2Q+XATKFD9BvcvIEQPCBdR3gLi0FBxTalFPp01ZaSAI2AQJu+bbJFW?= =?us-ascii?Q?Cs+KAcnx3JeVjGSF3Klc4ZQz4G1t7qudnU3ypdPdfGMTqrmokFcjNNos9+gW?= =?us-ascii?Q?O1lmV7L5Y4GNQIv5LRcQj6hy11za8X5nCtXpGcVZPmNhwtBImM7LCMVVkvTl?= =?us-ascii?Q?euQookQBSgcO9StmU9Faa7gumkPgq9ZHB0QM4t7PX0PqEoJBs4q5wtyXAOEx?= =?us-ascii?Q?ko/c0BaDOzVg4AcGXncM4APOdj2iXFEVGhiggULykxzbe6AyJvhBF67m/zIy?= =?us-ascii?Q?L8ud+NX/hPXZJjbxWATLuizJD+B856SgEgbRK42cPnoxCoKn+saCV3epxLQa?= =?us-ascii?Q?y4rkCNFV4gOOIigbgV3zPcQ1hW0JSa0AOoEbUQqhNjzEXoVGGXDiHQYgMXB0?= =?us-ascii?Q?9OxWyYLwUsk0jCsuxN/Q8FZKKdFSYPZcKeKUCVrv9aEgiHWjdqjAw72kn1EK?= =?us-ascii?Q?6aRl91L/YK5d6ncopZ5JY2P0ukH8usBVxp+ZkQzzd1b93NK/HYDdONUD97Y7?= =?us-ascii?Q?olV4GgOIBeKDJ/GcLuktqsNI/ZWuqgb4+Wm1CGqDHHNeEox+3INYdCKpyrD4?= =?us-ascii?Q?2x/TcFqcL+W5SPLNGK1CPST5qLYP9tU+9sgquMg8/B48JxE/MxfrYRkak8me?= =?us-ascii?Q?/4LkelwcyLpAd18Ms5+Eyc9XIt+E67ZZMTCA5u2O2ZsjUcEcfjPg6QX+Ie6X?= =?us-ascii?Q?6kiWKgVB0ckHRVoqT76I8ygpLUxJDz48EDhVo1LbfrT4?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: c37f16b2-f20a-49eb-0c5c-08dcb8582f45 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:47.1008 (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: mmQI055HW92zTc1nxgN4H95ey6zQ7tSOxU89iRLv+Mfk3lezhWXp465lxGxpHKQpda9s1kNKhH8pP+tH2zm+ug== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/decl.h | 294 ++++++++++++++++++++++++ 1 file changed, 294 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..930f777f064f --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/decl.h @@ -0,0 +1,294 @@ +/* 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; + u16 pkt_len; +}; + +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 nxpwifi_types_wmm_info { + u8 oui[4]; + u8 subtype; + u8 version; + u8 qos_info; + u8 reserved; + struct ieee80211_wmm_ac_param ac[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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 8355E197A9F; Fri, 9 Aug 2024 09:46:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196820; cv=fail; b=Yi6n1n3MU8FZrwqm5H1eMONAXNIY3UPgoYD92Io5OM3xkF6QRZQ0LeV0BsD6WtDJ6Tj5f2JqQyS3IVAKSJU2iCEbWXYJTKf1WPwbHrdArsohcI/G1XXRWe6TTr7O8skK01T1ao1VbF7H/+Moqyp4dU3AcvpvHXxmaoe3QQQzPj0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196820; c=relaxed/simple; bh=iPW7EHV4dQiVydUK5ulmopwJMF61KcLFxV9VKtsRCjA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=LCqCfLgGW0ASUaPVzoFt3DELHoyYzbzXRJDLMta7fChWSb550HC7VhqqBsGls+eW0eBNOd9XL0RILt6hOvaC81htpH/hKM6O2JjAKqiCUy6HTZJLOvVobCSP8JOtRHio+HDRGgIE7sDSpwyZssvEmCOsQ7OPK6ahzQS92H7psHY= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=T/hmNLA2; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="T/hmNLA2" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=HyA+qKbl4OM6JoGDokQvb/tQOB6Zm7rz/iUbuWtSv6KlS9CAEX/eruP1sdJhzyvRXL3ZvBmaNvgZrscNu7pF6iTaAHnOiBTth12tzK8V+MGwJJF/Z+muw0nTjSIPdOeK4sBaqBSNBq+6eFuyjF6taPvERa0rR+ls5KV1eIf2oajZEiqN0oS4OzHuEfxLXjlXYtZp3OMnTHJrpVt8Wv2G1d4vjvgh9ah+NyWA0MXH+4imZwisc6iVS824bTQQLDI2MIssAirocF7FVoLpa47p3gbcq45Wkc+/XMHwi8ngbtSuc2Vi6M9psM7nSlIjr1C6CCdlnr+Q+LfTWTo2h8svtA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=Kp/RnIW8RGclZufIVPDrZzne5U+G9qMYZazV6y6yN1o=; b=GTPphNxh/GXjDOWevUPlv9rUNwX/UFtOqV/YMAbCrVrpqFbQym5y/PfTY1f7y+4OpIVJ/Y9P1SMr8zNyiySRxvfX/dDqziRtvsfxSUCGq6MhhR+l9vunXyyS/aC/wqxSXyou/EoBvppEYX8dDZ1xnLq+bKQ6Dgyks9REVo/jqpcXqsrmKxTVTkTn7Gm+uI9b2AICCMGUSMhA37hOH7Eb0Bjmd7PesHGg3YF/nfgBcvQ8ie7jIjB7OV7I8vvsFphK6DhhZuakIOOXVDoiIuOtJcl27ahBjMFOEJwtNfEr9uNwPcS9yFXSZ7DoeONR+jSODP9hvDQQLqf5v2/MhvYElw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Kp/RnIW8RGclZufIVPDrZzne5U+G9qMYZazV6y6yN1o=; b=T/hmNLA2VdEnKJROxaPm7cLClIHcdKQbd1nWN/L0xBNMWOKd8332v23ve1tHU63tZzlYsAtKz/4RWaV+dmBvwHlVfdqXPZBdS9HLb8vTE2gZwbuUU8vAEzJOmYPSIE/Mvi4lY+7/PWpyBDVCl4UhoaloUHjfWuixWwjNP1ly/mueZ7F3c1HyxBH14nv+NoAaWyj5NligNu2Hy4PxUR3Dm9IHTJjYlVbsTsGTb1I3MumqFCYUfjU33A3VHT2AA6cHUZgiD1886w9SJCWK3MTUXz/da8QJ9lrd+vjHuEJSVvzm3jHSd7Bsz58qyxO2pye4/vAhPF4msLBcnlR8vXXRSg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46:50 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:50 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 18/43] wifi: nxpwifi: add ethtool.c Date: Fri, 9 Aug 2024 17:45:08 +0800 Message-Id: <20240809094533.1660-19-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 6311fd95-07d1-45f9-76f8-08dcb858311e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?YYBA6ZwFrWZ3LsfEcFHyMBYniIfMSGQghhhuVP3KTbs+zsi7G1I/yipCxGTf?= =?us-ascii?Q?megnmUhERjnd7hxG2XG07ntWz8tupFJTNeqdjt//MlobxqiBeyG80b/NNCIP?= =?us-ascii?Q?RBrl2SLJsGrEjJWcS3C8RyChjNEXfEWwXunhdkI6fZXBESIgGmM2zW5GneQ0?= =?us-ascii?Q?8HGS2tlH4/opwLOiMMvu0o7en2dtHgaxCZyrn8BZRjZZUn5Hx1CUWhIGVisI?= =?us-ascii?Q?+9MAJGvGSdNqlChiRvm6nBUXOOVhgoD0Rx2n+C/WUHfjhMPk/rjbAyYBg81F?= =?us-ascii?Q?myBgkmTOTbKlZTVaW/X/zwzWsQ8gbdEiwWixn84QgqKK1uIlGr9viAqsINPE?= =?us-ascii?Q?6DrBNulaMjmla+J3vCcjuSBL3jjK/R5SWymGWjFYx5r4ehUUtpyiNEVTZGLS?= =?us-ascii?Q?r+mW47PnRDwH0RO6MbYulQoxfGI+27rRz/lkZ6QCBEG4YtTwyaQsDfuHxdOk?= =?us-ascii?Q?XWrxlDhCpPqKlmmcvLnU1NrkA3umgLy6KfevR9khxwRYYLePxFT9kXwoh6/e?= =?us-ascii?Q?pozmScckd9vLsbPl2mGUEtbI2FewVaHWaD8nM8Oiju8yYXJazl5ehq9MJ38B?= =?us-ascii?Q?QjfA847ofPaWCDrvx0AEP6HvO5g/SBExTBoah4Y6vAxElEAzY8365WtVWwM4?= =?us-ascii?Q?uafH19PxRDyE817Aesvi3WErcDQ3XgRv+i62npw+iHmh9KjNuDtCkkUdAb+N?= =?us-ascii?Q?IXhBEKWkk0CdY7Lh7J3x7IY8z7Q4bciI+0LlFbbNS26ze2LW8Ttcbfspy+j5?= =?us-ascii?Q?cC6N+mE+gWo4Sc51uA3UE95OOVaLYnk2k9Hee94cwk83WtUhdLfEbEttRQHm?= =?us-ascii?Q?Hr4x94SOMvt6TV7FalHfebLMw/uEdbz2RsiN4wa7VMV1puVyBPBfwifGw4eu?= =?us-ascii?Q?2MYxF5LgJ9mYKZ7sS42cY81rz/wHjflAKpy1tyTlUyIjL8LrUn4PGsUiAsUB?= =?us-ascii?Q?UM7Eb4HAnFPSTLIDP3/V2fWiwPAAPQ/eMAA8pfIhleRZQPJ8WTUqt4oqyxQG?= =?us-ascii?Q?UBFPRANXaCeoairshOy9AkulAx9j+dHeY57LAOn6FwL1+EbrLKnVWDBMEDIa?= =?us-ascii?Q?D0U34kcjkWkPxT/FJioI9TpeOx+6WAmwLTOHQLThIYiwQnCMaLTVV0XJZntd?= =?us-ascii?Q?eOzuwy+JLPQ96vbBpfFH75qfLbhYuL8RUgh/g+e6Drq2tgp5YELe22jKF+Cr?= =?us-ascii?Q?vDRqEm6PcmwCjEtGuEgQ54kZEavjyNVewVridBLwxtzLrXuAAhoN+RUO6Cs/?= =?us-ascii?Q?WlIpAPwJQ5eC+LFm2lfWnGG3iZFXJnkuOxDWMy6mT4G+6fAmMduAhgs4N4rQ?= =?us-ascii?Q?0utcSCe33KjLRdcgwlv0LHcTq4d7s8ezIVHAdl3/BwLnIw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?+3OlpeWA0FDIf3rdAcc97iZ1wcsJAV9IS4v6Tfujl39m2jsP33Jyu1DBX/Cf?= =?us-ascii?Q?03KPtcJCv58Un60qTyuo4X+uUfwTWEVY6OEZ9PIoMcDtmaUkF1BOwNP8E/Y8?= =?us-ascii?Q?6okvyjXrfPR9G+sdh2YnB1f5aIZ7ot1GK1QX7dab6WUpyL61GZzt1XEhQrr7?= =?us-ascii?Q?P/t3qhW53FvAEBUmjM1SO45/8YrqcPd07nb/v6OiqGH4Sf/EbRJ9iMC09T46?= =?us-ascii?Q?NiiBie9v93VUAar2Ux8NtkQeW7kZXqOD+MOZAhOTeWS4Ps9st94Gv3pwMsDW?= =?us-ascii?Q?GPE91ifUmDivhJCg6rA0YESny+ORmsrdMDE/bco4lzHAfRnwsHI08XmffVNe?= =?us-ascii?Q?UXdlGMWKvzRJy6x98ZIHGF+eTQWsGzird1VFlgiLIs+UQ/R5rxRlDP0eSA4b?= =?us-ascii?Q?TTsJlYx3WiVIV6AX0NA9yUXK4swajieqHkSj4te27jzvUnkzdw83R4M5VWkS?= =?us-ascii?Q?/T1x7Xyjx+NR622hNy9BqVwIsJhoXeSpOkFO5HxMI71fJRwhtb2kqsKAQ7kr?= =?us-ascii?Q?p8g5uSqEJPtAMuXIa9TugewBEla02wyPSbWp/dIt5+yz+6m+dZVVroihO/JH?= =?us-ascii?Q?rACR8ekSBH5aiy489ZQE7uudmN9ljZrIzvv025ibWa1VhvtJgnR+5trac7KU?= =?us-ascii?Q?Ga2OojJoK+mNmvwY9saTRoq8fPxG3AbfZXW29iShVu9pljWmWqfsAJUmnYBP?= =?us-ascii?Q?pd/PfOJpxFoTPSjUMVB1TMW3baBDWU5o+2OM9lZ4vuAGPKJvgef3i4czon8b?= =?us-ascii?Q?WGrw9umo664ReVbzm7BE7mQohS7YLX2o4aKGUeCdcV6xt58rnrnPfdiXuOAf?= =?us-ascii?Q?8fSJvf5NFsvlrg5nbpTKznCCDDXDPIl0hc6l5W9alC3r1WjAn00kHrqT34F1?= =?us-ascii?Q?fXMcfXSAlUfCMkNpULZn3sW+DA2rGsjcg9sBVaU8SRYhrnxOYdvUTy6Ubj65?= =?us-ascii?Q?PYCwBY6TOFGZ7ed95eEeqmxplaafXF0V8F0xAlX1GCO1bmarg3r42SxwqKsz?= =?us-ascii?Q?PMQzkbhxT7fbS/EuFT+ty3nsRAw2aJF2bHFt4mjzt0Dd6+u0LEKX/sHkjsdg?= =?us-ascii?Q?BQgSe2QBUQZoaafB6v8EsHnx5Gqej9OgYTlY4D9syKC/OSJJK40G9No8Ugj4?= =?us-ascii?Q?pxsrQSQXZo/2qxsJvUQJudbqmK65yElheEFhj49CP3w73o/bMpg9BEUF6wqZ?= =?us-ascii?Q?1c2CNCNwlvaqxSqRzfcTrcNs+vqrhb4T8e7MA0qf+yj6pVTNv8T8pZk9JMgF?= =?us-ascii?Q?/XKXDPz6wjcXsomzl/DH7+6DgBwgB0K9OC6IzNUbOImONgipJ2uplCyBmebx?= =?us-ascii?Q?+nFGNjmCJSNt1iYyU599mmXq588Qi3xLVOExjC7HI1C7DxMsEiRdTzG5cgFQ?= =?us-ascii?Q?wTaIAFO5ng7itJx/wRdf9Fje+r0pRFIkg2eZ98blDum3iHDNckh12nS4aLQH?= =?us-ascii?Q?wiuqkbIeDj8o5Z0UYADjrHl5h2QTR4vUC7zwuyuxMenScvB30/vVCCNoNuY+?= =?us-ascii?Q?qoMDp0t1xJCgBjERp6ZtnYYz4SikMcwH9YrfoO+dkPvP9PtG9E/BtaymOvne?= =?us-ascii?Q?pjWAXHpRewH48nonyDAURkrK1lb5sT78kqtDfJL/Eweu7hnnlRFpRPKj4/5w?= =?us-ascii?Q?hdIhXesyLWsT8GJsi4lEJZt/fwaoCh514/YBbK13FvS8?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6311fd95-07d1-45f9-76f8-08dcb858311e X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:50.1682 (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: Hy4jXdfSqiqY8CjPJMSsmTS2IEEtKT276UrQOb9V7r6hBFDD+sFZcZw44ena4ZCTzhbPqDc58+5YdT6VkEGevQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 99FA119884B; Fri, 9 Aug 2024 09:47:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196824; cv=fail; b=U89Or+j104lyyiXqrzMM/zz9nOhpV/TN2X3iXwb467nVNVs+PMafwbXLnrZvIZ/egi1/9UApYgeNXLyaJqPyZ5L2nvt8DUcGWMigwXccoqCXlKpZR9Q79Jva3h6CH2SaMt4O4Wv5qbUcHpjpIILoF0n3LrJ3xIoFWc46/7waroI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196824; c=relaxed/simple; bh=v+F2pLrCwK5EGVDolUE0zv9WoBEvaARFWs0gxLvtaIo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=PUtthq1i08LAv6LYrqMzBZfCMhhIILn1k1lo3iYkTbd8zkpaTRU8hIgxZhG+dz0lri6qZt+tLIUEVh4Y0NylCdfINV0bmVTJnyqhGKH0gcjWnaKK4ohuQsBt4gkowYhJoVr5PQZwM9CYPtKW3TtSYXM3L7kQq7HCrqL0EwYd8c8= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=nPXomsdk; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="nPXomsdk" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Y1Yy1UKOpoKu6ScF5ERNeyqX5rNVNkHcmVxDpf8HQkoHTixfFiaEzh30sMN+s8+lGD33U3q78dEsYN7RKY48kbi0JQBff06rs29+OONSSJ4yXtsNvKKTG4W+761ThxqQQJIB8m8z+x6tnB0stN+gUmTuYtx1UTns3q8a8n3Po+DQAio3EpvA7BRjDJzmB3wvJVNtF585rYd2dkJ/uCCP6JUtIQ4CT38PWUmMU0Xs5XQwDNOeYN+vkrKoDsjkvzs7XA4EGAMCgO5Oxa+Fs70WmAhI6i6oK+a5QD+4p54X64Cc0ut9Z/uFZHEPwj3fIl2rhI7TbujMRo8EFOPkPtOGLA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=VRNYumgjhs9hspnO5aZmcVnKf/zEpc3qh4VleNSTR6A=; b=Hi8gK27xLd98Ar4UDEKzq95hvFQ/+yhaV1wcpiTZVOiLEdOIfnBeC5+lVF4A6UyeNNU5hQTSFW2mDuaws9M7WXZ8PjXbtc/wXA/omu84LilKodYbg7B1o1UI4t5rbWtt4me73/7mE1vmycjKm/TQu29ic1Vw34l3lTWJA9gyYIXT9irJJmlCi3sJ/sStP+ks8q0tLthXjKeLpC1ZJCbQpiyu5XJAi/evtC6Aapbnj5MVkbDp0400lyDe2eraQkuIA5tYzasFu2qltS7iD/STHtIs6nPHFrN2Vw2cag0RGP9vPkXGqR+K6eEgbFwVYvx9izeSfxe+280y6uGpFuzepg== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=VRNYumgjhs9hspnO5aZmcVnKf/zEpc3qh4VleNSTR6A=; b=nPXomsdkci7SqfPbrFgLauPvFEfLEkKar3v3yQPFRzsKtSqKyCAe6pcVyZDmXVJYU04si5hTl29JAFDDUwI+8eoM7hqqnRtkv8ZFswkGegf90XYKTVrJ6lNSv/nd1lZ27uxSMtapzTsIkLFGxxjOy4Gw6aGQCngfAnaZiveNovOR2MPZM1c1Ybwkx32v204nelQmLeIzsIfnoxsMjuudCwkAP6OkdrJgzaiCmU1QiJyc80vn/bEMylY5h9I/leTSZbN4aAiJT0Mn4lmo04vKjy0rSk8S+15t7nwi0PShbmOMxjvPvW/HOlpPrxfB/sA5/eDzbRAkGkBdSctles0sVg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46:53 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:53 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 19/43] wifi: nxpwifi: add fw.h Date: Fri, 9 Aug 2024 17:45:09 +0800 Message-Id: <20240809094533.1660-20-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: e8e39864-e0ff-4176-4f4a-08dcb85832f0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?gWfe2Lbf351qrXMs/6K9ZLwz8Yaxfss+YAZ4TgE2uj1xRFamjPhRY4FvtZ/O?= =?us-ascii?Q?axMzfQIywWwyZsLUoIh7AsIZj13YzqJg2IFdd8tyKmJPDdV3pGRvOSUdTY4s?= =?us-ascii?Q?KwF68Jnt2NjC6anmm/LiH3W0VF/geoF3+UreaSU/JK2Gg4GDh5MxDa9CHYnq?= =?us-ascii?Q?9VPB7mKjFF0YdA4ih5/4h4A7t0n+V5otQHI6lKThkhdYcS5ivtiCdoSWizOH?= =?us-ascii?Q?HM/q8Ff+zDxUcaRG+i8yQbL5/hRCLndWEQVTV7BfG5K/XOheGavBvMAIwtP/?= =?us-ascii?Q?Kt0Fm5qTTJoIqf/QtK2so5ig82k594KWoXoxXXDBz9zMrfRUWqQCXB2sZ77p?= =?us-ascii?Q?N+Vv1PMC29h67nav6ciCG46WeTu9E/3a9NG3ONEsbjao/0Wbwbr4UjRrQiop?= =?us-ascii?Q?tMI0v4L86NQcTsucVCCtFfiih8Chpq6OsYai2AmZtXYRImqweLdytetrVu9v?= =?us-ascii?Q?nHhX4TbgRKwjTZM6/uyFtwVDOPwGGMn0wMs6WAkLttUxogbwJU4F6R6/VNUa?= =?us-ascii?Q?b5v0ZFG80Wd3UpkRRRWeKLMmel9dPSb3k4Ajn+zxn2JUro5sVeW+LQsZbfA3?= =?us-ascii?Q?hgE4ImeNxj4zXAquEvqtE3+4WPEbPQutMcITqH8XucmPjOfQGZboE7msfhN9?= =?us-ascii?Q?FCjYZtYGYZLGfbOBKu4Y2uHKK/SK77MzmPNTSEjCgkSqNAn8F5pnIXVrbi8+?= =?us-ascii?Q?8KAi8BcJn8OFHvWj9RaB7ogKdLq6wi+Yllc7/HLRH25RTZRLmFLMgKiPLhRi?= =?us-ascii?Q?AY0Hn6G9KvvlBhDQIp4REzF6AAGGi1Yv56lATxoSWZUoRoX40I4tn+snC70J?= =?us-ascii?Q?kJKcjzB8Cvo24mo4AE9RttcJf4aUmEuEY2wF0YSzyX2riedo1GRhK7x5FoMN?= =?us-ascii?Q?m0EKB6Q3fxVTV6980KX7M29CJMeCyTKRTq6NlWAUhUJwB75SI4aF8+nAHwOA?= =?us-ascii?Q?FgMpD1OlPWPAS4hNSW6XG8A7MKV9iT/zXe/vcmaNCC4CJEL+N1R5dtHIkkf5?= =?us-ascii?Q?l7NBIF73/qQ3ns8lR4vF5T16ZkGZcuSB/RKnj/b8IT6RNth1n/v2Xl11XJgK?= =?us-ascii?Q?+lLzYv9zkQLolW+S4P2uZUaXehxR60ks4itQVD6+2E+PX84R9ZOjD+JPNVgn?= =?us-ascii?Q?Cunxt/0OM+DjTmsQpp6Gx/vr8Xjb8OHbFIDHJe+rNOlfkbeasVxnlWeNjqgE?= =?us-ascii?Q?3yYaJCxJCrj/sCOm/LfGMdF7BBAz/LWAjETH6mft5zYLtzh62ElImyHLS8+G?= =?us-ascii?Q?iIA03pKi0oeMvtuNdzlATG1n8OR+0NPwe3efiG4qlZVHrq/cp9CnvacVWCHM?= =?us-ascii?Q?dm7t0Kr4uPKilZvNMNvaxaXDXaRrevqld6bZu5ZKK8+kBA=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?nKvfW3ze5JRF/vfUZwwH4GVMTat6dQKdlFl4SU1N6+cHPRCQFny3CbjzJKRR?= =?us-ascii?Q?5WAHzVFu0P66+Mc5566Ic9iZ6CD/SyHumkm8PJBCEo1lnlit8gYNku1gj+Ju?= =?us-ascii?Q?+ap0QJJNpRf2TEHofsKYnp4b+h4SbPl+9vON11OkuC8m1uLnsYrBBpNjbB/T?= =?us-ascii?Q?voGOf6O07ZaturFWQGZg0b6i3BI5a5lchr9KhNkhGlk7WCRKesHXSAlm3YJs?= =?us-ascii?Q?HrSVsA7LuHhju0pXfdtZc8EsZlSfeh3zIfTNV5VUrt8mTN2UQPjtWyUCf6VL?= =?us-ascii?Q?8U3GB/UpIBpS2RuaGOcfn9gBILHCpQPG075r9RvYBN2pdAetFZqeKNFt/ehO?= =?us-ascii?Q?fdrF/N6Lewa81BHo7hSDwrth0aa8PXpuIYP3TvGZsOiZdD7GWU6+1dNZ8auY?= =?us-ascii?Q?ehGcfbgKzqTMPc/ZLw5g3eVP37XFomy5yDqrfP+vkGdg9IfLhVYShTApQIeg?= =?us-ascii?Q?GHL/g4hy+mKSpzcNzsozl8O/hYA31OMvZhS6GJKwsZqW3L+EDp3yAW+31TVS?= =?us-ascii?Q?GCFVK1ftaN5Vgw3pUN5l/H8zvOvPbKn5HSRX2LLUNZyHIKqZzeDN0PWn4IA8?= =?us-ascii?Q?6RHXNQf/b3HNVBP//dJF3nUqq5Et7NmGFGQQO7OR3cJuVVw/SrnyTZxh2VTc?= =?us-ascii?Q?Hk41AMuvZkXNMfVr8OErosdClHKnTUeaKBWIRHEyLNzjCH3c7LtuebR+//I5?= =?us-ascii?Q?23bvThpTjWrC6UhLQ6llorLSp6ONANa9BQtFQxiKo68MX/CLiSZjTwT3rr8e?= =?us-ascii?Q?krhbgevg8yetwU+GsuGdVhdPR+UvAO8jmZNRe8Q8BiDtbXp8sQOSrJyP9kPl?= =?us-ascii?Q?A7icMJPulRHjbJRF0W6nes/Y31nKgrWuvIR3Z1agQRSgXrDdcggs0Z9kdM5W?= =?us-ascii?Q?aTbHuDzEmktjMcxWcc4eqNKsas2hakMgWoOC9y1jU9IhSemG/461kRnOkSeu?= =?us-ascii?Q?x0uNC5gTBsetnfEmtxXsVPhuSogHPb3GywvvJqnR9kuFGQGQ/Qc80NAmIFlH?= =?us-ascii?Q?AvVndx98D46fBoRRymWHd08sStIkjOVHCKfnSnD4EosSw8voiZ1d76Nr3jPd?= =?us-ascii?Q?IBhxEo8U3QvDYAyAnPO3Zj31PYhhl90xOPC9ZWPoFxCrEOYj8LqI17yvdwE9?= =?us-ascii?Q?C3qGSllNMMhVaJ3O1lmcvDN2TSelWR/k9U3TyoTDZC/T1iS95FddqHixOMoV?= =?us-ascii?Q?ZmA20zNhj0H3s3p0IckVq78jrTwfUEbmxfXLsmqOr3rllRBJK/68BuU56Bfr?= =?us-ascii?Q?S3MkqOs5GX1S1ZtV91Id0ty9ouD5UThAb9K+f73P8kUW28IOegqoCRu6b3ak?= =?us-ascii?Q?otKY61rQjEMuzSv+EkQuI+3rzUV66NakUWDm2eMb3gCXflIL096S369K34da?= =?us-ascii?Q?JCWu05I0vgKBlRWgRYDaIADiNSfGne6w3rL/Bvn2ezxthz8/4rxt/UrWP7PE?= =?us-ascii?Q?Mg71xegtNw6riTvSfwK6Wf0A+KbjnKw7W7KRUbtASfe7mN+ApWDwYYrb0Yq9?= =?us-ascii?Q?+mvIBXh0jGJhHh9ipXTDBK8greSTgjm/ysEfaAsoWQSXWafnJdlb/8uj8mwv?= =?us-ascii?Q?9v2gvjkQv8SV9FmmJGWhXgYVmskwkeFUIDWAP+VLMM9y+GzwV0CtC/BqJHDG?= =?us-ascii?Q?DviWYNZ0mo5/RF2/7qo/6u7gVorftsjco4/f00X4BY40?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: e8e39864-e0ff-4176-4f4a-08dcb85832f0 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:53.4043 (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: PpI7Ikp7Bq+HsInAUIjVNkRdXGt7pmMI8Jf67yW2UzHPBAJAjCaFGATQZv1jbZ7IAYOKw2WrjRM6BUuXUnY/3g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/fw.h | 2249 +++++++++++++++++++++++++ 1 file changed, 2249 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..0bdf3ce16597 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/fw.h @@ -0,0 +1,2249 @@ +/* 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_REGION_DOMAIN_CODE (PROPRIETARY_TLV_BASE_ID + 171) +#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_VDLL 0x0240 +#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_PSK_SHA256 0x100 +#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_VDLL_IND 0x00000081 + + +#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_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_code { + struct nxpwifi_ie_types_header header; + u8 domain_code; + u8 reserved; +} __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_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 ieee80211_vendor_ie 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 ieee80211_wmm_param_ie) + 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; + +#define VDLL_IND_TYPE_REQ 0 +#define VDLL_IND_TYPE_OFFSET 1 +#define VDLL_IND_TYPE_ERR_SIG 2 +#define VDLL_IND_TYPE_ERR_ID 3 +#define VDLL_IND_TYPE_SEC_ERR_ID 4 +#define VDLL_IND_TYPE_INTF_RESET 5 + +struct vdll_ind_event { + __le16 type; + __le16 vdll_id; + __le32 offset; + __le16 block_len; +} __packed; + +#endif /* !_NXPWIFI_FW_H_ */ --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 12DF21953AB; Fri, 9 Aug 2024 09:47:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196827; cv=fail; b=BjxVbxDHoP17Ix0bVr7DQGyzLC4H9/ENPZeF4PVhv7xJOkF1vMJanMZervQkvgGylEzzurPDYPTZNB+zlKKJjoL8btkt2q1MzLig2qEhoFqfVbOATliIGOzm71OQxW5Wo+RLYTXwY17x7I3RlW3e2MagUj0RnuCBJvSH1ZAnJQ4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196827; c=relaxed/simple; bh=hK7zOgcNjCbIKSwTuKqkFzBfM58GUiUG2NZiiwmSfnE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=YgIYgkWswuOEf/8/24Vk2kdeD1WCal2weYsKcPtTG5c7UZTjsnWzFrQoJTApX5J97NZVSN/QbBgpbPPb8eoBg1wswig+5pyA7/VsmI8zCaLZknn/8tVhgtDvswJp/z34hkIzESQdd7rdzKELjCzL/SNzs+pKbhDuUg7lSz3ML6o= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=i/WEKTQL; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="i/WEKTQL" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=zDZivfAiMM2hYl0UIndA3i47xLpB7OY2PkKTFosfuS02ltr6zbGEXtZ5XObq8osJTtO5VWSRA0G0bQystgt8dk9Z8TRIXqnDbzy8MoY0Hk/ilNXQpG3rA0JEEF+mwhgJGO8riRRGluVH2fQCpB+UFMQfJ/8fyP8jDFY40H2uFreDXTzmiG5b4ga6lrdKs4ufIHwKJgA1pzyZFSG0BdWGJOFnYYde1CR7GipVp6CSia12fs7i/dpxOKywv2PVSjrwQ4b8bGh5AaoBhAbMr0RWE9xuFlTbli39lsK5sQvuf3xPis+xYL+XVR/5Di8/dmJE5JWZalRQAHkk4Rk1vzBOIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=GlL3lNRkNR2Ks9TWo9qIvoqcIZ83j5ygjGypIb8mm10=; b=tZYFivJXfFpLXu3VDjYdPD9p8Uo4QX3R+XV1nYnpYgCW4XT1Quqj5prAmgNYR5RcOYI6zqrTeACzxy2esurJHzWhAev3vS/0y9YzIgwbQkrqrANOuhPDxGdK6OgWWrgmVY4rpdn6TtOlqlru3RHYAUjjehnCWykrRpTWP3PErofxZaUV2RbIS6pmkTzQBxShmBgv9Td5e4YxZzf0lkjZP9WIa/gAwLiLTia0x5rJZ5yuqxLjDhmivleSLPJJ16cOps8JBTHjTlnV1sEgy9tL8EXYWGoY3zt6CUoF0ZWo1oPI4RWSstr1+owLnDlNr8CJCGtUrGyhe5rWXMKjszkY4Q== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=GlL3lNRkNR2Ks9TWo9qIvoqcIZ83j5ygjGypIb8mm10=; b=i/WEKTQL0zEiS5DRVy5vJjxKGGfP6nuydWWPkNeL29W9wWxjRhhPtxk1GjLwaKgwZi6TXJjAUaD+8GRzG7V56F9M6Lf2qGkTeJW7Dqraj/HvLyfBmhKORUfFwWf64055k4YnVJuNDal1zSVOv0DKT6wHUuXOG23oUjwJUK8lp6mQkZBocl3eNd3d8jDDxXOQhW4uX3V/mSj9kw4Vl+rj1FZ7DcN28QTm6cDp8zCwmQWMl7L6jg/54NkRhIcX++BlXcCDKUm+upBiA9+cuo8k3vpoF5+tRtyCXY6eoraSxdQzoshr76fiOE1hG3jsGjIHgktVZ4UeTNp2ooPctPqUIg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:46:56 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:46:56 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 20/43] wifi: nxpwifi: add ie.c Date: Fri, 9 Aug 2024 17:45:10 +0800 Message-Id: <20240809094533.1660-21-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 898e70b0-5eee-4a10-f227-08dcb85834da X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?5wzXYlrDG2h6kMb1fPKxpqq6hLIp32o2EGCRD8U/YDB0Gwe8BGs1eZVSzHH5?= =?us-ascii?Q?EDofhzCsPE/3MUmxjGbaRBSqYMOtTMWrKw5HFG9c/+3bnE45HklR1MIm4POB?= =?us-ascii?Q?SkWpaeKZyroixUfbkoXyKjGMI9Zuq6KoPVPU1PW+ODXay5PiZh8V/57pIP1H?= =?us-ascii?Q?3kd05+kMiNP/skO5ZGlVR6OzpsxzrNv58l1F+myVK3Luga9dmq5ilB2hNKy5?= =?us-ascii?Q?NnwYMKFEshKgKFeqxm3/NQ/JqZbIA8EFXLMUdVVVydaxFrByH1a+KLW8u8iZ?= =?us-ascii?Q?j9EZhJHHlIazUQP5qQcFCFAf5wH+wRYXUM5HFrUzgIVWHWl3T04O/dFmAfqw?= =?us-ascii?Q?MkK8VElsuW0f/DRVVfTpgMzO4PnMjdxz00sPZUiCQxqK+AUNMhtHremZbmFl?= =?us-ascii?Q?ZXRQ6J9TyHXSspEp0M7cFSe0aTcCAPFnYRqKLhNlgsAEVYS+LOhc0ljBpvkA?= =?us-ascii?Q?KNTu+lu5T8pCKRpBmSSjO1Ic5kXRHZmL5nuO3a4pfE+vpTZEP2v4EeXTxLvz?= =?us-ascii?Q?9IXqJgA8q1YZo4rc3DR0QyNwzmnT/1JQXfxvTAIxvr+g6HVdIFXvcOZ3A369?= =?us-ascii?Q?VaUS2LyNM04fas/ED2xAdlIeEgZLuiC3jfDPe2MfwZXg9O+RXflj3SLywx4J?= =?us-ascii?Q?MRE4ZX+Y3m7C7IeubFzXsCl0FZOWRPeN3pcOP3O9BI6CKfNBa+waVdUP0SXh?= =?us-ascii?Q?nB4fUC9tciNbO8OkjCdffEOK14l1gGnK8BRiedfw5MgpB8YbNORxteOiiJR3?= =?us-ascii?Q?MKQu6335hO89bWt2k6IPuduDCo6V0wyAhpnWHUfoaOhlzPKmflyxPSdofKMx?= =?us-ascii?Q?pEJHw0IMLoHjo3YHZ0U/v4bNyDKBIs7Sr46Qq+lLF1q8q4MJAAvjsjy5Zxl+?= =?us-ascii?Q?+A53E35L9VCHMrp8olkVaeJtdsGvG8gVFLmhxyhFIz51WAQX2BpE6uECu5/j?= =?us-ascii?Q?bSdCKoa1y5nf0WAellI14unCrA7PPkwu6BJ5aGdL2Eb9ffnfQdC7j3vF8bUz?= =?us-ascii?Q?TIfiZVEPbAsRCbtElDbhvhroknokoN/TAB5IxjzgslgoCw1euSCb3ym02CTh?= =?us-ascii?Q?ncUPW1u7hJV5CfADShemL07YBwE9aSdpNmUvZXSRMrHpByq4Eov1W0J8Q3JR?= =?us-ascii?Q?OeLBVcZlOurbI9I+Wi2ayNbSsRw5KZRn4cLPbLiVAJwzPT2FtM5WoKP24E88?= =?us-ascii?Q?0M+Wi6dKZ1niyLKeSF6IdZlBhnjmFnFWXyxj0SUXFUseDjPOj3xS355HHyPh?= =?us-ascii?Q?/TgThj4O4i4C9qMqwgk3GpA0Ae1Xuvy83TXOxJ8aPnOawBon9YSIsU+mHmYS?= =?us-ascii?Q?hqP8LjmzGgnTxY+cTCsOSPldcPG8DoiG18jRUAXnSv4ULw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?fbZXaNYiyCxrOnQgDYBup9wk0s3iR5mMnWz7xA5FkGT1K8pPs5h9KZIOjCu5?= =?us-ascii?Q?ZEUxH8KFOnPnwf2TDp98FdBHQTbS4/KRU6AEKc5HQE8dyyX3azKSGOZ3JQGz?= =?us-ascii?Q?QyyXa2q7HRrlPHnEV/xJU023y1umKZu3Na22d/G0c8wAZGmrahZ/mGwaiMq3?= =?us-ascii?Q?MRiMFFBqn6ahB9DkAF87QyH0svny01hYcXZaw4mePTqc8HIqabW//F+2Z5p2?= =?us-ascii?Q?Vg2v/pz6fjleWkWeB7LbHwWSqxIVzho/2PN7GCyCGVS6LMfEzxolVN23IKzH?= =?us-ascii?Q?ESpvIoHbScgJ6cbDSRZ5snMq2SDfL2wKUJ74n26dwq4TNSACmr2tGBI+wrtR?= =?us-ascii?Q?UK1lEfZM7NnI4bCxLb7WLVE9JhZNGpv3Ls4U5A1QJd9enB2Zmgs9o8zssfcg?= =?us-ascii?Q?USBHv3KzrGAHTHNYDUtwC2qNpVw/y20F5oolhZG1ik+qV+PjKrAgi7BfVIK7?= =?us-ascii?Q?+YE+pyAqPTBQki7zvIg974LIdV49Wc0eQT12WwSGdT+MNZHaYbgXiTv/qfiL?= =?us-ascii?Q?83h5f5ElHhO3b9cleT6E32FDdjV2Ukwc3HsDR/2z0mHMbSfDpwyvEtjWROBT?= =?us-ascii?Q?qyJ9MdN1AysMmmqWbG/EiIWMAlWIhXMb6eorlIXZan9e1vMljCZ8WXMFlocP?= =?us-ascii?Q?7k28COkAu8JyboIAmIC1xMMjzsrOo5jkz+0fdKBsr1ELYGONUcFh8e3El1kX?= =?us-ascii?Q?Mfowyl+yYoZ1F/5/A7BbNGUt1jd49M2rSvqUUnwOY+HnuDF5P09QWBPa2iBK?= =?us-ascii?Q?3b7WHXmfI7pYA15ns1NWnPsZqX6gkX4jliTbKShO00SMhvoYhUBIg0sqCZ2h?= =?us-ascii?Q?aq0sxucqcomhiIQ3cukqbtJpDLJTtjFCGwChkBEU/ahkdfk43z4KtS1wp28A?= =?us-ascii?Q?Q6wMHz0PQv1xPp2AlaAmGJK1oRZanedL9E1+wvVPuyoK09H8Oh3K/+St88eE?= =?us-ascii?Q?HdpBxWGQCiKSr0MPFDjtfAXPhVjh2fn5tXvIec2dN4ivWFHbwBJOyvXGraEx?= =?us-ascii?Q?f3BBvaN4jw2WAy80JiPiCy1Ac7bZV7S52dVIavtEKORtlj0JGkIYectDBHgk?= =?us-ascii?Q?0IXsaKvShqkXJXkx9brE5imI4fZjDkSdi1GMcEctUX6oOLQngDkTG7DLgaLO?= =?us-ascii?Q?R2kC7OrdVFXr0BUeoOLsr03NPM1H3dCnyeNNoRS1+dudV746YXphDhNe72yu?= =?us-ascii?Q?j5krNS4b82YWVYY5nN4wuM9NqHCr3RbpYpnPSPO13UVagsx66G+40pDrS9dP?= =?us-ascii?Q?3ppFtDz4hRqPzfau9GES8TQa56rH4Drb7AoiIxeMr+OjI0l1/2eLN/Mhg7XC?= =?us-ascii?Q?jpmWWrzsGSDP9JtMCu9+jLgx0FTlp63q58VXEfXgzD9YFrpGfiLpV1VYDzi8?= =?us-ascii?Q?jOKcFfhEpkzyZ8c9Bg0NVgStmptgHDDghTtYwJRZhLl+rKjitGfJBfxPo/8z?= =?us-ascii?Q?Z3QJs9hkZPW8n9TE99GKIwFTCw2pgLOB9IGsLVTyhBEtdVYdZer8ENs0YoOM?= =?us-ascii?Q?uYYSuzJ/PfE+Ok3OZ9/oMyb+HZmH0ykGVV5OqLkWwDCUag2/4rhN8wIPXJc8?= =?us-ascii?Q?jkRqGmzVHjYnkrh+gIgaaTWYdxlSPH32B8HWHdJIJJqLs0IByUUrzxU1Kuhz?= =?us-ascii?Q?9ZBqPMCEDOb+vwNc9jMWhlSXkjcMPT9jajqSN2q5AoJ5?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 898e70b0-5eee-4a10-f227-08dcb85834da X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:56.6735 (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: mXnAMe67PhX7UZI3NARWw5cej0gpXiiblq3DSOCyKmqpJQZ/PmZWO8QREwHIlVNBFU5ovPvzm/z5DvNToUcb0w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/ie.c | 501 ++++++++++++++++++++++++++ 1 file changed, 501 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..15bdc3c7a6fa --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/ie.c @@ -0,0 +1,501 @@ +// 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: true: yes, current IE index is used by someone else. + * false: no, current IE index is NOT used by other interface. + */ +static bool +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 true; + } + } + + return false; +} + +/* 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 -ENOENT; +} + +/* 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 -EINVAL; + 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 -ENOENT; + if (index =3D=3D NXPWIFI_AUTO_IDX_MASK) + return -EINVAL; + + 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 -EINVAL; + /* Check if this index is being used on any + * other interface. + */ + if (nxpwifi_ie_index_used_by_other_intf(priv, index)) + return -EPERM; + + 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 element *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 element *)vendor_ie; + if (le16_to_cpu(ie->ie_length) + vs_ie->datalen + 2 > + IEEE_MAX_IE_SIZE) + return -EINVAL; + memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length), + vs_ie, vs_ie->datalen + 2); + le16_unaligned_add_cpu(&ie->ie_length, vs_ie->datalen + 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 element *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 ret =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 element)) { + hdr =3D (void *)(info->tail + parsed_len); + token_len =3D hdr->datalen + sizeof(struct element); + if (token_len > left_len) { + ret =3D -EINVAL; + goto done; + } + + switch (hdr->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) { + ret =3D -EINVAL; + goto done; + } + 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 element); + if (ie_len + token_len > IEEE_MAX_IE_SIZE) { + ret =3D -EINVAL; + goto done; + } + memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len); + ie_len +=3D token_len; + } + + if (!ie_len) + goto done; + + 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); + + ret =3D nxpwifi_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, + NULL, NULL, NULL); + + if (ret) + goto done; + + priv->gen_idx =3D gen_idx; + + done: + kfree(gen_ie); + return ret; +} + +/* 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; + ret =3D nxpwifi_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx, + NULL, &priv->proberesp_idx, + NULL, &priv->assocresp_idx); + if (ret) + 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 97F55198E7A; Fri, 9 Aug 2024 09:47:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196830; cv=fail; b=pIZItuPSEkYfFYk9Wi9zS8ojIxd3PA+AVgJyXDrWcfEIy/HS8vVczMI7s2578uUcUfDRjA0V/tQCt9AjdC++z1NJXnGuO+CddMovXbLt62Mn/857i9CWkvH4HA0fWf0HRtk+49DNNN67uikNvDUe/1UfNzMjTXixdDEXStkHoQg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196830; c=relaxed/simple; bh=xKvPKqhPFcxDvxRT+XlZNSbIopHFE17bNCvofgIkhLk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=V20zr9/zAsL57vcdPp8gaIxqbghReltE1em74qvEbd3rb1ltgiJNPogwMU9KCpXiEJCCwhKxl6HpugZJoXIvqu+WqXn9PuR1f785JmOA25M3RXosJQSQvTsc/N2JIUlNjtCoTrX83nle4EdV/YDrw4mn/1YqisKKdZmPJdG2Z2I= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=JCMBySCC; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="JCMBySCC" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=xgXhGrjcSx5hh8VzF3/SslH+ChT3GArYgc/LHYC2UjvoXEq/TS438dwghv2qpE1Ezqp4OL+Nv6cyMd+A4Zg8PKf85ugWgYkWuItQFzIguCUtpRsucAeRLlUOFIVZBL/v++d8h92UmVUNOuHIG+1xR4QK+mUnl1BaWqFPQuvs1JH8z04redo1b6mkK1c2QcpBSzaDcI1I22/3EXMF5XdcpEUtJTqPwcHUPh7n+daOgEMrVB/c4euGMPkSubRyRx8Ejtg+KDxVwRC2LgcVXkheAQYthrKh1IbvP4Iiqa0WBeM86qpojMQApqrM966BsNANCGvvsgcVAKBnHAih8FvY+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=RX4zDpOaQmJjyeDmV1jRuzlR3oeTKyOqQha4c+FLJ2o=; b=wledxYsNZSHzKQCRIb1V41DJjRZQE2wImYbYuXUrtIWh4EWtyq/QhSOe7pTMmTPHIHCK+ecfpV26lyj3maivezDlDEP9r/fBcn4DoXx+Hk67w/NBoosDfuTKSihfFd+eAYB53HCMN31mwRvQX3joBJzynGKSIr2OmZyaTdYwtKPWYIfboUGKmtCTpevBm0zAxOIPgqnpIo8cPNGmQHeOZCVq54XaCwF/SS+nsvBapTgayNJFJf+UxAWCW3YK3o8XTjkuoPnxiREzSaE3cb7UfkrZOqUIVyYaI5kOAAZ2ped1twW7G0ieDFPn0E8iP2NDTvIrUJ7C3y5MC2aJYY3YBw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=RX4zDpOaQmJjyeDmV1jRuzlR3oeTKyOqQha4c+FLJ2o=; b=JCMBySCC4RnqU/n41agO2OSojueJaZsSLz5yYsAYLtZ8lPVt2ObPVvUJ4g+J2tg6uayMoypRBqlJNCoUviStrGUNBERhlhk7MqEl76+PydPExAUy3HMYcHfLk8afy0N3AmdCTytdtrjni13yCQE53YMQukEangjEGcOBb8aPU+BGPtJDcnZ4Lm14zUTeHPHx14UcNlbJ57v+rBAGgIUoTS6sfUmSq7r3ORd/DWyW+AbeNLYURJnDY7Q/9kP8wsj8TwdO8MDyymly+iiBrgPkGc8Ml4QmbVndFRNafLiZFQYUIiviufytjIZ/03IVMY84LxNxchnhE/AZG2FFKqlgyg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:00 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:00 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 21/43] wifi: nxpwifi: add init.c Date: Fri, 9 Aug 2024 17:45:11 +0800 Message-Id: <20240809094533.1660-22-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 02b93104-c698-47d7-a8ba-08dcb85836d1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?Ukg7Xr0Bv3OFMzT27qLUYfEoo/sXkLcnnKwkr4tJNe4u/fVRqhhPf9cUPsok?= =?us-ascii?Q?9xz+ANGYrAl5Sq1uNnt8Y00xmnOAk4jrdhtGwM20MyAVNqRisFMgC7VtuMIt?= =?us-ascii?Q?QAp3QJCiSMo45OzdsqOq5A1IX8n3Oxw0CfuUPnYc10hr9vH8IgugFIpluEnE?= =?us-ascii?Q?RAbzLy/kBK8iZsHLbpGaKFbuP9NZ4uKoauWepI/lB/y4thvjXIRNAbTWyaj2?= =?us-ascii?Q?pNoX4MsaLksIDV+qbVYExEvUXtKXu/SJdYcY9t9ME12KEf8NZA3R7ZwDAnYE?= =?us-ascii?Q?Ibhvglw+qZUQ5vJXb0Ne2EKxaswHAeaFd3w18BVAkNSbqrSpsavOw7cFN88N?= =?us-ascii?Q?5FYEe9rRvazW5El22JHU/+1+mSuxEg3/7G52zsUjFaaJraka2IPo6vJFTOum?= =?us-ascii?Q?ftI53rlF9TSfeZVs0eNuJq4dPilCHgN78hsPYrusV5YdzIv8MEKdSYR2uie5?= =?us-ascii?Q?8VoFqaQLNx5Zt2lR8oZaNoaQyXlXwMMuLPBoS3L6ifxlKLXPUU3orMYWUU5P?= =?us-ascii?Q?xytVpj0/alhOxr/F0sW7sulaQJLPCord4LBtG7lIBfnp1IMOSaAJDCR81mSd?= =?us-ascii?Q?Im8rSpBQDAOpBGTxw0VP5SXUTsyjiVl45tTdoR74G7QilRwWWSmTcSJtQPsO?= =?us-ascii?Q?uu50v/dx5clrISw6n/eQhPs/fni3xzADfNpZhj+YO49a7/6R5F4KA8vhd3KN?= =?us-ascii?Q?cLo4dHCqN6YZ9sI2WYj22jyHd3k5ye29vlGT39icM4/j2sS17/VCZ/3npacq?= =?us-ascii?Q?itBN5wh5uZvqQ69ciKpchbb65L7TUVEOH3rJtIV62/DX2o3BR49xg4/nHKLV?= =?us-ascii?Q?71yXadJdW2FruvMFTLhQetVe6ck8C9qqs1pUM0TpbMqL40BBRatqx+L4kzVt?= =?us-ascii?Q?8uLbTKdUrc2FApCP3+eESU7Gc3zJHZkpfI561RrsqHNtWtpNaiSPphRYnKdo?= =?us-ascii?Q?oEQ8+88lFGk58/LeTmZaqprKYPRrqXRYNuB9rWHlBAIb1H+FJ63SHAUkeyOL?= =?us-ascii?Q?CPNJutyuAdPkxVxJu05BY7YHoZlUU/abljQA+44GzZCdjbPXHkxGKlNErGtn?= =?us-ascii?Q?1BC5wb/CFklPe+WXjNJGgBWd3R0SfIjRpE3xuhVqZoKdJk0hhWhmZU26iMeQ?= =?us-ascii?Q?LtT96iXPv/Ib2b871W55Z6vRrx+VuyAC3PXhBtYnLRPB32JJlGFc+dKTipAA?= =?us-ascii?Q?+v3VIDR9+OwrF1A0NEm3l4ah1pt+iMy+iq85muBnvXmAGz88PfEsT12WOQBk?= =?us-ascii?Q?rY8OhbrftJ25tQrVmpn6tdc6DPRW5YAFriBtjONXaO1nQ9V5AJ5Nkj1i/kjK?= =?us-ascii?Q?kEuDHZBQzStgyuk7wHPWgPyx5d7xVa81OJL/+5KFYCMutw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?5nCvtqB1INoTecuF+I+WvJoNm6OjWMnkndPus/9yEBXVmhV9DUMf1y75BM7f?= =?us-ascii?Q?SpfbdOFubtXOKDWE8kP/40kTS5egZCWSe975pPPtyo5gfg6Gyf3vlPbUD32g?= =?us-ascii?Q?agRXK2dtL6wDGWVurB/VNJNMrXTy5VGPnf5sFBAq5OZIQICRtZ+AZwC5y5cJ?= =?us-ascii?Q?/8X3w9yEn7F8VQJeEg1jVSK6+wRNGim1aNTrll4N0hwoAG7VkG8QB1gM7fyc?= =?us-ascii?Q?5Q9cGrvoFF/6HVzfXdFGZZmVPbN7n09AtHBi6xs1S/m0B7KaowTx0g93sR0G?= =?us-ascii?Q?k80UBTIbGlLfym3OO31VmNX7E66binibzN0ptdEMrdwiw3EAXvDnM+A6mgZ8?= =?us-ascii?Q?vKv36IkMC1Y3WamViX+kc0u7XSWdqmEzQNBUhVzvtrynubllTOYqT7gQm3p4?= =?us-ascii?Q?NZ+OlYgkwMH6FzYSMGNzZ47X5sS8PDpSOEgcEWOmutgfw3gUYwZUQtLdJGDV?= =?us-ascii?Q?XX5yGsz1UWUh6uyBwIifJEmZS4RvfORYiira5bEfVQDDLXQFDzVO1uP+H5pc?= =?us-ascii?Q?4Riss+KT0OxOfMeQPA5rBkUVf9TiN8ZYEGhgZUjUjX90ppcjXrYiM5IfXjg1?= =?us-ascii?Q?8dWJ+jNxtd/8pEgOKgZeEVf05Axo/muALeq2oNtr9Rk68tf9UNMVD10zc0Cy?= =?us-ascii?Q?3t6F2icuMjCATmePzjyIY92+g3i1gL2cDTnnNYkLLobWJA1foKmXsmaS1Ovh?= =?us-ascii?Q?zCVlQrSrr7i5fnvyCLlPVx3kOTvme0yq0sVTj1UzvGX97tvC9GG7Mfp9wE6s?= =?us-ascii?Q?/c6Vw76mOE9MzcTTZ3kIuxNS5mP6NFXSa4Ja7NiwvQewvlej+j1i7owSiKPH?= =?us-ascii?Q?oW7nKKxnDY3J54FU68DjpNzCWwVs0B6NpdqblOCwqxEcb2X5YyNrvHlSCfpz?= =?us-ascii?Q?CYRKig92qU9m7TuigMJvwi8l+pwPK6JoidFGpRVKWMw6zwZfw7JJNoIZd6Xx?= =?us-ascii?Q?fHjv+LDIlGtOqVFuR66GeXLTd6mxvDWh2LMtOiUv59tlls2qtspFubU/ZlKa?= =?us-ascii?Q?sTVsjZtC8+/LtRYymrHaGGeWz7pkPqjgq0vx+cmczAknizrRZFWvEF6jIeoe?= =?us-ascii?Q?LaFqMCStSXZ/akWjuwXhZw5/YeKIhcdqG7RTRUcFwyYGBB1mJGuxzTzA8pVK?= =?us-ascii?Q?k58KJvLmbFXHA4A1wLPnOui+Tsea9wzOPtoQ/GEQZ2f+AkXNjXCTClT/uviR?= =?us-ascii?Q?pgjENLwVRrvJE1+7d35Y77LdSsgiHrapczLEsFUZa/qp5W0Phl2VAmuuvE8p?= =?us-ascii?Q?rrse5K4K66YV+0GYZUTJXYQrj6HQcQxj8xPBVqdQzCPhwVNMGnRkzSY6lLey?= =?us-ascii?Q?vraH5kJnjoyd0tCgx/bXL8Mtox1thI+JUmBSqGkx0w7FKRyMLPgEsVSiC/7s?= =?us-ascii?Q?0VftbFCzrCurZgRcDJCmv4WagrfWgX403pe1heAkMUZA4E0eLTiMD9TWVbvh?= =?us-ascii?Q?ayGBRukHkuleWzgCvRADli4Mwb7gPc8KRhC39zPPxADkXuaW7N13f7HWfEcW?= =?us-ascii?Q?vFcWax1OO9jhiIO8bPX+5xgtdEAxc2KOEEzH7KhpMPbXuEYkVh44kkTFCJz5?= =?us-ascii?Q?kc4llwO5Scj3oiAsJF4nnw04TmYWRxi0mM+sUkCa63rtvTHPa81wR0vuedgZ?= =?us-ascii?Q?7NPzeTNCULrurT2qSQOkZUWlgJ0eZNZjstmH9S4QTzPl?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 02b93104-c698-47d7-a8ba-08dcb85836d1 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:46:59.9684 (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: LG2tbCWYJsqyDQ8W8gLvNffKMvBdkiLRTrkyvp0LHIKAS6Jjj6p7fPzzUPtIEv8iUd62whpzNg+zlvo+cshmLw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/init.c | 694 ++++++++++++++++++++++++ 1 file changed, 694 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..05631f65aece --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/init.c @@ -0,0 +1,694 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: HW/FW Initialization + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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); +} + +/* 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 ret; + } + + 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 -ENOMEM; + } + 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; + memset(&adapter->vdll_ctrl, 0, sizeof(adapter->vdll_ctrl)); + adapter->vdll_ctrl.skb =3D dev_alloc_skb(NXPWIFI_SIZE_OF_CMD_BUFFER); +} + +/* 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); + nxpwifi_cancel_all_pending_cmd(adapter); + wake_up_interruptible(&adapter->cmd_wait_q.wait); + wake_up_interruptible(&adapter->hs_activate_wait_q); + if (adapter->vdll_ctrl.vdll_mem) { + vfree(adapter->vdll_ctrl.vdll_mem); + adapter->vdll_ctrl.vdll_mem =3D NULL; + adapter->vdll_ctrl.vdll_len =3D 0; + } + if (adapter->vdll_ctrl.skb) { + dev_kfree_skb_any(adapter->vdll_ctrl.skb); + adapter->vdll_ctrl.skb =3D NULL; + } +} + +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. + */ +void 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); + + skb_queue_head_init(&adapter->rx_mlme_q); + 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); + } +} + +/* 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; + bool 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 ret; + + /* 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 ret; + } + } + + 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 && ret !=3D -EINPROGRESS) + return ret; + + 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 */ + nxpwifi_main_process(adapter); + 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); + + tasklet_disable(&adapter->rx_task); + + while ((skb =3D skb_dequeue(&adapter->rx_mlme_q))) + dev_kfree_skb_any(skb); + + while ((skb =3D skb_dequeue(&adapter->rx_data_q))) { + struct nxpwifi_rxinfo *rx_info =3D NXPWIFI_SKB_RXCB(skb); + + priv =3D adapter->priv[rx_info->bss_num]; + if (priv) + priv->stats.rx_dropped++; + + dev_kfree_skb_any(skb); + } + + 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 5DA421990B5; Fri, 9 Aug 2024 09:47:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196833; cv=fail; b=EBRlRMdRgpk1Yx2UgE5OrAE9WsZ+/l6ozb9uIDHojTBw/6dd7ToIduQTiWR4tBACmw+u/uHTFLUHpsbF01TonIwPv2jdvgRFgFpUBgW5XPzq5A5tAl4b6fEVkmnCTzeMdhqBm2v0ewOYj9KZ9F5dRUz6uPpqM5rripc1hBmZa54= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196833; c=relaxed/simple; bh=Oi3qnNJt4LJk4DKV3ZKW5yBOjnZGOw3kse3oFKNuv/s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=TMf+PWA4H+hnC2rDM17Rt2/n0/V6UuKkU+cVcYWazH9WXe/cT9ZY9/QhSB1rkCG1TR+HR/KPwOKjKaG5z/8F5fhJ4DvLmVTlTq9nlcPLw73MdCa0ilPv3aL9QGwb611d4Az1xVbzPFsELMq1xCWo/BHZKw0kUz9xXYiHw2mvgAE= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=hqSE+bHk; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="hqSE+bHk" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kQi+4Mo4bOCjcDp3njwteGgzmhI7jwxjroEYNXDJ2eLB3mN66KNwctWZd/imWUKmCusDpt6S92fquKwVpVrAiWH6BHZZ6Q9+pceXN1AZU0MhLh6i+FQQI3MNxBeex9QgYk9q11Uqg6t9hMc6dWFX1UISEx/8OOVdCrusBwnvVJWED+VnGbHtc5r3gTgARIS5ud8m16A/4M3AQxBABZJWJQG69TbZMLDDgnUDDjin/ELvleDnOSaPVIhZBoSfW3xvRmWarss0HdHOJEbmqvIAN3P9y4LDLONnw43n/XIfArSaBSnUkveUN/47CsC2ui8Yww5WuERqZ+k6jjP3Xvd2TA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=Kx9huRG0RutdMrwCNrm5ho5HOnFBZiLXN721mVqGhVk=; b=hUTf5VyF/C63BUen1zmjw60PeA3YtnCWipxM1mMLo4IpO+a2BZXmnAUYXq9y6u9bSjgAahgXKGSXKNoimgkErjQOm5Ur7TvRvHIewls3b5+yDb7c+whQaL655QuoyhZ8aBrWvMMUPunn7gVkE+VevpFFlwHMg0Ecy5rZOqQJKOwMCxyYgGVaNX03KpD9u/QGhefyYBFT/KJMdljfhvcby9qiQPP39GfE0W1ZFHvZ/Lt8dcgNNJ53SaojTPmuti7jql2tdnwb66wZJhCzTddGWjJPWuTtwSOV1/aX5r+mPwG2Xxh/Yv8p3qoQ5ZfHH13y5NOriYFkyOldos4ad+K1/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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Kx9huRG0RutdMrwCNrm5ho5HOnFBZiLXN721mVqGhVk=; b=hqSE+bHkC+blcoKhz70xLdxhz1wl9IBneEQPvFLRWYXYCD1fws2WwnAhTsbc17sbZLVU74Hn9IhSYJmH9z0qcq24OTTP9DoqAvJLMwoEJ5ZPGKGSgCzakTQxhKBr04ntfDvSjxilrTqCBFq7isIRM3FNRhXSYrWuuzTfgZAAZ9GMTuTf+ANllYE/BOVrEQx6u2S5BHuzdOtR0kq9LRR2miRPdFZMRpmNLVa2bA2csA4Dsk02cnetUFgszGBwiHNquyV3yqXkDY3cmmhPs9J7Wydxjs1odwN3qmhpBUTg7kA7Vh0iEzb+tGTUa9Sr5pCh7eP6gNJk3ltaKojfHEAZyw== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:03 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:03 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 22/43] wifi: nxpwifi: add join.c Date: Fri, 9 Aug 2024 17:45:12 +0800 Message-Id: <20240809094533.1660-23-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 25f7acd3-dc91-4bd1-1193-08dcb85838cd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?xsYeKU9cruEIC8xHWJsgl6ErC6tn/+VeLnEDkg1XxnFcy8P9DdsYd5BQnLQl?= =?us-ascii?Q?tqduZmcy0UHd8GNtuqGWczLLJo/5eJCaXw/Cn+6rC7hsuh9KtdCimxmfsDB2?= =?us-ascii?Q?8MLf3OJ3ylJ4zeG7ma4b5orFkXMbqo782Q8ENnwKT9lLJGE1PC0E1lMZsyo2?= =?us-ascii?Q?oJucUErUN1WezwfJA4mwj3PkyGLiCw/w7LK4IvluA4u+RolS7kXvSEmzSXDK?= =?us-ascii?Q?Nen8Y4XsudebqY1dtbId9CrX6JC42gmMOtyrLyG4D+6CjBAs/K5GVOGsyK9N?= =?us-ascii?Q?V6FkDXCZb17Fnnq8e4ahSEjaXExYEwfqGFpjX7HFjeQXsd4/S2/HTdQJfCAL?= =?us-ascii?Q?LgxYmQpCps5C2JOZgW+/fig1wiWCVYelj0RHiVo+ahuUDDr0K3N3OgkrZuSX?= =?us-ascii?Q?ZL+xk0Ln4TeFA29MIq4bJcebP7NRPKhE8FB+O7U/wC+AL5Wo8v7fAYgBwHUh?= =?us-ascii?Q?fZ1rRUlGUybh25I6KNL7fpYJlR40Btu6YIMBLaEvo3PPXpVnMPs88IefYAz8?= =?us-ascii?Q?bG0cnpE5ERwvrx/Bs9twcevyWsEPh8dEy8XNI1U5qExeDpBJvdJGWVPxur1h?= =?us-ascii?Q?yAT19KoJgHKj6fcnb6DNjLleXhdmPOxby0mzXdTWoXISQXNWFddZIYfXKFlu?= =?us-ascii?Q?E0Uu9moADJoqBcUByWHj9oMD8DhF2zYjKokY7Eh0ypWJDbVzEF2C0XZuLODj?= =?us-ascii?Q?tOBiaxx8JVV54/2gR0nrS8Gtz67yopFmaZbJuOBsVjK6/I+8BIg/rTKXosWD?= =?us-ascii?Q?VeqJXvn8Z4cvRMvksO9ihMQKgHnRHdL2MqUq3cg1jn9dExXPwneF/Pdi/X6m?= =?us-ascii?Q?0A8EktxaedARZ2lvSyXNUKI4cF/8gyySkJY0ai1ZPFTW+ktOBAhPCd58Bz0g?= =?us-ascii?Q?kOWV5Yni2sjeIg1Q6o4Op1wykX3L/8/IHPFIuK37MuKsRKdsQo6MXK7Tqst6?= =?us-ascii?Q?OighjTT+/JSyT9g2rrbUzS84xJjDUrPukrO9yPJ9nSEnjd6ogY4ABpBHHV+G?= =?us-ascii?Q?am2d01AzT5DCRqv0ibiq40MdlrG0BNtwjGNLOoZJ4UzMMWWx1XK6mHwi3xnD?= =?us-ascii?Q?PN8KIZzvAvzI7oPuAT2jlACFXHpYoyepRmrPAQ4vi8Mkv2yNSO2BJ9WemrPh?= =?us-ascii?Q?cF9H4WksdUvID5C81GbwLQLztxobLB8R+p0gzMCPgSHIoteDiZXsUObvqpIj?= =?us-ascii?Q?vfG1u+NoDQtgAL37I4DnXlTj2J20Xw/jOhQ/AJf7t8A7yd7U9Gw/M0dfAaAe?= =?us-ascii?Q?XOWanFkJB+izEiEqSJTDVqzNfSdgi+eEyVFxR2NgQfydbW6vao2i6nq4ddla?= =?us-ascii?Q?TGCcxSk2U9nrhdICQXoJoFoErGXKbyJoPOvLoWsxC15fZQ=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?H5IQ32ar6uFHPwXd2daPZvia1PpcwoLVKN3jqvTUCq1YOUIErqgJi/Dd+vM1?= =?us-ascii?Q?zSWhdIDB++ceaWHIH2RDpTu4cQioZgIqtnjqcRIPDAJ0Mx2Obvdg05U1bY2c?= =?us-ascii?Q?2ATe/J1AAUpgnsVA36QTtox8xfcT6HR0ZJThLIwvXdL5vUR0ETL2lA7byU95?= =?us-ascii?Q?6igdWscLnMEZgbONl2SVsE7NGz6ZGC03Rw4uyVHK1vSMnksocZEZRUjP9eD4?= =?us-ascii?Q?Qg+c9XYzGh5Jqj4h7wiuTePbS81fINGnHL0XqPWBYhNzLcsFBnOw9NgivArz?= =?us-ascii?Q?JJK1UZZxRnXkrOdRQ4RjL2xN6VlagjtYMM1VrzTaPqTJ7rq30XcY7PfxVTJi?= =?us-ascii?Q?/BOAdM8io6ERHw2wxD4iR1lnjvGc4lTr88qzICT6naE2duuqfvSCykkKouOA?= =?us-ascii?Q?B8ZbF0rqtgfZLBmnDDum7EOQFtuzgxftqQaiXOlaxu46ZQxudnBGqka9l8F9?= =?us-ascii?Q?q0eHY+QGzRtIx+226lBSrG8YRYrajAkDTFp/KyAunU++qhXdnXmx8mAUviCr?= =?us-ascii?Q?D8jprCRhIN3EtLoGGz4pTXpwj38bl4HZES7Alq5e52QRFNc7sMnUiFBJfjXT?= =?us-ascii?Q?j2j/lhaXASwd6B2UaP5SiwBybCSYTzmzzNY6rokuFnygKf30H8kyU7xUlYX+?= =?us-ascii?Q?jwvhVfPxjhUO/6ZUaR0VbztMxWT2ZDtxt0K12fukmEzOBO73oBg99H8U3ysb?= =?us-ascii?Q?PtYoc3l3WX7VeSFwTaAy+zod5YsLVRSIycL8M4oiQF48DT8jyvSdyRFGyThJ?= =?us-ascii?Q?FlhUhru0Gp30etlBzBfeGI1jJCl7C/ES4cX8K+UPlRcXGpdWG0tmUeuiIFWa?= =?us-ascii?Q?pL7tnG6jLVMini6Eg8v7zxePzBfz2j1w+oCpuUbEfkcVij2205Mv1djJEqsh?= =?us-ascii?Q?tSkRokQWdloSgkdIT3E7Tb0m1LHepJk0B5deBg1E3/Yn/yJOEtgvctqEr8px?= =?us-ascii?Q?pY9kJziGICN6cfLuRtmeT7pDdqWUXnhQcAYiMqN3sgO1thMuiOxkOnudFZGi?= =?us-ascii?Q?sHza7kTd1kujpCZ4DoNO3e/YT7G2x/XtA6UbSuG4v/sU5WyspHtBu4eAEtcu?= =?us-ascii?Q?wtyIB1OlCdCp/scO0HKugfGvGx64NpMoxHPIWm7sXZAszYRJPGr9EYs0qW06?= =?us-ascii?Q?ct/F7WayJ7ft9Qrb0TouURy0egeJtW+bk7+J2cVxCukbJNs4EAgf7JJ8TI14?= =?us-ascii?Q?IzjB/6ZK+B2dj/zcym6yAY1BM3rKBC70FNU1uJEecjCqabeZIBfR/6A5BSbL?= =?us-ascii?Q?lmqUw/RhfA9TvMzlHrItdTpd7Jnnu29Zoy326/mKeymRGaGdLMTrlkFGTFEP?= =?us-ascii?Q?XV7YbEN/K1NEV8ByTDkPizC/OHJnneW4g6KlQ93p+wzaxj1zVIkCaXSsLYLq?= =?us-ascii?Q?vHZ54GZewarVIv4wTTF+GqI27BwoTcxSv0OEkGU57AntpYMIoowG0MPWtHZe?= =?us-ascii?Q?3eE5/Wv5kGyzuJmzpkDfVRRlT5CsWVuIV6+o9CaRfrqwZHmlYQnvtJFzAdV6?= =?us-ascii?Q?DnB0L7hgxliYA3v6kV+cHF0mykxIP+3kplEqrXgTfFdiWtbmyaaQ/tHpTnGl?= =?us-ascii?Q?VqIqFY6LhjDD6m5+XQWkYEIJIofpiBTMruCEU/4igzi1VYR4fF7cGHhqX4Mm?= =?us-ascii?Q?XFPZV22/sB3IWYEru2WuSp139LaYAnGfEeR6z7GG91vb?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 25f7acd3-dc91-4bd1-1193-08dcb85838cd X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:03.2829 (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: 9oZkTU9s51AdscErQ9TUrA8F2I2QCvHjGP6byrGFbk6qtzOI5gGlVw3YRbPUIqhi44Sy+kvK6XzZLIQWNMpUDg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/join.c | 915 ++++++++++++++++++++++++ 1 file changed, 915 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..842f26987728 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/join.c @@ -0,0 +1,915 @@ +// 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 "cfg.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 -EPERM; + 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; + int ret; + + /* 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 */ + ret =3D nxpwifi_get_common_rates(priv, out_rates, NXPWIFI_SUPPORTED_RATES, + card_rates, card_rates_size); + if (ret) { + *out_rates_size =3D 0; + nxpwifi_dbg(priv->adapter, ERROR, + "%s: cannot get common rates\n", + __func__); + } else { + *out_rates_size =3D + min_t(size_t, strlen(out_rates), NXPWIFI_SUPPORTED_RATES); + } + + return ret; +} + +/* 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 -ENOMEM; + + 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; + int ret; + + 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 */ + ret =3D nxpwifi_setup_rates_from_bssdesc(priv, bss_desc, + rates, &rates_size); + if (ret) + return ret; + + /* 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->datalen && + (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 -ENOMEM) + return -ENOMEM; + } + + 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 ret; +} + +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.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 & + 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 element)); + 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 -EINVAL; + + 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; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, + HOST_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "could not unregister mgmt frame rx\n"); + return ret; + } + + 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: + ret =3D 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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 536AA1990D7; Fri, 9 Aug 2024 09:47:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196836; cv=fail; b=VISpPRC4kKtZ2pQzqyZ1HkNwH6NQKY8aE1+ZxVBP4IoV7RjrCTF4Z45GpOc+3/5tiVzXEzGVRAXgmXck/aTktiE2w3MJKtKz4WCl9g8d+K3XjjUxQrG6yS3TMwGMkhEMPDq9mr4NAJ12bWkyIozwGpp8fwWpB4lXAJTsbRhdIuE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196836; c=relaxed/simple; bh=o0Dnw1GFJxV5F057desk0J4NecduvhXjZumLM20HBNU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=uNk4zvtUXfqtHgH8AGm/KoyYlqLLZ8fFpzOr6UlmyJoYm5uOKsCFFjgUaJRCQJxtJFynO6QuBCUyroD3QZ4K66pjmLCo6eWVGL0appdLojZw0kQWzSc4ybRzUGxSJgVMeKOq0ZDau95KAQo7Xqt+olHmPjycDnk0LXZoHr3yVco= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=YKSMf/3x; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="YKSMf/3x" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=sJl0uvbuGI3LhBwf6Ze0nQuDqOprbRwGuwME3w9nxagNmCS+GldCiQC+84fynrnyt7QPu1KtKWXBleTRjIDk7aDTGOu/G0ANvVOzP/G8pQVnwYmWuH+Na89S8k7LH1YiRrEnGHP2RS17M5vdvNSP5do7HjEVCM0M5zD4JZvRWqlN62scApNrkqsw/wo0j4F+KNL48lnRhQHOVtAEdAIdf72Cnm1ohxF5hxyY+O8Tu7Qm4aQnR6wXztchvrTekoeStP1ZER7fSW/h3d3tgu0dhrNltsNHofFcH7uB6isD4J8XLB6VaxlKzoImDJIQfxeaTo6ytNgzFtLbsSTD8qP44w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=+PDxQ7KNVQbH3U4uOMSyCEbWweJKkkV0P/s14apq1LQ=; b=qVkVykax7/6fv+gCwwlkWYpS3ZVB4V5NxDWLl52sQwSg59ruUJCBZKRT0uvSrSwarewxscVCUOs8YbXI0E5Y1HClyMEB/e9XvUrSCniKL8gkLbp9ybBGL4fTCbg4RWNswMoSQ3/TiQrBENAlPuJCDB8i2Jz3ujBE0lrcTxMsSmYmE0w9hYBoRJ0/iJVHuDWpP6LR7QdJ3VkQpXfDknlhk2OMreG9pKiHucbvSZaAZY0v4UAVSAZUrx3GeRiKurSK/sfj8y6eKpKnPy7f7wPiPQ4qY9X/N7QlKJYtTpiLO+dd0TBFc2Y9EMdxCJcbcOT1jfyW7Y37R+sAvmP/1fKmpw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+PDxQ7KNVQbH3U4uOMSyCEbWweJKkkV0P/s14apq1LQ=; b=YKSMf/3xdO/pntPHV8mu9RrEP4sbjc8qnwOPP41tvWTT6NzrQMWDNzpBuOvu0OgP6O2qZ1EJpMGqhqOzFF+wGdG+jQ58pRP8jjRgWgxobV6PFVHdmQBVyIyYnF3oY08wK2x7vQ6NoEu96pLUCIZ5leiBvhc5r/WUJEXj22hn5/ugRq16JiGlEWMvklt30TXoGAG2VbfbznX+Exo4a7oORdPmoyjuk4QfozsvcDhRT6Kaq4scx56Rgc+jkwrV0Ym9XHIuiYf/X+5JBl4oYLuKyR6DqoxdO2uukyEWxrYXmZ989+PWocvyLv0JWn8fBMQ2GRBd30RQ4rXwNkT3GUrVmg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:06 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:06 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 23/43] wifi: nxpwifi: add main.c Date: Fri, 9 Aug 2024 17:45:13 +0800 Message-Id: <20240809094533.1660-24-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 81c0bff3-fe33-4e81-34d4-08dcb8583af2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?nPFRgA1ZmeowMMmgS92A94AeLiZt+3TpRZLxJe66LDWawanubd53PIMEQAty?= =?us-ascii?Q?93Vw4TytGbtf2CNKgR38NZvquygMYIBynNpuA8TANFm7lqznhlBhVhqBrNyM?= =?us-ascii?Q?lBHDE2NH5a7Pz+Ew6PL4fXmLS9L4vAqY5xZ07zfXB/ugLr0lD8iDsyE8lOxp?= =?us-ascii?Q?mTpVuiJ+umAS/OvsKDACcMdgGPRLCOwPFQZK2PVstkQuCTF++nPsNDHr0i+6?= =?us-ascii?Q?ZPX6hKMQrGW4aKS+I+bVEtqs21VGMOH9B8L+5L2e5kfQdjrlfHpWPxHw5O51?= =?us-ascii?Q?2QFA1t8xm2MS2T2VUagV4xxsLGO8iXlqrWtQTbt7uOufVg4Vl64hPUx0r5f2?= =?us-ascii?Q?QDrg4HKT9izGc+pcVX3Lj0RyGbaROiGHi7zOma9Vq2e36ST4+7qLC9oaTgXp?= =?us-ascii?Q?NrEAF5BYpRtcuqQMVJFs7aqhvQ7Swt/FDDdJHSb1+Zd7t2R/irnjU8BjyEyi?= =?us-ascii?Q?sD3VGtWp9YcGfDyWLElwycUEHR2KQa6aTSD4HW+4c6pP53lq88ISlmBNaRIw?= =?us-ascii?Q?kb44hFtXg+bxvjOP7tdTFxWPu0AaXtvioHxO+FDW6uFgrGJdJsuypYoCSxGz?= =?us-ascii?Q?LkSIputyH7cpYVMqBbOLcR3hbxC5fufhz/lcHUw7T1MUligbOCoDh+caMMBv?= =?us-ascii?Q?et8eeaM2nSFlHldWKh9XWEmAXQ4I+ydJlBKBBZJ5WrFbq8qCkiMlaIPSqURi?= =?us-ascii?Q?6qSnUHl6idOlvtVsYsG67YtGkhcmGUn3Ykx+3xoVFsh4YNFcs1r9Gq+RLvyV?= =?us-ascii?Q?pbT3YHK3eGY5HM06wDDjlRiyJB5FUIIKcLNUnaGPTuIwZ5b+2EazVvWxB4IS?= =?us-ascii?Q?NoBsucV+io32yjBzV0cyTG55qvhLL3Dr6JvJvSH9LQRNHw/qBry/aNlHN0w5?= =?us-ascii?Q?CDCmGfBxFJbbCAzhhGOHDSbSvUKsmHWdvJI7WoECzNSIc6mGTECGIfcAlyrw?= =?us-ascii?Q?ykoShvDjW+8RVfLshNNk57hH5dDBuX4Y8Tme9ZEgJCCJlTFl61YjSKtIcVuO?= =?us-ascii?Q?yw6bexXfX2nFZt5pF40fl+WVRle0Ib7JUC7BMsEvn0Xpf2RoH4PB9CsAPHBj?= =?us-ascii?Q?YApdcFsbY6eiAInlEPovENClegIzvtafXjkX5Tf9SLLKcrzZttF/wwuP7irW?= =?us-ascii?Q?9uAYiiaYLia3A/DVVG0mlcSE8pdgBwi1v99YJyxYy3i4Z22zbjDjtFJ6X9nl?= =?us-ascii?Q?1A0ozu3uzXxwwAJ5QlEh9Ouo8rILKfM/Uu53QOQqrJ2FsStAYEzFYey6m8/c?= =?us-ascii?Q?9tQNsygo661Bp3rk2rmBrAEnU3+dbJ7cu9zyl7jn0MzkfiK6rHRLke7ejj8P?= =?us-ascii?Q?bGcpOoj31YYkxoGvxwwXlFeMSDnsJF9mywq+tyEiZzZVlg=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?QAKiE0LcJjUmh4FNU+TX66hF1hgogz/ZFd8k+6D/gZKekbrjgwE+BHGktSiX?= =?us-ascii?Q?UBUOzVrvCRGLQbd2K8BnHbp89/Be7POa8zDkn7pGmrC3JXpR/TXPGtRjq4c7?= =?us-ascii?Q?1mE46KLO0sBpjwRB2mAwaH41iJJnMq+gA4CaypQ/Zy0DSxKHUAACa3c4A3o1?= =?us-ascii?Q?RVjByjc66o7UmvTBD21X+pt+3JCiwpdCjQC+GEFHGQvY+uVq3uCXjdClImU4?= =?us-ascii?Q?5IWSeXjnSPKbu7lDp/4W7r2rtSxUZsp0ROKGtaeHKmsM06ZzK2h0ov1Mhd3r?= =?us-ascii?Q?d3IqV6kwntPAEOjpf6URR5WY02cjFOoKOg1TApWVYyQWKjuuBzMqPebGdC8Z?= =?us-ascii?Q?rU2Tgo+C2qKruUCunbQI9Dqfr9nA04oy9Msp17AvaJn6CYsekMg/4Pl906g8?= =?us-ascii?Q?m22kEQJVEGghTc8n5NSWLB8i0Rm4GfJ/YBZxTWuPUIBsCmfvAMaiFOP7uG27?= =?us-ascii?Q?2o7Tpyf+oQY/Wqefv7ACnRTuxaVI08WIW/vjfPlldffLHxx/3T65qD4TeV8u?= =?us-ascii?Q?ybePW5iKpEgFFa4T27Mgj0gyRKoOt6O+viwY7+S7GU3C9JEetvVpwgRkqRXu?= =?us-ascii?Q?8fZF3DQ9xhc6dJ9Z0KwMIjCAMN+6x10bj/WtwjTLV3HzR6GV2yS/xTO+V84H?= =?us-ascii?Q?CRNuRqWAR9SnsRqf7bHinWkLrVoZ6KOZK02rzQDWjjk3jtJe1e3tvXOGWK4L?= =?us-ascii?Q?HE9ACe20bqD2H5pStnXlYJcQZmvKGTW1GnHHik90r4vITIVFmWF7pbu+JfT/?= =?us-ascii?Q?x5sNkYgfciCnwNbw03A+GqTEDT7AreWpYEmVYNnA24nz9xvlOitu46Cwn3Tf?= =?us-ascii?Q?K0AKd7I2bMuTjrn6yDvJXkQyv/MMQ2YtxnLh1E2JiKx3m3exCWQJ8tOChdfV?= =?us-ascii?Q?LWslmTdaUcTEMm86r/Ul9Iqg00nhRN4pbHRBTpAO3cLDEs0u4Ra1L6JChGZ3?= =?us-ascii?Q?tnuRYJVOyck67bE2IT6/FPX/a8aeyafA6/GQiugduSkagjTIQpdz3whAIJDq?= =?us-ascii?Q?V3x871nbctZxZT+TTz8/hWqDyiZEelabIZnW22vWJxn9HlzE5eFhxcYJ70Mk?= =?us-ascii?Q?EB0LXJH8mEZCTAhj9f9CZGC5PNeQ8hp0RGqoqabIim63cWGnKZF/gIULL9Om?= =?us-ascii?Q?ztPXp+bhYcLmndNNpDtUKTK25uCiXpAr1HIiTBOnPkM6ra+Z2lbNo9F8P01d?= =?us-ascii?Q?F0/ueNjUDHSvJOY12vR64WELXeHaQfTbi6i7ndHwPkRI2k/lox95CojjzNMf?= =?us-ascii?Q?X3XGV36uvBpqlZi7vdTpMT7o002DSBv2m2o1YImye4tDwp79E2DdRNCRUsq/?= =?us-ascii?Q?GAkT9Rd77JP3Wv+dgr5MlzZwgo5U6/J2WizygBkA8jFG3rWuZly3oOnTwxX5?= =?us-ascii?Q?fZFLOUvGg0A6gXLf6WLaKFUt82mF4xFh6Csdqxbq3OUi61iSZXLWkLn0xuQV?= =?us-ascii?Q?SJvfDaE0ozy45B3CgA0Cup2+M0SlOwQNW6005BXQ3FRF7M4dMx0vzIECRAQK?= =?us-ascii?Q?XqSgcoCpOHWiRFXcpDsNK1S38WQpjfWvW4j5Rhpcjm8XGRmfEAdgiJocs15r?= =?us-ascii?Q?UF7VpHoElzVA4kklV5ozNq/bnCsVdMZbO75zomcAaapg/hHDdXOtmmHspMcj?= =?us-ascii?Q?OLQgVeVns1qKNELgCxjwIoF6WwAWapqT8Fs6hMpWxQA3?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 81c0bff3-fe33-4e81-34d4-08dcb8583af2 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:06.6276 (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: JFuRK7yU5RllKWN9eeW4WEtJdMJWNUIzWr2PVePF+xxktDIIceRqfQWp5ro0VSPySTT7F9mC5ZpR5ku6BfwP/A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/main.c | 1666 +++++++++++++++++++++++ 1 file changed, 1666 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..296a54240c2b --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/main.c @@ -0,0 +1,1666 @@ +// 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 initialization, this function also ensures + * proper cleanup before exiting. + */ +static struct nxpwifi_adapter *nxpwifi_register(void *card, struct device = *dev, + struct nxpwifi_if_ops *if_ops) +{ + struct nxpwifi_adapter *adapter; + int ret =3D 0; + int i; + + adapter =3D kzalloc(sizeof(*adapter), GFP_KERNEL); + if (!adapter) + return ERR_PTR(-ENOMEM); + + 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) { + ret =3D adapter->if_ops.init_if(adapter); + if (ret) + 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]) { + ret =3D -ENOMEM; + 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); + + if (ret) + return ERR_PTR(ret); + else + return adapter; + +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 ERR_PTR(ret); +} + +/* 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 void 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); +} + +static void nxpwifi_process_rx(struct nxpwifi_adapter *adapter) +{ + struct sk_buff *skb; + struct nxpwifi_rxinfo *rx_info; + + /* Check for Rx data */ + while ((skb =3D skb_dequeue(&adapter->rx_data_q))) { + 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); + } + } +} + +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 + */ +void nxpwifi_main_process(struct nxpwifi_adapter *adapter) +{ + 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; + } + + 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; + + /* 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); + } + + /* 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->vdll_ctrl.pending_block) { + struct vdll_dnld_ctrl *ctrl =3D &adapter->vdll_ctrl; + + nxpwifi_download_vdll_block(adapter, ctrl->pending_block, + ctrl->pending_block_len); + ctrl->pending_block =3D NULL; + } + + if (!adapter->cmd_sent && !adapter->curr_cmd) { + if (nxpwifi_exec_next_cmd(adapter)) + 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); +} +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; + } +} + +/* 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 =3D 0; + 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); + ret =3D -EINVAL; + 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) + 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) { + ret =3D adapter->if_ops.enable_int(adapter); + if (ret) + goto err_dnld_fw; + } + + adapter->init_wait_q_woken =3D false; + ret =3D nxpwifi_init_fw(adapter); + if (ret !=3D -EINPROGRESS) { + 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); + tasklet_kill(&adapter->rx_task); + 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 ret; +} + +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. + */ +void nxpwifi_queue_tx_pkt(struct nxpwifi_private *priv, struct sk_buff *sk= b) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + 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(adapter, DATA, + "stop queue: %d\n", index); + } + } + + if (nxpwifi_bypass_tx_queue(priv, skb)) { + atomic_inc(&adapter->tx_pending); + atomic_inc(&adapter->bypass_tx_pending); + nxpwifi_wmm_add_buf_bypass_txqueue(priv, skb); + } else { + atomic_inc(&adapter->tx_pending); + nxpwifi_wmm_add_buf_txqueue(priv, skb); + } + + nxpwifi_queue_work(adapter, &adapter->main_work); +} + +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)); + + 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 RX tasklet function. + * + * It handles the RX operations. + */ +static void nxpwifi_rx_recv(unsigned long data) +{ + struct nxpwifi_adapter *adapter =3D (struct nxpwifi_adapter *)data; + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) + return; + + nxpwifi_process_rx(adapter); +} + +/* This is the main work function. + * + * It handles the main process, which in turn handles the complete + * driver operations. + */ +static void nxpwifi_main_work(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); +} + +/* This is the host mlme work function. + * It handles the host mlme operations. + */ +static void nxpwifi_host_mlme_work(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 mlme work function. + * It handles rx mlme packets. + */ +static void nxpwifi_rx_mlme_work(struct work_struct *work) +{ + struct nxpwifi_adapter *adapter =3D + container_of(work, struct nxpwifi_adapter, rx_mlme_work); + struct sk_buff *skb; + struct nxpwifi_rxinfo *rx_info; + struct nxpwifi_private *priv; + + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) + return; + + while ((skb =3D skb_dequeue(&adapter->rx_mlme_q))) { + rx_info =3D NXPWIFI_SKB_RXCB(skb); + priv =3D adapter->priv[rx_info->bss_num]; + cfg80211_rx_mlme_mgmt(priv->netdev, + skb->data, + rx_info->pkt_len); + } +} + +/* 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); + tasklet_kill(&adapter->rx_task); + 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->tx_pending) || + atomic_read(&adapter->cmd_pending)) { + nxpwifi_dbg(adapter, ERROR, + "tx_pending=3D%d,cmd_pending=3D%d\n", + 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. + */ +void nxpwifi_shutdown_sw(struct nxpwifi_adapter *adapter) +{ + struct nxpwifi_private *priv; + + if (!adapter) + return; + + 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; +} +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 =3D 0; + + 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; + + tasklet_init(&adapter->rx_task, + (void *)nxpwifi_rx_recv, (unsigned long)adapter); + tasklet_disable(&adapter->rx_task); + + adapter->workqueue =3D + alloc_workqueue("NXPWIFI_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (!adapter->workqueue) { + ret =3D -ENOMEM; + goto err_kmalloc; + } + + INIT_WORK(&adapter->main_work, nxpwifi_main_work); + INIT_WORK(&adapter->host_mlme_work, nxpwifi_host_mlme_work); + INIT_WORK(&adapter->rx_mlme_work, nxpwifi_rx_mlme_work); + + /* 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__); + + ret =3D nxpwifi_init_hw_fw(adapter, false); + if (ret) { + 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__); + + tasklet_enable(&adapter->rx_task); + + return ret; + +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); + tasklet_kill(&adapter->rx_task); + 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 ret; +} +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; + int ret =3D 0; + + adapter =3D nxpwifi_register(card, dev, if_ops); + if (IS_ERR(adapter)) { + ret =3D PTR_ERR(adapter); + pr_err("%s: adapter register failed %d\n", __func__, ret); + 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; + + tasklet_init(&adapter->rx_task, + (void *)nxpwifi_rx_recv, (unsigned long)adapter); + tasklet_disable(&adapter->rx_task); + + adapter->workqueue =3D + alloc_workqueue("NXPWIFI_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (!adapter->workqueue) { + ret =3D -ENOMEM; + goto err_kmalloc; + } + + INIT_WORK(&adapter->main_work, nxpwifi_main_work); + INIT_WORK(&adapter->host_mlme_work, nxpwifi_host_mlme_work); + INIT_WORK(&adapter->rx_mlme_work, nxpwifi_rx_mlme_work); + + /* Register the device. Fill up the private data structure with relevant + * information from the card. + */ + ret =3D adapter->if_ops.register_dev(adapter); + if (ret) { + pr_err("%s: failed to register nxpwifi device\n", __func__); + goto err_registerdev; + } + + ret =3D nxpwifi_init_hw_fw(adapter, true); + if (ret) { + pr_err("%s: firmware init failed\n", __func__); + goto err_init_fw; + } + + tasklet_enable(&adapter->rx_task); + + return ret; + +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); + tasklet_kill(&adapter->rx_task); + 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 ret; +} +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 + */ +void nxpwifi_remove_card(struct nxpwifi_adapter *adapter) +{ + if (!adapter) + return; + + 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); +} +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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 EEA991991BB; Fri, 9 Aug 2024 09:47:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196841; cv=fail; b=QruSE6wy7byV5BAlz/2kNBQRmrMy+UEjmJNvDwXvCs2TzvIioQFhmicsoGa7uF1yS5ykChKMzOkKLpv7oVN4ZID0XIQsvfNDtAU0IsMvlAiH2281pMJnJOySyq+/AeSy4LZspemM1hUIBuILGsv7qqFVJM5xBB7ftzE9BUGMEFI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196841; c=relaxed/simple; bh=wG9KO3wyO5/+VlP9FWt+0iWhmYP42qArz/oeSaBwMSg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=jrRX7pmGIIR33STqjxa2rm4C1Nz6dWkw8vxVoZiscDvrb1LBolQpoofhvhx0ECA2pZbKpj3jZr4cNBax1WKq8fAAfO5oDmZ+nQTarpg2qwaZsDu+0DTvzHraVX1eSokucMMkb0j6pjBtpSACN7M3WJFCCNSVooCC/OIpYRDnLJo= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=YdexqPV1; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="YdexqPV1" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=GVfGIHkpIICc7TYALRq8ohHUMwy/9yvLTIMpsrkZfuC4C3Ttt4PxfyUr7XoBPt/tPpnJaYtvp+3kJaUgfgA/qNHRPyKKfup4NXc69DdG8Hy1ANvuLTMrHbwe5J9Ym05vvgtzcAAIx40ogjIdtVEe9MKXsfQoW1jPSd+EZY0s0Xz7w1blAcBPTwf2ozdz1mdJOaBqDte+hnFTC0cJeCBUBB1ZEVvCfcepktcwjK3/LS7KYWd1MvZLww3A7rC2qWMSHR60DbTyD2xNNDeCFy59hA8tU/EnvGb/YC/rdKB5cRFNd+bDTCT8X1Q1J+8edapMuLSii1VxfO5RZiHJ6Cu4rw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=vkAavaoGg43VlHv1lz0t3EQfOLCfry6Jlwy/EcVvtW4=; b=QkjH9twdtqAeIE5WCbN87iGblU71Afxt5weDgVS4oZFQlDnjk2sce6ixH1t0vSzM3x94SHvv9I5o2k9TsLvKFybbFTSDRY0LgKDhub1uhY08FkTM2WWfmBu1XtHuJCBbXFCD0q/RE6CndSb3Lr02BlgDCkD+QIdzRjL8GekqMPkEuGpaqfSbSnMdl5/gPCuMToPvFp9DBa8OOTPWmdPGwVxi5rLeDpjUVL+82berLA3b/owNyAYz+RAEN1VYEQFQU93cRr0BsvoZYrr3SqYNhy5J5/BfWGZ3Dq+AjwefoTzTDmGP9i035aJbVQc2wkHcEV5SwqdTl2fVw0rWKPQe8Q== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=vkAavaoGg43VlHv1lz0t3EQfOLCfry6Jlwy/EcVvtW4=; b=YdexqPV1PYe+CYybKRbxmRH6CJt+En3jGrmZr26e8Hgm+ygYLsWDosILfo7qQw+ufV4yM1rmoQ1HkhHw9VxdQPMDEvvMT/q93G0m7ronzfud7rtTbhkg6A0YmJeia5EIMB7qcREFEZt8eslRZB4pjfusfe7SPTsUcYyOpUmGU6k7tLMgtkukKiox/8W1DaV8Srz2EzM1Xhyeu1Z1eUE3ZT6xgRiRGReCK8FpaVC13OdZcLhIWCYrlKMp6nPBgD+jqY7clhiRfynzPHe02nRbhIuXb+AL63claAZ414r+PIXffEe9zgnkWxN8/KHp0LshDjH2u3TcDrs7JSdX41sbLA== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:10 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:10 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 24/43] wifi: nxpwifi: add main.h Date: Fri, 9 Aug 2024 17:45:14 +0800 Message-Id: <20240809094533.1660-25-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: f4a61959-a58d-44d9-eb1d-08dcb8583ccf X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?2WgnONESMjAlBF2Ci0GWfFoymP5jA1XtX+3ovdWlnJDN3dewPIba+YIL5oxQ?= =?us-ascii?Q?A8Zvktwzer2xGusDYgxeoSb/rVhKhk7Yti2PKBAwL0BxSQ1hY5ABpJYU8b2y?= =?us-ascii?Q?JSvCFWaHe/aOtao/LQImiy3MDVkNViQoDCaCYmWEyx3Nd7wmFIa73FH1B2ip?= =?us-ascii?Q?N/O/FKZSbh1t93WkT8e4XxBlYHur8cH5gvBJo6AXOjD9obVFOoMRYzVWVv4/?= =?us-ascii?Q?U//MGX0qtDH+V41gpM7ptgY+lmISehKdH58eqpglRtBEwFIN/xYqkz5OqenC?= =?us-ascii?Q?rw/ELdy80QQZWhjyrDTo7GrUc4BBCLipxCSSTOxkEUeEUelbXBE5LNkw1geP?= =?us-ascii?Q?mGhkvr0hSNXe7g4FsaJdl9bDBnhRCIli6hH23SeSwlQ+HU8AjY2ooIaURpTF?= =?us-ascii?Q?pmzE2p6stF6C5LLCwk43YcoetCi2yIbvthvf4LTmDjrPSZcri9iFrNtwecw7?= =?us-ascii?Q?JD0EiOJB0HKOWjDdqP/djZdTO8Jpsb+drCCJl8zhWrwZJh3MIUsSI5XrjoXm?= =?us-ascii?Q?lp12duEiXqu1pjM4wWNE7f7zIsCICK7Tm6vo1bVOQERT5L1UNoZFXuwYjGXA?= =?us-ascii?Q?R+GA849bAtXMtwoHWZrCaN+47EpTM3JblXVpRvNglez0gja1KWKMC9yl064z?= =?us-ascii?Q?Ih/Zc3thCfjYSaGuYS964XWc6A8Xisy8gkkCKC6djL+lzlyqU6uWuQslKCiY?= =?us-ascii?Q?4PNIh4N7UKqUiI4JgOVy1aMQEla3ro2x5rUds4z2h43lucvro2jHKRfv2fg2?= =?us-ascii?Q?R7hohk07IwNoMqKF65LiYa0q8qUINxZXKItREZsxZYqJRIC5pmFj7NfiXJig?= =?us-ascii?Q?Wm2+xl6JtYxxEyIdx2HsBM64VC7xx+IVhee2EiUl+ZuyVwlV2Nu//qwQOqt+?= =?us-ascii?Q?G74/G05KZXlVN/eNmpUUtEaC0s2mTjYA9J03EreBiUbieWQedxNUoZLgT9vu?= =?us-ascii?Q?sFMnqoY0H7Q5joVj2WH71cMB15egMS7MxnpeAkxjPVgit4b4R3qkrYfx5iuq?= =?us-ascii?Q?6BUpyUw7nrNVOYgkj7A5dErPA69RdG6CmqqR9wJbgFkZGAtMI0uyrxCz7q2r?= =?us-ascii?Q?6BcLurpnHx42ZekYl0/F9fy3bWyOVwjh5JZ3cr3nFkcgL65TrKnwEqmZzv2c?= =?us-ascii?Q?1RRWkXqr5HMCp5RD9sRhUydzIsLxesCrM9nM10um+3msu6r7yxWiIfnH/sDx?= =?us-ascii?Q?kuT6PMdBp7qUHdK5glwLPA92iZY3TBZ7XvvnR9ouMQe80Fo9rG5gitaXQp5E?= =?us-ascii?Q?cDL6QfOAUXDcwNMx1XtF7X4YaiRp3EEL9QJsMiJHMv5hkJtSNY6kq1d057tY?= =?us-ascii?Q?6Hdx6etXU62cdHfR8jb9DRGnE7n6HMvU3a4C+R5PXa1OfQ=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?jz1NQXg6jhIEoJ5v1jW92tNBvCQfA2OnaEUB1CdRXL6yFrfJ7xzFXzR484mO?= =?us-ascii?Q?WJpKnyBgWEmZVBOui6hGhbCtQy6wtcaA/x82L2UVzq3bALvniYx+oev3ZatE?= =?us-ascii?Q?aeCxIWoQwUVt4n3o4yQ/F83a1g4HoRY/rg+DkwxtDeZOhNdDBAAPFiSBTSMA?= =?us-ascii?Q?oreO42s7PiWfRxqoFvlzzYo4kzhtZRFKTPq48iP59elqoJgcuIa9M8xtcQr4?= =?us-ascii?Q?J5dNfUI9fd3Ae2F2QonkwJ+9HBXHwhWNOHBbKTRweU2YyHGw7ViiXudAtTnC?= =?us-ascii?Q?oZHP1RV0b83X2sArMU6Dp2A23ZpBKqalLvShDkgWEI8nkocVBENyFMWqnTwb?= =?us-ascii?Q?tffEX6WGGS32Q3aQA5Usue9ZgU+vIuNLdpjUeBGbSKw/Exsgycz0p+JunvxZ?= =?us-ascii?Q?bVAUYW47eQeok0VmmpjgQD08XWYM2pR6YT1eoA7U/fXZKgSvYExbiTfUwBlI?= =?us-ascii?Q?DtfSGdZnlqwyG2UfM4qy66h5aWLhMvUDbuhWu/TqSXDY3y2fUTWzBhQaWSBa?= =?us-ascii?Q?HpX5M3Dgei8FT1psmWqxsDKCjbLPBiUj6ihhtFRWwetHM4sEZJdhHGh+t8eT?= =?us-ascii?Q?f0T/o01GMQ5LOxDyJAB7iOhSLmPL7v3alSj4eNU+a1bYIFDI2aSV/DA5rtok?= =?us-ascii?Q?cowwxDi6MRi85UbuaTK3JNJEWVXt3HXB6mG6Epxe0HvqqeGcxAo53Ip29vTh?= =?us-ascii?Q?IFMAFFr5CjTGZweMoPmW6VJZCPqpWUXO65pnudsy4YBmXhh4ZSskGS357j9i?= =?us-ascii?Q?yfNC9VdY+tqq/7psCRgvae8Du27uEtPwWx27qkmtBNuh3ZiOa9uEjjf8ZCRp?= =?us-ascii?Q?/R4YrzziUASx/qZrpXjAxPvx+DTPbrPqj+CJIYTCzBsMUqFN2F83yjrZnR/W?= =?us-ascii?Q?xkYwkNF27ZzyuG2yNh7HEwWdfjpEblZjeBS+SFLC4YwS5xBy8C6/QGQIGx9i?= =?us-ascii?Q?sN8mWeFBIkTMaEz5/8vgvBmU8Nulw6tQHRqKw8iXeGuNtOXpi9mCinaeDJtA?= =?us-ascii?Q?r/ESnrzvWywPGZS3fOl07EICH2tzX3FU2OIROyRnWjl1W0GGAnaJDyV/4eOC?= =?us-ascii?Q?jw6mt9JJ/iubpYDTzIAMXgXfuYiNlOnA26N0QCI4c4a4fOy/y8MHxReyMS9U?= =?us-ascii?Q?8rj6KyC98voSy2tqeUZSfmXVZjYoLQ215UGq8DPowVaVfF5M4MuiID6nYqtz?= =?us-ascii?Q?iG2Wx91mL/6m00TLJEWuESC5k5R3KoY98FpTCnElmZ1+NP6roAuBueolwrRb?= =?us-ascii?Q?ooBYhjzBZjlXAM2/9usmdGYUgxLK/hiE0ZbyUqy41rYaUivM2H/ssmYvG93n?= =?us-ascii?Q?eE1Il+/2A+H1U2XH9zrARw8QYrhtegsggnoS61IVgSWq5gAJ5unBJb7wsGHM?= =?us-ascii?Q?iTgZ/H94n6D+zI4phjDeg9VH1BZS32607k+HOwutvyDqkTuBra9Ht19QjxMw?= =?us-ascii?Q?HfwqUub0kmVllMxQ2HmL/g+IMrC/QIRdU57HDr5b5lKD1s7x+uX47AjDN+E3?= =?us-ascii?Q?s/S8FuCzBmvsmZtUgLI+BypYsrKnaYIkfgb0FKWkIx/QiaBq5DYF+d4MhyYM?= =?us-ascii?Q?xBVcZsxYXtGEt3B62dHKfSKbqXl40COBX3ki74LTamA755zvtVRa0WpwZHbY?= =?us-ascii?Q?ghXGQH5N9sOA51fyx7I8v/g/JPdaG9baTtPLwS+wRTl7?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: f4a61959-a58d-44d9-eb1d-08dcb8583ccf X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:10.0321 (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: CA1VBVLRTVVpoWemLxy+hlzM8uMWBVv3k5CfgDaAWp5URFWE8s3xav0VEnwdG0VU7+F9eqwEsoAuLZZ4sM3RMg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/main.h | 1478 +++++++++++++++++++++++ 1 file changed, 1478 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..62a0f4a7e37d --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/main.h @@ -0,0 +1,1478 @@ +/* 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 "decl.h" +#include "cfg.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_DATA 0 +#define NXPWIFI_TYPE_CMD 1 +#define NXPWIFI_TYPE_EVENT 3 +#define NXPWIFI_TYPE_VDLL 4 +#define NXPWIFI_TYPE_AGGR_DATA 10 + +#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_vendor_specific { + struct ieee80211_vendor_ie vend_hdr; + u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee80211_vendor_ie)]; +} __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; + struct ieee_types_cf_param_set cf_param_set; + u16 cap_info_bitmap; + struct ieee80211_wmm_param_ie 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 element *bcn_rsn_ie; + u16 rsn_offset; + struct element *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 dfs_region; + 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; + 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 delayed_work dfs_cac_work; + 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 vdll_dnld_ctrl { + u8 *pending_block; + u16 pending_block_len; + u8 *vdll_mem; + u32 vdll_len; + struct sk_buff *skb; +}; + +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 (*deaggr_pkt)(struct nxpwifi_adapter *adapter, + struct sk_buff *skb); + 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 tx_pending; + atomic_t cmd_pending; + atomic_t tx_hw_pending; + struct workqueue_struct *workqueue; + struct work_struct main_work; + struct work_struct host_mlme_work; + struct work_struct rx_mlme_work; + struct tasklet_struct rx_task; + + /* spin lock for following variables which + * are used to synchronize main process function + */ + spinlock_t main_proc_lock; + /* avoid execution of main process function */ + bool main_locked; + /* indicate if main process function is running */ + u32 nxpwifi_processing; + /* indicate if there are more tasks should be done + * by main process function + */ + u8 more_task_flag; + + struct nxpwifi_bss_prio_tbl bss_prio_tbl[NXPWIFI_MAX_BSS_NUM]; + 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; + 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 dfs_region; + 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_mlme_q; + 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; + + bool ignore_btcoex_events; + + struct vdll_dnld_ctrl vdll_ctrl; + u64 roc_cookie_counter; +}; + +void nxpwifi_process_tx_queue(struct nxpwifi_adapter *adapter); + +void 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); + +void 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 -ENOENT; +} + +/* 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); +void 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); +bool 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_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); + +void nxpwifi_main_process(struct nxpwifi_adapter *adapter); + +void nxpwifi_queue_tx_pkt(struct nxpwifi_private *priv, struct sk_buff *sk= b); + +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(struct work_struct *work); +void nxpwifi_dfs_chan_sw_work(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); +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); +void nxpwifi_shutdown_sw(struct nxpwifi_adapter *adapter); +#endif /* !_NXPWIFI_MAIN_H_ */ --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 A16351991D9; Fri, 9 Aug 2024 09:47:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196846; cv=fail; b=Rh1GlwFdd5JiH8kkONBUt/gzT+pc7D3mm0na8IAEKOhJLL0ZcDWCDqzZjT3KpfpIayUwz/Zq3cxoyODQ534tZyYEULwHU6+ifkHTrDXWKF2tJx3rW/HF6UUeUQ2XRQ/zIhL/oWeSpMgNfqTxwQb2AARx19axGVgRZ2ghNY/d7Tw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196846; c=relaxed/simple; bh=QTGnfu0mS4vB6JQghPd5On84dS9pp+8pfV8mP1q2gJA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=BBasMGJOy/9JiOLNDazcAAGyRcfnEbpL6JkIjHjGBzSm6MQvYp1QP2A/KFM2QWtV9aK+DUzGjLdlI3kJuMQaKMJjbQt3SWqgR63+fn3/BA/gUwQWWn26GPT1bxanI053UBtoq3ldFr1jr5cHqse5A6zBJQZHaJ1C7F6gl0TQdE8= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=ON8G1GHD; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="ON8G1GHD" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=MJFUSmLBhWtO3R7r0wDX3kC90RoahCgVEj43eShIOF8K3srT3KUyKB/djFmGRA7zsrLsnYd52w4swZmpEDNDN6USm5VavrBoB/Z1MlrngOXwl+eiSadRd+ShYvN+Pa8bZB88DVecELtl60y8Qqsb6B4Vii6lOJY/02tT/9O4wSXuiI44PJmlNmgA01eQ+/C7XmOCLGG//Q6PMO3ZELNXPg+RrrH7N4ZnvhuzCo7BcTzxwjhIWqCgKSNe5LPglhKzHbr1qUVO1SCl+4xaaNhw61jnmloty492+tzJKPVVrmP/5Lr6zEX2hocNMC18EKIGO7wUcx8/C5IriWEBioqkFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=a27E56q0pFGuCYuL3b2T1ysBahWQneZjOFnQAlEJpeM=; b=xSQ9MAHaODbVJ6DeF3/Ke559GoHT7Z8nboU6y0F1EhvS3aa+lgMiNp8uW4u+HGr1bEna4S6aGGbRrPC+E6jaJuM9sBWsVzCCJ3K08ZnVVXptmlbbEtzVe/kA7kd3EgfxCmyKXuVVJG4UwojGk9vZePfdaLP2ucBOnWrPLRSB+XVqEcK++KKd4QN+cIjNfmHucBMdl1Rfypzl7mrDIucYygtwM3ComrenAp6cym08QE0oF+at074ne76Bgoei4fOMvS4Kfbc28W+aGpScIh2xiZfcMMuG9ZnSmlBSH/ulhTJGLMnUXJNZY4z1BNnIb6cOkvgBV+My3CInWBhmYzMt8A== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=a27E56q0pFGuCYuL3b2T1ysBahWQneZjOFnQAlEJpeM=; b=ON8G1GHDfnJusP0EmQ8ieTefVhcESyTiddF22nrI8OZBx+OUhuMnwN5UArIDBSojCRXY9dlEFxJJKdrV79cp2l5V1VBilZgC3GNps8yMoglQFCHp2WMImOCYqBMIfoIxLYKaJrFlaxyFyhC3a2pvkf9mWuQ1930WkeY2CjRMinECqM2EnCupVqs6fwG2K1zzQmD7loDSrH9kouyFl10lhFEZWs5ElO96AjgazyyEiPxVwT/sqHzZn8+n/BRr/zk7vhFiohOLGyRuJrjGQcaSodUvtfXyuReZ9ecNrAs/Vd1ZMbDNVd4dgbnf67cRO8i7qLWjtM06MZUCqfrKMuljyQ== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:13 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:13 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 25/43] wifi: nxpwifi: add scan.c Date: Fri, 9 Aug 2024 17:45:15 +0800 Message-Id: <20240809094533.1660-26-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 8389a0f4-b238-429f-b4a6-08dcb8583ed7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?+dJ2YGLQpQAfbHbnJjTRqYXemx/FBOAKLQu12eQS7kvRAtHb6u7e70pYMjuP?= =?us-ascii?Q?mL04glFtP2zygttef9xOMI3GCyh17N4m8NcXsNQbJIBKgztTVYoLOd3kWN6f?= =?us-ascii?Q?t8C+N/rPV6zAPPviV9D+XxxqvyvGlTeenLwLhIc8HMWcK+39b/Sw/VMuKzNW?= =?us-ascii?Q?7Ri3y/YurUeh8csbyfMFO1/3zFQNiQ5U3731HpnsnSmd9aP7Dxh3bHSxZpd9?= =?us-ascii?Q?8Le/WeJaWHFqSgSNKJQh3dUpKs3oRi5MJ3zLbaEmoOeHt6yBY+XlQMTKWQPF?= =?us-ascii?Q?/0rBq094sh6CCkizEbF+qjnwQbQgQkRT5zXr7IM5t4ekVCLIUUmnE4b+OAx9?= =?us-ascii?Q?P8yia8NWOLPLzEv7LmIL3i6CVF733gGoXMXAv/kNmtw9RYOTuvhnU7TyvgRG?= =?us-ascii?Q?gWJVY/+NbRBVeNvQC7WAp+eMjwP5d1JjbzkGsdWfCfaJZbDdBNNR7Ga39oaL?= =?us-ascii?Q?x15XwQpqnyeltnpjlZLp+YwdnWVMo+kH3UsrzkouV3dAfVPhp8mlSt/uydAn?= =?us-ascii?Q?KjBUIloHkGDrH6RZMDhTmFBKBtLJkTisPW5+TXXegkt3yXMEkvtOTh61+dkm?= =?us-ascii?Q?/VnjvQTPYgAFMdy1MXNOaeHrSN98n96epdpzIHVth7N8tkhWFpAUXWMwIXYi?= =?us-ascii?Q?YeYgxe+AmH145GUfpCLy7yTbe5Bu/g/u9+jfi/aWeP0JjmHgC2aMHdHgHG5M?= =?us-ascii?Q?H/udS1fECaIKanggoVMaC/kve16DY5VE0MSZB8cg+tI9OjU3CfOPXLx82cvB?= =?us-ascii?Q?dkuF+S81RbKmGpAKSq6/GCKbm0dVKSjIu+1lcnDnMwPaEyL4NdRBmzjPV27L?= =?us-ascii?Q?6IHkFDO5SeWOehuRaniOonvXOwR0tt3BGXVqAf03ClTVa3hyxz9cLhfoTuxv?= =?us-ascii?Q?h93hiMRFP/pfy+H7RSW7ubbJOAD8toCCljAczPzMoMqr+rCELoPqUImNx509?= =?us-ascii?Q?kIQ2mB8KeEBsWpjftYhfvzpwH+iK3tk3Sw1t0VQ3XBk1t5enpSzPjoaT7iaf?= =?us-ascii?Q?EZ8PPkA/s8v5rKgdhbaR8w3WtRF222qPaCQ4/X3WI93VXVCn4GABFfb2cgu2?= =?us-ascii?Q?OW2mgYv4AbA89Uyi08swIn0MZZlrQ13nEoO/dkY3zDwG/fBW6H34aLkBoijX?= =?us-ascii?Q?qMS/djfiXSuOTpOkj4054UWN+JX7nmHORuTtmRLH/4MqKcnB86owTE2MVi+A?= =?us-ascii?Q?FNQL0NAgu76qoS9z5liyFjva8aH4VdaC3/JsJkoix+EHDR6arCcAOlxWDdaN?= =?us-ascii?Q?ZECenZsKerf6e8HrELBQvs8FUFykCH5H2KrBvxVTOzOUxKEAi3b8uMFjKZ2D?= =?us-ascii?Q?DRUQFruL93+4HsOj6KQojB/TQcNZYveKneVXHktH1G0s5A=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?GNWUUS40Sh7YiW8WcP6A0vUbqAIkBU37A/HRPzgm+jSNgrBz5jIf4sglI7UU?= =?us-ascii?Q?18culJENfnIQgIJ9vTPY5rrVwTDpAsFCJhBbFU5yfLSQciQMR6fUgSIW3uF4?= =?us-ascii?Q?9lG7GtgaHI0NMCXwRrjZNu7ss/HWr7Lb52200slKFVmivw1bEiz2c8hyfwwW?= =?us-ascii?Q?kXN76U14lw85kgzB3YGgrljLKMmc4h4F6UwVLPDHxy/4jfKXctFolDOlTux0?= =?us-ascii?Q?mQwquXSKJ7SidFrCip0SNXcCyGWumOmuUnwSJ/EWwg71um6gN5kWaM7NcBl7?= =?us-ascii?Q?hScZzEp+A3z72/TM1xnIAo5DiOYTe2hqrpC9gyIMR8NG7rHDz1t7z6LcMKEh?= =?us-ascii?Q?MY5qA9G7qJv+/UjyM9dIQU8gxQ/Vy4RFK/SkcO/x70U5syDlEoFjv7jF2cXS?= =?us-ascii?Q?iU7Vp/TDif5yQ6ovJ755W2+7uzD1hdO9paVJ1eBpPpgmEzZeTBLvbL4NcsDp?= =?us-ascii?Q?+KbHzrmdnwfOQ8qTCh2dVqgyulzsVg4i/hsVA7UTL1B9EvEf/bPi9vjshxNO?= =?us-ascii?Q?l5svL1kiakZTn7YWPBp0TJs7KiGUc7AfDZezrboG9ah8KqPzed9tNwTr56bX?= =?us-ascii?Q?HiqFnjbDv5rExP1Al285JoafbjjrpBpwCe5/eZtd/lbuuZMk2LgcdbHu72h9?= =?us-ascii?Q?wUhW1liacDrZ2nE9OcGwBIv/5b1XrjcajOTLt5uZ44fK2nlgD3jNM2CvnzqK?= =?us-ascii?Q?E0iL8OckmP+7ADKXXozidQnfwBKU1pgnWSCr7GYQr6B+cm+sVGXpVelOrbG0?= =?us-ascii?Q?LsCHRR4RO5lb2xkD5dfebl1o4XfFVTYBtG2YNBC9mOpA+DQKE4bUFRyktcaD?= =?us-ascii?Q?ny9SwnPw/pHnYekQPtSxWNgv7Vw3nFJwuNvS7Va9oDPoHUmwcSkWES3WqI7n?= =?us-ascii?Q?lrlxU6ZyahMPoZtNfJQsZyzyXEjnOkh9d5xGCtyrRn5/0M/5sYUe/wyslkLs?= =?us-ascii?Q?O+xmKibDSy7bXJC4bOXWjNs4O4VpdYWBSRGLgkPuk+1ZgcHcSmytVuPtIavt?= =?us-ascii?Q?J3puaVnBfhc2+Kyenn8EOZ5yTr1yc1+t8hfHOUsDDia3A5Xz8znQ+RLEGp3a?= =?us-ascii?Q?E+I3VxUneNFX4ncD9Zq2pR7w/TmB4HzIk+dfb28EmHprlqQsrxFI0g2OEE9C?= =?us-ascii?Q?mekvq26EKYJo9vz5wyqxBRkt9KBcjfoMvkS6enUNj+qG4Lfy+GRa7Nj1/qD/?= =?us-ascii?Q?QLDq4V6P6/gs/y8AXc8AP5feRBE9rxNxi0IJZmOUFqMAZaN2+KoVfQJSJoO0?= =?us-ascii?Q?TrnCuV0glOmo/yUWXKWLjhodwlNDmVvG88tQGbr6muX9zbs1HzH4V7Nrmgow?= =?us-ascii?Q?K/nQrX/1wIXcHavhAPxUTd0lov19/3mX74fSKa/45+AG9VF3oj9yWKnhAt5+?= =?us-ascii?Q?bSDubEAizK5RA3cGmZ7W+eIJZmdeZWFMBVG7ld4bla4vg/aC6KQPUx14vYct?= =?us-ascii?Q?nXJSUNWbvbUq6KIf81fdHkyrBA0ojhGVmwTNCjFV/NLLKj0PBjZGYBG7ugss?= =?us-ascii?Q?9w+rqaBobocoBjIIpvX3VLtQgVuVHA259ORrAxQvRlEWV2gHuJwxLSvCqraU?= =?us-ascii?Q?fyw6Di64yNe6cShcz3LKp4OFzd6uEvnPu6XtOuoNHCDOM4tlyvHTi/7eEhIb?= =?us-ascii?Q?CftQ27ZBPQkMmpM8DHUcnX5ntmL5aH3yO58rmKf5WaAk?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8389a0f4-b238-429f-b4a6-08dcb8583ed7 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:13.4552 (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: UJT+1e6ny997nQFCA9htrcKzUNkZiNEGg0w2ZvFh8bFJF+TNuPFAPBuM83t82ISq8FY9deSu420Fn5JpS2iEyg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/scan.c | 2806 +++++++++++++++++++++++ 1 file changed, 2806 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..47037f2c2fb6 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/scan.c @@ -0,0 +1,2806 @@ +// 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 "cfg.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->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 element *ie, u8 key) +{ + return (ie && ie->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 int +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 -EPERM; + } + + 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 -EINVAL; + } + } + 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 -EINVAL; + } + } + 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 -EINVAL; + } + + /* Mode doesn't match */ + return -EINVAL; +} + +/* 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 -EINVAL; + } + + /* 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 -EINVAL; + 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; + } + } + + return ret; +} + +/* 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; + 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 element); + + 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->cf_param_set, + cf_param_set, + sizeof(struct ieee_types_cf_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)) + 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 ieee80211_wmm_param_ie) || + 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 element *)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 element *)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 element)); + bss_entry->ht_cap_offset =3D (u16)(current_ptr + + sizeof(struct element) - + bss_entry->beacon_buf); + break; + case WLAN_EID_HT_OPERATION: + bss_entry->bcn_ht_oper =3D + (struct ieee80211_ht_operation *)(current_ptr + + sizeof(struct element)); + bss_entry->ht_info_offset =3D (u16)(current_ptr + + sizeof(struct element) - + 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 element)); + 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 element)); + 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 -EPERM; + } + + 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); + nxpwifi_queue_work(adapter, &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 0; + + if (!bss_desc) + return -EINVAL; + + 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 ret; +} + +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 ret; +} + +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 -EINVAL; + } + + /* 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 -EINVAL; + } + + 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 element)) { + u8 element_id, element_len; + + element_id =3D *current_ptr; + element_len =3D *(current_ptr + 1); + if (curr_bcn_bytes < element_len + + sizeof(struct element)) { + 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 element)); + break; + } + + current_ptr +=3D element_len + sizeof(struct element); + curr_bcn_bytes -=3D element_len + + sizeof(struct element); + } + + 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; +} + +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 -EINVAL; + 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; + int ret; + + 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; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_CONFIG, + HOST_ACT_GEN_SET, 0, bgscan_cfg, true); + if (!ret) + priv->sched_scanning =3D false; + + kfree(bgscan_cfg); + return ret; +} + +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 -EINVAL; + 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 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 element *)(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 Sat Feb 7 11:38:14 2026 Received: from DU2PR03CU002.outbound.protection.outlook.com (mail-northeuropeazon11012065.outbound.protection.outlook.com [52.101.66.65]) (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 2A08419925A; Fri, 9 Aug 2024 09:47:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.66.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196851; cv=fail; b=kWzc0hL9VXBOBJypk3FOOuR67+4WYFWVGueSlCV3VY9jylospMLlXVtBhaJ69UPXs/hJXGKwl2qiNLHpx5a3Ysu1FYn0GDCR4ZVKbU++ElQrojQtS8h+JuvxD3EW9MzMyML3LCm7Wk9cuD/ynozyo35FtO+PoI0l9+EhXiYBmlo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196851; c=relaxed/simple; bh=nq9Sc81f10bkSfDZ58iCByMCvtTlYprErYi1ww86wE8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=MElrpND7nmANHbwA/dQ66oo8MZmc4vhJyTI8ye2yPIRpmSMY3ltEU4FQD9Xl+vZl7X8IdpXeGwH1VNHnI0zc/6Y3t3nbJ/vHIOMugOS07W+Ca5A5zNM+AAQtCQP9q2LYfo9OA6YJXEjp2uB0OTYzqjH2LvKjqkfc1Ms8H7jIuIE= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=mljDJDls; arc=fail smtp.client-ip=52.101.66.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="mljDJDls" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=LL4+RmJYMkpLqQrcc38XnTy8LZB4kh2PnFHt4ocsmM8SUvldax6S+fHrzaT5G+qkXYkrEFTq4j3PbeplAfF3I9CUCFUCMKHbFH9HVFgfO/fwOJ2tnR75OMEKzFpl5TwAHW0v8lM7go+Xp/hBK/4EDJHnu/A0eWrRwu3QTZVgDtsc+S6ncUhfRb8MhbQRDbzy56uWLmAkHxGtghg5pgZcCTz3UsqJxFEvaL0QpCSEH/BFVG3EcL4RQRo5IZrg9p9nPaPakRBw31Nqyt9FvBmfombqwNNtSquLeXBPI6wM+uus9C8TqxOZmfbbTmmm/XjaQ831GalSW1bevs8QH7vbWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=nw3MO4WDySgZxM8eqJR4mSnIZaDWuxgOFKERpZo1CMQ=; b=Vle2Q76/NrP1vJ5UgKbOMW/tEEHpLyXH1zNuh04cHVI3Nl5PVHr172IxFtMhPhgp03eHjuIR2nelO9wGpCyWCsQUgDhAgsvgqixyqh8WJZAU09WJi5cmnlgX9bfO2CQrQUraNu03rmSLTyB4Kft6d1EXabnjzhlgnAtDc6d6vozdJU7+qnSMGlltylvWPp2wKdFp3IBlvrFjquVBa7Hk/6xiUamar4Nf1626Bg29dc2yOLAwHh3vx+pBE6mvJmuMLPhlcK8zskQ37l3tC1AXB1GIkWhngAd2t+tEdvWPz/D5OOjYGJPU/p6r7HlIqR9RSKePod5k+uuhULHiUj8Nug== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=nw3MO4WDySgZxM8eqJR4mSnIZaDWuxgOFKERpZo1CMQ=; b=mljDJDlsGBMGC8Oy81UGNPuEy/8Ox7xdvIaaXndbNZqG9LdT0T+9zU7/LOEaN55YeWifuv/77UJQICmJnrcPKo5HXrV1vBZJYTv2Tz+IEkC8lJqz17xqcg3VVpoLG6gOOvGmZtSvNhBtv+KHHQX+UBhD5ZfeJrL2k5umb+RZCrsKJrh2kGnO2N0XHXWfXRvoYKB1pAyxMX0SPxVJvPl1RY6ne/cBMWs1WS7o2GYV+CxhPQFgVCzA5KbaTbwWR+m4UXoBSWs5Ff886kQQmO3stQVzyNZkw73zU/1WPkPyjUYJ5JRHS1pKP7SkIWQMy+e1GS42lxSkO43U9OAszzgPDA== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:16 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:16 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 26/43] wifi: nxpwifi: add sdio.c Date: Fri, 9 Aug 2024 17:45:16 +0800 Message-Id: <20240809094533.1660-27-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 2da3a220-56f8-40e5-750d-08dcb85840df X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?hn5oThla6Fhqvfqvsez6jS0Ny6tEhn3PLcGs2URo23vR6HjRICdgAGBxf/6Y?= =?us-ascii?Q?aTcn5r3IQGVjixzlZsF9CyaYz9FL5Z8+qtXvMHLMLq5uGiY4tfdbxo3jXEpT?= =?us-ascii?Q?0wsyxUSX61+8wHJQSYP5ZjGubwcAkFmFrW1Hvw3UopAyeFntswxSnsp1CJQN?= =?us-ascii?Q?3q9L3In0SxqKqQodKPxNn9TMYMiV+1fakeccbgFO3H9JArTAmeV0o+zDwXyr?= =?us-ascii?Q?FGzB66ZPuiLV9ssiLVZ3qAf8YBAWyita3+5B+ePBJigWOu0wlboN6+k0BAUR?= =?us-ascii?Q?e9akfzTxZPWXiGaXb5W6QvzhxSpi63bpOhV+nHQr2vbvFhcWUdlhGArUdXFL?= =?us-ascii?Q?ig8JO7OF81s+XxwMHK2I/Que26yBeUf0h09OjqoKtZPp0WBQIYCMS1Fbdrp4?= =?us-ascii?Q?lvV5ofva4lC0c9G5JeZZj8iJH9d0h50WGlO1DzeWQnGGRz5ICUA16IGijnpn?= =?us-ascii?Q?eNigus3p8Jeoa3C6s/BEx6CoxWnGg5dBkRAFZUXeP7uKnJ0FpqdngqLBL5Oz?= =?us-ascii?Q?1kby4pZaSSe0FCiIXZiE5LJ+ootPKjJW89WACRZfxZJVqHnkuiiTYGnOt4Kr?= =?us-ascii?Q?JikguOmyt6Y3vlpf3Oz1qvc5OSqZowmC9epL0KUKTureiv942Ip867RBDYGz?= =?us-ascii?Q?vtbVwHpPJMjHJzE56d+8Lje2rO9HZs3qgn8T8PhHtL6y4uq3aHRQetYqXMBi?= =?us-ascii?Q?6nqU7Foo1EC0lK3s4734TM/mF14mz1IsjAmMDcBms31fNW+D9mJV+X85Awj8?= =?us-ascii?Q?hsyXTBqS4bZ/3KGmPQ5b1Lu7KqKo3CFE7ve5ciGKMkxrpwkCxAelS6icTYpk?= =?us-ascii?Q?DkblS6ZzOH2W/Pr/3AyFt2e7II0nxcT6UGCdwCg1UHkxl6kprVckcOUnyQNl?= =?us-ascii?Q?f3hhnG3Ux7tEDjZUDRV1vG6JtXCdicKAlhP3O/i23wccwp/Pe04mB5hwd1kt?= =?us-ascii?Q?PuFp1uVO5xJdS2bAQWmto09qlAQaRkU7RDL+3S6QZCMfXIcziQas1HgUcwiX?= =?us-ascii?Q?nnH4bAYleKcHZYtb9Anll0MS+CNwB78iS9kYNNBLnO0aFmDQTOfeF9YJZQ00?= =?us-ascii?Q?YS+LHs5DfbK5P8ICTqgRso8/QwSdBH8eWrwIrNOVYk3Fj3uI9DPvxpc1le5I?= =?us-ascii?Q?C2VQe803XBjZnnPDsd6ivjt1WkOsRjSLMlrfbt570IFrXBuzsm4XvK0p8GHz?= =?us-ascii?Q?w/cFIahgEgbT42CV/a0lxyuM1Wdge8ulfrv32m8s3XXAJNjBDTPwbb6PMN7N?= =?us-ascii?Q?r08DHsjbWX5DOuApil+hbhmIGCazkXeRVwIzH8ob0wUHPrGW42AEUfR1EEJY?= =?us-ascii?Q?WWcfCLZMtxU7MJEa3mhLbKn8xArguJD3YM7u+4EVo2qWMw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?vJED5H/nYq2ZJ+eto8tUKIDIrxX0EZ/E7pG6ti7uz5OjdosiL/15tvzbgA/9?= =?us-ascii?Q?V5b+1t0ntudySIHm1spiSj9HACG/eL3H74PyzKg/8ScAyiqKh0+MN4YU3w1n?= =?us-ascii?Q?VTGz8j59z+INZ8Ymkrj19pJ2/w9qNIDVt/FEyw1rmV7UzgC/FpCH53HCNCG0?= =?us-ascii?Q?OVrHle0RgA3tjL4/u1FZMiIW9ff8PH7Xdk0kz0jb1pas4q3/7MVut5kiXhwG?= =?us-ascii?Q?aXj9KQOILe2A3yQE5H+n4l4mGp5tu9XdWQrgWeMRqsUuDCB3TTVj7tJVCoEH?= =?us-ascii?Q?k3Gd91pBIXN9NWu/IVOHjz/OsCVshvLWa9l/yIFlEhvz078/1o1PR+HFbroR?= =?us-ascii?Q?Cu9Q5HjuaqykWcirzNuQVz7APKPjNvqY0fwMC3odjsaswEHLgHRVrLJBkodN?= =?us-ascii?Q?jtZDJwXZVHnCQHvP5/dWEKCNgyADDMrk7WwqCwYp0fORDHV9smVoWvcDsuLB?= =?us-ascii?Q?Omlw5GRW9pNdvBpy+OcNCx+8mbtgSmFGhwUASFRQvmwUAA7vBq289PKYeuCe?= =?us-ascii?Q?1aXoz2iDcVdwDJOvG/+NiorVXV+4tImyerFyf9Us+GZARZBYrFkTOK1mZyXI?= =?us-ascii?Q?tVdUJ8eUoN29/qYfgPw/BOrfkPwQGBIaQnmF1Xmj08Kk09e/sgv+Chq980au?= =?us-ascii?Q?wn/PDI+PeFNqBD2IHY3DCyLYTeWGDi24HtIW7myyViPeEVRutbAPChizzRVs?= =?us-ascii?Q?kvmXpcHzOFs3Uv7kSMsPx3a5RiMM0aBJrhxlX6zptbSQZ7HydbPgZjF0J8xL?= =?us-ascii?Q?fSG8LEyLnqjSI/QN0N8DvF8I/gq5tGWPtrqUJa1dW6vi0OJRKIL0g4uFhC/N?= =?us-ascii?Q?Ns6MZF6y/UuJr+gzqFH/8MyWXoka68/+pFh+WzmNYhTPhX5digLqjat+7h7d?= =?us-ascii?Q?i/pI1kHckQRkSeogadiZAD4pHIBW9anBgMzBPjYlvu4TtQmeO2dJ2HKS6S8Y?= =?us-ascii?Q?8iPQ3Gmxq/EEN+R27dB0nqSkQO0Jg7PDJb0gBh06fdNYNliPa983UF/yz3r2?= =?us-ascii?Q?4Kzf1dtVIzwNtHFjSbvxZyHvpWMbY89gSFK9DWIsSxyVF/1rwse62MGbbGF+?= =?us-ascii?Q?+KMPkcTJbg1vRAOMtaLL/PFojTH1gXfA9yr88VcypzJvQ6GeILbSniwVrCGn?= =?us-ascii?Q?dfE3SLhI4p+GKz0uFKX6T4KDa99M4zPe0PSzCnGUrZ7LqQMlZXMfqt0QRkpf?= =?us-ascii?Q?7BTm8NxBPPGlPVAwwsL+7K92OWMOiiFB2wKWNRLchUC49cf4gfyj0kpgVuBk?= =?us-ascii?Q?tGgH8Q178kPnyN2iiUQv+avMzixmzoSxsdYeMwl4UmJIsX6h/V/5jPoYaZkD?= =?us-ascii?Q?dDjYTNjaALmu+TkaN8sZeKYgQ4TeERIh4C7xF+P1BDFlNOqf22pIKhH2puyc?= =?us-ascii?Q?eoDqWK6+ss2+FDc0YP755JiEVNojbLudEUhcBd4V6+MYd7ixh5qGbhgXtyAT?= =?us-ascii?Q?ciW3vkVS/BGDUTmU32eNzTw+wMGfqwRA+qKVUB93MvWqPtRm94wBGPiA613c?= =?us-ascii?Q?TJDHkHbbBrxurjRpswZciAmxdfjmgJoElTrKAsSDHlpOHDszhI4KtQf6RF+C?= =?us-ascii?Q?77ANHiv0pinOd7CKAeeeQB3SIYafKvecEHYgOE30UWO63ciY3DdAtKpcVhYb?= =?us-ascii?Q?gRHroy7bRXe3c6b+sHk6SRmU2XGPJ7StrCOJLvVmISiQ?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2da3a220-56f8-40e5-750d-08dcb85840df X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:16.8139 (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: SsAn9NIYv6FEtY5SmHJ+gdFS4oLFofudIntHHyHb5wqexs2ruchOx+kYNNjl6toxZeYp9wiwuoINJzOl0R7sNw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/sdio.c | 2648 +++++++++++++++++++++++ 1 file changed, 2648 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..9bc6338c95ec --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sdio.c @@ -0,0 +1,2648 @@ +// 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 "cfg.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 { + { .compatible =3D "nxp,iw61x" }, + { } +}; + +/* 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; + + 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; + 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 -EPERM; + } + + 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; + int ret; + + ret =3D nxpwifi_read_reg(adapter, reg->status_reg_0, &fws0); + if (ret) + return ret; + + ret =3D nxpwifi_read_reg(adapter, reg->status_reg_1, &fws1); + if (ret) + return ret; + + *dat =3D (u16)((fws1 << 8) | fws0); + return ret; +} + +/* 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 -EPERM; + } + + 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; + u8 winner =3D 0; + struct sdio_mmc_card *card =3D adapter->card; + + ret =3D nxpwifi_read_reg(adapter, card->reg->status_reg_0, &winner); + if (ret) + return ret; + + 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 -EPERM; + } + + 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)) + nxpwifi_queue_work(card->adapter, &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; + int ret; + + adapter->ioport =3D MEM_PORT; + + /* enable sdio new mode */ + ret =3D nxpwifi_read_reg(adapter, card->reg->card_cfg_2_1_reg, ®); + if (ret) + return ret; + ret =3D nxpwifi_write_reg(adapter, card->reg->card_cfg_2_1_reg, + reg | CMD53_NEW_MODE); + if (ret) + return ret; + + /* Configure cmd port and enable reading rx length from the register */ + ret =3D nxpwifi_read_reg(adapter, card->reg->cmd_cfg_0, ®); + if (ret) + return ret; + ret =3D nxpwifi_write_reg(adapter, card->reg->cmd_cfg_0, + reg | CMD_PORT_RD_LEN_EN); + if (ret) + return ret; + + /* Enable Dnld/Upld ready auto reset for cmd port after cmd53 is + * completed + */ + ret =3D nxpwifi_read_reg(adapter, card->reg->cmd_cfg_1, ®); + if (ret) + return ret; + ret =3D nxpwifi_write_reg(adapter, card->reg->cmd_cfg_1, + reg | CMD_PORT_AUTO_EN); + + return ret; +} + +/* 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; + int ret; + + ret =3D nxpwifi_init_sdio_new_mode(adapter); + if (ret) + return ret; + + nxpwifi_dbg(adapter, INFO, + "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); + + /* Set Host interrupt reset to read to clear */ + ret =3D nxpwifi_read_reg(adapter, card->reg->host_int_rsr_reg, ®); + if (ret) + return ret; + ret =3D nxpwifi_write_reg(adapter, card->reg->host_int_rsr_reg, + reg | card->reg->sdio_int_mask); + if (ret) + return ret; + + /* Dnld/Upld ready set to auto reset */ + ret =3D nxpwifi_read_reg(adapter, card->reg->card_misc_cfg_reg, ®); + if (ret) + return ret; + ret =3D nxpwifi_write_reg(adapter, card->reg->card_misc_cfg_reg, + reg | AUTO_RE_ENABLE_INT); + + return ret; +} + +/* 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"); + + if (i > MAX_WRITE_IOMEM_RETRY) + return ret; + } + } while (ret); + + 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 -EINVAL; + + if (!(card->mp_rd_bitmap & (1 << card->curr_rd_port))) + return -EINVAL; + + /* 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; + int ret; + + for (tries =3D 0; tries < MAX_POLL_TRIES; tries++) { + ret =3D nxpwifi_read_reg(adapter, card->reg->poll_reg, &cs); + if (ret) + 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 ret; +} + +/* 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) { + 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 done; + } + + /* 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); + } + +done: + 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 -EINVAL; + } + + 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 ret; + } + + 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 -EINVAL; + } + + *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 -EINVAL; + } + + 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 -EINVAL; + 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 -EIO; + 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"); + + 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 void 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; + skb_queue_tail(&adapter->rx_data_q, skb); + adapter->data_received =3D true; + tasklet_schedule(&adapter->rx_task); + break; + + case NXPWIFI_TYPE_DATA: + nxpwifi_dbg(adapter, DATA, + "info: --- Rx: Data packet ---\n"); + skb_queue_tail(&adapter->rx_data_q, skb); + adapter->data_received =3D true; + tasklet_schedule(&adapter->rx_task); + 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; + } +} + +/* 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; + int ret =3D 0; + + 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; + + ret =3D nxpwifi_read_data_sync(adapter, card->mpa_rx.buf, + card->mpa_rx.buf_len, mport, 1); + if (ret) + 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); + ret =3D nxpwifi_sdio_card_to_host(adapter, &pkt_type, + card->mpa_rx.buf, + rx_len, + adapter->ioport + port); + if (ret) + goto error; + return 0; + } + + skb_put(skb, rx_len); + + ret =3D nxpwifi_sdio_card_to_host(adapter, &pkt_type, + skb->data, skb->len, + adapter->ioport + port); + if (ret) + 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 ret; +} + +/* 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; + + if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS && adapter->cmd_sent) + adapter->cmd_sent =3D false; + + 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 -EINVAL; + 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 -ENOMEM; + + skb_put(skb, rx_len); + + ret =3D nxpwifi_sdio_card_to_host(adapter, &pkt_type, skb->data, + skb->len, adapter->ioport | + CMD_PORT_SLCT); + if (ret) { + 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 -EINVAL; + } + + rx_len =3D (u16)(rx_blocks * NXPWIFI_SDIO_BLOCK_SIZE); + nxpwifi_dbg(adapter, INFO, "info: rx_len =3D %d\n", + rx_len); + + ret =3D nxpwifi_sdio_card_to_host_mp_aggr(adapter, rx_len, + port); + if (ret) { + 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 ret; +} + +/* 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; + + 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 || + type =3D=3D NXPWIFI_TYPE_VDLL) + 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 -ENOMEM; + 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 -ENOMEM; + 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 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 ret; +} + +/* 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 -EPERM, 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 -EPERM; + goto done; + } + } + usleep_range(100, 200); + } + + entry->mem_ptr =3D vmalloc(0xf0000 + 1); + if (!entry->mem_ptr) { + ret =3D -ENOMEM; + 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)) + nxpwifi_queue_work(adapter, &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)) + nxpwifi_queue_work(adapter, &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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013017.outbound.protection.outlook.com [52.101.67.17]) (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 BD6141993B8; Fri, 9 Aug 2024 09:47:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.17 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196856; cv=fail; b=ELGHwiERkqO/kKXo948f+oqpmPYrlsOXRJMSDrXBME8k3/ToMSrKdrmA0orM5ztkPneDntT7z1nFNMkGcirt70oneLxyzrL6zEYP+iidJ/Nt4IW/n9Y8FvynFknjF4yRBWAFyB47CCqx5gk4zXfXKT4DD4y5i9AMLlaPbVDM32A= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196856; c=relaxed/simple; bh=DCwTnVB3QlB/eS0QSPmcBDEI3KgoxehEPKS7GWgAOuI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=n1y6IFquh7m9GnuD2IBOzOV7/D4ko1vOPgSghDHOpiaA+GNktD2yf+bOxvvB9T+c1h+G7WxthjK9iYqZkHPWP09jPvYzg7kONt8aEwjdSrctDsjM/zizTf3khcMfUbW8OiwiVwjTR9ihk+y1g/zF3yb8Osnx3QbciyuFW5YnF78= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=RALnBJII; arc=fail smtp.client-ip=52.101.67.17 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="RALnBJII" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=cYrBsRRbz3J02lbrCJtKxPMphED6gK/yOFmp1e1+bU+yL3ZsbgcXqggj1SnboV8MxihdxGEjR0Qb6othv4s4jwYYtf9t0bRVkAqrVk/ij/2W2WaIO61DYwJT8DImZGx0kGrKwpvPWCRuY22oieR6KI8liRkHhLJxA/mBh2D6jV/4is26usJD/h7qvzQVsLW8gEmGXHSBVDsFCdYbr3gtMSIIDJYf1aogOYVqgQh0pkqWZsp6a8Azqw/irpjlvSlyZ1jJr/WbaAkL3G8j52l1zaAatuHqGnjB2bUITDZrqk5/eM+jZwfJnvY8ERj0eeQDqUECXOX3Yur+BexrofYOxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=mazPM+XPfTLPhbUwAP6PEzMSUhyWb3BuoHixzO33xNI=; b=jzR6gJiCrHJYD6DuJe3UQag53AMo1Rv/ETA3PpoQw9LMt6xGnaYxlNiZmrUKjOw+6Wt27NSbuPJ6b/nL9tAbzqJgLw6wr9aD6nQrUIC2dD1pUVxZUJizDd2tIaRa1HzZAtsgH+9n2a8cJOCDAbgNjab12KN8aZke6c9vo3DAfAVIs8XtPT/1rHZyr5EjudBPj+UJt7sGwAgFGEE8aVazp2eGp0nzh2zfEv6ONDbFmYutF62kxuSrIKFhSTlJdkmsWonZEjHHl4qKVNhEzfOt33gcAEnz/MrUCIXynjygtsly+G+ziy4RyEL8Nd+HjkoJF/56fEqx7FzOUpPWDcHZjQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=mazPM+XPfTLPhbUwAP6PEzMSUhyWb3BuoHixzO33xNI=; b=RALnBJIIOCHgreMFuMOxHEpg+RP6G8mD8fQRTwTofodTz5CORT1Q6mWpWh9Zrr6dV2S0McSY9JJa+5073FY+eseY0v8fzt5YAlpC3TRciPfufaLFX59Y1gOaycGSyO03H1WIxfcfaZ5dzj12dpgf3jHLuk2maM6eFu2/7FDc+EhaVbEHwDcwjLNzpDWTHTlm4dSw/J8VYJcUZv6c5jrcZiru3brjMp6GKTJj1odhHM1c3hSHjUMyJn1/6kGnvGSU9uU/f9+MQA/xnoxgXw7KCMr9Y5B+0MbB+dU/LB9x1QKkLuFDiJ3utu00ewplSAkyb1DPoY6b9JNsF+/TJ23yZA== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:20 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:20 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 27/43] wifi: nxpwifi: add sdio.h Date: Fri, 9 Aug 2024 17:45:17 +0800 Message-Id: <20240809094533.1660-28-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: a7e7692b-fc04-499f-e8bf-08dcb85842eb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?QTWoNaKQnHL2hI4GxUIQ5yVI1CcO/e84SeUgAZv9syxR3I95snrjvFVxomoF?= =?us-ascii?Q?VArYMrxvGkKEl7cWA90mL/fY5ok1seolJGYpUtoPTYjLpSqjJFL6gU9qSlzd?= =?us-ascii?Q?VET7cRv6+7ghI+L8K3xM0NEq4BdJcN5M9HRbHpOtCuzxFcj3Bu5JZoMEsztK?= =?us-ascii?Q?Abn6YoxyNhHuYIEyeypjKzdJaelJBjkEgw++YN434f8PPVK0PaEznxGkFM9X?= =?us-ascii?Q?zCVpUiGc3m5YqRzxhAIrRMH8+jJGFwfocdRDHVGVKkvQDPbx/BGwdhAk0u38?= =?us-ascii?Q?+RAEsqmMKPWBvo9dEM3rJFUgBRPp7dFA2F+EzBranIaYTUVdqQDh2QZKFhDh?= =?us-ascii?Q?rKM05ss3jkzOX25jQMszO9szSp/5C+BwmGBh9O7hWST8k+/owtjf0YsDxq/a?= =?us-ascii?Q?7Rb5Q0gBtPkXiwVeNmQDrJr0Fw3HpgGTvSTEu8WsyOTPsKrVt/YVb+qmy+QZ?= =?us-ascii?Q?NMqBidHXkjsTnvalb3nCJE7+FwScr4pNkFPcXRE9h5sC80DNrKg1zPPCU9jX?= =?us-ascii?Q?L5yI/QpbBgM83dtHlVMZMymazMMaiuRySAuHFpLmSzDjO6bPeQyOpNiHMVd+?= =?us-ascii?Q?vlPhQddAhb2xFyM5xCJsMp3PksIPCLVIQCmfHx58YGmqCSGT4FT872Sz9t6w?= =?us-ascii?Q?uTj9i39ZZ5TT0fUwCvFfTjUBvvnd3pRb+VrzH2PEVyb8S9vN4t1CD9xeDF8c?= =?us-ascii?Q?6pogV1eTiRe0uvR4G6LFUAnVl9LcicTexQFnkWTbyW05RKN+p6JFiF1GnPxt?= =?us-ascii?Q?btUsB1i3gKkexoF/dJjfoNw5jYWKPkEwQAzOzluBI89TKDgd0vB0HRmm02xf?= =?us-ascii?Q?spvrr1nQu61Defb1aca4aLCXGxG84zUTv5fKG//WLwNwI8KpsZKOqllOxC/q?= =?us-ascii?Q?QgWmO8AfzBGWFnY4F3WaaOhZp4aBHERW6ZxzGcFWkPU0K/fta5eW6w/GQW3Z?= =?us-ascii?Q?q6qF6NcQNEpgLBkB9n0UpKZvI2a64KJqT/7YgrZgozf44XKqRkApo+b+SpNf?= =?us-ascii?Q?Vd/vqB84iYw3Vxem++2QYf1LOubGzQwFnxyUCCLZOWL9/2nFDRiTD4kcL/5h?= =?us-ascii?Q?KvvpCcoJR2RerfOskafGmiQuXg2PUtr0E+uUTjJ6ZCLNwMOQr+M4pqAM/Jcu?= =?us-ascii?Q?c30d5GNnwtlQAWVgsbGqtzNQzEMvh55mGH15yt5073vn71tvi8Km76sQOdVH?= =?us-ascii?Q?qi/hW/QXGxre6YdZ2QhuK3+ghG8fXSY4gjGaE2IeV83s279CtgJMpHGMZymp?= =?us-ascii?Q?OMUEQLD+KcSSn3I/l/beAVO3k8C0DFDru0tM64Ug+45gMfL10DiomwhT+aRV?= =?us-ascii?Q?eOeQjpDQ7BVshfrRv7IYTw0Z/1O1wvfQ3s9iW/CPGzt+RA=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?DIdBi7b/uKINwYBjCeeZFPqq9FCnhVZU9Nt+1ZEWFzcPciZHT2Qcj4ohQTQS?= =?us-ascii?Q?x+pYYfBOAI41L6j7iuoO4cCaWapqbgGSNXsjU5hbItDdMREnt2Tbc75tXoEQ?= =?us-ascii?Q?0SfFpY5Gd6DokXQgfcNoHSzmAzSC7r6XKOA3jQPBP6piqGWu5mltR8f05L1I?= =?us-ascii?Q?XDTm1HkdkFc/AzhQVDQkM4QNqPrHtLY4V5lC93DaHYa6exDIs41hN6bwTAV+?= =?us-ascii?Q?IjH2gtXQo0cwUXjMospfrJpGhZU57e2/DnPeeG7TtzgPEG4tl2byIRH4MkP2?= =?us-ascii?Q?wlwILCqBejDsxFekbldS9tyyqZt/yS1+2cLhdbun79eiG0f7Ffa3wnEvE+QR?= =?us-ascii?Q?S+YOeFwsXz6OBrvIdq8Dtjw5WRX1UL1X3TBo4c1NikwK2AyJoVGhmp3A6p9J?= =?us-ascii?Q?uhi2ENeNYW2xXgCH7obZzcidlFjCIbWJ2G8an3Gn9nphFHy2Las2ZDMotGOi?= =?us-ascii?Q?He2F2qKg3eAUHpLIhG47vjr4IojCZ601f14wwdszfwBydT7M6XmLHd1jduFw?= =?us-ascii?Q?avBFGa26lChmGq0njsnq9jhjvWKmvYcQrhF4O5Lr4wlcwNn2lq2ke295MOw/?= =?us-ascii?Q?dgM+MGI7tONrbLpm0t9OpsKzZ8e5m/QvCtanzg6xUNiCdIsmtisqayfYAUGh?= =?us-ascii?Q?vKuzDAa7wUxI+DgKEcq8XcYkRK85kHZ+LN6hdqGtXdBQL1ubpw4De0RZCmw+?= =?us-ascii?Q?eJeVkweW/IXuViqrHZCMVwsbWbztOAfZkY4nEtDZ/61aPn/ftyDqTBcZvVts?= =?us-ascii?Q?YeM0rvr7WrpNtuy9gQ4kwY4Gky7tBXrKxCi4fXFbNwfQp5T4KNHwusALe8S8?= =?us-ascii?Q?YQAP73VKh9i+C0fLBKQdpcOTddW5XAHe1RmapRxQWdpaDmoZQJwj+BCHhDs/?= =?us-ascii?Q?hEpc1gM5snFw/AYj76SHu32JMro74Ax8VSGxUd78oE/yHWfN3urrJjO/pfDC?= =?us-ascii?Q?ZxBNdwz6i3l66SaMj3d6gX47IrgriED+aU+Ec45YBqh/d3auoWFhW9YCqX2F?= =?us-ascii?Q?nu687YKLQoNlFrGgjgM+7rwuvv2Y7Xpr4MExYwUYrcaFb14tZo/y1p5un/Yt?= =?us-ascii?Q?w7X49+yHvjuJd65KXozfngir+NGiy+Y39qEMdRen6C8Lg8gVFLOdvKgF/yqD?= =?us-ascii?Q?dGQIRRP4/UxySt5J/WdWVDQDyrCCJNaXoBkUmjQun0g4L4ZYwCMwOVhVWESK?= =?us-ascii?Q?s56Y6cwk9FIX2bjOY0KGfsOswVah5eHUDDDi+xmagcM2yb65Io0ZDnsJ2zWE?= =?us-ascii?Q?wqB2Tef3Z+RiqYhhVUHHH3jC0qU8Q4nLhvsWhR3y+0VK5RHnMZggo5tBNpK1?= =?us-ascii?Q?Zm92GkIXX7KsPzEi5iURjyUg7z0IhQCBW/dvGGb2bxQOkQitCP8ridDz0wDY?= =?us-ascii?Q?246h/MiChlt9WLz8v7ZWjijvTxcSsYQyYHwm8duydtNmsSVGSwu8Ggg1wPAK?= =?us-ascii?Q?QYj1zTlEHEAaN+M2DI5kXrT8tAaBJYgLa1idbLzx/MpvW+cIc97UGba1BmOZ?= =?us-ascii?Q?NmfCT0SkCknthNAohvQPr8KE6LQ8iW4EUL1ZK7DLUMI4I0J+KjMI+OUN5yGq?= =?us-ascii?Q?DNzeKYyhpLI/g00KGurJSFDqlp3SQvxa04oxWgdrDHJ7BqWh4wwuNkpJH9iG?= =?us-ascii?Q?JQOP2xgwTYf+SGRsnnz2tq6OQ7ZAr4kAAz/5dTVR3f6g?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: a7e7692b-fc04-499f-e8bf-08dcb85842eb X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:20.2537 (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: Pdb3IS9uvLevAoZBCT1rNU2ysAi/MtBWETQ9XbnCHOw8Qgurvpwfa9p5ueJI0NH+dahjFC4VjN4aLmzyGnE/Ag== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- 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 Sat Feb 7 11:38:14 2026 Received: from DB3PR0202CU003.outbound.protection.outlook.com (mail-northeuropeazon11011015.outbound.protection.outlook.com [52.101.65.15]) (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 D3E3019925B; Fri, 9 Aug 2024 09:47:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.65.15 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196853; cv=fail; b=uwVaym3lQA9qYsUirK3RjMrmtfCwztIpO9kgHbMycRr6OZb6gByLHzAebiDWxT4e4qTfwKFjXniQpjXMLNchbZGnUTYLCSnA4VnI3evATIkVZ3kDzg3xQ5sq83HIZpYJG1vqqGeJ3W6sRXIL86BqAagUCAn1h0H2txLfFgCJgPQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196853; c=relaxed/simple; bh=iiRPE9BO7GBA46vg5R1pXog4fvuY0yPClrA9jKkNGD0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=bDArBmuPHL0pKII5vZcrux/tBdKuY1uuj9qM088F0OpolWlqIdujuH9ofKhNyEBzAv5NXBWdpTNvTvf3kNolA7T+/6aHKhnStD7ZYPxC1WK7a4nryclAyVkLgOpDHJciiVoWW76j5Dup40h68uyAJ5MSLzO+Ac5SVAGp1GMwJcE= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=Uw5qBRPy; arc=fail smtp.client-ip=52.101.65.15 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="Uw5qBRPy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ISJZDwngbmXp0vWBKZjhmk+MMM5oOKvr5dlpBiE3lmvloZRwwGByqcGSaTTNmWAhrDkPAhf8h35Ct9sDKUKr1vvlabQUdaHFHJLiuTZuP5NlnG2NH8M7U6WWRBENgj18Xe9sGxOG3JtHbQqXtbeINihua5obApvkg9TNh4KvsSpt7+/Ro19I7I3mu5LwbilvWAXFy4qUSbOvRgkaU/igeAeJoG/uICaodpwojiZnD0eCI4hl/mWg4UF5l9cpi+AsauNONvotLMG90ULss4yKJL7MkeidkSSLXeEn50rMjUUYRNK7503x3duzAJY2v7n18dNcqHpTN43/t4aCHddSBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=ebtt6Jg/w20urXUJwQ5PxMsaKp49U7eC8wCDwgmiSj4=; b=RNMfs0gWhVo8yOEx1u6HFj7Y7MKnUybKXgw/1qwOcJuZYFqOIAlks+abwNg0IlxIZay5LTwEycOA5BwSSJ3e+/YDegtYDY3B5VKAMn2wI+2m65E+E3aQDKvUAuqucWTPiMDZ8qGJPyxtqcHLuGVb4BgZ6aUsYKFEO5ktvLzNCOY7UEFn5+b3wBpHX9JGfKT2jLLQsiCxIHOr/kM4cP10q7If1ikL2EZ591GQWX3h7OZAj5C2/bOXx00ftYBQFLuSXi6fz8M/FtRXcS4khoO6iUGT/cJuu93K9NsX13H5krMcivdBG3pAgA41fclNfXSvvLXyepRFA7VYtQgQh7Zgag== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ebtt6Jg/w20urXUJwQ5PxMsaKp49U7eC8wCDwgmiSj4=; b=Uw5qBRPyvwxUqp2ry6cfogO+YV/Z0FhasyFfkF4YXTs7jGyVf58/t+y+Nl8c2yEj65QzMwUGtNJjMZT08TWUqA81fLg4FIrDnDMV2Na7O6Y/joC7qVw2iS9Y523GzJ9SlyrDId2gPhDKh3oqhD/BU4wDvTNo4oyo72vR28To0rM0PXlzFxd6IdgwrAuTM6GhVEYUkO83O24krHNxFrLGmXMDCO2GOtJnuzozMLWyGZA3Vcgsu+zx6Kv79QbP+SO3+z18dbbzPJRtersRi3EQnUfO4njlBM5dFoAHQvYPUzasieCM6SY7UXBCkylPy/0JzH5sVNj0xYydMJoMxvwCWA== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:23 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 28/43] wifi: nxpwifi: add sta_cfg.c Date: Fri, 9 Aug 2024 17:45:18 +0800 Message-Id: <20240809094533.1660-29-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 90b6b9ab-1a26-4c90-cab8-08dcb85844e7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?1Tx2o3E254XeORnI7Bi8PO0CzPYMenRo9h7ERjLk9hCH38UwWaJLMmMDBM5h?= =?us-ascii?Q?Z+dj65bi/IadYY0PAYo6IluVjv2vAsO+jfbbX31PdsVPVbmIc7cCmILXfbxK?= =?us-ascii?Q?mExi+OcViQIXOJ3JjfsfMgyjGMno2irXN+PCA9shC8DDOFZWDAakrScGfT9a?= =?us-ascii?Q?qeOUtjZcQKvRIXRv78mGyrF75b5JHuiSeMyuxo7uwtU7ji5mKexBOTHXcHwD?= =?us-ascii?Q?CJyh2ySoIU2pXRzKertr56dAjHfXuUtEGfOINoXdoUexqSaJ4sI1zlyrM+bU?= =?us-ascii?Q?C2l3hNloKAOYNdVU8zCL/+d64yQ4TPx2DCJ1dFObxfozISTto+yQtmNj9TK4?= =?us-ascii?Q?VRgcDsenu3VKYsVi/WE6yTEqvPZFMDmnqzExibJjXnToznbZM0BGGSwCc2RQ?= =?us-ascii?Q?1A8CTKpQ0LlrARchNYuxLQQza2AEP9UwBz0bk6RYoq8Dl0lvwuwGHKy2tqh5?= =?us-ascii?Q?AzCDNlEJY4wwyqClY01HqQwc4m05FVTB8/FPWEkDl4Ce6tc9qKKpashAGMxb?= =?us-ascii?Q?ZQPZ3Qa/EpDtzYZHREL0kfw9VcgL1YglhplE/aXsz/hjf4DpMQCv9QZQADr8?= =?us-ascii?Q?QNENWNENYc1x17EBydrRh0zuEOjwJvktziTLv4AZozSdMoRrBYGcb6e5KIq1?= =?us-ascii?Q?XUCIW2+dUGMlFdm2FQ2+8yS7urhlRpxxulxj7yzkAlP1EOpDXC3WN+HpZ1VE?= =?us-ascii?Q?ecslOohKtlaFkYLyuXmiM0aLVa2+8DQGXAhW2Qomj+4lOUUz5GDux07UHkkI?= =?us-ascii?Q?ItRaQUFf2Zl8D6Ms0fz2cR+7WzsroEqPXXOB/brlC2ayZudIOmXdPsoMr/61?= =?us-ascii?Q?lBtGrNMlUYBPPBs3HtowrgDlDX/82atSdu+ENnG71FW0izyhQaCZxd4GcXkU?= =?us-ascii?Q?+QHVLJQYjGCv0CWqWJ/BWHI/BPZ1SVzn7bnngKJ2NFqbj5Ke47/MvWOCWTHb?= =?us-ascii?Q?mZLqtSQ5G160Z20TmKEGqJp06WveNymfD4Dwpbhc+lb9V0y3Mf7spui16rk1?= =?us-ascii?Q?FmzRUob1TJ4rg8ut74xs0hfUymR9kJe7XRiwWn2SqH/xGtWnS5x7fq/YHLeR?= =?us-ascii?Q?QLiLPomEzz17t/5VOIC5IS/rQYlkK6j9adUcoS+myLy8qlrGDZYKBQOgcgA8?= =?us-ascii?Q?55bed1ishkC5R59YBZaNBTn2zFSvrDiEDDoCSdcVqNumI6YKfgpKEbk09LeQ?= =?us-ascii?Q?1YlWu7sA6GmCIsaGUhaHIOMIy4JmvFynKg9j8vzWMvnk34IKMQlblWJFl2Vy?= =?us-ascii?Q?urLWQ5h4SpotSpoXyY5UxjQirA5jp74GQg+0MHiJ9VUu9YlY4IezrHbLCJik?= =?us-ascii?Q?P7WnACqhn3RmjQiT+3dJ1p99Klmr0K96MD+Z/GK7RiGTWA=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?eT44+gjFHYYF/34li9DU1wmmahp/osbfln7N/gBpRIhCzXqD1ztNjYgfS+zI?= =?us-ascii?Q?VAYkmg4e/8i77u1YjONQgfYgB4shWYQQQCWYRLdWP/MqqnPdRo3qLDQaNS0x?= =?us-ascii?Q?QBVdPkRKXR4oUYQXmylpF34NUFd4ZlkCkqVJB1za0aBVJasnkQDgHLOLw13T?= =?us-ascii?Q?eTsCFLrhBb6t1SwQCNKQDH48CS1O8jBkVjqzdmaNrR6o/I4Osmq49wHne4Dz?= =?us-ascii?Q?rqCYFYWAqn8D7LbrZH0B7QbY4zGQtxNr+TGXWyM4PKtIhyeR/7Ts+l3ro03F?= =?us-ascii?Q?OtNDScxawJJ5QVp5CFEwN0hD2Zcnwt+dR/gI9zUsAcPOBlQ0VFd58Z6XemUQ?= =?us-ascii?Q?R0NjxbbZwTa6e4bgct8UCy3BJETwk9CSVJJyespmgSqiAN5SxdL6p9LCk5a3?= =?us-ascii?Q?ip4TurIaZRgPTGrzls/ZqPjHH6f0F48CCAIXxuJPUDx8NNoV5/mnvivqzHnR?= =?us-ascii?Q?R+1Y4hRhhh3mf9hXryH1yAP3ESlGzEqCqm09Evxy1nUwOV1RG5CG69vNAitr?= =?us-ascii?Q?2Hhg68JODOmQcHYY+rEg9G7WMKvOFz3HadjfKCvc1mcksMdEFo1bG9CF2Pqt?= =?us-ascii?Q?Z5P1dgzsiqHukpTL9zoglU+uuqA2pGHwLDtN2sngQCFzOyI+D6iSRN29cq5i?= =?us-ascii?Q?gjJ9JviPHtjmcXueuYq/TfBSX7EGevtHE2iHb863nIGoWfUXWDIec/hOFNo6?= =?us-ascii?Q?vTIhShCwBaGPMfhpjzeLUVTKJ/HudBI7fLU2jAQkoPInL9TOjf/7nnfZ5xoJ?= =?us-ascii?Q?8EpeqUwlM8vTd6ESjFQTSi5N6BHi5Krbf/it9fxGmnwmunOxIlPdF5BXPkAK?= =?us-ascii?Q?PsMek1YEY0pLMDVQKwQhgfAqWNVwSzpVQ6vsg5qWyojB0wosHd054M+9tYNc?= =?us-ascii?Q?35F85jwTRWumbeUfKzB3skeObvNd9/WumXzkozhJDfEV7EczAjEd1QEeUykw?= =?us-ascii?Q?+WDoXLZ0RHujo9S75rX5lCqTOwthSCi5s9BCyqSjnB3WJzEzSoA1LM/wc2D7?= =?us-ascii?Q?yED+PworxdUtYLbaQ6fZuS+XvNvPneu+n9MlNXbnelQ1Ur34Hv3sf9vDprDp?= =?us-ascii?Q?fn0SpflrfM3Rl992KYLUi4vZZqhDYTWZRYfciKvu3MzWfKYDK8o1WiX8WCpb?= =?us-ascii?Q?yUKJxx1Acg1GwBLku1IN9XGW7BGR/Q2LKl2GIDTYPpL38w0pbKA0XT7siE9v?= =?us-ascii?Q?wjetYlthBb37GBpQcUxhsHRlJAhnHXYgFV2V5E0XliN/6EVEqO/ckkKuog8k?= =?us-ascii?Q?VnxD8HZJ3xZ+tKR0cNkM2+htkPjDJHSaudoHaqpj/EEmU293v8quQTrRirzT?= =?us-ascii?Q?5RYj/VTLJheX6ucfSBxbv1bHGSlKPvQ+F7dECXgSs1ftowgLjDtKCRqFhrpS?= =?us-ascii?Q?rOt3ofrA1DKJqHtU4dgY163r5BX9GNr3RjqgwD66lhTG5vC5TKrFf2zZO9Tf?= =?us-ascii?Q?s3Cf6/aS0IGLhB7hLHimFK7ERoFjiThqHm+Rdjkw15FxNhxjSCHsm+mFti4+?= =?us-ascii?Q?b8vbCA5kT7wz/nZwox9XBBM+2wEahIOdX/0RM1IZyD+E+rdTVtOzcoSxtJyE?= =?us-ascii?Q?tEUmxU2k1m8upCmuvJIUW5/ot7+wexpnR1JTEsbdhdRNF60o/+kbm1IM40cY?= =?us-ascii?Q?k03lmtlBPChQTfeI4uD87fr6YXe0UmltQyMAUFTcD8g4?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 90b6b9ab-1a26-4c90-cab8-08dcb85844e7 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:23.6349 (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: MOZdXFo6L1L2mrEyECPsc78sXvEM3vVmc/tKqM2O6hfTJ38NkwOvWV+GbJfrFAQhPULj2wiCtffUUWLGoyQIJQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/sta_cfg.c | 1307 ++++++++++++++++++++ 1 file changed, 1307 insertions(+) create mode 100644 drivers/net/wireless/nxp/nxpwifi/sta_cfg.c diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_cfg.c b/drivers/net/wirel= ess/nxp/nxpwifi/sta_cfg.c new file mode 100644 index 000000000000..b5531f9f4759 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_cfg.c @@ -0,0 +1,1307 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: functions for station ioctl + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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; + int ret; + + 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(); + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_802_11D_DOMAIN_INFO, + HOST_ACT_GEN_SET, 0, NULL, false); + if (ret) + nxpwifi_dbg(priv->adapter, ERROR, + "11D: setting domain info in FW fail\n"); + else + nxpwifi_dnld_txpwr_table(priv); + + return ret; +} + +/* 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 -EINVAL; + 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 -EPERM; + 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 -EINVAL; + 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 -EINVAL; + 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. + */ +bool 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 -EINVAL; + + 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 -EINVAL; + } + } + 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 -EINVAL; + } + 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 -EINVAL; + } + + 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 -EINVAL; + } + + 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 -EINVAL; + } + + 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; + + return nxpwifi_send_cmd(priv, HOST_CMD_VERSION_EXT, + HOST_ACT_GEN_GET, 0, &ver_ext, true); +} + +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; + int ret; + + 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); + } + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_REMAIN_ON_CHAN, + action, 0, &roc_cfg, true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "failed to remain on channel\n"); + return ret; + } + + 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 -EINVAL; + } + + 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) + *value =3D reg_rw.value; + + 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 ieee80211_vendor_ie *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 element)) { + return -EINVAL; + } + pvendor_ie =3D (struct ieee80211_vendor_ie *)ie_data_ptr; + + while (pvendor_ie) { + cur_ie_len =3D pvendor_ie->len + sizeof(struct element); + + 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 element)) + pvendor_ie =3D NULL; + else + pvendor_ie =3D (struct ieee80211_vendor_ie *) + (((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 -EINVAL; + } + 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 -EINVAL; + } + 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); + + return nxpwifi_misc_ioctl_gen_ie(priv, &gen_ie, HOST_ACT_GEN_SET); +} + +/* 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) +{ + return nxpwifi_send_cmd(priv, HOST_CMD_HS_WAKEUP_REASON, + HOST_ACT_GEN_GET, 0, wakeup_reason, + cmd_type =3D=3D NXPWIFI_SYNC_CMD); +} + +int nxpwifi_get_chan_info(struct nxpwifi_private *priv, + struct nxpwifi_channel_band *channel_band) +{ + return nxpwifi_send_cmd(priv, HOST_CMD_STA_CONFIGURE, + HOST_ACT_GEN_GET, 0, channel_band, + NXPWIFI_SYNC_CMD); +} --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from DB3PR0202CU003.outbound.protection.outlook.com (mail-northeuropeazon11011015.outbound.protection.outlook.com [52.101.65.15]) (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 AF0D219309A; Fri, 9 Aug 2024 09:47:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.65.15 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196859; cv=fail; b=p4oIQewNFQexGxF16PRxz70r3Gt81Lt+qcIOAZJ0E15j5ao9gYzUqqec0NhK62M4+AZQi8I8yXyJDioxxN4CYdpjOdK1eZcNwr9mNmXXqmgnfkIWfrhbeiE1SYGIVtNHEVoZNbx+WWiBP0w2E18MWaImm/flxGJ1m1qiw4/Gx5M= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196859; c=relaxed/simple; bh=q1RR66ibqaq44AVkcDwxGl47kUCoQ9rwkWGpujIF8q4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=UjawMgCbe3ffkE5iOa5txwcoD7ZBW3oLYXLaLO4yTRS0diSIlpCmGkf2zoa/gCvFiQnQLGQ+60BBC0kGM20q7ccr8FUEebZYC8kP/nbUZ1Zpp63mhgLRFKp4rVHJlrfgiNCHusxn9RKOBHmYhpKI0ZwWSxMnwp9P/ZKFRu435oQ= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=beWKt75H; arc=fail smtp.client-ip=52.101.65.15 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="beWKt75H" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=HK/trwY+rIeHPvTo3TpenHE24fFESK7XaGLwLdszu2TkjFvYmolJzu+92MEHDjm5kDkFOFwOORdmwZTrlWHo5kjFclu+jAu/izDswJbx4wneTiI3G6RNA0n9xf1hFSeVs7uKWmfUuljwqZOLAiovRiGanD6GLch9v3hr8R/+RY27n13LVss/m56qN5N84q3qMVY/PKI6rPPnrlhtPK6woEY+dYwpBJ96rVVe0mhx6skeBAbIOzbUrZvpWG9/GQojzgY8b2S5tQfh0bin2jG4DByQYC1iJesgwiB+Pv+TKEp5ox13ZnZ/Me4L7EuQxEk8/VQeIQzSprngBOtTvkzU4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=ZCZFlyd4yQNCcedNTkvs+kZ7RZ/SxloyQiSs+pffz/4=; b=aWmIXfdO7SU+eA7ae9yQ/5vNWqPIey/CPIRbvZRffciWdmqeDJV5GmpPVbWw/76LsE7kA40rFmKUXQhrFlivNs23e2vdjubbWcqEEBxwuW5IM7FqKTfclUr9ArJMyajbvm9KhXWqB8zuMcJV6zkqFTcWfwqAdtlVjwQqxGo7/HAXwcKzQo53CmQKJJg7NSngP9Mui0Txe9hTUpwadSkQ2rkvEimNDUZsqzLmVCz1zN7ikaa30jS3suEJV/QBlRBcuBOCv9/bQC5xNW9MOFLHkgDMPPxz9WcKOgKSrcejto7xjnWg+iFFmhZ3XPZGZIPuCgUIoY7wXuqYfD1NkyAycQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ZCZFlyd4yQNCcedNTkvs+kZ7RZ/SxloyQiSs+pffz/4=; b=beWKt75HDe3X5sXjBEFmYqzhVVcjH4MSNfXYeDMlfTduDon0AC3h6AYNfngzAqosQ2JWxcvPmNlUlOihqeNSAc1E7MDlrwurhaxKNIKn9pGxxJbSNciTx/bX/+/8dY7srFUcWjugrBAd6DhlVJAtnUkycmHqVDhZRdHXEE8Eq4xSEAWgwYyQvZhqyyqXfYChkKPm4JjWYEWD2wzgJEubyNOUJNSZuyDvhL98ZXzA2EIPvYlysliOufpC4HVvzJZPFP405pfBtYvsON/9pTj4J1vN0tTC1gWqOgn7oFRT6SEQj9Do+2apjhw74r5eaI/tB/NkWb853KBf8rj9Aok24Q== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:27 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 29/43] wifi: nxpwifi: add sta_cmd.c Date: Fri, 9 Aug 2024 17:45:19 +0800 Message-Id: <20240809094533.1660-30-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 1ca59f42-fcfd-47d7-4283-08dcb85846e0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?7nH82TYOHAVaMO0O6o5LsNqtPkMGDoLNDDuIdPX4QPkeBxIr1VU/YxK0cacC?= =?us-ascii?Q?w+JmUW9Dp4lx93W7RNGPWrY8EWU9hpu7skS3KJWGYsVNCH7BfQgln+Y01BC2?= =?us-ascii?Q?FHZyODyEnkRC31hpcck5SmDx8eqe7nWqTdh9Kakx/q2zvfuK2rpGrV9izmju?= =?us-ascii?Q?u2Jw7lk+hJHJ73suE/Lwd0gsVVvS9DNPeuekTgujs73akr3xJ1MM/aJpmON3?= =?us-ascii?Q?GYtLZiXlyhDy9T8bpuc7iK5yMwgZCnware0X9pjB5hx6VZ9Ie9+/q9uZB4xI?= =?us-ascii?Q?9RSYAZhONTvLzNcdYQRkJE2uE5tA0y6NkwtCdXeD0PlEgrzddOnKvIc341At?= =?us-ascii?Q?kygVoArVtdlgxyzgzBEjQfVNal8Sk1WgDeK9KFoCCl37vN7DMZDB0j2U3xNr?= =?us-ascii?Q?1TOlIC7kymw4h5VPVwGxf8YsoYV6qfU52hNlJR9Q6lurjWDYL2UYV13a12X8?= =?us-ascii?Q?YjG4VH15sgvDQNwOjPLMB3KGg6c59VY7tHb0Y5lB69uKjfwpxECL4wIcxlmK?= =?us-ascii?Q?3aVXr534mGgfOavfFXTTkTu5bPlAcDR8f6Cw51tDpM/4RQWhZ25AubSWRJjY?= =?us-ascii?Q?yEeJ13bt0aoQQlt73ydhQDaDMX6XR0J4BAo9894v50pjpdRUgYSIdT2k/igk?= =?us-ascii?Q?407j8uRns66l+VpNvRcWb0WnLdl8gV2qxSf7MrXEuDndWo0kCH9O238yvKfq?= =?us-ascii?Q?0A+mp+re/F9eoFQfoBLGnagkncruXdxR2sV9kxqhGlhJmB2EBW6iStehZpzz?= =?us-ascii?Q?NHg7Q4ThrvJLOZcjN5I36e52cxpMmnS7b2Nc+WsGw0Nan8X8BMfsZrZPOBpa?= =?us-ascii?Q?uiAdHkl2YzanWey7i66c4rBN+J5TiLKcN/pDMZ2z3Qkuzs1wVAjV4P6AhoZW?= =?us-ascii?Q?XuLBOobOeHwS77HKuWOzBBKFQGmHk+6wal6m6ub9Zd0iWtXUp6O9RxKJc4w0?= =?us-ascii?Q?BgmAPmVPMEC/6JqwEMtE98oVXakeK835zMtGz5eW++dpgrIJ7KFTK1Tl6dXd?= =?us-ascii?Q?3i+NISUyoOHPpHCT6uiye4XVMWmVECC4K8cpFhEUVnJUSUYiUgdoyTsXuw/y?= =?us-ascii?Q?ag4B0/i212gtYmVqrJiJA0TvzFRsOyIAM6nVnSsJsAJ1f4s+YyXKUY+SRp8d?= =?us-ascii?Q?AnhjFTTRoP4+/+wGA0XztNpVN1QTGmK9puOVOrhjHg/oFEY9M6eEI+ci//96?= =?us-ascii?Q?DvbOkzNZT5erOdaO7AO9O1ajwJsG6KolA6ISR5ZeWvgmMNpgIeSApQzOQYrF?= =?us-ascii?Q?NCvOPwFUBEl+ySxGoMj4xNXYngD16nmyGORWgG5AfhGp2MlgR70tyIqFJphZ?= =?us-ascii?Q?wTMzIvG6TsCN+MQGv3bfbouwmZRJZPrb3xUXOUDFWVG9Dw=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?UwlIa0rGGPC4RuMmfKpIXy1UYEAXWEkrOe4nuwjK8saviNHlopoak9Lu4Rkg?= =?us-ascii?Q?L3X5EWRwtqS3Jde4XHkeVpBAFQEOLJhPbarTSKNC05C4xh/W5QPSsdK9whTZ?= =?us-ascii?Q?TSMOGkvdETcQYF5DjIE6Yopvajm86a/4P5abIa+CsR42BXYQIK49hN38hXzp?= =?us-ascii?Q?tGv+Ve9xrzlIw+TASH5FqSDoE4epzUnUcxPaQRV6qxp0KUkLUmf/bdvBoUoe?= =?us-ascii?Q?JCjWCtZ6W4PsHdcZL5BtUQBjTW2eoqug8J6F296hnVimJ7YeUrfevHjxBKN4?= =?us-ascii?Q?lIVfokqXIbttTyMAeuWnAVqWcoWABGYO8/2E4TSIULlG2nPoKVheR3qfpnhH?= =?us-ascii?Q?SzaEHpWbI1zqkaTHS1aM+imm3Z3F6cnuN7IzHKRQs0M9JAPoTzcgCGKhGDza?= =?us-ascii?Q?QThmaho9k+SuS4gnmhIgh7X7sTQKDXEhuy7XFNv1Ds6w+3ineagCfOiDwTeT?= =?us-ascii?Q?x1Lo64uPpVIkbUy9RfrpdJPNOKbn9aniO498wSUV/QpBTSrXxxvQAA04KVSl?= =?us-ascii?Q?H8WmM4Z2zt8iNtHm1IskgFk43TlgsJQGXopWrOR0wKbUMQFucoesZyvGXzg2?= =?us-ascii?Q?Wq8s60OqcssNaElRBLv4Qr0y5AN7vZaph7KvFYHch54NTd0c+AcwPUcPZ7Bp?= =?us-ascii?Q?L1ickIUY1t4toKmh7rfBfKX+TWMdlXrP6pgji4yBkkUfXgiXWT9dbzYBWypT?= =?us-ascii?Q?pqpK8T8e5HjIOdNp6/dCQ358YhF8DZ3sJo0UGoYgQp5iWhEnmJZ3vYEVcoIj?= =?us-ascii?Q?nXEDHS9APW0tw/+D8MmODX7MPT2lCUsJryw5hEawtDB42U8nuOutkEi7+Zbc?= =?us-ascii?Q?wy5oF8LjWYIaR8ijcAMcy0kaG1rrrtEr911tqGOaNbdmQFPtJzD8g/YxqR0k?= =?us-ascii?Q?WK53lCvIGyWcG8KyQmJPn61z1wq36vVP4517i3YLLy/Y+TCBujZeTcjSIysn?= =?us-ascii?Q?JwRMDSAFuYPmMFO1bku4SHPpjMK1EwlphZ55v6HwnPSNYeR46UbQhdo1Tpf9?= =?us-ascii?Q?/B2wNBI6HTXnYVsz58mSX1ZH/q+0Ts6Mw8WuPVsANWGd3pkqf1y7eTLSYIKM?= =?us-ascii?Q?R14XqWJcwc2d55KKtxy1rDlEeLLf48g62LenbU0RKoTczV7B6oCyOG3LUONA?= =?us-ascii?Q?z1weBnlj+kMNUcKGm2FSa/RnUZgBuCzpkMfURGvVN+nOHcKgLECURT1+f5Fv?= =?us-ascii?Q?k/mR3qIg/mESVIaeUQ6CGEb/KrblVayEAPWPhArrZR6XlLo3D5f/hz51Dgwp?= =?us-ascii?Q?zanYdsJdfUi16yMha1l4+5dQTjFREyyCOmHANuL0L94ae8qPs7NDF7+8AZRw?= =?us-ascii?Q?wQgk7Uv0qGfklwZYz4SozxKWYgmibe/y6Z0ZNS3g0i14z2l5v9ppM6w91bSO?= =?us-ascii?Q?x/U3KGMOgJKjKoLvHuESS9oIM+BUeVgh4sfjX62nOypl03E9lydn1C71lE7x?= =?us-ascii?Q?JYOcOlnZd+Nd6PGga36Y8qFEAGz/76qeqlZf40m8Rj6HGIq5iJwiJ7eM8SH3?= =?us-ascii?Q?qG8VTilkW8KfLTpuay92l5Lj8O2kkhp5+Spo0Xo1okTgV69iYLwg9yT9RE2R?= =?us-ascii?Q?6znVJxOqO8yCy3ugCAlZuKnVW90vRZEmy1/zVUec0xUKkTDV80O2FLM5ZuZT?= =?us-ascii?Q?mB9Obfaqt9oMCvJy/s1ljKbHQosAqmp15eVwaQv7Awhj?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1ca59f42-fcfd-47d7-4283-08dcb85846e0 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:26.9843 (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: twVysr0A0m1S97LhSUqDjU4Chu1kmLv6spkbDbiT77jHUvZ52TQiXg53p65rtxjhe2cxbrBeoulBX52KDBXdew== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/sta_cmd.c | 3233 ++++++++++++++++++++ 1 file changed, 3233 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..ef4980b48b60 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c @@ -0,0 +1,3233 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station command handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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 -EINVAL; + } + + 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 -ENOMEM; + } + 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 -EINVAL; + } + 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 -EINVAL; + } + + 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; + struct nxpwifi_ietypes_domain_code *domain_code; + u8 no_of_triplet =3D adapter->domain_reg.no_of_triplet; + int triplet_size; + + 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); + cmd->size =3D cpu_to_le16(S_DS_GEN); + domain_info->action =3D cpu_to_le16(cmd_action); + le16_unaligned_add_cpu(&cmd->size, sizeof(domain_info->action)); + + if (cmd_action =3D=3D HOST_ACT_GEN_GET) + return 0; + + triplet_size =3D no_of_triplet * + sizeof(struct ieee80211_country_ie_triplet); + + domain->header.type =3D cpu_to_le16(WLAN_EID_COUNTRY); + domain->header.len =3D + cpu_to_le16(sizeof(domain->country_code) + triplet_size); + memcpy(domain->country_code, adapter->domain_reg.country_code, + sizeof(domain->country_code)); + if (no_of_triplet) + memcpy(domain->triplet, adapter->domain_reg.triplet, + triplet_size); + le16_unaligned_add_cpu(&cmd->size, sizeof(*domain) + triplet_size); + + domain_code =3D (struct nxpwifi_ietypes_domain_code *)((u8 *)cmd + + le16_to_cpu(cmd->size)); + domain_code->header.type =3D cpu_to_le16(TLV_TYPE_REGION_DOMAIN_CODE); + domain_code->header.len =3D + cpu_to_le16(sizeof(*domain_code) - + sizeof(struct nxpwifi_ie_types_header)); + le16_unaligned_add_cpu(&cmd->size, sizeof(*domain_code)); + + 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 -EINVAL; + } + + 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 -EINVAL; + } + + 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 -EINVAL; + } + + 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 -EINVAL; + } + + 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 -ENOMEM; + } + + *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; + int ret =3D 0; + + 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); + + ret =3D nxpwifi_cmd_append_rpn_expression(priv, + &mef->mef_entry[i], + &pos); + if (ret) + return ret; + + 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 ret; +} + +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 -ENOMEM; + + 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 -EINVAL; + + 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, CMD, + "%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 ret; + + /* 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 ret; + + /** 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 ret; + + 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 ret; + } + + 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 ret; + 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 ret; + + 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 ret; + /* 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 ret; + + 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 ret; + } + + 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 Sat Feb 7 11:38:14 2026 Received: from DB3PR0202CU003.outbound.protection.outlook.com (mail-northeuropeazon11011015.outbound.protection.outlook.com [52.101.65.15]) (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 C09DE19A281; Fri, 9 Aug 2024 09:47:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.65.15 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196862; cv=fail; b=UERalqAX3iePVfJhsg1yD79x0ZXXsIbuAW7xEB+gn1VGbif6xfu3oIYUeFAB5UKKghH14XuhFF6e3nvDj1wm1XTuOWMxmjFXt+k4QBAEElWBqDozQQAWn4uncpDsmOG6roOBTx6rEB26+FKuZmGvbgRMJx+QxHGCqcIbmHfKnFk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196862; c=relaxed/simple; bh=7Oafm1/MBy1j9Ld3SJToc8AKiZ2k9RgvoY4xcriuiJc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=Q0GlmjHv+EeEKzW1kOjDfRkwZOZdIrGAuequfCaLqJJ0I1BBXroY1E1noDgr+76E+BGWl6TMtOmdvxaw1wyJs/DlbLGAH+UMm5NwKkgqEPnfhNC3ZaEwsFTxA2qigcXPb91gGdl8+0rkTQO0GTdHHGcovuPCxYujSEPb8b08dYg= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=GHo/JfPS; arc=fail smtp.client-ip=52.101.65.15 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="GHo/JfPS" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=xJicGw8upUTc8MAwS+0Wn92Vv1nvcy+FS5EyXRgK8o89mszc+0s0fK8uRlRCsR1a/Gb4H7sYqzrlX2r6Xs3E5bZRaoqLOyuN9HgNM1kreGmplW3q91vRFsHDFrxdWL2hepDcAJSMdFPcsA/jE9yCilB7/DSq6E+G8adj7Ri8vOKZsK78Iho+2ow+h/iOULScE5bzPRtEtdRYtmmjmyEbiZkQD/pICbB6m0i9HyjHyIOCGoiWT7d+fSmB42uPDTOTm6/M9JXYMg5LsrdONs/bu5/32CH05oMgtck28YEWSfvZjJHEucsabxiYcQ7xfWqRQD9QI2/TJ0DmcZjE3A55/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=SdE9qNROvq51dOan1/lsUiVmQnJIgEmfg2mnL1hTZLo=; b=vmIzOQQiMmaAs7RBCKdlD4X40yFD7TVldhowgtx7A1vNVoOz4myw353Pk9DihbyXsj62yw3qbHD/gWf2Nyu1Cy5vDeBRy4IJn/d17XoPRZrk40LouMgueMXjvSetmintpUawDIIPJPc1uTjBOAnlXNMqSjtfgObVj9EV7B/NVOzBOcemgzE3jLD0FOnmB5K/lyR9r8HfsSOj8+wuzPwzwCqe/6TPnuzNDmGgOXtsYWnqskfxv3e3wgdENnH0DW0Vkks+CP+BqQ6Ny3Oq8Ar1nYi4ecg0N6ztxj10n8l8ZeREgsEc7I0HEWB9xdfSQQtyXP+K7Uv2MbZxUf687IueAw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=SdE9qNROvq51dOan1/lsUiVmQnJIgEmfg2mnL1hTZLo=; b=GHo/JfPSr8uTXCeVy8h/OKdJN7/PAlJf60Ux7Dlyc/bT1SLfuzP4e71pYkIrs9MHLY/R4kKdDcFqpYZNqW3Z3scP1U6hA5WkUz3EZEu2sGzsOd/FG02nE4iGrt6xitjPh5dFDyA+mD08K5x6Hevzc+UcOxv0Z8Iuh6CcogApvKU6u78lk7+9Wee90s9oDfMvT8S1day3V6u89Luzk36RcHd6IdzhkJTtJvJq3HgTPPx9Xgi/XqdUlw2eZWqhFLu1U/tqSTBvNvcTZv84L4Dfnng90V2CJmoFH+6SWzKlV44LCzLjobxaif3AFXKtnqd9YS8Bg39giKTerpLIlhyyyw== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:30 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 30/43] wifi: nxpwifi: add sta_event.c Date: Fri, 9 Aug 2024 17:45:20 +0800 Message-Id: <20240809094533.1660-31-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 3ccc03bc-4b9f-4295-068c-08dcb85848e0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?uBRTg7mGT+9aTk21FTfzxVfSwX9pt4AyOX6OH1dDAoVj63nCl0Kvk3xxpNZD?= =?us-ascii?Q?aJNdEgia5EbFFq5qwJvQxj1TfkA6EqBsM1DN0W3+4csANA9GAibgofLBbmMK?= =?us-ascii?Q?8/wk4HSRChDRH9bpGwzJ05jEM4cTkNZ5mNg9Z86DFzhhqPB/fn0XjDTPEHn3?= =?us-ascii?Q?nA3PeGCWnf27J7VjNAvFSQzBYwXpGxCea2hJab7mzGkmLa7uEGfWXjHQ6yCI?= =?us-ascii?Q?aiU8j/7ywhaLcsOQG8kpRm/R1LL1212aqbayw68PjyQhlc09PdzVUYgTEW6+?= =?us-ascii?Q?LNZu8b/2odUm5U98eHg2oqzYadpqwovRHGxYzfyTsJIQEFjuGv1XOrhcOhEM?= =?us-ascii?Q?0rUjbaJ7Q33g+6aLVkybmtz1SE8wDrt9QWNGaJ0K3DmRNZ9xB9r11S0u3eyA?= =?us-ascii?Q?meuhL+OK6fpfbeC8yrFuyT2RMEYFtIFm/F4WexJAhEM1uFfj2Q+Rpdw6TFlW?= =?us-ascii?Q?diPk0fS8qVC+tu+a1QHBndG1RYpf/f60RkR1CN7QalWT1gDmldjooUBF3yoR?= =?us-ascii?Q?v75e/VvlbDsZVO5e7N3iW+knVI7aVRP9aIwXaxzW5D14yPcS4mORkaCApfrG?= =?us-ascii?Q?X/XK7zSI3fCQYk5aghecyEq6b2Ww8Go0gvR9/y9tebimAQamGKGiGMDMgvQd?= =?us-ascii?Q?j5hceTjeiW0T3mf63o0nryUPKpJAZu2eew6eHMK2XalXMzOZeV95Pq8dQCT4?= =?us-ascii?Q?bHnBdqYD/5pvRIYunwUek+iyfIFF8EO5BL/KXIlLqoBtvxBEmE8BFc8pWFkc?= =?us-ascii?Q?4l5P7NPVfqcuCNiSV5qp9dgYcvK3GAl+x4/izf2P5CojEEvmmw5Q0Bt/n+6y?= =?us-ascii?Q?PuP27RGHhIFx11VtElc0UjbMe0YLVqMrpMsxgpKlvs6PuT5F35CR8Mf2Uf8n?= =?us-ascii?Q?j6AU8pSgTaBkzeBbFgmT7hmYbs5tZkX/JJeVZVax0fbOSXV7fnjn/DPgCcR3?= =?us-ascii?Q?XQZFtUXcQFSYk/xwpwRupc+YeQ0FPmjStTl2Oozy2+yK9h8oe30m5JhbXDI/?= =?us-ascii?Q?nCKUPINyAaMM2YnAydzYlmI78oIcJsd5OQrbdmA8dEn0jnpz7YO4tan7o4Zw?= =?us-ascii?Q?eMP5kQcM19rLxFIG6a4knnXjSEbgRaXVlY7iJlG8LrvNZwvAgHrWsFRxL03o?= =?us-ascii?Q?SryJBs4lpyjqAobMOoO7vpFwiJYP9F2ilz4vzAWalTcPqKI7eX057/r9UOX1?= =?us-ascii?Q?SQk4LgiX9J5WgY8ar+QvtaM/+vD5X2rK+gNOIKkbYFaY14bJTNiI6N7UJ3m6?= =?us-ascii?Q?Ox65a1yv+PakbMlpHTm73n1+sRZHhyaGZ8hS079YibUY2KSpfm5P3EARiMAd?= =?us-ascii?Q?WEpxMshopEVidK/i072qXLciYyP7L7rzOqD0Cnao8y7E3A=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?PIPH0+DDzhJ259pLxV73Q2/mmtYdWHB2qTBb4y0KmTupOPjCFkLLk40ZF6eW?= =?us-ascii?Q?YTjwetD62XbkEi2io8Whk/5TKJXIV9cgSKpPz96wJUIgIrRCcw7lG73nAh1P?= =?us-ascii?Q?d1V3Vs8pyqStvyWozY8sUfGDhijJ9eW8uB8SorfrXKo/Te4Zs1D1IN/NqRlF?= =?us-ascii?Q?vrfYkq7Tie5BRitpUwErQBIhMjT754UlTFHh4jKqaV3KE8lQMH9pEBZboMVJ?= =?us-ascii?Q?oU8Fd43WfPjsO/bHu8uMpuhv/lUci1l4f/mUHFwIzwWZ4hZ79GXdKqNeGtO5?= =?us-ascii?Q?TqIJ6+SVdC72LDkAPtQEcj5I3thuYRYanwtTDFuyOQQry0aYVyuDg7uGduqJ?= =?us-ascii?Q?0J+p+qpfG3+vYwAWlm4ZiyOmE+5AOZ/XIQS/f6C1FbRePaI7YxmxM7wl0wGO?= =?us-ascii?Q?fXKPoHhFEykpDvwi677cPn19G+4QfgWmBCR0/QNy5Gh3Lev7uepmyPT8lYdY?= =?us-ascii?Q?n75R1lf6tHEmujH54eoo8zyAlXrHx7YZJiyJN8icC1jkFM8IRJ/KSvrZDEea?= =?us-ascii?Q?z3l076bDWrEtWdwj3yjN53LPrTje5soxkJpoS3yGA2yBGthpxm2DA0lDz3zT?= =?us-ascii?Q?XXy+aKRa+XJvBZiwNanaydhYybaPGok5znw85tN/X1F17BfSGWG8o+H+SYRM?= =?us-ascii?Q?Bv7Lueos2SrWUs1G5rBMEAfd7hGP2UtU2xo/Qpmnvv+8jrnAcefnkBMGaBs0?= =?us-ascii?Q?shZDwdeRS3ztA++TNsuvXrF5yGh/Bx9VT933Ilb0lWhvRor0qtkfO4k+92vW?= =?us-ascii?Q?Ol4FWGkU3DOXPhwP3V9qqHbmuYYVPkAAF9/hRpTuDJNTCn3M/PjmdCl1T6wa?= =?us-ascii?Q?Jk/QhGLhfPbomnI3NWWSYiagTTzLonlI1GAMWAsmubf1FXG6Yj8hAhNDheQo?= =?us-ascii?Q?CJN6WBS+AQ7GrEMItuha/EbhzL9F7acW/cfy5NCdbvlEXDh5vUOwCrJr5FDq?= =?us-ascii?Q?FnxdkmXdKYtPqHe1U0zlNdmrRXnGcpMP9/FsSQE+hhyIVNRi41FoXZUkWWF3?= =?us-ascii?Q?TJtPam3FxqGtyVbTIIyogiigP/MY2uBJAQuqO/zvcG6fC3XGYT2xG5EiQI2h?= =?us-ascii?Q?qNxit9cyAJ1ANmvXgHluc9cQHYlQ/wXiXl1LaSNY7ATSZZntVh0zKYmBvOAC?= =?us-ascii?Q?E6cqXyS1RT1CziX2zfFI52DqcXsIyURo9eJa4NPydmqHl0kaTkVqGBvVMeEK?= =?us-ascii?Q?ApwRwIIdEYhRzFvCEhdSNXhcpg96cKcGg8cuacX73/3swr1NQmqQmLxoy4yD?= =?us-ascii?Q?h9FfcFvpDva23SizJl4biSca6MeC0V2AwoM4onB3qFpA7Ux6McJiQFmqnSgI?= =?us-ascii?Q?3OyiM85ivDDpual/qz03X9SSlmAP2ldeV+PXYNP/t0rtYF1JnlsqYa7rqjbD?= =?us-ascii?Q?WUwGRpb/fz4iN+VOsMf64T2hN4K5Q16vcNOwZHL6mVFWvBkJ+dYDjk8IpgDJ?= =?us-ascii?Q?6n+djNDiYGvMVrttU1NjtwxcmN/rsi0Vs1gR2BIzN77Owh0PCXzB2rb5yWJm?= =?us-ascii?Q?txMRFzH5ur4RQFSaN3PQxJy1CJwbPB52WZUAuaecjpK2Kqygvtpy8bRtKSND?= =?us-ascii?Q?9D8fZX07ZmcXhaqHiBGrm5KFk4zh7RG1MaJ6yMgqdvIKt/zOYGMw0iisy4bP?= =?us-ascii?Q?wegdxyqdEFB4I2qGccvDOv1SmLrdVnGiDV25CkUIFLsL?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3ccc03bc-4b9f-4295-068c-08dcb85848e0 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:30.2426 (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: g0vMZTFvzw6PSg1lBTfiWQvNS0ehC7cyqy10jFP68zJ9lRJx4YAv2gLN7yo42f8TkH9t7Ruok9HvWiyoWbW9Mw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/sta_event.c | 864 +++++++++++++++++++ 1 file changed, 864 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..58852a63df44 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_event.c @@ -0,0 +1,864 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station event handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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; + + adapter->dbg.num_event_link_lost++; + if (priv->media_connected) { + adapter->priv_link_lost =3D priv; + adapter->host_mlme_link_lost =3D true; + nxpwifi_queue_work(adapter, + &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->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 int +nxpwifi_sta_event_vdll_ind(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_process_vdll_event(priv, adapter->event_skb); +} + +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_VDLL_IND, + .event_handler =3D nxpwifi_sta_event_vdll_ind}, + {.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 Sat Feb 7 11:38:14 2026 Received: from DB3PR0202CU003.outbound.protection.outlook.com (mail-northeuropeazon11011015.outbound.protection.outlook.com [52.101.65.15]) (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 E312519AA58; Fri, 9 Aug 2024 09:47:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.65.15 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196865; cv=fail; b=TgOEr4mW3jowo/BNZ7zuja5U3fxxILj3UsrWpKblk4WKei2fW4Ph/ie8shRv6evFDeA5QCTi7ww00mZQfE9jWPtwg0XpEFsFLkxb8auRxgDLAuetVmB4+x3uuSj5Urnsk6I8p0EveygkqNh4S9Pw65Wumx1Or+XfGIbdgKeGr44= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196865; c=relaxed/simple; bh=ZjDal+MPnFNL/z0sJX/OgwVeAyQ1K/UPEsksaa34CdA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=NTWhBDpCUgXx9WBa0GAiYrAe9zikXnP73nsnPqwf5qGfPg50nFq6C5DQIfFDi9FFaahWRJhGaK1xYG/ogQpQ6IoZ45qSRhFoZYDywsOv1yscniXNzY6nxlT0uMXsgGUQqPT/jzA97Eem8DMsr9P4klgUbG9nva4EqpMtzmh0qao= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=L1BQuN8L; arc=fail smtp.client-ip=52.101.65.15 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="L1BQuN8L" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=K13Nq1tfCmWHSh9UBw2DYDn8gZ8IZ283Lpw6OTh/Ifqx+QKja8VP/QdCRvpcIRhSL/DuAhcWCYzFlRK3famk4+cbMnptQj3Zu2KFze614GzyaSfNxfRZvD7NwOUdyt9nAc+BwZ0V2jwaHeu+JxC0NxkCAcI5xugFFs4D3yRmGq5qCw1j5oexuB2CgLYXbKr3f040wWrZMbO5ZsPHDa273AdKp1IlslfhkiAxd5M0iRQBEnJGt6X0BKEr5VV6moUifMpgeYSdVB4J8UWApCMkd9RP285TKMrc6SCQhq9n+T2N420eFZMajT9/zLSqBb5m/X/nz7PMCdxNmY7RIgktqg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=ysjBqJy3xkCGEqnSDU1KLslufZowZuRkFYV0QmhyZb8=; b=J3Lw6DMbPYJKLi2vQLL7SnCX3PtZa9F7qLlUD0bQ11+XrSHXchXARuZ1tqJGiTu67Q/hWr9TeSYTcMF6PWJBr/wjCX+w4R5H0k/+ScImj35zo11efZvL1xw39dWofO8dWD5QtF8VMGO/p155SIY1GWI9Waw2kTZ7L9d+oRjAhdc+v2YiiOQ960bJ98OaziGCdi3rMW5ei6sztjqQiKbS5cRFajroCfbkmmtG9quuUXzIQZ32/ea56TNvsuBKDm0UMZU75TtzWYh8HUnmQvvHhncFGtoQr7WCRv6G67XhUsNUGiom1JXn4kE6PmvrVY3/cjA6z1j3juRulATRFQaWmQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ysjBqJy3xkCGEqnSDU1KLslufZowZuRkFYV0QmhyZb8=; b=L1BQuN8LesO/tbx2O1TlVVjnDFVf3qZaDGTGK/nUI5iAwx4S0rHPFq4iRXeIIr+ALDqVEQzGbWrfy+w9wFDM33sJdOiL4HUQInwTTWs6f9cwXIbMIu8Y14cjTYGJFX2jn8KL+8qF92svNG5/cXZGzTmo41YCyIQvtxgOZDFSfOs7H7Jo7Jvse6YrApcnBtkWhFnc9JRlA7XRl0GC3j0HjrUOkcR1HiBNI6xZ778rU8B+48sBcT9u8fGDahs5bgvgsxgFX0YXninhKRr05I+bVOvAbRDl8Xgtv/9GNLOUuGk4TIj9abxIho9jmSzwZQwOCUbQXX0vRux9Ab1h/4PglA== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:33 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 31/43] wifi: nxpwifi: add sta_rx.c Date: Fri, 9 Aug 2024 17:45:21 +0800 Message-Id: <20240809094533.1660-32-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 885472ce-9459-411c-8d1b-08dcb8584ace X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?HXfpLFdr6Iwy2w9mgl8AunJlEYZ4MNdF7fynRpZY8z1JSSCg7s3WFjDQlqVX?= =?us-ascii?Q?qJmWyGv5AZTR/K11DeSeCwxBBNEGA3NuKMynV+ukYKVzykg97Gn1PwqlOxCe?= =?us-ascii?Q?0GMiRBYverIyS6K9gG1oI5CfN3zFMJYFvVQN3X0ktpKADrY7qTGPn+Y+lEim?= =?us-ascii?Q?Q3lu9r7G3A36/kjaYydLWCChpnYeAG73+EoEiRJ2hbfzVSQSIpF6lkSZzrfj?= =?us-ascii?Q?rIgdGOBucKNw+njEmuzDo3puP5+uvVieAAysCZ8Ppxl1L4LTSAjNtaQIIFNR?= =?us-ascii?Q?RLnRkBjCisKj5LiFgJbL2eL2AaiYlCGVKVR+sGHL9Kov/MeNfqt8kNBgwQi2?= =?us-ascii?Q?2q8O/PQ9wN5cLkXaKKx/tHAn9ulVH208FC4Ylvqsaew189ZmE3shIjg0ccoC?= =?us-ascii?Q?vY2NRDy6et5U1TWpFLThdsSd2U9c5ZHK3mvJ/CfXZId9eXOVyLSL+Eel4IjN?= =?us-ascii?Q?C4oRKEzOLsasycueiHB7w1BTW8JhQIZeoss3lrxRsWg7NHWoZ775BTTIfom5?= =?us-ascii?Q?v4n/VgbyDNmPOkKI95sthYWO4FjgaDhPEGdLHzMErwMVJqMWhy3xfdjwr3Kr?= =?us-ascii?Q?Ylxxy12A0iK1C4tQtL8psNBKuoWPy76N5gHNJ9DtMMOmCW7UjBr+fRgRZ2jP?= =?us-ascii?Q?amX6vTzjFN4cr2ZWUQ2j7vZOgw0hcspMV+zPvAR/HKAmojZ1MsAWq+a5w4Y6?= =?us-ascii?Q?nc4YmUaI/MTGESxOP0MdHHnz6jMXlf9OQ3UqXRwtI5lpgFuNCjt08Ax/NEid?= =?us-ascii?Q?A4auks8pP+yafopCulHqZh3OKHEJs1uMm+YgxCPh5lrHkf9A/sji503kx1tY?= =?us-ascii?Q?lmX/gT+igE4avTSSqvz0FahJiRpPN3UU+gtXpo+Ko8kPdIDHcsHfR98UiBR3?= =?us-ascii?Q?z1gO1lr6T8kKXLeyYNWkR3UDnEkcJRurZVtt2Aq9ibkRrO1plKn5x8NKiw7r?= =?us-ascii?Q?X1zHUEc2J8jIjz+aLsZ1PelUK67rM76tj4cnN9OUXCsG4gXA2mN4bUIK0GXx?= =?us-ascii?Q?3GkW95/XPIqfOnxwMchT5Lwoi3PPFwWOeArcT9i8ENddDgBLaoPVRVEPu2p2?= =?us-ascii?Q?ZAMLrotlQkPmC8ELLg5XoO13r3Yu8W/hv+YK7RNsODGWiIvuqufWLwB+CAEb?= =?us-ascii?Q?+BUvok2FtNqhAb8m/YyK1RGfEng36pl6VXOULUBOwPCgZ+y6DlH8PT/LYgft?= =?us-ascii?Q?lI+CeUUZnucXux4c9kHswCktqBi75ddqXyXUkBY5P7XxZ5wXtzZ1Sa/6CypF?= =?us-ascii?Q?1aeW/S+ZhONJHTTXLRVvGnedr/QXloL5SG/lLVo18rTbAKPo24Br6OyHpwPm?= =?us-ascii?Q?pWGpgtVMmu7kx90f7CgKdViF+p0E6eGW++pKKRNm7Km+Kw=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?+kQApdAsLnagX8PJGx3B7PhFVkfBa0X7vwwRT6hOLNhpdvIZS/mBr01CMI9Q?= =?us-ascii?Q?4obnk6VenLEllzIa1HdnlirquqtV44dzDh3anZ+gNibUIZ7cS6OSebKQJif6?= =?us-ascii?Q?JPcaxYkfTveHvBmPceUioORmfqzQS/SxXpw8osJluVHmq947eq9hvtFu817Y?= =?us-ascii?Q?J2852BLeOz/y2nt6NZDB6EMMDfG/kM1H3pj1IwpFgHphBxUAieDIWqiOV6Ju?= =?us-ascii?Q?JVzkOunq0woXUFIzwnE2+7AxmywK/tWcAJKxqpX21ZnlAfKa7LxMI8PE0aLJ?= =?us-ascii?Q?75M0AXV4v4ABy9J2MzMCZOwR507LO5g+Xg8dfqfh889X/JUTNCHTpD64t6uh?= =?us-ascii?Q?aHDLGSrzdo6+4BFnc+oocDhdB4VlQJZtIw+v3/LWONLVejkONOHo6/TlQfcB?= =?us-ascii?Q?yafY7ePDBMA0SEYR6a/eigUM9yUw/JfbREQqozLB+jS1zlckl2UDAh2pbJPn?= =?us-ascii?Q?SXmqHizkx65smqyP8OJewORUS6ayOHQbbxAoOXUZ7b49IZUlK7B4FOSKSkWx?= =?us-ascii?Q?0AiebKWMJtrPkatSVhUOZyeKSKU6tBpeaLJVKGmtf9z0SwMVLO9JteH+cpdA?= =?us-ascii?Q?22fTrGd1FmRCk1is8rVOEf0+dz233qt4YqVxIt3PwURBzxDsewwkKFQu6xss?= =?us-ascii?Q?XUqc5Wvs42G5B1lfVe9YDd3H5MPMiqd5dQa8QaEj/Lu8cVAf8Ari3FdCUk3B?= =?us-ascii?Q?ksJdOq2d2LWjqobjhgCDgEwJC+lNMjX9yZbHwzA0jWoajIgQKk7Hxe8mwEPU?= =?us-ascii?Q?2jmZG1LGGUWFFr81vvIaY1SZ1QCcXBO0Ng244H15FfexJk+XrLVYJ+F9qSCy?= =?us-ascii?Q?3gWuvr3Byru7JzQLMV6mc9sUp9aXzY/TS8F0ha8UgWkutMa5jffjdxP/ZG6m?= =?us-ascii?Q?qXODNJALlQe6hIhyYx55NbK78uOnbcVk0XS+2KK4WuvZUFwBRg3OJLfDF90u?= =?us-ascii?Q?6BYo5j7458zG1sy1xOsU788Mn+KBsgwUH/47LEoBCsPTaxVB4eo9G6DOFJMS?= =?us-ascii?Q?7Rqw94F7QT9IaYm4LA0JlCQRieAB+5uRqIpCV+KlyKF0zyIxeOYTao0cZRAH?= =?us-ascii?Q?BarqPF3QSIzRplKXG9n/2R+xCxxKMaWfWwJBkUUYYmZ5s0mNXNsU7cx/Or9H?= =?us-ascii?Q?5xAyRHlomdc5FKeKPrysAHQPKt+LfaqUPk6aJ7otVogXjp2tf79Lv6KK7nNg?= =?us-ascii?Q?HXGorbJVrgJqnw/1txQcy2CtXep7T1kRBFT5S3m/utY875giLc64DFxG5UEi?= =?us-ascii?Q?rHGHKJyH+hkBDdl8awgy8WEpxMSSPW9R8ljsZxViNwUoLDK3fJKbDVVNYmTe?= =?us-ascii?Q?y6ZRvRV1Dl2xXEX1dcF8lPNxHVuuSnFvlDziJqoRPufqix1nePuDojxJKF/O?= =?us-ascii?Q?zQ/Eoj/MjBPUwiLbRXHroSlulE7t+okRnjmFfGxrBq/ei6dYF/2I/p7F5keN?= =?us-ascii?Q?Ii+rP2O7yUoBNQ46FXUEWM9qmx9hmAAfTY+i39ogz4oHB7bFXcC+urfeP9gT?= =?us-ascii?Q?Ca0RZ6TviGyqsXBlB3vPfIKtuuWl3NMV+Uvckhh9jhQui8lRf6PGIwf+vQwY?= =?us-ascii?Q?nQ5NAzxlfavgCyFBXJ45Z+vWqf7A4Zb6fRYdwP9kpZV1jIYUIG8tm4rxLD+s?= =?us-ascii?Q?rG18zPM+jJr4zxHJ1vzwjlPIVstai35mQY7PBFqPNN3n?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 885472ce-9459-411c-8d1b-08dcb8584ace X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:33.2866 (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: 8WqAK42TPiKG0hwNKmlrDwyWdUmPir8lN5dWUWwkdFYAiP/x9/OSCWHuwsZGnIyRhlRwUoZW8n/3qr+wUHrv5A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- 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..e1608299a841 --- /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 "cfg.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; + 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_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 -EINVAL; + } + + 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) + 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 && (ret !=3D -EINPROGRESS)) + nxpwifi_dbg(adapter, DATA, "Rx of mgmt packet failed"); + if (ret !=3D -EINPROGRESS) + 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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013040.outbound.protection.outlook.com [52.101.67.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 6633519A292; Fri, 9 Aug 2024 09:47:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196862; cv=fail; b=cKUL/5UOgr/e7a/wl4NfCiVHQRYhJ0IVNLMod71JtaWtwIZMgKrH99zfAD/amy+PHS8M9RUe1sJykrYwrO7NcNEKObl+oNUtwcJ5sK0epbmhvi1DZM/lQS9cpFssKvxu73Xr7bzAXiFgGsXhV4bfIH8/zm550W/bX36R8DEHbBM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196862; c=relaxed/simple; bh=DDQiYReXEn8m66gnYh6BKe8sKCmgXc9a08gjrNYGTeA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=g9CKm9lrNdSWveqByViHuQXpPW7amITLblC++rDEJ4BAzzv9KKWaR+zZzr4VP34RJTmq10aJtApE5EPQktakluAB+3QD3yc0oTDLTEK8vvj4MHT0D1ztiFw+yS9JWvuhyfNx24T6mM1snHIvwHrVHUtX5uV3PQ3fNjF2tYQQwAk= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=k/NcWVWn; arc=fail smtp.client-ip=52.101.67.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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="k/NcWVWn" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=y+Icd5mvKahcSXz6z4VSBhSQwfz0gUb3hU1uvdAXPRj1miyY6tl5C7cNE2aluY5Gy8hH8bo2s59KNeeA8wXKJJ1Y08QDM1yM6O16mZav9lGf9wWfEctntsj7BBVGgBRhJV/GuSzQwAcOi94pXerZ5BRXuhTPkSkOcLmwV6dwZw3eV88JemPnfNevwEdDSHhD/9XKtALrL86A1pjE6LwEOnSbrsWj/qEgVLZ/mjc/etzzfXnDuWFl1llPZ/RRb5WMxWPOhmQNgWZT8+e31h1T2mSj66qHau1c0QZ8WmLsrybKVzJEiJAEALSNNoeU5C7ORiTdzJ4Eiq+qtLTSN1/lHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=wPYKdYedoU53SfuboJdEPF5gmNgQoeI+D72UANQYILg=; b=Z1YjspJ/kDRDUVvAzsjsu9JXAC1AW5xmw0UIHyIRT1t954EfNCKkMFjGw3x0orjkRJPgD1msZiNxhYYDLTOQ6Oh1+GgyXu5vZpTC9E+OQohrqQQsmMHfaIEaP+QedqtR45npIzWu/5Gkm/dxqr0vg8FdvML3zM9EXQXxsFkjEH3T0x8YWNKaUhQKc35qRykM6w5cePDsHcaF51OXYkhLDTpYnOhycxwQ5aY8SdAfOEDsX1wKKkBSs9QPT4jkCczUD98M46dYBZosEBS1CRJX3NO2+ToSdj03eLzWOi6w9n584v7b4xRoaKYMcx5Y46mVjhCS6gpReQitnxhZx88Efg== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wPYKdYedoU53SfuboJdEPF5gmNgQoeI+D72UANQYILg=; b=k/NcWVWnINkYFPsUfRYEojZhLvTvSktN13ULsCQk4LSTvoix9ePLJKwMTe3ZLjQB5Nxwqlp+UdMWw/LxmdzzIwUWSno6APVNfA7dAWXYg2ytUP3ixKYcram/10Ckq8f3itke0a/OlwyDXPOXFdLPv46pAQb0By3PD9K2HNEPOvHjN/3RIlX2XcgZHvxCLv5b7ruJd1fjRzcgNljOQ1Bq/kqZYR4rekQzX9nHBAQkWVXgRGXTj6b377Y8C8wxy0dU17jWayh5ZUyRRVfNKR8GbJbnTm8p5a8MmE1sVUiTtiSxrPApBG0jhgrXJ3D9JvsR18QSGt5n1TBZqAXIsL5wNg== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:37 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 32/43] wifi: nxpwifi: add sta_tx.c Date: Fri, 9 Aug 2024 17:45:22 +0800 Message-Id: <20240809094533.1660-33-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 93207915-a224-4da1-9327-08dcb8584cee X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?3d4prWFXeEiybTOgBnjv54e0CPkufRrWf50WH66HN3ycCpx+TRoWQXygNUnA?= =?us-ascii?Q?ILWF1VnfSKVrTamf/YW1WRPWWMvZpghAeFKLwFJrSKwBZR5tnUw0p6w7E6YQ?= =?us-ascii?Q?P9YU8RD3zwJdcOm2Lnu62VkWRW5X708FLVkXaXob6j/3doAKdPohkuHaM6qD?= =?us-ascii?Q?lUUqTYfKmH1Q26iVx7u5XauGgnj7eyW/W2tLkhHXY/lkNn7EVv794PIWAQo5?= =?us-ascii?Q?+CdVwmKvocy0kkEfhyOPxyxdS56wr1ruoui7oELHUow8/WCmC4SHtELwNZ9D?= =?us-ascii?Q?xDtHvMQvLELRlqRpKToxtJbjE6EwZ28vWVI5oe4FL3gNuQm98JrO3RvgcuNK?= =?us-ascii?Q?PKc3tQ9/bj9vB3UnE7oX+3GlXPFcy46LcSK1bWXXFeqFi3DrL5se35/LYvFw?= =?us-ascii?Q?49ftfSOW+SwUBv6drvmlWY1SoaS7eknYJtRLYVC9yIgkklY9ubk+oMcI1d/Y?= =?us-ascii?Q?yH1l4F7w48sSGP717BnmpwNSyf10D5wi4VygDyBfFnrPgBu6PgWjcmmJvfAI?= =?us-ascii?Q?cSgip2B8f/yPwAGjvlKS8ocPqjyiytK6WRfKhjaCfLEJYGxk+jdhznKBu1oQ?= =?us-ascii?Q?d3/6YE+wzwggQC+7mM0kbgYgN6L2rjdiRV/YOdF7KAiBWylpW2y54wpvVbpN?= =?us-ascii?Q?WeaCvKCfWIXlnKEXcETjKkZZzz8aT1s3Reu3p3TFNEz/B58M2QeiLkuHs70G?= =?us-ascii?Q?B1zcmawKbY8b5Ofe7J12gPXhBNrVeJA4UaA2XxG0H61pchcqCEWAc/YVnmIF?= =?us-ascii?Q?ngvshwUbnBRmA72bMosHEG1htmBBYc0fpmf7r/lu3Xq0cTkrCFnDL+SKXW9U?= =?us-ascii?Q?xqhaVUoNj1Hn5sKz4KMpxr1uNh3SYbPLbD1B07SJRD2HiQolSEeSZIwaayVw?= =?us-ascii?Q?4XGGwROynimvkEYsD/ki3qD68zfnttoE3JeHqJULgWx2nr1edCGVTxNH3zuV?= =?us-ascii?Q?A1zQhOE3tctMki2sjDeyHx5vjSQP2DyEPElBwUYDkRkI6aIDOiKF0HfHYbug?= =?us-ascii?Q?epePX8odnWHQig6TCBsR4V2DnrPwMMlk2Bttv6MgkREPBjNCOR10y9J+MZ3s?= =?us-ascii?Q?6juY9czEhf1//5QBwPx1mv2RvzpNvmNgh+2xfwk3oE/EWiG0qkjksGTVy3Gi?= =?us-ascii?Q?EldT7075FhdEBP7Ve/wG8kNXm8ilP44z3Lvt/8TBZ3urx3tiAI/JaqakXx9B?= =?us-ascii?Q?Him39zuiOyq4ArtNiSjmpFoDjTZIacCfkExA+eeCC9B8pWV23MPGso7x8ovY?= =?us-ascii?Q?AAiwq1EgJHkVCd1rkHMvD2PtYEW9nKTRYmPyCabEX9LtC/pj9EPe0LlySidS?= =?us-ascii?Q?tod8x4VEe4mg92mPk/GEIlAiazseuOy27+yHRHWfbZnvdQ=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?dXl7Vlc/sIaqJBGRiNayJZDCbo/rB8Tv/SsskeF4Dwo5GyiescgYYhBt+Io8?= =?us-ascii?Q?kZZMQov/tfP50x8kHK3GlRaIJXGD2pSF5AcAp/QZEgM40x/nF6kee/PJZT74?= =?us-ascii?Q?gcDRWRLUWji6wE+WkfkG8WsunBk7qFtke+WJa++XakGuUV5KbaLb9Yy2lhIb?= =?us-ascii?Q?q4wpOi6t8Stdfawf4LozWuaIFdQPWE+USh+tHkS0p8bvU6E7EKGN8PgNIHss?= =?us-ascii?Q?9O9vinWJtiWt7t5n1XX2GlLbD4s2f89KPd5wyQbdUSEE012vAOt2WHHRsXMW?= =?us-ascii?Q?ux/eD5HyjjvIEanjkdqNPiA/luhrlclEAFFtvJrCpxnz8RiEo5maRuZ7jIHb?= =?us-ascii?Q?EIwpMKZdmioxfd6TSi9xgRpHV3T7USsbBbzqhRS5X+di5ZLkPcCbYtiPaky3?= =?us-ascii?Q?/9ctHRa5NUNy6Bwd8IICo5K+i7TLton8lifUzyoyRdcVVyUapG/YiUA0oniH?= =?us-ascii?Q?yCjEDgIupYdEpmkNbFF7ugdeyX9biqlRb3T4GLktHauy7IC5eWRlXpnmFL0F?= =?us-ascii?Q?5jHQi0pT5awQwra7+Ln1DQGIQe3kUv+QG+CPS6kXDK47pwopixIwYGSUg8bA?= =?us-ascii?Q?4UvDQdq3BKR1oOwGcKzgmMolkxDu/2VobefluErorngYRskBLsxNyMgFoGQg?= =?us-ascii?Q?ywj713RtKmdRzNp8PPzgIMzON0hZ0e+4M5CZNAeadS49csMN66elMY8d/7Ev?= =?us-ascii?Q?54Olhx0+xzOFxy8304P71wVT5deAsRgIBI0RfYghpP8GIiZpp/G5cRdFAyyB?= =?us-ascii?Q?YsxL3q/Nwg2q0+LUp68Wn0DeeAJL1yw54q/yizu5SUaZBkhoy2pon7yEFara?= =?us-ascii?Q?9yamzoEa+sIK00uT5FD4Vvkzr9rdAiM1OpYf3CXPUpcQQUKmsFGWigapEFTK?= =?us-ascii?Q?dasoYptXyoKBDNFXN3sChQCvD1tx6EwWDWsvisY3w6dcsi6hABfjf4SAf/Yk?= =?us-ascii?Q?ATBvxjKImWPZ6EdXzcGXxFN0U4hJA6NZOt+2DAcbQzHjukAIJxGb6EJ5mzRO?= =?us-ascii?Q?27CUZlAVYZKtNxe8MJfNJSeX/aBL0ticEroR5cc/xaFLpr1lHmCiAgXIPnXt?= =?us-ascii?Q?CvMljtg4pZtYw/CcCRYkNjjqhihtJsqNVNlmHllOV3EtLrGrhIkX74mxt53y?= =?us-ascii?Q?0R3XQIm2vwVg1w/w6+51q8iXeGpqLBCJ+MrmmBPjFV+LC9nat+vwiPFcYu9M?= =?us-ascii?Q?XwFqLuBKMZYOgU/D49PWJiH/M92qVRnbJRHEweCLEG/WrynkSakG1fteeYca?= =?us-ascii?Q?lj57QeuBbqm0ARKmK5w2Pw5O6vdVgIs8RWQzuc3LVRfhjWXKbjJvMPNyB1gA?= =?us-ascii?Q?/X3cSSAw6yGHKtWK6wXykCd2Z6o2jvW1GfPUZmeR6FLGM2VhFUxr1ReoENFX?= =?us-ascii?Q?zwk3dONdL6HWkNA5Yn6Pj2+96gYdqY72VE7U8meJk4yZk5Dih41jz1ye03mI?= =?us-ascii?Q?iANxmUkemHvTQm11T+Sxqlw7YrCpiK/C7ytCXCop4XrsLUpgSUkUQP1Yq91t?= =?us-ascii?Q?IVkHumdtJRTmxvm11JT++8jrRJYPAxEw2MXqHibGtBZM1VbW3Y51zP2umcxV?= =?us-ascii?Q?FPL+ETiubs+qwtp1BQ94rhP3YSLhneu8iP9F7k+Bwmf/hGQK4CkMueVFqMph?= =?us-ascii?Q?8IlBDS/L4MWkMYfOaCzSVH2jPRWdy9xVBV8bYO4ZKWF5?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 93207915-a224-4da1-9327-08dcb8584cee X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:37.0233 (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: iFHVDau/7EgUDNa6dRwdAmJG032GlE/gqIqR9APX5YpiawVU9/ZWGnwW6iMzw7Xh9xOSjkhu2qB5AUISzQEmcA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/sta_tx.c | 209 ++++++++++++++++++++++ 1 file changed, 209 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..f1b686ecc843 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/sta_tx.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: station TX data handling + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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 -EPERM; + + if (!priv->media_connected) + return -EPERM; + + if (adapter->data_sent) + return -EBUSY; + + skb =3D dev_alloc_skb(data_len); + if (!skb) + 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 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 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: + 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; + } + + 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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013040.outbound.protection.outlook.com [52.101.67.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 3E13A19AD48; Fri, 9 Aug 2024 09:47:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196865; cv=fail; b=jIOyokGQCJzgY56oDo9C7FXn60X/6aAcEKb3CxW3B7EQjSGrsWwgwCNTBp0Pm797FttpWSlAzHLxP97bHgPD5OOSkdntg3hCja+JOYszkDbpiFM/3xo/wUeI1wI2xteyjjtkHQ8wYzIaSlRsH3OSIc5PcGJUjNwrodHFkNroyl8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196865; c=relaxed/simple; bh=0foHhzZXDVtTTmtALmLNAKsobPNH8aCc51X2vIiJAfA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=QC1tbS6ZwEibJrnmqnwSSoOS85ffnF2kssAX+MJlGiKIlCBZPdWdwwuh3vA59Jq0cwzmEvnKbnY30+4l43gtTgpIBf7KCglVEYj2bhWqPlsymx1w5r5A6Z9QuxJpNom/kTDrA8gIj1li3h9atts9dMtJOvqwUBsbiACDj+Vhhts= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=Ui4sjTLu; arc=fail smtp.client-ip=52.101.67.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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="Ui4sjTLu" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=M3012qx51JYs238zSkuD88LBBTCP6SlajjU/V1o7oMjSyeSfW3RF5sRp1u+av0blchMyunXYfmmGDED8PdpMBUNx6N3AoQHSf0KAz9gT+zSqjQrmG7vad5yzK/VwZGEt0sqAln/6qtxf8fCdWmawLnRxY3o5sKtZd18QIbBfFoLr5BY1+I4aUmEqGxo6tFpr2iAHo8w+NNe/Wa8b0S7QNvqYg6fiPY/y6lSeZDTtD0Dmgtykada2qIgRSQIp7EQvQqN3lccKJGHMtjvdTuGZLMBPk1p30ISYtWq4CJyKz1rH8sxURLmr1Axjg8w9pxlZ2qY6Br0JBPL84HvZuvFnew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=RjdDSqhEjpHYUdYJjHVZDVET+mboUoj9PnFSwThXIrM=; b=uVP1awQKEBn+TZACKUfVYhHN5iclQSSCIgwJvq6x3+RZI4GxZr0jdOU9qJuT9hEI0tNpHF3m0Xdgzsw0Zr9rnnHNq+pNzjhDcXIE9KILz4abtn+EL+9vOmFk98Pdtb+knNm/rMUwM7h0eXMSdQ/DD1+9p9/uE5za4CO/13HoDJisfxexbbcdJaEBRO/owsWLFy2vEIE7OVPN+dVbmHrX2rdMgAVzWJbizR/Ibp0vL85GMm+/4cefH8KayQS9XXN2u26wCZfUXfepuKw57DQVIUlkxgn4x0UUKD/B9Z6Q1dIbTkHPVXvIm0Nvfrlo3BlFRzthOOyzy4aLrSCPOBg2nA== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=RjdDSqhEjpHYUdYJjHVZDVET+mboUoj9PnFSwThXIrM=; b=Ui4sjTLudNudQDxMp9OsMopkFHRLGA6dn1Y0VJxPqQCAmUaxpxWXiTvaL+dyN7OExlXs++OLo95W9nrXdodMce2DQF2F4wxdplgf4ScnDNIS7oJvR+2jl1ejpjw8KImECC+m9/FtvF/LgjS+C+blZpTvsKwy+Uy1aJp2FjHuDNlNqTt4bYf9b93JsIJILpiKgPTB4ub97NnaBbNY171QW1Rjwqp59Q440jVHyBsW4mUeUaJ/6aNiUjPE+/40pPTWCyyvRoXu37nuN1CFIhH8vf+3RAj+pVzP2aWRmUDUExoF7DbBZE8ZEDcxBZFO4AD5E+KsMCxw4VZb+ezrGnk6Hw== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:40 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:40 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 33/43] wifi: nxpwifi: add txrx.c Date: Fri, 9 Aug 2024 17:45:23 +0800 Message-Id: <20240809094533.1660-34-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 63a2a05f-8999-459c-45cf-08dcb8584ee4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?PK+ZR9Hzm4ivHhwtbbJysvYKGTGoXqpc4nV2DOotampQPQAFHZDGBltTtprT?= =?us-ascii?Q?aO+F8A66ffTyjidNfyA5gWeQrakQUpkHT8OBwdFkSBF5JD8m9Rime68YyEjj?= =?us-ascii?Q?rciItYv+jXV3AinnI675dclJBEgXUtCLosdJHFCwgqW8sLiCoNQ0fFJGVdLx?= =?us-ascii?Q?Qve0/h7GEmioTas3xdkANONB3gWMBKLxQg455T8jWgY0NIry/3gJXY0DK4rk?= =?us-ascii?Q?Gr5Mu0zVFhMCpKpaxCYIyrLD9UusIG15QcfN1tYqpUqAcrpxDdVxVgZivwTP?= =?us-ascii?Q?nOaxKB8L2hW53GywIWtSvk/RrKnSyBUxJYoROZHU/mFBHhlJZG6iFTgIZzX3?= =?us-ascii?Q?krDx8EYiaCjknZYlmJS2vJex3PpEBpmciE7dLx/OKAc+NJJy3G4WWTKR/9wM?= =?us-ascii?Q?1Xyb138gR4W9/ez0nqi4yb2WBHx1F4ZAz7dr8IFOgijRAtKjZ39zoBW27W3u?= =?us-ascii?Q?uKtAg/p5Z0pajf0u8rRtqry22ATRYdlgres6/nioZAyWczRsjelKJYyXi+Et?= =?us-ascii?Q?RFUhnabyw/XuI4rlXNmgsaRwvEKsqbClTd7LD74DLQTvQmgKFW6ZEHec7HA5?= =?us-ascii?Q?slONwptcxDrxklpSIFiTcxJD/Rbgi2Tp4rTqt0rXE0leJfMdhg7H3BE5Y/Yi?= =?us-ascii?Q?n2GOKPFoz5s+sTEt0gjD+0B2oeYNuvx5r7C/VTJZDyfj1q6GE88u9ehWW04U?= =?us-ascii?Q?pPBcxoXQEed75LfBgpSwhbN096A8jZ9Yo2SkcoWm3jYEqprlIoOrMIgwa7u3?= =?us-ascii?Q?efvCK6qrYFRIW5tivF5EzCRRUavNeM0JaoC1xlSexx2X1XfVgYWpib7DYZl1?= =?us-ascii?Q?85czo7gSqktRpmRgE8zg57EMIye6S3ocBes6Cyns1Ao/q4W2wBEINy98pn4h?= =?us-ascii?Q?6OfMNR3YibycWvSJv+Qt5uRYlkF3BX3GrqgihPlGE7k5SuvEAfUQQHaJIL8q?= =?us-ascii?Q?dRiKp+XmRk48EIapsJw0gKy7MhfMQVK673qG9W5GHsozTTVqZSSjRpIDVudW?= =?us-ascii?Q?I/FmGnM9I3HMTJIIw4OBQsnhmXuXke+Fuson01Jccfuj7eBDfJtAXRFDll2Q?= =?us-ascii?Q?B6vMkJ+ZwnsqicdhQaNjjkZxc85jFYrNZOzob4uVq2EfbXAwOomW3ZBsj9Sa?= =?us-ascii?Q?YjYICmY4LY2iuM8FrGXaKjMFiTVgcjw5l0ISPnSfslIy9h1pooXlVTtHlDXN?= =?us-ascii?Q?T3GjlJFLoh/gR/IpTpixApHY56ERDKiiWXBGr0iJU4xTjfen0f+yXoyXEtDD?= =?us-ascii?Q?PuI8Q5C3Ki91jexbDjl6zvdpK/HEtb+h5rO1mFwQiMwF/ZzoTfvbg3D6ngSn?= =?us-ascii?Q?tADLJZ12TUnsrWxE2jUIzPTTq/oaSVsGNV80QXme8aKbbw=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?GD8ylD7Cn002A6audz05b0wW+86w787vg0owX+UOhTCE3meQnrrEJR2LcZZW?= =?us-ascii?Q?dUYcHdzAsNE+nK4XrE/LlEjT9aRTiWqzm+ikAWSLGMUoONvwliOUpF6PVUiV?= =?us-ascii?Q?6XyM7hF0jtNalfEWpf6Tne7yNf4iD34FMUeZKK650BrldwdyWu21WGfqJCG1?= =?us-ascii?Q?Tb6CmpQOxBEgWo9eXnpfxnZ8xcwtnXikk56ni/MmVNPCeU45/TGhW8vOk2WG?= =?us-ascii?Q?IlTN0KiuTE467m9TK88AX7kPNE7kIekl/25TP2amhgX42mz7bOcDl4oGo4Rg?= =?us-ascii?Q?fdO3IamWQgMzSMySmbPfwL0Qk5odIxTLBek30bDRJp/jImNgZDAs+yMoQeEN?= =?us-ascii?Q?SfOLkUzzyoOIUMT2ybdr5LmLWlPRHrPGlAmEs/tewqoH7F2naP5j75NudKtl?= =?us-ascii?Q?r8LWgMBJgPk/03M6+Yc9FC2ipjzHHnmX5Yekj+lEiy4Mi8eFBPK51LtsSK+E?= =?us-ascii?Q?FeFSLhqTjqGrohw6gM8hErn6xt/jLoh+SBMcVch+Bengn3rE1S/xYL7Suvzz?= =?us-ascii?Q?wwGC8w16aqgypgWiEGco+GJd+VRiAZyomp8MrgduItpye4Urv3cDRhlJ4V0I?= =?us-ascii?Q?WVrGEUi2WChvYIbYyUGsCbzUj+lV8piAxrXPnGBvit1XP8rnuLknJfAM64Xp?= =?us-ascii?Q?TC0Nim3huXnQZQknPN+sPoAu+YOJv6bJ8EQo/bdezrTvb1rqjWH9UAX6BI+i?= =?us-ascii?Q?5MU/c+CMFvD7tVznB04z+6WA1hM/t9oCJsTZfqUkdv/ZKVKh0wl2glZwbens?= =?us-ascii?Q?PO0yrOhwOtUBm87bAdkrT4gYz3aggjc/EQ/V1iiTuMCibdh1Yc9liiLyGRCa?= =?us-ascii?Q?5jvUt4/ttYHRztfaRi9fd1Ww1vMFoC67bT1gtNStLHHsLCfbKD6jslfMVk+A?= =?us-ascii?Q?dDAM5vPmUB+f+k81bdIRC3+PBlEFZc0lhiRKFlxbSViceby1UkH2o/Cja3pU?= =?us-ascii?Q?bRONEEBc+hwXJ2KTtEEns2FsxP5FdLgeWtISMWmCuak26bTiIdErSt/QTQ7i?= =?us-ascii?Q?cOfSMbzoDv5WMzwDymK0Y6gQrE9Wv1g8olCv9S7i5NNkSe6c+57vptj9cKRX?= =?us-ascii?Q?WVPeXM4wutwci//E1pMvUJXXP9/LEtHYfWnk9sCWX10vGTv/siLN5QKusW6B?= =?us-ascii?Q?4m6dYdpG6cZ91f71pR8FzsjeuszWwxTRmYFNb/cmAur7YgnzTVxZBEsrqB/3?= =?us-ascii?Q?zUWW9xUmIv1027atb35bFJziNzxyuK+VIXXxOEseU12rwG44oAhJIuXqPKS5?= =?us-ascii?Q?xSae7AKKJl/g/jbYokpF06XpqDENcVLnq5fLEgZcMrfbVZl3Lww88ygbsF9T?= =?us-ascii?Q?XDc2ao9XnckW37kKteFHCXj/e04xJWAjS3HdcVeaB7fZ8Y9G247YUghtuZuu?= =?us-ascii?Q?7CQ7k1IzzfPs1DC6XdT2RsYatbqp7VLl3tETEAqGTmUSqaqw5lBjRuAp2oK2?= =?us-ascii?Q?7j4ONYNEWKxDyMMpoM1bXyPcF6dBV7McKI1Dzr3FjVnup0PizpciK9BMb1YE?= =?us-ascii?Q?xUJufP1YL3Jb9Q0jHm93Qxa7OFNrJ84nqJw8c+UWHQQAhKAtoNGDlnZu/WdO?= =?us-ascii?Q?U4rqNegkKo726hl4ReZQKfIXedEcXLZqjAuV0xWNYNw6dxARy9YOSWFt5+sH?= =?us-ascii?Q?0ZThe3zMJXvmW++ZNOWcx45OrZZyNkB4fQAxRR5j4D2V?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 63a2a05f-8999-459c-45cf-08dcb8584ee4 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:40.3321 (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: HsIbmySnFunsEsWEmPYKrXlyutg/AQS66wCvoAPIixEZ0BPbU866C2pSK8uhNX5JIiDwdPligSLfS2vjyfSQ4w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/txrx.c | 358 ++++++++++++++++++++++++ 1 file changed, 358 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..860c88bf8ea8 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/txrx.c @@ -0,0 +1,358 @@ +// 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 "cfg.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 -EINVAL; + } + + 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 -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: + 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; + } + + 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 -EINPROGRESS: + break; + case 0: + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + default: + 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; + } + 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 -ENOMEM; + + 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 Sat Feb 7 11:38:14 2026 Received: from DUZPR83CU001.outbound.protection.outlook.com (mail-northeuropeazon11013040.outbound.protection.outlook.com [52.101.67.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 0A70B19B3C4; Fri, 9 Aug 2024 09:47:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.67.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196869; cv=fail; b=u9xd6Cwherb1m7p3QeWPNfROjyMrrPrDza+coz+P2Sx6OTTuL4gMJpuO31iCh7VwHSxOl2bdqmD3L2yE8FLY7zkbyIEXeFpig8Yu8ZZaaQR5GWWQjmp7EbInAfSkMHvcqlBE1Ko3PfU5Xru22G3hP+TmQRqZ1RmUg8e+DME1bDU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196869; c=relaxed/simple; bh=mQMlMVVESn0FnuvfHDNqswYDdHOrIVEn+RNZKqsKAAw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=qoHu9moiGGA0c31E+JL622gXdckrvb27nq7wwbA6dCbXj08lqecfRKFL6PcmTZoTOemiCzkdqnoTgToxjNxb22lVM0qnbrpKncf/+VfOfgwK7M+70qud31HP7c57xm2fMnp+j5dLP3JNzGUysnq310LPqQgFQTawT0JcQsTY8Rc= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=fvL1mIBk; arc=fail smtp.client-ip=52.101.67.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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="fvL1mIBk" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=gxyXeEKyk4u/To6GEE6MTw0rsRYL460CsoNyQov4huNcwHg4YCcCrCG08ETxrrsTlrcNSMgs94FgtPbSHicW8P0kOxkZihV4D/INvrp5CDfPion/pbPhL6d/SeG/s36kceUXS3fkJEphSt/7PnXpq6Y2AY4p/q3bmP1+NY1HIlIJ57wKPFFwUEreWfcTZDshiHz/beBALT6w5fWDEyK+LDw/BcXT7jfflGWYj3piuhISmDF52merKb9u2sIDf9D43CSY56B84E/xCO7CYZ3hiQJMCG3R6JMAUW6Q540VKHtsEtJ+aOBXFt15+d0+t4VyJ1JCQq0ibJ0GBUBpfmIGjg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=edEx4pIjp0el0wyJGuwFGwTxMJwWiWDH+qpmn5Srf3Q=; b=IRq4D8Gae/VB/ci8qISW++5oHqUJc37Hph/drBVy6QoTRVQPeG5jvet/Ae1EejkdO8fI3VW155O3+iKXAxuFspleW1+uvcCsc8G7YZmpwVOvR/CLL1rdLvraW3UrYOeihJZJTx8CftZxV4kzT0Z0oyqu7UwWXBcgGX3YuI5QmuoSi4vubVV2X06Do8FrO9+Y5vk12/YEU5BZJhQxLjmnTEz0EdFdPVVjx0TzI6eSGJrpX/SSLqE/8QBuf80xeqG78lrljMSNjfSYZsa4eXPd0rHizovFWrtOlfhoYRqC+lbsUS6/riBLPNhBvB1iS4s5atQ41ATQgdyh6Dc1cDYwvw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=edEx4pIjp0el0wyJGuwFGwTxMJwWiWDH+qpmn5Srf3Q=; b=fvL1mIBkrwI3GQFu0d5vXNst8JL4+62rd0+wG0IG/4Wnl0MxRFpktg26mZhKtKtkorIgRfY9C2L90aPW/nJqM/DHybFn2s1g2JorAqmkM4pBDXDeO2fCCKvR3TulHvx8uyc0sV9/4W6Tsm6szofFtpWd3ZGcKEuPI+TcTbCSuldzt3CS7aSTg0wHnL17FLU/q25mVHSjfEoHqs+U7b1mtyzfl3jJz0svsFc77SLA75y/oS5bHkI3/jGleddYDyUboNRgcTshr2ecrul6ajnOwK5r8VPXN47/l/vkM2GvJeAEnGLI5mENKXCkAAiK1kZTdNeNZnTOt3g5WEGhpx/GsA== 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 GVXPR04MB9949.eurprd04.prod.outlook.com (2603:10a6:150:112::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:43 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:43 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 34/43] wifi: nxpwifi: add uap_cmd.c Date: Fri, 9 Aug 2024 17:45:24 +0800 Message-Id: <20240809094533.1660-35-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GVXPR04MB9949:EE_ X-MS-Office365-Filtering-Correlation-Id: 33e03b6d-baf4-438f-dbaa-08dcb85850d5 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|52116014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?CksC0cQPgOhv2s0HH2zaaeryw06F69T3dHdCtKBpte9yfKYYX+1gDuxkovb8?= =?us-ascii?Q?3PgFqQkeeS1sqNab0Ry7D6VuYPKjXAz2S/r7RUhVv1xJ3e1LFCsOPvWyEJ68?= =?us-ascii?Q?2qOqwg2VuQJ8yuBbDYZ+dFO6XN/ENxveTYq8g68z5QrgnIxwD1v8Q0Yqg7a4?= =?us-ascii?Q?qqZPTUMx9ByJ0aFlj9/+nJPSE8VyQzz1t5JnkNLPisjGWi3fB4OAkzS0EBv7?= =?us-ascii?Q?2q4yKCbJxKcl4QOvCIIAXbOjreBlSzwz9d5WH2YWToswqaSXLWwykT2DTKKO?= =?us-ascii?Q?NtSZVJHRDFUfzwQTA1XGQ3EYTIC4CTRkC2kIKZIi0Tge9J8eTc0Xo6kPVCfU?= =?us-ascii?Q?1V1RPbHDC5hFWQdbxpGes/CTRZjfnVobgsy4cvk7MseAlwXORbS2+x7ThAKe?= =?us-ascii?Q?bVaT2GiC7NUu+KNtHdgDocnIAe7IOSkgjRETIL6H5hgf6gRCT8oD1xZNmUDa?= =?us-ascii?Q?fRBPQkFuTJspb81LgFKQ/2t7q+30n7oj1SZoFRWXbCo4Dhd9vcAB+Nzcu58P?= =?us-ascii?Q?yVBaVbwIIFqtHFdkpAcfzT97ktYjJgpcdGv8BlRBTgVDGmD6An2zHHsqKQib?= =?us-ascii?Q?CZZv1z/GMGRI/Ix1KCO7CPt0S/PnWvUBro69QsBlsbLGR0OP5LyjKvgtCMPk?= =?us-ascii?Q?OHsYxsY9ogKag7jEqzrO3OgNChA8l2wjqAK5EIIk9nlaAC/R67MhnUlPTk08?= =?us-ascii?Q?2BwxsboHij/NAaFGDE7G2l/g9Fwpj2uHXJ6lQQ/yKnAeThypDuXv1ZB5xuz8?= =?us-ascii?Q?O2DmxcHuJiLmBr5SHep4ufYWv10yRWTukbBY3xi3Rw657alRUiws4kZrfvk9?= =?us-ascii?Q?L5xFUuCZsDnO/Wm0WgW+2rA4ZjxOTEt0j9gAmSZ+opfl/lprt7cpyrG3nNl0?= =?us-ascii?Q?HDrUb/ztpBXoDIiPuOSjJG6riS7dTEDxYYafQbxhUFHh3qI708ALtoQKRgs2?= =?us-ascii?Q?V83r32QgFaIc9zovgEI/xn8Y5byrCSguW5RQfv+xHBrvYwY3+pK5BWIWVeYc?= =?us-ascii?Q?UTG2/o3pwJf1Zqf6O0XC26UlMfU2A6a5Axk/3QPJ44aWfti1nNnqcI5QOVqL?= =?us-ascii?Q?mXGnBUl4QJRFGfPZLLtCQnNzWt5ZMbxzqpHE5xqdjIDDi33A655glKcGJ2GM?= =?us-ascii?Q?aqqoAV2QhBi2JDR9d8kEuTfpGohCxmPc9LVSx7j/cUHQY4CoT04KeL5Z4vzE?= =?us-ascii?Q?FQWxQbOfNv+R146NZ1ujcaCVfOYfETcIXhVx8R84B8cdPgseiCrqrvgocNlO?= =?us-ascii?Q?bPCTtMg8DS3I/ORTb8kTQyqW6vhDYkbZjRcxL4ZSCSidXaDIwaQ8r48/e2b5?= =?us-ascii?Q?/ZghoI4PV89dtLFu+3yCGFX4Hl0iRcMtbC7OF+lKwLUHYg=3D=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:(13230040)(366016)(376014)(1800799024)(52116014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?zpr6oICATnLR9UyuaWM8lYVmSzbyNwHzltlnrYZGUlidZ2Ddpq/qvZNbCoJ6?= =?us-ascii?Q?FDf+3dPtu4MZQObvvhE6JJnBo+Qyq3xq6jUcwC2PEgNpUTIpWTKkSWik81iA?= =?us-ascii?Q?0B7Ieo60j16xDCKckTFE21TRGwImt5vvsTvtQuPiCh5VZIkrkhJIqKB550e3?= =?us-ascii?Q?7xS56Bojx0lUBm9YXf3AWSPjdFRK/OA/3X1sOuboyL68dyQVHhJ/knLUvmCk?= =?us-ascii?Q?e4rypAR3EsXrBLaA2Tcj3Vrs8m/8WVM/SyFhZnA4hvlAZmQ9WP2mjDBSDbXc?= =?us-ascii?Q?KZ7lsYMu8sRYslSVNOLvD31YZfLk/CI/fERm2Zo+eG4ns2Je9jxWIbJrucvn?= =?us-ascii?Q?b7qqOW5GoR3UB6oLU+IcBIupCISJ2S44cqXDnXy/iSwprZQPxeP5NYX/D/pW?= =?us-ascii?Q?u+61EWlnD8SjvUTkLPsh3tDoIrDOfnd01tCKRYj30uemebTLdrYeWLX7XfaK?= =?us-ascii?Q?wmryrRLAWUu9xJgXUXDUpAErj18O0hBFiVEjQbbS++gZ0c33UUcP9RgNqS/a?= =?us-ascii?Q?nM4ZiJfFk+FvXevXBuMfkncn1mQPnnPib13sFobRl0HnCsFcFiU68RQ4wGY+?= =?us-ascii?Q?NMkvVvNvTTEV4nh3130H1yi91fOUpUKfqRU4K7gfB7oHtgji4GTXvYLh+4/u?= =?us-ascii?Q?mwJgCpm/AgMgOuRoBOpc+t2rG4Ttt0ogJc+8o+3+cWAEl4MtOrc3phQc9YWX?= =?us-ascii?Q?0RcknR8+wXhVxNgWHwY+VtGt8+pSJkOLL4ZWy8w/cGEOc6Zb6J4mNfK5OuCe?= =?us-ascii?Q?grh6tfcme5Fw1jfis+d0Vul8dz4odv3FZbBFPVQJ9LEKjKocmb68UyrXmKTV?= =?us-ascii?Q?3oEV5gnlMkmuYHxOVyCWm5piTjEs4X77SDJRZRrcA8cNGrWI5UH6EeKwjqYs?= =?us-ascii?Q?sOwtiIF4r/O29PuUD82p9Y0egY17WdcVmYquTzFrDoWaOmsbIqStvqL4T9LO?= =?us-ascii?Q?3khSFCKE+UzN5qx4FLGMhRhVWmK/cZ05i6kipuGTGPIkvvnCoWiY2fwwZrbW?= =?us-ascii?Q?F2YnGm+9YCM36XxBMsbo5mCjWdPQbVEiXHvD54YzrLt4UVXNRp9apEse59Yo?= =?us-ascii?Q?yz6i9WReqJOBfYKI5CZlb+4mcVki+HO7X09deZwq/L2oOIDvcTaKQ0NZu0ih?= =?us-ascii?Q?fcH2gM2JXqZS0VHSOfqUnBhzbQVOWGPZ8JF49pMAPTOhz3vnbIEiIVhVqP7N?= =?us-ascii?Q?rhi98DTSiiT9dHEC8B6nR+TjjQY81F9kczv3IJh7doOBFyt5meD80W3YfocQ?= =?us-ascii?Q?19ks1r+Rj9IZdXGBm2AXEvZ37vm5zvVgA14pwta/B0fINj8s67d4/UM8rNSm?= =?us-ascii?Q?MXOOMVEpT7J0ayYD+Y5WAYq4X7xnvtrTClapQ903WaXKmrie9k26I2codWMU?= =?us-ascii?Q?33wktLrM+nEKnfhsH2rL1wsELvCrkD8g4O7rvAcqeobjbubh8wvzO0oKghpN?= =?us-ascii?Q?0bKYD2ZvhjLJvbSHt1gi6bqGMPw5bVYI2Z9V42t7HSKSrBTnyiZ4YOObG507?= =?us-ascii?Q?XYInL076FHvFH5w2x+oHLIXxUTKWuLt9TKQ6WA4pNefQ4lwJrxSwjQSYwg2q?= =?us-ascii?Q?nidAsDvyETn1sX47N7+RpUczR7q0/xZ42MbtB3OqFGW9i5STeOboAEpiQ1M6?= =?us-ascii?Q?i68KK6Taou5yTi9FnKnNOA54s/4XRsQDLjzpTuUApp9U?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 33e03b6d-baf4-438f-dbaa-08dcb85850d5 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:43.6406 (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: 2PFmreIi2lu5WS9o7q+c0c/xATMKp1XFWaIC6kT1tm9Vebwl/bgVGLRoF2vFskbamSzl84wNhyqFYJxO8YJsQA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR04MB9949 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/uap_cmd.c | 1169 ++++++++++++++++++++ 1 file changed, 1169 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..0b50f842c8f4 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/uap_cmd.c @@ -0,0 +1,1169 @@ +// 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 -EINVAL; + + *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; + int ret =3D 0; + + 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; + ret =3D nxpwifi_uap_bss_param_prepare(tlv, data_buf, ¶m_size); + if (ret) + return ret; + cmd->size =3D cpu_to_le16(param_size); + break; + case UAP_CUSTOM_IE_I: + ie_size =3D cmd_size; + ret =3D nxpwifi_uap_custom_ie_prepare(tlv, data_buf, &ie_size); + if (ret) + return ret; + cmd->size =3D cpu_to_le16(ie_size); + break; + default: + return -EINVAL; + } + + return ret; +} + +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; + u16 cmd_size; + 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 -EINVAL; + + 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 -EINVAL; + 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 -EINVAL; + 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 -EINVAL; + 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 -EINVAL; + 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 -EINVAL; + 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 -EINVAL; + 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 -EINVAL; + + 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, CMD, + "%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; + + bss_config->protocol =3D 0; + if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) + bss_config->protocol |=3D PROTOCOL_WPA; + if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) + bss_config->protocol |=3D PROTOCOL_WPA2; + + bss_config->key_mgmt =3D 0; + for (i =3D 0; i < params->crypto.n_akm_suites; i++) { + switch (params->crypto.akm_suites[i]) { + case WLAN_AKM_SUITE_8021X: + bss_config->key_mgmt |=3D KEY_MGMT_EAP; + break; + case WLAN_AKM_SUITE_PSK: + bss_config->key_mgmt |=3D KEY_MGMT_PSK; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + bss_config->key_mgmt |=3D KEY_MGMT_PSK_SHA256; + break; + case WLAN_AKM_SUITE_OWE: + bss_config->key_mgmt |=3D KEY_MGMT_OWE; + break; + case WLAN_AKM_SUITE_SAE: + bss_config->key_mgmt |=3D KEY_MGMT_SAE; + 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 element *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->datalen > NXPWIFI_SUPPORTED_RATES) + return; + memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->datalen); + rate_len =3D rate_ie->datalen; + } + + 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->datalen > NXPWIFI_SUPPORTED_RATES - rate_len) + return; + memcpy(bss_cfg->rates + rate_len, + rate_ie + 1, rate_ie->datalen); + } +} + +/* 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 element), *(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) +{ + int ret; + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_UAP_SYS_CONFIG, + HOST_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg, true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to set AP configuration\n"); + return ret; + } + + ret =3D nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_START, + HOST_ACT_GEN_SET, 0, NULL, true); + if (ret) { + nxpwifi_dbg(priv->adapter, ERROR, + "Failed to start the BSS\n"); + return ret; + } + + 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; +} --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010001.outbound.protection.outlook.com [52.101.69.1]) (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 AFF4819CD0C; Fri, 9 Aug 2024 09:47:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196873; cv=fail; b=mj54fnlCyW+r3dPQ3VI5qdXOrHdEc6Crej2xjQa8+8uf7ZryT0LcTQVVu9fuIUhqR0jlWsVZUOBY3r72d8XRP6O0Juy2BH1gET1RUOUpuTNxNvVEu1BVkwl8emvn+OUdVdJxMtuGHNrkh1Nkl0d2XZNaCabM8HlfzACRgYR3+Rk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196873; c=relaxed/simple; bh=nmm00EqlvqqB9ONFL77FJ4LIqEcU0BeA2BVvF6WjoQM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=KjaXx+0kNazw4OWwVaPBmyvZIcr8rqL6m1DipAr5qlPmIljw1au7WgLeFPs8zp2IY088VsJ+WzokkfUnZAVM8BV6jgVNT05LffAHCc4WZY0kbNBm9NAu/9RMfzYR+bhiL9akldDlbBOXm879O9FEjgbhT8nrG7nElwS5Y+3iUDM= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=i1bnE84F; arc=fail smtp.client-ip=52.101.69.1 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="i1bnE84F" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=FCOGkSJSLR9m5m4mr2GVSmkoMTfZwUpsGP0b//a+wrDJlcNh+cYCM/SnCu14MWGYdbTwI/9ZymJGhjdCKrKGCi9Gr31JWa+i+1oD3uaSp81D1ZNy0VmIgriTRP0zasfVyHYA4T8ImL+VrH3C3B/YbC78DCWpxZy+y2GYmfMrVaPFj79uPZzyQAyw7j5RQJOw2jATK1g4sK1KnmUNN/JIHHADrc5PRck6+VCHeqq4KzoefWf98mcrkDO8Jhf7lv3Dy4EIbpc9qgsH71k4omcDqQcSYHN1BiPENww/Ba9B2adpTjeRQc6ubiE78C75y1iL5vBdJxHAX8XKJsj6GyWZ6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=9Ceh7Hex2+aHv5fXQbSM5/PyD7L3CEEGXLz4AOSwpD4=; b=cbHSSKH4DxD6WMqNUAO9/vTVltXBlEN0HHaiS51WwmH90hsZO1qszN0N6H599NyGROyQ0UEVHKnZH/GmppN/gqu+6c9DUNHMs6AAuTBA/sY3oBDWUkhVA28GQ2optXhyXtajgqWSQQnW0FrW5XvozzkTQQ2igZnhiSIsjEbNs88iCo5Z4BlqApNE4/A8S4CtpXgnkQFrNWc3xVq+gWTWII5rudA7iEAEzOoKqnw+o4GscOInC5yDgR9/wXNDUE5QbK9bzwYO6UxvYfvunhQMC1J9Ea6bl5sEa9admKBcszuM8aw2BtiBHCHbui45V/59TqXWjBv0k/aNmVbVge5GlQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9Ceh7Hex2+aHv5fXQbSM5/PyD7L3CEEGXLz4AOSwpD4=; b=i1bnE84F31/n1XxmP+tICX/PGMl74PaSVtfQmDbBISSs55JmlIDRKvO7sjKJlOgr3d6uSYX1G+78tQfGQcuCShjNelSaQPmnYKf0XUsBBUMTeZHvoTxt91qQaaEMGwTrdMVwGbRlKN3k+dPj9D0U6EPkXe54CtTfACEUTNRCKFFxtZe9f8mRtjcF5V3r9qWrrqTNPtnbOMChvfE6TY6LXccXwOyIGcq/HXsULG9lpE1qsY79mS3mc27Hf96gm40fJAb8sYY7bSIlq7ZgtuFq2Xvtv3Hc3GdWJ3tf5DNLWOaVXXJcC5CAIHv7qSZ50r0SsO0tBIPgjm1IRajm1i6XHg== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:46 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 35/43] wifi: nxpwifi: add uap_event.c Date: Fri, 9 Aug 2024 17:45:25 +0800 Message-Id: <20240809094533.1660-36-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: c300eef7-6901-4d1e-88ab-08dcb85852cd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?45VpfvGGKeVV+iNkiKkI4VmshDW4ChfSpLFQUkA/hRG3gXIxlz1++DaHrwK0?= =?us-ascii?Q?A0kAI4azVoIG25j/8wWllUi6oFX0M14AJD5LJwMWiRXuqIG/PJP8TRar7qla?= =?us-ascii?Q?0qkoE7dRPB5seA2Ng3X1HafsJi1lT989yxb+bXnT6ZPGQxsy4hk/S6I/ia1i?= =?us-ascii?Q?EpG3Zj+wM+PgE3GFvwD/p7+vwJkxcjP+taZWx2niZs5orRrKB9yty7x+ZIXv?= =?us-ascii?Q?zFov0Ey2l2ij22qUMwS7s4yFsl63SA2yHGoBI07/Hx5LtU7Fl+Xi0n2RkG4Y?= =?us-ascii?Q?t3nxtSgqgKpTUlqZgItG9NwRbl+7lqG0XkFoXs0vo1rbjrvsB+zIG58mhhT6?= =?us-ascii?Q?aDmFYUfJlrLJ0PpUaHN8HaQBQpniKZR7OnfUfnWDmKvXw3Ya/7R6wBy/aF1C?= =?us-ascii?Q?s2Pz8Im3w2cCdUyUV5yfq/fFD6I5voVqMdWrbwpFzSg7ZnHsrG5BhkMn5ZBS?= =?us-ascii?Q?6O9ndVG1BXPtxSdIXhQIhrjL12JNkydj3U+q5ZN11FQvAiCBNyEryuiK/Jcl?= =?us-ascii?Q?WaL8+RVPrhQ03EyG0qGnv0mDe2D7iZbudBMmqbOHPoJ5WAj2zwqyPTJLvPGQ?= =?us-ascii?Q?e3+4epHTuUZsCe1SPfF+WJBU0hPJwPszuHt7T11GuDBdywGaWHdYtqiOiBoU?= =?us-ascii?Q?wMbqXyB+Djcioq5ISGiEME5qKmyYJVHY+W1n82/79oyJQfjyBrWuJPf2tAv/?= =?us-ascii?Q?DlzzcFynW+Zx5Ogf2cNA8wgEHIXZVdvHQRre6G0s60JZX3Ede0ZzNMtzEOlH?= =?us-ascii?Q?/P4ezNk+hLcfZqVPzm2V3v1Fpp1QItLmqZbhyzvefY85lhUhjY0b0WCX1o8D?= =?us-ascii?Q?DGXZFge3Av9/jZ4thLb9EIF2jogdIKb8j99HAO3Nh4yN8T9ylusbx6PoPk7+?= =?us-ascii?Q?2BPnRr5tR/aMjEmNX159Q2EVa0OVr1yI+0iwLI9g/SW3XpmjBiDfQXqFhPCn?= =?us-ascii?Q?xHrPGM5E7ABgjDm1KpPYyJ8Zd0hL348c4OFAk39LrEIxdQdBe0qX9WPj+A7S?= =?us-ascii?Q?NPGLE/warIZi63CNnOR8sILOcTyCql921TSsvWMwRlzyc0NuyZPsK1CyXvDJ?= =?us-ascii?Q?dQo0Fms37kXvjSoSU7tu/TAlN1L7CRll4eTJFb+EP9pLWgjlRk1KHsTVuMLs?= =?us-ascii?Q?B2eoBJt34wKFmtyPqqntDOrw6xA6t+RcryqRyspkKYutm5UxldGcSd+aDxxW?= =?us-ascii?Q?+QcIy6UGaN47PGMenKYwWo49Jq4Y7OoePQsPgjw2nqUEoCaYvG5ROAvUYzt3?= =?us-ascii?Q?9Ofb4zgUOYSDrlQ0agGZJB+ec978mh1Y9yEPUqPNJTRXnIn85+YhTDjtFY+s?= =?us-ascii?Q?L2/z2QXOGAZxk32nQxwE2o9+98P3W7uxBULGyj0dYKHgKg=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?l1wnm4uquqMAiG4Eqn5t9hOTbabLqzz/I6fFh2x7B5MZkuaMM2CLZreG0wXp?= =?us-ascii?Q?+Apca3qmrFQnMZy6A5tYEagw8IqabLEpnTsd1AVPHpl8iXDRf7egX70RSsTN?= =?us-ascii?Q?/qQJ8LGDkNDnCOcXQ2F/Yd8Id6i3++20/M1QS/u2O3vjMxJkFrk1o+j+dZ1E?= =?us-ascii?Q?U4Y6pP79aMXI4+Gi78WaE8rJGgRCWPn3yqH8Y8q5vS3/x6FxWjyMLmbw3FJs?= =?us-ascii?Q?slGF5UxSC9KU+kdWuXxy2elfLL8Z8oGxRPcv9ml4yUX5DpXrSjqyTqepZk9S?= =?us-ascii?Q?Q8mWtjOI2ol/zrw0H39/diU00zOKoJY4jiv1y8s8qSi9DIJWhDpn4+jerAH0?= =?us-ascii?Q?fggC0BqF6WYIxWDFL7CVKoeZORHHeNfJA5iBVb13lLEsKPl+hyoCaKfze56y?= =?us-ascii?Q?auqfst36vvr1uROKx7s5i2DZXk6EPODa8iW/axuvQlVwD8+X8jc3sfd1L4Qu?= =?us-ascii?Q?jEIJsePTx1I4Dw3Uia9d91jbyYwq+K9ba5XlX7PA2PWY8ab1L3ByiTxJd+lR?= =?us-ascii?Q?60qCxgwrHoe34KtwPwVKxyqRxlTxNesXvmMy+zMvill8RuPvKxHG7+eRIzMY?= =?us-ascii?Q?u/y/OQTDqCZX+D9xQ9VsQvvPvpfFsehhT39WAw+6JuYxR4P5uO0bUFTj42Uq?= =?us-ascii?Q?lXEKaQGjvvkqioUS/6xRX/tQt18La+jT/W5Ss7mhmOYT7GYdZpNFbG4kM2wg?= =?us-ascii?Q?Wyod1+uYTVU9Ep8ba05T1f7MI5JcqOnUdQwvAJAHCQqOi4YmXNXnXtVJGokR?= =?us-ascii?Q?9idzZAq9nVi/fFy1wZ6l7clLfhWxidJvDOyWKdwIM/Vatjy5wHoGnvwc0HsV?= =?us-ascii?Q?WivKRPPtlW3x0GB+A5ktv/H4f2Q+mAYK0/Yzommm5XMjkZ2tIpTmbF16b1oB?= =?us-ascii?Q?HvfQjAab5jcy5gbrGqb0OfgpdRXhZESz9x+0ccE7Zh2+F34Z7MHgJmejCmwm?= =?us-ascii?Q?lZtFcX4r3PDgS7Qjh661oNXgRhZUWzfWdmj5vKZw9VKkkXa6A9YXb8qyOh1K?= =?us-ascii?Q?Lv8zjhIkwORxP1cyYvI7V8NjH71CFcpIRefDUJ9m0yP6QjWiD6rp8OZ3aBqn?= =?us-ascii?Q?mfti0rqIx5l5hdLn2PDHEGtCDdOkl33Al5FV5MJTHRhvvqeAYvsWhzkoivJl?= =?us-ascii?Q?dSRwXtA6nT+AUJLQ2yjQB/KxAnnyjNNr8WjI5d7xmwfNxighHHhmhHR6uOBz?= =?us-ascii?Q?SrmIazvxTuF8bBTxS0+XKtfdFAb7dvhlWaupV57bnxmy97gyJ1zpZJIfmEyM?= =?us-ascii?Q?ZxtpMmuL3HTYjE1yBKFQCBVKfC3vM9U3RhqWTNiqVbvZa2hVtkaPv1buwDU6?= =?us-ascii?Q?tIVoYY1I21nnJVLdykfPTx7rGRWfdVSUlZYCodKOcSxNt0ArzzA+vp9lhLPL?= =?us-ascii?Q?XJJF3bfileuei2PcZIXD+Dylw5APEF6uqMmZKgQu1IHQhtx4avR5IiybCCEl?= =?us-ascii?Q?eiDJt0+BZw0daDfxMQLGyIYnU7MyaJnDiAoZxeIqbRjCItKFgleBLyfPXEjP?= =?us-ascii?Q?GuD9z2dgU1IY440NtVBNDww3lFbfR8kCkcfh5nh/FqLfckbe4p/MQFguxVnv?= =?us-ascii?Q?QfikVNaT0d3YylKeNUwpGabAlW6rDo2UBFKJS1J9fnyLpsG0ZucLUIEgIw8d?= =?us-ascii?Q?Y88CZOgZi44MC3osDS8oCheIe76Y1BXAcFnkSufunxSR?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: c300eef7-6901-4d1e-88ab-08dcb85852cd X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:46.9050 (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: fvXtBXTi2/El42YSl7XNbjMyr0zkp0C6loGJFUJC52qpv0m7PvMnd8+rEXyeF/2aKWaz22bvKRoWTJp9W6DoFA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/uap_event.c | 491 +++++++++++++++++++ 1 file changed, 491 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..9fb0abdf5b3c --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/uap_event.c @@ -0,0 +1,491 @@ +// 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->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 -ENOENT; + } + + 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 ieee80211_wmm_param_ie *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->len =3D (u8)tlv_len; + wmm_param_ie->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 & 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 int +nxpwifi_uap_event_vdll_ind(struct nxpwifi_private *priv) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + + return nxpwifi_process_vdll_event(priv, adapter->event_skb); +} + +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}, + {.event_cause =3D EVENT_VDLL_IND, + .event_handler =3D nxpwifi_uap_event_vdll_ind}, +}; + +/* 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 Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010001.outbound.protection.outlook.com [52.101.69.1]) (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 D179319D07A; Fri, 9 Aug 2024 09:47:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196876; cv=fail; b=npQSgV5QGCJPYzW2Ux/Uy8m2eXJhMo+e4Gi9qv/EVXcdHYUTsmxPHC/0ZXik5D0Kf2SDABUuJ8S42xzsMMvqwnCUp9MXRhxnd8w4Ug0zv7fw0LQPkAGIpddSueDOAmhme4GpGKUHVZlcZSCsifkSJAdkSLEktHdXtGN0HLae4rY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196876; c=relaxed/simple; bh=PJwWgNafYEvNChbAOajpS7VRK80Rd0RJvL+1bFodo78=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=bF1Na316cpcvXePMUbeMstvBDCVTyen+zcvEHfCmtDssKH11gwrbh+w6Z7aRc3C/Odx8Y2hlnoYttdAapRHBuxOqGd8MP2XZT+MCNNxZmE76rWO2f79Vb/LtODhM+ifukN/d73ch+VcaZGs8G7SmS2B0k622vn0pE1vjrOlwyXg= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=F2MQ5LXQ; arc=fail smtp.client-ip=52.101.69.1 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="F2MQ5LXQ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=lyy4FKoTkHaRfbY0NWoKxaEn9fqB9Rqu64DkCbRovQGBV6vgYtduzmy5jskpk/42bRmi1Ld438vYP6OWq4f5MUmX+En63RScLTVBOw1WZBXq38byelMhkOfyetnmWuVpTAvz9b5f9GXMIaVMlgt6OWXYN387ohZqQ2tdWWkJ8ilGRT0mqnXZPUAfkka0n34JNDYTmZbfnzTlPtHj6yPNePGji0kwi53hJyiqkK0lVC+IHBoDr2XRzpD38Kd/f2usK27phxEPHX/syNClTIJVsLz4H+vpHHKAntQrfgIlSoZM2BlSrWlP4LZ5resNE1crt7uBkVq6/0+PY92B8U2RUw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=jvPY5ptuBWJjuwawDhf/2mnTFwoF6mW0U43JF7OFyN8=; b=kUNsUBDiJAsvrRyjdFK9pjI5eyp5HefawnTup+Ju1RoxhqmLCCwuOjWVmEsPthZPRJTCfPatOioyohBm3+j92qM24AdL+NjFnop12iQHB/AK4kvKsypTNPKLAKfIdkjaoNwirtHZdRzwJq7OS9OPbcUMN/tlICQDwVBEr9KwSgjn88gFaHAaEoTVTJBU5KVVmd7P41MIunZA/RFI1uhInyB2ND7V5N6AuPv+ZjslhglYcpQmcRNYtV/RhS8GI04zVa9ZCWNJUNWHZW6KT8nRWP6ibpL/BSqyPvALdcS9jLIE5KVuqMU3TmusygR011uY579xxVwSKKMVSa9mLWrGCQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=jvPY5ptuBWJjuwawDhf/2mnTFwoF6mW0U43JF7OFyN8=; b=F2MQ5LXQiLSMXlbIsccguoHevGuPx4Y+6CWQEaJfncUClL2x5oqFgrjP7lGh1d6EhC3i0AsaQ2wTVE/z1WI2FII0/BR2FMrwouBVNk45S0uDi2mwiBcgdI0p7OVUJY+FzThQq7q3HzhWvGhu5D+YC4no1liOa9mCq06yNeugw1uhhAopKI/v3KuKz7c5zm2dAAjUqd9JrLtpemAUz2YrAiA1WBh2zc4qyPVselN/a/j2WWGcRppWVjYnlggTLmcROtfUtifpEfEhdEMa5EYZ+w3lWkfZUqvCUOIfT9mh/lbbCtC56D1RNqOIpzy00k4MzfXA6jg8zexa2Y3M1fFrig== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:50 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:50 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 36/43] wifi: nxpwifi: add uap_txrx.c Date: Fri, 9 Aug 2024 17:45:26 +0800 Message-Id: <20240809094533.1660-37-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 6a4a119a-fd33-4fee-2970-08dcb85854be X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?sQLtWs/d0PHU3kR/40Y7r+u25RvExiAEkJef8xmVJalfeuDeLay4wmYNIpXt?= =?us-ascii?Q?gOQ+AqYQaXg2EKKuImpZv0XB6X5DeVS2ndGcsLVB6mRmyygFD1vetiqagclu?= =?us-ascii?Q?TmyR88/o6pn0vEWUVsgQ4/lAt+Vgm9p+AhEZKOXVjXL4DckZEqawrEot5GaR?= =?us-ascii?Q?Jfj0koztRaEd8nylMedhzWgLH3AvqDn21LovrlJg+XJVuk3TfbU35WduAKOd?= =?us-ascii?Q?crvRxw2wTtzS/lBXluv+tfhyfIX/xkYF0AnLf5fiU9ZwY8VVCI60FdiOXeDJ?= =?us-ascii?Q?kPpomOjKOA79sUzvyEedAjIH5fKFSxNhI1kU1WgwGkK3YsTFfRWe/LLyRakJ?= =?us-ascii?Q?u/jm1AjGmROGCPSok0T4fnozym3PT1W2lOhJMzExtu74lSizTFJKut4TBp88?= =?us-ascii?Q?kf13bwoMPvRocitYAyMYPmMoOpwmS0CAVa8Iqa5XO2D0+feiSfLjlOw7e1P2?= =?us-ascii?Q?H3w9lNrsxoe6L+VQWSNb/84QBtGP1YM1rwkvEndmgHfGrrgpWt83KDRehJBu?= =?us-ascii?Q?IJV1HLje43oG6sASxCOVL21AIHlszj5aL1f/Mo15uSAJcdBdRveOozSci2Ar?= =?us-ascii?Q?4g6Gce5lHR+kbY2r+jV/nAfd2BHMIBS4EVBLltcLqdwJdbKZy5cX/Wp4rdmH?= =?us-ascii?Q?ECUiUygLnYLCA+SUTe8QH+DBYZKzd2WRcX43MxYYMNnFYiH7uy+LBFnCOqQA?= =?us-ascii?Q?nkoUnhqI7rOBpLz8erwm+768z2qHB2cxqcFdD5QDYp29qvrhQsFoZyyUU7gI?= =?us-ascii?Q?AJIZb6hiyoQd4noV8GKntSgUh95n5GAUAeA2ZGTqilPbe44Bi+xVR82erGy/?= =?us-ascii?Q?VBdpNwyU5i4rWJcXTcjSPY7Y8vV3O5KOQUftxmDzT3w9HSGKehEwWFismcs1?= =?us-ascii?Q?Nw4uSmZ1bqo5IdIQdT9tI33Cn/QSyRqlodvpNChWHCU0jMpNkn2f++SDxfg0?= =?us-ascii?Q?sITkZQ0z9rG2EjAFFnA4qJ3EB1lWjUfYqRtrcWxG8WP48Pwbf2M8d4YagfYB?= =?us-ascii?Q?pGlNguCAdsa1j9GrMidcAg5H6eNjS6gTy/L2og1sgU+8dK3jQR04xzk1cxNA?= =?us-ascii?Q?oqaIzcjsKpYW/z9Ii5wP2qJm2Fo9t2Hw2Wjveq+eTSI5u+Efm2mOTVZbqBKh?= =?us-ascii?Q?E36P22hFhHUeAGrXwpZKEBwujQPL7qeZGlGSzMaAggIlWTeR1932VGa6r0M1?= =?us-ascii?Q?VDEFyBI88rClQqGFazRamTtaHKjMq9aLe41v5h3ND3GvVAK8bvyX+hXKwtGG?= =?us-ascii?Q?XchPG6SFwVO4P9tSv6Q4vRugftnnqapzcbfPigS5K/sOaHgj5RBb9YkYxyQa?= =?us-ascii?Q?6ETOowoLuFwYJ5jC+rRRebQV7v8CE5zFMZwPKJfya9McEQ=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Uw8dQR+uU7/QNcP+g6ZM2wktWw0qO5R3vSlWWni2Ljm2DVL4upoWesdJQ7C8?= =?us-ascii?Q?AyquomZ5UN7ClT/4HEx68kOWHG7bbFQxF+23gxpE5Wi2rS1q6hbP2Nlh2xm4?= =?us-ascii?Q?yuxA826OLjqg/1cA93GHpaMOQVJxStjtFsk2DDXnqrVcHpgT6aL2zhqvZkBh?= =?us-ascii?Q?z+hmfXeIrzsWIm+T7/nyI4cll9R0ruYSztqFhdMyffbRW1Tz0wOqbQVFr8gu?= =?us-ascii?Q?SAntg6aIRq3/6c0YLiwNIJwJIDJgzL62o2qyJuBKmq9Mc3lNQh9CUj9aIOdj?= =?us-ascii?Q?4Cvq+KneCiVtRtriN6bQBvwscuW8grA01uNhzTXYu4UcDjMDUohKraxKt3yn?= =?us-ascii?Q?NJF8APIPyc9uu4CUTU4DY8E8iW2oP3hnAqJpF3x2gpO9cO+AWhI662sU3h6R?= =?us-ascii?Q?G9huvynpYtbCAMN2zpfEdtFixwK6pucUCQoQ1iOBMWfMQL+ggyopcmEseFBh?= =?us-ascii?Q?5437wlgr+NNOuLMQEH3W3WqlQaK4cJgeiN2Dks2lbhsNNJfuY31u4KPT30ye?= =?us-ascii?Q?Xl+zNrqYxjvZshPmuQH4niBkARnciovnkrkNs/lWlq07gd6inVA5ve7CnUe3?= =?us-ascii?Q?wCiEZFVgNtYKZAADEU7sRdtJ110HB2/thNnXlNUB26dlrdD3+W50W4oSkCx9?= =?us-ascii?Q?tXWjQLGu31hjwMYBHPRS/DJWTnMIhZyVyJgkfaiQppREBQlRzSGZd5+X12qH?= =?us-ascii?Q?K9QnU5tBZY+eQU2vZ7cYgJtbymb7uFcuFS3H6bCJKisZGxB4VYLOtUV29W5a?= =?us-ascii?Q?0vBHe0aU+NhdDr4Pb0jqCb5WdRqxnv1wOrQYMPC3UcRRhz72guXK/z8354hF?= =?us-ascii?Q?CX37o3ndYujvL+CUJAriQZ37Uvu/s69fgW0GsdAbWdzJ3U47ggIkkEwQFDWH?= =?us-ascii?Q?HTwSf3a5rqTQacF5812XpxP8kiJtzvxPixho06JHR9Nen1LbwDyjy/KSyKCl?= =?us-ascii?Q?QXzr6JYPdIx5DNjq3QcxYe6YL6Xa6n81khM5p2oiKLnTWxYdQwgUSJrse0HD?= =?us-ascii?Q?pRAo24cwSpFF+WKozooJ+lFl20LE/FIdie5C1nFTpMUqoBh8QIHfp16lWFuU?= =?us-ascii?Q?TZ9waCfKZ2/3X1MbkIsaetfCLyQHll4CSYUUnD+d2eewTrvP+Q9f+TceXU78?= =?us-ascii?Q?x40V5LTniimJ5pifj1HJpakuwkAhUmDy7fX6csaUd8SCqnVx7yjblw+drZer?= =?us-ascii?Q?bl5vxF/GQ/MlLHWFoDRM9PEFjvJkqKW4kPcDI2Jk/CG/LQFolzyDwI6yYxVX?= =?us-ascii?Q?sZsV/VWb2QRkDK/99CODc/bqVMChbx/5diXQcVaVEpK1NlH7mznCSLTRydAJ?= =?us-ascii?Q?Ev5rFZWh6rcDPQSxWNYhQnjSjixfCHOx2jXR9jL2Ky9l1RNG6da8BlFrzcTl?= =?us-ascii?Q?ZTNwXf/8PADt4wdlIm4V+PQPoMkF9uUOzt7d2vm5kzi89dAJkhL0twZQHcNP?= =?us-ascii?Q?SJTyhNUMAWrU64v5oBqAH5fNITsX72AGjqapqq6OV8b6yhm1yzftOMjeT7ee?= =?us-ascii?Q?uqQeGUqN8m5LYWuFRjWvDnrg2UP4ADlzxZ39YrCuIFGaTCjrssNN6+5IDbJK?= =?us-ascii?Q?ljiKjDsbwtmD56957pgP9LKMoOnUvePNxteL2P84+AVwYuhlciU20jFGpZlF?= =?us-ascii?Q?mmeMnNg6QJW1FWu94nG7XiGkOq5W17NmvGpjPtSbAoqt?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6a4a119a-fd33-4fee-2970-08dcb85854be X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:50.1872 (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: qmUwh1A32p10wPcoNxA1YZvtpo2P/51vrDj43ynbikgh6+kK/TGbCQNIBoF130wkUTHqLaC9gyFCc/vaFh5X0Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/uap_txrx.c | 499 ++++++++++++++++++++ 1 file changed, 499 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..b3a3d7cd9ce3 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/uap_txrx.c @@ -0,0 +1,499 @@ +// 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 "cfg.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(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(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(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(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_work(adapter, &adapter->main_work); +} + +/* 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 -ENOMEM; + } + } 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 -ENOMEM; + + 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_work(adapter, &adapter->main_work); + /* 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 && (ret !=3D -EINPROGRESS)) + nxpwifi_dbg(adapter, DATA, "Rx of mgmt packet failed"); + if (ret !=3D -EINPROGRESS) + 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 Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010001.outbound.protection.outlook.com [52.101.69.1]) (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 DB58619D098; Fri, 9 Aug 2024 09:47:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196879; cv=fail; b=kpv756nbOLmCq3iIg2DsqnHvTKxiitXbtLh8oEQuhQp3DJ7ThDGObo3tKX0WbmT2DBZtBGvdA7ud4fvFZClcPqvuIXJmIhIJZXwQYumtpyTdEiCVaAWjTzSlMl8Si5Y3agWhIibg8f28SmvIomDjZ7ATwSe1Te2WOWgmg0m5ZOA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196879; c=relaxed/simple; bh=TFwgryrsCBngxMIy+Dc7535KB+oEo0+Cl669+ewN908=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=lZ3p9HgrAspsMcTuf3hV+czickRmo9dncHj9kgj+uude3LUSdSh+fGYf7cJIBQaNmIu0E5W7WaFpx0NMrAf610Wu8ezO6haJBAnYWjpsWM8vLtnjDfzH+hY2LyKx3x5A2+qOtwyqGCasChRegSWQoVDGXFGFqSv0vI3uAkd9mLY= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=mHET9exJ; arc=fail smtp.client-ip=52.101.69.1 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="mHET9exJ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=xUGOOyFGYBZV8D84Q9tejRHg2RumjhVF6RhBlQ+6zRBa3ekTfiIAtOwUVsl0Fa607g74/QA/lHBqhOBx9z9jw1PvMJYYQ6vaOSK0Hmoejje72+ixLf03tqG2EbXK5OJoeUNW8fMIfsTwla343oYHkZp7NaxZtj9u7Szkle8erA3gtx1yIhRmXExkq/aC3jY31bpFZIFKIg7myW0C44wKLAnmF9YLrYXBPaCjPnW5wFEBvQQBe1r12zdXGBPGlDjiXKyPa1wGYxWUrv3xdjAaticDw62uI5LaQS2suKJHxi/ahsLByh7475k6aHLs61x5FaedODzwshOs/A0jev/DNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=nhWSGyCuR12bQuKsbf6S7EDHf+BeoVujZcFSLpvb0HA=; b=JNdy4gnR/c3zlPhDpLgyaMCAdxXHGNboDLm1RvjJLQpdOl0lOlz7fRqfxj2/W+pdkT5DANunSuNuu7v4LCeW1/OBlhfBjGRNU8n+MR3zx9JXVD6+FbNLPmMt8tKn+adZvmBiGAIHTxJ06n8Odf+E2wrqKT3kR8lGud+WF9+nQSWHfETVQ/Be5brww5RNUT1XsGp/YwmZ78S/KxKBTdxNjjFfa+39vqykPIjDqdMMd1AidzcOf1bRTVuuWQ3RzpfkCxVkU/8S4hAQ+GM4GRbzYW9zsp11oIMzFy+Rmr2HwsGiIeX4GXOP8+RF9bi5FtdFb9S7lr71wAE8HaeU3wSfHw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=nhWSGyCuR12bQuKsbf6S7EDHf+BeoVujZcFSLpvb0HA=; b=mHET9exJmJJdDT3E0gItMNlYvdZBgAdavlQt1w+MY84GuYJGVSUG4vOCsfXbuvtjAjKldw2vbrGEiRWybzsKWVAA++8QYPGWCHtzDsi6QFdDfVB7hCwWcDCoTaJrOTyUyWYn8neVNwxI3lk/4ElMKrcPQSH2ouKUPStyDC41sZ5g/pCB2jxguhNcdu2Sn7CnnFHLoWp2OYhmy1JSq9oRs1CbAdcvQY9bTudo8Is2GdfC+tkxPFUeWlQLWxC4yYe/XhFIM1bnKFJ1yA9lVqHPK+klBtg8B8q3hzAdJuSFziN/FWrL3NYjOLsv1vp3zkNxSRPhTmAUsEKEHPcJZQ+uDA== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:53 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:53 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 37/43] wifi: nxpwifi: add util.c Date: Fri, 9 Aug 2024 17:45:27 +0800 Message-Id: <20240809094533.1660-38-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: a3226dcd-5a5b-48a3-2810-08dcb85856b7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?NPKiLy/L47ggP9tejFGrALq35q9d19P9qdvGeqehyq19fZqVi7fvWwl2+1ZD?= =?us-ascii?Q?xubpHzHZ+DsSEUahay/vnLlEVNKyZftS3wszLVzdxc8pYGGIjEq2GmAPJdeg?= =?us-ascii?Q?flvTU2svAEmcdieENuVZMPeTNJujGA17WaOnmj5ss9HzvdPtbtwSRVTqBZaZ?= =?us-ascii?Q?z7AIBlQHExKTT/RUq18pEUfYpOHu5qh6VBWoaxV/M5P8MIo+lCez0CjEm0kd?= =?us-ascii?Q?oWv15cWe9seD2l5YcuYBd0vlyhXxTrMBD8tEoxQkJoI2CgvYg86Ro94vGpOq?= =?us-ascii?Q?CUGezOjtvZPTnKIxHt7y6AhA1NIXJbfsLuar+qjeJEpKU8h+xPCn2WmFlV1c?= =?us-ascii?Q?ISiSCCYOjVBFBHXDNJl7vJzOsrzrV3BlsQEADca63l3SYlY6N0/1vdliNbe9?= =?us-ascii?Q?iOM9PzZHxA0mzWlP7A1s0VzgozWbeUg95FkXdIsq2nGjtXTAgkj6wkPB9UqJ?= =?us-ascii?Q?A8ESgZtxvnCBZnxl+47p0cQRB2KTu2fQmMDQma5zkMuwz9SGeDCjRbxmRIul?= =?us-ascii?Q?cYM2IsIscxbKlY6i0sLC1J7flZ64lVQ56+Ckjs+Pf8Mic8zExxefsCjCqznW?= =?us-ascii?Q?HSOuXqs0OR7EpbOokADliIkuzmceeFr2dJxLcpZv+NAzcLSINUH49wFceCax?= =?us-ascii?Q?u9Vp+ESh5CpMQQFZ8CuhtyZZh8saekByBOTR/6sCQ8FPRxq4Y/MLP1rj3IM9?= =?us-ascii?Q?fDc3arHpG4JBOZIlgq6Mp+n0j27Wr5kVU1vkXQ6WMflRJdm622k91Y/LvdNV?= =?us-ascii?Q?Wl+Y5aYrEw8abi5MyFj6KqlKlKKnAGCkg64HRbSM4yVT3CijxtTwOqQMSSuX?= =?us-ascii?Q?49GpKJxyDtEDXXCppNwCWQIk/UeGC8zXghRPlyOpYKdXeojMmZpYR48am+2F?= =?us-ascii?Q?uzPlapi3PPGmfDrvWCUPu+vywLnEFQ9WXztVXpR/QZ9CDIfb22vx5iyvSwYA?= =?us-ascii?Q?El7IsaHJMDQbJNvcKFd+fG6woH0fVVCme2504Bw6JCukD9yfFBfjhsBJfJ8n?= =?us-ascii?Q?FeflFcYVaQDKmRdaM8bqQiF5oS80e2X/kBYd1IYgkdo/b5Kc/c2ZfVdxuI1u?= =?us-ascii?Q?WDi5HW+Hd6hIwlz0vMkEO3y92B+RIUJltr3Z8XzGG8dTeXePtSr4w6M6iEBk?= =?us-ascii?Q?pk2g15dPhEJsWVFVuE6j0oHrvqTzw0sRrBNeqlvn41pcmPGeDoY0GKSU/7QJ?= =?us-ascii?Q?4wn1dca5IBo/8IQFlbHfClTNdKn/JoTJ66jwpLbw5x4Sg38gg0tXVKrWA8N+?= =?us-ascii?Q?Z7OClecLkJD1Ei4T2OF0mXy5d5HosYuOIC0sixQfVUGpdHFKgaVe7dJmqvsT?= =?us-ascii?Q?QV7Gb4BHxiFNf0ck/DXHGdjtgNnGffEJRbYpMoVzhU1aeQ=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?yuE7TFgOdB9tqrSxa92ckDKd0sgrbcuNe90ZZ8oKbGsqUPi97bb4lKP/0Hck?= =?us-ascii?Q?vT+33xtBspIvQ4viYpdjyo0W0cSPvapucmIXLDV2sc9hXbvY9uPuKzNt7fjf?= =?us-ascii?Q?Za5TELhHD8RQkPzv9ZFh0j1hcsbkEhcfF52l92mLx6kjB+H4mGuhPi4J4ZHk?= =?us-ascii?Q?ehgrEm0DVmZwNOpUi4tZ6ayDXwPFhPPC1Xv2UrmV18EUBlGEGz6JqdXJ1yS2?= =?us-ascii?Q?Ax1q8desOJLyC51nZxYuNrXY1gMvoYgxAaSx2QlNgZcppeOIR9ZeV1yDEX1u?= =?us-ascii?Q?98+B/ZgouHEggmSUGsRfqkbuk84o2wZ8ePr3D4CFKcuACA7mGoZP7IzBzfqO?= =?us-ascii?Q?T2MYoVI9uROg+mCedBUB/peopbGNlgII0ivRRAh7S/F+r5PMEyuJH7HIrRPn?= =?us-ascii?Q?DZCiIALNrqNKBao7dNhwZH4WXYWzHK3BBkL77LQV9WJEX2jz1eZfo5m8jrVQ?= =?us-ascii?Q?YBGceHIrVzL8JqYYcABhberf9cT/QLKvAKRaDYSdSHwCUbgd0D/TQCGanhTL?= =?us-ascii?Q?oKjW5v3vRPl5EHXL3K3GPuS0WWYtguzw5WQq7QV/9D9beil/hhKIuvnwbG9I?= =?us-ascii?Q?D10a1pc+bhCjLuwY/9paJZye2SY0QhLMm/0szahV3MPNszlyQOWxImu4NXl+?= =?us-ascii?Q?g/x3LdW8C8jYLS670rlevTgwApJ/EMK4vfH53MbvuH7NVVP5n3iHOedS+w3e?= =?us-ascii?Q?ZtXbeKAxecf7wscD0uMS6Fc8b5QvhH0TPE7uck3LeGBQ94BGpCyGhyLXDOh5?= =?us-ascii?Q?FDSw+NzCSWo5dsEabChdj6Per3pcC7skkVlsTX7sHXJdoJVyOOeNbkts1jzE?= =?us-ascii?Q?PLurORTh/bSPEje9PGZXli1ulQy6DssnhfVg4MVGvqgLbLWVIx00UniWUd6k?= =?us-ascii?Q?mIHaUVr9YoYKZtwTGyJb73+TiixZ3SZNtcysSHOcyb7auEDdkMj+ylTzDAMl?= =?us-ascii?Q?IiWrhR4xHqNSPyoFVv8/MXdYLAH6cpktL/N1ccpnWMdbKeVkir7tOYFcOImQ?= =?us-ascii?Q?4h1Ykj9yP2z3tqDyEvFlZ8lKLxIbe8jsxKr9X14r37s9ynWae6g8PvgQzNrY?= =?us-ascii?Q?1syCgzVBENIYwO7QOsiQK8XYj837rrA7uJTcUDVBjge5qFms7jXmc/Wv3yAr?= =?us-ascii?Q?xDBfvs/7RWwm3zxUfThiYxVojwACOmeumDq/loLKhjXLnMPcTo8+KQNbqiCd?= =?us-ascii?Q?p0vU4i7be6KmO8z6Cyi8YTbkG9Enp0yUtFxG2X/9vUSF9LrDV+qzuARa8I7t?= =?us-ascii?Q?uo6uL3FrnGw4ZFikzLTHYwckcyVtZphhaYs/PbXhTjDHulPE8jPZA2nRGi/Y?= =?us-ascii?Q?Jfwzd254GsDZJ+fifilDywnB7AGYceFP25jAZBCOXmSwUe+r1L79uMD00zIq?= =?us-ascii?Q?VKmyILv39O3GUg079noFIhRM0PEj/nFjZxVs9Jny3fAsUeOk7iT3JvWPSfG3?= =?us-ascii?Q?8Ep1pjSTBqVk4IvFWhmzm3xue8pr9KCSdYl8peiEijyzLXjuEhhMqNkTkwZQ?= =?us-ascii?Q?fn2ofS2bd2JvCbrrBHWjL+n/1ceh9BsrIZWScA2lLEdPvDKq7GmAVrsk2Cab?= =?us-ascii?Q?dGUvCaJh9hyZUHtIx+iNrA4i+QZNniBQJEnFbyao3FNpWzQvjYVpd8Ta9yh1?= =?us-ascii?Q?cSRvb6WQY05x57IvUvceYNZVzOE8Nh3JrUrOtkpkF7gZ?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: a3226dcd-5a5b-48a3-2810-08dcb85856b7 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:53.4702 (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: De04QY9tshB5mPJYq/LqFPW4Ez+lvwalYZ5I2ErVTgefs0G5IHz4SvANweB5nYSprHxn+zKX1XENitj7ehQNeA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/util.c | 946 ++++++++++++++++++++++++ 1 file changed, 946 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..7ddb7df4ec2c --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/util.c @@ -0,0 +1,946 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: utility functions + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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}, +}; + +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. + */ +void nxpwifi_init_fw_complete(struct nxpwifi_adapter *adapter) +{ + adapter->init_wait_q_woken =3D true; + wake_up_interruptible(&adapter->init_wait_q); +} + +/* 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 -EINVAL; + } + + 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 -EINVAL; + 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 nxpwifi_adapter *adapter =3D priv->adapter; + struct rxpd *rx_pd; + u16 pkt_len; + struct ieee80211_hdr *ieee_hdr; + int ret; + + if (!skb) + return -ENOMEM; + + if (!priv->mgmt_frame_mask || + priv->wdev.iftype =3D=3D NL80211_IFTYPE_UNSPECIFIED) { + nxpwifi_dbg(adapter, ERROR, + "do not receive mgmt frames on uninitialized intf"); + return -EINVAL; + } + + 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(adapter, ERROR, "invalid rx_pkt_length"); + return -EINVAL; + } + + 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)) { + ret =3D nxpwifi_parse_mgmt_packet(priv, (u8 *)ieee_hdr, + pkt_len, rx_pd); + if (ret) + return ret; + } + /* 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))) { + struct nxpwifi_rxinfo *rx_info; + + 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(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(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(adapter, MSG, + "assoc: receive disassoc from %pM\n", + ieee_hdr->addr3); + } + } + + rx_info =3D NXPWIFI_SKB_RXCB(skb); + rx_info->pkt_len =3D pkt_len; + skb_queue_tail(&adapter->rx_mlme_q, skb); + nxpwifi_queue_work(adapter, &adapter->rx_mlme_work); + return -EINPROGRESS; + } + + if (GET_BSS_ROLE(priv) =3D=3D NXPWIFI_BSS_ROLE_UAP) { + if (ieee80211_is_auth(ieee_hdr->frame_control)) + nxpwifi_dbg(adapter, MSG, + "auth: receive auth from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_deauth(ieee_hdr->frame_control)) + nxpwifi_dbg(adapter, MSG, + "auth: receive deauth from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_disassoc(ieee_hdr->frame_control)) + nxpwifi_dbg(adapter, MSG, + "assoc: receive disassoc from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_assoc_req(ieee_hdr->frame_control)) + nxpwifi_dbg(adapter, MSG, + "assoc: receive assoc req from %pM\n", + ieee_hdr->addr2); + if (ieee80211_is_reassoc_req(ieee_hdr->frame_control)) + nxpwifi_dbg(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 -ENOMEM; + + 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 element *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); +} + +static int nxpwifi_get_vdll_image(struct nxpwifi_adapter *adapter, u32 vdl= l_len) +{ + struct vdll_dnld_ctrl *ctrl =3D &adapter->vdll_ctrl; + bool req_fw =3D false; + u32 offset; + + if (ctrl->vdll_mem) { + nxpwifi_dbg(adapter, EVENT, + "VDLL mem is not empty: %p old_len=3D%d new_len=3D%d\n", + ctrl->vdll_mem, ctrl->vdll_len, vdll_len); + vfree(ctrl->vdll_mem); + ctrl->vdll_mem =3D NULL; + ctrl->vdll_len =3D 0; + } + + ctrl->vdll_mem =3D vmalloc(vdll_len); + if (!ctrl->vdll_mem) + return -ENOMEM; + + if (!adapter->firmware) { + req_fw =3D true; + if (request_firmware(&adapter->firmware, adapter->fw_name, + adapter->dev)) + return -ENOENT; + } + + if (adapter->firmware) { + if (vdll_len < adapter->firmware->size) { + offset =3D adapter->firmware->size - vdll_len; + memcpy(ctrl->vdll_mem, adapter->firmware->data + offset, + vdll_len); + } else { + nxpwifi_dbg(adapter, ERROR, + "Invalid VDLL length =3D %d, fw_len=3D%d\n", + vdll_len, (int)adapter->firmware->size); + return -EINVAL; + } + if (req_fw) { + release_firmware(adapter->firmware); + adapter->firmware =3D NULL; + } + } + + ctrl->vdll_len =3D vdll_len; + nxpwifi_dbg(adapter, MSG, "VDLL image: len=3D%d\n", ctrl->vdll_len); + + return 0; +} + +int nxpwifi_download_vdll_block(struct nxpwifi_adapter *adapter, + u8 *block, u16 block_len) +{ + struct vdll_dnld_ctrl *ctrl =3D &adapter->vdll_ctrl; + struct host_cmd_ds_command *host_cmd; + u16 msg_len =3D block_len + S_DS_GEN; + int ret =3D 0; + + skb_trim(ctrl->skb, 0); + skb_put_zero(ctrl->skb, msg_len); + + host_cmd =3D (struct host_cmd_ds_command *)(ctrl->skb->data); + + host_cmd->command =3D cpu_to_le16(HOST_CMD_VDLL); + host_cmd->seq_num =3D cpu_to_le16(0xFF00); + host_cmd->size =3D cpu_to_le16(msg_len); + memcpy(ctrl->skb->data + S_DS_GEN, block, block_len); + + skb_push(ctrl->skb, adapter->intf_hdr_len); + ret =3D adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_VDLL, + ctrl->skb, NULL); + skb_pull(ctrl->skb, adapter->intf_hdr_len); + + if (ret) + nxpwifi_dbg(adapter, ERROR, + "Fail to download VDLL: block: %p, len: %d\n", + block, block_len); + + return ret; +} + +int nxpwifi_process_vdll_event(struct nxpwifi_private *priv, + struct sk_buff *skb) +{ + struct nxpwifi_adapter *adapter =3D priv->adapter; + struct vdll_ind_event *vdll_evt =3D + (struct vdll_ind_event *)(skb->data + sizeof(u32)); + u16 type =3D le16_to_cpu(vdll_evt->type); + u16 vdll_id =3D le16_to_cpu(vdll_evt->vdll_id); + u32 offset =3D le32_to_cpu(vdll_evt->offset); + u16 block_len =3D le16_to_cpu(vdll_evt->block_len); + struct vdll_dnld_ctrl *ctrl =3D &adapter->vdll_ctrl; + int ret =3D 0; + + switch (type) { + case VDLL_IND_TYPE_REQ: + nxpwifi_dbg(adapter, EVENT, + "VDLL IND (REG): ID: %d, offset: %#x, len: %d\n", + vdll_id, offset, block_len); + if (offset <=3D ctrl->vdll_len) { + block_len =3D + min((u32)block_len, ctrl->vdll_len - offset); + if (!adapter->cmd_sent) { + ret =3D nxpwifi_download_vdll_block(adapter, + ctrl->vdll_mem + + offset, + block_len); + if (ret) + nxpwifi_dbg(adapter, ERROR, + "Download VDLL failed\n"); + } else { + nxpwifi_dbg(adapter, EVENT, + "Delay download VDLL block\n"); + ctrl->pending_block_len =3D block_len; + ctrl->pending_block =3D ctrl->vdll_mem + offset; + } + } else { + nxpwifi_dbg(adapter, ERROR, + "Err Req: offset=3D%#x, len=3D%d, vdll_len=3D%d\n", + offset, block_len, ctrl->vdll_len); + ret =3D -EINVAL; + } + break; + case VDLL_IND_TYPE_OFFSET: + nxpwifi_dbg(adapter, EVENT, + "VDLL IND (OFFSET): offset: %#x\n", offset); + ret =3D nxpwifi_get_vdll_image(adapter, offset); + break; + case VDLL_IND_TYPE_ERR_SIG: + case VDLL_IND_TYPE_ERR_ID: + case VDLL_IND_TYPE_SEC_ERR_ID: + nxpwifi_dbg(adapter, ERROR, "VDLL IND: error: %d\n", type); + break; + case VDLL_IND_TYPE_INTF_RESET: + nxpwifi_dbg(adapter, EVENT, "VDLL IND: interface reset\n"); + break; + default: + nxpwifi_dbg(adapter, ERROR, "VDLL IND: unknown type: %d", type); + ret =3D -EINVAL; + break; + } + + return ret; +} + +u64 nxpwifi_roc_cookie(struct nxpwifi_adapter *adapter) +{ + adapter->roc_cookie_counter++; + + /* wow, you wrapped 64 bits ... more likely a bug */ + if (WARN_ON(adapter->roc_cookie_counter =3D=3D 0)) + adapter->roc_cookie_counter++; + + return adapter->roc_cookie_counter; +} + +static bool nxpwifi_can_queue_work(struct nxpwifi_adapter *adapter) +{ + if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags) || + test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags) || + test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) { + nxpwifi_dbg(adapter, WARN, + "queueing nxpwifi work while going to suspend\n"); + return false; + } + + return true; +} + +void nxpwifi_queue_work(struct nxpwifi_adapter *adapter, + struct work_struct *work) +{ + if (!nxpwifi_can_queue_work(adapter)) + return; + + queue_work(adapter->workqueue, work); +} +EXPORT_SYMBOL(nxpwifi_queue_work); + +void nxpwifi_queue_delayed_work(struct nxpwifi_adapter *adapter, + struct delayed_work *dwork, + unsigned long delay) +{ + if (!nxpwifi_can_queue_work(adapter)) + return; + + queue_delayed_work(adapter->workqueue, dwork, delay); +} +EXPORT_SYMBOL(nxpwifi_queue_delayed_work); --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010001.outbound.protection.outlook.com [52.101.69.1]) (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 08ED019D89A; Fri, 9 Aug 2024 09:48:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196882; cv=fail; b=cKUesZWWXsgvewv2L5CJ7/qjjPXYwVTY7tdRcq+8yhG7xYK0DU2VsqeBGKvYWNqKsFFf3z3X9qOd1QOq8XCdra04jLdaovzjrYOH9TOu2XTShitwAdYMG55fw2WDn1E98gzM2H1FegD4RvrwJdZ3RdbByT4zJlutIS/ToJbnlco= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196882; c=relaxed/simple; bh=tp90pHiNnFMTZUCcpw6Id7ktOM6NLbgvG3kpHZqpjKg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=EtqV+KPaG5TO6s1AfQ48CjTXYqP5eJfMH+xWLwhw49Q449ljiMmSqxPbc+EqOAzkkYBDbwqvtX5D6zu2efp0+hGUgS2CFo6KQBq1LE3GkdEBSqPiliUInaG/0pqBJJH8byHjGrVOIOCxRNtfNmsctILHolrWoQ1Z09oAJ5nzB7I= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=ZHmh+6fu; arc=fail smtp.client-ip=52.101.69.1 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="ZHmh+6fu" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=dNzcV0ZDQf8Gk1h1ZTYoJNPGYzxmJVXkd0RS76jyBblOz5GcFKk4UwxxOwNBfb/wVW0yIazj3v+fREtiVQy+mLbuYd0vjWI7OzeXx0NENEktjDLLlAb4KKLieW4mPqe5zqt7DWyZaxw+pxvkfZyrtjtHHmEeRztuKIuJ6m3IXQCm+E8ZcgIHvPC+kjreKHxESyrYGgIYXbvgXUQ14z/yEyMwuF5PHVcUYdw//AfFXeKE99VG0Z2Q0pwbSiRIzwv50hoIGlzoxdYavnIVtBGzqBGrUePIkY8aQw89vJl/q54BKKP5lWuPivM0+TdQWqHkOHZXXfbFxXhygpa6NFqB6A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=O2511BHSxmECGkDmV0EyIawAlQqTep7qT0n8dj1bwGA=; b=ObYT5VM5RdwQFZ+edvzL7f06wutQjZ+TlXuPvCxUD258b5p29Gv5UEvih9ueRtWihbS1L837jQGoVXgk2D1CJfPAKd+GJhIEwChxvozaVoCYvYbstDcFQBczecKm9YOPXOM2244fVmgIz/3rwnvE1P37hqOvU9H/eHLkY/h6vgAwvRdndDKM8ChWbpJIg68DeqK858MPJtb+6MCd1AKSZ0vAVXfPEC7/NhED0PYKfLWDVhrd4QvlfAAzJFw/Y7ehyvIbeWsyxHfxF7hyMfIwmqO1VdpIoGWLfzkfFdR9V9rAh5KIR7+Y56TTYuUZsl8PWCbrW3sDgSjub70OYUXQSA== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=O2511BHSxmECGkDmV0EyIawAlQqTep7qT0n8dj1bwGA=; b=ZHmh+6fuLF3pa+SJPwIWtqG0gxaM+v2gjT11Z6VdarCyaaCT+ea8VB4RexuxmRqNyTB0CMcI0iajC3fUDgDCL6/nQwmpavRdudg4x6VTEPuhzhReVQPuhAzm9cCc1P1KrXPWrqW96bTE6Q+vjX0fa8TyFmeMRurPcDjOb7O3eaQncalHnzyz/L/xPbAgmE3jgmVss9jHMluAGD9e++6lxKgYC22gIixn0KrLx8fSBClXLPytoBCKtYxCMELZUNTWyPyCbDRJUI/RbqN0hmfNwjK1ycCrCBVHW5AXPmddcwBUW8IGce4zrt4UG3bThF5Dc/+qr9b+TvNrEvSKscC3lQ== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47:56 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:56 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 38/43] wifi: nxpwifi: add util.h Date: Fri, 9 Aug 2024 17:45:28 +0800 Message-Id: <20240809094533.1660-39-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 58692884-7026-48ac-894d-08dcb85858a5 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?W8uQPXCwGht2D55YSSc5xERtKawSOkZAWmqyYIsLlPOmmEoju180q8wAc+jH?= =?us-ascii?Q?uNk35i93OnOeVvd5O9uWoZLhokczEcX9NvKKP+dZpAD2YkQfryhe9SYWO99g?= =?us-ascii?Q?GFlmGL7B9O1GotXbH+6liylxDOs1LLa5eUrb55xOe92gprc+lf37Ruf7oxd3?= =?us-ascii?Q?qXb+V+3jvHRJlixL3pR4HgSdUBYBZalHpGAAhR4kDtgZWGg04jyQvQ5vlb9Y?= =?us-ascii?Q?D5BfEhruTVCN2I3pD5S0FACrgXvEfPr6o3UpGph3D1jZpsgyiBT4pafPD4H9?= =?us-ascii?Q?ekU502zcKPe36J1EXQ6mdIkwEKkG+z3IIeXK4jA98jmLJi5Y3BP+q/tvk8Wc?= =?us-ascii?Q?jYpwHGj/A0e4hHiFay7tT0VyyBTZ11XNdgbu/Yam9o7+bj68Xp9QBLMbctwg?= =?us-ascii?Q?NRdztPBaF2ehbpFZtLemvjOK43hxsBKux5gCsxMJhVwDW+JSyLq7QcwPn/mF?= =?us-ascii?Q?PVzXTb8b/ufOO4nBGn70gzXp7zZHvmGGJiqI2KV3r4vVs28CH1zOJN8POwJP?= =?us-ascii?Q?bG6Xuc8V/99cFU5R2Nlp0jq+gE++FQGmsZne4bVPYgqSBALYYghEEpBL20UE?= =?us-ascii?Q?vq0B9y8sQR4WSITYzLJ+eQXoraZh24aavu1u0GUnKEyp0BGpp50uT/vUSv3x?= =?us-ascii?Q?TsvCa8SlNVfJtQygLhMiFEz/AQF6fSppt2x8ayQhEpb3pjqjmb/2Q1wpDqqv?= =?us-ascii?Q?ZXeTG4fOd4rzZoXkl2Mb0ntTvIf2jiQfsbLgtirmyJHCWgwX3A2mei/Wnvcj?= =?us-ascii?Q?kF0LEY7N0NBBu55XfdMmHdiliUd8emEOdQc635QtuATYT+FDe/F7A4leqX/e?= =?us-ascii?Q?loMM4BnxCVqx4Hnn7ynyGi3q4E7WNqM5lgdP3OAUO06kL1XsUqum8fm2Ok27?= =?us-ascii?Q?biQU0tI0O2tYv+YUxiYpk1JWdopZJaNsGgJ3r5IZlSkwwfLk5OIjeNmGoixq?= =?us-ascii?Q?KH9MTkGlm9vZ/B1ZYuhVPvMieMVTuuJjUSKeBoqB64+C2k0meWz0Jp1D2Umu?= =?us-ascii?Q?eWNzC8usCCIyO7vpQrZUpOm4yXL6F3dwcUGzxBRIEZDDPRCZtFcA3Wel3TTn?= =?us-ascii?Q?T5ce5ZVGYB4iR3exyy65CszWAs6p0QinVS1eG0VIgpnvtRarKKXmI0LiYMy9?= =?us-ascii?Q?dSZRuEY1178FMhFwP6T0QRKtwHKHkpclk/MFERp6IHAXeVqkY6WPOSVt8KEE?= =?us-ascii?Q?Y6OCmlxTT5+BIk1UEZCJChPe/708KlsrNTP1VneOiYrNttYeeR4nVQ3cjfcX?= =?us-ascii?Q?OkJIvb9ojGL7La7VwA66Eztx8HadrXURfxYXA4ov9vTcWKSinxfgOLn0IG6Z?= =?us-ascii?Q?M+lUYOBOPa2Zui02jUvvahzDo9inWJhZcekSEstdXc6oYg=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?T3ZS0JFu/ISHdTbMURZhCdFPRQ8gPldSnKBAYj6jsGMOn/WbQTkfA9T4fmrH?= =?us-ascii?Q?j6bfrPBku5TXC0jrj4PuEUXKWR7fzYQ5RMIZy1PxgpHKnXfAwlgtxnLl1R3d?= =?us-ascii?Q?bSgER57l1KiFlydtig91fONGKLWAUvg0M4Uh5nx0G2AsWe5xnGVLflAPLI2n?= =?us-ascii?Q?WoQ8mHbHydgP1omVoxcntRqlxtdoKm3620zov7YoGamJellLG35wnsLxWih2?= =?us-ascii?Q?rGVYSGJE24dG43aBPOqCmA64wOq1aM7cjibbh1XTZTbgkIVQ5nu4sOWZObHw?= =?us-ascii?Q?M1PDYjr3gheokcLVU6J/dtFRa/ZfVwh4wW5UBx3Y3xUYxxtEuSuvdTZsu/Qz?= =?us-ascii?Q?BIxElHIVYWLbWSP1bPIJ2ZKy1icrIVLAMz2Oipty5d8meLxm0/V5UnDV7/cQ?= =?us-ascii?Q?nlbwPFrHwxYtpMGbAPbXB+gwtGQWkKV2JEvRJyUlnhUCCzv2RlWNKfWswtqN?= =?us-ascii?Q?II7LZBrNyMkz9otkvHV2bUqswet4hGP/3Zv8q9to6MAwutyL3fqPLeUoJ+ZK?= =?us-ascii?Q?H6ixFrfWPkhdn8Gugt6kvdT42166725pcAKQF6uOqZhFdoFmP63YdJvsQhdP?= =?us-ascii?Q?a0Teywo1Na3PGJgOuVyPMDPAInmqIcOkBQgA+xNncVVf/MgWjzeNRWcszWIT?= =?us-ascii?Q?9h9fSiLiROHKgpwRqYmEq1Dv4uqw7FJkX8br/axxR5gfp+1NxI/fbzU2HZAC?= =?us-ascii?Q?X0PVfZtkpb6FSlVA9myIJ3hvIpOOAsqJKV9EW3w95tY9wXMl0+ij7N2iiyJh?= =?us-ascii?Q?e5GJFWN9mJVsSVPRH/aIr464hC3D1AJyc3+p8yFTgxDX8dIXAhGZ9ygZKmjk?= =?us-ascii?Q?8KPwGmEdMs11UU1YXc7BPRm8GxndjwyEFJS2BpVUkmJdnl0v25syVitaAJ7G?= =?us-ascii?Q?cn8K6X6HoFziRCzN87IUAb3D2QRl/3Oy9JH9FjM69Ti50Uv8iuslaaAS7ots?= =?us-ascii?Q?mQH1l/xnMUVfbCjZSfBO00TbuPa4Fuu2Vw3H7V7CHj2aNxBlHKlxb9HIC6aU?= =?us-ascii?Q?JJPygsVeMdFiu6Otoh1T9yUI/f9b1LuLD4Xf8sG64ioYgiRdkO8OY8lPYx4s?= =?us-ascii?Q?D7f9v2R26lmwyXERax3N3XpwlpdlXDytKdRKB41hP0ilH5/nNq4OLgdHyva5?= =?us-ascii?Q?zGhvuzc37enuzaPtBzgvHOfhfaY/P1K6aMHntQBGpMIF6oEebqkKcNLqorkN?= =?us-ascii?Q?vuPrP+nRoOam1dAgx7pGXikiSnCmmdn9+exJw+/oNW72SdmyHS0BVIB23nqb?= =?us-ascii?Q?gJMQi7xbq/xbdlAaheRzmGmEG1ulcHAToNZUZecCnongeu/WJdOg6phERMNY?= =?us-ascii?Q?Z95zmfwuwir75X3aBzhjPnuek97s0X/agYADPDCnY9UxXHTlasuJY+zHPmKR?= =?us-ascii?Q?dVoKKmZKvsG/YlcptKfQqpL/wPZuvvRKNiD2ni9nlxEt9ut+iIJ8jDH+hbGR?= =?us-ascii?Q?MmwXeo+Etv3MXhv0QyyCYwgta6iXTrtWABwnONYYu6x+EDM/Gai2e7t3Bt/N?= =?us-ascii?Q?2JPU6nCX4v1+O163k0AFNgzYeVBOBbF81Fjb6jzSPzG1hW4aPWdYR/E3QfCC?= =?us-ascii?Q?4u95mWZvZFdPp6Uf8XVZ/PL/Aj05yFKoJHhVAc1/L7q9sYCZ2S8was78Dwof?= =?us-ascii?Q?oP6mlAhmxSvZglnimgvtSwS/siVJ6vcDP23RoYS2DSaT?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 58692884-7026-48ac-894d-08dcb85858a5 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:56.5268 (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: 76WaYXBbSKnKQWafrgRtfS7LMIdcoj0kSHPUdg44H+iOEolaOwR9HkKwQWyukWeelkKbOj2vbcjV6ggAMKi3pw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/util.h | 108 ++++++++++++++++++++++++ 1 file changed, 108 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..17089c673f3a --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/util.h @@ -0,0 +1,108 @@ +/* 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_adapter; + +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); + +int nxpwifi_download_vdll_block(struct nxpwifi_adapter *adapter, + u8 *block, u16 block_len); + +int nxpwifi_process_vdll_event(struct nxpwifi_private *priv, + struct sk_buff *skb); + +u64 nxpwifi_roc_cookie(struct nxpwifi_adapter *adapter); + +void nxpwifi_queue_work(struct nxpwifi_adapter *adapter, + struct work_struct *work); + +void nxpwifi_queue_delayed_work(struct nxpwifi_adapter *adapter, + struct delayed_work *dwork, + unsigned long delay); + +#endif /* !_NXPWIFI_UTIL_H_ */ --=20 2.34.1 From nobody Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010001.outbound.protection.outlook.com [52.101.69.1]) (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 791DE19DF40; Fri, 9 Aug 2024 09:48:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196886; cv=fail; b=s7dWfr/K45RF9CX/NziNwpBGE1mR1gYmI1sulcdjiithq/hKmMGL7wvW1Tq4D7tdlwny+6lNMhB6CWnBjoDZppi+I2ta9077E/N+RBZrkyKmE+OxxGWNvuwmQ/VqBpTeC7RbxDiV+FNEddJ+aXrO3uLfsp7DQKVJJSCrpN6zHrY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196886; c=relaxed/simple; bh=tpfCXag9igXOnb/Y7Mna/367mSvAiIZUSb89xTy6+as=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=jfcSsdrPnT00TWNBhH5fMn4B5G8H09QmZnftC4Qld/fNzGclYbcQfnYzKQDD78J0cS9vUNHNtiOWEMjDkJ1hzqfDakPN+5PtLFVuk414irwDS2EE/hoYORJwpCeoVeiQQsZ5WPppm4szh6g3osr2D+S/cEWwSct7/BmoJgQNrTA= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=Lv7+uiMy; arc=fail smtp.client-ip=52.101.69.1 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="Lv7+uiMy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=EJkE2g064Y3YrYxNksxOSzOootbxAFGEAdV0/V5LDdcKr8EZVeTYTtsQDpvL+A16RPLxmZ7m2y4ie10BOLosZwLVwIQNYY0Cm9qluc1SSA2GXBhTQmt/R2B3FDGURwSdozwvAjIv7jx6w/XGEcEa8YO+W72jMAiUtRhaafT9nhduB1i61wYrn3Z4yWusXpPHvxgEfyzicbFfJC2d4JTGcJ3b97OkEMop8LkyWaVshiPlnsKEYoluQfB2WCIbpq1A08XiVfi9IXsSvYzGaCdaAY8BLczCtbbZt6BKOkiBG4nqJV64VL5iDLoauWsU8YT5k3q86wt6sGbnghDXdUkF1A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=7zbgy+vJKXupLqBAyhE0jhVfMSCKGY18qtybv2w6LBI=; b=hxNOqDrXDR4ALnKn0fWKhumnoDBEr5AeFbRsIpWYoj5+71GYFyUyKiiInlN4ooH6/xNuOLMz8407S3reF+y9TK5UAWfnLxbKnAKAJ7FgI8C0yVNekKFx4mu0e2MNfgffRkjQvnKtprAijWpUQJNRI0LtJruoZSjS/UxLRAYYSLovDqCkP7o1knKCgrGYqGBe8ab1sb+21xYAtqqmakNWToRYyKsH+Px8y8NN65vS72zj3MWScGPte86HnRCTVudxdNhIKKCKPwvfE0zw7qHvmxlwy2x9yLERSOCz+Hse0VM+NydINkS3f+oQFebO17HglLbL+Cluqa2e8BrT/7dmmA== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7zbgy+vJKXupLqBAyhE0jhVfMSCKGY18qtybv2w6LBI=; b=Lv7+uiMyeGHCuvPTJXmhktmtc9Uoehd+iN2LyyxbAV0q+tb2s5+Ie4m9o4A33PGvCyoyri+cqFkzP9iaULzQI2WM4PRytq9cIzudVq/mKQGhN12VaB2QuTVXtXugcgAwTzU4PQSeA1O8kClLtWthiMrYceqgjaFATTEzS0aPOubP07GJkMS6q3aezshtT8kxo7xGAjxFayP+qRKwMgkaPUzrbD+URqxKza1IFGDPe/s0CfotYMNbFnQ3IbzXzThvfzZOEq5FL7IBo7/yHNKclZRjF451sqQOh8Zb4O4lO0zagC64vYxrYXLGMzq9402IaNFpRdFGN2/e7kmA2S3v5w== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:47: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:47:59 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 39/43] wifi: nxpwifi: add wmm.c Date: Fri, 9 Aug 2024 17:45:29 +0800 Message-Id: <20240809094533.1660-40-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 9a4c2686-1d3f-40d0-a1ac-08dcb8585a7a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?v1FgRAcI/w8rz9fx6vljXLtAPSjXRNu698BhHexA6VCGAmVvKfp28s2ft7dG?= =?us-ascii?Q?LzeJDss79q0RX0aZwEakHM3BbFSQ8irtoaDoWXQX85WDSMb2btetHemlwC5t?= =?us-ascii?Q?gampLAd2kCvXI4YrmpzrENdwGR5p/qQdJ/z6GkRQV7l2XKVuTWiUwG0iuDW5?= =?us-ascii?Q?UWGP57tDVb1oFBK0EOrOhKzSm4AVh32Ylj+BaYAGbQyxeFqfMFGvEfu6s2yN?= =?us-ascii?Q?yfI1VXx5RnqqfwaSeV9lePwg+rstfU8QMC5ofzJB0rhM96omldysnzCvFYrX?= =?us-ascii?Q?miXjYQ/yFckZr9c4/YfkcVkS9BqGaY8PM7ar29oQDL3ZfHKhxfAcLmvQnD/d?= =?us-ascii?Q?mxUN/pq5DGrkzg6IB66Il6feF4g1HS0c/uLjwhkNTpep+qbK7lVFTMS8btEy?= =?us-ascii?Q?TSUGtkJRU/5LmPvSHE71qeYo/LlUsLedhxe2OOfb/2aVKX1oZPsfv/COQ3DV?= =?us-ascii?Q?hv6n3jl/YzIVLsvjM2Hl7Z6TcJDTvJfqmaGta01Da0OBiYHktn9q/cKco/cX?= =?us-ascii?Q?azQugXMLO7/OCIp3btI2JYKRYAgwljekdsoSZPhVnA5pubDoZtlseCaxOmA1?= =?us-ascii?Q?A9ylDIDH9SwGu21/5mHQ0jAmAl2tK3uisRq2abg8d06uHUu8QzpHelvcYBM5?= =?us-ascii?Q?ot0KH2p9vd8VI5DYR+FqoXmNf7cbHoZW3ofH9RL4Bkcf2p+Gp8Z7aoM0mf1U?= =?us-ascii?Q?eQqlTkh+ncbxGG/yhmehJH/MqAoFKAMYywIrhzPnad2J9ZETKhZM7zxOVcbr?= =?us-ascii?Q?Kxfw8ev1vl5uo5emZaRdJa4pXNb9hM3kXN4fqQiWDawQYFjYktMVHese+l74?= =?us-ascii?Q?nrTEvmrw2J04uCULq41RIfGyzfU9p0H4aaqn+4FngKgce184wY6V1+T7Tzcf?= =?us-ascii?Q?hqn34mm50BLERgWvoRYqOmp3rgMF27USeS36Pkgeq6qiLSLE1hracl4TYaIQ?= =?us-ascii?Q?h6WNaVuWs9Ifg5GNH07V+ZxrCQZgWuUgqBxhb50jOgOlTI8jsEmEqlSEEcqJ?= =?us-ascii?Q?1pBRIO/05aB/D26RYORlDNE9iBb3Sp7l+jBW+8/i7tRQ8JqSGJpYAVckEGQB?= =?us-ascii?Q?DBNgw9j37ri52Q0dxNgMaKe3bBa7TaGnx1y2jRs84R9OJ7YE2yfLRUYCltwI?= =?us-ascii?Q?X681DvIvaaPxZNwFPRlfVrQeaVj7Y3KSvp7kn6HKh8hmCT7y72WMs/CHYOdr?= =?us-ascii?Q?IrGxKl/VXl993wy8iWiSkebVEnGYe5pdoFIEyeM0kTtF/EsSrZv54Oh1SGVY?= =?us-ascii?Q?LG16LXKEdu5WxWeCJNDKoDIJNohqXQJstfVTNLQjtQev/68KHeyUq1rvaQyL?= =?us-ascii?Q?a7BC2sX7xHy3Lld5CGS4u/0Wt8fnJ2JR+3b6Xd/haGgY+w=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?+hhiuO9GPes/tonJOm4NwRWRTTfLiLDwkRer/MrdubYjjt9M0ST8EQntG5h9?= =?us-ascii?Q?Tugj6/l543wf/UqU/PsD+RIqpfipOsAH71xMdPMtp8vRQB+8AUjR3j7JASmv?= =?us-ascii?Q?s4v2WC3OD0wtiC9SKpmZ+3Y1Be5qOCFGyZ393mrK2QkyGg9zgd9P8XNm71u0?= =?us-ascii?Q?EtM2xqsTzdtL00YZofF0ghH1AZtfrRY+y4DvqdnGtZLAfIUDLF30rglaC6c8?= =?us-ascii?Q?HOO/cnUsKvheYSVb9hCD1+Y5FPnYqx6/93SnCgLSWFuIOu6S+2atFRi2HPg9?= =?us-ascii?Q?l6g0717wX1MLgO5um9fgZAyMn09US5y04UO8xCwpBzybGSw5Mz0hMITh0cLo?= =?us-ascii?Q?CfUnZbKe1EYFyEdJC0QVB00mYiE0gRAFMUL8oYjbv1O/jw/H8IZ9DUTLQlnm?= =?us-ascii?Q?fLqySrpBj8WIcxPDS7drd7VsYSYhpMxpl4lk1jc6eThfA4mFF45q4e5EvSv3?= =?us-ascii?Q?l/SXUxcJ5fv9MTVvdUpZcRv6NzheXHVthPS+fAjYnjf+DQWc+kXk1Akt3nW5?= =?us-ascii?Q?xUznGlGNDY4V3tOJVNveMrkIvMaYaJAQlgA6mhDEyj84/v36Im3WYSTTXEBz?= =?us-ascii?Q?jI9TbIgctc/D0PL/uaT8Hut+gKMzXTBVH0lbyBAtuUfa7MZbw+WNQ1aiKmFR?= =?us-ascii?Q?2h2UyZBPJcRWcRk0iIVvQq2BhXjHyf/dBSR1dJXkOeXyY8oLd54y/djIfGI4?= =?us-ascii?Q?A7NAdV9Wv0NWigrcQKK9YM52U4PmghVyQa2yArLqgemqJh1FPCTq4BReeUCn?= =?us-ascii?Q?tnSSvaTcwvhdpys2bqPIxPtZqkm9Eg+WlmznriOzXDniBuIhTWZkDsY7Wv4q?= =?us-ascii?Q?FcXj35CrHzUc7RKCGgH2SrdUzdWyQ97dHwfl0sw/Fzhb8XmH3WsBAIz+1/H8?= =?us-ascii?Q?84/Mof8soEErjl9TaOVBaIUyWqCZW2qbALxbjtk/eevhvSYvRGLbd2gO4d+E?= =?us-ascii?Q?JNtBsIB+dUMgJIEt8P9VhBVkGVSLorUu1/m0rgcoW80RiU57RsYuZUrNOchE?= =?us-ascii?Q?14/DjHIyajJL2ogBBMrIfI5Ah0wJmjfGQUxiWq+D3BFoMN5wL+CxswB18ngX?= =?us-ascii?Q?Usndhnq/wU1xnP9kyVTjY1PY+uUcuyGU3vUegytOLmlAoMfE8/p6X/dlIASl?= =?us-ascii?Q?3PbgYpaoV5pgm/+6SP7t4POLWiv4lQC+bin+1oaw/fpXywEX58jAt/GQPFX+?= =?us-ascii?Q?PRT0jbLQmJYSaRkW3zjslipqgD4oljDZvG4rz49WoOXkm9JClKiLQ66LwaKe?= =?us-ascii?Q?dnlmAQRbEXCG2hYh9VA4m8TzstEK09odTVGpyUEny0sAl2YSyES9z6UgxRf0?= =?us-ascii?Q?PNObh832LnO3rYmNvmPrV0ySLAImhJRsQYVscjlr6aMQXVTlByNF4jeMZY72?= =?us-ascii?Q?1a4nmcAjFpJaJpyN5ZAn6LGW63gFVhr9DFGVW6UT4WFdf+yQWqn9XrWzWYxs?= =?us-ascii?Q?LeefLJlOjBlFka8VkwRbDmtAUXQ8NlqoSZyVaHyiv6KEIvhKFszULBYaeEJL?= =?us-ascii?Q?VuzopMI4HJXzoooRfN1MDnMEHPl4BuQChiVJtR9Pa/t4PunJQfJWwyjz31Xx?= =?us-ascii?Q?Efhx/eQqOiSoK+iI7g7KrO0aVDRrYgMzUB2tPvgxB8BzlLVxKOurrvrSRLlU?= =?us-ascii?Q?GOZDASNLB+8WCfD11XPJdF4f8yTR2lAtE9bFvvv29HcD?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9a4c2686-1d3f-40d0-a1ac-08dcb8585a7a X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:47:59.7558 (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: c9FIZNTjYPKaBw0+O0Sb6gHyLIDHV2y8jNUvetk9YM0Oc4vsEv5SE8AQMHfUITdDJGv6DArE65lc/m6u2wucIQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/wmm.c | 1379 ++++++++++++++++++++++++ 1 file changed, 1379 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..d8ae54458096 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/wmm.c @@ -0,0 +1,1379 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NXP Wireless LAN device driver: WMM + * + * Copyright 2011-2024 NXP + */ + +#include "decl.h" +#include "cfg.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 ieee80211_wmm_ac_param *ac_param) +{ + 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 + & NXPWIFI_ACI) >> 5]], + (ac_param->aci_aifsn & NXPWIFI_ACI) >> 5, + (ac_param->aci_aifsn & NXPWIFI_ACM) >> 4, + ac_param->aci_aifsn & NXPWIFI_AIFSN); + pr_debug("EcwMin=3D%d, EcwMax=3D%d, TxopLimit=3D%d\n", + ac_param->cw & NXPWIFI_ECW_MIN, + (ac_param->cw & NXPWIFI_ECW_MAX) >> 4, + le16_to_cpu(ac_param->txop_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 ieee80211_wmm_param_ie *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 & + IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, + wmm_ie->reserved); + + for (num_ac =3D 0; num_ac < ARRAY_SIZE(wmm_ie->ac); num_ac++) { + u8 ecw =3D wmm_ie->ac[num_ac].cw; + u8 aci_aifsn =3D wmm_ie->ac[num_ac].aci_aifsn; + + 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[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); + } +} + +bool 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 (!skb_queue_empty(&priv->bypass_txq)) + return false; + } + + return true; +} + +/* This function checks if WMM Tx queue is empty. + */ +bool 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 (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. + */ +bool 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 ieee80211_wmm_param_ie *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 ieee80211_wmm_param_ie *)(curr + 2); + wmm_param_ie->len =3D (u8)tlv_len; + wmm_param_ie->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 & mask); + + if (wmm_param_ie->len + 2 > + sizeof(struct ieee80211_wmm_param_ie)) + break; + + memcpy(&priv->curr_bss_params.bss_descriptor.wmm_ie, + wmm_param_ie, wmm_param_ie->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 ieee80211_wmm_param_ie *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->element_id); + + if ((priv->wmm_required || + (ht_cap && (priv->adapter->config_bands & BAND_GN || + priv->adapter->config_bands & BAND_AN))) && + wmm_ie->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 & 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; + + /* 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 bool +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 bool +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; + 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 -EINPROGRESS: + break; + case 0: + nxpwifi_write_data_complete(adapter, skb, 0, ret); + break; + default: + 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; + } + + 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 -ENOENT; + + 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 -EINVAL; + } + + 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 (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 Sat Feb 7 11:38:14 2026 Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11010001.outbound.protection.outlook.com [52.101.69.1]) (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 BDDAD19D89A; Fri, 9 Aug 2024 09:48:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.69.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196890; cv=fail; b=o0oulWLLFfkpa6uiCCwxrqf2PV4P5E+AvCDXYt77kAHF8OVPYrcrCEvSw8MbJxOkskKfOnj2aBL6/KVljDB3DzsAXadY9Lade3E1xaMYYqUiIcL2xLVjSIctHeB20PzPcxtvMQQjBqYG3r96nYGLbO0jE+MQ3SyYMpBM3wa4bp8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196890; c=relaxed/simple; bh=FOt+cZidB2Yxar++XFT2S53xkdTDVNiquxmSCJazfEQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=F3wHcJJr304UD2MzRY9GxcHQsLthFyTlcEE/CHiGmdzVDFe8TjADfOXhCnSi3zGPRahxKhUD7mC+f3w7VQoZ2u+IbRHkTtpdsT79uz/tBWPPDjYSbOnPp4DHt8CQI9+Gj53KCwo0JaKtQKzXzce8p8yqtcaL3pqCsPEBJ2pM9U0= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=krfEM5IE; arc=fail smtp.client-ip=52.101.69.1 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="krfEM5IE" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=hfl7ddqeZNF1uINr/WwzOR/q7qWdkqCn/3fL5YgB/Rvget+K/4g2w0XacsghH2+a8FeoeOpbsoAmV56owTBsF8kUBKMfiQCb0HO7skOj+/c7FcoZXuRbdtS7VIJWghICFnS992TdU2hTBCXyorUW1xecNYgB3nWrSaZIRK4YEGA9rm9Cp2UOa14DvxSu9UXu4o+tKxILByyB8Snq+1UrHQXtbxKpjNzph/51Kw+w9VrNCwWFQWJs2FkqJbBJfAT92lntLXqtfRoEAYrRcg6wCHackwNa9VhxNbU/m6cku//bJdFHNOs1amf0wovRe7Y7LXaf7adfJh8no2NgQ1JJcw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=aXykF0am/9voC6dIHGjayFXtS8btaToNjb0SipAQ/JA=; b=WotAqpkN5xCXsRbluvVy+pGp+Opgraw3eHxf1JJ1d1KY1n+/C3Mbt7GV9fEeK1Xod+Af06U7oTfU97mziKvkIqSzsU66RNOikAvI0k88WDVS+eXRSq/GXVnirYkvQluZtafh0TGYS0X7zYK8PITnIzfH9zpW9TJ6gfNFrUCOmi13mUhyF6OTU/dTE8wtbFDNmjzmYi6Qdjuyypxae2tcHMi7Xr/2AGMTCThIX+p8nkYT+CWplHVnaA92KEFVqxnYTuiz/5doAleEGxwrAN3rmhZDXXR11lAelzOQ5vP8OnwNJzFN6Ug9vQ8NNSL47UF/zSWqd2Pf8t65DvXocf83/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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=aXykF0am/9voC6dIHGjayFXtS8btaToNjb0SipAQ/JA=; b=krfEM5IEFqtEN8RElazMFDTd+4IQmMKdS9Mj61bWKex6m5f7Wbl5Cyt5UIc8SM0wywBqoyxZlOblL9LKy7+UrbhpIgSjmyFWw7lk/dXQwHnTeb/fy9A7krLMNN6vDBS/R4ltQeYJOx1UCFmig8laU9wsFk8X9RG5NMc7WlkInrvG18t4VSp1LABQJrf8vUw3BZggCZlXEYDSmtCqi+K6k0vijqRTuenP8RodWc00+BPOea2YoJlhvEHHNfZRYxn132Mb9U/o58j96BC4UGg1HcwAaUcQkMkIMrx2U/LBsbCty1Z79uzEYF7TEvfmQvBMbWWH5F4UohjVXjmQwGZOHA== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:48:03 +0000 Received: from PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257]) by PA4PR04MB9638.eurprd04.prod.outlook.com ([fe80::f950:3bb6:6848:2257%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:48:02 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 40/43] wifi: nxpwifi: add wmm.h Date: Fri, 9 Aug 2024 17:45:30 +0800 Message-Id: <20240809094533.1660-41-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 1998d713-97a0-4964-a6c1-08dcb8585c67 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?bQIGOWrsf619JbnG3UAArYEZU/n/coICZLCThxX2iQZC5R7TpYRfL0aIHsQR?= =?us-ascii?Q?SK63p/ELNVNmgFFN7dYvsOeNytzDID26g9BmTputJxzMYrSBT0chwNvKN5qx?= =?us-ascii?Q?j2PZZfEfX5gJCVnoH/uw07Tkv0QZj1aGqRQhz/eDoDVlntP1LlfsALnPYqTZ?= =?us-ascii?Q?x/59rM+8cbSelHacWYU26Z59eLbwAqqyyX3YSBoSTMwrcemyIzjqzkWG2oIG?= =?us-ascii?Q?onH1Z49Rf5ipnn7VZ1rSG8c5M5vz2MnOMwYjHfXD9GHwz1qpHwxNpuQ7OdAc?= =?us-ascii?Q?PdMrB6OY0R4jkN6MimSbHumw6op6I5OYHYSS8UqI0sJSIM097PqhOz9hXU5C?= =?us-ascii?Q?jeYczfW0m/ZcNxN4lrC1VLaFnDVeko9YBLODJFFaD8e+uvEjbXKBwEYR1TW9?= =?us-ascii?Q?1DEgi4ga89LMORH317mqOy6ixzA+G/ozdYlJ8SdRUsFx3fgDy8TjAx3ya//5?= =?us-ascii?Q?Djpoz6kzSQcJueuOxmgMcqnVItwAn5dxSZ0/3ZFZcp3g//rMYostgcV1nPBQ?= =?us-ascii?Q?OuHO+fn1U8tfss+qcn5crId295+BKNAXozioh+Jrn7Eiga81oNGU8Oco9b+f?= =?us-ascii?Q?v2DB9nPlSd+DO+pArj03T3mDbDaYuF8BDGEibUMg6la+q/fhOZpGgqP2ZaPz?= =?us-ascii?Q?ErV6LA6ze7SHIirM9+UD1rM+3ZpxRJC3DM3MpxV64qhZHUsN1vqFIV6UnWOn?= =?us-ascii?Q?7n41XT/X9FD6cMsG+m/1OoRty+5CMfIQGSG0WtvlOUzalfHknjabphOjgeyE?= =?us-ascii?Q?DcOs/zVkhppvdhuBAqQnuSZI66hy21JhbldCv9etO/HhfOhWA0TACu9S69VI?= =?us-ascii?Q?QYx457Yrw1ftVrZ/aXFJnPEUn5FX186e2p1ijGQllVQnwV3l+k6zgbskg/Sn?= =?us-ascii?Q?Rpa65fj9SMukyfV/zGzJtJjElyfCws8z8GSDgzMmuqO7747XRHOHndDxnlL1?= =?us-ascii?Q?hRsFefE/+QweMNsmk9P7lbd5tFhiSigYArlgq57fEbxmPdWpMrs5eX9wSPix?= =?us-ascii?Q?Jdvyt3/M6yUoEMCyicYlubYRupsxaCfLUOx/QNS0fsPAY2RzGGGDQmWE+BIG?= =?us-ascii?Q?HcUSiwKbADR9FLhQjzkBsGIPkySzjAMoYjqms9mtQ1V3CD49Fa08+YyBdx5J?= =?us-ascii?Q?qP7QjFGIdODYJ5BtTC3la/mqDjkGK7GHYtfIoyqiGQ5m6nSSt/PB4l94HMMb?= =?us-ascii?Q?18JB/KO3hwX+uHbHWEW+uQ69gIw/LUlUKUaSD/S7mh+ad+5DzdRZ7eYewoB6?= =?us-ascii?Q?lyMgnuiobdMaqQq4NpbMl8S/xelTMatVwvmEPJrT9Hd7nsTixfYpqlu5K/aB?= =?us-ascii?Q?4jsvA22jC2uMnvKitSheZ3Aih2xnjCI+vn8g1pf7XleF7Q=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?As4rWfdmH5Szb0T+YAGy3AiNgxPAr7WfgRRyiwY5XtFbZBWIPyhtW9kfWiXO?= =?us-ascii?Q?Mr4GIhmg6aPbiNX4fwZxqv59AAhMzurrgOwn6u1kX/6bYYN9Gzo0s/rkN22j?= =?us-ascii?Q?01oUFG6OlcSxl9IzGME9W/GBCy/xrdqVohlz7TCfdvhpXnrd+Nxit0ynqVnI?= =?us-ascii?Q?1b/WPRDYZyYoXQCjDTHMiJUkEiDh5l4XJJbh++IDGhdt3MAjYVcR0WEdYHQC?= =?us-ascii?Q?LIiEQ+gTsmH3xsoQU8lI+aRCfo5JIerRIigJJSNKhNG60mfhh7Xp8EcfPRs5?= =?us-ascii?Q?TRqjmyLymgQkJzwrhp38gSvAV5AqpsaLSyaAlL1L2atZMgRZIs/JXNZMF2LA?= =?us-ascii?Q?CGXUBtMRXaYhg/jF/LOB9ApCsKvDGzEpf8mMw3gVugi0rpxK+l94CzWNnK6Q?= =?us-ascii?Q?oYXWdjfu2AuM4e/HZH0jtiaoPDJTAcDEVq6Beeiqmj6CMxuxnmNZKY9mmeV3?= =?us-ascii?Q?H7ftkkNZ4+kpKkdzoPQzlPEfxF6crmtTQNHkGP7WsYcajOE8cCBmhSApIm0j?= =?us-ascii?Q?qTZcgR7bHs7CB8Hwh62jfJuOvc6AyefE3Mr5bRgAkzRxpY6cyI1YOttcItHL?= =?us-ascii?Q?RYMf89WlvghgYQXFTc3WoFVbxpCQlRoy3Qll1aQP9BGm4U0RWxAMZEJ67uWB?= =?us-ascii?Q?mDWy/3bG3fYntXu5C0eDsUTb51X9056sLa6O9DK8qclNmwKziRuA60a9y8lj?= =?us-ascii?Q?bEQSQKElJYnbTzNya2VYapN3JLu44dU8gg8Mba87N1LQssQKAOUgUTaPMuVc?= =?us-ascii?Q?V7Yn3qMZo/KysXZfqi2VGFk9Ze3osqmMWpyUF8qPho3d6psB8GSBxHN1dMyj?= =?us-ascii?Q?jz02lXI34S76Uh6nHKZctNsN8dFJ+NzCgAE1UkUwcFTC/JWNXJ1yhG02M3RG?= =?us-ascii?Q?TrkzoNUyllLO5L6KI4n3xAjze8ST4OX2UNVCXYPvP1rIMxJQcx/j7l5bMzOt?= =?us-ascii?Q?zCGpvPYU6W3oXzblRciHfdlarCKWaKy+yYVAF6+INAaLMqo2bnWzrTUjvb33?= =?us-ascii?Q?Ng91ysweYOoyvHqXilYbpZBzlMktNsUui7MnZhozWV6CWxVQvUPRaL/AghjW?= =?us-ascii?Q?0DK5AutwU/1MVWIQ2HZ2tY0bSVol74HBLgzzvPuQbeABhNhg4/fQKDi/zkK3?= =?us-ascii?Q?dkWDvCFnsxNKT8zvbP6JWUqIRXbAFjTHSFVxOFQEAKUH487uGaz5eoKleOHb?= =?us-ascii?Q?iy4AyG+ZCHwcLXoIVSvmkqez7hhZf8WbGndEySujcLQjTC0EJW1CnPdNy+el?= =?us-ascii?Q?Zy3yhtmJ208jQO6Qp/a20nTDZyRXx6qHlkBtFPZ2lbivhgOMZ6l+fpYkP532?= =?us-ascii?Q?VygOQOM35P/RSFhzzK2vgJFoE2/E2o423tdHp1NsAMwMi2/z28xvzlcn7KNf?= =?us-ascii?Q?atUZ6pc0VGK23YUkj8+o9dZNKNVgeeUzyKeaojL+1w/702CnAKVW924eQG4B?= =?us-ascii?Q?6xgbfdSidbJOKfaYk3e4TL35s9RsdSEgbxlsoaXxo5RIT1L5WPRniieYrwtW?= =?us-ascii?Q?G7K6f8EgnoTJsIw7Sw+VAQUutJukrZmcDIqgw+/6rTzUZmq+JXU0tEN1b3W7?= =?us-ascii?Q?nXXh1UKvXiOUgHG0mwA4l9wo5At8v2fwSebXLu5kB514Nj2E0IMbCkCuiDB9?= =?us-ascii?Q?cBH4do0+j3talkFUlZTorVfvXjCblEyu7GFdxthlLMu4?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1998d713-97a0-4964-a6c1-08dcb8585c67 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:48:02.8881 (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: dVKJN+bkww5Bst7jzEASm75AIksW1n6it7v4ugLSfZC5Dz4PU1m8E5cT9VpdSLaOdHRD3AOWkGAPCZtuBEo9ew== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 Content-Type: text/plain; charset="utf-8" --- drivers/net/wireless/nxp/nxpwifi/wmm.h | 78 ++++++++++++++++++++++++++ 1 file changed, 78 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..fc9bbb989144 --- /dev/null +++ b/drivers/net/wireless/nxp/nxpwifi/wmm.h @@ -0,0 +1,78 @@ +/* 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; +} + +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); + +bool nxpwifi_wmm_lists_empty(struct nxpwifi_adapter *adapter); +bool 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); +bool 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 ieee80211_wmm_param_ie *wmmie, + struct ieee80211_ht_cap *htcap); + +void nxpwifi_wmm_setup_queue_priorities(struct nxpwifi_private *priv, + struct ieee80211_wmm_param_ie *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 Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011065.outbound.protection.outlook.com [52.101.70.65]) (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 7711E19E826; Fri, 9 Aug 2024 09:48:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196895; cv=fail; b=EZlLDNztiAZOPVA4qDdESSBzS627lWeZN5KOcRhHeSqapfjKD/Ksmlorea5kAMnRU5Di1sdIFqNXy533J+OuWkLMH27+377X8pq6pcQuRNR9kdKQ/v8wQFcKvg4teCH1B1eTodGvFrBKMsJdlratKSsB6pgQrbneg2HzPUTCiF4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196895; c=relaxed/simple; bh=n17QDADJXrjc3wuFOUIEeEJWZL+PpjoYbwMv0BO0H3I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=dNVXJq0FKi4DKUiv6eL9/uW9TEhzVUvB8EhczHtA7Kk3zOhnZ4MNdZ4vleDjtyDtzLFOLDdleov9AyO5+ibmqsyEkrk9NWQtgHGiFoMCqpHTdis/HEPKdAcvwQZDwlmaW/ETbxCyuzAxOb2wYPA8nHx3lgOQqto6dLiQgsoB3fk= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=CaSPWbaW; arc=fail smtp.client-ip=52.101.70.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="CaSPWbaW" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UoxjDra0kwceiVxKLsL0WoyqmVzNbdjEEfGw8GTNjmx/+IvVHusr+8oZWvj2VXrrP//jPfNUizH5+4WqbvdN78l3n0hEPrGU7ASb3M0sOd4Lb3/UIOPitE2f/7QOE0jv41SlDGEIniRmJju8NIxjcoUULNoIPvJfQJsWh8QecwVykYqwzmLeFAD1wplftKBR6gKgPgLC4GgG5Q5lSWLVMKHrXMTj4x9ci6M90TZHkzri+yXSaQ5fMQ8Vv2LpxNEFfExm42EGZnNueuek+RAVmsxTqM2WBGKgn1+kM9BfEJehH5j1/5PVhaf202AU3EYFMtIZ0DvmnnEkYaGcUCRaPQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=DUpUA2ia2xppuxw8nSNWAcwX48cZIngt31uNtniNw+So7Sh2iZuHQ4nasjFF846aCou/JnAOiOHGnKZW0f9euYjq6VcIN9NvMO72yQ+vpVv61N+CQgVDXpIs6xU5768nSa4rFpYZw+S7SIRfrtk7QU014WtRcQ36SFHgSbEo2xwjHq2ODjLJQFHt7lCioZjval7lN5wsZKZ0wRSb6HC7DkZ9TTQIdO9OhKUKJdO4uHMvkLTFwQnjAdXYEYCkzBAYAz1Ow/tzsoe3TfFtVWaI6uoP4+JNA8nm/FPLgLdOwcsEUf+lW/rGQU+7nJLs0qwfaEzTb+JFChSppVamuQ/CLQ== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Z7MeuOgQrbSP0BuVj0rjMFxdtU8YgEfcffhYnh1ojkU=; b=CaSPWbaWb8cORNfbEgQrnSIQzX5RTx8eUNiuhUZrRaDTkjKeHIfu0k9BdmyMdiyYbnZMbM2/FtxmLp5ZyrgNjqqpkAbxY9bJKA67dx5WG9HRfXSo7u6PAsNdcDYwt8Xz2jnwbFkpdVCboxgwLZtQAdsB/5kKjEOutBtynN0MJShynFSI+60ACAKTpXLuszmJidiPAAI1MB0x1ZEHmzsIu2YGWWdQ0KlRkUGSI61YyC/9Yq/b561D01rtKKGPef8N3AFNbZdpDVjGJ0otoXkE/yk2tiUgUCOlnpT4whF5z9GPkGs3myNrGx0JMdGI8hzbdlBtzme6pEJLzZbZAOyA8g== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:48: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:48:06 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 41/43] wifi: nxpwifi: add nxp sdio vendor id and iw61x device id Date: Fri, 9 Aug 2024 17:45:31 +0800 Message-Id: <20240809094533.1660-42-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 82a8b469-f040-4102-eae7-08dcb8585e43 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?l4iqm7iZP0FRUrvJMtj8bAoV1ZI0mvGyFKN/a7E7si9WDYyJBd/qto9880Sd?= =?us-ascii?Q?EDPPXrJYBBl2gVmJAE/Q7f3YSvHHSjG37W0hy9ZWbkjfvP/duvo9he+vvrWI?= =?us-ascii?Q?3QlRL/vO8mBwxpGataMEYzEx9Wems55v6O5xAFrOjWDtezs8RcEx6TnRMG+O?= =?us-ascii?Q?Z+2/vHPZTz75vf+pGfBbFMWPfx+wc9UffOesp2eLGr2wW69I/d8yUNgFzVXY?= =?us-ascii?Q?CKXxsJk254+CUSKDO14iVc34wc7hiC7uFN8kBaa6FxOcX4Nn1VjJyCaKkGVG?= =?us-ascii?Q?9cMv4bAxmbUjepSUqvojHVQMRQ68EbqZeHwbZ4Kwhn0f6iI0+k+5eBzSO4Su?= =?us-ascii?Q?lmG04cGCjLOXSEAH4OU2zof8IekjyJO0vKqE/xOcQk1jXkWtJC+UeErwKTXP?= =?us-ascii?Q?hU7gnrHBobsirMnCgO4D1A3ik3MauPQ4t9JYF5ocA21JAbfcpoVMCohyW/t2?= =?us-ascii?Q?ZuC00uIlL0X733iwJrWt6c1xegvvR8WNZIhmoeo026KRpPXv/NoxMyXI+WrI?= =?us-ascii?Q?NFLEdErATMKuPXIOAHkfhcucGqfLOZCS4MhDskyK6KxTU7mYyXH/NMAD1xF8?= =?us-ascii?Q?a966Jk2K5e6qSogE8s4T57LygTcvqom7z5Ci5HnahOQyD9SYmigkGWrI08rP?= =?us-ascii?Q?LgIy2eUQMqRpXwV4cp4gHksnxGiZngvl/cO2MAwGska779IY5PlFxDjQWpAc?= =?us-ascii?Q?6f5rF9rhFbivmVVXDsEK47WsPLFWtHhguKFEiU8Na+EZdRCWlE94Z3tC+f8P?= =?us-ascii?Q?B6ywFOmVGk9Gx1nxLLkzakkPjJftmW6PewYSGB+v5ezMG5BHkDZwl9u7Vu/r?= =?us-ascii?Q?f0vS3QLKcwApxyjaCcNXnQeJy23b4Czf9lAsqYpmShQOVEZOeZ5AC8/yIJJY?= =?us-ascii?Q?QIlQhGrV7bUGxowWtGSkDStKBONWh1uOcwuWHPuRRyhzBFI9pBoBqURclNKw?= =?us-ascii?Q?gdFmzpuRDVAOu1HTWevsyD+yu9k8g2DMu9XTczojUKVAiOGmw/uRaVGj/IyT?= =?us-ascii?Q?e73w0EGzmIl7wnH5NH/uOGq9zCIGqU76puZBauqHNm+7UYGsj+NqfUhEleX3?= =?us-ascii?Q?cFsjiuax8JZYbJsWVcSZleqKRLydnP8iil7N91LsE28oGjl/jchsALfIbotJ?= =?us-ascii?Q?hNQbocDxorkjJH9QKH37m1sBS2JgOoVpJ+vjDbOyj1XDdCciEJZAFIT85yG3?= =?us-ascii?Q?p0gHJF06bGHXc7oNulUvhYSmBQE1VAPb/fVWjYOduMWhLOUpH6mI40cnKcyE?= =?us-ascii?Q?timSWDOuSw85DmhWpNdriKfqTTSoSkep0krv8vv88+T7AzZzUzJgyOgdccu1?= =?us-ascii?Q?eNjEtjS63lMOqHlX35b1PlfKJ688yw4ItkhLUAh5TkdpEQ=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?AVVZ8X9kRmbDSUOX0jZSbZipGIwOxzjfm1caZJv1k6ebbltd/kQTx14OmN8U?= =?us-ascii?Q?srZVZSJODjqoWZbJ2UYLg/mJWsOGUxqCbhw4Osz1+09LDjUMQEQLpJ3RW+5b?= =?us-ascii?Q?D6epVCOkILULCuNtQcs9OCPpdWfBIBmTbMbuwNOY/4YjXeB3KQl5UO5sKRzY?= =?us-ascii?Q?tcPl60nRjXT9PahShCctgHUM47IoUaYQGXX6IPOmyQt/fHjWyztfNnFFFkyq?= =?us-ascii?Q?PwVOLg4Nz8UQeNWr2Z6JoW2XsLJ7yuKQtevUd70I5lKTZhdMDjdaihH4Ic9a?= =?us-ascii?Q?CzLGll8i/OsYTn4kpEfUadaGopAVGC080DJYJM21MZNIMKtzY73IQr5rUkxP?= =?us-ascii?Q?E8nXqf8tevWk/6bMkivA5DzTwI1JAmSw351u0678ngz6XWTDQNXvinaX40/C?= =?us-ascii?Q?ummvsThQW2koZR2tB4feVixZqbJjJuAdprutQ2/bMKwh3q/UZpSYtw29VRkl?= =?us-ascii?Q?S3oJTLL5bKscyxVQ/f3Mu+GO1qf+m1L3osurnvO7FMUw043gnEdnEvzjeqFu?= =?us-ascii?Q?q5hf4dKkWp01DsBA4oA/hyoqJXoe/PwI7OTb/pbpdxRo5msxF5hs1AXmLGnP?= =?us-ascii?Q?UQTWx5E9m3jRJi26F0QzsgrwD8fhq5Yox9w1f32XrFrZFWMMNFzOdZJ9sSyN?= =?us-ascii?Q?UuEjyem/zz8XuE8iEXxHRrkk8Yni9tGxg1/tYYPOcPl+d2XpnujBeBCiiVoO?= =?us-ascii?Q?/RLc2ywQyXiPzITI9HFFYhXjRON6aqFz2Ss75Ozp5NmuOsB5GiU1YAgPlgK/?= =?us-ascii?Q?Y4FURX0Hp72ye6LA3BNhH2Y3YqjK8gVePfOZ/mzKTW2AkiggL8KNdRGIF0YC?= =?us-ascii?Q?rb6qiVdodOgQiMIXkQ1Wo/7WmRBeEWdENNhDLeEc5C/1hvkP2Uw61io97kn7?= =?us-ascii?Q?0d9Hl3VJfASzNDe+9VJwwR+dLAhTophcMg8VzJXDEy1fnNOdrhXx0LcCVREu?= =?us-ascii?Q?FqV6Z4L6lQppoI0PYwu6dQJ9g99OuZLnGfhec8hel82Vyl/CRgmQGsZ+s0mG?= =?us-ascii?Q?7oEWOxNjK+wLVBPqER7Jyx5FjoHPC/FaimUrJhNxEIQg5st9OHL2BAlBIGTi?= =?us-ascii?Q?4eA297P5QA1+n5OT7B/ZhQVAvfmr9SSDNNKfgAsWkYK64hAJfx06wYv3bTt/?= =?us-ascii?Q?cYsBtsoEyi3H27i+pnWE6CWVTYLsPjTOarOQgsycE+wWeAP9VU67lbgXAp2F?= =?us-ascii?Q?y6EgTRb8XqZ5fA2a0JHKCGRNaDVXx6rUF0XefmPmQuGFmXncvArdCWcXQdbj?= =?us-ascii?Q?sBEdLSC3xKKAotDATActO9liICZU0iEaFIgE9pdTRChBLaXCMKxx88LPW9Tx?= =?us-ascii?Q?3MVsHfBcq1yZgR3O1DmUS69zR+gmkM/6Syc6yPZhczf/daqyj6N0rIGMu9x0?= =?us-ascii?Q?Crbli++Wn49+QN95RRps0F5trCGqi2VNzFCl5dZPvAd6nVxjbzQaMXiLfDku?= =?us-ascii?Q?HeJr1Q8NaWtLAgVp7NFZ+mp89wN3+yvyG0CjBY37CMXRGu53Qpqc8iLhfP+W?= =?us-ascii?Q?naTnhhQY9bn/toRNc9sPi+bg0RUrCK6kDYnDOqCZY+7Ew00J0M8h76WW/6Im?= =?us-ascii?Q?HDeumaGEt28mcWBeiwyc3xEsl/9TC6/Bb5WvQ6LFYuWpDqotxK4TAXvB5+ks?= =?us-ascii?Q?jONluBwG7E/5ckhoELipV8cbT7jRoijxIyFJDIt+BtqX?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 82a8b469-f040-4102-eae7-08dcb8585e43 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:48:06.1604 (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: NgJiNBIo0YO+9BsZqo0itEsnnTNue6RG768X++Zn9i4PvOUZQdjfUn3cAy9ktRBopskI2WfpJQG3A92Uxq5eBw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 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 Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011065.outbound.protection.outlook.com [52.101.70.65]) (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 9B5C419FA90; Fri, 9 Aug 2024 09:48:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196897; cv=fail; b=j4lGunpK7923yg/JC63Wqjmze1nA8L1AY4NwkUiV8Q5QFTMsf/agf8FPuzzEQN87HwfJUSk7xJHFg93kmHb0cnNSfCjW2tKRHV9t37oQNHFdZFbQS0zfApE+wc0NWZACouvejvBJeSGl5jsXaxv4I7kVVMmyWJzAPUdnjd4khPw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196897; c=relaxed/simple; bh=p5QNdxKjCzze8oseGgqjKq6i5bte1ayavw215JXhUlo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=SjinRpd3W+bW/aQWmdWWzjAokau3KQkbh33BPeOPuLseHwFBp36UshVCggaI+P6EPolRKn65Gr3MoQ3J8oWKoHahjFeSt1nPfEVZaOCliw+L3XcSOCKeyYGX69GDzA4xv7Eoau30uKQh9NdWxOPfI5it1K/sNFnir5Nu/pK3sPU= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=db7weDwy; arc=fail smtp.client-ip=52.101.70.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="db7weDwy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=lY6tAVFcBPpw/Wtv81+FN9QtGHY7ptbH2RTt6D+qfjDqxfeRFEUKECtY/heh0rF8yz5lxKFlt/Xp3RHkuwXHnfMMCWWPwOKoF3tXmAPxWNdcO+9yLYRwqgfGRWh2ubZD7Id+9fySSfiIhgtWcZFcZ4BqGanYZKdckPqjfAj/0kLmV4TzT6DF9Hcn8W0JtOo16nW2Zoi03yc9cvnP/w4oACiqg/78vSMvunfb/IIjTYNlGIAnKbFScztBql+O+qYzdUPOwEMy6F7cvF7Q4ov1UFzVppaaYvfrDJclmiDmBVIxedzwhf46SeVh43yrRFv8FuOfhhCJM9byRApqYNl4+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=34canxyc8wauY9Vz4GDFQmmBBJyG2eNXVG74r/71FfU=; b=f7m99EhoWK28S3RydKTbe2fE/sZCbp4XE3Aq4iPcaxeNFfJtgkX7veWjQi9CIwEyO0OePo+JY1tuoT8KDAGQYbGMEpkq6eDx9ViU1wE0wAQFvUyWhPijr3b5JaCAwlwEaIbpyYJeudoAa4ylK9KuzmkIQh8+2enKmqVf08bqeamHMPrRa5lyWpe78j+WF/tvd+/uBMzjEtBVwDLXELNPZRbAhc8nYV+VOq2gLWclIBUg9rXG6JfHCc5rXZ1pfCfCKaCBAULtxCFIvI/Aq9JtSvj1be5xCA1b3J5HZy5wXPF8lp+nhtWVZehkb15R0i+35jB6/NBjKgBcGw+l4fPDXw== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=34canxyc8wauY9Vz4GDFQmmBBJyG2eNXVG74r/71FfU=; b=db7weDwyxP3gljdsy5xflg6fia2to709rGWG9BGV5Rsc8rc2i8RCTCc/yG310Oujn2gedHPCIsj8gBSi69OwFemutanyoXlOeRft2VW225d7K0o6k27RD7ZbRm7RfbaBvN/rVU/SOsxjGJaXuPhRpwVzxq+fEhWYfwBgpxXuX16aWUeSKdEgPxTqEY21p2BIud27vmUErgY9HBv1q58YXXbvjlIEBiXPBojbfCwdJzYZ4SO1uSKbtmVmTIsEKLi87OOetPpI3MD5xT3jPf6wUBlureTS0TqS27+ICVghVjGCiq1DPnslrhOfPtIEjHsvBAnlAsDP+9cFyZ4VpnfsNg== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:48: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:48:09 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 42/43] wifi: nxpwifi: add Makefile and Kconfig files for nxpwifi compilation Date: Fri, 9 Aug 2024 17:45:32 +0800 Message-Id: <20240809094533.1660-43-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: bd5587c8-360e-4751-f469-08dcb8586047 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?VgzfmkZE9nIx/bO19yEzvTbBIu5Z8Y1m/1HdEFnswl3YNvLaOz8vaL9LHFXl?= =?us-ascii?Q?eyyi7fmzaZYp0p0jRmZdDLfRVYQviToXgjQpFcHGdwPq1Xs6F2hL2+ygw7rE?= =?us-ascii?Q?LTu2p135BgmiuoAw3nHfAO1+mVgPUr9cmp+oCcsKpSvpv3Ov4o9U5KA19oZb?= =?us-ascii?Q?EYOCYgN2N9cVQeyhQGEvnqcEUyKEk2+FNclNH1SgaqG8y0e1MqcNyxG8pYPZ?= =?us-ascii?Q?Lo3Ifqn3YzTDKYTXJ9ECvmVDpvbdLbXikX/n5mN3qsb9PtcpwcmOZsBIsxzP?= =?us-ascii?Q?yEUBtNVyK7lwGB9SkU/lsGf5CkXvn/zCziXfu72ocFLtUB2mgTkEXX4kN9ap?= =?us-ascii?Q?xf3d+lxzHSyfHTf3jZEHRQOUpajsm43FqtBPsGnw/pCRz4KEZLLGetk98Tf4?= =?us-ascii?Q?TRsE49FOJL80mXrMFJYJjkOMcDbEdrbWlZeWA5yllUS6stUH9v20baEff7WL?= =?us-ascii?Q?ursAelzsv+j4j3W0V1cNUEbAxLIhPCzQmx2VSKOI9Ca0EzZx63noXFxG+bIZ?= =?us-ascii?Q?E1bp3LCVEwe3I/34gEoAHnNgmA+wkptLyFAaPV09IAZxXVi31hAlebUKKwOp?= =?us-ascii?Q?7IFJH2JFv1S92hPu+oBrYGse7tT5e8yx/r5TjyTlYbr019QvPDOvjx4OJ2qp?= =?us-ascii?Q?DU25x3hhwCIC2v1Dp25kLetZ56CepT5ouvGZKipIYPwqpcYGNe3S4aDtYJ3h?= =?us-ascii?Q?0K6o0xhYFLvXqNmXMdCUF2hr/kyD0vZdc8lO7rUBLHLMdEC1dTq3ue+/ORN+?= =?us-ascii?Q?CNWCCmXThfRg5ZSAO5qnjiFcYFrqeI1zDxDN41LeCV9EOGJa3p9kILZs3SxF?= =?us-ascii?Q?btEBNPabVdN7dLe/P4Y2fnt1tfthB/lQRAt5WnqOq7bFYFomlBtUkqMpgkvm?= =?us-ascii?Q?s1Dy+xVPC+Hngysvq3M3sTsMGe0bUvoN7cnZc9y7lm1XOVZWDRJLGUaYEJzP?= =?us-ascii?Q?YmJYqfdodLGhkn0s6C0zDkKtOJc2olGNEtUlvj/9oWnKRD1UNxOc9whUj0R6?= =?us-ascii?Q?ywLfSPnuIFkZ+5eOWbpEsE4NO6b7Q7p/uMj1qKyKSaTUSjNnx4hvkPd5n13G?= =?us-ascii?Q?4zSPGP+FJ2RFNdCAc9jT2ZDo0JU959ZSJSXipuVVliaTtAp+2AV15qRMv4Ns?= =?us-ascii?Q?pKthLNNT1JhjxLXquVROvfRkTLR86zhTLoWMEp08Cyng5XMkNQV8cV8hNGO2?= =?us-ascii?Q?JMkZFJ3sW9ewZYSt1DLmZC90QikFfX7gxBND4f2Ymy2K7gpS2nnYskCVJ4Fz?= =?us-ascii?Q?VoWk66DYGTlaqTpMzl3xvTj+RLJZ1idhS0N3juSrV8zcpdlhrj93jDUc16sV?= =?us-ascii?Q?n4iwu32UJl7iKQzqpwP95DjShS9fZ27PqWtFqFW5RUEoNA=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?20E4Du2ohOspi8bfeGpp63L2N8TjmIgnhDoVhKZfiSN/f7KyRIgTHZNM2KCI?= =?us-ascii?Q?By/bjtrxIr+LOYej+KXKJWmPxMo4QHk3B/B+wQl2OxZzPEOIMavOxJu7e43b?= =?us-ascii?Q?S1/wtqF/qMh3tCo9/NDE26ocbIbDtjxXAKm4pXmr2aF4S+3ERLxqLbHGfMQA?= =?us-ascii?Q?rm15qe9IzXqxskXiUd4ROSLnFziMB6GnCPPN1VMmAvVdF2hKvQQbhLGio/88?= =?us-ascii?Q?o3ad8NiVPRUj8PDp5h5VKdvQXKFB06ilDm9JHaMmlxbBcArKTgQlBYwwwJ+c?= =?us-ascii?Q?BP7SEgJxqj1OBcNhT3Nb5opa6+HdGfDc1LtARyfuDrbjnP4PrmrIyfa6Qw4E?= =?us-ascii?Q?QcQ8uhw51Xbb5+h4PgXPz0jTs/KQNP1U2Yg1/SuxeFZ53JtJ39hm/5SgQ5lB?= =?us-ascii?Q?1zGuQAUrq2gSG0ouKkp7ZvcH97FOIfx5mFhDF+nc4KSixF8Mzj+ZQCBHrOBg?= =?us-ascii?Q?txiFNbF6w47q7leCsOEw1HG6pvLH4int4W3yvsEMoBh0alvrxemi4FkqM48O?= =?us-ascii?Q?cmYgFQ9mOSppzx8kNXCiUlBQoJcvywWeug4St7h+0DQJoQrVVQcb3R/Lv5ls?= =?us-ascii?Q?lq6SMdJEyzCpFN1O+V1TKacZQYnCR+yMgonMeMgnpPxXXZIfSXIYWzmFKqBD?= =?us-ascii?Q?hRJZg/RZ8mUQgw2fxM8wHPyNshIhp2NDqN6S8SiieQz9FnSAneEMWlou4hE4?= =?us-ascii?Q?bUR4JUfLwtmR1gSRrurIxVfju2BXiXyzPSio7xuyFYSJsXdKzMxYhagIIqGj?= =?us-ascii?Q?T8XhC8S9fB/6glQFZotDrGoWJMNM8VQKvUZ5E1bqFg6zenfYQ1MUXZroQEM2?= =?us-ascii?Q?jQiBFQKv6sN+HJDdGM1EILMTpChOMTS4VMCTGxFIh3SRb7st5cy6gUPjvYN3?= =?us-ascii?Q?gwK7obgWDSxla+3D/DR51/+ROI616sde5g95zrp2jzUdaXNYsjEOGGVy+wu8?= =?us-ascii?Q?9yZtetAnlWxj87L+hxIf3qWEJePCjtacwegcJKYglnGxsVLWLohn61o1+9T6?= =?us-ascii?Q?eWIwxd4vfrx3A9x3LzBwWnaIk1U7lA5hudhsFBK4eS+OqNgNFX5RzDlf6Uh7?= =?us-ascii?Q?0BSBh5Z9Okmf/1tOnW/bYO0fF4UcwEU0XVHLslIK7ZaeGcXzp8zw9qGXLCc3?= =?us-ascii?Q?9Hdwt7GhsT60rOOayfwRkZ+C7ZbAL+vOKcTlMb/z8/q0G7B9QqizeWTbL5+R?= =?us-ascii?Q?uUOtiSmd+1l3KAtbCJdIkaSAl5rG8GfuM1MFLj3ZhfOx86j8rkTb/A1EBEH3?= =?us-ascii?Q?xZmQ1Pj0Eu267/WQz8tjg4nugH3oXrJWcQZo7pbBCeQwA/SuHRkJl1pgOsXt?= =?us-ascii?Q?h17RwAm11UolsrXXoEveaCHnFjgVGQ3XrbbvGEBpETvV+viv427q9VEn/D4U?= =?us-ascii?Q?R690zmR6K26GEJsXrKpxSErLVncraW0eX5RknDlXwfGJWf5oT0Q3LhUyIrDl?= =?us-ascii?Q?Xzpi4EPk5oNmSHqqqcrP+xMrgWXtmyA8MSwtWm9MaHQxiHUUQKhmz6H3pQqy?= =?us-ascii?Q?oKkfg36fpxbONU4XEwojtjcIbApJ97lQKN7puEA2Xn4bsl6Qig0dj4BEvKRC?= =?us-ascii?Q?x5vgi7XefckgOM0So60//E9Xg659OvX8b+4zp4mzJjWKvAgtkTkDo8r+mD2A?= =?us-ascii?Q?DYrPXwKXaddGBkSCMFm/35o2jCXaLLitLK4juyHlERZ1?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: bd5587c8-360e-4751-f469-08dcb8586047 X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:48:09.2919 (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: vDClxZqxq5zyCs0XjwhpfX8q1DtDbYaf4bc8ON4dIe0aev8q6REXXcNBAlQziX9g6hRXAp0jp8wQ7Qbbjjwehw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 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..6456d11a5ca2 --- /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_cfg.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 Sat Feb 7 11:38:14 2026 Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazon11011065.outbound.protection.outlook.com [52.101.70.65]) (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 3C47D1A072D; Fri, 9 Aug 2024 09:48:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.70.65 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196900; cv=fail; b=l4Ws47e7SrutfcjBHgqF6ybbORUi6BVUEXFzgdy7YN04OrBHVVZwd5Qjlc9zwti4nSrnFedyA4IWctkKwXqB0XYx/zuCzLOG4zV/JkmI2atEyeygKQQQDwYugZPIwN/zIIBpydgFTU6cVcn1e8PmNHfAg/6O707ufEoTjH8seDE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723196900; c=relaxed/simple; bh=98Pyhc1vmdONEtH69+rLK+sjsXdvJntJ4nMJov5RyGM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=j8uRmUg9Lv2fHopozkPPdBCebXq9MM50Bzuuk3e9JChu+67AANLtCyG0+Q1FtYtf8h0574RIhqg8kZsxr/638tGoV+B3kBqXUWG95vnOzpgeBOFiGlc/rDd//e+1jvDHEPq2pOeioYZvcgn31nxzRvPgpnr0gCppZZLCQ2GlzFk= 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b=muoDIXXJ; arc=fail smtp.client-ip=52.101.70.65 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 (2048-bit key) header.d=nxp.com header.i=@nxp.com header.b="muoDIXXJ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=SjfVufCiX16q1Fbw4X43bpw/D1Xv3iFxu9l8baGAxguyo+UORos5fzZoxiexyQAO3stjme799/QhbbNdYjgwU/33QhZnKP8016f+pS87v6nMAkt9KVi8ZmUXBrBEldZoCanLgsAN5dxHy4vwU4iWt0be2fqcRllAfLlvWxcwjj+oFBJoTUkItlZ9r+GvY5G+wt42xJAMfe7M3FaBI26tRM435d+LsmucuJGTNBy8odmxg2AUaykrVoETBHHMZV2SqsNDvgvCK3zNK1qZRuVZ8CCMW/kiM6hdOD0TL1zYoYt0OZy2XRFVSVfl3VKVOOFZE03ImNOHydLXDX2B3yj4mA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=cqAjyqQDEwzBFE1vd1n7Finm5tDGokZZiNeKEDgM5hU=; b=LHnEruwdEKm4g9yPbqQIHlUipIJ3/ZbGrHch8HCCbHDGEwkwq4x9540O+lfzCBxsm90YrovAt82+T0fbhcfuq+LhBrM4gE/T4GbrXdYAN6gQQW+L07rdGv8iAczBpQCZdizxfUKtv3D3tsHyNUpFtZ9kCMrRGe+HnHtkn+wMfm5W0P4FW48o28CXFA9vMrFAK5jFiuvi6wS4ffK45K0ZTF8IMIhmbdPpRaCNSWEwxz9GZOco94FfESi38Pqm8KtztUL+9UZrcTtAeyRQ+hhxnciwU3n3k4Kcv5uM7/8NP92C5BYxwaqs4ysHtSghCM2pPZU0OyprfB8O+bKvOOzhkg== 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=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=cqAjyqQDEwzBFE1vd1n7Finm5tDGokZZiNeKEDgM5hU=; b=muoDIXXJgV5RyBzB+d5MgkvxSMwnrbez5oUFKe15XLbLujgGp5pHO6bNgm1pzrMPMuGrs6B85MVW0LUkQW3fEVi8mxLB6LjArZzWv7BMh01AJTN8woINoJ99kA3lJmC8eNNI4KGYwvpEJOIP8x/8uwXqNIkr6/4w9jBg9ExF1ugHibV11hoJe9r8Ku3HDGCxiLa5Zd8RNdb9Cs/kpC9UlZei4IW3/8bx4yXMQMWQ/VFe/0nwOvrQC8URqneE+C1Yyi9kc3SU3K/7bnrIC9ZKhgBTRTvpPe7djyyoiG2Rv0rz1odeV4UQsisrm1rJ/++qv1QDPZjJRWk+u5dNfxTXhA== 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 GV1PR04MB9120.eurprd04.prod.outlook.com (2603:10a6:150:27::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7849.13; Fri, 9 Aug 2024 09:48: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%5]) with mapi id 15.20.7828.023; Fri, 9 Aug 2024 09:48:12 +0000 From: David Lin To: linux-wireless@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org, johannes@sipsolutions.net, briannorris@chromium.org, francesco@dolcini.it, tsung-hsien.hsieh@nxp.com, David Lin Subject: [PATCH v2 43/43] wifi: nxpwifi: add nxpwifi related information to MAINTAINERS Date: Fri, 9 Aug 2024 17:45:33 +0800 Message-Id: <20240809094533.1660-44-yu-hao.lin@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com> References: <20240809094533.1660-1-yu-hao.lin@nxp.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0178.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c6::9) 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_|GV1PR04MB9120:EE_ X-MS-Office365-Filtering-Correlation-Id: 4c477a5e-b5bf-4e90-2d4e-08dcb858622c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|52116014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?STaYYNr/cMfBvEHbd44bwKxfJrKvuXN+5TC9f8ulO9yAycZrWqDc31QzUzbF?= =?us-ascii?Q?0671gAZ6BxS0csdFvjsd8THrK5TuNcTqWJW+11V/OjvkXxq7TUtgo2t6xYak?= =?us-ascii?Q?Q0thRQlBRJEXH3kKDa3CXrHytkRuNUO1rXMLpVQ7BahcgiutqXHWhv2krIsF?= =?us-ascii?Q?x52mfTK6WB6/rGEsMjR3UxNxfM02xsTqPGru84g1aHACYXwIgPr8vQ2+Bujb?= =?us-ascii?Q?p7fe++1Xr6l+kCIyNCG5z02L4kwO9NKmF3SGZChi5uTnoTx0AM2Ed34rBInz?= =?us-ascii?Q?IJe7veXwPX2/5ouCBDhPlWjYWkhqc9GUxBRSoLIxCZq7DWb+BbeuS6LuoOy+?= =?us-ascii?Q?OPmuMIz8+7mEAqKFNFVI4zSKKtkeu57kab337P7DBSJpKjTizX3BQboMJ6Pg?= =?us-ascii?Q?03bZkJdR/HhJv/khGXe82EAvVCZMq5yWOk5qfCFwzKm1Na8vS3/VJasxiJyB?= =?us-ascii?Q?qUipjYnXRamHWIyXNgsgNrpM9b27Y7qlLf/Va0qwYouZ+9w49Gh4MIDO09zO?= =?us-ascii?Q?PRQWxd6gz644CVIXM/IDDE5g9opUPyRuIcTAwXPAYjIxeJw0hCsYURaYFW/O?= =?us-ascii?Q?Mj0oJs1cFZ+1Zk/0VhTMpWMZuO0CUR0JQB5uEXBB9R0PDh+vgcX6OthM5M9b?= =?us-ascii?Q?bUtey0sB/ZYXkS7Azz9XECq6Uy8fQViS55QaadjLJhmkz82dbB0BiK/2Uwas?= =?us-ascii?Q?oX0ItZaP1u+GVQydmS3hm/KNeiNroiuUF9W2sww7gbpuSLw+InpsAIqu0Vfd?= =?us-ascii?Q?bX9mLOBnR0yR+pE3g7DfgVhjMbsvCO1pZ/f3aj+esMxKDF7DtIaN2xXTWY/N?= =?us-ascii?Q?pX1XBehao/oRkRyPjRJLONOWSWuRN1wB5DljH9FjZWiR+Ojv5Fsh7gKvH+qh?= =?us-ascii?Q?yo05mOproiz7jI9157G1h4il3Oci1/IvtyMi76Xps8wyR/QIl2/WNHsko351?= =?us-ascii?Q?uFPSZlqoQOoXKOgZJYPQTkleZxaV6dECK1QKr6/rXMk2QAj87ph3mTY14IYg?= =?us-ascii?Q?+hsKTYFzQqEgo8P6DzSB243/INKf3LxnNQu/AsaHYHGAeOr6ppTwHRo33MsP?= =?us-ascii?Q?k23PJaRJwJ1F/3VRpxb0XIIYKTrVdnqCGsyPfICdWjkzj1jdgSg9ciplH9lm?= =?us-ascii?Q?Z8+nLppioVpQIHis3+KRGvBBVGPhC2ReWckhfbPxb5LEsCB//p5SAmEYf9+Z?= =?us-ascii?Q?0r850GckIsEGBI4DibHGNCOpJKXbj8aiYqHfSlz7Md/4tl08eXDu8yIZJR+z?= =?us-ascii?Q?mnPbSvNlt0HXs3zqwqweOkSdxuFSl8Hv8blSUVNjcYm2wwE/AQm0gOC7eHef?= =?us-ascii?Q?e/w/zKn3sES/n4bE/ngjg5O8E8YJe0UoPD4uzXrguquYTQ=3D=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:(13230040)(366016)(376014)(52116014)(1800799024);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?wsJir3a8yo0s8NvH0gbm5iFxX1XaooBL3VlB4/S2km9MZj4lg0lTlWqjBcfc?= =?us-ascii?Q?yh8zDmc9Jkf1fr9UDmL+7WULCxvXP1b/6aaHuxSeWiQaBUuRYlPSjybyr1p8?= =?us-ascii?Q?zDDOu3HkpRZJQLTLeXZS6j1PRXiAzHeHx3VzgVXSGQdw3K84C592RP2+EyMW?= =?us-ascii?Q?cCxHf1U/EMlZc5NjQGo1Lee8HSIpPeMgRat7Pb/pnnsJajktpTQkmwjd5Wv3?= =?us-ascii?Q?i08tRNA1feop5ChpRPR/FhC3CfhDgGP6GHZgc3oBlSMOI+GsNIb4LvKxg96N?= =?us-ascii?Q?TGVNjJMu38nu6m6rPECgx9ZC6m+RR7H/ZpiFGbtXDUvFRKdBGod74j7oM35B?= =?us-ascii?Q?ST9HVOXpQcZmeUIarS9g1yFUUt7I7uhKWIR2ElAuBy7BHuwyEf0LvpzIvcC0?= =?us-ascii?Q?+Tat+41UX9+ncV0GN37MFfJ0bgniqFjQnqogUh2xfS6cTzSaKD41dpXi7Nba?= =?us-ascii?Q?0No2gE+KDaHvuUEJ1SJ4u02UZQDh6cMr3METDt8mmlWsHobx/x7Za6xsZHrE?= =?us-ascii?Q?lXAfpFuIy90h1rDcPdMAOM0ItSoceJ8KOV5DMunyOpeJLSBeh+7R4cvyI+cE?= =?us-ascii?Q?mef16BWV6bwxIBkUOygwLrqo3sAZe/MZCXQI73jXcM3U3fTbea6+Eu2KTk4B?= =?us-ascii?Q?CG/vw+8basaATX1RBRzRbP1CA5mJIejvHKCXzc0vCsUEkKo/6Z1SW5PX+MFU?= =?us-ascii?Q?3m6XoX5tFViqU/6KFds/626uoUh9lah/+2zhzETvPmq6fiQAKnpxuyT8/W18?= =?us-ascii?Q?jYK3b4xRuKxgbIwi0HxfwfgYtBXFb2En54QzTNzBNjvJD4pwGDXpbxHsciub?= =?us-ascii?Q?sEO3j7gAoZW3zJ0zTUt6dQQcSDR12gwNz7wZq+UdvrgnDpy4XKSBQpCBDj1C?= =?us-ascii?Q?6X/p292cFUbVqAdoPTJPn3aRnmCpGNN2exKbqknJTE/bM0D4f/uK/cQTURg1?= =?us-ascii?Q?YYwrXrWL6zslT+61vLaFRq0JE1yCMPGpLNpDGfrMgCpoAKXlB6UEnHzMPdLZ?= =?us-ascii?Q?FmP1ar7a/F2EUvmAhoYQrST5OFi57NSl5BF/oEqe4O2sFPVwwvoAdoGw+Ufw?= =?us-ascii?Q?U3OKDF+DkjG++SMcbQtRT8NrdmXsoKb1ERLVYyEc31W/a82pPQKmzLSz704n?= =?us-ascii?Q?G26FVFBkXjvt/I02n4bM7VAC1NFn7RUW0SumfruiWRqVQ06aGV4LDoaFvioo?= =?us-ascii?Q?C3qD9PiSusU73ouAXyR8O8wC8aHEAuwGS7MiQsgh2SLpDDy1oVq76mzOlxv0?= =?us-ascii?Q?/ncET0x0CzVij3cmzF9O90qHJZtiyf7lkw2gDeuttWgVcJHkSQNkkrpttZW8?= =?us-ascii?Q?Q2ScK+OIpWwhM/a2MWTHL5H7FRxi6YMzIulhaO+fv2oRvBkiu2cStpOibhFE?= =?us-ascii?Q?f+DDZqJBpXqPP0bABiqz1txMyJx/+q1cT3AA7AL3DDWZjd+Lr6G2Ox94fshx?= =?us-ascii?Q?yNVEa0+KeVOo3oj7nhxvi1ecxMDv1kKl8v8LBMXmobk2Mp3FUkEPcsqMuSP3?= =?us-ascii?Q?bnqEFS9YMY0VIP8ujVDuX8ciDWQUuJWSSsKZFCLdMRTYnfye70DoYO4CGJa3?= =?us-ascii?Q?tZZ1PrQZ0H6pkERPeQ773J6xc4K0ho31w5OBVNzToVRfuFXdh8+/yPnbF3gS?= =?us-ascii?Q?ZfKPML01lc2AvoguBYpbqYvc7ZhyNg9NCVsHlBVHrW2s?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4c477a5e-b5bf-4e90-2d4e-08dcb858622c X-MS-Exchange-CrossTenant-AuthSource: PA4PR04MB9638.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2024 09:48:12.7046 (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: rs4W1iqNkhI5XjaBOZNRKs75/Yuz6UjW50gl/tymK+ZDVlltehT/2sWiL5kuhh2fI11lkeoopho5m8zW7Zj93g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR04MB9120 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 42decde38320..a7f8d53615a6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16461,6 +16461,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