From patchwork Mon Sep 20 16:11:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?SsOpcsO0bWUgUG91aWxsZXI=?= X-Patchwork-Id: 12505847 X-Patchwork-Delegate: kvalo@adurom.com 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=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,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=unavailable 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 AE5FFC433F5 for ; Mon, 20 Sep 2021 16:13:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8C2CB60F58 for ; Mon, 20 Sep 2021 16:13:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243167AbhITQOx (ORCPT ); Mon, 20 Sep 2021 12:14:53 -0400 Received: from mail-dm6nam11on2076.outbound.protection.outlook.com ([40.107.223.76]:21537 "EHLO NAM11-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242950AbhITQOK (ORCPT ); Mon, 20 Sep 2021 12:14:10 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KVg8mZlDXS0nhPCEQBZQCFYR4z3YqkCl1D1ITi/BCdRW60KKqbeet2BnB6/VbmPjBERd1OHbWNmYsjNM3vgQxSfu9LPPZ8CHlDFO2YUZEbmRk0kc3JPkjCD999BrDZSUiuSJ37s8v841gJ3uiC93rMvkYcI0FpmqOpEwrDqp//h5X9/G57WDoV0HP5i5SFe92oEe3dd/vusB887YD/CAXIKe/96+zjB5pK6P++ZcmqiC4pAUn3WEgSFaDpjCyY7CVsZIh7SL5xXbt+pCMKad5nF+1h6Owza9exstFusxU85Z7QyI2vsrw4lVJzJyHyiaAFD9v98Hku/wI41C9Wpnig== 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; bh=JoF8rd7pOcuK4trIqHcnLJlpHT7+vJdshQrnJJlm26k=; b=VoRbxskgHqOl5dXTWBgYx69B+RjP9UuA2qQPkCh3sO9Q/1Rwwz0ziRWQZ0JGhUKyXQHbzACwQBzxeTXjZXzJSlJKtgmts+KcGqDDssFH8I8StQy3YSN1x7+12iE6L1VGERPwemoZdITWIFyY/JpCUs0khk7v7CSXqJ6xhrPbjx5YgfZy5AFmGh1NUWXK4GhgMqsy9xZMwLCLeeptmZZrvgWD/dYHJSc9p6+0PwGBTypX0kyQc4CvfXasDDJtZP9eOiLp+si5MLS9F4h8FK4/2h4rexdTTP2CoazVPvgVV7osfYb3xzz9v5DFDMwviUBCDPkxbNztu9l3MHKkkHvPtw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=silabs.com; dmarc=pass action=none header.from=silabs.com; dkim=pass header.d=silabs.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=silabs.onmicrosoft.com; s=selector2-silabs-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=JoF8rd7pOcuK4trIqHcnLJlpHT7+vJdshQrnJJlm26k=; b=QnuStiXniHQDmFfmSbPqBgg5zGSTc+yMLaDN9wsFJNb7Ikh09Mvb3FD+okZasUWxOqrx4jg59OIAz3+oHocIcL4S0PsfBw2Ecv+8hL7n7PTILterXKdPoB60vaPmirR+zq+o1BobStCylwE45EHbzq9QxPJuhD44XeUezb4SJz8= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=none action=none header.from=silabs.com; Received: from SN6PR11MB2718.namprd11.prod.outlook.com (2603:10b6:805:63::18) by SN6PR11MB2557.namprd11.prod.outlook.com (2603:10b6:805:56::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.14; Mon, 20 Sep 2021 16:12:25 +0000 Received: from SN6PR11MB2718.namprd11.prod.outlook.com ([fe80::7050:a0a:415:2ccd]) by SN6PR11MB2718.namprd11.prod.outlook.com ([fe80::7050:a0a:415:2ccd%7]) with mapi id 15.20.4523.018; Mon, 20 Sep 2021 16:12:25 +0000 From: Jerome Pouiller To: linux-wireless@vger.kernel.org, netdev@vger.kernel.org, Kalle Valo Cc: devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , "David S . Miller" , devicetree@vger.kernel.org, Rob Herring , linux-mmc@vger.kernel.org, =?utf-8?q?Pali?= =?utf-8?q?_Roh=C3=A1r?= , Ulf Hansson , =?utf-8?b?SsOpcsO0bWUgUG91aWxsZXI=?= Subject: [PATCH v7 13/24] wfx: add hif_tx*.c/hif_tx*.h Date: Mon, 20 Sep 2021 18:11:25 +0200 Message-Id: <20210920161136.2398632-14-Jerome.Pouiller@silabs.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210920161136.2398632-1-Jerome.Pouiller@silabs.com> References: <20210920161136.2398632-1-Jerome.Pouiller@silabs.com> X-ClientProxiedBy: SA0PR11CA0064.namprd11.prod.outlook.com (2603:10b6:806:d2::9) To SN6PR11MB2718.namprd11.prod.outlook.com (2603:10b6:805:63::18) MIME-Version: 1.0 Received: from pc-42.silabs.com (2a01:e34:ecb5:66a0:9876:e1d7:65be:d294) by SA0PR11CA0064.namprd11.prod.outlook.com (2603:10b6:806:d2::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.14 via Frontend Transport; Mon, 20 Sep 2021 16:12:23 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a9e9a57a-6566-40c8-fbcd-08d97c516f60 X-MS-TrafficTypeDiagnostic: SN6PR11MB2557: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:21; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: kEW7pkqDpFgK9wqfkt1rBtnmckSe/noz9WUcPi7EYwOJJ7KOzeW/ISJQsOraMSZNr7+kmVPcV25LhNmZjZzH0n+aX6topMl6FfF/s2kA5KjCYINi9ZKxoHc9OXYyo0ZQ7xMFzaHc53ZhXSvHTw3fkdSUYttaUW1bzW/WmBc7Hn0Fo1HBH548hfh/8PIu3+jtFYenjV6xH2bhHa/hYbSFCc5UiwvRKA41bbfq6mbpf0tENL6V0DF8mrRca5kAWdiKReRfpEBuYg9QdzUfJzMOFUJ5vVumkPbcslJ8gM/mIhRTiRAuLxJKyigs5iLrcTNFD9/I1gAJK6xlIKVI3DT3BIPHmACtNXHUWvcBFXqfjtu36uTI9OMAPcaRN1RD50p1BfZDKGr9vw+XcWWBFQCB8Gmpp2we+E/MsPzqtyVuVCmGyFSvf4CAThp6qhNYohsZ8cG58XcQ7L0ame1/r7AbStQojieHYIb0Qd6kSv/sDWgQqqKwiNJx3GF65jGPnaI7v1ksZkToMt8q/Ov0S06vMbEmhtaZyBTVRvr6/TDR59IAoM3mveCeF3H2XoNQMBCFSiLx3U1VaXD9bSWNdkVykn9/WBdxXWKMK/WqDj7ricoGZ2EOyvDj3wm4v6qsNhQcq9ffEJPwO05AexKKQWYkAQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SN6PR11MB2718.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(39850400004)(396003)(136003)(346002)(366004)(376002)(2906002)(30864003)(1076003)(8936002)(54906003)(38100700002)(86362001)(6486002)(36756003)(66574015)(478600001)(5660300002)(7416002)(6916009)(186003)(66476007)(2616005)(7696005)(8676002)(52116002)(66556008)(66946007)(4326008)(316002)(107886003)(83380400001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: imHCePSTQXDHIDVVv8LXkNJFvzXS7NIofseugW+kW/ZAbUb0hC4Tw2lXM6pOb4HJU8sYCcKBva1SFc7GTdao/MzsufFRg0Zck03wCiXTJ4lPjsO3CkSD7xYRhUrbbcWTOYC1f5J+kS7AEMTb1aEVLwodiV+4InvNszYBl6d8MNfJZRUezX3zAO2tozNDavb3l+ITEtGTZopv5s4c4B30JxGTYvI68tBLfE//1D0aI01iRhzoI0G1m1AQOwOeQj2N6dtaUfIC5VLkuw1iq/APOlgquvWb+wWfyciyBrgxGc/YqMEQ8FyQ+4ecy+Zd/1m4bFnm1uN01egd0wjby4Lo3DFkrNQlhF50s3ai9c2wsVEa2Xd847RqE0SZtvpqFOwAlRrW4iQchezgQCbEtfd9BvRe1khoKBMDSkJ7IaNIvzVjLsJs3Tm0Vp2c6VXIuSppvr6VYimLS0E1J2BZ/7NtMrBe6IC4qCmBGuXpsffDqUs/GJYJEXUzFgiB/fUtmW+58IygzdEJPp4fE8m6Oyq6nE97KD3nYaKMMgOJAvG5IacreeoZA3n4Vokki+DHgk4QUSxvsZhVERdOP2wuZLy5hzGYbISFY3TAXLYbW+N9e17kR7jWPnd6RB0jVqZs90weLIeILmah2+siHv4DLH5FN9FxRAFa5l7Whm3ILpMMH4x6/iwvaMzzYzMu5l2tKPUyzQUlG1y8s9wNjW4UUMjahVYRF11OhPGY9WBajrcYP2NB+ZOBoU4HPyco0VS62BFIa1VCL6mUy+Uha99R7MMZjtTK7+A5wbnwKOqd/A7el6vzPdG9W9XzDOmIy8D/S6kk X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: a9e9a57a-6566-40c8-fbcd-08d97c516f60 X-MS-Exchange-CrossTenant-AuthSource: SN6PR11MB2718.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Sep 2021 16:12:25.6205 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 54dbd822-5231-4b20-944d-6f4abcd541fb X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: AK3IpymSuJrKvrrrhzU9sa3HvjdtQ0Ow0iFOOv7YOUFgQET0EPS21HMhh+E0Lxrrp8WB9ystGobGJGClxC67Vg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB2557 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Jérôme Pouiller Signed-off-by: Jérôme Pouiller --- drivers/net/wireless/silabs/wfx/hif_tx.c | 514 +++++++++++++++++++ drivers/net/wireless/silabs/wfx/hif_tx.h | 60 +++ drivers/net/wireless/silabs/wfx/hif_tx_mib.c | 324 ++++++++++++ drivers/net/wireless/silabs/wfx/hif_tx_mib.h | 49 ++ 4 files changed, 947 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx.c create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx.h create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx_mib.c create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx_mib.h diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c new file mode 100644 index 000000000000..d39366c171ba --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_tx.c @@ -0,0 +1,514 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Implementation of the host-to-chip commands (aka request/confirmation) of the + * hardware API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include + +#include "hif_tx.h" +#include "wfx.h" +#include "bh.h" +#include "hwio.h" +#include "debug.h" +#include "sta.h" + +void wfx_init_hif_cmd(struct wfx_hif_cmd *hif_cmd) +{ + init_completion(&hif_cmd->ready); + init_completion(&hif_cmd->done); + mutex_init(&hif_cmd->lock); +} + +static void wfx_fill_header(struct hif_msg *hif, int if_id, + unsigned int cmd, size_t size) +{ + if (if_id == -1) + if_id = 2; + + WARN(cmd > 0x3f, "invalid hardware command %#.2x", cmd); + WARN(size > 0xFFF, "requested buffer is too large: %zu bytes", size); + WARN(if_id > 0x3, "invalid interface ID %d", if_id); + + hif->len = cpu_to_le16(size + 4); + hif->id = cmd; + hif->interface = if_id; +} + +static void *wfx_alloc_hif(size_t body_len, struct hif_msg **hif) +{ + *hif = kzalloc(sizeof(struct hif_msg) + body_len, GFP_KERNEL); + if (*hif) + return (*hif)->body; + else + return NULL; +} + +int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, + void *reply, size_t reply_len, bool no_reply) +{ + const char *mib_name = ""; + const char *mib_sep = ""; + int cmd = request->id; + int vif = request->interface; + int ret; + + /* Do not wait for any reply if chip is frozen */ + if (wdev->chip_frozen) + return -ETIMEDOUT; + + mutex_lock(&wdev->hif_cmd.lock); + WARN(wdev->hif_cmd.buf_send, "data locking error"); + + /* Note: call to complete() below has an implicit memory barrier that + * hopefully protect buf_send + */ + wdev->hif_cmd.buf_send = request; + wdev->hif_cmd.buf_recv = reply; + wdev->hif_cmd.len_recv = reply_len; + complete(&wdev->hif_cmd.ready); + + wfx_bh_request_tx(wdev); + + if (no_reply) { + /* Chip won't reply. Give enough time to the wq to send the + * buffer. + */ + msleep(100); + wdev->hif_cmd.buf_send = NULL; + mutex_unlock(&wdev->hif_cmd.lock); + return 0; + } + + if (wdev->poll_irq) + wfx_bh_poll_irq(wdev); + + ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 1 * HZ); + if (!ret) { + dev_err(wdev->dev, "chip is abnormally long to answer\n"); + reinit_completion(&wdev->hif_cmd.ready); + ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 3 * HZ); + } + if (!ret) { + dev_err(wdev->dev, "chip did not answer\n"); + wfx_pending_dump_old_frames(wdev, 3000); + wdev->chip_frozen = true; + reinit_completion(&wdev->hif_cmd.done); + ret = -ETIMEDOUT; + } else { + ret = wdev->hif_cmd.ret; + } + + wdev->hif_cmd.buf_send = NULL; + mutex_unlock(&wdev->hif_cmd.lock); + + if (ret && + (cmd == HIF_REQ_ID_READ_MIB || cmd == HIF_REQ_ID_WRITE_MIB)) { + mib_name = get_mib_name(((u16 *)request)[2]); + mib_sep = "/"; + } + if (ret < 0) + dev_err(wdev->dev, "hardware request %s%s%s (%#.2x) on vif %d returned error %d\n", + get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret); + if (ret > 0) + dev_warn(wdev->dev, "hardware request %s%s%s (%#.2x) on vif %d returned status %d\n", + get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret); + + return ret; +} + +/* This function is special. After HIF_REQ_ID_SHUT_DOWN, chip won't reply to any + * request anymore. Obviously, only call this function during device unregister. + */ +int hif_shutdown(struct wfx_dev *wdev) +{ + int ret; + struct hif_msg *hif; + + wfx_alloc_hif(0, &hif); + if (!hif) + return -ENOMEM; + wfx_fill_header(hif, -1, HIF_REQ_ID_SHUT_DOWN, 0); + ret = wfx_cmd_send(wdev, hif, NULL, 0, true); + if (wdev->pdata.gpio_wakeup) + gpiod_set_value(wdev->pdata.gpio_wakeup, 0); + else + control_reg_write(wdev, 0); + kfree(hif); + return ret; +} + +int hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len) +{ + int ret; + size_t buf_len = sizeof(struct hif_req_configuration) + len; + struct hif_msg *hif; + struct hif_req_configuration *body = wfx_alloc_hif(buf_len, &hif); + + if (!hif) + return -ENOMEM; + body->length = cpu_to_le16(len); + memcpy(body->pds_data, conf, len); + wfx_fill_header(hif, -1, HIF_REQ_ID_CONFIGURATION, buf_len); + ret = wfx_cmd_send(wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_reset(struct wfx_vif *wvif, bool reset_stat) +{ + int ret; + struct hif_msg *hif; + struct hif_req_reset *body = wfx_alloc_hif(sizeof(*body), &hif); + + if (!hif) + return -ENOMEM; + body->reset_stat = reset_stat; + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_RESET, sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, + void *val, size_t val_len) +{ + int ret; + struct hif_msg *hif; + int buf_len = sizeof(struct hif_cnf_read_mib) + val_len; + struct hif_req_read_mib *body = wfx_alloc_hif(sizeof(*body), &hif); + struct hif_cnf_read_mib *reply = kmalloc(buf_len, GFP_KERNEL); + + if (!body || !reply) { + ret = -ENOMEM; + goto out; + } + body->mib_id = cpu_to_le16(mib_id); + wfx_fill_header(hif, vif_id, HIF_REQ_ID_READ_MIB, sizeof(*body)); + ret = wfx_cmd_send(wdev, hif, reply, buf_len, false); + + if (!ret && mib_id != le16_to_cpu(reply->mib_id)) { + dev_warn(wdev->dev, "%s: confirmation mismatch request\n", + __func__); + ret = -EIO; + } + if (ret == -ENOMEM) + dev_err(wdev->dev, "buffer is too small to receive %s (%zu < %d)\n", + get_mib_name(mib_id), val_len, + le16_to_cpu(reply->length)); + if (!ret) + memcpy(val, &reply->mib_data, le16_to_cpu(reply->length)); + else + memset(val, 0xFF, val_len); +out: + kfree(hif); + kfree(reply); + return ret; +} + +int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, + void *val, size_t val_len) +{ + int ret; + struct hif_msg *hif; + int buf_len = sizeof(struct hif_req_write_mib) + val_len; + struct hif_req_write_mib *body = wfx_alloc_hif(buf_len, &hif); + + if (!hif) + return -ENOMEM; + body->mib_id = cpu_to_le16(mib_id); + body->length = cpu_to_le16(val_len); + memcpy(&body->mib_data, val, val_len); + wfx_fill_header(hif, vif_id, HIF_REQ_ID_WRITE_MIB, buf_len); + ret = wfx_cmd_send(wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req, + int chan_start_idx, int chan_num) +{ + int ret, i; + struct hif_msg *hif; + size_t buf_len = + sizeof(struct hif_req_start_scan_alt) + chan_num * sizeof(u8); + struct hif_req_start_scan_alt *body = wfx_alloc_hif(buf_len, &hif); + + WARN(chan_num > HIF_API_MAX_NB_CHANNELS, "invalid params"); + WARN(req->n_ssids > HIF_API_MAX_NB_SSIDS, "invalid params"); + + if (!hif) + return -ENOMEM; + for (i = 0; i < req->n_ssids; i++) { + memcpy(body->ssid_def[i].ssid, req->ssids[i].ssid, + IEEE80211_MAX_SSID_LEN); + body->ssid_def[i].ssid_length = + cpu_to_le32(req->ssids[i].ssid_len); + } + body->num_of_ssids = HIF_API_MAX_NB_SSIDS; + body->maintain_current_bss = 1; + body->disallow_ps = 1; + body->tx_power_level = + cpu_to_le32(req->channels[chan_start_idx]->max_power); + body->num_of_channels = chan_num; + for (i = 0; i < chan_num; i++) + body->channel_list[i] = + req->channels[i + chan_start_idx]->hw_value; + if (req->no_cck) + body->max_transmit_rate = API_RATE_INDEX_G_6MBPS; + else + body->max_transmit_rate = API_RATE_INDEX_B_1MBPS; + if (req->channels[chan_start_idx]->flags & IEEE80211_CHAN_NO_IR) { + body->min_channel_time = cpu_to_le32(50); + body->max_channel_time = cpu_to_le32(150); + } else { + body->min_channel_time = cpu_to_le32(10); + body->max_channel_time = cpu_to_le32(50); + body->num_of_probe_requests = 2; + body->probe_delay = 100; + } + + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_stop_scan(struct wfx_vif *wvif) +{ + int ret; + struct hif_msg *hif; + /* body associated to HIF_REQ_ID_STOP_SCAN is empty */ + wfx_alloc_hif(0, &hif); + + if (!hif) + return -ENOMEM; + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_STOP_SCAN, 0); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + struct ieee80211_channel *channel, const u8 *ssid, int ssidlen) +{ + int ret; + struct hif_msg *hif; + struct hif_req_join *body = wfx_alloc_hif(sizeof(*body), &hif); + + WARN_ON(!conf->beacon_int); + WARN_ON(!conf->basic_rates); + WARN_ON(!channel); + WARN_ON(sizeof(body->ssid) < ssidlen); + WARN(!conf->ibss_joined && !ssidlen, "joining an unknown BSS"); + if (!hif) + return -ENOMEM; + body->infrastructure_bss_mode = !conf->ibss_joined; + body->short_preamble = conf->use_short_preamble; + body->probe_for_join = !(channel->flags & IEEE80211_CHAN_NO_IR); + body->channel_number = channel->hw_value; + body->beacon_interval = cpu_to_le32(conf->beacon_int); + body->basic_rate_set = + cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); + memcpy(body->bssid, conf->bssid, sizeof(body->bssid)); + if (ssid) { + body->ssid_length = cpu_to_le32(ssidlen); + memcpy(body->ssid, ssid, ssidlen); + } + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_JOIN, sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_set_bss_params(struct wfx_vif *wvif, int aid, int beacon_lost_count) +{ + int ret; + struct hif_msg *hif; + struct hif_req_set_bss_params *body = + wfx_alloc_hif(sizeof(*body), &hif); + + if (!hif) + return -ENOMEM; + body->aid = cpu_to_le16(aid); + body->beacon_lost_count = beacon_lost_count; + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_BSS_PARAMS, + sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg) +{ + int ret; + struct hif_msg *hif; + /* FIXME: only send necessary bits */ + struct hif_req_add_key *body = wfx_alloc_hif(sizeof(*body), &hif); + + if (!hif) + return -ENOMEM; + /* FIXME: swap bytes as necessary in body */ + memcpy(body, arg, sizeof(*body)); + if (wfx_api_older_than(wdev, 1, 5)) + /* Legacy firmwares expect that add_key to be sent on right + * interface. + */ + wfx_fill_header(hif, arg->int_id, HIF_REQ_ID_ADD_KEY, + sizeof(*body)); + else + wfx_fill_header(hif, -1, HIF_REQ_ID_ADD_KEY, sizeof(*body)); + ret = wfx_cmd_send(wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_remove_key(struct wfx_dev *wdev, int idx) +{ + int ret; + struct hif_msg *hif; + struct hif_req_remove_key *body = wfx_alloc_hif(sizeof(*body), &hif); + + if (!hif) + return -ENOMEM; + body->entry_index = idx; + wfx_fill_header(hif, -1, HIF_REQ_ID_REMOVE_KEY, sizeof(*body)); + ret = wfx_cmd_send(wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue, + const struct ieee80211_tx_queue_params *arg) +{ + int ret; + struct hif_msg *hif; + struct hif_req_edca_queue_params *body = wfx_alloc_hif(sizeof(*body), + &hif); + + if (!body) + return -ENOMEM; + + WARN_ON(arg->aifs > 255); + if (!hif) + return -ENOMEM; + body->aifsn = arg->aifs; + body->cw_min = cpu_to_le16(arg->cw_min); + body->cw_max = cpu_to_le16(arg->cw_max); + body->tx_op_limit = cpu_to_le16(arg->txop * USEC_PER_TXOP); + body->queue_id = 3 - queue; + /* API 2.0 has changed queue IDs values */ + if (wfx_api_older_than(wvif->wdev, 2, 0) && queue == IEEE80211_AC_BE) + body->queue_id = HIF_QUEUE_ID_BACKGROUND; + if (wfx_api_older_than(wvif->wdev, 2, 0) && queue == IEEE80211_AC_BK) + body->queue_id = HIF_QUEUE_ID_BESTEFFORT; + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_EDCA_QUEUE_PARAMS, + sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout) +{ + int ret; + struct hif_msg *hif; + struct hif_req_set_pm_mode *body = wfx_alloc_hif(sizeof(*body), &hif); + + if (!body) + return -ENOMEM; + + if (!hif) + return -ENOMEM; + if (ps) { + body->enter_psm = 1; + /* Firmware does not support more than 128ms */ + body->fast_psm_idle_period = min(dynamic_ps_timeout * 2, 255); + if (body->fast_psm_idle_period) + body->fast_psm = 1; + } + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_PM_MODE, sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + const struct ieee80211_channel *channel) +{ + int ret; + struct hif_msg *hif; + struct hif_req_start *body = wfx_alloc_hif(sizeof(*body), &hif); + + WARN_ON(!conf->beacon_int); + if (!hif) + return -ENOMEM; + body->dtim_period = conf->dtim_period; + body->short_preamble = conf->use_short_preamble; + body->channel_number = channel->hw_value; + body->beacon_interval = cpu_to_le32(conf->beacon_int); + body->basic_rate_set = + cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); + body->ssid_length = conf->ssid_len; + memcpy(body->ssid, conf->ssid, conf->ssid_len); + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START, sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_beacon_transmit(struct wfx_vif *wvif, bool enable) +{ + int ret; + struct hif_msg *hif; + struct hif_req_beacon_transmit *body = wfx_alloc_hif(sizeof(*body), + &hif); + + if (!hif) + return -ENOMEM; + body->enable_beaconing = enable ? 1 : 0; + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_BEACON_TRANSMIT, + sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_map_link(struct wfx_vif *wvif, bool unmap, u8 *mac_addr, int sta_id, bool mfp) +{ + int ret; + struct hif_msg *hif; + struct hif_req_map_link *body = wfx_alloc_hif(sizeof(*body), &hif); + + if (!hif) + return -ENOMEM; + if (mac_addr) + ether_addr_copy(body->mac_addr, mac_addr); + body->mfpc = mfp ? 1 : 0; + body->unmap = unmap ? 1 : 0; + body->peer_sta_id = sta_id; + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_MAP_LINK, sizeof(*body)); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + +int hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len) +{ + int ret; + struct hif_msg *hif; + int buf_len = sizeof(struct hif_req_update_ie) + ies_len; + struct hif_req_update_ie *body = wfx_alloc_hif(buf_len, &hif); + + if (!hif) + return -ENOMEM; + body->beacon = 1; + body->num_ies = cpu_to_le16(1); + memcpy(body->ie, ies, ies_len); + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_UPDATE_IE, buf_len); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.h b/drivers/net/wireless/silabs/wfx/hif_tx.h new file mode 100644 index 000000000000..e57eabdcfa77 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_tx.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Implementation of the host-to-chip commands (aka request/confirmation) of the + * hardware API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (C) 2010, ST-Ericsson SA + */ +#ifndef WFX_HIF_TX_H +#define WFX_HIF_TX_H + +struct ieee80211_channel; +struct ieee80211_bss_conf; +struct ieee80211_tx_queue_params; +struct cfg80211_scan_request; +struct hif_req_add_key; +struct wfx_dev; +struct wfx_vif; + +struct wfx_hif_cmd { + struct mutex lock; + struct completion ready; + struct completion done; + struct hif_msg *buf_send; + void *buf_recv; + size_t len_recv; + int ret; +}; + +void wfx_init_hif_cmd(struct wfx_hif_cmd *wfx_hif_cmd); +int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, + void *reply, size_t reply_len, bool async); + +int hif_shutdown(struct wfx_dev *wdev); +int hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len); +int hif_reset(struct wfx_vif *wvif, bool reset_stat); +int hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, + void *buf, size_t buf_size); +int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, + void *buf, size_t buf_size); +int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211, + int chan_start, int chan_num); +int hif_stop_scan(struct wfx_vif *wvif); +int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + struct ieee80211_channel *channel, const u8 *ssid, int ssidlen); +int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout); +int hif_set_bss_params(struct wfx_vif *wvif, int aid, int beacon_lost_count); +int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg); +int hif_remove_key(struct wfx_dev *wdev, int idx); +int hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue, + const struct ieee80211_tx_queue_params *arg); +int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + const struct ieee80211_channel *channel); +int hif_beacon_transmit(struct wfx_vif *wvif, bool enable); +int hif_map_link(struct wfx_vif *wvif, + bool unmap, u8 *mac_addr, int sta_id, bool mfp); +int hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len); + +#endif diff --git a/drivers/net/wireless/silabs/wfx/hif_tx_mib.c b/drivers/net/wireless/silabs/wfx/hif_tx_mib.c new file mode 100644 index 000000000000..97e961e6bcf6 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_tx_mib.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Implementation of the host-to-chip MIBs of the hardware API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (C) 2010, ST-Ericsson SA + */ + +#include + +#include "wfx.h" +#include "hif_tx.h" +#include "hif_tx_mib.h" +#include "hif_api_mib.h" + +int hif_set_output_power(struct wfx_vif *wvif, int val) +{ + struct hif_mib_current_tx_power_level arg = { + .power_level = cpu_to_le32(val * 10), + }; + + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_CURRENT_TX_POWER_LEVEL, + &arg, sizeof(arg)); +} + +int hif_set_beacon_wakeup_period(struct wfx_vif *wvif, + unsigned int dtim_interval, + unsigned int listen_interval) +{ + struct hif_mib_beacon_wake_up_period arg = { + .wakeup_period_min = dtim_interval, + .receive_dtim = 0, + .wakeup_period_max = listen_interval, + }; + + if (dtim_interval > 0xFF || listen_interval > 0xFFFF) + return -EINVAL; + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_BEACON_WAKEUP_PERIOD, + &arg, sizeof(arg)); +} + +int hif_set_rcpi_rssi_threshold(struct wfx_vif *wvif, + int rssi_thold, int rssi_hyst) +{ + struct hif_mib_rcpi_rssi_threshold arg = { + .rolling_average_count = 8, + .detection = 1, + }; + + if (!rssi_thold && !rssi_hyst) { + arg.upperthresh = 1; + arg.lowerthresh = 1; + } else { + arg.upper_threshold = rssi_thold + rssi_hyst; + arg.upper_threshold = (arg.upper_threshold + 110) * 2; + arg.lower_threshold = rssi_thold; + arg.lower_threshold = (arg.lower_threshold + 110) * 2; + } + + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_RCPI_RSSI_THRESHOLD, &arg, sizeof(arg)); +} + +int hif_get_counters_table(struct wfx_dev *wdev, int vif_id, + struct hif_mib_extended_count_table *arg) +{ + if (wfx_api_older_than(wdev, 1, 3)) { + /* extended_count_table is wider than count_table */ + memset(arg, 0xFF, sizeof(*arg)); + return hif_read_mib(wdev, vif_id, HIF_MIB_ID_COUNTERS_TABLE, + arg, sizeof(struct hif_mib_count_table)); + } else { + return hif_read_mib(wdev, vif_id, + HIF_MIB_ID_EXTENDED_COUNTERS_TABLE, arg, + sizeof(struct hif_mib_extended_count_table)); + } +} + +int hif_set_macaddr(struct wfx_vif *wvif, u8 *mac) +{ + struct hif_mib_mac_address arg = { }; + + if (mac) + ether_addr_copy(arg.mac_addr, mac); + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_MAC_ADDRESS, + &arg, sizeof(arg)); +} + +int hif_set_rx_filter(struct wfx_vif *wvif, + bool filter_bssid, bool filter_prbreq) +{ + struct hif_mib_rx_filter arg = { }; + + if (filter_bssid) + arg.bssid_filter = 1; + if (!filter_prbreq) + arg.fwd_probe_req = 1; + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_RX_FILTER, + &arg, sizeof(arg)); +} + +int hif_set_beacon_filter_table(struct wfx_vif *wvif, int tbl_len, + const struct hif_ie_table_entry *tbl) +{ + int ret; + struct hif_mib_bcn_filter_table *arg; + int buf_len = struct_size(arg, ie_table, tbl_len); + + arg = kzalloc(buf_len, GFP_KERNEL); + if (!arg) + return -ENOMEM; + arg->num_of_info_elmts = cpu_to_le32(tbl_len); + memcpy(arg->ie_table, tbl, flex_array_size(arg, ie_table, tbl_len)); + ret = hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_BEACON_FILTER_TABLE, arg, buf_len); + kfree(arg); + return ret; +} + +int hif_beacon_filter_control(struct wfx_vif *wvif, + int enable, int beacon_count) +{ + struct hif_mib_bcn_filter_enable arg = { + .enable = cpu_to_le32(enable), + .bcn_count = cpu_to_le32(beacon_count), + }; + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_BEACON_FILTER_ENABLE, + &arg, sizeof(arg)); +} + +int hif_set_operational_mode(struct wfx_dev *wdev, enum hif_op_power_mode mode) +{ + struct hif_mib_gl_operational_power_mode arg = { + .power_mode = mode, + .wup_ind_activation = 1, + }; + + return hif_write_mib(wdev, -1, HIF_MIB_ID_GL_OPERATIONAL_POWER_MODE, + &arg, sizeof(arg)); +} + +int hif_set_template_frame(struct wfx_vif *wvif, struct sk_buff *skb, + u8 frame_type, int init_rate) +{ + struct hif_mib_template_frame *arg; + + WARN(skb->len > HIF_API_MAX_TEMPLATE_FRAME_SIZE, "frame is too big"); + skb_push(skb, 4); + arg = (struct hif_mib_template_frame *)skb->data; + skb_pull(skb, 4); + arg->init_rate = init_rate; + arg->frame_type = frame_type; + arg->frame_length = cpu_to_le16(skb->len); + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_TEMPLATE_FRAME, + arg, sizeof(*arg) + skb->len); +} + +int hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required) +{ + struct hif_mib_protected_mgmt_policy arg = { }; + + WARN(required && !capable, "incoherent arguments"); + if (capable) { + arg.pmf_enable = 1; + arg.host_enc_auth_frames = 1; + } + if (!required) + arg.unpmf_allowed = 1; + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_PROTECTED_MGMT_POLICY, + &arg, sizeof(arg)); +} + +int hif_set_block_ack_policy(struct wfx_vif *wvif, + u8 tx_tid_policy, u8 rx_tid_policy) +{ + struct hif_mib_block_ack_policy arg = { + .block_ack_tx_tid_policy = tx_tid_policy, + .block_ack_rx_tid_policy = rx_tid_policy, + }; + + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BLOCK_ACK_POLICY, + &arg, sizeof(arg)); +} + +int hif_set_association_mode(struct wfx_vif *wvif, int ampdu_density, + bool greenfield, bool short_preamble) +{ + struct hif_mib_set_association_mode arg = { + .preambtype_use = 1, + .mode = 1, + .spacing = 1, + .short_preamble = short_preamble, + .greenfield = greenfield, + .mpdu_start_spacing = ampdu_density, + }; + + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_SET_ASSOCIATION_MODE, &arg, sizeof(arg)); +} + +int hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, + int policy_index, u8 *rates) +{ + struct hif_mib_set_tx_rate_retry_policy *arg; + size_t size = struct_size(arg, tx_rate_retry_policy, 1); + int ret; + + arg = kzalloc(size, GFP_KERNEL); + if (!arg) + return -ENOMEM; + arg->num_tx_rate_policies = 1; + arg->tx_rate_retry_policy[0].policy_index = policy_index; + arg->tx_rate_retry_policy[0].short_retry_count = 255; + arg->tx_rate_retry_policy[0].long_retry_count = 255; + arg->tx_rate_retry_policy[0].first_rate_sel = 1; + arg->tx_rate_retry_policy[0].terminate = 1; + arg->tx_rate_retry_policy[0].count_init = 1; + memcpy(&arg->tx_rate_retry_policy[0].rates, rates, + sizeof(arg->tx_rate_retry_policy[0].rates)); + ret = hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg, size); + kfree(arg); + return ret; +} + +int hif_keep_alive_period(struct wfx_vif *wvif, int period) +{ + struct hif_mib_keep_alive_period arg = { + .keep_alive_period = cpu_to_le16(period), + }; + + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_KEEP_ALIVE_PERIOD, + &arg, sizeof(arg)); +}; + +int hif_set_arp_ipv4_filter(struct wfx_vif *wvif, int idx, __be32 *addr) +{ + struct hif_mib_arp_ip_addr_table arg = { + .condition_idx = idx, + .arp_enable = HIF_ARP_NS_FILTERING_DISABLE, + }; + + if (addr) { + /* Caution: type of addr is __be32 */ + memcpy(arg.ipv4_address, addr, sizeof(arg.ipv4_address)); + arg.arp_enable = HIF_ARP_NS_FILTERING_ENABLE; + } + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE, + &arg, sizeof(arg)); +} + +int hif_use_multi_tx_conf(struct wfx_dev *wdev, bool enable) +{ + struct hif_mib_gl_set_multi_msg arg = { + .enable_multi_tx_conf = enable, + }; + + return hif_write_mib(wdev, -1, HIF_MIB_ID_GL_SET_MULTI_MSG, + &arg, sizeof(arg)); +} + +int hif_set_uapsd_info(struct wfx_vif *wvif, unsigned long val) +{ + struct hif_mib_set_uapsd_information arg = { }; + + if (val & BIT(IEEE80211_AC_VO)) + arg.trig_voice = 1; + if (val & BIT(IEEE80211_AC_VI)) + arg.trig_video = 1; + if (val & BIT(IEEE80211_AC_BE)) + arg.trig_be = 1; + if (val & BIT(IEEE80211_AC_BK)) + arg.trig_bckgrnd = 1; + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_SET_UAPSD_INFORMATION, + &arg, sizeof(arg)); +} + +int hif_erp_use_protection(struct wfx_vif *wvif, bool enable) +{ + struct hif_mib_non_erp_protection arg = { + .use_cts_to_self = enable, + }; + + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_NON_ERP_PROTECTION, &arg, sizeof(arg)); +} + +int hif_slot_time(struct wfx_vif *wvif, int val) +{ + struct hif_mib_slot_time arg = { + .slot_time = cpu_to_le32(val), + }; + + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SLOT_TIME, + &arg, sizeof(arg)); +} + +int hif_wep_default_key_id(struct wfx_vif *wvif, int val) +{ + struct hif_mib_wep_default_key_id arg = { + .wep_default_key_id = val, + }; + + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID, + &arg, sizeof(arg)); +} + +int hif_rts_threshold(struct wfx_vif *wvif, int val) +{ + struct hif_mib_dot11_rts_threshold arg = { + .threshold = cpu_to_le32(val >= 0 ? val : 0xFFFF), + }; + + return hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_DOT11_RTS_THRESHOLD, &arg, sizeof(arg)); +} diff --git a/drivers/net/wireless/silabs/wfx/hif_tx_mib.h b/drivers/net/wireless/silabs/wfx/hif_tx_mib.h new file mode 100644 index 000000000000..2a3b84868ee4 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_tx_mib.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Implementation of the host-to-chip MIBs of the hardware API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (C) 2010, ST-Ericsson SA + */ +#ifndef WFX_HIF_TX_MIB_H +#define WFX_HIF_TX_MIB_H + +struct wfx_vif; +struct sk_buff; + +int hif_set_output_power(struct wfx_vif *wvif, int val); +int hif_set_beacon_wakeup_period(struct wfx_vif *wvif, + unsigned int dtim_interval, + unsigned int listen_interval); +int hif_set_rcpi_rssi_threshold(struct wfx_vif *wvif, + int rssi_thold, int rssi_hyst); +int hif_get_counters_table(struct wfx_dev *wdev, int vif_id, + struct hif_mib_extended_count_table *arg); +int hif_set_macaddr(struct wfx_vif *wvif, u8 *mac); +int hif_set_rx_filter(struct wfx_vif *wvif, + bool filter_bssid, bool fwd_probe_req); +int hif_set_beacon_filter_table(struct wfx_vif *wvif, int tbl_len, + const struct hif_ie_table_entry *tbl); +int hif_beacon_filter_control(struct wfx_vif *wvif, + int enable, int beacon_count); +int hif_set_operational_mode(struct wfx_dev *wdev, enum hif_op_power_mode mode); +int hif_set_template_frame(struct wfx_vif *wvif, struct sk_buff *skb, + u8 frame_type, int init_rate); +int hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required); +int hif_set_block_ack_policy(struct wfx_vif *wvif, + u8 tx_tid_policy, u8 rx_tid_policy); +int hif_set_association_mode(struct wfx_vif *wvif, int ampdu_density, + bool greenfield, bool short_preamble); +int hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, + int policy_index, u8 *rates); +int hif_keep_alive_period(struct wfx_vif *wvif, int period); +int hif_set_arp_ipv4_filter(struct wfx_vif *wvif, int idx, __be32 *addr); +int hif_use_multi_tx_conf(struct wfx_dev *wdev, bool enable); +int hif_set_uapsd_info(struct wfx_vif *wvif, unsigned long val); +int hif_erp_use_protection(struct wfx_vif *wvif, bool enable); +int hif_slot_time(struct wfx_vif *wvif, int val); +int hif_wep_default_key_id(struct wfx_vif *wvif, int val); +int hif_rts_threshold(struct wfx_vif *wvif, int val); + +#endif