From patchwork Tue Dec 19 11:28:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Matyukevich X-Patchwork-Id: 10123095 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5C7F86019C for ; Tue, 19 Dec 2017 11:29:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5A229292A1 for ; Tue, 19 Dec 2017 11:29:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4ED8C292A3; Tue, 19 Dec 2017 11:29:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 08110292A1 for ; Tue, 19 Dec 2017 11:29:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967046AbdLSL3o (ORCPT ); Tue, 19 Dec 2017 06:29:44 -0500 Received: from mail-by2nam03on0052.outbound.protection.outlook.com ([104.47.42.52]:40224 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S965745AbdLSL3e (ORCPT ); Tue, 19 Dec 2017 06:29:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantenna.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=M4F9lv4EXGu+BSgfQvqQXL1xUixgEpzYuEyGWe1KZFg=; b=X2NDPBiV5v/axG34adZW8weYFK2xtRpeLkRKqrkryyJWEGBL87rLAMTOBh2PtiRWlKj3GYHjEpARpYoN/zequLqGjHh8BixX5xYlgm3v6KZoqW+upzL8ccfuJBVRatk3Grpq+glari4dCaVn+BCE/hxArtqvEu00gv9VnouMuns= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=sergey.matyukevich.os@quantenna.com; Received: from bars.quantenna.com (195.182.157.78) by BLUPR05MB1923.namprd05.prod.outlook.com (10.162.224.13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.345.10; Tue, 19 Dec 2017 11:29:26 +0000 From: Sergey Matyukevich To: linux-wireless@vger.kernel.org Cc: Igor Mitsyanko , Avinash Patil Subject: [PATCH v2 08/10] qtnfmac: modify GET_STA_STATS cmd format for back/forward compatibility Date: Tue, 19 Dec 2017 14:28:54 +0300 Message-Id: <20171219112856.22463-9-sergey.matyukevich.os@quantenna.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171219112856.22463-1-sergey.matyukevich.os@quantenna.com> References: <20171219112856.22463-1-sergey.matyukevich.os@quantenna.com> MIME-Version: 1.0 X-Originating-IP: [195.182.157.78] X-ClientProxiedBy: AM6PR0502CA0022.eurprd05.prod.outlook.com (52.133.16.163) To BLUPR05MB1923.namprd05.prod.outlook.com (10.162.224.13) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: b125d0dc-3f40-482d-253e-08d546d3c35f X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603307); SRVR:BLUPR05MB1923; X-Microsoft-Exchange-Diagnostics: 1; BLUPR05MB1923; 3:AullLm1j4wMHnzydraQp+9gXCz54SZqVisntnYBp42wTvfCYnuUwgyxk4j1MiUdEuXhpUhmbMQkNWgHbBYSDuBP7UBXTACFoDEyROSCa7hmV1LHU+asbt4jY6IjbQAg8mPsPYuJ9ZcJ++/r+/LJJmB4V4fkanBwdaKJxkpM6Egk91KP69+TA5xZ3jEl6M8cpyJxsjNfgsp7z8bHAKN7NuQsz9jpVQ3u+zNKIr3LobMHiPdRTSs/NRCf8fcy92y2k; 25:/TI32WpF44nHRfIqdtG/5GFCiEpjgs6GZt0FgqNgxv2oNNBaeRrUqmmyONX28KUxU2AwSLMQnlQPf8YbKm9fHxrxkM+Rg/0LvbIo8EE/7nN4DYZDh85DF/Y76N5dwaKxB1ArUjM/IEkL69WYXREUW2WiRY1Pqbdh7cxIgJ4l0FWXZZ8E3JCfZqNRWorlkR4taEs5Mo1efea8CRwEGh832s0BChOufwYwjXxnqlMrNIHr6w6oWReIFs3muoF3aBwK0jCrPSQe2Hfu1Lz0HIHnkfG8hQFmq/8WqBzAMcoxtNwPrCKOLXLuVr6JRolJgy6b3v5UEEPXLvP+zu6EAVOHtv3bA/+V5V4B1yoxO8cv0Rk=; 31:cm6Q1kUwVzWLgvGygJWK8AB5+5t28U8XxPKdtA+k3EBbM0NTtvC9BokKFq9asg+Q6rj5L2uoWifJ8W4ENnn/MygNvsi6nGPK8e887D9iJ/2Etcy7KZI3ayfEQsxNnCA99b2bhJcodj6SwHNxLTJ/umtdfrstKkD2Dvfmsfu3gipP/gyLxkGh1IQ3t55CdRXMMIA142dAG/+m+Hca2iWd1ANsgRz3nSJE/4M6dt0sgyg= X-MS-TrafficTypeDiagnostic: BLUPR05MB1923: X-Microsoft-Exchange-Diagnostics: 1; BLUPR05MB1923; 20:IoCC77Zg5iAyBzEwR1jsZcEIcRXA0/E1y1GW79PSG6pXTWbFmtvRmuYy1GsupEu2FEr5PhIQOV23waNbny+qzzsIvTAKWkKEL8yfy9y+YeqpMXsymQak+RcDwuXXHLHZj+Npm777oqLY0PopdWqWhbd466DDJ0blyloAlNT0zV6ws0Hh9iR2TEZGYHG7ljHVrN11APsr5gOy8bh7QCWccj6LgMwkcLF1grBnV6QJSn3p5eL0jNt9Jw4q4ckHhWeVvb6bqGnwuek4/+St/XnWmD+wOiN2zl2v8U5+fWwELQyMrvgzUukKtuqHit4ehdtxJQE7liXuNEnOfzftlqbfYDAqTcbVQk8Tn7kMrDbxle+DLSL4sz1oI92eiQIP9QtDJK/Ms5bePKFWDxu3IWeuB5SqxJY3ZAtr2Kf8lXuxn+OhInGbCSutWwPdXlkUkiT6AksJ9SU1uYuynzlNnBBx2IR2W3QIKMHX448GReYIJmFwFfUcYSpM9upvWko4+vSn; 4:WBMPq1hhMPtJREoKIfdI59NqzixWTXpQGG2u+mVYv4AGxtV55YOMUkb2tEcx6AG+mi9N3jiO/QULLKhY3Rpfl/iVqlfdr2uCxC125NkxKu3KCr2zQSpKXfSYYlGioMMj0aNWsCE3rOGLkfziAOmt9QQ4W0HkdZY7KMk4FrVy6wyVcic3d6CYd64huaWfx6QnK8Vr6olGfwXkHsV2VBLCb2Gi69V5ZK/8MRnzgzJuEIC2qEqLz4Oh4qxzFsjkXgXUSlY8/URE31Nf25d82VwRdA== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040450)(2401047)(5005006)(8121501046)(3002001)(3231023)(10201501046)(93006095)(93001095)(6041248)(20161123560025)(20161123564025)(20161123558100)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(6072148)(201708071742011); SRVR:BLUPR05MB1923; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:BLUPR05MB1923; X-Forefront-PRVS: 052670E5A4 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(366004)(376002)(39840400004)(346002)(396003)(189003)(199004)(48376002)(68736007)(50466002)(59450400001)(5660300001)(2950100002)(6666003)(6916009)(316002)(52116002)(76176011)(386003)(7696005)(97736004)(51416003)(16526018)(16586007)(107886003)(25786009)(575784001)(54906003)(4326008)(69596002)(86362001)(53936002)(2906002)(81156014)(103116003)(6486002)(2361001)(2351001)(478600001)(8676002)(50226002)(1076002)(8936002)(7736002)(81166006)(66066001)(47776003)(106356001)(105586002)(3846002)(36756003)(6116002)(305945005)(53416004); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR05MB1923; H:bars.quantenna.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: quantenna.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR05MB1923; 23:E4QL70Cj5NzpQfWLD9Z2pNjMd72LRE0IRFK9I1DN/?= =?us-ascii?Q?yNp4cBiVcYPiq0/8dAPJ3SYTKXhyR/swTNt78TZic3g/aZRjNTyKa5j6Q8Sc?= =?us-ascii?Q?q4S79CTFY7ttXwZkYzrMvYOOkXenXCo1LORmjmXIhdoVq24PjmYE0fqf215C?= =?us-ascii?Q?pNJKb2rgyfE7/UYvVNpaKLF44kCIpbAbMQrHXA2tiP25X3NujzNwo/u4UFmp?= =?us-ascii?Q?xaCF77nC5gzhvD4uO5ulSAuJ1BPhddS33UL56Fc+A18hduea/BhXNU+qkSHi?= =?us-ascii?Q?FUxsoalAK0WAhK2dW2PcndYdcIZjRrmSicm0X3x7kGJ0xol6PbiDDywe2ZVO?= =?us-ascii?Q?D7+neCtuBw+gj5YjnA1S+EkDMutTevkK1jO8uTQKfa8ao14BVhAkGb6d/78l?= =?us-ascii?Q?mIreAX+MvYgmtRkbCEhO8IotOrah/mJFxnYnqz5Rv0fcxsUv8DiUQKF+Ib/I?= =?us-ascii?Q?usji9qtm0OR1eWMpPHBywjQPrnTAVIO/0shXgD+NaA8w2depfK+vjKJThVWT?= =?us-ascii?Q?VGc61Iy+hFxvm8mGyq92HOzR+ajSRwMKyG6BKVC5UxeAXPS6vEn2Fxua8UQc?= =?us-ascii?Q?y7B+il27LxIaXkz/Iu5dOdGuItADDlSWEHgLn2pS5FD7CsooHS7nkLBrzeQ6?= =?us-ascii?Q?oMLf8UmweAwwJKJg1fsdA9J/mSVC7wcgk6RI945LpPjvGpY9CDy9TPDd6Z2t?= =?us-ascii?Q?ksn7FxYG3R7wV0g7p1+FJW3f7X1r1TPyIU0HBfTyg2/lhKLuo/hkR+IPwxMN?= =?us-ascii?Q?CqvH3hDCDwCgC12dcrHlBFx38YqGUKg0ZYV4ip27m/RjZ8vmrF67HhsvKTDd?= =?us-ascii?Q?+h2yn+Lev8MyPtI5bH7Z3WH8zUoTF5G4BJvzYGowvL0dtmDPLM/JX0lF6fCR?= =?us-ascii?Q?hSz5lMrN5u8LRPxRxi4i1nW9B+EEPS4oKauC5sKfjp2XPh9Dh81DY5ByCkXa?= =?us-ascii?Q?fRBDOdfCRqzyUVXixarbD1jWlzZgd0xYEjuJB01p8Ct73va8mzq5Tgq/wF5+?= =?us-ascii?Q?k78/XBbu8s4MzrRKxhcavEAZu9mE7dyIFBSltu4pTUbLGg7unZfb4IKsKCyJ?= =?us-ascii?Q?AFvg5nW2gstwb+GpwsWSnh2D/UiZ1UDe3uqw2kfO9BvRu9dpnG1MYu/D2Bzy?= =?us-ascii?Q?9eK8wO2tIb4VKCuN3DF2Z6gM88/76qQ9uTvmPyKCU19QfrbNVOJbg/U6zqur?= =?us-ascii?Q?UKGdczyq2jCLQ6jy/nKr8dpC4n2+KX6kxA+1RlVKtce04t2jMtG8f32Mcg2U?= =?us-ascii?Q?FCjCjSqGf/aTUUrRao=3D?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR05MB1923; 6:2jD2T1DOBpUuNeJYP5hKv7l03saCXtYQgNCdY8Ne9qrVgK4f87QX1djfZglHRRUn46+jpqi/rjS6fA6TTBBjplsGdlaxAnMmROZJk6H81enez2yWLliGy6gd92e8/f5VYZJdCFWAdnbE8qEB0XYzXr3Yxoyg7/KxKM+H3UNLugtHe93Ht7+0epR6V2KxLWBLa8Oq51rXV0UaHaWWglbhv1eogwPrC6iBURI6pAr3W+BmeDeMbJyM/fpBg9XVWqdp2z/dOPZKtiTF9SOJGXtZmzNq1N6T4fXQKqVDzrRJEz92eNPUDO5b0XTm3DSKzK9FirqPGRfk8SA6K6BTBvsp6maIaoTdFWRsv1Pbr0ov/7s=; 5:2b6DYSLnU+e8/RrI2NsrRmZbCQ31SQBRlDXZWrgICjOIQ0zhYoEna/nOFeKRCBUEEo5jkyWYjqvhtibhnk43n4x9rsOivr3PPsAXGkLYrmBw8pQLSOVt1g4mvp605VsCv+rc5H9JZ+IkbKSM3IA/Jm0Y5r0kHsJo7nsiKYJEDNo=; 24:mH3v0xlNBa6+R3BaI7PnuvRhQPyqxo4vPZKoHvKTdUZDUFONwgAOdPzwi0Nrf37MLoms6akBOlFAQpYLasbrNQ81RBn1tZIu7Lw6vCAzxvM=; 7:gOn3YjlAMQv21qvmzhxQh5Cp9mZL7sVyHdoh8086A6CZQ0mg58clctYf5CmODM+wUPxBmMpV0RPTXJG2dpWr17Yr8QMoR4fEnWbaUs7POXL4FPU/bZJkx4QmyNXQHZbMFdPrWjBmGJnFVa1sqrBR1WQ9obRVF+fBgSVrldyq5foEaA8UfBDnp/F0fUHK6C5GV68SA2Cyyh/GKBXyW/4GmK2aHFUXscr9mDt/m2+KmTlZrur83hv92e8/M+FuSCf2 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: quantenna.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Dec 2017 11:29:26.4973 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b125d0dc-3f40-482d-253e-08d546d3c35f X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a355dbce-62b4-4789-9446-c1d5582180ff X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR05MB1923 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Igor Mitsyanko A set of per-STA statistics can potentially change quite often. To ensure backwards and forward compatibility, modify GET_STA_STATS command format: - introduce two TLV types - first TLV is a variable-sized bitmap of statistics values that are filled by firmware - second TLV is a structure with statistics itself Only values specified in first TLV are valid. Signed-off-by: Igor Mitsyanko --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 217 +++++++++++---------- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 204 ++++++++++++------- .../net/wireless/quantenna/qtnfmac/qlink_util.c | 12 ++ .../net/wireless/quantenna/qtnfmac/qlink_util.h | 2 + 4 files changed, 267 insertions(+), 168 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 839e86b99837..38b9c1078058 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -461,30 +461,8 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, } static void -qtnf_sta_info_parse_basic_counters(struct station_info *sinfo, - const struct qlink_sta_stat_basic_counters *counters) -{ - sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES) | - BIT(NL80211_STA_INFO_TX_BYTES); - sinfo->rx_bytes = get_unaligned_le64(&counters->rx_bytes); - sinfo->tx_bytes = get_unaligned_le64(&counters->tx_bytes); - - sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS) | - BIT(NL80211_STA_INFO_TX_PACKETS) | - BIT(NL80211_STA_INFO_BEACON_RX); - sinfo->rx_packets = get_unaligned_le32(&counters->rx_packets); - sinfo->tx_packets = get_unaligned_le32(&counters->tx_packets); - sinfo->rx_beacon = get_unaligned_le64(&counters->rx_beacons); - - sinfo->filled |= BIT(NL80211_STA_INFO_RX_DROP_MISC) | - BIT(NL80211_STA_INFO_TX_FAILED); - sinfo->rx_dropped_misc = get_unaligned_le32(&counters->rx_dropped); - sinfo->tx_failed = get_unaligned_le32(&counters->tx_failed); -} - -static void qtnf_sta_info_parse_rate(struct rate_info *rate_dst, - const struct qlink_sta_info_rate *rate_src) + const struct qlink_sta_info_rate *rate_src) { rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10; @@ -493,22 +471,23 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst, rate_dst->flags = 0; switch (rate_src->bw) { - case QLINK_STA_INFO_RATE_BW_5: + case QLINK_CHAN_WIDTH_5: rate_dst->bw = RATE_INFO_BW_5; break; - case QLINK_STA_INFO_RATE_BW_10: + case QLINK_CHAN_WIDTH_10: rate_dst->bw = RATE_INFO_BW_10; break; - case QLINK_STA_INFO_RATE_BW_20: + case QLINK_CHAN_WIDTH_20: + case QLINK_CHAN_WIDTH_20_NOHT: rate_dst->bw = RATE_INFO_BW_20; break; - case QLINK_STA_INFO_RATE_BW_40: + case QLINK_CHAN_WIDTH_40: rate_dst->bw = RATE_INFO_BW_40; break; - case QLINK_STA_INFO_RATE_BW_80: + case QLINK_CHAN_WIDTH_80: rate_dst->bw = RATE_INFO_BW_80; break; - case QLINK_STA_INFO_RATE_BW_160: + case QLINK_CHAN_WIDTH_160: rate_dst->bw = RATE_INFO_BW_160; break; default: @@ -578,87 +557,125 @@ qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst, } static void -qtnf_sta_info_parse_generic_info(struct station_info *sinfo, - const struct qlink_sta_info_generic *info) +qtnf_cmd_sta_info_parse(struct station_info *sinfo, + const struct qlink_tlv_hdr *tlv, + size_t resp_size) { - sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME) | - BIT(NL80211_STA_INFO_INACTIVE_TIME); - sinfo->connected_time = get_unaligned_le32(&info->connected_time); - sinfo->inactive_time = get_unaligned_le32(&info->inactive_time); + const struct qlink_sta_stats *stats = NULL; + const u8 *map = NULL; + unsigned int map_len = 0; + unsigned int stats_len = 0; + u16 tlv_len; + +#define qtnf_sta_stat_avail(stat_name, bitn) \ + (qtnf_utils_is_bit_set(map, bitn, map_len) && \ + (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len)) + + while (resp_size >= sizeof(*tlv)) { + tlv_len = le16_to_cpu(tlv->len); + + switch (le16_to_cpu(tlv->type)) { + case QTN_TLV_ID_STA_STATS_MAP: + map_len = tlv_len; + map = tlv->val; + break; + case QTN_TLV_ID_STA_STATS: + stats_len = tlv_len; + stats = (const struct qlink_sta_stats *)tlv->val; + break; + default: + break; + } + + resp_size -= tlv_len + sizeof(*tlv); + tlv = (const struct qlink_tlv_hdr *)(tlv->val + tlv_len); + } - sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) | - BIT(NL80211_STA_INFO_SIGNAL_AVG); - sinfo->signal = info->rssi - 120; - sinfo->signal_avg = info->rssi_avg - QLINK_RSSI_OFFSET; + if (!map || !stats) + return; + + if (qtnf_sta_stat_avail(inactive_time, QLINK_STA_INFO_INACTIVE_TIME)) { + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); + sinfo->inactive_time = le32_to_cpu(stats->inactive_time); + } - if (info->rx_rate.rate) { + if (qtnf_sta_stat_avail(connected_time, + QLINK_STA_INFO_CONNECTED_TIME)) { + sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); + sinfo->connected_time = le32_to_cpu(stats->connected_time); + } + + if (qtnf_sta_stat_avail(signal, QLINK_STA_INFO_SIGNAL)) { + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); + sinfo->signal = stats->signal - QLINK_RSSI_OFFSET; + } + + if (qtnf_sta_stat_avail(signal_avg, QLINK_STA_INFO_SIGNAL_AVG)) { + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); + sinfo->signal_avg = stats->signal_avg - QLINK_RSSI_OFFSET; + } + + if (qtnf_sta_stat_avail(rxrate, QLINK_STA_INFO_RX_BITRATE)) { sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); - qtnf_sta_info_parse_rate(&sinfo->rxrate, &info->rx_rate); + qtnf_sta_info_parse_rate(&sinfo->rxrate, &stats->rxrate); } - if (info->tx_rate.rate) { + if (qtnf_sta_stat_avail(txrate, QLINK_STA_INFO_TX_BITRATE)) { sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); - qtnf_sta_info_parse_rate(&sinfo->txrate, &info->tx_rate); + qtnf_sta_info_parse_rate(&sinfo->txrate, &stats->txrate); } - sinfo->filled |= BIT(NL80211_STA_INFO_STA_FLAGS); - qtnf_sta_info_parse_flags(&sinfo->sta_flags, &info->state); -} + if (qtnf_sta_stat_avail(sta_flags, QLINK_STA_INFO_STA_FLAGS)) { + sinfo->filled |= BIT(NL80211_STA_INFO_STA_FLAGS); + qtnf_sta_info_parse_flags(&sinfo->sta_flags, &stats->sta_flags); + } -static int qtnf_cmd_sta_info_parse(struct station_info *sinfo, - const u8 *payload, size_t payload_size) -{ - const struct qlink_sta_stat_basic_counters *counters; - const struct qlink_sta_info_generic *sta_info; - u16 tlv_type; - u16 tlv_value_len; - size_t tlv_full_len; - const struct qlink_tlv_hdr *tlv; + if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES)) { + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); + sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes); + } - sinfo->filled = 0; + if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES)) { + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); + sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes); + } - tlv = (const struct qlink_tlv_hdr *)payload; - while (payload_size >= sizeof(struct qlink_tlv_hdr)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > payload_size) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); - return -EINVAL; - } - switch (tlv_type) { - case QTN_TLV_ID_STA_BASIC_COUNTERS: - if (unlikely(tlv_value_len < sizeof(*counters))) { - pr_err("invalid TLV size %.4X: %u\n", - tlv_type, tlv_value_len); - break; - } + if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES64)) { + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); + sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes); + } - counters = (void *)tlv->val; - qtnf_sta_info_parse_basic_counters(sinfo, counters); - break; - case QTN_TLV_ID_STA_GENERIC_INFO: - if (unlikely(tlv_value_len < sizeof(*sta_info))) - break; + if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES64)) { + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); + sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes); + } - sta_info = (void *)tlv->val; - qtnf_sta_info_parse_generic_info(sinfo, sta_info); - break; - default: - pr_warn("unexpected TLV type: %.4X\n", tlv_type); - break; - } - payload_size -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); + if (qtnf_sta_stat_avail(rx_packets, QLINK_STA_INFO_RX_PACKETS)) { + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); + sinfo->rx_packets = le32_to_cpu(stats->rx_packets); } - if (payload_size) { - pr_warn("malformed TLV buf; bytes left: %zu\n", payload_size); - return -EINVAL; + if (qtnf_sta_stat_avail(tx_packets, QLINK_STA_INFO_TX_PACKETS)) { + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->tx_packets = le32_to_cpu(stats->tx_packets); } - return 0; + if (qtnf_sta_stat_avail(rx_beacon, QLINK_STA_INFO_BEACON_RX)) { + sinfo->filled |= BIT(NL80211_STA_INFO_BEACON_RX); + sinfo->rx_beacon = le64_to_cpu(stats->rx_beacon); + } + + if (qtnf_sta_stat_avail(rx_dropped_misc, QLINK_STA_INFO_RX_DROP_MISC)) { + sinfo->filled |= BIT(NL80211_STA_INFO_RX_DROP_MISC); + sinfo->rx_dropped_misc = le32_to_cpu(stats->rx_dropped_misc); + } + + if (qtnf_sta_stat_avail(tx_failed, QLINK_STA_INFO_TX_FAILED)) { + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); + sinfo->tx_failed = le32_to_cpu(stats->tx_failed); + } + +#undef qtnf_sta_stat_avail } int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, @@ -715,7 +732,9 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, goto out; } - ret = qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len); + qtnf_cmd_sta_info_parse(sinfo, + (const struct qlink_tlv_hdr *)resp->info, + var_resp_len); out: qtnf_bus_unlock(vif->mac->bus); @@ -1992,21 +2011,17 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac, cmd = (struct qlink_cmd_change_sta *)cmd_skb->data; ether_addr_copy(cmd->sta_addr, mac); + cmd->flag_update.mask = + cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_mask)); + cmd->flag_update.value = + cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_set)); switch (vif->wdev.iftype) { case NL80211_IFTYPE_AP: cmd->if_type = cpu_to_le16(QLINK_IFTYPE_AP); - cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags( - params->sta_flags_mask)); - cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags( - params->sta_flags_set)); break; case NL80211_IFTYPE_STATION: cmd->if_type = cpu_to_le16(QLINK_IFTYPE_STATION); - cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags( - params->sta_flags_mask)); - cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags( - params->sta_flags_set)); break; default: pr_err("unsupported iftype %d\n", vif->wdev.iftype); diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index f4d7d1603e3c..5d98000b0f5b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -19,7 +19,7 @@ #include -#define QLINK_PROTO_VER 8 +#define QLINK_PROTO_VER 9 #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -185,6 +185,17 @@ struct qlink_auth_encr { u8 rsvd[2]; } __packed; +/** + * struct qlink_sta_info_state - station flags mask/value + * + * @mask: STA flags mask, bitmap of &enum qlink_sta_flags + * @value: STA flags values, bitmap of &enum qlink_sta_flags + */ +struct qlink_sta_info_state { + __le32 mask; + __le32 value; +} __packed; + /* QLINK Command messages related definitions */ @@ -402,16 +413,14 @@ struct qlink_cmd_set_def_mgmt_key { /** * struct qlink_cmd_change_sta - data for QLINK_CMD_CHANGE_STA command * - * @sta_flags_mask: STA flags mask, bitmap of &enum qlink_sta_flags - * @sta_flags_set: STA flags values, bitmap of &enum qlink_sta_flags + * @flag_update: STA flags to update * @if_type: Mode of interface operation, one of &enum qlink_iface_type * @vlanid: VLAN ID to assign to specific STA * @sta_addr: address of the STA for which parameters are set. */ struct qlink_cmd_change_sta { struct qlink_cmd chdr; - __le32 sta_flags_mask; - __le32 sta_flags_set; + struct qlink_sta_info_state flag_update; __le16 if_type; __le16 vlanid; u8 sta_addr[ETH_ALEN]; @@ -755,17 +764,27 @@ struct qlink_resp_manage_intf { struct qlink_intf_info intf_info; } __packed; +enum qlink_sta_info_rate_flags { + QLINK_STA_INFO_RATE_FLAG_HT_MCS = BIT(0), + QLINK_STA_INFO_RATE_FLAG_VHT_MCS = BIT(1), + QLINK_STA_INFO_RATE_FLAG_SHORT_GI = BIT(2), + QLINK_STA_INFO_RATE_FLAG_60G = BIT(3), +}; + /** * struct qlink_resp_get_sta_info - response for QLINK_CMD_GET_STA_INFO command * * Response data containing statistics for specified STA. * + * @filled: a bitmask of &enum qlink_sta_info, specifies which info in response + * is valid. * @sta_addr: MAC address of STA the response carries statistic for. - * @info: statistics for specified STA. + * @info: variable statistics for specified STA. */ struct qlink_resp_get_sta_info { struct qlink_resp rhdr; u8 sta_addr[ETH_ALEN]; + u8 rsvd[2]; u8 info[0]; } __packed; @@ -1003,6 +1022,15 @@ struct qlink_event_radar { /* QLINK TLVs (Type-Length Values) definitions */ +/** + * enum qlink_tlv_id - list of TLVs that Qlink messages can carry + * + * @QTN_TLV_ID_STA_STATS_MAP: a bitmap of &enum qlink_sta_info, used to + * indicate which statistic carried in QTN_TLV_ID_STA_STATS is valid. + * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by + * &struct qlink_sta_stats. Valid values are marked as such in a bitmap + * carried by QTN_TLV_ID_STA_STATS_MAP. + */ enum qlink_tlv_id { QTN_TLV_ID_FRAG_THRESH = 0x0201, QTN_TLV_ID_RTS_THRESH = 0x0202, @@ -1011,12 +1039,12 @@ enum qlink_tlv_id { QTN_TLV_ID_REG_RULE = 0x0207, QTN_TLV_ID_CHANNEL = 0x020F, QTN_TLV_ID_CHANDEF = 0x0210, + QTN_TLV_ID_STA_STATS_MAP = 0x0211, + QTN_TLV_ID_STA_STATS = 0x0212, QTN_TLV_ID_COVERAGE_CLASS = 0x0213, QTN_TLV_ID_IFACE_LIMIT = 0x0214, QTN_TLV_ID_NUM_IFACE_COMB = 0x0215, QTN_TLV_ID_CHANNEL_STATS = 0x0216, - QTN_TLV_ID_STA_BASIC_COUNTERS = 0x0300, - QTN_TLV_ID_STA_GENERIC_INFO = 0x0301, QTN_TLV_ID_KEY = 0x0302, QTN_TLV_ID_SEQ = 0x0303, QTN_TLV_ID_IE_SET = 0x0305, @@ -1038,67 +1066,8 @@ struct qlink_iface_comb_num { __le16 iface_comb_num; } __packed; -struct qlink_sta_stat_basic_counters { - __le64 rx_bytes; - __le64 tx_bytes; - __le64 rx_beacons; - __le32 rx_packets; - __le32 tx_packets; - __le32 rx_dropped; - __le32 tx_failed; -} __packed; - -enum qlink_sta_info_rate_flags { - QLINK_STA_INFO_RATE_FLAG_INVALID = 0, - QLINK_STA_INFO_RATE_FLAG_HT_MCS = BIT(0), - QLINK_STA_INFO_RATE_FLAG_VHT_MCS = BIT(1), - QLINK_STA_INFO_RATE_FLAG_SHORT_GI = BIT(2), - QLINK_STA_INFO_RATE_FLAG_60G = BIT(3), -}; - -enum qlink_sta_info_rate_bw { - QLINK_STA_INFO_RATE_BW_5 = 0, - QLINK_STA_INFO_RATE_BW_10 = 1, - QLINK_STA_INFO_RATE_BW_20 = 2, - QLINK_STA_INFO_RATE_BW_40 = 3, - QLINK_STA_INFO_RATE_BW_80 = 4, - QLINK_STA_INFO_RATE_BW_160 = 5, -}; - -/** - * struct qlink_sta_info_rate - STA rate statistics - * - * @rate: data rate in Mbps. - * @flags: bitmap of &enum qlink_sta_flags. - * @mcs: 802.11-defined MCS index. - * nss: Number of Spatial Streams. - * @bw: bandwidth, one of &enum qlink_sta_info_rate_bw. - */ -struct qlink_sta_info_rate { - __le16 rate; - u8 flags; - u8 mcs; - u8 nss; - u8 bw; -} __packed; - -struct qlink_sta_info_state { - __le32 mask; - __le32 value; -} __packed; - #define QLINK_RSSI_OFFSET 120 -struct qlink_sta_info_generic { - struct qlink_sta_info_state state; - __le32 connected_time; - __le32 inactive_time; - struct qlink_sta_info_rate rx_rate; - struct qlink_sta_info_rate tx_rate; - u8 rssi; - u8 rssi_avg; -} __packed; - struct qlink_tlv_frag_rts_thr { struct qlink_tlv_hdr hdr; __le16 thr; @@ -1243,4 +1212,105 @@ struct qlink_chan_stats { s8 chan_noise; } __packed; +/** + * enum qlink_sta_info - station information bitmap + * + * Used to indicate which statistics values in &struct qlink_sta_stats + * are valid. Individual values are used to fill a bitmap carried in a + * payload of QTN_TLV_ID_STA_STATS_MAP. + * + * @QLINK_STA_INFO_CONNECTED_TIME: connected_time value is valid. + * @QLINK_STA_INFO_INACTIVE_TIME: inactive_time value is valid. + * @QLINK_STA_INFO_RX_BYTES: lower 32 bits of rx_bytes value are valid. + * @QLINK_STA_INFO_TX_BYTES: lower 32 bits of tx_bytes value are valid. + * @QLINK_STA_INFO_RX_BYTES64: rx_bytes value is valid. + * @QLINK_STA_INFO_TX_BYTES64: tx_bytes value is valid. + * @QLINK_STA_INFO_RX_DROP_MISC: rx_dropped_misc value is valid. + * @QLINK_STA_INFO_BEACON_RX: rx_beacon value is valid. + * @QLINK_STA_INFO_SIGNAL: signal value is valid. + * @QLINK_STA_INFO_SIGNAL_AVG: signal_avg value is valid. + * @QLINK_STA_INFO_RX_BITRATE: rxrate value is valid. + * @QLINK_STA_INFO_TX_BITRATE: txrate value is valid. + * @QLINK_STA_INFO_RX_PACKETS: rx_packets value is valid. + * @QLINK_STA_INFO_TX_PACKETS: tx_packets value is valid. + * @QLINK_STA_INFO_TX_RETRIES: tx_retries value is valid. + * @QLINK_STA_INFO_TX_FAILED: tx_failed value is valid. + * @QLINK_STA_INFO_STA_FLAGS: sta_flags value is valid. + */ +enum qlink_sta_info { + QLINK_STA_INFO_CONNECTED_TIME, + QLINK_STA_INFO_INACTIVE_TIME, + QLINK_STA_INFO_RX_BYTES, + QLINK_STA_INFO_TX_BYTES, + QLINK_STA_INFO_RX_BYTES64, + QLINK_STA_INFO_TX_BYTES64, + QLINK_STA_INFO_RX_DROP_MISC, + QLINK_STA_INFO_BEACON_RX, + QLINK_STA_INFO_SIGNAL, + QLINK_STA_INFO_SIGNAL_AVG, + QLINK_STA_INFO_RX_BITRATE, + QLINK_STA_INFO_TX_BITRATE, + QLINK_STA_INFO_RX_PACKETS, + QLINK_STA_INFO_TX_PACKETS, + QLINK_STA_INFO_TX_RETRIES, + QLINK_STA_INFO_TX_FAILED, + QLINK_STA_INFO_STA_FLAGS, + QLINK_STA_INFO_NUM, +}; + +/** + * struct qlink_sta_info_rate - STA rate statistics + * + * @rate: data rate in Mbps. + * @flags: bitmap of &enum qlink_sta_info_rate_flags. + * @mcs: 802.11-defined MCS index. + * nss: Number of Spatial Streams. + * @bw: bandwidth, one of &enum qlink_channel_width. + */ +struct qlink_sta_info_rate { + __le16 rate; + u8 flags; + u8 mcs; + u8 nss; + u8 bw; +} __packed; + +/** + * struct qlink_sta_stats - data for QTN_TLV_ID_STA_STATS + * + * Carries statistics of a STA. Not all fields may be filled with + * valid values. Valid fields should be indicated as such using a bitmap of + * &enum qlink_sta_info. Bitmap is carried separately in a payload of + * QTN_TLV_ID_STA_STATS_MAP. + */ +struct qlink_sta_stats { + __le64 rx_bytes; + __le64 tx_bytes; + __le64 rx_beacon; + __le64 rx_duration; + __le64 t_offset; + __le32 connected_time; + __le32 inactive_time; + __le32 rx_packets; + __le32 tx_packets; + __le32 tx_retries; + __le32 tx_failed; + __le32 rx_dropped_misc; + __le32 beacon_loss_count; + __le32 expected_throughput; + struct qlink_sta_info_state sta_flags; + struct qlink_sta_info_rate txrate; + struct qlink_sta_info_rate rxrate; + __le16 llid; + __le16 plid; + u8 local_pm; + u8 peer_pm; + u8 nonpeer_pm; + u8 rx_beacon_signal_avg; + u8 plink_state; + u8 signal; + u8 signal_avg; + u8 rsvd[1]; +}; + #endif /* _QTN_QLINK_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c index 37b78f00e8e5..19981d6440b6 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c @@ -164,3 +164,15 @@ enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val) return QLINK_HIDDEN_SSID_NOT_IN_USE; } } + +bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit, + unsigned int arr_max_len) +{ + unsigned int idx = bit / BITS_PER_BYTE; + u8 mask = 1 << (bit - (idx * BITS_PER_BYTE)); + + if (idx >= arr_max_len) + return false; + + return arr[idx] & mask; +} diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index 260383d6d109..6c24561eb41f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -69,5 +69,7 @@ void qlink_chandef_q2cfg(struct wiphy *wiphy, void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef, struct qlink_chandef *qch); enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val); +bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit, + unsigned int arr_max_len); #endif /* _QTN_FMAC_QLINK_UTIL_H_ */