From patchwork Thu Jun 17 15:58:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viktor Barna X-Patchwork-Id: 462775 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71FB1C49EA2 for ; Thu, 17 Jun 2021 16:03:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 586F561249 for ; Thu, 17 Jun 2021 16:03:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233618AbhFQQFu (ORCPT ); Thu, 17 Jun 2021 12:05:50 -0400 Received: from mail-eopbgr80052.outbound.protection.outlook.com ([40.107.8.52]:15895 "EHLO EUR04-VI1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S232689AbhFQQFs (ORCPT ); Thu, 17 Jun 2021 12:05:48 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LAwLi2WcGFr2ubLd3VKBmadjM/fYm5+xuNowp1f+B+Agpny2CFLxVDFBgrIrquADa3awGmd8Yz7PSaOCJzsF/9DcYubQTPhYd2oXmm2A4DTlH32FTJQydm7cYJVNDcAyCvlEGbW1NAI1eJKEnfdm3KmdiVuBTpSdOfV0ezv4i58K2KK90chJZkBeBrZWuRKIjVJGXR42R9DhVz7beyWfjmhmP5L/30klQxQBxziMWqYW42rkleLbl+ZlsX+3q7dus1AQEpGv0BIxCdnbuM8BQ23t25k/luu79DeHHB6Onxk9BdvClBedbLk4EnFZpX2tSE+1u3kvNDhEGrrmBnm5aA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0KATMfPmJp/KJWKiWZBc3jTXXdjpmP3/fPJ14IpM31M=; b=D8LDzp/VOD7s/aa8lu1hULX4ccFdXmFN4iSBgCnnvo4pjlTbNvT6mN26uKR5fYlXUSWJ8MWeN2EyJYBuRn7e3YhpuqaBrcaOIpoMnyrGwXvCR4lVi6a7lZWjKioERzwPuQBNw633eHrQmXM94CnS3ts+GsyYIjStt30czNAoD1Heb5CPjlU5xF34kY9xdKh+FGHu67vKcjayl6yEAfJ5xfGH8XckKjSt9Y7ZjA1J/i0683pSQu+EJ2Vmk4eIyjYvuFVCVtGSYyNvni9FAHBthevChHoOEzLdDL0Aq+rGUfk8GeqQN9bO8ZLsqhyBYt8DuBosQmJegr+ZYROHKxoVLg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=celeno.com; dmarc=pass action=none header.from=celeno.com; dkim=pass header.d=celeno.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=celeno.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0KATMfPmJp/KJWKiWZBc3jTXXdjpmP3/fPJ14IpM31M=; b=DxW7QestOKeCeitcd7TWHE/norc9cRVTdM9CSBHESliTkLPukFZGAH/fvwTPd18NgGsdcke/771O5Z2SWrGx+T0l/0sK8l51MD9PCZloDntr4XqVLpFuVQgzP0AZKsXSyRRhLeApYxy/WiFMhugJiHQGZdb9kfzq6gJx6JvO/iY= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=celeno.com; Received: from AM9P192MB1412.EURP192.PROD.OUTLOOK.COM (2603:10a6:20b:38b::16) by AM9P192MB0966.EURP192.PROD.OUTLOOK.COM (2603:10a6:20b:1ce::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4195.25; Thu, 17 Jun 2021 16:03:37 +0000 Received: from AM9P192MB1412.EURP192.PROD.OUTLOOK.COM ([fe80::1847:5583:4db7:102f]) by AM9P192MB1412.EURP192.PROD.OUTLOOK.COM ([fe80::1847:5583:4db7:102f%4]) with mapi id 15.20.4242.021; Thu, 17 Jun 2021 16:03:37 +0000 From: viktor.barna@celeno.com To: linux-wireless@vger.kernel.org Cc: Kalle Valo , "David S . Miller" , Jakub Kicinski , Aviad Brikman , Eliav Farber , Oleksandr Savchenko , Shay Bar , Viktor Barna Subject: [RFC v1 032/256] cl8k: add cca.c Date: Thu, 17 Jun 2021 15:58:39 +0000 Message-Id: <20210617160223.160998-33-viktor.barna@celeno.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210617160223.160998-1-viktor.barna@celeno.com> References: <20210617160223.160998-1-viktor.barna@celeno.com> X-Originating-IP: [62.216.42.54] X-ClientProxiedBy: PR3PR09CA0018.eurprd09.prod.outlook.com (2603:10a6:102:b7::23) To AM9P192MB1412.EURP192.PROD.OUTLOOK.COM (2603:10a6:20b:38b::16) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (62.216.42.54) by PR3PR09CA0018.eurprd09.prod.outlook.com (2603:10a6:102:b7::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4242.18 via Frontend Transport; Thu, 17 Jun 2021 16:03:08 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e45f85f9-2070-4250-4ead-08d931a966fc X-MS-TrafficTypeDiagnostic: AM9P192MB0966: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:454; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 7b6qT2wJhaSNv5IgmUhSbfcZyG0+2TSuK/R1xGbCqjE35jXb5iPfcg+fVNZjCPts9HpgcKcu7BW7FEoST1h8KZPniK+1Ap5ZmBQkX07WazPF1Oz8nUJb6TYCmdyfpg5LFQKNp/0EhVMdhRTCr3zH6yxybz/z8gH2a+b3DeKXppr7U1fO0Z89aD6doTcGW+A22gNqHd0hBtM46Fe1qBTc9BmF/ywbtaMmQyVW/EnpBhz8kDJ23/ms/QQq9NK2n8qkSdu0viSZ3CvB+GwGGYeVftvS9nYCd5bbhewGuOJ42rgOhmgQGjr0MhD+vX3uqORdP4bGZ3Z/G1I+uJrky6w1W84sobO4qSMl81IiGSzxMxHOztYWz9Ytc7q/bjUjSsLAt9ekj/AKdODHHHa4ar1Veq6KaFMYwz8iuWR3jaE/Lok/XEhotqCxRgVUqutqle+WlG2Nus6jTar516YvtSmyySU5/yA2YUqLpFpbRsYvkL+HVHm1j2Yae3HmFMfOYbIoG/qmGRrib6riSV2WOrHGolJAwDkoZLxkyQ2r+vne2OQH88MrntM1GTtrgZEivUOMxYd6rkVaCsYq9DlNi8qzeek5GR2KBekwUH9LnZSOdfNkWG8WIQ5J2YFYe1HHyVm2kt14UINUKYM8775MbyPkYc29UnGj1geYNmESXfMB2bgCjOcaZqS5BRip3YF20RV9tVyPe7P1VoTEvHltU1EAJw== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM9P192MB1412.EURP192.PROD.OUTLOOK.COM; PTR:; CAT:NONE; SFS:(136003)(366004)(346002)(39850400004)(376002)(396003)(30864003)(4326008)(1076003)(2616005)(8676002)(186003)(6512007)(6486002)(107886003)(83380400001)(6916009)(38100700002)(55236004)(316002)(16526019)(6506007)(38350700002)(6666004)(54906003)(8936002)(26005)(508600001)(36756003)(2906002)(9686003)(52116002)(956004)(5660300002)(66946007)(66556008)(66476007)(86362001)(69590400013)(32563001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: NokdRWNpvhupUv3FrAqZOm97MGD7flL46TDaotAHlnTJJZNZKU8yCHEq8FdDnU1kvLKuWoyrsQK3ReE1Xv8fxG8BUYxFrjoXqhl8KfkaghqwNZB71wejE6PTm9qegfVGk6a/moz4gxRlRIlSvCO0bqpGa6IVjisWrzrrFKue6jBnA3+nPwAY1nCM+M6tq+f4mAGcq9LTCi9s1BuI0qYucQh4SctdmE8TkMt2cFd3epCETe3KbxggDKXvg3wcpEXkUbkaCYVTg9g4tBVi5ESDRpVyHLpBhSu7pgxlGqvEN6fe2ErQZ98XUbKaUXMRzgsc0iIsfsDpEPEAuI7pzm0BFwa/17PFg26Nx1qhxAo1ZjfP7FRlDsvTnYKWmPAJTcz4I2sTQZS3CEVjQ7veBYwVCJsBHqOWE9XVAc+i/U/oVUq6RE5hmt4EzzrXjRCzjlj7nxIuh2mW6N5D8zN4oLYQE22DmJ2KVy/SSqv6jlW5oRh/PDNs9R44TA2Oo9KJ8GTjvy1ZHKc8vp+tV1BdZHZe790ccTBc4ewNBZDEXlhic52xgK67Lky4I7AUv2IjrviSaqRXKNPRxztVCcduI9A8aZ/6UdPGeuTLbVzxJdiB7mjOUvG9YFaFrWnH48UlqzqEO5w53Mr28iP2f5BZyRCNday27ItptDfL40Idfw8mJROE9Rpen0R7H29U+hB49jXC0A34iUTZyCGWvcSY1e/8IUmenwavf7tsjCG43mCbwxPw1Ao/YguGsbZkOxbGP3YkOSQ7PACjBNGsT8xM/UFWXwytMBKgluichM9fvY4QY1950nbfnaYX9uRjD/EGOLIYfNRH9GM0epN6Yop8VNRXfpLx5fld1D2DM4LLiW3yIKEXHSH59YNwz5w72Od2OMkh3TP/kix4y/B93UbHRLDMEnqq9j3l80mTPF1MPPJjIC+9rCcPZ0VW9d9nhHhimxtzRi0EakxuZGGP55np0//eH8zw7iloYUyIUqcEIwlUPcn9dme/fnCxQdWTzKXQbKcrRcbjkQs1rUYMlg0UIBF5DIwwXLhgdYokSMJRcP7FP1Umd/4j54rJXXQir+R/rURVF9dD+TYjxet/NvcF1TEdAtyL5abiO9cMiVIzks7psqueeyAlMZ4g1UxZ9Ht9Nw/doM+4SrFhyRig9G6tD8eueO4mwr66KR6dakm7jNE8lSncPxDDR/u/cFHR9mRIsjl+UwW/pSxxbYtKLnIh7BA96n5nVEOIpHaLN1co1zRcnRETomn9uYlvNv1uAC/QqQk5zSPKumLZ+C9b8SvG1xyrSXB2O9SMpi2ntJywl0rmaHq4VRxEARvRe+IPOFrGQ1s3 X-OriginatorOrg: celeno.com X-MS-Exchange-CrossTenant-Network-Message-Id: e45f85f9-2070-4250-4ead-08d931a966fc X-MS-Exchange-CrossTenant-AuthSource: AM9P192MB1412.EURP192.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Jun 2021 16:03:10.0126 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: f313103b-4c9f-4fd3-b5cf-b97f91c4afa8 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: PEpiHuLBL/mERpamn3qEGvJCJIXAl2X6Xu/19Yo+5RkbhqJLZAPdCq5hZQ5iuE6Ue1QLrQ5VXrlsMaOCxk5xxg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9P192MB0966 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Viktor Barna (Part of the split. Please, take a look at the cover letter for more details). Signed-off-by: Viktor Barna --- drivers/net/wireless/celeno/cl8k/cca.c | 518 +++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 drivers/net/wireless/celeno/cl8k/cca.c -- 2.30.0 diff --git a/drivers/net/wireless/celeno/cl8k/cca.c b/drivers/net/wireless/celeno/cl8k/cca.c new file mode 100644 index 000000000000..70f1d54b771b --- /dev/null +++ b/drivers/net/wireless/celeno/cl8k/cca.c @@ -0,0 +1,518 @@ +// SPDX-License-Identifier: MIT +/* Copyright(c) 2019-2021, Celeno Communications Ltd. */ + +#include "cca.h" +#include "reg/reg_mac_hw.h" +#include "reg/reg_riu.h" +#include "band.h" +#include "hw.h" + +#define TO_PERCENT(val, interval) (100 * (val) / (interval)) +#define SET_CCA_OPT(en, a, b) ((en) ? ((a) |= (b)) : ((a) &= ~(b))) +#define MDM_AFTER_L_SIG 0x3F0 +#define MDM_BEFORE_L_SIG 0x3F8 +#define SAMPLE_RES 5 + +static void cl_cca_print_cs(struct cl_hw *cl_hw, unsigned long time) +{ + u8 cca_cs = TO_PERCENT(riu_cca_cnt_cs_get(cl_hw), time); + + pr_debug("cca_cs = %u%%\n", cca_cs); +} + +static void cl_cca_print_mdm_state(struct cl_hw *cl_hw, unsigned long time) +{ + u32 cca_mdm_state_p = TO_PERCENT(riu_cca_cnt_modem_state_p_get(cl_hw), time); + u32 cca_mdm_state_20s = TO_PERCENT(riu_cca_cnt_modem_state_20_s_get(cl_hw), time); + u32 cca_mdm_state_40s = TO_PERCENT(riu_cca_cnt_modem_state_40_s_get(cl_hw), time); + u32 cca_mdm_state_80s = TO_PERCENT(riu_cca_cnt_modem_state_80_s_get(cl_hw), time); + + pr_debug("cca_mdm_state: primary = %u%%, sec20 = %u%%, sec40 = %u%%, sec80 = %u%%\n", + cca_mdm_state_p, cca_mdm_state_20s, cca_mdm_state_40s, cca_mdm_state_80s); +} + +static void cl_cca_print_mp(struct cl_hw *cl_hw, unsigned long time) +{ + u32 cca_mp_20p = TO_PERCENT(riu_cca_cnt_gi_20_p_get(cl_hw), time); + u32 cca_mp_20s = TO_PERCENT(riu_cca_cnt_gi_20_s_get(cl_hw), time); + u32 cca_mp_40s = TO_PERCENT(riu_cca_cnt_gi_40_s_get(cl_hw), time); + u32 cca_mp_80s = TO_PERCENT(riu_cca_cnt_gi_80_s_get(cl_hw), time); + + pr_debug("cca_mp: primary = %u%%, sec20 = %u%%, sec40 = %u, sec80 = %u%%\n", + cca_mp_20p, cca_mp_20s, cca_mp_40s, cca_mp_80s); +} + +static void cl_cca_print_energy(struct cl_hw *cl_hw, unsigned long time) +{ + u32 cca_energy_thr_p = TO_PERCENT(riu_cca_cnt_energy_thr_p_get(cl_hw), time); + u32 cca_energy_thr_20s = TO_PERCENT(riu_cca_cnt_energy_thr_20_s_get(cl_hw), time); + u32 cca_energy_thr_40s = TO_PERCENT(riu_cca_cnt_energy_thr_40_s_get(cl_hw), time); + u32 cca_energy_thr_80s = TO_PERCENT(riu_cca_cnt_energy_thr_80_s_get(cl_hw), time); + + pr_debug("cca_energy_thr: primary = %u%%, sec20 = %u%%, sec40 = (%u%%), sec80 = %u%%\n", + cca_energy_thr_p, cca_energy_thr_20s, cca_energy_thr_40s, cca_energy_thr_80s); +} + +static void cl_cca_print_energy_band(struct cl_hw *cl_hw, unsigned long time) +{ + u32 cca_energy_20_band0 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_0_get(cl_hw), time); + u32 cca_energy_20_band1 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_1_get(cl_hw), time); + u32 cca_energy_20_band2 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_2_get(cl_hw), time); + u32 cca_energy_20_band3 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_3_get(cl_hw), time); + u32 cca_energy_20_band4 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_4_get(cl_hw), time); + u32 cca_energy_20_band5 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_5_get(cl_hw), time); + u32 cca_energy_20_band6 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_6_get(cl_hw), time); + u32 cca_energy_20_band7 = TO_PERCENT(riu_cca_cnt_energy_thr_20_band_7_get(cl_hw), time); + + pr_debug("cca_energy_20: band0 = %u%%, band1 = %u%%, band2 = %u%%, band3 = %u%%, " + "band4 = %u%%, band5 = %u%%, band6 = %u%%, band7 = %u%%\n", + cca_energy_20_band0, cca_energy_20_band1, cca_energy_20_band2, + cca_energy_20_band3, cca_energy_20_band4, cca_energy_20_band5, + cca_energy_20_band6, cca_energy_20_band7); +} + +static void cl_cca_update_counters(u16 *hist, u32 counter) +{ + if (counter == 0) + hist[0]++; + else if (counter > 100) + hist[CCA_MAX_SAMPLE - 1]++; + else + hist[((counter - 1) / SAMPLE_RES) + 1]++; +} + +static void cl_cca_print_utility(struct cl_hw *cl_hw, unsigned long time) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + struct cl_edca_hist_db *hist_db = &cca_db->edca_hist; + u32 cca_cs = riu_cca_cnt_cs_get(cl_hw); + u32 edca_busy = mac_hw_edca_cca_busy_get(cl_hw); + u32 cca_mdm_state_p = riu_cca_cnt_modem_state_p_get(cl_hw); + u32 tx_mine = mac_hw_tx_mine_busy_get(cl_hw); + u32 rx_mine = mac_hw_rx_mine_busy_get(cl_hw); + u32 sample_cnt = hist_db->sample_cnt; + u32 edca_busy_diff = edca_busy - cca_db->edca_busy; + u32 tx_mine_diff = tx_mine - cca_db->tx_mine; + u32 rx_mine_diff = rx_mine - cca_db->rx_mine; + + /* Cca utility formulas */ + u32 air_util = cca_cs + tx_mine_diff; + u32 wifi_air_util = cca_mdm_state_p + tx_mine_diff; + u32 not_mine_rx_wifi = cca_mdm_state_p - rx_mine_diff; + u32 mine_util = tx_mine_diff + rx_mine_diff; + u32 non_wifi_util = edca_busy_diff - cca_mdm_state_p; + u32 not_mine_util = edca_busy_diff - rx_mine_diff; + u32 not_mine_time = time - mine_util; + + u32 air_util_percent = TO_PERCENT(air_util, time); + u32 wifi_air_util_percent = TO_PERCENT(wifi_air_util, time); + u32 not_mine_rx_wifi_percent = TO_PERCENT(not_mine_rx_wifi, time); + u32 mine_util_percent = TO_PERCENT(mine_util, time); + u32 non_wifi_util_percent = TO_PERCENT(non_wifi_util, time); + u32 not_mine_util_percent = TO_PERCENT(not_mine_util, time); + u32 not_mine_busy_util_percent = + (not_mine_time > 0) ? TO_PERCENT(not_mine_util, not_mine_time) : 0; + + cca_db->edca_busy = edca_busy; + cca_db->tx_mine = tx_mine; + cca_db->rx_mine = rx_mine; + + if (sample_cnt > 0) { + cl_cca_update_counters(hist_db->air_util, air_util_percent); + cl_cca_update_counters(hist_db->wifi_air_util, wifi_air_util_percent); + cl_cca_update_counters(hist_db->not_mine_rx_wifi, not_mine_rx_wifi_percent); + cl_cca_update_counters(hist_db->mine, mine_util_percent); + cl_cca_update_counters(hist_db->non_wifi_util, non_wifi_util_percent); + cl_cca_update_counters(hist_db->not_mine, not_mine_util_percent); + cl_cca_update_counters(hist_db->not_mine_busy, not_mine_busy_util_percent); + + hist_db->sample_cnt--; + + /* Stop sampling */ + if (hist_db->sample_cnt == 0) { + SET_CCA_OPT(0, cca_db->cca_opt, CCA_OPT_REC_HIST); + pr_debug("Record is done\n"); + } + } + + if (cca_db->cca_opt & CCA_OPT_UTIL) + pr_debug("air_util = %u%%, wifi_air_util = %u%%, not_mine_rx_wifi = %u%%, " + "mine_util = %u%%, non_wifi_util = %u%%, not_mine_util = %u%%, " + "not_mine_busy_util = %u%%\n", + air_util_percent, wifi_air_util_percent, not_mine_rx_wifi, + mine_util_percent, non_wifi_util_percent, not_mine_util_percent, + not_mine_busy_util_percent); +} + +static void cl_cca_print_tx_rx_mine(struct cl_hw *cl_hw, unsigned long time) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + + u32 tx_mine = mac_hw_tx_mine_busy_get(cl_hw); + u32 rx_mine = mac_hw_rx_mine_busy_get(cl_hw); + + u32 diff_tx_mine = tx_mine - cca_db->print_tx_mine; + u32 diff_rx_mine = rx_mine - cca_db->print_rx_mine; + + cca_db->print_tx_mine = tx_mine; + cca_db->print_rx_mine = rx_mine; + + pr_debug("tx_mine = %u (%lu%%), rx_mine = %u (%lu%%)\n", + diff_tx_mine, + TO_PERCENT(diff_tx_mine, time), + diff_rx_mine, + TO_PERCENT(diff_rx_mine, time)); +} + +static void cl_cca_edca(struct cl_hw *cl_hw, unsigned long time) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + bool is_24g = cl_band_is_24g(cl_hw); + bool sec80 = !is_24g; + + u32 new_edca_busy = mac_hw_edca_cca_busy_get(cl_hw); + u32 new_edca_busy_sec20 = mac_hw_add_cca_busy_sec_20_get(cl_hw); + u32 new_edca_busy_sec40 = is_24g ? 0 : mac_hw_add_cca_busy_sec_40_get(cl_hw); + u32 new_edca_busy_sec80 = sec80 ? mac_hw_add_cca_busy_sec_80_get(cl_hw) : 0; + + u32 diff_edca_busy = new_edca_busy - cca_db->edca_busy; + u32 diff_edca_busy_sec20 = new_edca_busy_sec20 - cca_db->edca_busy_sec20; + u32 diff_edca_busy_sec40 = new_edca_busy_sec40 - cca_db->edca_busy_sec40; + u32 diff_edca_busy_sec80 = new_edca_busy_sec80 - cca_db->edca_busy_sec80; + + u32 percent_edca_busy = TO_PERCENT(diff_edca_busy, time); + u32 percent_edca_busy_sec20 = TO_PERCENT(diff_edca_busy_sec20, time); + u32 percent_edca_busy_sec40 = TO_PERCENT(diff_edca_busy_sec40, time); + u32 percent_edca_busy_sec80 = TO_PERCENT(diff_edca_busy_sec80, time); + + cca_db->edca_busy = new_edca_busy; + cca_db->edca_busy_sec20 = new_edca_busy_sec20; + cca_db->edca_busy_sec40 = new_edca_busy_sec40; + cca_db->edca_busy_sec80 = new_edca_busy_sec80; + + pr_debug("edca_busy: primary = %u (%u%%), sec20 = %u (%u%%), " + "sec40 = %u (%u%%), sec80 = %u (%u%%)\n", + diff_edca_busy, percent_edca_busy, + diff_edca_busy_sec20, percent_edca_busy_sec20, + diff_edca_busy_sec40, percent_edca_busy_sec40, + diff_edca_busy_sec80, percent_edca_busy_sec80); +} + +static void cl_cca_print_edca_nav(struct cl_hw *cl_hw, unsigned long time) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + + u32 new_cca_busy_nav = mac_hw_edca_nav_busy_get(cl_hw); + u32 new_cca_intra_bss_nav = mac_hw_intra_bss_nav_busy_get(cl_hw); + u32 new_cca_inter_bss_nav = mac_hw_inter_bss_nav_busy_get(cl_hw); + + u32 diff_cca_busy_nav = new_cca_busy_nav - cca_db->cca_busy_nav; + u32 diff_cca_intra_bss_nav = new_cca_intra_bss_nav - cca_db->cca_intra_bss_nav; + u32 diff_cca_inter_bss_nav = new_cca_inter_bss_nav - cca_db->cca_inter_bss_nav; + + u32 percent_cca_busy_nav = TO_PERCENT(diff_cca_busy_nav, time); + u32 percent_cca_intra_bss_nav = TO_PERCENT(diff_cca_intra_bss_nav, time); + u32 percent_cca_inter_bss_nav = TO_PERCENT(diff_cca_inter_bss_nav, time); + + cca_db->cca_busy_nav = new_cca_busy_nav; + cca_db->cca_intra_bss_nav = new_cca_intra_bss_nav; + cca_db->cca_inter_bss_nav = new_cca_inter_bss_nav; + + pr_debug("cca_busy_nav = %u%%, cca_intra_bass_nav = %u%%, cca_inter_bass_nav = %u%%\n", + percent_cca_busy_nav, percent_cca_intra_bss_nav, percent_cca_inter_bss_nav); +} + +static int cl_cca_cli_help(struct cl_hw *cl_hw) +{ + char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + int err = 0; + + if (!buf) + return -ENOMEM; + + snprintf(buf, PAGE_SIZE, + "cca usage:\n" + "-a : Print TX mine and RX mine [0-dis, 1-en]\n" + "-b : Print energy detect registers per20 [0-dis, 1-en]\n" + "-c : Print EDCA registers [0-dis, 1-en]\n" + "-d : Enable/Disable CCA statistics - [0-dis, 0xff-en all]\n" + "-e : Print energy detect registers [0-dis, 1-en]\n" + "-g : Print mid-packet registers [0-dis, 1-en]\n" + "-h : Print histogram [0-reset, 1-print]\n" + "-i : Print NAV busy registers [0-dis, 1-en]\n" + "-m : Print modem-state registers [0-dis, 1-en]\n" + "-n : Set modem-state registers [0-before L-SIG, 1-after L-SIG]\n" + "-r : Record histogram [samples #]\n" + "-s : Print carrier-sense register [0-dis, 1-en]\n" + "-u : Print CCA utility [0-dis, 1-en]\n"); + + err = cl_vendor_reply(cl_hw, buf, strlen(buf)); + kfree(buf); + + return err; +} + +static bool cl_cca_is_hist_empty(struct cl_edca_hist_db *hist_db, u8 cnt) +{ + if (!hist_db->air_util[cnt] && + !hist_db->mine[cnt] && + !hist_db->non_wifi_util[cnt] && + !hist_db->not_mine[cnt] && + !hist_db->not_mine_busy[cnt] && + !hist_db->not_mine_rx_wifi[cnt] && + !hist_db->wifi_air_util[cnt]) + return true; + + return false; +} + +static void cl_cca_print_histogram(struct cl_hw *cl_hw) +{ + struct cl_edca_hist_db *hist_db = &cl_hw->cca_db.edca_hist; + u8 i = 0; + u8 range = 1; + + pr_debug("|---------------------------------------------------------------|\n"); + pr_debug("|Samples|AirUtil|WifiAir|NonWifi|Mine |NotMine|NotMine|NotMine|\n"); + pr_debug("| | |Util |Util | | |Busy |RxWifi |\n"); + pr_debug("|-------+-------+-------+-------+-------+-------+-------+-------|\n"); + + for (i = 0; i < CCA_MAX_SAMPLE; i++) { + if (cl_cca_is_hist_empty(hist_db, i)) + continue; + + if (i > 1) + range = ((i - 1) * SAMPLE_RES) + 1; + + if (i != 0) + pr_debug("|%3u-%-3u| %5u | %5u | %5u | %5u | %5u | %5u | %5u |\n", + range, range + SAMPLE_RES - 1, hist_db->air_util[i], + hist_db->wifi_air_util[i], hist_db->non_wifi_util[i], + hist_db->mine[i], hist_db->not_mine[i], + hist_db->not_mine_busy[i], hist_db->not_mine_rx_wifi[i]); + else + pr_debug("|0 | %5u | %5u | %5u | %5u | %5u | %5u | %5u |\n", + hist_db->air_util[i], hist_db->wifi_air_util[i], + hist_db->non_wifi_util[i], hist_db->mine[i], + hist_db->not_mine[i], hist_db->not_mine_busy[i], + hist_db->not_mine_rx_wifi[i]); + } + + pr_debug("|---------------------------------------------------------------|\n"); +} + +static void cl_cca_opt_update(struct cl_hw *cl_hw, u32 cca_opt_prev) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + u32 cca_opt_new = cca_db->cca_opt; + + if (cca_opt_prev == 0 && cca_opt_new != 0) { + cca_db->time = jiffies_to_usecs(jiffies); + riu_rwnxagccca_1_cca_cnt_clear_setf(cl_hw, 0); + } + + if (((cca_opt_prev & CCA_OPT_TX_RX_MINE) != CCA_OPT_TX_RX_MINE) && + (cca_opt_new & CCA_OPT_TX_RX_MINE)) { + cca_db->print_tx_mine = mac_hw_tx_mine_busy_get(cl_hw); + cca_db->print_rx_mine = mac_hw_rx_mine_busy_get(cl_hw); + } + + if (((cca_opt_prev & CCA_OPT_UTIL) != CCA_OPT_UTIL) && + (cca_opt_new & CCA_OPT_UTIL)) { + cca_db->tx_mine = mac_hw_tx_mine_busy_get(cl_hw); + cca_db->rx_mine = mac_hw_rx_mine_busy_get(cl_hw); + cca_db->edca_busy = mac_hw_edca_cca_busy_get(cl_hw); + } +} + +int cl_cca_cli(struct cl_hw *cl_hw, struct cli_params *cli_params) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + u32 cca_opt_prev = cca_db->cca_opt; + u32 expected_params = -1; + u32 param = (u32)cli_params->params[0]; + bool print_tx_rx_mine = false; + bool print_energy_band = false; + bool print_edca = false; + bool print_all = false; + bool print_energy = false; + bool print_mp = false; + bool print_histogram = false; + bool print_nav_edca = false; + bool print_mdm = false; + bool set_mdm = false; + bool record_histogram = false; + bool print_cs = false; + bool print_util = false; + + switch (cli_params->option) { + case 'a': + print_tx_rx_mine = true; + expected_params = 1; + break; + case 'b': + print_energy_band = true; + expected_params = 1; + break; + case 'c': + print_edca = true; + expected_params = 1; + break; + case 'd': + print_all = true; + expected_params = 1; + break; + case 'e': + print_energy = true; + expected_params = 1; + break; + case 'g': + print_mp = true; + expected_params = 1; + break; + case 'h': + print_histogram = true; + expected_params = 1; + break; + case 'i': + print_nav_edca = true; + expected_params = 1; + break; + case 'm': + print_mdm = true; + expected_params = 1; + break; + case 'n': + set_mdm = true; + expected_params = 1; + break; + case 'r': + record_histogram = true; + expected_params = 1; + break; + case 's': + print_cs = true; + expected_params = 1; + break; + case 'u': + print_util = true; + expected_params = 1; + break; + case '?': + return cl_cca_cli_help(cl_hw); + default: + cl_dbg_err(cl_hw, "Illegal option (%c) - try '?' for help\n", cli_params->option); + goto out_err; + } + + if (expected_params != cli_params->num_params) { + cl_dbg_err(cl_hw, "Wrong number of arguments (expected %u) (actual %u)\n", + expected_params, cli_params->num_params); + goto out_err; + } + + if (print_tx_rx_mine) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_TX_RX_MINE); + + if (print_energy_band) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_CNT_ENERGY_BAND); + + if (print_all) + cca_db->cca_opt = param; + + if (print_edca) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_EDCA); + + if (print_energy) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_CNT_ENERGY); + + if (print_mp) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_CNT_MP); + + if (print_histogram) { + if (param) + cl_cca_print_histogram(cl_hw); + else + memset(&cca_db->edca_hist, 0, sizeof(struct cl_edca_hist_db)); + + return 0; + } + + if (print_nav_edca) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_EDCA_NAV); + + if (print_mdm) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_CNT_MDM_STATE); + + if (set_mdm) { + u16 psel = param ? MDM_AFTER_L_SIG : MDM_BEFORE_L_SIG; + + pr_debug("Modem state register set to : %s L-SIG detection!\n", + param ? "after" : "before"); + riu_rwnxagcccastate_0_rxstatecca_20_psel_setf(cl_hw, psel); + + return 0; + } + + if (record_histogram) { + pr_debug("%s recording samples\n", param ? "Start" : "Stop"); + cca_db->edca_hist.sample_cnt = param; + SET_CCA_OPT(!!param, cca_db->cca_opt, CCA_OPT_REC_HIST); + } + + if (print_cs) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_CNT_CS); + + if (print_util) + SET_CCA_OPT(param, cca_db->cca_opt, CCA_OPT_UTIL); + + cl_cca_opt_update(cl_hw, cca_opt_prev); + return 0; + +out_err: + return -EIO; +} + +void cl_cca_maintenance(struct cl_hw *cl_hw) +{ + struct cl_cca_db *cca_db = &cl_hw->cca_db; + unsigned long time = jiffies_to_usecs(jiffies); + unsigned long diff_time = time - cca_db->time; + u32 cca_opt = cca_db->cca_opt; + + cca_db->time = time; + + if (!diff_time || !cca_opt) + return; + + if (cca_opt & CCA_OPT_CNT_CS) + cl_cca_print_cs(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_CNT_MDM_STATE) + cl_cca_print_mdm_state(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_CNT_MP) + cl_cca_print_mp(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_CNT_ENERGY) + cl_cca_print_energy(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_CNT_ENERGY_BAND) + cl_cca_print_energy_band(cl_hw, diff_time); + + if (cca_opt & (CCA_OPT_UTIL | CCA_OPT_REC_HIST)) + cl_cca_print_utility(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_TX_RX_MINE) + cl_cca_print_tx_rx_mine(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_EDCA) + cl_cca_edca(cl_hw, diff_time); + + if (cca_opt & CCA_OPT_EDCA_NAV) + cl_cca_print_edca_nav(cl_hw, diff_time); + + /* Rest CCA counters */ + riu_rwnxagccca_1_cca_cnt_clear_setf(cl_hw, 0); +} +