From patchwork Mon Nov 13 10:28:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Matyukevich X-Patchwork-Id: 10055527 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 AFEC06029B for ; Mon, 13 Nov 2017 10:28:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7C17C29362 for ; Mon, 13 Nov 2017 10:28:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 710CF29367; Mon, 13 Nov 2017 10:28:47 +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 459DB29362 for ; Mon, 13 Nov 2017 10:28:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752353AbdKMK2p (ORCPT ); Mon, 13 Nov 2017 05:28:45 -0500 Received: from mail-sn1nam01on0085.outbound.protection.outlook.com ([104.47.32.85]:59533 "EHLO NAM01-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752260AbdKMK2k (ORCPT ); Mon, 13 Nov 2017 05:28:40 -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=Yy8POCd5GnGC7vXPIPcdTHXRJNyo3lXI46kcXrDSvT5QbPM3tPM/ObGbcYIYUoOICTHbff9MA5qNHdtr5DSidmtIqL1DIkTTjr5XSEeZTevGg82qkjJ7LRVz8DzO8l4ylKRryDzNWrZepUk4Q13mZoDFGVAHlOMYFt7TJfX7nDA= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=sergey.matyukevich.os@quantenna.com; Received: from bars.quantenna.com (195.182.157.78) by BLUPR05MB1924.namprd05.prod.outlook.com (10.162.224.14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.20.239.4; Mon, 13 Nov 2017 10:28:36 +0000 From: Sergey Matyukevich To: linux-wireless@vger.kernel.org Cc: Igor Mitsyanko , Avinash Patil , Vasily Ulyanov Subject: [PATCH 08/10] qtnfmac: modify GET_STA_STATS cmd format for back/forward compatibility Date: Mon, 13 Nov 2017 13:28:13 +0300 Message-Id: <20171113102815.11254-9-sergey.matyukevich.os@quantenna.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171113102815.11254-1-sergey.matyukevich.os@quantenna.com> References: <20171113102815.11254-1-sergey.matyukevich.os@quantenna.com> MIME-Version: 1.0 X-Originating-IP: [195.182.157.78] X-ClientProxiedBy: AM5P190CA0007.EURP190.PROD.OUTLOOK.COM (10.161.47.148) To BLUPR05MB1924.namprd05.prod.outlook.com (10.162.224.14) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: b6d3acf2-f564-4729-989b-08d52a814d2f X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603199); SRVR:BLUPR05MB1924; X-Microsoft-Exchange-Diagnostics: 1; BLUPR05MB1924; 3:8zIsrJh7Z4GlwEGCrXKh3IRxUiJKI2KcPU3NgBO3v0hpuASjXimBxhW9nh4IlN4Y6jBn4RYBEWItGU/jS08H+6Anf2KTb3Eir7mSvlYa2/e4Llj19PwL7yCwB9AuG0Cx3S6S+RXb/tKmZ3cGD8vxvUvzAs4YOiV2YESwF3EQ4fJyHIhogKthCedn3siLrD4Z95WZszyXbPRpcay3IQVk2TcijAU5To+F2QUc2Kh+yuOQ1a96x30nnqOoBvkYmp63; 25:iGMjzZLRlR87DJaNoW8fi98KMahF87cwhVFAjlmAAZ+Lo2ntW/zW57naezgJULN1zcfHWu8h/RBMuD3JeO+4vIBJxyTtjclHOA5kNyEsTMjoKBoaCWbzAru+HoRBA2TvfaubQtARfWoBR0ycFtOB5DswcMvBPz9VlZ/SW0Fx9361g12fiBAcMBNAKrMvGKgCmRqVZXcP7naKUuCaITyBq9WSQufrAlMJ6vVHOxMSbytudXmg/4X9WXEregKPh2eSoFQ3gNvLvtGixaYHCWC4ZFM63z5/zY/+RETMF1P/ZBQ63iP9gKnqRO0PzxiCCNXn+p0b6slIUZoGWH93xT6L1zIXsH5GnbScj5SlyjYUbZc=; 31:vVLcYup+U3kHaiB9cdfJXYdhwVOWyBlxujDHYGwD5Syx0XsrQ5vOpwlmFYsbNCl1L0A3M3XbFh7AZJh9ob8ttnjLC/ETpxy+bVtoicn8Vr0d80tcM11SmUThKiSkB2pru0hICqJcclRNATCOpTCigna/9x9ocGXFIp8oNpvhxgvkytLZbDIGMAX5n4TtP9ul2LTfB6DHpNYchrUPvHWgshMtNYZ4Yc3ZYpcCa70OQ4I= X-MS-TrafficTypeDiagnostic: BLUPR05MB1924: X-Microsoft-Exchange-Diagnostics: 1; BLUPR05MB1924; 20:Pv52Jcii6Ti9wpsGpCUm1QOOIWHwUtC9kvBveMmjoZQEPk913Anpr9mB9UqfnyQnlu8H3Jv+zcpPIJNcWJU/Ms2kKkU690Drb1yeuQRUL+KWsmX1EmRJP54h5/HtoltSXr2IQI9Y41cgbNnDMcX1EkUxRwJAovWRbOMRcRb0prAklxUClN238VrrzAsTbaC0vQWKP4Vuo4Ai4eTA6jGb3p4aJlmHgj2GFYYQCdNghwLT96EgRdvzimLk0uwvfGv+OfYlYL+lk//o70WxTakR3b4AczWbIoDDQT1+QawgDHWFNI+1fNFUsukoZsdCLvfumkrKIOYegKN6Wpi/aSK187BH8zf05mCzyE+RU+8BvWxrP2QofdTswO4Hb31H072ccp3IzLwVakOHGlWNNIeW/igk+1x1Ixjgy8eb9IJu70CNEUgLWig88BqjCWhp7wTXP2pZuyxhxEizxwu9DJaTVkX4UrLd+TgSHIgKcCUr3kjWAPxdPe+1J0C0sVrFyL/i; 4:BP6MKkxI+2618xB112eFnCZoy9rV8sN66N2OkYJC2oj6BPgYAiHcdx/z4ySxrqRN6gj7qrlsY7uym57KkEo8JatH/ikMrzrbLRnKGoO8AuX9YSSxadH72v0Wa3uJdplTt+x4KN2blAwwHb9K13+KsOud261Ha5LZ6yoqprr5YdLHMhbqpzm/1FJEwhWMj4zdiNAPYtE18L9IK35XkHGGZS+kUiwz6smOW41DOhbZKOi9oj31/4hVowiNONgaNNZ8e51rQPLtHScqN4kSvSRUnA== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(100000703101)(100105400095)(93006095)(93001095)(3231022)(10201501046)(3002001)(6041248)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123558100)(20161123564025)(20161123562025)(20161123560025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BLUPR05MB1924; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BLUPR05MB1924; X-Forefront-PRVS: 0490BBA1F0 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(376002)(39830400002)(346002)(199003)(189002)(5660300001)(107886003)(47776003)(105586002)(50226002)(54906003)(66066001)(53936002)(2361001)(76176999)(316002)(6486002)(6916009)(50986999)(97736004)(4326008)(33646002)(5003940100001)(106356001)(2906002)(6666003)(2950100002)(25786009)(101416001)(16526018)(189998001)(81166006)(81156014)(86362001)(575784001)(8676002)(6116002)(3846002)(478600001)(68736007)(53416004)(48376002)(7736002)(50466002)(2351001)(16586007)(103116003)(69596002)(36756003)(305945005)(1076002)(8936002); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR05MB1924; H:bars.quantenna.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX: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; BLUPR05MB1924; 23:7swQAKfE2TrxBbMkpDWCKmWv839lXdFDydFGW6MdO?= =?us-ascii?Q?Z7cUildHCMNslWO6LJeVfSXcW0vVX67sLDTo3ahvigx6UaBPVpVWdXGIfm+l?= =?us-ascii?Q?Yxy+QgaInG3Vmb4l7ievB7UBbl/OAHFkp52u00cZ0YOMZR446OOhEj1i+KrI?= =?us-ascii?Q?Iv4DcpdIN2FQO1Hx15pLRlM+NxL0s5jfzt36fe08Ad0xvPcenbjD+HWjb2cP?= =?us-ascii?Q?D4ZycrfaFgpvWQLxIHGvNTjw8uIyS5lEMLk5DV1k2pcahyBGwSSlDDWrxbPo?= =?us-ascii?Q?Iod8aAmVO/bgFebgzIoX6fSDclG+nEkp5UVFAh7pitwijNUf7vOGnq/XKNwx?= =?us-ascii?Q?iUAMO+Kzenqpm1MUoIldWQ4Yya6MAYXxe4NDUAMiQaBDzK5OGX/Ko35mQah0?= =?us-ascii?Q?h7NcZ7UWtE6QBv2Ak+SbC2nPHp14moy51QBN8SfnClvbW47S+zacyMcA4edD?= =?us-ascii?Q?7epfN5fDp9IbFFi1fYLUFvGh/hjORFbb85xC3K1wPxFR+2ZhgKvzkBeL2D62?= =?us-ascii?Q?wTVWslF8cXduRH9oI09nzRNhCg8B3pU3ziMIpmto0f/+zcOLqRmRtLQPlc42?= =?us-ascii?Q?tI0ee2mHaCj5hruILByKWf91xri/XAelekvjV/lhTUQSqk7X6AcgvSpsR0pe?= =?us-ascii?Q?cU2srCJWR5b+wzAaGnK/+dAGAqjSByUtyT6tJDyEI2v72wjuQ14ql+bHSzkq?= =?us-ascii?Q?l22BK9hOQ5Rb94pZ6ENwTe01m/mflk9Tf00XY90xLVpTTWR75N4OUL1Z7OEG?= =?us-ascii?Q?jUcif2nwCCPu6Cp7tLNjMJ9v+8o4aVXiczV3OlBVY7VppDIf6K7I6xNUQtvN?= =?us-ascii?Q?ko0tg6WTDvuDQo/x5NvU4V1b5yOlfkp4lvAQOysjPB+lFSIz6lYmkRQMU6YC?= =?us-ascii?Q?ArFe/EgAVQrZ3FYTPMtLmnGPjH5283vawGWACMIWmdfoguFLNbMEjP7Yz463?= =?us-ascii?Q?5nzSRcccK2nSrfaa8VkD0n+iJAE93rqBIc+E7Fi6lrcSETsjPRcumOkqRVdN?= =?us-ascii?Q?fOfxr2vIp6IVpECJzwweg7wdNu+wKyM9GEEbcPcvf6OdWV5GPfxNWX2sVXZD?= =?us-ascii?Q?uaOJNXvdcNQiXILrroN1qepEBm3b640pcr0KK5pWcawSusWkuUOZ+EEVxwmQ?= =?us-ascii?Q?tnEBbkNa8xXgjQc76xnGWWBcPbnUegmlKmL4LjLPanBqJ4+K0jvXkxYsGhHZ?= =?us-ascii?Q?9garykV+CGEWA96ChR95o9I6aLKLNHGGDVYO3O8HZMwy3zmNKTZjG1mtHtAr?= =?us-ascii?Q?oeIXYKopLyY89uZ/2w=3D?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR05MB1924; 6:bcjPcPq72UiFs79fvtDaMehSlIa1w0BqHqJGpyfcDY4DBthVPsp31Ul9TuWcF+YOmurdcSv09rcya9I4ZLy3ZzCJELA1PWF4jdkdWT+GimLUwS7Hj1KAE1NaMIBO5OhJnqKmhxjOuTRTgzj387lyhp8ENnhhObbhr6W0xO05AFoZq6xioCQNTpqUoDV4S9xwnbbWC/jIn2qNLY97pHHLgCj9z6aliv+giqOvz+pIPPjbHncAS6Bg9pbUgtRmzldzwy4enEhsfn5T5DAjxSnfLyreWQo3Zygm3bIU39YOVAjf+t1dVlbHnts0R//qp0rSRDK5pM0T6Ixa/JUCBwm6zqPcZZdXGgF0wRY0Oe2EyM8=; 5:VEzjAbFbKKOcfy2yE+BojusKGJX8k/PJBhAIABO7SrZgWK9DJLWcNDaZogJJCGTgiPd2+qEQ8+XI1gITbBms1/pg7IZ2AIW5tzEYdJzToFY8u584UlwOG4JmFuXtrzivfh0/yCIEiNXM25ErkiQnt4mxtR+3GyFfqqjeQUVQKFg=; 24:nLvzVTqECHpMAE1XSj76bHN+0XK3R1+KYFzI/WewLQ7334cY3EKN2rgt70VLK8Ny8WQGp2abn2WsTeFdhYVq79yuQ73V0F6LpZOcp1IShEs=; 7:RQRrhJTu/k4oHYoF7EI4tIaBXaJEiuWmEfdUTSfZzObMQCk6xNVA35ShuVmvKy9Ef/frae7fv16AfKnNiEyZkDBZypczecqtMSmxPBKRsDC7y5vM9avRhDK5neeexx3NIkLUMpiSJep+Jgu0ziPaDC60Bfn/QdXmLsNlNonHgOibOs/JYRCsS1lyxnGCOT24ERvxb5DnYE4fTc+vhaGcgBe5ppfyGLN39PK7nIvnExXzNHnGASO5RKhG84HOcDUe SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: quantenna.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Nov 2017 10:28:36.8467 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b6d3acf2-f564-4729-989b-08d52a814d2f X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a355dbce-62b4-4789-9446-c1d5582180ff X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR05MB1924 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_ */