From patchwork Mon Sep 20 16:11:13 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: 12505825 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 6315EC433EF for ; Mon, 20 Sep 2021 16:12:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 481F461166 for ; Mon, 20 Sep 2021 16:12:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242355AbhITQNZ (ORCPT ); Mon, 20 Sep 2021 12:13:25 -0400 Received: from mail-dm6nam12on2084.outbound.protection.outlook.com ([40.107.243.84]:20373 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S237445AbhITQNX (ORCPT ); Mon, 20 Sep 2021 12:13:23 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=J33kfZ+1cW1fTLNeDsQFyYqwFp53racN2ILzyrKGYY8VNi+b9TzNfRKf914pbzpB8W2nGYb/oIS8viGaaE79sRajCjoaV5BuiNG4a7WG7zqEDajajQHnt+NNUGu5THHP8G5DvUXefaBEuW1DJrOBxICXUHla9MTb9eKgEyYPXN2hHOOhAD1x2PGmw2eo9DpfmUBrj8sBDAEFy6g2Vr5RABLk0eVLPJAnhwcgbYK9eSE4G1KyS9LUbqMQ0roPYBgW3r2b57qQyzmrUaGTi5kciczrsbJFMZ/2VB5J5YikGZx4fM/bL0a22tRgvrSSGXIM/Uagh8KDkgQ5zjnjEFxTpQ== 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=IyY90r6QMFMHTI+VFb7nrT6DVJW15/DHuG0/svc2nKU=; b=H6LQPMENJRstnuhFaL5UwyN+NFYrrMlO84WBfTsTsI19PVyrcuyDJHfjJ4ToOe4ucJWuZzi9dKC74mzqT4BaakzydCLOci2gXX0PxL9xyES3RsTWiNKE865mLD8TvZpR+wwocSTH/+92my52FiWeA5CMaGVMK5Xw7AmmpQ70G5v81q65bVhyHJr6pBDsnjkSoSAuRWnP+QfDfYfoCeJJzWHwPTk0LhvpYB2lU2Sf/qXN2NDYqzwY6YZP38NWjkk8ykfg+l6A0JLKtQO15FvlQ5c1u488jrJeYb10AYaGN9PErBh85aLpGo6wPrZGwRj88Y+oLcEqt5zIDXKM0eOAJw== 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=IyY90r6QMFMHTI+VFb7nrT6DVJW15/DHuG0/svc2nKU=; b=TDtrY0dNYq7bkF+lPXoOhd5ExgfKWw54dGzdeHaop02dMijr+/Yfw4aBl4ZWHkjqohJ+VUd0ZTv4ly7Je7brSPzMfFejNbcLAL9aWNf7YpS4l39hW4OADGm7olRYIxL57a4hsSxcR3TGHggUwo2x9lA5Oq17OKfrfBBS9fI76C0= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:11:55 +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:11:55 +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 01/24] mmc: sdio: add SDIO IDs for Silabs WF200 chip Date: Mon, 20 Sep 2021 18:11:13 +0200 Message-Id: <20210920161136.2398632-2-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:11:53 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 3ca91d95-524d-4989-b469-08d97c515daa X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:6108; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: nvENJ9D9ITvMcToeSe9b5DmBOSwqPaZ1G/bJOiT8PUUvl/GHbdNDAnC/43uxZJHIBOzfk3pFVx7qgiZGWIu48xvpyxVi5x8ltoK+AkqwQ5/Y3VKvmDBGDcP9VjE3rozdjxoSIV6jLdKqDo/6Pp+aWc5+tfbnk2pqZ8j2mBqOR7cPDehz24rZiPBMr6k3TlaAlXel4p+mCwUvnqHbkwqbeuAX55gIhJZ37vTJn0NxgiJa+Nmcj+r4RnaO7YHTKm14Jq+EfMprZgFAMu+DozauVnHj3QQ87DEZIU/xYIVUNPmBdHRTw20JKpoCq5XIEfbDEHAU3lkhiEpH5iqi7nElwibvGOhOe5f5L9QxexawTMX+2yKE+orfoIsnHpCMCz2y3u5YBSvx5BG2ZfWixmyUO2k4IDGBXsgU1KQVwKfyyQKjGLoFoXolmKnMJTBT1DtBUtQdan+OA+w+IW3tv+K2wQeWLmNA7oXTRwmfk82NIyYx7EnmSUJVVpBCeWjkEvZ1lNffMgl1VZchlA/eFMymEBF6kkb6bD6D8SK7dMB9UQFcjfCTGvBxLIPWXTjvdCIdMchfyDxLWqbdBj5y5u7ZW9jJnLoxOaIMudVf3g5F/K0LSri14FZB5oopHlj+np35i6f78N95k0QtewJ4Oa3J/Q== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66946007)(52116002)(38100700002)(7696005)(6916009)(2906002)(1076003)(4326008)(4744005)(8936002)(316002)(8676002)(508600001)(86362001)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: rVRdA4PGHp8ciu6e+wzmlLqK3MUgAwafnMquSP8mSZdoloc7vn4DcHXKacgvoHjwIoPj2GTcSed9rq0IM5LaqwKB6DJbYlrUlGKzvWoA0R88XJiEJsiG9O1jAXABh7hIR2CErLyMUkm15TiWi+LRDTfF5bfzqjOT9HsWVY4HrzB86g6qq0GvmNPIVwhNqkWvWlmAJX1cdXcp1GbUm5yoYXnYEVG3hRpBvrdgKMa6gzUocEEzRqj/r1zI+kpPIDg0RudrbqmOJEE/B3eWLikAMlnlaHxvkfgruDMShFrNfGg+yEhwyyEivK32rqh1YHrOzxA/18qmmyKR9HkC4y+imI+LR+J7ecAkFzVbndY7qOkBpX4Zn0HVFAhZVw9Yt0JivVziFcZsg/BT8lXxPN4zr/S+feiIc+kFsEqCIrphqFi9tPa/9OP9cpaFWzjeB+sCVQlok1cW3ksvVRzvenfscxLC8bVJtW35t55tvyDm8MGQT9asbMALMr+68bSQ6KhxpjHL3n6359y3bbnhU7VxK7Q7Qyf9qTagEe24rkLjgt87aH0jqJgdxgSzYE66XC0t/H/ajID7mBQL0w40/noMj2un/ozrSiF9LC48nwsbGtLiMo6INfWbJ8KBOAQMXhYnardYWPHJC53JymyiPf8nwM8Pp8Np88QDZaq8vcWxLy0VXrKTCwtHv64hTXU5r3YheIN8UuWMQyZPX2FfotI3IoqsBYicYMrkUSkEmo12APZBWG18s8XwWHDKFinbaiDn+cpwTbmcAQEhJQAqZRfOjRawPvG9/9RCMj4pHiZrxzNvh585e6PdDjB2/P0G+tsU X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3ca91d95-524d-4989-b469-08d97c515daa 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:11:55.7817 (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: H6YfIPJHVawO+7zHDUAwS93ZiuIECV8lD1BSzU0VInpJi0AImPUn7KzOJNUH6rPx+uvLVXISDezixyXDHDmBPQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Jérôme Pouiller Add Silabs SDIO ID to sdio_ids.h. Note that the values used by Silabs are uncommon. A driver cannot fully rely on the SDIO PnP. It should also check if the device is declared in the DT. Signed-off-by: Jérôme Pouiller --- include/linux/mmc/sdio_ids.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index a85c9f0bd470..483692f3002a 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -25,6 +25,13 @@ * Vendors and devices. Sort key: vendor first, device next. */ +/* + * Silabs does not use a reliable vendor ID. To avoid conflicts, the driver + * won't probe the device if it is not also declared in the DT. + */ +#define SDIO_VENDOR_ID_SILABS 0x0000 +#define SDIO_DEVICE_ID_SILABS_WF200 0x1000 + #define SDIO_VENDOR_ID_STE 0x0020 #define SDIO_DEVICE_ID_STE_CW1200 0x2280 From patchwork Mon Sep 20 16:11:14 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: 12505827 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 86C55C4332F for ; Mon, 20 Sep 2021 16:12:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7291061166 for ; Mon, 20 Sep 2021 16:12:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242417AbhITQN3 (ORCPT ); Mon, 20 Sep 2021 12:13:29 -0400 Received: from mail-bn8nam12on2087.outbound.protection.outlook.com ([40.107.237.87]:42848 "EHLO NAM12-BN8-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242363AbhITQN0 (ORCPT ); Mon, 20 Sep 2021 12:13:26 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Bb6Z6KAkAFmf3NV5PZIfeD6/1gNTsmTM40Rr//vB3AJeosl6+G2mIRAPPkiMuo8l5ibV4RCHZ1VVo4wTZHXxQkxKS4qLdmLf1KBb9HjPa+hKrgFJY2Itn3P3IyjgK5j0RQkQXIM4v58K+h4Oa0uLvsJqp5L5Ha2Gzimft4/tup0FobKY5DrSUAY9S6fmDnTqPjdHcdKvfqozrqKkAuGR6Vn6y0FETzl8FyLgcue+r/Ahi+WrFYzVWfhRaFibR8tfRlfUc36NL4LPIdZ9z1J+hO/n05Vwfwni0eaR+Oyx4d5eaobp44cR53H0U2D0OoTMJZ2DsiBvZhUhg/F5sTsJ2g== 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=dRv4I+hELjkukyufIfYHuzZysN6ITNytJ3iPa3qM7eY=; b=JyIMEIbbqgwqCJcWT+vi42RAJHOeEkLA63MsIiHdzVpjL7tNbn8QMa98/rihJwV4SIuA6nycIMgxLU4CSsR2ogEnIR04VU6NjfWy5xcZJGE0d4Nvq+KElyZy5ejkPlPpcu3lALaOkOAZSY7TZkZ55QjxUCafTJ/0n0+0HD7Ijngh1Z8zarIjD2YHCDphx2cLp4LRmnGp9D59sqAHwndfb18EpVFWAK0NmBKlciyzGGqFit/YV0mlyn3ES7aXpVm+e3VnKFYZHGOAkeq+2jb8mg6DA4RMz9CRSdIylnLNVWCkuwx3uvyjHiSfIfRm0wd5L6WczLCAziY06+ca3wQJbQ== 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=dRv4I+hELjkukyufIfYHuzZysN6ITNytJ3iPa3qM7eY=; b=VQS+EKdhmK97wGMg2fJTY96f7jB+Qqi3YldvTA78nki+0VMTgVUwWHjdjbn9A6xf8JMbCtyt+zm6mtPXTHhJddSTeVOWkJUYGrhpqM4tSdhknVJoW8POqwl2Oy7PIrTHN/RNN123P+2drb5H/CXtfgFNk8753YafTYmHhFmBUVw= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:11:58 +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:11:58 +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 02/24] dt-bindings: introduce silabs,wfx.yaml Date: Mon, 20 Sep 2021 18:11:14 +0200 Message-Id: <20210920161136.2398632-3-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:11:56 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 3be3e88b-bb58-42c0-3f31-08d97c515f18 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Py4qAE5CCuF/BAJS4xMn4upRZ7sQqbDat1PXUNt3g0RkPZHsX4JFq+PKC833wRse4o3W2bGWch+atmIJun5DvcHSHfjO3YWl+Y8IvHG+ibwz+3ZgELsFl/VT5GHYp28kmXJGSJRJRd1q2Z34nD/REgsjxxf/iKY2MTPjR51AyhGd5qtsUPgqOL16+TMSMiqCrFX8vY2uHfeYEqlDVolPApy0dB1665zatVi5Ga/4+NSWFVKcse/ygmBx32i5Mr1z+jxA9+nS+wUxt+z83h2L+QH3sunJTmvpG3pr9ymsNfFbyqKo37msc/dKp2bQxXFYdByEzJSdflzAr0NFvBeZuG4AownUff6xQwGpuToxFd8/UTeR7LL04vEaj/EAppeIZkB4ambWMYy41ILNpeDjPT7y/d4zx3cTInfSzP9/bCM1V6ChPqzI7oJ9Gj1uJmXH2sbI1p1n2Slsk5ItVUfnT8rM6L4fOkpn2Zhw5PZAxbLsFF1ye/ygxhDqFbJ+b+nsZ61jIn1q1qiwvmja69nso2RLd9W6yF/O1kEbO4QD8Ezdm+N5FMEnvUPdxprKLgv476RVhXuq/r9NItVHTyjwDlbZQWutxpSSg08EKt5L+pNDBpg2p5cM5YNgTrlfLjp+teqHCK/rYLsPvc623v1orcq6hvYgF5An4VLgyRBo+8qJSbFyJrcGLO9Nh6KDYd8c/ao5oXHedbD6PdOQFxw+o2yNtLo6c5ABM66sQoMjkPg= 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66946007)(52116002)(38100700002)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(6666004)(7416002)(966005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: sc5TZxy/Cb4ejXycCR3phKPXWF8ePGjTNUdgbABHhITsGgmUhUyj1e/Ovod5zHRz4AjBhyckUl1K/GNYEoTOCnsg3sxo/ysmhYwaps/LA5f/j6jkgJOHRMXCcTB7SS+v3q2l7uRBqvLoGcnoFWG5qptSn12EmAKf2tSyXlWiqgTU58l0EhG9u7RidKeYE3FMMb6DjyzlOuYPmbvkjLk6675RKd8jCWogPmWUD+JxTZDMCdyobcCQIJuKPrv2XGeMh1STmYbPWpUnheGbDXbFOKJRHG3R3H3BUj+hy6OoZhv1HyT4mUruKPoHc5KplNQUhW1Uy6qprsJIOknFIR6uQBgQyrNjL7bhhlLoYZlT76pl68w2hMhzKh/CnklxnlhcHzODeHDLU5i76r5IfitqBFkAmc5iya3DrzXfmOvR9cUlc8dQ5uo1jxfJN84PJRWFoj20wro9J5pmo7KK8YNIeH7976MByf93lva2ONrioZQs9MqrLyAeP5k9ZSx0hI9zm2idG872hRPEFMk10dplnumlOyUzLx7P3x7cSvcJwUn/EqiKQTwLHjX2e0cSGp0mcbT/om/DqxgkAi2m+oqG89mkMlTt3MfAVXDlJK29DcxNdvMHPSOSCxDwZ/bf8FaymYitkDNu56aEbR1Ei4XwN0cyBsnYaWLYZgKYTKodudcuoqElYvoW7gbpARLJnanAurG4f1dsQ4nyQeBsichZJ+9+zc/r0K8IkGxCEozlG3xAL2nM/qesPNSBpmm8Zvp6nFxLnx8faNbOoI3224cQ4eYPkolpPahkYHWUmWiA49ZYvv9jYNAshStem6BdKs11 X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3be3e88b-bb58-42c0-3f31-08d97c515f18 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:11:58.2333 (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: UqIps7Bx3GD8sHE06vxxbtNGib7SIECEteUeMs3+vM6g831QJ3QJo8UHoT/EfvucRwGUCayaIRop0QunGCsxww== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Jérôme Pouiller Prepare the inclusion of the wfx driver in the kernel. Signed-off-by: Jérôme Pouiller Reviewed-by: Rob Herring --- .../bindings/net/wireless/silabs,wfx.yaml | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml diff --git a/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml b/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml new file mode 100644 index 000000000000..8a249ada45dd --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml @@ -0,0 +1,133 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2020, Silicon Laboratories, Inc. +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/net/wireless/silabs,wfx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Silicon Labs WFxxx devicetree bindings + +maintainers: + - Jérôme Pouiller + +description: > + Support for the Wifi chip WFxxx from Silicon Labs. Currently, the only device + from the WFxxx series is the WF200 described here: + https://www.silabs.com/documents/public/data-sheets/wf200-datasheet.pdf + + The WF200 can be connected via SPI or via SDIO. + + For SDIO: + + Declaring the WFxxx chip in device tree is mandatory (usually, the VID/PID is + sufficient for the SDIO devices). + + It is recommended to declare a mmc-pwrseq on SDIO host above WFx. Without + it, you may encounter issues during reboot. The mmc-pwrseq should be + compatible with mmc-pwrseq-simple. Please consult + Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml for more + information. + + For SPI: + + In add of the properties below, please consult + Documentation/devicetree/bindings/spi/spi-controller.yaml for optional SPI + related properties. + +properties: + compatible: + const: silabs,wf200 + + reg: + description: + When used on SDIO bus, must be set to 1. When used on SPI bus, it is + the chip select address of the device as defined in the SPI devices + bindings. + maxItems: 1 + + spi-max-frequency: true + + interrupts: + description: The interrupt line. Triggers IRQ_TYPE_LEVEL_HIGH and + IRQ_TYPE_EDGE_RISING are both supported by the chip and the driver. When + SPI is used, this property is required. When SDIO is used, the "in-band" + interrupt provided by the SDIO bus is used unless an interrupt is defined + in the Device Tree. + maxItems: 1 + + reset-gpios: + description: (SPI only) Phandle of gpio that will be used to reset chip + during probe. Without this property, you may encounter issues with warm + boot. (For legacy purpose, the gpio in inverted when compatible == + "silabs,wfx-spi") + + For SDIO, the reset gpio should declared using a mmc-pwrseq. + maxItems: 1 + + wakeup-gpios: + description: Phandle of gpio that will be used to wake-up chip. Without this + property, driver will disable most of power saving features. + maxItems: 1 + + silabs,antenna-config-file: + $ref: /schemas/types.yaml#/definitions/string + description: Use an alternative file for antenna configuration (aka + "Platform Data Set" in Silabs jargon). Default is 'wf200.pds'. + + local-mac-address: true + + mac-address: true + +additionalProperties: false + +required: + - compatible + - reg + +examples: + - | + #include + #include + + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + wifi@0 { + compatible = "silabs,wf200"; + pinctrl-names = "default"; + pinctrl-0 = <&wfx_irq &wfx_gpios>; + reg = <0>; + interrupts-extended = <&gpio 16 IRQ_TYPE_EDGE_RISING>; + wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + spi-max-frequency = <42000000>; + }; + }; + + - | + #include + #include + + wfx_pwrseq: wfx_pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wfx_reset>; + reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + mmc0 { + mmc-pwrseq = <&wfx_pwrseq>; + #address-cells = <1>; + #size-cells = <0>; + + wifi@1 { + compatible = "silabs,wf200"; + pinctrl-names = "default"; + pinctrl-0 = <&wfx_wakeup>; + reg = <1>; + wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; + }; + }; +... From patchwork Mon Sep 20 16:11:15 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: 12505831 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 8311BC433F5 for ; Mon, 20 Sep 2021 16:12:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6FDA161175 for ; Mon, 20 Sep 2021 16:12:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242489AbhITQNg (ORCPT ); Mon, 20 Sep 2021 12:13:36 -0400 Received: from mail-bn8nam12on2051.outbound.protection.outlook.com ([40.107.237.51]:10688 "EHLO NAM12-BN8-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242368AbhITQN3 (ORCPT ); Mon, 20 Sep 2021 12:13:29 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UkbsHm+jvGHABoAWrwC5dE0yjp5TlexJbys5Fg67IczydctZcl4hWuXgC3D38/eBE0zncOqGmT2fhtUnG7MMQCirztIgy/BKEMlAmqWpbzsRh+eFm0PryTQOilmJR5RDtJqYRfGC1ijHpCjgS/pDNZtpdNdHet8xW4XAIlJgWUD1Fm5YIz0twLHX/KRUYOXLscLncWj2cpAWnuwvehKStaXym5a6JA9zpeCrOOSkvWmioa1uQVKsHi6rAeWEBOA9F8h134j7X3mDK5dGTWjXWCrv+kfvpC4bRqFrxGzQY2TGVRK9kjsub1JBTvhoVQ9S+QpG8r9USdXfmniavbmjiw== 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=GNjCa2/lBKQ/1xBUi2Ezo8tCWK2S1z49PHV2SuZVb4o=; b=Q05r5zhS66rnfz1omxdxZqTna+R/UHChXNSMihw8eWA5e2RXedYgWDkHKUsaweKB9ylbZyUB0sBHX+CghuF5Aw0V2cszfwwS2wd4DKK2LrnhZHjteF115SYJW8uxT9LFiPCMMXvvYhdiyGoTDVus46Jv4cSHswCMtJCdhktve+5oHCnLwcIzUN0mAiT9jd2czch4w2DASQvJltHTUqVufW2Q4FjX+HFPs3w0ucQStKJD9ErybgmF1RHn87N30UAIb0SHTSQTPzZ92sJWDQO4ELhA1VjwX9qkRDulVRxLvn2IeYlV1KAK3DKyC627ShtznONVREOafLQwe9ELfF6WOA== 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=GNjCa2/lBKQ/1xBUi2Ezo8tCWK2S1z49PHV2SuZVb4o=; b=Q+2U4W1WRWbqhijTp26F59cQQB9Rbu2bi7CGMoLt1cu6LbYCcMbwVzlWF0GG02haW1xxh0ijgLq4p0ZePJpiHoPGI5VxBg78XtPuk9oxh+ZbJoqX90kN/wPnw0jG1G46f7UAS76MDV9lX2q3EQnvO55pFQvaXmZN7kZuH0YKfHI= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:00 +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:00 +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 03/24] wfx: add Makefile/Kconfig Date: Mon, 20 Sep 2021 18:11:15 +0200 Message-Id: <20210920161136.2398632-4-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:11:58 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 126a7755-6629-483f-3587-08d97c516093 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Ly5He/F+1LF2pjtD9sGdb6tPuCQOhDz6lIv+XSvrUJ64pEgyBm4FbLAxhD+Y1c+CSmtNCPl7TsfuLq9fKIVOfwK2r+TpLcrlX2/Y1Q8xrMt8XR/EyGMgHqv/4vnA4yp+/pO787n+FwoOM/kCaQ7GxSuvfc0M0Q8QJ7HjpJsMhX0Pk4ngDUnf4G5HrPvztGUsgjXN4c8yFxMXOfhuZ99BSl3BkyesoQQLH8p2kyTN9CfdtO60AdLdZtcpxr/m53UpBvRn4bDRGlYYA8WanDpzl0LE54u80tXZLq0HWj8yO3O+fv2c/9QkwC5rVe+oYRhjjK4gfmMrweK0051Tdut/EKJ3FdGyE3xcllCVKbZFH4xdQipqO7EQVioLcb8A+4lbnIJ2j4qdRlDtsJwLlMDvJ/pE0BksyAEn/isAey6ShSj7yu9a6hROeo0lD1SrZRxXsTBXgC3yBKASpSIu6R3HrU+MhM0tE5kN7pHlo4mEEuB4C9/rsbZotqaEWN59SINZmHmlYCWWHrYM2BohDqeS7TtketXK8/0XrtVRuyBxwQgPyfOUwMsUFB1N6KgZedBxUlmgVqKO1D8VPdmykA98D7W6k1lrKEbhHCKKdLIs9gLAZH3EWv49PrUT8pa02/6u/DzGhvNBWB8HeZ/lgd2SpQ== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: bOjIgo+kcj8mN2eb44nn/T+Va/JuGYHsbKuqSkjivS+1H7UGu2Ec8dSysb/rqbwnIT2eIJlNYdR7QWTp59vaxe5b7hAMae2Rk9MeWw2dFOxwwJR403ShpOf6wu7qZ8z8bEMYMrN3SuSwLViLMcYKL5XtChxoPg/bSy5kmEF6Gc3I4Szww7sGtuWX12BTgjY1GlKoGNpbZLZ8eKDlB05bHjUspBkovqu2FQx1dH9Q4NCUFMXOkSvl0uzNJHpP5K8o7llrV/awYwkVRF2vsE+OYFsy+rVmUlzJwsaU28verH9oxTODIRbwLmmPrr1gqtGO+fexOq8lCLTBZamE+pOSBD4Qu/D6GqabiKgYbH/9UO2lzFXt0UAn2kBLZv/Mz3gncbUVrXiZZyYRCz9NAOPeVDrWAEYHBNFa0SLfP1f3M6/9GhmIqEzecQKcSvqSajfRVv2kLSlnLHnKmUmcQ3086AQxC1oI6dQMZGJTBXvZGjYOPXXGuh/9vv9ywyCgWJ3BJl0FwlBu66MBD/KVjyZuGNuXCf6J2N1yy580VKWvQOtx5ht9drcl+vHGILTk8NIda1a7WwOLU9X1SR9cqoIgboQmDAWQGvEyEWQznzUh2pHsSV4V2R8UWcduqtsHVTLO4pmoQlX4YRHVZGiLdZd4BLDuM0+9xmirbntVa/Gh5vVJiY1W2T+4yAL2gCU4Gx2v3AYRYp4ssRsVSmbVbQioAEWiA80Wu5WfOO0gbosoES9ppjZFTYDupWG5xFTWugIOov694ERNFf0JhhYeivf5VoUEzQtUxO2Xeh2t9aZBfAYRpMQaHT8D0Q/U1SZrC/uT X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 126a7755-6629-483f-3587-08d97c516093 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:00.6719 (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: 49n6/yiGj0w3RLwsl6aQj5S2djNuXfw2n2wOjKnSc718zPBilQKt4Ms0rwdJ4aAI5jSX2U+aUH8xkSOuCgjf8A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/Kconfig | 12 +++++++++++ drivers/net/wireless/silabs/wfx/Makefile | 26 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/Kconfig create mode 100644 drivers/net/wireless/silabs/wfx/Makefile diff --git a/drivers/net/wireless/silabs/wfx/Kconfig b/drivers/net/wireless/silabs/wfx/Kconfig new file mode 100644 index 000000000000..3be4b1e735e1 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/Kconfig @@ -0,0 +1,12 @@ +config WFX + tristate "Silicon Labs wireless chips WF200 and further" + depends on MAC80211 + depends on MMC || !MMC # do not allow WFX=y if MMC=m + depends on (SPI || MMC) + help + This is a driver for Silicons Labs WFxxx series (WF200 and further) + chipsets. This chip can be found on SPI or SDIO buses. + + Silabs does not use a reliable SDIO vendor ID. So, to avoid conflicts, + the driver won't probe the device if it is not also declared in the + Device Tree. diff --git a/drivers/net/wireless/silabs/wfx/Makefile b/drivers/net/wireless/silabs/wfx/Makefile new file mode 100644 index 000000000000..f399962c8619 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/Makefile @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 + +# Necessary for CREATE_TRACE_POINTS +CFLAGS_debug.o = -I$(src) + +wfx-y := \ + bh.o \ + hwio.o \ + fwio.o \ + hif_tx_mib.o \ + hif_tx.o \ + hif_rx.o \ + queue.o \ + data_tx.o \ + data_rx.o \ + scan.o \ + sta.o \ + key.o \ + main.o \ + sta.o \ + debug.o +wfx-$(CONFIG_SPI) += bus_spi.o +# When CONFIG_MMC == m, append to 'wfx-y' (and not to 'wfx-m') +wfx-$(subst m,y,$(CONFIG_MMC)) += bus_sdio.o + +obj-$(CONFIG_WFX) += wfx.o From patchwork Mon Sep 20 16:11:16 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: 12505829 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 3EFE3C433FE for ; Mon, 20 Sep 2021 16:12:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 284DA60F70 for ; Mon, 20 Sep 2021 16:12:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242446AbhITQNd (ORCPT ); Mon, 20 Sep 2021 12:13:33 -0400 Received: from mail-dm6nam12on2042.outbound.protection.outlook.com ([40.107.243.42]:26081 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242440AbhITQNb (ORCPT ); Mon, 20 Sep 2021 12:13:31 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=E2B4OgqDzFXlnjg/RMBCseCgMNt+FJ4P0DYHDH/re/8Rii1tkBpFGY2Eh54i+lF05u/PjsDW+NEaxfnpihseo8t2Sc0iZDlAt8K8zn3eRp7DKWEMymtTZ8zdMhoJP3L0nFZSayJmJIzmwk4HHQMG9eYlyRu8e9zcbxW6Gi23FzKtPTmJqBzZSqTmS6Fgl77C8OYDjTBQcpVX6zoOzqW1rEpe1rcqGDQ3NJ/9dxgBXP3RaY4pYMtEeQTqIWx6YVecAhTfH5hakLv5/obBvjFwF7haztxnMDnDoaNUSvkl2SSlAh8c+8HLWic/xM3SVh5+/B7kDgVXqSHk9+VRBfF3Sw== 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=YReMQuBIPzwL0X2SQqdaw4bILayGeux92jRvC6HO64U=; b=Ezzkeu1J8qzJ6wmRIuWgdud74yeVVA3xY4ilmT0N2ipcl++OcM+ii7G+snYLNx7WJnK1UEwuhRAYEVfAGXffRVTL0vsyHHzEPN58+iLpsrjEHEK+DJh+GV8ZMDEOvneeK+UMfXuxoJ+B9gPpgQesu4eY43zGXXgVUH3v9FfNavfX21W4FZwMsvGbR+f8Q2Ryt1imQruMI2vwwqiFr0nqZMoToPRuXZdBG5rOCJWpTMY+RwWsBP3gaxcuXWD7fJytjofVjr7bsK/T+auXAOii1SndYS8xZGIBl+hr0v3YgF02jia4bLZAvqV03pGpGFd2ic7f09ev5O5052X/CzjZ/g== 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=YReMQuBIPzwL0X2SQqdaw4bILayGeux92jRvC6HO64U=; b=Fh5mG9r1bRvj+c5vVCAKKUDHgXqDsKyVGN2MiBOQNAbIt86U2umNPjCf+SBk/YQ3z2cOnvbt/oxr0nqLhrTXpADStKRv6VXN1aonbLA+39ftfHjxuoaaGM75XtyveFtIYXaoJaC1DAaoms6Nd1vkPjeTpTAIZhcOLoHVocNmGrU= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:03 +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:03 +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 04/24] wfx: add wfx.h Date: Mon, 20 Sep 2021 18:11:16 +0200 Message-Id: <20210920161136.2398632-5-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:00 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 816aa8d7-db5e-495f-cd1d-08d97c516203 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:773; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 6qvBmaFrqJ+i9YvPmPZOtNzzoydLBzEhfRN6Qs1jcQC3agHNS441a374Dd1POiGcbrPlgC9eIjFNlNqu3OUimc+Jr+iaS8qQIa4Vl9eb+51rue67FqgsX4sNd0zl7h/O+lr2ybTroVTk4Td3SsGZcHAeRtTXvtlrbqfIRa4ud/UKHRShgKk0zx+BvUNapnDRRUEAjRZT4p/IlE1jroIg8zoaP5X7nb+fmkGMob3qz6jkwrO0VQRAI25kON1Jgh0Rzc10rR3qhJfmlbTEYHZBHXKoJVGG4XRUEyzH9FvlgdQ165kUwsZ5JZjCV//Z8oRwWwWx1Gh9Usv0KdIZAQ/b9TR1TBQkhOjYCGWQ+NRXzRnvs0d8+F87JbwWS/beRykZ1Xd17jvrfUV3DZ7M/nweCxxxcXkmCzpcY9a/8G7sY5eKinQL8hACAh0H34mW+k4KPjQw403An231CG7IN35I5Lisps8Et5RszXB34DbgR3hLzaBzGgRlUxJ/Fv5oqtaQGAINu4AOn3MuMU1MX5o+Hen7dZ6J6dNUokwe87AUl8uFt+xhyq5DDwb8sWRarp5haOp5LZ/XnBvMGSOkUEXhdyUaBenhOWJ+X6gui7SrLpzTlgS0BK9L34OYZ15Pp1uf3LXDPA6BaaBJnjxBk6mf1w== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 5AlCFuwwkm56xHhgsvTn7gOFv4dRXqsawEYPnF9gdPLP34FgKKsAQeLsS2HgtdpXopaNVOoFChkZ4U6fV7pr9xCzTe9clOJfPRaxpmGjF4RwpLFfg7RnnCXZp2AMtQ9HUl2DX60RG8GtjdMGCLH5JUZY29mzjr2TcHO7jxPQLFBho9vx3r6LOkVCK4zcPJ6dTENysNS2OYqiwI70Hazt5wnt1/IEBxodtX3nDVIOD8WGUfsfdeaMkym+vUJZKD9WWfsUFSj+gbvfzkH7wW8jnB4IyhiXLhHc2UoEnwTA+JVScc0AphdMElX6ZpzORzn0cMl6ZNFrdXg5rWwwg9T1aQucSeFxNFgfUoFqC0b7qLvYEA7DrXC/VkIOeoaqd2uVDtQDhn5H7fRwSu4PyiRgzrte6Y60zJlkwlTWnI13baAbYUFXvuS1XkEzPv3PpGE2Dz5SOErXGy1miTkmXBncbEeIXdKKqffdpiOFqSqO/ZnfPfdO49xt5lHMlK6b/6ENywuOS5ccxRqlYP9a90FkJ5U1uDGlH4tGnB4yOsnQMdWU7MQRkYlB/rora9dTzvRXGduQ/En58DxLAPduZndp5nG8fVNow5trfWPZL2hTX9Yr1IPuk87BBNR8so29/QeFpga+xehRdyE0GYP+YpOQ1XXLOEDsDSh3fW5vop2XUj8jzUQkMrv22okX8Rk7463HV+qzv7Ku+QIJKrjdNgc4ZiK6WUfzHy41ztmgRjYTcbteutkftq2D+aE8/TYDKxez9+U2xBocisUHppKhZDBqQj4xvHJuPI95v9WKnTesp4maIRlGAu2Zd8LLgTsLCMi0 X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 816aa8d7-db5e-495f-cd1d-08d97c516203 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:03.1055 (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: /7pU1F51IwzlBlrLv8Zuj3D1DC0OwsMj3jZiHwIB1b1PgTWY2yolztj4J2daXO2UXXV4QGEw0SyQn8wDtWyipA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/wfx.h | 164 ++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/wfx.h diff --git a/drivers/net/wireless/silabs/wfx/wfx.h b/drivers/net/wireless/silabs/wfx/wfx.h new file mode 100644 index 000000000000..f8df59ad1639 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/wfx.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Common private data. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (c) 2006, Michael Wu + * Copyright 2004-2006 Jean-Baptiste Note , et al. + */ +#ifndef WFX_H +#define WFX_H + +#include +#include +#include +#include +#include + +#include "bh.h" +#include "data_tx.h" +#include "main.h" +#include "queue.h" +#include "hif_tx.h" + +#define USEC_PER_TXOP 32 /* see struct ieee80211_tx_queue_params */ +#define USEC_PER_TU 1024 + +struct hwbus_ops; + +struct wfx_dev { + struct wfx_platform_data pdata; + struct device *dev; + struct ieee80211_hw *hw; + struct ieee80211_vif *vif[2]; + struct mac_address addresses[2]; + const struct hwbus_ops *hwbus_ops; + void *hwbus_priv; + + u8 keyset; + struct completion firmware_ready; + struct hif_ind_startup hw_caps; + struct wfx_hif hif; + struct delayed_work cooling_timeout_work; + bool poll_irq; + bool chip_frozen; + struct mutex conf_mutex; + + struct wfx_hif_cmd hif_cmd; + struct sk_buff_head tx_pending; + wait_queue_head_t tx_dequeue; + atomic_t tx_lock; + + atomic_t packet_id; + u32 key_map; + + struct hif_rx_stats rx_stats; + struct mutex rx_stats_lock; + struct hif_tx_power_loop_info tx_power_loop_info; + struct mutex tx_power_loop_info_lock; + int force_ps_timeout; +}; + +struct wfx_vif { + struct wfx_dev *wdev; + struct ieee80211_vif *vif; + struct ieee80211_channel *channel; + int id; + + u32 link_id_map; + + bool after_dtim_tx_allowed; + bool join_in_progress; + + struct delayed_work beacon_loss_work; + + struct wfx_queue tx_queue[4]; + struct tx_policy_cache tx_policy_cache; + struct work_struct tx_policy_upload_work; + + struct work_struct update_tim_work; + + unsigned long uapsd_mask; + + /* avoid some operations in parallel with scan */ + struct mutex scan_lock; + struct work_struct scan_work; + struct completion scan_complete; + int scan_nb_chan_done; + bool scan_abort; + struct ieee80211_scan_request *scan_req; + + struct completion set_pm_mode_complete; +}; + +static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id) +{ + if (vif_id >= ARRAY_SIZE(wdev->vif)) { + dev_dbg(wdev->dev, "requesting non-existent vif: %d\n", vif_id); + return NULL; + } + vif_id = array_index_nospec(vif_id, ARRAY_SIZE(wdev->vif)); + if (!wdev->vif[vif_id]) + return NULL; + return (struct wfx_vif *)wdev->vif[vif_id]->drv_priv; +} + +static inline struct wfx_vif *wvif_iterate(struct wfx_dev *wdev, + struct wfx_vif *cur) +{ + int i; + int mark = 0; + struct wfx_vif *tmp; + + if (!cur) + mark = 1; + for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) { + tmp = wdev_to_wvif(wdev, i); + if (mark && tmp) + return tmp; + if (tmp == cur) + mark = 1; + } + return NULL; +} + +static inline int wvif_count(struct wfx_dev *wdev) +{ + int i; + int ret = 0; + struct wfx_vif *wvif; + + for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) { + wvif = wdev_to_wvif(wdev, i); + if (wvif) + ret++; + } + return ret; +} + +static inline void memreverse(u8 *src, u8 length) +{ + u8 *lo = src; + u8 *hi = src + length - 1; + u8 swap; + + while (lo < hi) { + swap = *lo; + *lo++ = *hi; + *hi-- = swap; + } +} + +static inline int memzcmp(void *src, unsigned int size) +{ + u8 *buf = src; + + if (!size) + return 0; + if (*buf) + return 1; + return memcmp(buf, buf + 1, size - 1); +} + +#endif From patchwork Mon Sep 20 16:11:17 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: 12505833 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=-21.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,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 74BABC433FE for ; Mon, 20 Sep 2021 16:12:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4EF6661175 for ; Mon, 20 Sep 2021 16:12:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242779AbhITQNz (ORCPT ); Mon, 20 Sep 2021 12:13:55 -0400 Received: from mail-dm6nam12on2045.outbound.protection.outlook.com ([40.107.243.45]:61920 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242448AbhITQNe (ORCPT ); Mon, 20 Sep 2021 12:13:34 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=BfNvZkXoQ8MyEAozyDk3uKV9okXJBn1mUyynJLypL0oco00sCepUP7YfO9HAIMhnCfTYDJTwgh9NlZgq5R1CFj07Ix3jdWHQi15kIvDlh5ojkedjwcUAogMAED32NwnafegBc/yZk6V0aNw2Ba7PNX1bzb9z4vm2a3IsY92nEh6i4HmQABZNkDhYaLJmAjo5QdErC/rb0aYsDSVKbOtTsv9YXPPO1L3P977ivA0+eklu178rDmJLrEd66Kzv/QX0R18p4QkpWfZBqNa+Q/9ee6cUobNjY2tNsD1XloVxtGiHnhB3Feyi+7Tik5CiUFgLGp6LpoW4RZTfEu9nLIds6g== 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=x3CoZ+AhrYp9f2SD5ySiZke4mr6oE7e2csN2AGZmPmI=; b=BIJteWKLCw1vPg/KCv7rtVTaWcVkmmUHbP0A7lXFgo5yrCXnX1425238L90bOqaxdieTBD5gA69/94u+Kf+tSS7PTv1wc2bZAvA3tbng1O8VZ7Z+i1Bc1/l75x9/gHehtbvrXCh8/1Z5t3xqW9E4o14TNZjZWVsLNTCk0A4GpFchxTrCckhUsTe4hM2RBZFUxvoC7SG0y8eSopxqWL67ThYx4VCAVOnWghNCCkAEseQQwB2ViREURQxUscqDyuTukR+cKGcgztkL+kz4T8ymXK18vVES0mMeXMb+/DJ16cfPwqnsKXW25+JtOtruvgeeQujZkTXlm3VGcAXBxyEgzA== 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=x3CoZ+AhrYp9f2SD5ySiZke4mr6oE7e2csN2AGZmPmI=; b=irgqtHqMWKXHdickKH2+7+cdC75GgJy2VG7PviOvLmO5h6+EX4eDdZ92hiGrZTYSqi5Cm143pxPTomVcwmpc3Zb9jP10U94pfq02DOydvtnsrDwVXjM8u3x0ZeDxLNhVqex4vnd85IxApdEZnVjaYe5KRdbuBmmv/wuajyKc7Mg= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:06 +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:05 +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 05/24] wfx: add main.c/main.h Date: Mon, 20 Sep 2021 18:11:17 +0200 Message-Id: <20210920161136.2398632-6-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:03 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 80c87f71-2d47-43ff-822b-08d97c5163be X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:208; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: AlzjsDZiObLXJhvNQYqCPIomxJjJKA/1YIFr+DRm6NGUv6A04KUR1JT5FpDld9hcdMKpY5OKqTf3CNpwLNZI/qUn63tNm1bGR9Kb+QeqUAZqTCi2p7fgpbSlse6HeAoZUNvz+ofKz/seCoVUi1ecdccTBKTvocmiwBrY/zFSjkr986s/iLacqG6ngq1YBHGABzTDJAAKTewhGVgYWD22iHFhtO90ZI2bwABYSWeEw6odNfB+6d/XaRhB1nXHX9rbQ3GnkQYONNs8oZYmWFVzu6R5OJ5DknFQkD5U7oNXlvu+2omvqVZfYYvN5eRaGPxe//Nq6PfcFHHtrXdWni9i4ktjKs8lRMlvAOnKgKKFR5IanzQDEqMK9S/LpjxTnfJvbOJYQ4mnt87nnnyDpFSK9uLrxWgBKq6iEIwJQj3vczbdJgloPb/uzJCFcj50CJElgSL1R0H/Ara5gIVCYQiwzONTNx0ghY0Ly9ikLHVy46fspT2zLtrjah0iKmmcXPj+JT/JAePISu0MsQvKm6FqnH596IpiDNm1C8SW+4j8x+zKM54i4caVqjLwtR+qJs42I1ncUnlVt3n43E4le+owx+X14oeRXZRahV9qio0mmu7uAs9/3nV/8NaL83MEjJauPlowEJUPKLMDcTSM1rZ66g== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(30864003)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: /unptU1Fh0K8M+bGsBUFGHfXxJAS9N06+sJtK8FD+N3diEPk8ZoytnucHlrCgrzLFFjKXCET0DRggw6Yqch9ceFYIVNoos4xDxrAYG71PJgTMpd5rDdDiKtiMeLs3nrR7vaG7Y7sGQnUVHk8WYLUS1HlGsTvNsh4c+2LM3fkoskvc17TCriiysC8FELYcO0PNeecxkCzbqohcGKI9eok8lDsT/i0E9dsVVH3Shiu2uUVqsU7kaibonfK/bTm40MpbX7CTfTwIM137wGisLF2GtX2BK/4Ig12xE0OuX0y4kQggre/2/DS/pf7hvhahxhuhdgnUcmhBPGNEXtkVQRKLtgFaW3U+4hWd45WIyvgJ/66qLKUTCavDaaK96FpDWXDgh8/WcD2ZdXxmp732p9YG/xQCBwstvdRhjmc63HUGULFjtCoIMBYyGUGUuZeHYuYFLho9S4OZs4TA1osW1iZ/AXUsWP95UoEJNFhQEVDlGLJkpzwHMiypN3lc4BBhk1U2XRMYGKjxKmfcniW4Q1VKRT5FuhvQolRthJaX/RsbKdGsxuns6CxWuqnvskANse5iophiAbXzEh0YMbWNfha/9ve6MunExjHPOy8lZUIAHYU+Ui9kyJ6Jwz/f/knGYPMSTGpzdpPPPa0S7Rg5+7IgE581hboZRKgKpjMoXCMZtHkzX4BubNO30Sn4DvCjA4qUw3+c88EIst3wcqofGYbc/xTZ7hqmWiBTcnv9Z2Vjh6tpqbrkUS2eH8D+0dq0zwL/V+MwxlbNR3GCb7DcdB2OkL8WYh9DGbIyM6iDdeKTKfJnG8WBzD3f4hkXq+KuivF X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 80c87f71-2d47-43ff-822b-08d97c5163be 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:05.8519 (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: t8uy2MHx5WPa2GclVjrUJNjmjQu5eBrsBMUIr5G8cfhzSyMrvPlx0/AxU1b4H7ezaTCoPZ/aI/uQOaS4sz/L2w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/main.c | 503 +++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/main.h | 43 +++ 2 files changed, 546 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/main.c create mode 100644 drivers/net/wireless/silabs/wfx/main.h diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c new file mode 100644 index 000000000000..b2ca49ca36e3 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/main.c @@ -0,0 +1,503 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Device probe and register. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (c) 2008, Johannes Berg + * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (c) 2007-2009, Christian Lamparter + * Copyright (c) 2006, Michael Wu + * Copyright (c) 2004-2006 Jean-Baptiste Note , et al. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "wfx.h" +#include "fwio.h" +#include "hwio.h" +#include "bus.h" +#include "bh.h" +#include "sta.h" +#include "key.h" +#include "scan.h" +#include "debug.h" +#include "data_tx.h" +#include "hif_tx_mib.h" +#include "hif_api_cmd.h" + +#define WFX_PDS_MAX_SIZE 1500 + +MODULE_DESCRIPTION("Silicon Labs 802.11 Wireless LAN driver for WF200"); +MODULE_AUTHOR("Jérôme Pouiller "); +MODULE_LICENSE("GPL"); + +#define RATETAB_ENT(_rate, _rateid, _flags) { \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +static struct ieee80211_rate wfx_rates[] = { + RATETAB_ENT(10, 0, 0), + RATETAB_ENT(20, 1, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(55, 2, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(110, 3, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(60, 6, 0), + RATETAB_ENT(90, 7, 0), + RATETAB_ENT(120, 8, 0), + RATETAB_ENT(180, 9, 0), + RATETAB_ENT(240, 10, 0), + RATETAB_ENT(360, 11, 0), + RATETAB_ENT(480, 12, 0), + RATETAB_ENT(540, 13, 0), +}; + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = NL80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_channel wfx_2ghz_chantable[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static const struct ieee80211_supported_band wfx_band_2ghz = { + .channels = wfx_2ghz_chantable, + .n_channels = ARRAY_SIZE(wfx_2ghz_chantable), + .bitrates = wfx_rates, + .n_bitrates = ARRAY_SIZE(wfx_rates), + .ht_cap = { + /* Receive caps */ + .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_MAX_AMSDU | + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), + .ht_supported = 1, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, + .mcs = { + .rx_mask = { 0xFF }, /* MCS0 to MCS7 */ + .rx_highest = cpu_to_le16(72), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + }, +}; + +static const struct ieee80211_iface_limit wdev_iface_limits[] = { + { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, +}; + +static const struct ieee80211_iface_combination wfx_iface_combinations[] = { + { + .num_different_channels = 2, + .max_interfaces = 2, + .limits = wdev_iface_limits, + .n_limits = ARRAY_SIZE(wdev_iface_limits), + } +}; + +static const struct ieee80211_ops wfx_ops = { + .start = wfx_start, + .stop = wfx_stop, + .add_interface = wfx_add_interface, + .remove_interface = wfx_remove_interface, + .config = wfx_config, + .tx = wfx_tx, + .join_ibss = wfx_join_ibss, + .leave_ibss = wfx_leave_ibss, + .conf_tx = wfx_conf_tx, + .hw_scan = wfx_hw_scan, + .cancel_hw_scan = wfx_cancel_hw_scan, + .start_ap = wfx_start_ap, + .stop_ap = wfx_stop_ap, + .sta_add = wfx_sta_add, + .sta_remove = wfx_sta_remove, + .set_tim = wfx_set_tim, + .set_key = wfx_set_key, + .set_rts_threshold = wfx_set_rts_threshold, + .set_default_unicast_key = wfx_set_default_unicast_key, + .bss_info_changed = wfx_bss_info_changed, + .configure_filter = wfx_configure_filter, + .ampdu_action = wfx_ampdu_action, + .flush = wfx_flush, + .add_chanctx = wfx_add_chanctx, + .remove_chanctx = wfx_remove_chanctx, + .change_chanctx = wfx_change_chanctx, + .assign_vif_chanctx = wfx_assign_vif_chanctx, + .unassign_vif_chanctx = wfx_unassign_vif_chanctx, +}; + +bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor) +{ + if (wdev->hw_caps.api_version_major < major) + return true; + if (wdev->hw_caps.api_version_major > major) + return false; + if (wdev->hw_caps.api_version_minor < minor) + return true; + return false; +} + +/* The device needs data about the antenna configuration. This information in + * provided by PDS (Platform Data Set, this is the wording used in WF200 + * documentation) files. For hardware integrators, the full process to create + * PDS files is described here: + * https:github.com/SiliconLabs/wfx-firmware/blob/master/PDS/README.md + * + * So this function aims to send PDS to the device. However, the PDS file is + * often bigger than Rx buffers of the chip, so it has to be sent in multiple + * parts. + * + * In add, the PDS data cannot be split anywhere. The PDS files contains tree + * structures. Braces are used to enter/leave a level of the tree (in a JSON + * fashion). PDS files can only been split between root nodes. + */ +int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len) +{ + int ret; + int start, brace_level, i; + + start = 0; + brace_level = 0; + if (buf[0] != '{') { + dev_err(wdev->dev, "valid PDS start with '{'. Did you forget to compress it?\n"); + return -EINVAL; + } + for (i = 1; i < len - 1; i++) { + if (buf[i] == '{') + brace_level++; + if (buf[i] == '}') + brace_level--; + if (buf[i] == '}' && !brace_level) { + i++; + if (i - start + 1 > WFX_PDS_MAX_SIZE) + return -EFBIG; + buf[start] = '{'; + buf[i] = 0; + dev_dbg(wdev->dev, "send PDS '%s}'\n", buf + start); + buf[i] = '}'; + ret = hif_configuration(wdev, buf + start, + i - start + 1); + if (ret > 0) { + dev_err(wdev->dev, "PDS bytes %d to %d: invalid data (unsupported options?)\n", + start, i); + return -EINVAL; + } + if (ret == -ETIMEDOUT) { + dev_err(wdev->dev, "PDS bytes %d to %d: chip didn't reply (corrupted file?)\n", + start, i); + return ret; + } + if (ret) { + dev_err(wdev->dev, "PDS bytes %d to %d: chip returned an unknown error\n", + start, i); + return -EIO; + } + buf[i] = ','; + start = i; + } + } + return 0; +} + +static int wfx_send_pdata_pds(struct wfx_dev *wdev) +{ + int ret = 0; + const struct firmware *pds; + u8 *tmp_buf; + + ret = request_firmware(&pds, wdev->pdata.file_pds, wdev->dev); + if (ret) { + dev_err(wdev->dev, "can't load antenna parameters (PDS file %s). The device may be unstable.\n", + wdev->pdata.file_pds); + return ret; + } + tmp_buf = kmemdup(pds->data, pds->size, GFP_KERNEL); + if (!tmp_buf) { + ret = -ENOMEM; + goto release_fw; + } + ret = wfx_send_pds(wdev, tmp_buf, pds->size); + kfree(tmp_buf); +release_fw: + release_firmware(pds); + return ret; +} + +static void wfx_free_common(void *data) +{ + struct wfx_dev *wdev = data; + + mutex_destroy(&wdev->tx_power_loop_info_lock); + mutex_destroy(&wdev->rx_stats_lock); + mutex_destroy(&wdev->conf_mutex); + ieee80211_free_hw(wdev->hw); +} + +struct wfx_dev *wfx_init_common(struct device *dev, + const struct wfx_platform_data *pdata, + const struct hwbus_ops *hwbus_ops, + void *hwbus_priv) +{ + struct ieee80211_hw *hw; + struct wfx_dev *wdev; + + hw = ieee80211_alloc_hw(sizeof(struct wfx_dev), &wfx_ops); + if (!hw) + return NULL; + + SET_IEEE80211_DEV(hw, dev); + + ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, CONNECTION_MONITOR); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, SUPPORTS_PS); + ieee80211_hw_set(hw, MFP_CAPABLE); + + hw->vif_data_size = sizeof(struct wfx_vif); + hw->sta_data_size = sizeof(struct wfx_sta_priv); + hw->queues = 4; + hw->max_rates = 8; + hw->max_rate_tries = 8; + hw->extra_tx_headroom = sizeof(struct hif_msg) + + sizeof(struct hif_req_tx) + + 4 /* alignment */ + 8 /* TKIP IV */; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); + hw->wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; + hw->wiphy->features |= NL80211_FEATURE_AP_SCAN; + hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; + hw->wiphy->max_ap_assoc_sta = HIF_LINK_ID_MAX; + hw->wiphy->max_scan_ssids = 2; + hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + hw->wiphy->n_iface_combinations = ARRAY_SIZE(wfx_iface_combinations); + hw->wiphy->iface_combinations = wfx_iface_combinations; + hw->wiphy->bands[NL80211_BAND_2GHZ] = devm_kmalloc(dev, sizeof(wfx_band_2ghz), GFP_KERNEL); + /* FIXME: also copy wfx_rates and wfx_2ghz_chantable */ + memcpy(hw->wiphy->bands[NL80211_BAND_2GHZ], &wfx_band_2ghz, + sizeof(wfx_band_2ghz)); + + wdev = hw->priv; + wdev->hw = hw; + wdev->dev = dev; + wdev->hwbus_ops = hwbus_ops; + wdev->hwbus_priv = hwbus_priv; + memcpy(&wdev->pdata, pdata, sizeof(*pdata)); + of_property_read_string(dev->of_node, "silabs,antenna-config-file", + &wdev->pdata.file_pds); + wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup", + GPIOD_OUT_LOW); + if (IS_ERR(wdev->pdata.gpio_wakeup)) + return NULL; + if (wdev->pdata.gpio_wakeup) + gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); + + mutex_init(&wdev->conf_mutex); + mutex_init(&wdev->rx_stats_lock); + mutex_init(&wdev->tx_power_loop_info_lock); + init_completion(&wdev->firmware_ready); + INIT_DELAYED_WORK(&wdev->cooling_timeout_work, + wfx_cooling_timeout_work); + skb_queue_head_init(&wdev->tx_pending); + init_waitqueue_head(&wdev->tx_dequeue); + wfx_init_hif_cmd(&wdev->hif_cmd); + wdev->force_ps_timeout = -1; + + if (devm_add_action_or_reset(dev, wfx_free_common, wdev)) + return NULL; + + return wdev; +} + +int wfx_probe(struct wfx_dev *wdev) +{ + int i; + int err; + struct gpio_desc *gpio_saved; + + /* During first part of boot, gpio_wakeup cannot yet been used. So + * prevent bh() to touch it. + */ + gpio_saved = wdev->pdata.gpio_wakeup; + wdev->pdata.gpio_wakeup = NULL; + wdev->poll_irq = true; + + wfx_bh_register(wdev); + + err = wfx_init_device(wdev); + if (err) + goto bh_unregister; + + wfx_bh_poll_irq(wdev); + err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ); + if (err <= 0) { + if (err == 0) { + dev_err(wdev->dev, "timeout while waiting for startup indication\n"); + err = -ETIMEDOUT; + } else if (err == -ERESTARTSYS) { + dev_info(wdev->dev, "probe interrupted by user\n"); + } + goto bh_unregister; + } + + /* FIXME: fill wiphy::hw_version */ + dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n", + wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor, + wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label, + wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor, + wdev->keyset, wdev->hw_caps.link_mode); + snprintf(wdev->hw->wiphy->fw_version, + sizeof(wdev->hw->wiphy->fw_version), + "%d.%d.%d", + wdev->hw_caps.firmware_major, + wdev->hw_caps.firmware_minor, + wdev->hw_caps.firmware_build); + + if (wfx_api_older_than(wdev, 1, 0)) { + dev_err(wdev->dev, + "unsupported firmware API version (expect 1 while firmware returns %d)\n", + wdev->hw_caps.api_version_major); + err = -ENOTSUPP; + goto bh_unregister; + } + + if (wdev->hw_caps.link_mode == SEC_LINK_ENFORCED) { + dev_err(wdev->dev, "chip require secure_link, but can't negotiate it\n"); + goto bh_unregister; + } + + if (wdev->hw_caps.region_sel_mode) { + wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[11].flags |= IEEE80211_CHAN_NO_IR; + wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[12].flags |= IEEE80211_CHAN_NO_IR; + wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[13].flags |= IEEE80211_CHAN_DISABLED; + } + + dev_dbg(wdev->dev, "sending configuration file %s\n", + wdev->pdata.file_pds); + err = wfx_send_pdata_pds(wdev); + if (err < 0 && err != -ENOENT) + goto bh_unregister; + + wdev->poll_irq = false; + err = wdev->hwbus_ops->irq_subscribe(wdev->hwbus_priv); + if (err) + goto bh_unregister; + + err = hif_use_multi_tx_conf(wdev, true); + if (err) + dev_err(wdev->dev, "misconfigured IRQ?\n"); + + wdev->pdata.gpio_wakeup = gpio_saved; + if (wdev->pdata.gpio_wakeup) { + dev_dbg(wdev->dev, "enable 'quiescent' power mode with wakeup GPIO and PDS file %s\n", + wdev->pdata.file_pds); + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); + control_reg_write(wdev, 0); + hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT); + } else { + hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE); + } + + for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { + eth_zero_addr(wdev->addresses[i].addr); + err = of_get_mac_address(wdev->dev->of_node, + wdev->addresses[i].addr); + if (!err) { + wdev->addresses[i].addr[ETH_ALEN - 1] += i; + } else { + ether_addr_copy(wdev->addresses[i].addr, + wdev->hw_caps.mac_addr[i]); + } + if (!is_valid_ether_addr(wdev->addresses[i].addr)) { + dev_warn(wdev->dev, "using random MAC address\n"); + eth_random_addr(wdev->addresses[i].addr); + } + dev_info(wdev->dev, "MAC address %d: %pM\n", i, + wdev->addresses[i].addr); + } + wdev->hw->wiphy->n_addresses = ARRAY_SIZE(wdev->addresses); + wdev->hw->wiphy->addresses = wdev->addresses; + + if (!wfx_api_older_than(wdev, 3, 8)) + wdev->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; + + err = ieee80211_register_hw(wdev->hw); + if (err) + goto irq_unsubscribe; + + err = wfx_debug_init(wdev); + if (err) + goto ieee80211_unregister; + + return 0; + +ieee80211_unregister: + ieee80211_unregister_hw(wdev->hw); +irq_unsubscribe: + wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); +bh_unregister: + wfx_bh_unregister(wdev); + return err; +} + +void wfx_release(struct wfx_dev *wdev) +{ + ieee80211_unregister_hw(wdev->hw); + hif_shutdown(wdev); + wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); + wfx_bh_unregister(wdev); +} + +static int __init wfx_core_init(void) +{ + int ret = 0; + + if (IS_ENABLED(CONFIG_SPI)) + ret = spi_register_driver(&wfx_spi_driver); + if (IS_ENABLED(CONFIG_MMC) && !ret) + ret = sdio_register_driver(&wfx_sdio_driver); + return ret; +} +module_init(wfx_core_init); + +static void __exit wfx_core_exit(void) +{ + if (IS_ENABLED(CONFIG_MMC)) + sdio_unregister_driver(&wfx_sdio_driver); + if (IS_ENABLED(CONFIG_SPI)) + spi_unregister_driver(&wfx_spi_driver); +} +module_exit(wfx_core_exit); diff --git a/drivers/net/wireless/silabs/wfx/main.h b/drivers/net/wireless/silabs/wfx/main.h new file mode 100644 index 000000000000..115abd2d4378 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/main.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Device probe and register. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (c) 2006, Michael Wu + * Copyright 2004-2006 Jean-Baptiste Note , et al. + */ +#ifndef WFX_MAIN_H +#define WFX_MAIN_H + +#include +#include + +#include "hif_api_general.h" + +struct wfx_dev; +struct hwbus_ops; + +struct wfx_platform_data { + /* Keyset and ".sec" extension will be appended to this string */ + const char *file_fw; + const char *file_pds; + struct gpio_desc *gpio_wakeup; + /* if true HIF D_out is sampled on the rising edge of the clock + * (intended to be used in 50Mhz SDIO) + */ + bool use_rising_clk; +}; + +struct wfx_dev *wfx_init_common(struct device *dev, + const struct wfx_platform_data *pdata, + const struct hwbus_ops *hwbus_ops, + void *hwbus_priv); + +int wfx_probe(struct wfx_dev *wdev); +void wfx_release(struct wfx_dev *wdev); + +bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor); +int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len); + +#endif From patchwork Mon Sep 20 16:11:18 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: 12505835 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 227F7C43217 for ; Mon, 20 Sep 2021 16:12:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0CEDD61163 for ; Mon, 20 Sep 2021 16:12:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242538AbhITQN6 (ORCPT ); Mon, 20 Sep 2021 12:13:58 -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 S242528AbhITQNi (ORCPT ); Mon, 20 Sep 2021 12:13:38 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iO1chGQmT58B9Jh+R00LK5mcpfIOi7PGaN5ro74Gde3J2xuNDEPN5t4DgvPswTjyrL7sVHC0Nr297ndTjrtVnhZjpiphyvVUz27/oHHLjwsdY+SREE0bp0aoDPH8kg9GdH7+Lr2ILx4JyZ0P6N6fFTP8nxUti9xGNDoJV1OfNJSg8Y0vugKFXtECYBXTdDEBnXQ/N6O2tBZcsCu+jT6fjD6E+4khwW8ubQxtHFGJP03enjQe64v8sapjjkfHOhPGfw0+8gJyqcK2amorq6j8AZl/A6wAdOz80UvNUPo5BfQiZzjlVLv6R0t0dghlWmigaWAotfM3jJVXu2+K9abfyg== 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=51XqWHJtByRQLPsnY3wtzpUPOfwDveF+8mA8Bal+JXA=; b=J15/oONrpof7TklhtN9Gsg47xvksyl2YPGiy1HcRQuVIUzsIpWl+W2ExminVbt6si7oX4oHYV+EqNMqGnRuUa60q91rS/xOAQ9F3KvyEOvtoWzLNf4BtPgwZG+7OEN6YDtrB7N7EZ5zZ3K+Xk9TIzBnKwsd/UG37jgnvaoyD9riaDYBUjxQYeaUMu2o4rHOAxTz9L2ZnwbnBD0tyERuvK3RBi1KYYI6iJVu3555L2NeaCvwNoISWzqhtwxg/jI4FLEnvGz1cKDesU8GLb3mmTfzDuWLPK+eFiuuVx1bB73UY+QX+BdV5kz3JL4TlhzIolr7OjJwPCmUoRV0ir6T4Yg== 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=51XqWHJtByRQLPsnY3wtzpUPOfwDveF+8mA8Bal+JXA=; b=E+LuKdBVpvgS3FS1jn1Qlts2IM3YImFG3d2OYFq2tTEzwaQqV54ssGh6cRodk7obtBRn9b9SnyB0q/9BEsTWfIocrmPJfwAiMKuEe7P1/fguTsjIc5vsHuNrHV33hYfbX+Y9XtxGZcS4DCjDdMdGF+TvBr2NiDCYJCTuEXTc8k8= 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:08 +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:08 +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 06/24] wfx: add bus.h Date: Mon, 20 Sep 2021 18:11:18 +0200 Message-Id: <20210920161136.2398632-7-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:06 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e0e2b772-fe34-43ef-0172-08d97c516517 X-MS-TrafficTypeDiagnostic: SN6PR11MB2557: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:421; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: w0r0Iq+B3KsCuXeQMcuB9nxxH6F+dOgvu1kZ9iOJRggGNCgxGOzex4L0Xta5Uas9l0u8I6VlTOWIQVbXljAFQkQ8xUjgI5NvCLVgMAFcOGWYUtS5qntPDihBdcMI5GX5QRjja/DXfoGpM+nBOIcXtBgkf6pxtbh2u1YA0YZCga03//p1sgtlPEnlxZMTEmJqQSlP+b+Z4i4AxfrymCV5Kj4VLLutW00Dm/VQvrHBum4R1/m48WTRRw99GH+4EZo0eh2FYms5wIBt3dBfJDebgezRk6YweR+Z+xJo/LdbCxfHsMGNYtYPyQaIih9ExZp4rkfocfUjAizNdFsH9Jz8Jmyls5fALce+DUn93+u0a5osBY4lPy0YP8YEmvGLPGfMg9EYGzzjHk2LXwESgZn4LhKn2DhPY+amM/hBn+SSVAPqCrxsU7EZRpGGQwo9WA+gWT2nsDJ+B+XWp2Tapcnqk4g7yQ02miThzkr6CtB617gdaJz1bN7FWlremCuj4ayo+m+UtHCaKKW40+zUNU+kJ9c/D/Wc7LZdiHZ6rqPxKGVxNybJ1GqKcxmSWDoDlBBoCbRsE8kQnpJwSIVJsvjJghLbjFEu4jFB9CvULhhAQCBBDdxNL8kxVHi+CWr4eDKF2Ro6VV7d4Jzl0WrfZpSVwA== 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)(1076003)(8936002)(54906003)(38100700002)(86362001)(6486002)(36756003)(66574015)(478600001)(5660300002)(7416002)(6916009)(186003)(66476007)(2616005)(7696005)(6666004)(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: Ve9up69E+6hm+MTzWUH/niY37VJ+2PnOOo/aHaxKTVjcibVJErrQDahFIYsSnrSO3jMsIZwoJE9dKNn0HxXjF5xpBUJQgbI9CH+rrnUXljSPgbBV/SlkgvM3WSsj6vZrefmkk7QAKYWbDeWZOXNWOFqDxUXNFG1e9ZgHNy1PZdVvEYeidkaw/XGyLbNIU0psR9vIRiNt/Zj9gATATETdG2Yh0FtFcqpJLcq8sYvYwMJmrFGuCbcD/szaW0POOwxxU/3DbK0He8RkMoKIX9PnJeicF4q52PEU4k/sZvmvXuh23vnp/CQblVFGC9Ur9N/2AqMuVTm01Q01C1EsvK+jA4C/tNBQX9mbF580eJ9CBeSuYXI3Z9KcGnDDa4k0jRn2U+nWHnULakDTrVoJS+Gp5dS6RTyCJanfHIXF6D/A4LRoNEkjggX9m3oHLr7M2cuvyKtJEOXpx7Pj9RGnISRhtgt5kMAVnUh2UPOyFk+gmffxPsBbbTaziEL4lS7FtSMT24m2dNhEunNN7TrFt3DQrqCQwI0mQaMOhiOtD5QeMZmfjwjxrL4usbCCPm/Px3jlc49R2LfbyAT8hiWepdNR2yIUGCaB1S3Nv8XbpKuJO/P/ewAYO176Po3jhRDNOSlqMPm60cSgO4QFUkgSE69E3dLXZculDeEJQufaKC2zysQumM79Y8v4eX3Ic74I0NCGiHDC6n8XiDRP8c2EN2PM4qGBgifuFXpCb+PHf/URNHrGJESV7AQQhl72M2X/ojV3I4MbV3zc3ZBSgczH+nQRDzaSTUE3F8jJQd74VB6Q7bSXTSmPE71LCnrXbrV1sqfh X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: e0e2b772-fe34-43ef-0172-08d97c516517 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:08.2126 (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: vl1djcmqEzBA6sSmyTG0WfMehA/ZM3RcLNzIpDiaqo+dsPk+hnUKZb7RSTkkuurewLSKJLt29vR6i2YkPwlL7Q== 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/bus.h | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/bus.h diff --git a/drivers/net/wireless/silabs/wfx/bus.h b/drivers/net/wireless/silabs/wfx/bus.h new file mode 100644 index 000000000000..ca04b3da6204 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/bus.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Common bus abstraction layer. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_BUS_H +#define WFX_BUS_H + +#include +#include + +#define WFX_REG_CONFIG 0x0 +#define WFX_REG_CONTROL 0x1 +#define WFX_REG_IN_OUT_QUEUE 0x2 +#define WFX_REG_AHB_DPORT 0x3 +#define WFX_REG_BASE_ADDR 0x4 +#define WFX_REG_SRAM_DPORT 0x5 +#define WFX_REG_SET_GEN_R_W 0x6 +#define WFX_REG_FRAME_OUT 0x7 + +struct hwbus_ops { + int (*copy_from_io)(void *bus_priv, unsigned int addr, + void *dst, size_t count); + int (*copy_to_io)(void *bus_priv, unsigned int addr, + const void *src, size_t count); + int (*irq_subscribe)(void *bus_priv); + int (*irq_unsubscribe)(void *bus_priv); + void (*lock)(void *bus_priv); + void (*unlock)(void *bus_priv); + size_t (*align_size)(void *bus_priv, size_t size); +}; + +extern struct sdio_driver wfx_sdio_driver; +extern struct spi_driver wfx_spi_driver; + +#endif From patchwork Mon Sep 20 16:11:19 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: 12505837 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 9268AC433EF for ; Mon, 20 Sep 2021 16:12:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7959B61184 for ; Mon, 20 Sep 2021 16:12:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242654AbhITQOE (ORCPT ); Mon, 20 Sep 2021 12:14:04 -0400 Received: from mail-bn7nam10on2055.outbound.protection.outlook.com ([40.107.92.55]:31296 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242661AbhITQNu (ORCPT ); Mon, 20 Sep 2021 12:13:50 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=XP7/cJrcHZecIdgKC9bZ4DIe8OS40PSz0j07ZlgTzdPrFMUJEg9G2B0OYmxGOSZT+sb1VJTZWHQiyFxBlRO20z9kkKpFBWP+srBOWZFOSAsqDvgbFqG6Q3AYU/COCGN88PrVHV86fP8KfLkE4Ikl+eKTKUkPeJ7Wp1ImOY2xm1lblEGQODpDAHRh8fG9xWaA3GP7IKnDmaMFLeRPgjorJDbbTiipFpgHIUb5OTl79uL6oHPsOh0qfMOoNDZ1TIzOUCbVJJFMk4FWiVTrIBnTn8okwSKmXgQCFilQtG0nFZ9S0/uIEOnNe97oU6I+5gSeT0hF/wzughz7+lfRYM5dXQ== 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=agdAC3VUVrwvu6B1Coi2+jA/vJB6/tC0zCloVaIaojU=; b=M14Wp+hHRf/C6o1Voulz4iiKtl6OUc6aMYrkWHDuah7TBMb7wW/njzc5+7Uh1pTv5r2E+xhk5YlWzw0Wn5fdHG6/6PGEYSecyM2kJgpqcqinhik5GOMIO/tg6PhpxndyQW/eBnclB2p1xLCJ5COj4vyHoZGxiejMEjjwL3n94VVVlI7VsipeZ0RCHwASyuS10B2a7jJrnaJiuBTVY5uD1eWC/H7ITvUt+Ap9xovsxLqakYcZ91t2RjWYK+jBPtQLwZ0tIr7ODNPgNnhhakFUiZrSQ7w6+sL6szhIne/LGLUDQrx3uLzjiu4jrDOYYZmzb4HTYHTQ2b4dWwIA7JuDJg== 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=agdAC3VUVrwvu6B1Coi2+jA/vJB6/tC0zCloVaIaojU=; b=QwP2Vvx8tPpRt10pQuN0WiU0EPz5Tpqlm6yKPhS0BYzMPKvIxCwU87yfim+1RmGsZryF3NLav8H4FhN6NGXWOTx2YRaeHXsBXPhGXpsrW173GnvBdLjer4mAwf1KuaTKjzuOOxDdbZKf13qor5Sy5QDj1OaWX3ZGLcuKhqE7VHQ= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:10 +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:10 +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 07/24] wfx: add bus_spi.c Date: Mon, 20 Sep 2021 18:11:19 +0200 Message-Id: <20210920161136.2398632-8-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:08 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 64cba47c-47f5-4dad-7680-08d97c516685 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:2733; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 0t5vd3oCG1NrPdHf97NukwSvn4nLuR4YzXUG3B8aw63F8mRhBnWa/s9ny+daQiRBar6I72l3GFGQSGhWsUvAIbT206jJbzBxz9NZ0n6jcUROwGbYf9kkuxTiJ5HgW8Qzi7/aZF5t853xXwAUxLX20DcB7ODpKlNmjz+TZqChTCp8yd6V7V6iXsL/bVF0Z3EuGzOrkvZh5Aqg2ojwD00D7G4zH5ohfH8rQkOyh2U5hQAlrvyPURqitLyP9aUz5VmmbCOX7oAYT9FaYEG9KopB+1tP12YByBuVYkED/8Ao1Vnj8QVMGdvFO1VMSMH4TW8lKtUO3A868Nqt4ozJEB0pj9YtYAG7j7odAjUGgzAYiw84je17XKSRU6atLVJA/zp156vzQ8hzillpRQPpNVx2wAmNLW+FEqh+T4htuBncWzyYDPg5TP0agL09JnbVifk4gLElMF6fyfGyjQpRycwMkcqLQnPFW1u2FUb3GeK7oeFVh8zyQB2ZGg2A9WrjfRcvTsiJm61tFhVnokMpzspZXwjX/tFfjlVqX5ouB4SHh9+jOLS6TU6HhqI/mmRLPy9OSNa00zrblgmhQQspXfpo+dXjDmYGySnWYjZOTaJPwC52q+aQUFkJLISBqEA4alMDc3B4M7YUMc5E8Kt/80zr5Q== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 7kCobPDItjEN7DDCBeF6TF23+HXVwK5qhWUSfhdSHqs/WnsT8Cl4xXoLxWPpEz3OLLbaVdikoyyCFRKO+e7vicwBgnpxQB1rGJrkL01T/JyhZZZvIRR4QiyL0f2yp4u5cCLE4++MU7bRQxJAHlpg8Fk9lYlOyOuf8BmOg+sY1n1+1R9Un4bEXBEzCK+J1LiHd6OyQrPV4yJVvpEzCqviFHKpoKyW0Cs2xXn04IDRoV2EoLlNWKibX4mYAWg3dCmf9pRRInUhWalZSseYFJzckze2DCPGhPmZ/sDSIKrz0nLv+4mvmlQWze4SoaOc3UqueP7b4pQTov1pT7f1vG5e3rgIqTILm+KRazq1cQGcRutVUOoL39AzBsVSk4pNtWtBnXzU/7wKcQ59G/Kbshl9rNrcB+epomeS3qkb1KajEE4qyrNQY4zlyvAnKTY9WV/DityXEp+p+MkOj9clvis+Xlh3f0jDNuKNoYPsoArVLZV3KbfBAXB9MbSJLweDb5hrJHwWMFpVttUycymCBuL7pqJsWA9ldtmsAUFuz2rzc9AUzdLnj+UceCJVTfHQPx5PkES0u/9t7CQo1eWhyrgLdaOQcyMF+Pf39Z5tHMp5fMo+JZ1FHsifyl6on19TPT9EekqC2u5FFy/PWCgKvWXdcXjdVOEoDTkIyM9iVwzo2epy8N1s3xgdnYdeDoRdj+20QQucZm2/y3MWr7ISkhi0KNZ8d4UGplmZR+DCMWRIsElGr2q9LGgkOJD4DqLeJE9PMMZGgkHDwa6/5vuM+0sr94SoNnLFp1ID33vq7O+k59d7hK88GoE423dztXum+9kL X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 64cba47c-47f5-4dad-7680-08d97c516685 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:10.6352 (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: x6mv1mbzsjjV7dCUz9dpS8aUE1jIZY+1f2owwz9Co3s6YhXcSZoE6VBdWNbpJzoYHx7rgBKFtdMaD9KHP/iF7A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/bus_spi.c | 271 ++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/bus_spi.c diff --git a/drivers/net/wireless/silabs/wfx/bus_spi.c b/drivers/net/wireless/silabs/wfx/bus_spi.c new file mode 100644 index 000000000000..55ffcd7c42e2 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/bus_spi.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SPI interface. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2011, Sagrad Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include +#include +#include +#include +#include +#include + +#include "bus.h" +#include "wfx.h" +#include "hwio.h" +#include "main.h" +#include "bh.h" + +#define SET_WRITE 0x7FFF /* usage: and operation */ +#define SET_READ 0x8000 /* usage: or operation */ + +#define WFX_RESET_INVERTED 1 + +static const struct wfx_platform_data wfx_spi_pdata = { + .file_fw = "wfm_wf200", + .file_pds = "wf200.pds", + .use_rising_clk = true, +}; + +struct wfx_spi_priv { + struct spi_device *func; + struct wfx_dev *core; + struct gpio_desc *gpio_reset; + bool need_swab; +}; + +/* The chip reads 16bits of data at time and place them directly into (little + * endian) CPU register. So, the chip expects bytes order to be "B1 B0 B3 B2" + * (while LE is "B0 B1 B2 B3" and BE is "B3 B2 B1 B0") + * + * A little endian host with bits_per_word == 16 should do the right job + * natively. The code below to support big endian host and commonly used SPI + * 8bits. + */ +static int wfx_spi_copy_from_io(void *priv, unsigned int addr, + void *dst, size_t count) +{ + struct wfx_spi_priv *bus = priv; + u16 regaddr = (addr << 12) | (count / 2) | SET_READ; + struct spi_message m; + struct spi_transfer t_addr = { + .tx_buf = ®addr, + .len = sizeof(regaddr), + }; + struct spi_transfer t_msg = { + .rx_buf = dst, + .len = count, + }; + u16 *dst16 = dst; + int ret, i; + + WARN(count % 2, "buffer size must be a multiple of 2"); + + cpu_to_le16s(®addr); + if (bus->need_swab) + swab16s(®addr); + + spi_message_init(&m); + spi_message_add_tail(&t_addr, &m); + spi_message_add_tail(&t_msg, &m); + ret = spi_sync(bus->func, &m); + + if (bus->need_swab && addr == WFX_REG_CONFIG) + for (i = 0; i < count / 2; i++) + swab16s(&dst16[i]); + return ret; +} + +static int wfx_spi_copy_to_io(void *priv, unsigned int addr, + const void *src, size_t count) +{ + struct wfx_spi_priv *bus = priv; + u16 regaddr = (addr << 12) | (count / 2); + /* FIXME: use a bounce buffer */ + u16 *src16 = (void *)src; + int ret, i; + struct spi_message m; + struct spi_transfer t_addr = { + .tx_buf = ®addr, + .len = sizeof(regaddr), + }; + struct spi_transfer t_msg = { + .tx_buf = src, + .len = count, + }; + + WARN(count % 2, "buffer size must be a multiple of 2"); + WARN(regaddr & SET_READ, "bad addr or size overflow"); + + cpu_to_le16s(®addr); + + /* Register address and CONFIG content always use 16bit big endian + * ("BADC" order) + */ + if (bus->need_swab) + swab16s(®addr); + if (bus->need_swab && addr == WFX_REG_CONFIG) + for (i = 0; i < count / 2; i++) + swab16s(&src16[i]); + + spi_message_init(&m); + spi_message_add_tail(&t_addr, &m); + spi_message_add_tail(&t_msg, &m); + ret = spi_sync(bus->func, &m); + + if (bus->need_swab && addr == WFX_REG_CONFIG) + for (i = 0; i < count / 2; i++) + swab16s(&src16[i]); + return ret; +} + +static void wfx_spi_lock(void *priv) +{ +} + +static void wfx_spi_unlock(void *priv) +{ +} + +static irqreturn_t wfx_spi_irq_handler(int irq, void *priv) +{ + struct wfx_spi_priv *bus = priv; + + wfx_bh_request_rx(bus->core); + return IRQ_HANDLED; +} + +static int wfx_spi_irq_subscribe(void *priv) +{ + struct wfx_spi_priv *bus = priv; + u32 flags; + + flags = irq_get_trigger_type(bus->func->irq); + if (!flags) + flags = IRQF_TRIGGER_HIGH; + flags |= IRQF_ONESHOT; + return devm_request_threaded_irq(&bus->func->dev, bus->func->irq, NULL, + wfx_spi_irq_handler, IRQF_ONESHOT, + "wfx", bus); +} + +static int wfx_spi_irq_unsubscribe(void *priv) +{ + struct wfx_spi_priv *bus = priv; + + devm_free_irq(&bus->func->dev, bus->func->irq, bus); + return 0; +} + +static size_t wfx_spi_align_size(void *priv, size_t size) +{ + /* Most of SPI controllers avoid DMA if buffer size is not 32bit aligned + */ + return ALIGN(size, 4); +} + +static const struct hwbus_ops wfx_spi_hwbus_ops = { + .copy_from_io = wfx_spi_copy_from_io, + .copy_to_io = wfx_spi_copy_to_io, + .irq_subscribe = wfx_spi_irq_subscribe, + .irq_unsubscribe = wfx_spi_irq_unsubscribe, + .lock = wfx_spi_lock, + .unlock = wfx_spi_unlock, + .align_size = wfx_spi_align_size, +}; + +static int wfx_spi_probe(struct spi_device *func) +{ + struct wfx_spi_priv *bus; + int ret; + + if (!func->bits_per_word) + func->bits_per_word = 16; + ret = spi_setup(func); + if (ret) + return ret; + /* Trace below is also displayed by spi_setup() if compiled with DEBUG */ + dev_dbg(&func->dev, "SPI params: CS=%d, mode=%d bits/word=%d speed=%d\n", + func->chip_select, func->mode, func->bits_per_word, + func->max_speed_hz); + if (func->bits_per_word != 16 && func->bits_per_word != 8) + dev_warn(&func->dev, "unusual bits/word value: %d\n", + func->bits_per_word); + if (func->max_speed_hz > 50000000) + dev_warn(&func->dev, "%dHz is a very high speed\n", + func->max_speed_hz); + + bus = devm_kzalloc(&func->dev, sizeof(*bus), GFP_KERNEL); + if (!bus) + return -ENOMEM; + bus->func = func; + if (func->bits_per_word == 8 || IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + bus->need_swab = true; + spi_set_drvdata(func, bus); + + bus->gpio_reset = devm_gpiod_get_optional(&func->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(bus->gpio_reset)) + return PTR_ERR(bus->gpio_reset); + if (!bus->gpio_reset) { + dev_warn(&func->dev, + "gpio reset is not defined, trying to load firmware anyway\n"); + } else { + gpiod_set_consumer_name(bus->gpio_reset, "wfx reset"); + if (spi_get_device_id(func)->driver_data & WFX_RESET_INVERTED) + gpiod_toggle_active_low(bus->gpio_reset); + gpiod_set_value_cansleep(bus->gpio_reset, 1); + usleep_range(100, 150); + gpiod_set_value_cansleep(bus->gpio_reset, 0); + usleep_range(2000, 2500); + } + + bus->core = wfx_init_common(&func->dev, &wfx_spi_pdata, + &wfx_spi_hwbus_ops, bus); + if (!bus->core) + return -EIO; + + return wfx_probe(bus->core); +} + +static int wfx_spi_remove(struct spi_device *func) +{ + struct wfx_spi_priv *bus = spi_get_drvdata(func); + + wfx_release(bus->core); + return 0; +} + +/* For dynamic driver binding, kernel does not use OF to match driver. It only + * use modalias and modalias is a copy of 'compatible' DT node with vendor + * stripped. + */ +static const struct spi_device_id wfx_spi_id[] = { + { "wfx-spi", WFX_RESET_INVERTED }, + { "wf200", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, wfx_spi_id); + +#ifdef CONFIG_OF +static const struct of_device_id wfx_spi_of_match[] = { + { .compatible = "silabs,wfx-spi", .data = (void *)WFX_RESET_INVERTED }, + { .compatible = "silabs,wf200" }, + { }, +}; +MODULE_DEVICE_TABLE(of, wfx_spi_of_match); +#endif + +struct spi_driver wfx_spi_driver = { + .driver = { + .name = "wfx-spi", + .of_match_table = of_match_ptr(wfx_spi_of_match), + }, + .id_table = wfx_spi_id, + .probe = wfx_spi_probe, + .remove = wfx_spi_remove, +}; From patchwork Mon Sep 20 16:11:20 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: 12505911 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 50CC3C433FE for ; Mon, 20 Sep 2021 16:14:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3D00D60F58 for ; Mon, 20 Sep 2021 16:14:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243617AbhITQQN (ORCPT ); Mon, 20 Sep 2021 12:16:13 -0400 Received: from mail-dm6nam12on2045.outbound.protection.outlook.com ([40.107.243.45]:61920 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242407AbhITQNw (ORCPT ); Mon, 20 Sep 2021 12:13:52 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ADs00xBAQRAj+tiFlrfsP0ZmzOsxn/ox+TDwq9p3tSsWGqwGobkzdhOc/fNrIrmH7jrcdzmCCSv02ghSo2iB33wG1V0zfIC+Z9M13zB2Dz3yK/p5sBIJ2llk8M2U61hm8VuoBy107JARz+4VOK0w4EkoR5FXPOyjtkZ7c4h336QOxxu4Xf18h8R/swPOAJdFF5cMOcWU14QTMb28HgqykqM/t5OYVdYJS7W+tbL3qTj7/jkuB9fEY8jQKBtlP6420TGCzI7V9GHRU7kRpUjUuWZTGI1xjdHZ/n2Zl8lpQz1XNX6dG6XcZL6ahh7ZgR18usoOQE0YOvgxRdv/g86f3w== 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=xmd7SUjoSEyeOiv4CDsasXGm1X8plGvXuvoFzyTPzWI=; b=GaCzUjUdFMbt+/H6mF8HBY8e01XnqaMuOQdEJjxOr1PHEyXfl/0hxvhy/lfyNF3wN09hzUyP6V+/tjgXf+sfgVofXbrluM9+XbsvNxpL5yhwCUaA6nqbD7d25qCIodNf5fMOfwFwCjZmuECF8q5IwyB1pJglEKugwCwhcEmvFMsJ5IDNBaQ35GksnroRUzocvakdJ/JOb9NcfnCDSBVrU+phEhD3C5Ur57kgPhFJ71egVMVEcRMvic42IJb5kiqBJ2SX7AdxE63cAB9v28YWivpU/TGcooWWQovSJk0eywq4UT6Z7oeTOH2LHMNucgR47vQQCVsPRpL7uePjQt2SyA== 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=xmd7SUjoSEyeOiv4CDsasXGm1X8plGvXuvoFzyTPzWI=; b=F9OZpj3oWdHKkaCLkUl2512Q/DK5cLDufABNvCuytPSCzRd+DBkGc67f2pisaE6fjTBlNEIkSJ/uG4c+RJfSXwXcVd8zVjeE+jh/HfmibKgByM0FXUp0xYgiLzMIqs1rgmu5zyQPy69r4VyiQfSJBAAGoyd5lieZPZa1VelJXBI= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:13 +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:13 +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 08/24] wfx: add bus_sdio.c Date: Mon, 20 Sep 2021 18:11:20 +0200 Message-Id: <20210920161136.2398632-9-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:10 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0d202181-b998-4321-eb8f-08d97c5167f3 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3968; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 5T/g3h2CV41NvybzkZPgiEexmnN+vyEp6EQXVOPWFiAWZv5hFKsbFkQqLzF5ZYG4OKmXLus9ekh9ox7qLe6Bdwuca+LsttCzxhVVl1WmQ4QMnUSHsp46PcmaNECUD5zJ6K9E1IgClvw/WJOx00NeGiQkVCQLpumuabD57JQhjId3vpEqaoqCsmxuaFrr+Jtxm2L2FLixz8CxvMYO8v2DEYBCWUi1gBYaomfYDELoQ0uHaEaxmjpyqyrwBVRW9jks3zC2Ntd3xxcnuSW2kKaVWQqm4hFwvuxcNhDvllLrbn1q6vCqdMdZvUiuAMXmpXc6QrssfZ3ucSnJtSiG+tj0uVt4ufOwU5NylqssQQevjrYQSB5EF/57sI8gHbneTH6fp1aQrtCHTZ7hgpg7fSrFaabveVvAM5J7geqPRuMEc1XZvR8oq64YoFlA92iFUzpZS3iRYcDpN1lUdijQ9F3guOTwQkKDSbYBPmjYlsb3oHwOuFLn65a6Ar4uHiNHViIOHPkDETGnOEog7MSMmK04jDBMcRXhRtMugwobwjRXCcUgRltY9qY07cieokiopDoJ/ixbe+9aaPegiDq3eka8uE5m/0a4wtUdhMohIHsOCcRWN8/Gw6iHAgE47fB1gs1+3au++H2nvNsk3DPVywnsWw== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: Vq8nJjddZvPufEMX6w5He5Fei9WUb4uENKsatcF+cBjrI3LesH4Ry8VKyKgl5YGmkyaCAc8k7q+9L2in/1iHT7xlA+x15JhBcY5BWOCx7ibhsA7ihIU+E/KmB7xdD9YeqrqlQLz27KfKiSH5wU7Zliicwbb1f0utqgUXhFpBN7Wvcgow42I2eHQHLkeqO/grTNd9Aey4MGm2w20jMQ+fkzb+VcDO3oxleItXKZx93CjCQxEpGSsaWQ5LstWlAJtcrutWd8Cs/SKfTqZead4NObQhBkzI72zy0VCLQyVBDg01FQUX0ONBKm/pg0psXm1MRalzTqh4uTrAEVX5s8Gp9RIvtgQUy+AR8oN++SyhuF2BegjGM6mTKiXex70QMvLKQSi5QD+xt0d+DNhJJ2+WPUw6v6XaD+PefFWQxEhDIUT0qcAsoINdCcDQMr3TMVkdRL6azfmxMyZ4naCYa86x+ciIGP4jNphIMrJOBOocbrddokxht2y4Ubl20X7AduRVe+6DenQm+kRo61CDJgMurDVtYLTvs3RZenUhm2sIN+4vUmjVQYcW45qEdc2+nrXpJUkCUhdN5eGlAk939zDl/lnXZSlAqOodifkkT4cAWbSxCXw0+3EZa4ka+Ish6MX9k26TjtdGzCsp/PtKt+OZm/GT5yUCoRkntrDqxRsPpTaSO8uvS016FSa2oQaS/U93H2CwztsMXgYveNhf8ai2oXp0RUS507YlD709D/9qjiU1q6Ijh/eV5WFVTvx7CxE4j4Y+rqWQxHdaSWbude17F4AN7SMht1oFR/DzabHa4lgmkef2o9LmlSlDhezeCy5e X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 0d202181-b998-4321-eb8f-08d97c5167f3 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:13.0238 (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: +LiPnag1ZNr3wmmlltyyJ4jhYsb8OY9ZS3H5d8DcBWWpz47edHRzCKmWvCFLGNzkw8d8BUDeM/pc7T18Y3ci8g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/bus_sdio.c | 261 +++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/bus_sdio.c diff --git a/drivers/net/wireless/silabs/wfx/bus_sdio.c b/drivers/net/wireless/silabs/wfx/bus_sdio.c new file mode 100644 index 000000000000..869ecb7d99db --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/bus_sdio.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDIO interface. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bus.h" +#include "wfx.h" +#include "hwio.h" +#include "main.h" +#include "bh.h" + +static const struct wfx_platform_data wfx_sdio_pdata = { + .file_fw = "wfm_wf200", + .file_pds = "wf200.pds", +}; + +struct wfx_sdio_priv { + struct sdio_func *func; + struct wfx_dev *core; + u8 buf_id_tx; + u8 buf_id_rx; + int of_irq; +}; + +static int wfx_sdio_copy_from_io(void *priv, unsigned int reg_id, + void *dst, size_t count) +{ + struct wfx_sdio_priv *bus = priv; + unsigned int sdio_addr = reg_id << 2; + int ret; + + WARN(reg_id > 7, "chip only has 7 registers"); + WARN(((uintptr_t)dst) & 3, "unaligned buffer size"); + WARN(count & 3, "unaligned buffer address"); + + /* Use queue mode buffers */ + if (reg_id == WFX_REG_IN_OUT_QUEUE) + sdio_addr |= (bus->buf_id_rx + 1) << 7; + ret = sdio_memcpy_fromio(bus->func, dst, sdio_addr, count); + if (!ret && reg_id == WFX_REG_IN_OUT_QUEUE) + bus->buf_id_rx = (bus->buf_id_rx + 1) % 4; + + return ret; +} + +static int wfx_sdio_copy_to_io(void *priv, unsigned int reg_id, + const void *src, size_t count) +{ + struct wfx_sdio_priv *bus = priv; + unsigned int sdio_addr = reg_id << 2; + int ret; + + WARN(reg_id > 7, "chip only has 7 registers"); + WARN(((uintptr_t)src) & 3, "unaligned buffer size"); + WARN(count & 3, "unaligned buffer address"); + + /* Use queue mode buffers */ + if (reg_id == WFX_REG_IN_OUT_QUEUE) + sdio_addr |= bus->buf_id_tx << 7; + /* FIXME: discards 'const' qualifier for src */ + ret = sdio_memcpy_toio(bus->func, sdio_addr, (void *)src, count); + if (!ret && reg_id == WFX_REG_IN_OUT_QUEUE) + bus->buf_id_tx = (bus->buf_id_tx + 1) % 32; + + return ret; +} + +static void wfx_sdio_lock(void *priv) +{ + struct wfx_sdio_priv *bus = priv; + + sdio_claim_host(bus->func); +} + +static void wfx_sdio_unlock(void *priv) +{ + struct wfx_sdio_priv *bus = priv; + + sdio_release_host(bus->func); +} + +static void wfx_sdio_irq_handler(struct sdio_func *func) +{ + struct wfx_sdio_priv *bus = sdio_get_drvdata(func); + + wfx_bh_request_rx(bus->core); +} + +static irqreturn_t wfx_sdio_irq_handler_ext(int irq, void *priv) +{ + struct wfx_sdio_priv *bus = priv; + + sdio_claim_host(bus->func); + wfx_bh_request_rx(bus->core); + sdio_release_host(bus->func); + return IRQ_HANDLED; +} + +static int wfx_sdio_irq_subscribe(void *priv) +{ + struct wfx_sdio_priv *bus = priv; + u32 flags; + int ret; + u8 cccr; + + if (!bus->of_irq) { + sdio_claim_host(bus->func); + ret = sdio_claim_irq(bus->func, wfx_sdio_irq_handler); + sdio_release_host(bus->func); + return ret; + } + + flags = irq_get_trigger_type(bus->of_irq); + if (!flags) + flags = IRQF_TRIGGER_HIGH; + flags |= IRQF_ONESHOT; + ret = devm_request_threaded_irq(&bus->func->dev, bus->of_irq, NULL, + wfx_sdio_irq_handler_ext, flags, + "wfx", bus); + if (ret) + return ret; + sdio_claim_host(bus->func); + cccr = sdio_f0_readb(bus->func, SDIO_CCCR_IENx, NULL); + cccr |= BIT(0); + cccr |= BIT(bus->func->num); + sdio_f0_writeb(bus->func, cccr, SDIO_CCCR_IENx, NULL); + sdio_release_host(bus->func); + return 0; +} + +static int wfx_sdio_irq_unsubscribe(void *priv) +{ + struct wfx_sdio_priv *bus = priv; + int ret; + + if (bus->of_irq) + devm_free_irq(&bus->func->dev, bus->of_irq, bus); + sdio_claim_host(bus->func); + ret = sdio_release_irq(bus->func); + sdio_release_host(bus->func); + return ret; +} + +static size_t wfx_sdio_align_size(void *priv, size_t size) +{ + struct wfx_sdio_priv *bus = priv; + + return sdio_align_size(bus->func, size); +} + +static const struct hwbus_ops wfx_sdio_hwbus_ops = { + .copy_from_io = wfx_sdio_copy_from_io, + .copy_to_io = wfx_sdio_copy_to_io, + .irq_subscribe = wfx_sdio_irq_subscribe, + .irq_unsubscribe = wfx_sdio_irq_unsubscribe, + .lock = wfx_sdio_lock, + .unlock = wfx_sdio_unlock, + .align_size = wfx_sdio_align_size, +}; + +static const struct of_device_id wfx_sdio_of_match[] = { + { .compatible = "silabs,wfx-sdio" }, + { .compatible = "silabs,wf200" }, + { }, +}; +MODULE_DEVICE_TABLE(of, wfx_sdio_of_match); + +static int wfx_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + struct device_node *np = func->dev.of_node; + struct wfx_sdio_priv *bus; + int ret; + + if (func->num != 1) { + dev_err(&func->dev, "SDIO function number is %d while it should always be 1 (unsupported chip?)\n", + func->num); + return -ENODEV; + } + + bus = devm_kzalloc(&func->dev, sizeof(*bus), GFP_KERNEL); + if (!bus) + return -ENOMEM; + + if (!np || !of_match_node(wfx_sdio_of_match, np)) { + dev_warn(&func->dev, "no compatible device found in DT\n"); + return -ENODEV; + } + + bus->func = func; + bus->of_irq = irq_of_parse_and_map(np, 0); + sdio_set_drvdata(func, bus); + func->card->quirks |= MMC_QUIRK_LENIENT_FN0 | + MMC_QUIRK_BLKSZ_FOR_BYTE_MODE | + MMC_QUIRK_BROKEN_BYTE_MODE_512; + + sdio_claim_host(func); + ret = sdio_enable_func(func); + /* Block of 64 bytes is more efficient than 512B for frame sizes < 4k */ + sdio_set_block_size(func, 64); + sdio_release_host(func); + if (ret) + return ret; + + bus->core = wfx_init_common(&func->dev, &wfx_sdio_pdata, + &wfx_sdio_hwbus_ops, bus); + if (!bus->core) { + ret = -EIO; + goto sdio_release; + } + + ret = wfx_probe(bus->core); + if (ret) + goto sdio_release; + + return 0; + +sdio_release: + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + return ret; +} + +static void wfx_sdio_remove(struct sdio_func *func) +{ + struct wfx_sdio_priv *bus = sdio_get_drvdata(func); + + wfx_release(bus->core); + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); +} + +static const struct sdio_device_id wfx_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, SDIO_DEVICE_ID_SILABS_WF200) }, + { }, +}; +MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids); + +struct sdio_driver wfx_sdio_driver = { + .name = "wfx-sdio", + .id_table = wfx_sdio_ids, + .probe = wfx_sdio_probe, + .remove = wfx_sdio_remove, + .drv = { + .owner = THIS_MODULE, + .of_match_table = wfx_sdio_of_match, + } +}; From patchwork Mon Sep 20 16:11:21 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: 12505841 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=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 48304C433F5 for ; Mon, 20 Sep 2021 16:12:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 29EB761163 for ; Mon, 20 Sep 2021 16:12:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243084AbhITQOR (ORCPT ); Mon, 20 Sep 2021 12:14:17 -0400 Received: from mail-bn7nam10on2055.outbound.protection.outlook.com ([40.107.92.55]:31296 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242622AbhITQOC (ORCPT ); Mon, 20 Sep 2021 12:14:02 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=n2g64VocaGCNgb4CD0LuhnWwSE5p+DnmTKtNekgQ7ZZtyHO9ZTSRJmsWuqqoB5jya0owtPAtEXOoCwt4Pia8slVESyoQiWm7ueSoEseX4gIFwlu/oRWW3E0J12hrDNOEFL2wvu7vnaz0THUXZ9qD1liVJybZ5m1BPzOq4tdd1li9WmMxNXsFDpqaVeRfyydzaXAxH3mnA8T4H1d5DCeX5+JTDk8Ui3vWwcqhq0l2f/hqHV8O8/2J+GgeKqFceUNSFmJ1SEO709fY00d9WpNBS4pLr79mTyawQVI16exYpzhI6S1q4S+rECppunMJNeZ9xHt71/FBgBnlEzBSBLLtNQ== 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=L1PGQFYwqGncDdlTHJJr+Np/ZfkOZwxSjiFSMD2Zj+E=; b=GVV1F/3gpYCPIJTkKwHTTupBym147PeiMqWyJxI35rkBS5l84yKTtxz19nhWNpmUo3B3hxStdjIK9t6rlCb1GmXZJ1aHkHYhw8V4ZAnI2//gAxXSR34nC4QkmXTEYR+L5eBAFuw+zuqArkoTKUrgmyzSU6eAR6BSP1WR341l/q5IH9Opl7B7U3WabFudSYqjNhJMpmSfRsxm1scPP0flWYYPnm6JbenEgr3OQwO7NBUauthfQ4o8gLu+5YisqRDq8tj+Rjs+t9cxsF3vDzRAQ49OIE2rZ0KcB1bO4D2Mqf1DJG9Y56cg8Z3HSGOpeGPrjszwS1HvCcVRXFPuf3Y4Kw== 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=L1PGQFYwqGncDdlTHJJr+Np/ZfkOZwxSjiFSMD2Zj+E=; b=K1GUHjPVgACXIZ/+ivY8tj5+KZFOpRAK9dZcYRG6W154GhYaBq181KeyWcGwdEHqpjJs6vwpCODp6qsvIuRrjy2s2KmvVSG71jvgrfwKEK1itcpAoQa/cVKwY07VylQQVYKjAczKnREsTviCBdWcWeB+oUnCriQLatsGHl8widQ= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:15 +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:15 +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 09/24] wfx: add hwio.c/hwio.h Date: Mon, 20 Sep 2021 18:11:21 +0200 Message-Id: <20210920161136.2398632-10-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:13 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: fc9a73be-eb4e-4099-3d5e-08d97c516969 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:561; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 35F+oabE5g0tpcnLFQyGUVNd5c8UOV6GiMqwkW3g4nYb3yhLn4PwtHN5JSqNH/2Mn5xOco3n5Pd1noC+h2ZEJQW8rkNnbudywlEmkvvniSdP7F2qLffDxh0LQnDVUhD6NyW2pKF78PRIHIbx2+mU5XKp5Ck6Oo8giYDUaKAkyMMiVtONYxbwoqk92loa38TrsxZtSo7iE14Tg93XYMuX7ZOmY9UY1ePOz4b2/3CNA46Fa6CIyoTvJ+Wn2vEFaejeSrojGSsOMISJq4juLlyaG3eWP3qynBbqE0A5t754Cjy8dz/cHkW5mO+YXnPpTmpasxztS61AhIU7EG/NFt3DzmdnKp2aGioBMYexIN8pUAHD8VGQM8EiySfUxRgvfiOhw9vtorcYJnIcq29VxCGA6vqB773hplcfTmapt9gxlyNpIfpSOGhNXYQ7V0NdxSyTosnVv0GUeCmlOifiVGcc7IsQeOSQnfnI3kQeFuV6YqTlJ7dmggzD/9SmO53tBHvi14L9RNbVJ4ec7mxsd/3MW3Sw01UGjG+GC6uwOExaU0Q6oDPB7AJ+Ltcyd04ZsNbXyZ8ELdScuOh9BQYUY5sSsc9E3rzRHdcrvuNGk1Hz+MP25+I2hNDroAZnNiKPKIT00cfhUlURHHpmRtF0owyzdg== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(30864003)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: JT1QHXJCufY6NSQXEMMwHrHS6kuw9P3YFkBo+zxcZmI3hZDcOi4PPpSXpK/VC1T/tDO5Otef84Eaie8ez/rnkkVEkkaDuJr7ID5jWuuB9ZLYc4HwOujiwtVHNHsX67HRyDcFTgx3Ce49ywK07rFa/ZuiOh08F/EPdwk/fOoelCwymxLuGJE1RLMa0sFZW31ArVL3vkOH7f+TwC4lqTE99eB4Zxa3JT6FBQKu3ai2OqGb+QUnfZktMRJRtCkRVQXDkxRGuAkqRyHyTGgi0XTeajhbCvpWyPXA0szwdV+xBJ4slxOSiAFRPfu1Yy4oaJnGkJBc0Sdyc9mO1HNbsKlRIEGz2Z29msygyncGRKHZyf2BV2zelFDLSATfK8g04vEl0KX3GZyKJsgsEO7QYh6DK4oY21BfX5Aefw0dRVGu/kFw/fU4SR2mStCzQJJR25IoyIY1bCTGQwM0iR2LUpdwTHeIRPer5kCnalBYyUYhSpHe6pngWCf2p9d0hOR4YvNx6pHCmNipcOJfEyjBurCIlqF/n4p33brayuECxKTK9UCeAvS5F3QRLRuugOsLXJzKiVlUPsEfc0Fx0bi4Q+xZpspuVR42sBeZp80NoVZHxVEcqHJMgtxzUB60EjpGMJ8qDZ3GQ8Ywpo7xbfdvtPnBtTedUwvKfaIFzG6KAf+8GID+M0AzLsyZmsMnlxT85bXlOoUlr0PNuM5pCtYhnNiuZvJz2vuE4jcC7R1+RNm8AFsCc8gzW/iB6U+/7rmt4f1dQnLPcwysO1D9wyokuJMxevK6jSUK4oof3NgsZvzT932zMbhUmBMiqkl+Lyo5Cs1X X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: fc9a73be-eb4e-4099-3d5e-08d97c516969 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:15.4584 (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: LiuQURjEO0hPFOMsXbUoZ5UaSyguDJWTW2brIN6/RVx31E2mERE2sEclB6FuWWyxGcJk/nOtmJULE0UKV/4myA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/hwio.c | 340 +++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/hwio.h | 79 ++++++ 2 files changed, 419 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/hwio.c create mode 100644 drivers/net/wireless/silabs/wfx/hwio.h diff --git a/drivers/net/wireless/silabs/wfx/hwio.c b/drivers/net/wireless/silabs/wfx/hwio.c new file mode 100644 index 000000000000..393bcb1e2f4e --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hwio.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Low-level I/O functions. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include +#include + +#include "hwio.h" +#include "wfx.h" +#include "bus.h" +#include "traces.h" + +static int read32(struct wfx_dev *wdev, int reg, u32 *val) +{ + int ret; + __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); + + *val = ~0; /* Never return undefined value */ + if (!tmp) + return -ENOMEM; + ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp, + sizeof(u32)); + if (ret >= 0) + *val = le32_to_cpu(*tmp); + kfree(tmp); + if (ret) + dev_err(wdev->dev, "%s: bus communication error: %d\n", + __func__, ret); + return ret; +} + +static int write32(struct wfx_dev *wdev, int reg, u32 val) +{ + int ret; + __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); + + if (!tmp) + return -ENOMEM; + *tmp = cpu_to_le32(val); + ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp, + sizeof(u32)); + kfree(tmp); + if (ret) + dev_err(wdev->dev, "%s: bus communication error: %d\n", + __func__, ret); + return ret; +} + +static int read32_locked(struct wfx_dev *wdev, int reg, u32 *val) +{ + int ret; + + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = read32(wdev, reg, val); + _trace_io_read32(reg, *val); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + return ret; +} + +static int write32_locked(struct wfx_dev *wdev, int reg, u32 val) +{ + int ret; + + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = write32(wdev, reg, val); + _trace_io_write32(reg, val); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + return ret; +} + +static int write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val) +{ + int ret; + u32 val_r, val_w; + + WARN_ON(~mask & val); + val &= mask; + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = read32(wdev, reg, &val_r); + _trace_io_read32(reg, val_r); + if (ret < 0) + goto err; + val_w = (val_r & ~mask) | val; + if (val_w != val_r) { + ret = write32(wdev, reg, val_w); + _trace_io_write32(reg, val_w); + } +err: + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + return ret; +} + +static int indirect_read(struct wfx_dev *wdev, int reg, u32 addr, + void *buf, size_t len) +{ + int ret; + int i; + u32 cfg; + u32 prefetch; + + WARN_ON(len >= 0x2000); + WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT); + + if (reg == WFX_REG_AHB_DPORT) + prefetch = CFG_PREFETCH_AHB; + else if (reg == WFX_REG_SRAM_DPORT) + prefetch = CFG_PREFETCH_SRAM; + else + return -ENODEV; + + ret = write32(wdev, WFX_REG_BASE_ADDR, addr); + if (ret < 0) + goto err; + + ret = read32(wdev, WFX_REG_CONFIG, &cfg); + if (ret < 0) + goto err; + + ret = write32(wdev, WFX_REG_CONFIG, cfg | prefetch); + if (ret < 0) + goto err; + + for (i = 0; i < 20; i++) { + ret = read32(wdev, WFX_REG_CONFIG, &cfg); + if (ret < 0) + goto err; + if (!(cfg & prefetch)) + break; + usleep_range(200, 250); + } + if (i == 20) { + ret = -ETIMEDOUT; + goto err; + } + + ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len); + +err: + if (ret < 0) + memset(buf, 0xFF, len); /* Never return undefined value */ + return ret; +} + +static int indirect_write(struct wfx_dev *wdev, int reg, u32 addr, + const void *buf, size_t len) +{ + int ret; + + WARN_ON(len >= 0x2000); + WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT); + ret = write32(wdev, WFX_REG_BASE_ADDR, addr); + if (ret < 0) + return ret; + + return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len); +} + +static int indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr, + void *buf, size_t len) +{ + int ret; + + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = indirect_read(wdev, reg, addr, buf, len); + _trace_io_ind_read(reg, addr, buf, len); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + return ret; +} + +static int indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr, + const void *buf, size_t len) +{ + int ret; + + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = indirect_write(wdev, reg, addr, buf, len); + _trace_io_ind_write(reg, addr, buf, len); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + return ret; +} + +static int indirect_read32_locked(struct wfx_dev *wdev, int reg, + u32 addr, u32 *val) +{ + int ret; + __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); + + if (!tmp) + return -ENOMEM; + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = indirect_read(wdev, reg, addr, tmp, sizeof(u32)); + *val = le32_to_cpu(*tmp); + _trace_io_ind_read32(reg, addr, *val); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + kfree(tmp); + return ret; +} + +static int indirect_write32_locked(struct wfx_dev *wdev, int reg, + u32 addr, u32 val) +{ + int ret; + __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); + + if (!tmp) + return -ENOMEM; + *tmp = cpu_to_le32(val); + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = indirect_write(wdev, reg, addr, tmp, sizeof(u32)); + _trace_io_ind_write32(reg, addr, val); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + kfree(tmp); + return ret; +} + +int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len) +{ + int ret; + + WARN((long)buf & 3, "%s: unaligned buffer", __func__); + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, + WFX_REG_IN_OUT_QUEUE, buf, len); + _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + if (ret) + dev_err(wdev->dev, "%s: bus communication error: %d\n", + __func__, ret); + return ret; +} + +int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len) +{ + int ret; + + WARN((long)buf & 3, "%s: unaligned buffer", __func__); + wdev->hwbus_ops->lock(wdev->hwbus_priv); + ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, + WFX_REG_IN_OUT_QUEUE, buf, len); + _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len); + wdev->hwbus_ops->unlock(wdev->hwbus_priv); + if (ret) + dev_err(wdev->dev, "%s: bus communication error: %d\n", + __func__, ret); + return ret; +} + +int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len) +{ + return indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len); +} + +int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len) +{ + return indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len); +} + +int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len) +{ + return indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len); +} + +int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len) +{ + return indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len); +} + +int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val) +{ + return indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val); +} + +int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val) +{ + return indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val); +} + +int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val) +{ + return indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val); +} + +int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val) +{ + return indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val); +} + +int config_reg_read(struct wfx_dev *wdev, u32 *val) +{ + return read32_locked(wdev, WFX_REG_CONFIG, val); +} + +int config_reg_write(struct wfx_dev *wdev, u32 val) +{ + return write32_locked(wdev, WFX_REG_CONFIG, val); +} + +int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val) +{ + return write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val); +} + +int control_reg_read(struct wfx_dev *wdev, u32 *val) +{ + return read32_locked(wdev, WFX_REG_CONTROL, val); +} + +int control_reg_write(struct wfx_dev *wdev, u32 val) +{ + return write32_locked(wdev, WFX_REG_CONTROL, val); +} + +int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val) +{ + return write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val); +} + +int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val) +{ + int ret; + + *val = ~0; /* Never return undefined value */ + ret = write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24); + if (ret) + return ret; + ret = read32_locked(wdev, WFX_REG_SET_GEN_R_W, val); + if (ret) + return ret; + *val &= IGPR_VALUE; + return ret; +} + +int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val) +{ + return write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val); +} diff --git a/drivers/net/wireless/silabs/wfx/hwio.h b/drivers/net/wireless/silabs/wfx/hwio.h new file mode 100644 index 000000000000..d34baae47017 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hwio.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Low-level I/O functions. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_HWIO_H +#define WFX_HWIO_H + +#include + +struct wfx_dev; + +/* Caution: in the functions below, 'buf' will used with a DMA. So, it must be + * kmalloc'd (do not use stack allocated buffers). In doubt, enable + * CONFIG_DEBUG_SG to detect badly located buffer. + */ +int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t buf_len); +int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t buf_len); + +int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len); +int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len); + +int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len); +int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len); + +int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val); +int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val); + +int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val); +int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val); + +#define CFG_ERR_SPI_FRAME 0x00000001 /* only with SPI */ +#define CFG_ERR_SDIO_BUF_MISMATCH 0x00000001 /* only with SDIO */ +#define CFG_ERR_BUF_UNDERRUN 0x00000002 +#define CFG_ERR_DATA_IN_TOO_LARGE 0x00000004 +#define CFG_ERR_HOST_NO_OUT_QUEUE 0x00000008 +#define CFG_ERR_BUF_OVERRUN 0x00000010 +#define CFG_ERR_DATA_OUT_TOO_LARGE 0x00000020 +#define CFG_ERR_HOST_NO_IN_QUEUE 0x00000040 +#define CFG_ERR_HOST_CRC_MISS 0x00000080 /* only with SDIO */ +#define CFG_SPI_IGNORE_CS 0x00000080 /* only with SPI */ +#define CFG_BYTE_ORDER_MASK 0x00000300 /* only writable with SPI */ +#define CFG_BYTE_ORDER_BADC 0x00000000 +#define CFG_BYTE_ORDER_DCBA 0x00000100 +#define CFG_BYTE_ORDER_ABCD 0x00000200 /* SDIO always use this value */ +#define CFG_DIRECT_ACCESS_MODE 0x00000400 +#define CFG_PREFETCH_AHB 0x00000800 +#define CFG_DISABLE_CPU_CLK 0x00001000 +#define CFG_PREFETCH_SRAM 0x00002000 +#define CFG_CPU_RESET 0x00004000 +#define CFG_SDIO_DISABLE_IRQ 0x00008000 /* only with SDIO */ +#define CFG_IRQ_ENABLE_DATA 0x00010000 +#define CFG_IRQ_ENABLE_WRDY 0x00020000 +#define CFG_CLK_RISE_EDGE 0x00040000 +#define CFG_SDIO_DISABLE_CRC_CHK 0x00080000 /* only with SDIO */ +#define CFG_RESERVED 0x00F00000 +#define CFG_DEVICE_ID_MAJOR 0x07000000 +#define CFG_DEVICE_ID_RESERVED 0x78000000 +#define CFG_DEVICE_ID_TYPE 0x80000000 +int config_reg_read(struct wfx_dev *wdev, u32 *val); +int config_reg_write(struct wfx_dev *wdev, u32 val); +int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val); + +#define CTRL_NEXT_LEN_MASK 0x00000FFF +#define CTRL_WLAN_WAKEUP 0x00001000 +#define CTRL_WLAN_READY 0x00002000 +int control_reg_read(struct wfx_dev *wdev, u32 *val); +int control_reg_write(struct wfx_dev *wdev, u32 val); +int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val); + +#define IGPR_RW 0x80000000 +#define IGPR_INDEX 0x7F000000 +#define IGPR_VALUE 0x00FFFFFF +int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val); +int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val); + +#endif From patchwork Mon Sep 20 16:11:22 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: 12505849 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 AE711C433EF for ; Mon, 20 Sep 2021 16:13:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9731860F58 for ; Mon, 20 Sep 2021 16:13:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242931AbhITQO4 (ORCPT ); Mon, 20 Sep 2021 12:14:56 -0400 Received: from mail-dm6nam12on2045.outbound.protection.outlook.com ([40.107.243.45]:61920 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242946AbhITQOK (ORCPT ); Mon, 20 Sep 2021 12:14:10 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OllwQfcteoKFqTCvawRCX68C4BcdSwMPL+P5k8Gr4HVbt07P3iv+WBBOk+OkMWK5ucwhzDcp+hRn1HUg/gq5ZhXEbkRxfTJyw+3asT48NlYdEdklOW1gMOm2ghRjSlKWZw/G63ziJovFlMSP74fBRf2VcIoMrcJBn0h9xqBhtPCTUXHZV30prfrCFWtSg846yOh8S7q9d06GfUWHh60ql3ZQOTYDxo3sYVnlRoVtH5KOLQ6v4FZc0y12ODvUPqmrj88THb2/udEzKnOuYWzhpSfFic52czXAw/jl2zu2swmT40Au7Pjw6UrxW7aSgWK7fRVuaRCIYrPT9pEyg5OKXg== 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=fcEwwc3i6agT46bOKiI8eUhDKxo9lKyrYIMHtt/BQts=; b=kekbJNZe5LXkSzEjJyMejrF8Cd7EpH9OAP5OT+KFvn3IelRPq40yWvRzPXSh1FW/DkSMRl3k/NWpol9EApKU5ZKywTo2V7dhS4O04itLdCNKTePDZS8Qsqq5VGsp0tDyOm/beAVb6G1BzXnyhhPHcP/lI/ubd5lSPyTNEtM5WUzdt+VED9PXtjFDhOpZpvJgNfNlf6tJmdh+G3cX35Ubu7dmJbqa1QEbEJuBwa9WqfBIK5dxsMwKWHvQGInHSoMAmysy7WinMh1D1l3vsKxY0pvB5nVCVXwkGvX12mDbDCFSTlWG6D6oRZvMJ2lQ0VFeIiptW435Kmqo91G1aKL3rw== 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=fcEwwc3i6agT46bOKiI8eUhDKxo9lKyrYIMHtt/BQts=; b=jwdzrD2sQWY347TDddC6Vys1mzHvPAhsVJdId+GhB+kzpV3XT5WtN5aHka5ldOo4S+Xmr6Y8CDFH8hwqEmWlilhlfhHK6a1RhpsxLTbDdHsjI1/VeFA+rzPo6+7Nd2XDy0ndbhar63hYWVqlhR0y6m3RMKejC1KPlEX29cCJqKY= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:18 +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:18 +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 10/24] wfx: add fwio.c/fwio.h Date: Mon, 20 Sep 2021 18:11:22 +0200 Message-Id: <20210920161136.2398632-11-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:15 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 36f90ad7-7a9e-4cab-2c04-08d97c516ad6 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:1122; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Lq5thWUJkZZm9qjiBnYBuayVIbPM0FIbMdJBbv91XlhBuoJWahJV/s02SUm5C9KGULh8e9ylYa1L8BB1jlVhdu9m1MdvHOhOMuPukv8foTCNfxYBElmk+wQJT7J6SRSflliM8SSfbaPwNQLC4DR0vLFP1GoIadEH+ZHFKcY5sy6T9FuX8tzIVSlRUcABtV3ZPA5VhHuhB4PC+V4omZr0VIwNhdElTH8Q9lTlFOlqeDjSawnOTiu7QNL7AdBWMMAk6tG/mvMPxsNRIcyKAeO9SgcA8JWxUNYIDXilEpYn7qc2JL7RvybkcOFUjgGq5+Ks0ku2/P8yO9T7AjyWijt8TZiB+QjgJ71jYeFoo+7ZcifWbwJTZvHFpF/kgUfs9Qf2yea1g/dGyRD83Eu4xAcvzNLVEFD008vS3EKPYcKomwNRpie8P/HhEOIkv2rVrXBEyAbJVjVbE6WoigckKeEwVP+CGYX4ZX2P7I8oAMbHFvqSldta1ZfXnOmCEXBSFNaqnNKc/fJ5CRUpVUgyMnRjD2kVlb4TW//EWkrAsDdNc8hf8vMFgDseDRvjHVhp2bMoUb30ABa+ufVfOBkh+RStfXVNoWOxTLcom+xHxtByF8jsUSOpZvE0MAeipVLc9wGya8bEq2HsCjG6Df9FuRf5rA== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(30864003)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: N9iDkwz5rFSY596UB6pmvEdqI68HAsLpYR74qhV8PchNiBOO4TYXgFS7mHu+VkMjOMI5CsyzMAX7Fll839PK6hG0P/HB6MTK2fmdrToFk2rmWRKMxWNBGcFRd/bwdigX//Cxd3k9NqYSSEHEAqlBZdcoIogkqEiFFBOvCAvkZq5PrKYwUujQwjpcRGFsW6leJFFAPzavqSFAHgoWPjJUOWjyvU/daU4lE3IPFnDOGxFlaUSaFp8ZqEUT993W4L0BWq/1rTfBSFovsZXOdQJOzQbP7cE5l9gVFiNBTmG4yEHlgkNuI64wnqKaRp5fph9tFP219IfcWbDGWgCW8if3Vnq0joHrzgN3RUzODzRUaUl4ywR994L3NDyht2Bv6jxsCozmfrr83KinicyMXAOus5Fl9ELYnfV5dH5mIpns8yOXTmdfSR84iF6hyFmX6qY5PTsRua6LUwy/Lw44MdwctNSL89UveEJ1UMdf9prTwMGyH+/XBdbcSkKcf4U+WSWVYKLD+6doMP4XKGDIIXbUNj5ZuN0UGObd0rP/P4dQGW+gNtPar/qMblKlol/0XzlAAzlAifpAhokxA4KKG+jdmyzNFLUvsc4V3D8uOUULybTAeA7uoYyV4+hLeldsSGzevS+gNzV81XBR6a89c/12RFdtiDYw4pyPMLY+lKYmo/N04RgiNJhtJwm2dhjC+kobnO6DTY/hSq+yNjHBrn3Ljwuue+sdyJJNopAlH7ghWGrK0LHIo+/l2Q3g7ybsuvY/VDR2QeBAsy+6Nzrn1JCiP5n14ZVG++F5xpTA39AB+V9UWFfuL/gOMvXEOM+9A2x4 X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 36f90ad7-7a9e-4cab-2c04-08d97c516ad6 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:17.8700 (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: cXFtK4zO3sC4z2Qv30Qa30YHSho48O6Kqb1FDDsK5utrnBxNxP8WFWj1ndRESJ0DxEiGaERpixTTxdMmQ3nUzQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/fwio.c | 405 +++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/fwio.h | 15 + 2 files changed, 420 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/fwio.c create mode 100644 drivers/net/wireless/silabs/wfx/fwio.h diff --git a/drivers/net/wireless/silabs/wfx/fwio.c b/drivers/net/wireless/silabs/wfx/fwio.c new file mode 100644 index 000000000000..98a9391b2bee --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/fwio.c @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Firmware loading. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include +#include +#include + +#include "fwio.h" +#include "wfx.h" +#include "hwio.h" + +/* Addresses below are in SRAM area */ +#define WFX_DNLD_FIFO 0x09004000 +#define DNLD_BLOCK_SIZE 0x0400 +#define DNLD_FIFO_SIZE 0x8000 /* (32 * DNLD_BLOCK_SIZE) */ +/* Download Control Area (DCA) */ +#define WFX_DCA_IMAGE_SIZE 0x0900C000 +#define WFX_DCA_PUT 0x0900C004 +#define WFX_DCA_GET 0x0900C008 +#define WFX_DCA_HOST_STATUS 0x0900C00C +#define HOST_READY 0x87654321 +#define HOST_INFO_READ 0xA753BD99 +#define HOST_UPLOAD_PENDING 0xABCDDCBA +#define HOST_UPLOAD_COMPLETE 0xD4C64A99 +#define HOST_OK_TO_JUMP 0x174FC882 +#define WFX_DCA_NCP_STATUS 0x0900C010 +#define NCP_NOT_READY 0x12345678 +#define NCP_READY 0x87654321 +#define NCP_INFO_READY 0xBD53EF99 +#define NCP_DOWNLOAD_PENDING 0xABCDDCBA +#define NCP_DOWNLOAD_COMPLETE 0xCAFEFECA +#define NCP_AUTH_OK 0xD4C64A99 +#define NCP_AUTH_FAIL 0x174FC882 +#define NCP_PUB_KEY_RDY 0x7AB41D19 +#define WFX_DCA_FW_SIGNATURE 0x0900C014 +#define FW_SIGNATURE_SIZE 0x40 +#define WFX_DCA_FW_HASH 0x0900C054 +#define FW_HASH_SIZE 0x08 +#define WFX_DCA_FW_VERSION 0x0900C05C +#define FW_VERSION_SIZE 0x04 +#define WFX_DCA_RESERVED 0x0900C060 +#define DCA_RESERVED_SIZE 0x20 +#define WFX_STATUS_INFO 0x0900C080 +#define WFX_BOOTLOADER_LABEL 0x0900C084 +#define BOOTLOADER_LABEL_SIZE 0x3C +#define WFX_PTE_INFO 0x0900C0C0 +#define PTE_INFO_KEYSET_IDX 0x0D +#define PTE_INFO_SIZE 0x10 +#define WFX_ERR_INFO 0x0900C0D0 +#define ERR_INVALID_SEC_TYPE 0x05 +#define ERR_SIG_VERIF_FAILED 0x0F +#define ERR_AES_CTRL_KEY 0x10 +#define ERR_ECC_PUB_KEY 0x11 +#define ERR_MAC_KEY 0x18 + +#define DCA_TIMEOUT 50 /* milliseconds */ +#define WAKEUP_TIMEOUT 200 /* milliseconds */ + +static const char * const fwio_errors[] = { + [ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption", + [ERR_SIG_VERIF_FAILED] = "Signature verification failed", + [ERR_AES_CTRL_KEY] = "AES control key not initialized", + [ERR_ECC_PUB_KEY] = "ECC public key not initialized", + [ERR_MAC_KEY] = "MAC key not initialized", +}; + +/* request_firmware() allocate data using vmalloc(). It is not compatible with + * underlying hardware that use DMA. Function below detect this case and + * allocate a bounce buffer if necessary. + * + * Notice that, in doubt, you can enable CONFIG_DEBUG_SG to ask kernel to + * detect this problem at runtime (else, kernel silently fail). + * + * NOTE: it may also be possible to use 'pages' from struct firmware and avoid + * bounce buffer + */ +static int sram_write_dma_safe(struct wfx_dev *wdev, u32 addr, const u8 *buf, + size_t len) +{ + int ret; + const u8 *tmp; + + if (!virt_addr_valid(buf)) { + tmp = kmemdup(buf, len, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + } else { + tmp = buf; + } + ret = sram_buf_write(wdev, addr, tmp, len); + if (tmp != buf) + kfree(tmp); + return ret; +} + +static int get_firmware(struct wfx_dev *wdev, u32 keyset_chip, + const struct firmware **fw, int *file_offset) +{ + int keyset_file; + char filename[256]; + const char *data; + int ret; + + snprintf(filename, sizeof(filename), "%s_%02X.sec", + wdev->pdata.file_fw, keyset_chip); + ret = firmware_request_nowarn(fw, filename, wdev->dev); + if (ret) { + dev_info(wdev->dev, "can't load %s, falling back to %s.sec\n", + filename, wdev->pdata.file_fw); + snprintf(filename, sizeof(filename), "%s.sec", + wdev->pdata.file_fw); + ret = request_firmware(fw, filename, wdev->dev); + if (ret) { + dev_err(wdev->dev, "can't load %s\n", filename); + *fw = NULL; + return ret; + } + } + + data = (*fw)->data; + if (memcmp(data, "KEYSET", 6) != 0) { + /* Legacy firmware format */ + *file_offset = 0; + keyset_file = 0x90; + } else { + *file_offset = 8; + keyset_file = (hex_to_bin(data[6]) * 16) | hex_to_bin(data[7]); + if (keyset_file < 0) { + dev_err(wdev->dev, "%s corrupted\n", filename); + release_firmware(*fw); + *fw = NULL; + return -EINVAL; + } + } + if (keyset_file != keyset_chip) { + dev_err(wdev->dev, "firmware keyset is incompatible with chip (file: 0x%02X, chip: 0x%02X)\n", + keyset_file, keyset_chip); + release_firmware(*fw); + *fw = NULL; + return -ENODEV; + } + wdev->keyset = keyset_file; + return 0; +} + +static int wait_ncp_status(struct wfx_dev *wdev, u32 status) +{ + ktime_t now, start; + u32 reg; + int ret; + + start = ktime_get(); + for (;;) { + ret = sram_reg_read(wdev, WFX_DCA_NCP_STATUS, ®); + if (ret < 0) + return -EIO; + now = ktime_get(); + if (reg == status) + break; + if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT))) + return -ETIMEDOUT; + } + if (ktime_compare(now, start)) + dev_dbg(wdev->dev, "chip answer after %lldus\n", + ktime_us_delta(now, start)); + else + dev_dbg(wdev->dev, "chip answer immediately\n"); + return 0; +} + +static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len) +{ + int ret; + u32 offs, bytes_done = 0; + ktime_t now, start; + + if (len % DNLD_BLOCK_SIZE) { + dev_err(wdev->dev, "firmware size is not aligned. Buffer overrun will occur\n"); + return -EIO; + } + offs = 0; + while (offs < len) { + start = ktime_get(); + for (;;) { + now = ktime_get(); + if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE) + break; + if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT))) + return -ETIMEDOUT; + ret = sram_reg_read(wdev, WFX_DCA_GET, &bytes_done); + if (ret < 0) + return ret; + } + if (ktime_compare(now, start)) + dev_dbg(wdev->dev, "answer after %lldus\n", + ktime_us_delta(now, start)); + + ret = sram_write_dma_safe(wdev, WFX_DNLD_FIFO + + (offs % DNLD_FIFO_SIZE), + data + offs, DNLD_BLOCK_SIZE); + if (ret < 0) + return ret; + + /* The device seems to not support writing 0 in this register + * during first loop + */ + offs += DNLD_BLOCK_SIZE; + ret = sram_reg_write(wdev, WFX_DCA_PUT, offs); + if (ret < 0) + return ret; + } + return 0; +} + +static void print_boot_status(struct wfx_dev *wdev) +{ + u32 reg; + + sram_reg_read(wdev, WFX_STATUS_INFO, ®); + if (reg == 0x12345678) + return; + sram_reg_read(wdev, WFX_ERR_INFO, ®); + if (reg < ARRAY_SIZE(fwio_errors) && fwio_errors[reg]) + dev_info(wdev->dev, "secure boot: %s\n", fwio_errors[reg]); + else + dev_info(wdev->dev, "secure boot: Error %#02x\n", reg); +} + +static int load_firmware_secure(struct wfx_dev *wdev) +{ + const struct firmware *fw = NULL; + int header_size; + int fw_offset; + ktime_t start; + u8 *buf; + int ret; + + BUILD_BUG_ON(PTE_INFO_SIZE > BOOTLOADER_LABEL_SIZE); + buf = kmalloc(BOOTLOADER_LABEL_SIZE + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_READY); + ret = wait_ncp_status(wdev, NCP_INFO_READY); + if (ret) + goto error; + + sram_buf_read(wdev, WFX_BOOTLOADER_LABEL, buf, BOOTLOADER_LABEL_SIZE); + buf[BOOTLOADER_LABEL_SIZE] = 0; + dev_dbg(wdev->dev, "bootloader: \"%s\"\n", buf); + + sram_buf_read(wdev, WFX_PTE_INFO, buf, PTE_INFO_SIZE); + ret = get_firmware(wdev, buf[PTE_INFO_KEYSET_IDX], &fw, &fw_offset); + if (ret) + goto error; + header_size = fw_offset + FW_SIGNATURE_SIZE + FW_HASH_SIZE; + + sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_INFO_READ); + ret = wait_ncp_status(wdev, NCP_READY); + if (ret) + goto error; + + sram_reg_write(wdev, WFX_DNLD_FIFO, 0xFFFFFFFF); /* Fifo init */ + sram_write_dma_safe(wdev, WFX_DCA_FW_VERSION, "\x01\x00\x00\x00", + FW_VERSION_SIZE); + sram_write_dma_safe(wdev, WFX_DCA_FW_SIGNATURE, fw->data + fw_offset, + FW_SIGNATURE_SIZE); + sram_write_dma_safe(wdev, WFX_DCA_FW_HASH, + fw->data + fw_offset + FW_SIGNATURE_SIZE, + FW_HASH_SIZE); + sram_reg_write(wdev, WFX_DCA_IMAGE_SIZE, fw->size - header_size); + sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_PENDING); + ret = wait_ncp_status(wdev, NCP_DOWNLOAD_PENDING); + if (ret) + goto error; + + start = ktime_get(); + ret = upload_firmware(wdev, fw->data + header_size, + fw->size - header_size); + if (ret) + goto error; + dev_dbg(wdev->dev, "firmware load after %lldus\n", + ktime_us_delta(ktime_get(), start)); + + sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_COMPLETE); + ret = wait_ncp_status(wdev, NCP_AUTH_OK); + /* Legacy ROM support */ + if (ret < 0) + ret = wait_ncp_status(wdev, NCP_PUB_KEY_RDY); + if (ret < 0) + goto error; + sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_OK_TO_JUMP); + +error: + kfree(buf); + if (fw) + release_firmware(fw); + if (ret) + print_boot_status(wdev); + return ret; +} + +static int init_gpr(struct wfx_dev *wdev) +{ + int ret, i; + static const struct { + int index; + u32 value; + } gpr_init[] = { + { 0x07, 0x208775 }, + { 0x08, 0x2EC020 }, + { 0x09, 0x3C3C3C }, + { 0x0B, 0x322C44 }, + { 0x0C, 0xA06497 }, + }; + + for (i = 0; i < ARRAY_SIZE(gpr_init); i++) { + ret = igpr_reg_write(wdev, gpr_init[i].index, + gpr_init[i].value); + if (ret < 0) + return ret; + dev_dbg(wdev->dev, " index %02x: %08x\n", + gpr_init[i].index, gpr_init[i].value); + } + return 0; +} + +int wfx_init_device(struct wfx_dev *wdev) +{ + int ret; + int hw_revision, hw_type; + int wakeup_timeout = 50; /* ms */ + ktime_t now, start; + u32 reg; + + reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_BYTE_ORDER_ABCD; + if (wdev->pdata.use_rising_clk) + reg |= CFG_CLK_RISE_EDGE; + ret = config_reg_write(wdev, reg); + if (ret < 0) { + dev_err(wdev->dev, "bus returned an error during first write access. Host configuration error?\n"); + return -EIO; + } + + ret = config_reg_read(wdev, ®); + if (ret < 0) { + dev_err(wdev->dev, "bus returned an error during first read access. Bus configuration error?\n"); + return -EIO; + } + if (reg == 0 || reg == ~0) { + dev_err(wdev->dev, "chip mute. Bus configuration error or chip wasn't reset?\n"); + return -EIO; + } + dev_dbg(wdev->dev, "initial config register value: %08x\n", reg); + + hw_revision = FIELD_GET(CFG_DEVICE_ID_MAJOR, reg); + if (hw_revision == 0) { + dev_err(wdev->dev, "bad hardware revision number: %d\n", + hw_revision); + return -ENODEV; + } + hw_type = FIELD_GET(CFG_DEVICE_ID_TYPE, reg); + if (hw_type == 1) { + dev_notice(wdev->dev, "development hardware detected\n"); + wakeup_timeout = 2000; + } + + ret = init_gpr(wdev); + if (ret < 0) + return ret; + + ret = control_reg_write(wdev, CTRL_WLAN_WAKEUP); + if (ret < 0) + return -EIO; + start = ktime_get(); + for (;;) { + ret = control_reg_read(wdev, ®); + now = ktime_get(); + if (reg & CTRL_WLAN_READY) + break; + if (ktime_after(now, ktime_add_ms(start, wakeup_timeout))) { + dev_err(wdev->dev, "chip didn't wake up. Chip wasn't reset?\n"); + return -ETIMEDOUT; + } + } + dev_dbg(wdev->dev, "chip wake up after %lldus\n", + ktime_us_delta(now, start)); + + ret = config_reg_write_bits(wdev, CFG_CPU_RESET, 0); + if (ret < 0) + return ret; + ret = load_firmware_secure(wdev); + if (ret < 0) + return ret; + return config_reg_write_bits(wdev, + CFG_DIRECT_ACCESS_MODE | + CFG_IRQ_ENABLE_DATA | + CFG_IRQ_ENABLE_WRDY, + CFG_IRQ_ENABLE_DATA); +} diff --git a/drivers/net/wireless/silabs/wfx/fwio.h b/drivers/net/wireless/silabs/wfx/fwio.h new file mode 100644 index 000000000000..eeea61210eca --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/fwio.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Firmware loading. + * + * Copyright (c) 2017-2019, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_FWIO_H +#define WFX_FWIO_H + +struct wfx_dev; + +int wfx_init_device(struct wfx_dev *wdev); + +#endif From patchwork Mon Sep 20 16:11:23 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: 12505907 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 361CEC433EF for ; Mon, 20 Sep 2021 16:14:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1D8BD60F58 for ; Mon, 20 Sep 2021 16:14:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242697AbhITQP5 (ORCPT ); Mon, 20 Sep 2021 12:15:57 -0400 Received: from mail-bn7nam10on2055.outbound.protection.outlook.com ([40.107.92.55]:31296 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242382AbhITQOP (ORCPT ); Mon, 20 Sep 2021 12:14:15 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OzGcdXR8/fALP3nQjZkrG/BKVLDWGKFDBCQi1oSTTiMiSaVAVE1p4q7JzZprVzaywgJE9B9Nyi7I1lMXayiqUY1gssZY+DeND+VTmxdqHHg7PaqQj8SxR79ESp1Jzha7e1wAtkIzuJez3tBPeOQlg+qL2OJ0a3F1VKkEHpVIh7kYSsj5dfMS0VzTyUDAgX47UAQtA8diyxFBPpXTZrQQUWk4fGQxwueJgPOYJI/jvWqAnw5K9tjktW6cvaj4n47+2469jSxey9Qo1qsf7xNuC5Ade2N1zBNVI1WnwvgF/mEiO2YPRJiTeOlZtpWnPRZ8CXCiLwmew+W4gIGl7qXbWg== 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=lquym0q6CMbsfLPbe1AK9mls78xc1jS4/BFzqXVswKE=; b=eEtVkaX7X7vrpn9NGwuBVHw+bQSpHuZIvV8RzVgnCj4rgvINmGFqm1XERxGgm3wOnurhoKgzRiVl5B26+dDSe9XGKNMXXi4mnJumHcvEMUb8J8vg2ICc5AA9ZGj4fyRat9AICyfhGvFNO413sYvZVsfIlAjy+i9W5164AJDuw/blVvdq0RqBIbCDijtpt5SXejlMZQscTEE1v6+jLOEBJiUALW68Gsk4rnOjhgTAMrjvU/M6MHhURi3ofZAPpURLdg9tLZmZ8yl+4G0soR25KAAiO0so6MKVK1WHS67/IEK/xRJuYX5kHGbScgx228vdXXaYH870alGk74dlLqGb5Q== 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=lquym0q6CMbsfLPbe1AK9mls78xc1jS4/BFzqXVswKE=; b=H0/hBmwCAf4URiYlYN5RHm45k1VXmW8o/IA9eYtRWEkrhb7AWeHQXQ/SsE/beQRyBtrGM+nQsdmfx422nKP08FO4l/N7YJaXLeykmbwzrxYD+oXFWIi2r+u/GoWoLRAEf25A/0t/zbUuNVmAjrq6Hq3K/Hi7307AljhqdaTXEu0= 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 SA2PR11MB5002.namprd11.prod.outlook.com (2603:10b6:806:fb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.16; Mon, 20 Sep 2021 16:12:20 +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:20 +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 11/24] wfx: add bh.c/bh.h Date: Mon, 20 Sep 2021 18:11:23 +0200 Message-Id: <20210920161136.2398632-12-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:18 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c624894b-ec7c-4c29-f81c-08d97c516c40 X-MS-TrafficTypeDiagnostic: SA2PR11MB5002: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: jNV6WoFrzP8xvrzd09e9tq72/ribMVSpPx3uC+4W57vqnblD3rq3j9qCYuIyEqKTiCReWMjcECAjmrbyf1MIy2HeU7VMk4XS+/OokREF/rO4CNE/ODBPA8fs89HPTgt+bfNfQO6srq/t1hRCKVsxcgU6vfcW9ptbW+gxM2dqjksPE14TFRcU1JiKCUWObmt1afKlrHwAzfZnjqjxhUUTLGr9BTzkgIBG1GJlUrNfwGl7DPUFop4IJTInrffzvC3gLYMoUu7Wxf7Wj7LXhR+nNopbiPxwSJpyUraXT9k5JPC8rHVf6W0X45E3huUj5qMAVtmiqESmBWyTgfecmX1OjSTwoB9Uz+xxpZJYFnW4z7MIrMfviyWXHtz5wGidKjgo3vJc/zl0WE5ZAsu7kzu1d3esgNqjys+/C6E8RkNQlYgCjU4RdkJHD5JiL8tCV/iWT5+tFBuWCGpb3oKKtrb2HngAj5K0FgN2niDBqJj7Fo6iz65UDl1ser/yIc6V6YtdBe4DO9codIwNfNO3cKMfmRoo+hPRSO0l2FEsUby/No8dLlIe6GHqE2XPwD1wSeWhv3d9j7QmiZyeTeDY7IxAlUJsyMXh6Y3rBw/cE+pLITLUvxmUhwWKmYG3rmRriJopB8jkSFQuOfwmLt2vsrjSiA== 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:(366004)(66476007)(36756003)(2616005)(66556008)(107886003)(186003)(54906003)(5660300002)(6486002)(66574015)(66946007)(52116002)(38100700002)(83380400001)(7696005)(6916009)(2906002)(1076003)(4326008)(8936002)(316002)(8676002)(508600001)(86362001)(30864003)(6666004)(7416002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: LbkQ4MGodi/YVi6/ywH1P0zh7GkW/xuJKpJfgxEtzd+CSP98JVVbEpSHGWufblfyQolqucSfnaFGp7J4o5hmxV5NJ4ZcNU4T/6w6S1R9RFgfMRB6edSAeNUws/7aN8XLaklm6I7XZK3TjPRWLrtj2ijDZDy8cf1RxfdWS0eXxIPXk6dqIG+/LnjXyZBkyEjq0nmOJazRL9GIUHfZi6IsXc0htsF0yaniU0LU1GBAe5Fb5XIpqvzqiVIYXsyZX+8DLhuyyA1Ukz/6WZsyEGkiGLYN5KtFkFujB8+gM8iFguLLuVVxyV1iRZLbOdTAbm+PF/E/0axN/au+0t9JI6qs29KF9aL3CeVqnbnh5PGXGiLC+oeshmrYHG7DoyiV1mM/589AreKkdNFsr8rykAOXqBjq7x+s8ZTynSBV1p9GiwMkaCxhUKMe2deHgw7Z/BQ5hOvPrOrtIJ8bYdrlITekeICXDyg+6afPaX4dWXN1sxVjUoEPE2KfL09N8bQfnVJk2/DAKyiyziHBbh6mgAJbunuy1pz/WL1eICQCwdsPmL73WfpRWLsiFzIOXvxaphpWFx1d7gvSqW4i1jVBuVzInegW+aFQ8gA4FPpdW+IUkIbOqmElX5wRPlTe6AqYIM7u7265Bh7YO0rxHmwbNkWaZpC0bkPeg1drQFavfofeJVL0ga0nP+t+cI5DQHMOiZF14FRPc2l1tCkJ1rTqQsBwjtBv3TACOxcYvsCQ+8KksWed7y1H8oP7u6PVNbPt9uh9Tibo9lmegArmXGpZ5fk7GjnNBopGEjFXyyLZQ1K8nyQWUqRqo71MJZnD0dRsHOtZ X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: c624894b-ec7c-4c29-f81c-08d97c516c40 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:20.2786 (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: 0/L9vR67b4XzJgV5BpOu4n2YsojGqWd/F9a8IIISN0RmPf4SN0uOTlA/97bSUvPYl4d5k0ANBfKr/+DfrdzJOg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5002 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/bh.c | 329 +++++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/bh.h | 33 +++ 2 files changed, 362 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/bh.c create mode 100644 drivers/net/wireless/silabs/wfx/bh.h diff --git a/drivers/net/wireless/silabs/wfx/bh.c b/drivers/net/wireless/silabs/wfx/bh.c new file mode 100644 index 000000000000..a5daf393f5aa --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/bh.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Interrupt bottom half (BH). + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "bh.h" +#include "wfx.h" +#include "hwio.h" +#include "traces.h" +#include "hif_rx.h" +#include "hif_api_cmd.h" + +static void device_wakeup(struct wfx_dev *wdev) +{ + int max_retry = 3; + + if (!wdev->pdata.gpio_wakeup) + return; + if (gpiod_get_value_cansleep(wdev->pdata.gpio_wakeup) > 0) + return; + + if (wfx_api_older_than(wdev, 1, 4)) { + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); + if (!completion_done(&wdev->hif.ctrl_ready)) + usleep_range(2000, 2500); + return; + } + for (;;) { + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); + /* completion.h does not provide any function to wait + * completion without consume it (a kind of + * wait_for_completion_done_timeout()). So we have to emulate + * it. + */ + if (wait_for_completion_timeout(&wdev->hif.ctrl_ready, + msecs_to_jiffies(2))) { + complete(&wdev->hif.ctrl_ready); + return; + } else if (max_retry-- > 0) { + /* Older firmwares have a race in sleep/wake-up process. + * Redo the process is sufficient to unfreeze the + * chip. + */ + dev_err(wdev->dev, "timeout while wake up chip\n"); + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0); + usleep_range(2000, 2500); + } else { + dev_err(wdev->dev, "max wake-up retries reached\n"); + return; + } + } +} + +static void device_release(struct wfx_dev *wdev) +{ + if (!wdev->pdata.gpio_wakeup) + return; + + gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0); +} + +static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf) +{ + struct sk_buff *skb; + struct hif_msg *hif; + size_t alloc_len; + size_t computed_len; + int release_count; + int piggyback = 0; + + WARN(read_len > round_down(0xFFF, 2) * sizeof(u16), "request exceed the chip capability"); + + /* Add 2 to take into account piggyback size */ + alloc_len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, read_len + 2); + skb = dev_alloc_skb(alloc_len); + if (!skb) + return -ENOMEM; + + if (wfx_data_read(wdev, skb->data, alloc_len)) + goto err; + + piggyback = le16_to_cpup((__le16 *)(skb->data + alloc_len - 2)); + _trace_piggyback(piggyback, false); + + hif = (struct hif_msg *)skb->data; + WARN(hif->encrypted & 0x3, "encryption is unsupported"); + if (WARN(read_len < sizeof(struct hif_msg), "corrupted read")) + goto err; + computed_len = le16_to_cpu(hif->len); + computed_len = round_up(computed_len, 2); + if (computed_len != read_len) { + dev_err(wdev->dev, "inconsistent message length: %zu != %zu\n", + computed_len, read_len); + print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, 16, 1, + hif, read_len, true); + goto err; + } + + if (!(hif->id & HIF_ID_IS_INDICATION)) { + (*is_cnf)++; + if (hif->id == HIF_CNF_ID_MULTI_TRANSMIT) + release_count = ((struct hif_cnf_multi_transmit *)hif->body)->num_tx_confs; + else + release_count = 1; + WARN(wdev->hif.tx_buffers_used < release_count, "corrupted buffer counter"); + wdev->hif.tx_buffers_used -= release_count; + } + _trace_hif_recv(hif, wdev->hif.tx_buffers_used); + + if (hif->id != HIF_IND_ID_EXCEPTION && hif->id != HIF_IND_ID_ERROR) { + if (hif->seqnum != wdev->hif.rx_seqnum) + dev_warn(wdev->dev, "wrong message sequence: %d != %d\n", + hif->seqnum, wdev->hif.rx_seqnum); + wdev->hif.rx_seqnum = (hif->seqnum + 1) % (HIF_COUNTER_MAX + 1); + } + + skb_put(skb, le16_to_cpu(hif->len)); + /* wfx_handle_rx takes care on SKB livetime */ + wfx_handle_rx(wdev, skb); + if (!wdev->hif.tx_buffers_used) + wake_up(&wdev->hif.tx_buffers_empty); + + return piggyback; + +err: + if (skb) + dev_kfree_skb(skb); + return -EIO; +} + +static int bh_work_rx(struct wfx_dev *wdev, int max_msg, int *num_cnf) +{ + size_t len; + int i; + int ctrl_reg, piggyback; + + piggyback = 0; + for (i = 0; i < max_msg; i++) { + if (piggyback & CTRL_NEXT_LEN_MASK) + ctrl_reg = piggyback; + else if (try_wait_for_completion(&wdev->hif.ctrl_ready)) + ctrl_reg = atomic_xchg(&wdev->hif.ctrl_reg, 0); + else + ctrl_reg = 0; + if (!(ctrl_reg & CTRL_NEXT_LEN_MASK)) + return i; + /* ctrl_reg units are 16bits words */ + len = (ctrl_reg & CTRL_NEXT_LEN_MASK) * 2; + piggyback = rx_helper(wdev, len, num_cnf); + if (piggyback < 0) + return i; + if (!(piggyback & CTRL_WLAN_READY)) + dev_err(wdev->dev, "unexpected piggyback value: ready bit not set: %04x\n", + piggyback); + } + if (piggyback & CTRL_NEXT_LEN_MASK) { + ctrl_reg = atomic_xchg(&wdev->hif.ctrl_reg, piggyback); + complete(&wdev->hif.ctrl_ready); + if (ctrl_reg) + dev_err(wdev->dev, "unexpected IRQ happened: %04x/%04x\n", + ctrl_reg, piggyback); + } + return i; +} + +static void tx_helper(struct wfx_dev *wdev, struct hif_msg *hif) +{ + int ret; + void *data; + bool is_encrypted = false; + size_t len = le16_to_cpu(hif->len); + + WARN(len < sizeof(*hif), "try to send corrupted data"); + + hif->seqnum = wdev->hif.tx_seqnum; + wdev->hif.tx_seqnum = (wdev->hif.tx_seqnum + 1) % (HIF_COUNTER_MAX + 1); + + data = hif; + WARN(len > wdev->hw_caps.size_inp_ch_buf, + "request exceed the chip capability: %zu > %d\n", + len, wdev->hw_caps.size_inp_ch_buf); + len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, len); + ret = wfx_data_write(wdev, data, len); + if (ret) + goto end; + + wdev->hif.tx_buffers_used++; + _trace_hif_send(hif, wdev->hif.tx_buffers_used); +end: + if (is_encrypted) + kfree(data); +} + +static int bh_work_tx(struct wfx_dev *wdev, int max_msg) +{ + struct hif_msg *hif; + int i; + + for (i = 0; i < max_msg; i++) { + hif = NULL; + if (wdev->hif.tx_buffers_used < wdev->hw_caps.num_inp_ch_bufs) { + if (try_wait_for_completion(&wdev->hif_cmd.ready)) { + WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error"); + hif = wdev->hif_cmd.buf_send; + } else { + hif = wfx_tx_queues_get(wdev); + } + } + if (!hif) + return i; + tx_helper(wdev, hif); + } + return i; +} + +/* In SDIO mode, it is necessary to make an access to a register to acknowledge + * last received message. It could be possible to restrict this acknowledge to + * SDIO mode and only if last operation was rx. + */ +static void ack_sdio_data(struct wfx_dev *wdev) +{ + u32 cfg_reg; + + config_reg_read(wdev, &cfg_reg); + if (cfg_reg & 0xFF) { + dev_warn(wdev->dev, "chip reports errors: %02x\n", + cfg_reg & 0xFF); + config_reg_write_bits(wdev, 0xFF, 0x00); + } +} + +static void bh_work(struct work_struct *work) +{ + struct wfx_dev *wdev = container_of(work, struct wfx_dev, hif.bh); + int stats_req = 0, stats_cnf = 0, stats_ind = 0; + bool release_chip = false, last_op_is_rx = false; + int num_tx, num_rx; + + device_wakeup(wdev); + do { + num_tx = bh_work_tx(wdev, 32); + stats_req += num_tx; + if (num_tx) + last_op_is_rx = false; + num_rx = bh_work_rx(wdev, 32, &stats_cnf); + stats_ind += num_rx; + if (num_rx) + last_op_is_rx = true; + } while (num_rx || num_tx); + stats_ind -= stats_cnf; + + if (last_op_is_rx) + ack_sdio_data(wdev); + if (!wdev->hif.tx_buffers_used && !work_pending(work)) { + device_release(wdev); + release_chip = true; + } + _trace_bh_stats(stats_ind, stats_req, stats_cnf, + wdev->hif.tx_buffers_used, release_chip); +} + +/* An IRQ from chip did occur */ +void wfx_bh_request_rx(struct wfx_dev *wdev) +{ + u32 cur, prev; + + control_reg_read(wdev, &cur); + prev = atomic_xchg(&wdev->hif.ctrl_reg, cur); + complete(&wdev->hif.ctrl_ready); + queue_work(system_highpri_wq, &wdev->hif.bh); + + if (!(cur & CTRL_NEXT_LEN_MASK)) + dev_err(wdev->dev, "unexpected control register value: length field is 0: %04x\n", + cur); + if (prev != 0) + dev_err(wdev->dev, "received IRQ but previous data was not (yet) read: %04x/%04x\n", + prev, cur); +} + +/* Driver want to send data */ +void wfx_bh_request_tx(struct wfx_dev *wdev) +{ + queue_work(system_highpri_wq, &wdev->hif.bh); +} + +/* If IRQ is not available, this function allow to manually poll the control + * register and simulate an IRQ ahen an event happened. + * + * Note that the device has a bug: If an IRQ raise while host read control + * register, the IRQ is lost. So, use this function carefully (only duing + * device initialisation). + */ +void wfx_bh_poll_irq(struct wfx_dev *wdev) +{ + ktime_t now, start; + u32 reg; + + WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ"); + start = ktime_get(); + for (;;) { + control_reg_read(wdev, ®); + now = ktime_get(); + if (reg & 0xFFF) + break; + if (ktime_after(now, ktime_add_ms(start, 1000))) { + dev_err(wdev->dev, "time out while polling control register\n"); + return; + } + udelay(200); + } + wfx_bh_request_rx(wdev); +} + +void wfx_bh_register(struct wfx_dev *wdev) +{ + INIT_WORK(&wdev->hif.bh, bh_work); + init_completion(&wdev->hif.ctrl_ready); + init_waitqueue_head(&wdev->hif.tx_buffers_empty); +} + +void wfx_bh_unregister(struct wfx_dev *wdev) +{ + flush_work(&wdev->hif.bh); +} diff --git a/drivers/net/wireless/silabs/wfx/bh.h b/drivers/net/wireless/silabs/wfx/bh.h new file mode 100644 index 000000000000..6c121ce4dd3f --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/bh.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Interrupt bottom half (BH). + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_BH_H +#define WFX_BH_H + +#include +#include +#include + +struct wfx_dev; + +struct wfx_hif { + struct work_struct bh; + struct completion ctrl_ready; + wait_queue_head_t tx_buffers_empty; + atomic_t ctrl_reg; + int rx_seqnum; + int tx_seqnum; + int tx_buffers_used; +}; + +void wfx_bh_register(struct wfx_dev *wdev); +void wfx_bh_unregister(struct wfx_dev *wdev); +void wfx_bh_request_rx(struct wfx_dev *wdev); +void wfx_bh_request_tx(struct wfx_dev *wdev); +void wfx_bh_poll_irq(struct wfx_dev *wdev); + +#endif From patchwork Mon Sep 20 16:11:24 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: 12505843 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 CD61DC433F5 for ; Mon, 20 Sep 2021 16:12:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B2DFC60F70 for ; Mon, 20 Sep 2021 16:12:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242406AbhITQOP (ORCPT ); Mon, 20 Sep 2021 12:14:15 -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 S242734AbhITQNw (ORCPT ); Mon, 20 Sep 2021 12:13:52 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fIBhkhWBluVLDjuDZ/JJVKdka/yeMXbKeKpbmrYsvukh3x5t46nRtsjmsnPHQYUlQ2KG3+XzByXu6dQwMD8URMv5Mal1q+x0GRJ/3zpL2v4Yog2uCNo5UlyxME6AEDyIqSjhKeULpHjp6uJRNhc7fUd95UoKZ8n7gACuSM+vak9jOSuqyVu3U/S4OEkHvfdiVKIQUVUMWSZz8sL1wMvNJoMbUelkGeRrkKps8VDqISbffAg3zXUQgfWJGBl1N05aSbjjpnH8qxTYg3xDSAMsuNCnb37YGaOREEmzCOMiU6RC8NB0oaSaWsrwLeZyGYyXn8Vo8h+02o92X5D4maZAFQ== 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=5oz+9ddYfjNJudQmnwjNkzjn0Y/Ivhg75We5t20cLdk=; b=EcSqkZEj9hEJtP/oSYfhFAMhG0HOLqEI5Y3tR25aW9vB6vViT6Hdxdi/WD9R/r7AL9ku4SCM+hiRxjqYpXB2KDl3m41ShSdPDGiHH07FUhFGI/i6pUAEGWeqggGvwTyrTn3dBEootpMm5E6TPzRy6AQbYHKZgqCe8Y5JTe/OoCsWO6xB0+m84aIKpZHFuGSNtxO3DsdFW4kTnEggzZlDv4rlMjq7/0ORxFmjOOl4mKtdntLEIwqcUC9CZjGYtmmsbyxO6OXJF3wXQ6nS6WvEyRjF3KSY84R64qfack15XLpUYMKG8+n9hiN8EB5GUZmArErp/ONHl2RSTUeKfq8O4Q== 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=5oz+9ddYfjNJudQmnwjNkzjn0Y/Ivhg75We5t20cLdk=; b=ELT+8wKPrNBN6aOQ4EAKuHxHEi+JdlTXlJv0BOkGjcfME0GSo7269gd++R8aE6mqcBxAQQ+V3Po+Oc0NJhIQf6yTwdi+CiCXkhh054BPlbhPThdhaubZI2H0t1HmwpFqlr9f8bG2jeqIZZS6hMXY9SGIp4V3ctdVPsSpDNZ+Ah8= 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:23 +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:23 +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 12/24] wfx: add hif_api_*.h Date: Mon, 20 Sep 2021 18:11:24 +0200 Message-Id: <20210920161136.2398632-13-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:20 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 121f5259-b4bc-421d-2621-08d97c516dc6 X-MS-TrafficTypeDiagnostic: SN6PR11MB2557: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:111; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: mRRkpaMVzrkx2bIohQp+HWcJdslkD4h7oY4Xluog8Q78UUpAhFN2jUulSJ5QnyeHittTTxNOhKe/0bqd6g0bvGcc+b5Hsv77mexNd5UPdO5J77aLXHqWRcsT25gbmbix5ItGxaF4fBjW3XYZaIgB6Fkof+7EXRDTog92SKX+1UcCj7A0WrqU30hEShmXw7VcoroZ1jfGP4VLYBIQTAD4sJADeP8a4FzPos/SremZtx1XrHfHmFs9ypcVaugjz5f+atQ8DaeIboN/IWZSoDK1T17lV2ZI4aLoDC3a1b9BEW2A77MseEOiiBnAunQwgQ1fUGMynrkGznQkx88yp3NeNIIhkXKeTyMFtvg29slENEyvXBPjl4ZqO5DcQkhbKapF7d+zVOSo5bUOtc1GWhdVbIy8v1YS1NYaVg6zMkApc/DPgQDsWtB0rzVotk/540PFo6pBfz90IGErB6Kpa1hwQ5oIpixypvi/nmpX6F5j1/Q98b0UIi9xuDx4q82mx38Hm4AbQQA1tACFu8C8M3M0yllBL+MVZzIAUBurmlP7PnVSyVXR3egu7JA0Mhg+GN6gZ0/2w6mcW2FjWSzJXtCN+dnkr8FubxglwKDLrbOAN9QNjxIBhQDDBv7X9Mr3r6tIjju/tEWdU/ujiwmxlveQnA== 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: 8epQK9csrJ+1BrOczVDbGHEY5Nm3nbZgR2ts2Mdz7PykZaslkqThtRVSJkwOlMC/4o3Vv+ff+IF68ETq8nprBSbgMHg6/ifgKJgv8rQoJKl3ZuWiSs8yo3GccAiyUZBDcWDNNXcQ104MiavLlmQZTt9VLlU0TsMJNVMpYiSIregdOW2PqCUp8lRhBpQ3zUKfdULBr8kXFvvF4jOUc3urO43I5XokiaOPdB3xeEcDv07HIsLSAFHxIKxS7FRylAZiI9U9BCRnM5Olztmb7F0mgyI/AcuOaJt3lIJOzUJIfU3oVtJKu4W8tRHTYqaQyQGAMmMCZnRNfcn0pYL370O6bzeN4IlkvmK9Y1lleanVtdrJBXRGF4LC8xU6Ra52ai0Wy1gLwAN/KV1ADDAVIrK0OUqhNFAoYnwjpe9XogA/jRTZWjgdI8vA94ZDHkTbMwMpRfouedf6SJ4PjSNiiUBXuUs/zc2NciC1DIg56B6LE0jdQ9lGmyzJnEdUDrKxMTjSjmjmMfsyLpmARkIo36YcZd73SZcKPwW7+j19kZfnc4enKWD7kf1ZmjkkDYXZr5RVl2DGNEqlmON5AzE2Hx3LjJXXX48k0MwZ3yUwUpJUvgZ6kAAFk54j8dnl1fh+HoLb0QXhlkTzWuxrVdnU+/lVC47nhx8xR6Fjo8i/oeAMdXVROZiyTYfY2+ed/r18m/QyLxo6ZpZdxGtu+PkXHrB9qUkczcz8Gt4qeLU5yV9o49epZV+zqxvebc5C2tEjuWyLdPxZip+lzTacrlfdLtCCJeDdOUYUHNG8+xuJ+eIXmgq5rgRPkApiKPAo6CbVcmHR X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 121f5259-b4bc-421d-2621-08d97c516dc6 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:22.9231 (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: B1FH7Fq0194sUQzBsegLil9ikgtZw8hgFk8VLY9MzwYqNJpgPfGboRnpHz/7Y/HeMU890KAvGlypmJaUOM/2Zg== 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_api_cmd.h | 555 ++++++++++++++++++ .../net/wireless/silabs/wfx/hif_api_general.h | 256 ++++++++ drivers/net/wireless/silabs/wfx/hif_api_mib.h | 346 +++++++++++ 3 files changed, 1157 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/hif_api_cmd.h create mode 100644 drivers/net/wireless/silabs/wfx/hif_api_general.h create mode 100644 drivers/net/wireless/silabs/wfx/hif_api_mib.h diff --git a/drivers/net/wireless/silabs/wfx/hif_api_cmd.h b/drivers/net/wireless/silabs/wfx/hif_api_cmd.h new file mode 100644 index 000000000000..b0aa13b23a51 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_api_cmd.h @@ -0,0 +1,555 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * WF200 hardware interface definitions + * + * Copyright (c) 2018-2020, Silicon Laboratories Inc. + */ + +#ifndef WFX_HIF_API_CMD_H +#define WFX_HIF_API_CMD_H + +#include + +#include "hif_api_general.h" + +enum hif_requests_ids { + HIF_REQ_ID_RESET = 0x0a, + HIF_REQ_ID_READ_MIB = 0x05, + HIF_REQ_ID_WRITE_MIB = 0x06, + HIF_REQ_ID_START_SCAN = 0x07, + HIF_REQ_ID_STOP_SCAN = 0x08, + HIF_REQ_ID_TX = 0x04, + HIF_REQ_ID_JOIN = 0x0b, + HIF_REQ_ID_SET_PM_MODE = 0x10, + HIF_REQ_ID_SET_BSS_PARAMS = 0x11, + HIF_REQ_ID_ADD_KEY = 0x0c, + HIF_REQ_ID_REMOVE_KEY = 0x0d, + HIF_REQ_ID_EDCA_QUEUE_PARAMS = 0x13, + HIF_REQ_ID_START = 0x17, + HIF_REQ_ID_BEACON_TRANSMIT = 0x18, + HIF_REQ_ID_UPDATE_IE = 0x1b, + HIF_REQ_ID_MAP_LINK = 0x1c, +}; + +enum hif_confirmations_ids { + HIF_CNF_ID_RESET = 0x0a, + HIF_CNF_ID_READ_MIB = 0x05, + HIF_CNF_ID_WRITE_MIB = 0x06, + HIF_CNF_ID_START_SCAN = 0x07, + HIF_CNF_ID_STOP_SCAN = 0x08, + HIF_CNF_ID_TX = 0x04, + HIF_CNF_ID_MULTI_TRANSMIT = 0x1e, + HIF_CNF_ID_JOIN = 0x0b, + HIF_CNF_ID_SET_PM_MODE = 0x10, + HIF_CNF_ID_SET_BSS_PARAMS = 0x11, + HIF_CNF_ID_ADD_KEY = 0x0c, + HIF_CNF_ID_REMOVE_KEY = 0x0d, + HIF_CNF_ID_EDCA_QUEUE_PARAMS = 0x13, + HIF_CNF_ID_START = 0x17, + HIF_CNF_ID_BEACON_TRANSMIT = 0x18, + HIF_CNF_ID_UPDATE_IE = 0x1b, + HIF_CNF_ID_MAP_LINK = 0x1c, +}; + +enum hif_indications_ids { + HIF_IND_ID_RX = 0x84, + HIF_IND_ID_SCAN_CMPL = 0x86, + HIF_IND_ID_JOIN_COMPLETE = 0x8f, + HIF_IND_ID_SET_PM_MODE_CMPL = 0x89, + HIF_IND_ID_SUSPEND_RESUME_TX = 0x8c, + HIF_IND_ID_EVENT = 0x85 +}; + +struct hif_req_reset { + u8 reset_stat:1; + u8 reset_all_int:1; + u8 reserved1:6; + u8 reserved2[3]; +} __packed; + +struct hif_cnf_reset { + __le32 status; +} __packed; + +struct hif_req_read_mib { + __le16 mib_id; + __le16 reserved; +} __packed; + +struct hif_cnf_read_mib { + __le32 status; + __le16 mib_id; + __le16 length; + u8 mib_data[]; +} __packed; + +struct hif_req_write_mib { + __le16 mib_id; + __le16 length; + u8 mib_data[]; +} __packed; + +struct hif_cnf_write_mib { + __le32 status; +} __packed; + +struct hif_req_update_ie { + u8 beacon:1; + u8 probe_resp:1; + u8 probe_req:1; + u8 reserved1:5; + u8 reserved2; + __le16 num_ies; + u8 ie[]; +} __packed; + +struct hif_cnf_update_ie { + __le32 status; +} __packed; + +struct hif_ssid_def { + __le32 ssid_length; + u8 ssid[IEEE80211_MAX_SSID_LEN]; +} __packed; + +#define HIF_API_MAX_NB_SSIDS 2 +#define HIF_API_MAX_NB_CHANNELS 14 + +struct hif_req_start_scan_alt { + u8 band; + u8 maintain_current_bss:1; + u8 periodic:1; + u8 reserved1:6; + u8 disallow_ps:1; + u8 reserved2:1; + u8 short_preamble:1; + u8 reserved3:5; + u8 max_transmit_rate; + __le16 periodic_interval; + u8 reserved4; + s8 periodic_rssi_thr; + u8 num_of_probe_requests; + u8 probe_delay; + u8 num_of_ssids; + u8 num_of_channels; + __le32 min_channel_time; + __le32 max_channel_time; + __le32 tx_power_level; /* signed value */ + struct hif_ssid_def ssid_def[HIF_API_MAX_NB_SSIDS]; + u8 channel_list[]; +} __packed; + +struct hif_cnf_start_scan { + __le32 status; +} __packed; + +struct hif_cnf_stop_scan { + __le32 status; +} __packed; + +enum hif_pm_mode_status { + HIF_PM_MODE_ACTIVE = 0x0, + HIF_PM_MODE_PS = 0x1, + HIF_PM_MODE_UNDETERMINED = 0x2 +}; + +struct hif_ind_scan_cmpl { + __le32 status; + u8 pm_mode; + u8 num_channels_completed; + __le16 reserved; +} __packed; + +enum hif_queue_id { + HIF_QUEUE_ID_BACKGROUND = 0x0, + HIF_QUEUE_ID_BESTEFFORT = 0x1, + HIF_QUEUE_ID_VIDEO = 0x2, + HIF_QUEUE_ID_VOICE = 0x3 +}; + +enum hif_frame_format { + HIF_FRAME_FORMAT_NON_HT = 0x0, + HIF_FRAME_FORMAT_MIXED_FORMAT_HT = 0x1, + HIF_FRAME_FORMAT_GF_HT_11N = 0x2 +}; + +struct hif_req_tx { + /* packet_id is not interpreted by the device, so it is not necessary to + * declare it little endian + */ + u32 packet_id; + u8 max_tx_rate; + u8 queue_id:2; + u8 peer_sta_id:4; + u8 reserved1:2; + u8 more:1; + u8 fc_offset:3; + u8 after_dtim:1; + u8 reserved2:3; + u8 start_exp:1; + u8 reserved3:3; + u8 retry_policy_index:4; + __le32 reserved4; + __le32 expire_time; + u8 frame_format:4; + u8 fec_coding:1; + u8 short_gi:1; + u8 reserved5:1; + u8 stbc:1; + u8 reserved6; + u8 aggregation:1; + u8 reserved7:7; + u8 reserved8; + u8 frame[]; +} __packed; + +enum hif_qos_ackplcy { + HIF_QOS_ACKPLCY_NORMAL = 0x0, + HIF_QOS_ACKPLCY_TXNOACK = 0x1, + HIF_QOS_ACKPLCY_NOEXPACK = 0x2, + HIF_QOS_ACKPLCY_BLCKACK = 0x3 +}; + +struct hif_cnf_tx { + __le32 status; + /* packet_id is copied from struct hif_req_tx without been interpreted + * by the device, so it is not necessary to declare it little endian + */ + u32 packet_id; + u8 txed_rate; + u8 ack_failures; + u8 aggr:1; + u8 requeue:1; + u8 ack_policy:2; + u8 txop_limit:1; + u8 reserved1:3; + u8 reserved2; + __le32 media_delay; + __le32 tx_queue_delay; +} __packed; + +struct hif_cnf_multi_transmit { + u8 num_tx_confs; + u8 reserved[3]; + struct hif_cnf_tx tx_conf_payload[]; +} __packed; + +enum hif_ri_flags_encrypt { + HIF_RI_FLAGS_UNENCRYPTED = 0x0, + HIF_RI_FLAGS_WEP_ENCRYPTED = 0x1, + HIF_RI_FLAGS_TKIP_ENCRYPTED = 0x2, + HIF_RI_FLAGS_AES_ENCRYPTED = 0x3, + HIF_RI_FLAGS_WAPI_ENCRYPTED = 0x4 +}; + +struct hif_ind_rx { + __le32 status; + u8 channel_number; + u8 reserved1; + u8 rxed_rate; + u8 rcpi_rssi; + u8 encryp:3; + u8 in_aggr:1; + u8 first_aggr:1; + u8 last_aggr:1; + u8 defrag:1; + u8 beacon:1; + u8 tim:1; + u8 bitmap:1; + u8 match_ssid:1; + u8 match_bssid:1; + u8 more:1; + u8 reserved2:1; + u8 ht:1; + u8 stbc:1; + u8 match_uc_addr:1; + u8 match_mc_addr:1; + u8 match_bc_addr:1; + u8 key_type:1; + u8 key_index:4; + u8 reserved3:1; + u8 peer_sta_id:4; + u8 reserved4:2; + u8 reserved5:1; + u8 frame[]; +} __packed; + +struct hif_req_edca_queue_params { + u8 queue_id; + u8 reserved1; + u8 aifsn; + u8 reserved2; + __le16 cw_min; + __le16 cw_max; + __le16 tx_op_limit; + __le16 allowed_medium_time; + __le32 reserved3; +} __packed; + +struct hif_cnf_edca_queue_params { + __le32 status; +} __packed; + +struct hif_req_join { + u8 infrastructure_bss_mode:1; + u8 reserved1:7; + u8 band; + u8 channel_number; + u8 reserved2; + u8 bssid[ETH_ALEN]; + __le16 atim_window; + u8 short_preamble:1; + u8 reserved3:7; + u8 probe_for_join; + u8 reserved4; + u8 reserved5:2; + u8 force_no_beacon:1; + u8 force_with_ind:1; + u8 reserved6:4; + __le32 ssid_length; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + __le32 beacon_interval; + __le32 basic_rate_set; +} __packed; + +struct hif_cnf_join { + __le32 status; +} __packed; + +struct hif_ind_join_complete { + __le32 status; +} __packed; + +struct hif_req_set_bss_params { + u8 lost_count_only:1; + u8 reserved:7; + u8 beacon_lost_count; + __le16 aid; + __le32 operational_rate_set; +} __packed; + +struct hif_cnf_set_bss_params { + __le32 status; +} __packed; + +struct hif_req_set_pm_mode { + u8 enter_psm:1; + u8 reserved:6; + u8 fast_psm:1; + u8 fast_psm_idle_period; + u8 ap_psm_change_period; + u8 min_auto_ps_poll_period; +} __packed; + +struct hif_cnf_set_pm_mode { + __le32 status; +} __packed; + +struct hif_ind_set_pm_mode_cmpl { + __le32 status; + u8 pm_mode; + u8 reserved[3]; +} __packed; + +struct hif_req_start { + u8 mode; + u8 band; + u8 channel_number; + u8 reserved1; + __le32 reserved2; + __le32 beacon_interval; + u8 dtim_period; + u8 short_preamble:1; + u8 reserved3:7; + u8 reserved4; + u8 ssid_length; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + __le32 basic_rate_set; +} __packed; + +struct hif_cnf_start { + __le32 status; +} __packed; + +struct hif_req_beacon_transmit { + u8 enable_beaconing; + u8 reserved[3]; +} __packed; + +struct hif_cnf_beacon_transmit { + __le32 status; +} __packed; + +#define HIF_LINK_ID_MAX 14 +#define HIF_LINK_ID_NOT_ASSOCIATED (HIF_LINK_ID_MAX + 1) + +struct hif_req_map_link { + u8 mac_addr[ETH_ALEN]; + u8 unmap:1; + u8 mfpc:1; + u8 reserved:6; + u8 peer_sta_id; +} __packed; + +struct hif_cnf_map_link { + __le32 status; +} __packed; + +struct hif_ind_suspend_resume_tx { + u8 resume:1; + u8 reserved1:2; + u8 bc_mc_only:1; + u8 reserved2:4; + u8 reserved3; + __le16 peer_sta_set; +} __packed; + + +#define MAX_KEY_ENTRIES 24 +#define HIF_API_WEP_KEY_DATA_SIZE 16 +#define HIF_API_TKIP_KEY_DATA_SIZE 16 +#define HIF_API_RX_MIC_KEY_SIZE 8 +#define HIF_API_TX_MIC_KEY_SIZE 8 +#define HIF_API_AES_KEY_DATA_SIZE 16 +#define HIF_API_WAPI_KEY_DATA_SIZE 16 +#define HIF_API_MIC_KEY_DATA_SIZE 16 +#define HIF_API_IGTK_KEY_DATA_SIZE 16 +#define HIF_API_RX_SEQUENCE_COUNTER_SIZE 8 +#define HIF_API_IPN_SIZE 8 + +enum hif_key_type { + HIF_KEY_TYPE_WEP_DEFAULT = 0x0, + HIF_KEY_TYPE_WEP_PAIRWISE = 0x1, + HIF_KEY_TYPE_TKIP_GROUP = 0x2, + HIF_KEY_TYPE_TKIP_PAIRWISE = 0x3, + HIF_KEY_TYPE_AES_GROUP = 0x4, + HIF_KEY_TYPE_AES_PAIRWISE = 0x5, + HIF_KEY_TYPE_WAPI_GROUP = 0x6, + HIF_KEY_TYPE_WAPI_PAIRWISE = 0x7, + HIF_KEY_TYPE_IGTK_GROUP = 0x8, + HIF_KEY_TYPE_NONE = 0x9 +}; + +struct hif_wep_pairwise_key { + u8 peer_address[ETH_ALEN]; + u8 reserved; + u8 key_length; + u8 key_data[HIF_API_WEP_KEY_DATA_SIZE]; +} __packed; + +struct hif_wep_group_key { + u8 key_id; + u8 key_length; + u8 reserved[2]; + u8 key_data[HIF_API_WEP_KEY_DATA_SIZE]; +} __packed; + +struct hif_tkip_pairwise_key { + u8 peer_address[ETH_ALEN]; + u8 reserved[2]; + u8 tkip_key_data[HIF_API_TKIP_KEY_DATA_SIZE]; + u8 rx_mic_key[HIF_API_RX_MIC_KEY_SIZE]; + u8 tx_mic_key[HIF_API_TX_MIC_KEY_SIZE]; +} __packed; + +struct hif_tkip_group_key { + u8 tkip_key_data[HIF_API_TKIP_KEY_DATA_SIZE]; + u8 rx_mic_key[HIF_API_RX_MIC_KEY_SIZE]; + u8 key_id; + u8 reserved[3]; + u8 rx_sequence_counter[HIF_API_RX_SEQUENCE_COUNTER_SIZE]; +} __packed; + +struct hif_aes_pairwise_key { + u8 peer_address[ETH_ALEN]; + u8 reserved[2]; + u8 aes_key_data[HIF_API_AES_KEY_DATA_SIZE]; +} __packed; + +struct hif_aes_group_key { + u8 aes_key_data[HIF_API_AES_KEY_DATA_SIZE]; + u8 key_id; + u8 reserved[3]; + u8 rx_sequence_counter[HIF_API_RX_SEQUENCE_COUNTER_SIZE]; +} __packed; + +struct hif_wapi_pairwise_key { + u8 peer_address[ETH_ALEN]; + u8 key_id; + u8 reserved; + u8 wapi_key_data[HIF_API_WAPI_KEY_DATA_SIZE]; + u8 mic_key_data[HIF_API_MIC_KEY_DATA_SIZE]; +} __packed; + +struct hif_wapi_group_key { + u8 wapi_key_data[HIF_API_WAPI_KEY_DATA_SIZE]; + u8 mic_key_data[HIF_API_MIC_KEY_DATA_SIZE]; + u8 key_id; + u8 reserved[3]; +} __packed; + +struct hif_igtk_group_key { + u8 igtk_key_data[HIF_API_IGTK_KEY_DATA_SIZE]; + u8 key_id; + u8 reserved[3]; + u8 ipn[HIF_API_IPN_SIZE]; +} __packed; + +struct hif_req_add_key { + u8 type; + u8 entry_index; + u8 int_id:2; + u8 reserved1:6; + u8 reserved2; + union { + struct hif_wep_pairwise_key wep_pairwise_key; + struct hif_wep_group_key wep_group_key; + struct hif_tkip_pairwise_key tkip_pairwise_key; + struct hif_tkip_group_key tkip_group_key; + struct hif_aes_pairwise_key aes_pairwise_key; + struct hif_aes_group_key aes_group_key; + struct hif_wapi_pairwise_key wapi_pairwise_key; + struct hif_wapi_group_key wapi_group_key; + struct hif_igtk_group_key igtk_group_key; + } key; +} __packed; + +struct hif_cnf_add_key { + __le32 status; +} __packed; + +struct hif_req_remove_key { + u8 entry_index; + u8 reserved[3]; +} __packed; + +struct hif_cnf_remove_key { + __le32 status; +} __packed; + +enum hif_event_ind { + HIF_EVENT_IND_BSSLOST = 0x1, + HIF_EVENT_IND_BSSREGAINED = 0x2, + HIF_EVENT_IND_RCPI_RSSI = 0x3, + HIF_EVENT_IND_PS_MODE_ERROR = 0x4, + HIF_EVENT_IND_INACTIVITY = 0x5 +}; + +enum hif_ps_mode_error { + HIF_PS_ERROR_NO_ERROR = 0, + HIF_PS_ERROR_AP_NOT_RESP_TO_POLL = 1, + HIF_PS_ERROR_AP_NOT_RESP_TO_UAPSD_TRIGGER = 2, + HIF_PS_ERROR_AP_SENT_UNICAST_IN_DOZE = 3, + HIF_PS_ERROR_AP_NO_DATA_AFTER_TIM = 4 +}; + +struct hif_ind_event { + __le32 event_id; + union { + u8 rcpi_rssi; + __le32 ps_mode_error; + __le32 peer_sta_set; + } event_data; +} __packed; + +#endif diff --git a/drivers/net/wireless/silabs/wfx/hif_api_general.h b/drivers/net/wireless/silabs/wfx/hif_api_general.h new file mode 100644 index 000000000000..3e4bd509dd78 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_api_general.h @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * WF200 hardware interface definitions + * + * Copyright (c) 2018-2020, Silicon Laboratories Inc. + */ + +#ifndef WFX_HIF_API_GENERAL_H +#define WFX_HIF_API_GENERAL_H + +#include +#include + +#define HIF_ID_IS_INDICATION 0x80 +#define HIF_COUNTER_MAX 7 + +struct hif_msg { + __le16 len; + u8 id; + u8 reserved:1; + u8 interface:2; + u8 seqnum:3; + u8 encrypted:2; + u8 body[]; +} __packed; + +enum hif_general_requests_ids { + HIF_REQ_ID_CONFIGURATION = 0x09, + HIF_REQ_ID_CONTROL_GPIO = 0x26, + HIF_REQ_ID_SET_SL_MAC_KEY = 0x27, + HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS = 0x28, + HIF_REQ_ID_SL_CONFIGURE = 0x29, + HIF_REQ_ID_PREVENT_ROLLBACK = 0x2a, + HIF_REQ_ID_PTA_SETTINGS = 0x2b, + HIF_REQ_ID_PTA_PRIORITY = 0x2c, + HIF_REQ_ID_PTA_STATE = 0x2d, + HIF_REQ_ID_SHUT_DOWN = 0x32, +}; + +enum hif_general_confirmations_ids { + HIF_CNF_ID_CONFIGURATION = 0x09, + HIF_CNF_ID_CONTROL_GPIO = 0x26, + HIF_CNF_ID_SET_SL_MAC_KEY = 0x27, + HIF_CNF_ID_SL_EXCHANGE_PUB_KEYS = 0x28, + HIF_CNF_ID_SL_CONFIGURE = 0x29, + HIF_CNF_ID_PREVENT_ROLLBACK = 0x2a, + HIF_CNF_ID_PTA_SETTINGS = 0x2b, + HIF_CNF_ID_PTA_PRIORITY = 0x2c, + HIF_CNF_ID_PTA_STATE = 0x2d, + HIF_CNF_ID_SHUT_DOWN = 0x32, +}; + +enum hif_general_indications_ids { + HIF_IND_ID_EXCEPTION = 0xe0, + HIF_IND_ID_STARTUP = 0xe1, + HIF_IND_ID_WAKEUP = 0xe2, + HIF_IND_ID_GENERIC = 0xe3, + HIF_IND_ID_ERROR = 0xe4, + HIF_IND_ID_SL_EXCHANGE_PUB_KEYS = 0xe5 +}; + +#define HIF_STATUS_SUCCESS (cpu_to_le32(0x0000)) +#define HIF_STATUS_FAIL (cpu_to_le32(0x0001)) +#define HIF_STATUS_INVALID_PARAMETER (cpu_to_le32(0x0002)) +#define HIF_STATUS_WARNING (cpu_to_le32(0x0003)) +#define HIF_STATUS_UNKNOWN_REQUEST (cpu_to_le32(0x0004)) +#define HIF_STATUS_RX_FAIL_DECRYPT (cpu_to_le32(0x0010)) +#define HIF_STATUS_RX_FAIL_MIC (cpu_to_le32(0x0011)) +#define HIF_STATUS_RX_FAIL_NO_KEY (cpu_to_le32(0x0012)) +#define HIF_STATUS_TX_FAIL_RETRIES (cpu_to_le32(0x0013)) +#define HIF_STATUS_TX_FAIL_TIMEOUT (cpu_to_le32(0x0014)) +#define HIF_STATUS_TX_FAIL_REQUEUE (cpu_to_le32(0x0015)) +#define HIF_STATUS_REFUSED (cpu_to_le32(0x0016)) +#define HIF_STATUS_BUSY (cpu_to_le32(0x0017)) +#define HIF_STATUS_SLK_SET_KEY_SUCCESS (cpu_to_le32(0x005A)) +#define HIF_STATUS_SLK_SET_KEY_ALREADY_BURNED (cpu_to_le32(0x006B)) +#define HIF_STATUS_SLK_SET_KEY_DISALLOWED_MODE (cpu_to_le32(0x007C)) +#define HIF_STATUS_SLK_SET_KEY_UNKNOWN_MODE (cpu_to_le32(0x008D)) +#define HIF_STATUS_SLK_NEGO_SUCCESS (cpu_to_le32(0x009E)) +#define HIF_STATUS_SLK_NEGO_FAILED (cpu_to_le32(0x00AF)) +#define HIF_STATUS_ROLLBACK_SUCCESS (cpu_to_le32(0x1234)) +#define HIF_STATUS_ROLLBACK_FAIL (cpu_to_le32(0x1256)) + +enum hif_api_rate_index { + API_RATE_INDEX_B_1MBPS = 0, + API_RATE_INDEX_B_2MBPS = 1, + API_RATE_INDEX_B_5P5MBPS = 2, + API_RATE_INDEX_B_11MBPS = 3, + API_RATE_INDEX_PBCC_22MBPS = 4, + API_RATE_INDEX_PBCC_33MBPS = 5, + API_RATE_INDEX_G_6MBPS = 6, + API_RATE_INDEX_G_9MBPS = 7, + API_RATE_INDEX_G_12MBPS = 8, + API_RATE_INDEX_G_18MBPS = 9, + API_RATE_INDEX_G_24MBPS = 10, + API_RATE_INDEX_G_36MBPS = 11, + API_RATE_INDEX_G_48MBPS = 12, + API_RATE_INDEX_G_54MBPS = 13, + API_RATE_INDEX_N_6P5MBPS = 14, + API_RATE_INDEX_N_13MBPS = 15, + API_RATE_INDEX_N_19P5MBPS = 16, + API_RATE_INDEX_N_26MBPS = 17, + API_RATE_INDEX_N_39MBPS = 18, + API_RATE_INDEX_N_52MBPS = 19, + API_RATE_INDEX_N_58P5MBPS = 20, + API_RATE_INDEX_N_65MBPS = 21, + API_RATE_NUM_ENTRIES = 22 +}; + +struct hif_ind_startup { + /* As the others, this struct is interpreted as little endian by the + * device. However, this struct is also used by the driver. We prefer to + * declare it in native order and doing byte swap on reception. + */ + __le32 status; + u16 hardware_id; + u8 opn[14]; + u8 uid[8]; + u16 num_inp_ch_bufs; + u16 size_inp_ch_buf; + u8 num_links_ap; + u8 num_interfaces; + u8 mac_addr[2][ETH_ALEN]; + u8 api_version_minor; + u8 api_version_major; + u8 link_mode:2; + u8 reserved1:6; + u8 reserved2; + u8 reserved3; + u8 reserved4; + u8 firmware_build; + u8 firmware_minor; + u8 firmware_major; + u8 firmware_type; + u8 disabled_channel_list[2]; + u8 region_sel_mode:4; + u8 reserved5:4; + u8 phy1_region:3; + u8 phy0_region:3; + u8 otp_phy_ver:2; + u32 supported_rate_mask; + u8 firmware_label[128]; +} __packed; + +struct hif_ind_wakeup { +} __packed; + +struct hif_req_configuration { + __le16 length; + u8 pds_data[]; +} __packed; + +struct hif_cnf_configuration { + __le32 status; +} __packed; + +enum hif_gpio_mode { + HIF_GPIO_MODE_D0 = 0x0, + HIF_GPIO_MODE_D1 = 0x1, + HIF_GPIO_MODE_OD0 = 0x2, + HIF_GPIO_MODE_OD1 = 0x3, + HIF_GPIO_MODE_TRISTATE = 0x4, + HIF_GPIO_MODE_TOGGLE = 0x5, + HIF_GPIO_MODE_READ = 0x6 +}; + +struct hif_req_control_gpio { + u8 gpio_label; + u8 gpio_mode; +} __packed; + +struct hif_cnf_control_gpio { + __le32 status; + __le32 value; +} __packed; + +enum hif_generic_indication_type { + HIF_GENERIC_INDICATION_TYPE_RAW = 0x0, + HIF_GENERIC_INDICATION_TYPE_STRING = 0x1, + HIF_GENERIC_INDICATION_TYPE_RX_STATS = 0x2, + HIF_GENERIC_INDICATION_TYPE_TX_POWER_LOOP_INFO = 0x3, +}; + +struct hif_rx_stats { + __le32 nb_rx_frame; + __le32 nb_crc_frame; + __le32 per_total; + __le32 throughput; + __le32 nb_rx_by_rate[API_RATE_NUM_ENTRIES]; + __le16 per[API_RATE_NUM_ENTRIES]; + __le16 snr[API_RATE_NUM_ENTRIES]; /* signed value */ + __le16 rssi[API_RATE_NUM_ENTRIES]; /* signed value */ + __le16 cfo[API_RATE_NUM_ENTRIES]; /* signed value */ + __le32 date; + __le32 pwr_clk_freq; + u8 is_ext_pwr_clk; + s8 current_temp; +} __packed; + +struct hif_tx_power_loop_info { + __le16 tx_gain_dig; + __le16 tx_gain_pa; + __le16 target_pout; /* signed value */ + __le16 p_estimation; /* signed value */ + __le16 vpdet; + u8 measurement_index; + u8 reserved; +} __packed; + +struct hif_ind_generic { + __le32 type; + union { + struct hif_rx_stats rx_stats; + struct hif_tx_power_loop_info tx_power_loop_info; + } data; +} __packed; + +enum hif_error { + HIF_ERROR_FIRMWARE_ROLLBACK = 0x00, + HIF_ERROR_FIRMWARE_DEBUG_ENABLED = 0x01, + HIF_ERROR_SLK_OUTDATED_SESSION_KEY = 0x02, + HIF_ERROR_SLK_SESSION_KEY = 0x03, + HIF_ERROR_OOR_VOLTAGE = 0x04, + HIF_ERROR_PDS_PAYLOAD = 0x05, + HIF_ERROR_OOR_TEMPERATURE = 0x06, + HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE = 0x07, + HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED = 0x08, + HIF_ERROR_SLK_OVERFLOW = 0x09, + HIF_ERROR_SLK_DECRYPTION = 0x0a, + HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE = 0x0b, + HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW = 0x0c, + HIF_ERROR_HIF_RX_DATA_TOO_LARGE = 0x0e, + HIF_ERROR_HIF_TX_QUEUE_FULL = 0x0d, + HIF_ERROR_HIF_BUS = 0x0f, + HIF_ERROR_PDS_TESTFEATURE = 0x10, + HIF_ERROR_SLK_UNCONFIGURED = 0x11, +}; + +struct hif_ind_error { + __le32 type; + u8 data[]; +} __packed; + +struct hif_ind_exception { + __le32 type; + u8 data[]; +} __packed; + +enum hif_secure_link_state { + SEC_LINK_UNAVAILABLE = 0x0, + SEC_LINK_RESERVED = 0x1, + SEC_LINK_EVAL = 0x2, + SEC_LINK_ENFORCED = 0x3 +}; + +#endif diff --git a/drivers/net/wireless/silabs/wfx/hif_api_mib.h b/drivers/net/wireless/silabs/wfx/hif_api_mib.h new file mode 100644 index 000000000000..da534f244757 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_api_mib.h @@ -0,0 +1,346 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * WF200 hardware interface definitions + * + * Copyright (c) 2018-2020, Silicon Laboratories Inc. + */ + +#ifndef WFX_HIF_API_MIB_H +#define WFX_HIF_API_MIB_H + +#include "hif_api_general.h" + +#define HIF_API_IPV4_ADDRESS_SIZE 4 +#define HIF_API_IPV6_ADDRESS_SIZE 16 + +enum hif_mib_ids { + HIF_MIB_ID_GL_OPERATIONAL_POWER_MODE = 0x2000, + HIF_MIB_ID_GL_BLOCK_ACK_INFO = 0x2001, + HIF_MIB_ID_GL_SET_MULTI_MSG = 0x2002, + HIF_MIB_ID_CCA_CONFIG = 0x2003, + HIF_MIB_ID_ETHERTYPE_DATAFRAME_CONDITION = 0x2010, + HIF_MIB_ID_PORT_DATAFRAME_CONDITION = 0x2011, + HIF_MIB_ID_MAGIC_DATAFRAME_CONDITION = 0x2012, + HIF_MIB_ID_MAC_ADDR_DATAFRAME_CONDITION = 0x2013, + HIF_MIB_ID_IPV4_ADDR_DATAFRAME_CONDITION = 0x2014, + HIF_MIB_ID_IPV6_ADDR_DATAFRAME_CONDITION = 0x2015, + HIF_MIB_ID_UC_MC_BC_DATAFRAME_CONDITION = 0x2016, + HIF_MIB_ID_CONFIG_DATA_FILTER = 0x2017, + HIF_MIB_ID_SET_DATA_FILTERING = 0x2018, + HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE = 0x2019, + HIF_MIB_ID_NS_IP_ADDRESSES_TABLE = 0x201A, + HIF_MIB_ID_RX_FILTER = 0x201B, + HIF_MIB_ID_BEACON_FILTER_TABLE = 0x201C, + HIF_MIB_ID_BEACON_FILTER_ENABLE = 0x201D, + HIF_MIB_ID_GRP_SEQ_COUNTER = 0x2030, + HIF_MIB_ID_TSF_COUNTER = 0x2031, + HIF_MIB_ID_STATISTICS_TABLE = 0x2032, + HIF_MIB_ID_COUNTERS_TABLE = 0x2033, + HIF_MIB_ID_MAX_TX_POWER_LEVEL = 0x2034, + HIF_MIB_ID_EXTENDED_COUNTERS_TABLE = 0x2035, + HIF_MIB_ID_DOT11_MAC_ADDRESS = 0x2040, + HIF_MIB_ID_DOT11_MAX_TRANSMIT_MSDU_LIFETIME = 0x2041, + HIF_MIB_ID_DOT11_MAX_RECEIVE_LIFETIME = 0x2042, + HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID = 0x2043, + HIF_MIB_ID_DOT11_RTS_THRESHOLD = 0x2044, + HIF_MIB_ID_SLOT_TIME = 0x2045, + HIF_MIB_ID_CURRENT_TX_POWER_LEVEL = 0x2046, + HIF_MIB_ID_NON_ERP_PROTECTION = 0x2047, + HIF_MIB_ID_TEMPLATE_FRAME = 0x2048, + HIF_MIB_ID_BEACON_WAKEUP_PERIOD = 0x2049, + HIF_MIB_ID_RCPI_RSSI_THRESHOLD = 0x204A, + HIF_MIB_ID_BLOCK_ACK_POLICY = 0x204B, + HIF_MIB_ID_OVERRIDE_INTERNAL_TX_RATE = 0x204C, + HIF_MIB_ID_SET_ASSOCIATION_MODE = 0x204D, + HIF_MIB_ID_SET_UAPSD_INFORMATION = 0x204E, + HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY = 0x204F, + HIF_MIB_ID_PROTECTED_MGMT_POLICY = 0x2050, + HIF_MIB_ID_SET_HT_PROTECTION = 0x2051, + HIF_MIB_ID_KEEP_ALIVE_PERIOD = 0x2052, + HIF_MIB_ID_ARP_KEEP_ALIVE_PERIOD = 0x2053, + HIF_MIB_ID_INACTIVITY_TIMER = 0x2054, + HIF_MIB_ID_INTERFACE_PROTECTION = 0x2055, + HIF_MIB_ID_BEACON_STATS = 0x2056, +}; + +enum hif_op_power_mode { + HIF_OP_POWER_MODE_ACTIVE = 0x0, + HIF_OP_POWER_MODE_DOZE = 0x1, + HIF_OP_POWER_MODE_QUIESCENT = 0x2 +}; + +struct hif_mib_gl_operational_power_mode { + u8 power_mode:4; + u8 reserved1:3; + u8 wup_ind_activation:1; + u8 reserved2[3]; +} __packed; + +struct hif_mib_gl_set_multi_msg { + u8 enable_multi_tx_conf:1; + u8 reserved1:7; + u8 reserved2[3]; +} __packed; + +enum hif_arp_ns_frame_treatment { + HIF_ARP_NS_FILTERING_DISABLE = 0x0, + HIF_ARP_NS_FILTERING_ENABLE = 0x1, + HIF_ARP_NS_REPLY_ENABLE = 0x2 +}; + +struct hif_mib_arp_ip_addr_table { + u8 condition_idx; + u8 arp_enable; + u8 reserved[2]; + u8 ipv4_address[HIF_API_IPV4_ADDRESS_SIZE]; +} __packed; + +struct hif_mib_rx_filter { + u8 reserved1:1; + u8 bssid_filter:1; + u8 reserved2:1; + u8 fwd_probe_req:1; + u8 keep_alive_filter:1; + u8 reserved3:3; + u8 reserved4[3]; +} __packed; + +struct hif_ie_table_entry { + u8 ie_id; + u8 has_changed:1; + u8 no_longer:1; + u8 has_appeared:1; + u8 reserved:1; + u8 num_match_data:4; + u8 oui[3]; + u8 match_data[3]; +} __packed; + +struct hif_mib_bcn_filter_table { + __le32 num_of_info_elmts; + struct hif_ie_table_entry ie_table[]; +} __packed; + +enum hif_beacon_filter { + HIF_BEACON_FILTER_DISABLE = 0x0, + HIF_BEACON_FILTER_ENABLE = 0x1, + HIF_BEACON_FILTER_AUTO_ERP = 0x2 +}; + +struct hif_mib_bcn_filter_enable { + __le32 enable; + __le32 bcn_count; +} __packed; + +struct hif_mib_extended_count_table { + __le32 count_drop_plcp; + __le32 count_drop_fcs; + __le32 count_tx_frames; + __le32 count_rx_frames; + __le32 count_rx_frames_failed; + __le32 count_drop_decryption; + __le32 count_drop_tkip_mic; + __le32 count_drop_no_key; + __le32 count_tx_frames_multicast; + __le32 count_tx_frames_success; + __le32 count_tx_frames_failed; + __le32 count_tx_frames_retried; + __le32 count_tx_frames_multi_retried; + __le32 count_drop_duplicate; + __le32 count_rts_success; + __le32 count_rts_failed; + __le32 count_ack_failed; + __le32 count_rx_frames_multicast; + __le32 count_rx_frames_success; + __le32 count_drop_cmac_icv; + __le32 count_drop_cmac_replay; + __le32 count_drop_ccmp_replay; + __le32 count_drop_bip_mic; + __le32 count_rx_bcn_success; + __le32 count_rx_bcn_miss; + __le32 count_rx_bcn_dtim; + __le32 count_rx_bcn_dtim_aid0_clr; + __le32 count_rx_bcn_dtim_aid0_set; + __le32 reserved[12]; +} __packed; + +struct hif_mib_count_table { + __le32 count_drop_plcp; + __le32 count_drop_fcs; + __le32 count_tx_frames; + __le32 count_rx_frames; + __le32 count_rx_frames_failed; + __le32 count_drop_decryption; + __le32 count_drop_tkip_mic; + __le32 count_drop_no_key; + __le32 count_tx_frames_multicast; + __le32 count_tx_frames_success; + __le32 count_tx_frames_failed; + __le32 count_tx_frames_retried; + __le32 count_tx_frames_multi_retried; + __le32 count_drop_duplicate; + __le32 count_rts_success; + __le32 count_rts_failed; + __le32 count_ack_failed; + __le32 count_rx_frames_multicast; + __le32 count_rx_frames_success; + __le32 count_drop_cmac_icv; + __le32 count_drop_cmac_replay; + __le32 count_drop_ccmp_replay; + __le32 count_drop_bip_mic; +} __packed; + +struct hif_mib_mac_address { + u8 mac_addr[ETH_ALEN]; + __le16 reserved; +} __packed; + +struct hif_mib_wep_default_key_id { + u8 wep_default_key_id; + u8 reserved[3]; +} __packed; + +struct hif_mib_dot11_rts_threshold { + __le32 threshold; +} __packed; + +struct hif_mib_slot_time { + __le32 slot_time; +} __packed; + +struct hif_mib_current_tx_power_level { + __le32 power_level; /* signed value */ +} __packed; + +struct hif_mib_non_erp_protection { + u8 use_cts_to_self:1; + u8 reserved1:7; + u8 reserved2[3]; +} __packed; + +enum hif_tmplt { + HIF_TMPLT_PRBREQ = 0x0, + HIF_TMPLT_BCN = 0x1, + HIF_TMPLT_NULL = 0x2, + HIF_TMPLT_QOSNUL = 0x3, + HIF_TMPLT_PSPOLL = 0x4, + HIF_TMPLT_PRBRES = 0x5, + HIF_TMPLT_ARP = 0x6, + HIF_TMPLT_NA = 0x7 +}; + +#define HIF_API_MAX_TEMPLATE_FRAME_SIZE 700 + +struct hif_mib_template_frame { + u8 frame_type; + u8 init_rate:7; + u8 mode:1; + __le16 frame_length; + u8 frame[]; +} __packed; + +struct hif_mib_beacon_wake_up_period { + u8 wakeup_period_min; + u8 receive_dtim:1; + u8 reserved1:7; + u8 wakeup_period_max; + u8 reserved2; +} __packed; + +struct hif_mib_rcpi_rssi_threshold { + u8 detection:1; + u8 rcpi_rssi:1; + u8 upperthresh:1; + u8 lowerthresh:1; + u8 reserved:4; + u8 lower_threshold; + u8 upper_threshold; + u8 rolling_average_count; +} __packed; + +#define DEFAULT_BA_MAX_RX_BUFFER_SIZE 16 + +struct hif_mib_block_ack_policy { + u8 block_ack_tx_tid_policy; + u8 reserved1; + u8 block_ack_rx_tid_policy; + u8 block_ack_rx_max_buffer_size; +} __packed; + +enum hif_mpdu_start_spacing { + HIF_MPDU_START_SPACING_NO_RESTRIC = 0x0, + HIF_MPDU_START_SPACING_QUARTER = 0x1, + HIF_MPDU_START_SPACING_HALF = 0x2, + HIF_MPDU_START_SPACING_ONE = 0x3, + HIF_MPDU_START_SPACING_TWO = 0x4, + HIF_MPDU_START_SPACING_FOUR = 0x5, + HIF_MPDU_START_SPACING_EIGHT = 0x6, + HIF_MPDU_START_SPACING_SIXTEEN = 0x7 +}; + +struct hif_mib_set_association_mode { + u8 preambtype_use:1; + u8 mode:1; + u8 rateset:1; + u8 spacing:1; + u8 reserved1:4; + u8 short_preamble:1; + u8 reserved2:7; + u8 greenfield:1; + u8 reserved3:7; + u8 mpdu_start_spacing; + __le32 basic_rate_set; +} __packed; + +struct hif_mib_set_uapsd_information { + u8 trig_bckgrnd:1; + u8 trig_be:1; + u8 trig_video:1; + u8 trig_voice:1; + u8 reserved1:4; + u8 deliv_bckgrnd:1; + u8 deliv_be:1; + u8 deliv_video:1; + u8 deliv_voice:1; + u8 reserved2:4; + __le16 min_auto_trigger_interval; + __le16 max_auto_trigger_interval; + __le16 auto_trigger_step; +} __packed; + +struct hif_tx_rate_retry_policy { + u8 policy_index; + u8 short_retry_count; + u8 long_retry_count; + u8 first_rate_sel:2; + u8 terminate:1; + u8 count_init:1; + u8 reserved1:4; + u8 rate_recovery_count; + u8 reserved2[3]; + u8 rates[12]; +} __packed; + +#define HIF_TX_RETRY_POLICY_MAX 15 +#define HIF_TX_RETRY_POLICY_INVALID HIF_TX_RETRY_POLICY_MAX + +struct hif_mib_set_tx_rate_retry_policy { + u8 num_tx_rate_policies; + u8 reserved[3]; + struct hif_tx_rate_retry_policy tx_rate_retry_policy[]; +} __packed; + +struct hif_mib_protected_mgmt_policy { + u8 pmf_enable:1; + u8 unpmf_allowed:1; + u8 host_enc_auth_frames:1; + u8 reserved1:5; + u8 reserved2[3]; +} __packed; + +struct hif_mib_keep_alive_period { + __le16 keep_alive_period; + u8 reserved[2]; +} __packed; + +#endif 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 From patchwork Mon Sep 20 16:11:26 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: 12505913 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 8DAE7C433F5 for ; Mon, 20 Sep 2021 16:14:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6E29760F70 for ; Mon, 20 Sep 2021 16:14:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243662AbhITQQQ (ORCPT ); Mon, 20 Sep 2021 12:16:16 -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 S242612AbhITQOh (ORCPT ); Mon, 20 Sep 2021 12:14:37 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lPVDt09G8tMhScVNCp45xB5Nbs53bc1XmBy2KNBzFJhpDm20uCwq0ofM9Wzdev05RI47hYgJBGeITbhp7ja7+otnECpU4yfNPxwxTi6SZZD+vj/fXdpgcgJStUC1D4Pv8RlBGnAN6QdsXcAr2q+zjWLfS8eTnVQToICpHYwy5ttbzPkgNM36p2aD56fpLaBHnfKXMNMlZmZeueVYqYSaC150W0cVra+mwVb9CljTUNBTW1bWrRYX8R8CPe4kQ4d7lXVpAIE7ooTXGo/LCxebNQ3/WMwvdRVn6h8qk6FqwSS6HozJl8A6PNxgT3gEFkzFVYZQiVu/AyCgXsDOlrK9Og== 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=xdE+7Y9kU+Kuls8oPQCRxATfxUpgKTkyNGR3RtiwYqc=; b=OI2AQOdrLf0fSPgZ7+CnYLpWEWEwv31EdL5KgQjwyr66Pr/S34Vwxp7/C3w4qcH/TsUglp6MN5rhSvFfU14Vl9hoD5kocHVAOv7rDfQUvSIr59jltzQX4X1W5OX8amr9MYv44YtPo47BMuDf0aKe2d8sroV+i1qW68H7noVZ07A2lL8wLUyXBWoC0/PgxPYyzjhEm7EM05dFySqKKI6wuDdgKhH6AUkx16v2HR/vzxQ/kW/HxyQcF7/uK5s2qb7dGVYG9E/ErvtPWP0vC7n2YPHBO5wFm3Y+I54/w8MD96BSgj23ivIV/Kc6bUXrEDep14SHsKR0o/m0mX01llGrLA== 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=xdE+7Y9kU+Kuls8oPQCRxATfxUpgKTkyNGR3RtiwYqc=; b=WlhXPF/D93Oe4VZyQ0OvXBy7lfemBqGT1ceEGcLRGl058ATq96WOVSjGHKgAj55kGgk0+fyeNoRVg1zXfTG6WuxizcuC3k9UmLB/p7M7/HkU+v8wKsOV9Ntmtph1t+6VDeqZ7EzmONLKo3LQ5m6GIsoPgDv9voCJm/87Hxz83fg= 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:28 +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:28 +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 14/24] wfx: add key.c/key.h Date: Mon, 20 Sep 2021 18:11:26 +0200 Message-Id: <20210920161136.2398632-15-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:26 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 674c307a-548b-4d78-c87c-08d97c5170ff X-MS-TrafficTypeDiagnostic: SN6PR11MB2557: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:346; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 5d8D7BsKbhQCuNAEtJK6gMQDApOkfD+79khQqLsoqxzkkZA468jRVAmQMDXfJ8Cvgitir12deS7WpbcWqEZwErPD5z3AL2x6w26BuBiEHAMbf15ps5Fxr9aCjPoir1j+6miUj3A+RgLhrnh/otCj7us95vDjnya4Tx4vqKKqNgkQLXI4cQswjAuTZpwwdPnJBP3bw8CZ/W+1S12rR0ZfyVkVkCR2iOiHgQZHYt9XRsjhrQRYwo5Xw1nAUk2DckgvzSyXhrz0L4UAzsbbY9rjjhw+X5PGtyfGyRgWfeTb5daqbS59AKl4tmRJQqr63PCNSweUwgqHUydgp+CuuyXNK4r/6MyzSXya8c1z8hTQaggIcKjFNrjvv8Str9uD/JMw8xV1863PLkGrJRzzCAHN8nBp4PpirvGU9yHtvM1P9xdQInTHKafe4nMZCdbllGuOH8DY6XvVb/CuTBB40cWjHxKdVlKM/jMpAzNI3cTyFz8HjCuE6Gbag5kjETMadrGz72Xmsq/dtmODJVyjmowNffoIxaNT4QZjwOUNZCUzCyBLA1rMSnIXaJueJJK5B5DnWcJigDurH93Sj2T1acnkmAOu/EdmJgRVZ5dBRAhTQEYHjFrupYRpTgOocqcu9frXrx0FPKudYNwsSm8BzUpdYg== 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)(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: HrUjRt+eufEnxxcjTRQudWc1udIjPzHhj8lzhDprL8KmzioWJ+9KDV4Ld+JNWT2TpfcYhGkpCkAbYcK55k2wLPfDJ56XBCKDN5HBb47sr+Y68mPUAC06GatpV3U9fHGMyPA5ZUoeNXAVhm2KZ6oQAWNKhAMXhxI6OH59eFok05Zv1ZL2vO20tUDK3aolUZN8rzCGoyNhZtrwjtlll0Z+ys2qYPAEXoINt+JiN15LUzQO+5NR74dhUhfYxMLBaFbWToRC4cc4kjXgiCVC119qMyn5l354AwFXuvXs62QWVrkQv/642LaTbBrVCiSavkg3rPDcyZ/dQLJDykdBC58w3QEIZWOOw5hIgk1ccdqsskJHMUx5ifSdrITkvVH0OxptxABcjLp0wurX3YaxKGFRk7eXpHGjNoEXjyPap5p+rTnPOhUBeqfL9WzpkcY1d9r1xwasTEoZHfREeZlG2+FqNikEaKPXJXdpzDqbfhNjO/e+8kzj/Ik0qcG3qZRGPzZGYQ5lquIQLIrFACbszTzuUWu+VKq4xyRCRlDAicoIoIZkJ7LJLklSCmmk7KCgwJs5h5VUrhj9WyFeC+3kHtgIuaKPwXWpFodSFehVk4Yw25c57+Ul9VMeSk5yFRts8PFvWo5Tl1On7jRLeXOqJnV5OzPBTnZVQ8EohIQQYAmojs/5ZS/FSIqHP9wm7gyQbU1zLG5qD/4Ae0k7gfQTBXrwP47hxBHvcEc0X4+UF63bvbP43RdEYQ5/q1gQEm0YuE58HyPf4pqFOD9zITQACnFyUSq4nvPfElXmPyaAohhGHEFsMcyvBYNnILf7Q7i3zLEe X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 674c307a-548b-4d78-c87c-08d97c5170ff 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:28.2280 (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: +yLOnlvCo2/qNEA5juyh74xK8EZTOdORzkPsE1IPWHSGS1IioU5NoFhVjmOaai20d7OlULmgNGG2s1NoTarJLw== 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/key.c | 241 ++++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/key.h | 20 +++ 2 files changed, 261 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/key.c create mode 100644 drivers/net/wireless/silabs/wfx/key.h diff --git a/drivers/net/wireless/silabs/wfx/key.c b/drivers/net/wireless/silabs/wfx/key.c new file mode 100644 index 000000000000..65134a174683 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/key.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Key management related functions. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "key.h" +#include "wfx.h" +#include "hif_tx_mib.h" + +static int wfx_alloc_key(struct wfx_dev *wdev) +{ + int idx; + + idx = ffs(~wdev->key_map) - 1; + if (idx < 0 || idx >= MAX_KEY_ENTRIES) + return -1; + + wdev->key_map |= BIT(idx); + return idx; +} + +static void wfx_free_key(struct wfx_dev *wdev, int idx) +{ + WARN(!(wdev->key_map & BIT(idx)), "inconsistent key allocation"); + wdev->key_map &= ~BIT(idx); +} + +static u8 fill_wep_pair(struct hif_wep_pairwise_key *msg, + struct ieee80211_key_conf *key, u8 *peer_addr) +{ + WARN(key->keylen > sizeof(msg->key_data), "inconsistent data"); + msg->key_length = key->keylen; + memcpy(msg->key_data, key->key, key->keylen); + ether_addr_copy(msg->peer_address, peer_addr); + return HIF_KEY_TYPE_WEP_PAIRWISE; +} + +static u8 fill_wep_group(struct hif_wep_group_key *msg, + struct ieee80211_key_conf *key) +{ + WARN(key->keylen > sizeof(msg->key_data), "inconsistent data"); + msg->key_id = key->keyidx; + msg->key_length = key->keylen; + memcpy(msg->key_data, key->key, key->keylen); + return HIF_KEY_TYPE_WEP_DEFAULT; +} + +static u8 fill_tkip_pair(struct hif_tkip_pairwise_key *msg, + struct ieee80211_key_conf *key, u8 *peer_addr) +{ + u8 *keybuf = key->key; + + WARN(key->keylen != sizeof(msg->tkip_key_data) + + sizeof(msg->tx_mic_key) + + sizeof(msg->rx_mic_key), "inconsistent data"); + memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data)); + keybuf += sizeof(msg->tkip_key_data); + memcpy(msg->tx_mic_key, keybuf, sizeof(msg->tx_mic_key)); + keybuf += sizeof(msg->tx_mic_key); + memcpy(msg->rx_mic_key, keybuf, sizeof(msg->rx_mic_key)); + ether_addr_copy(msg->peer_address, peer_addr); + return HIF_KEY_TYPE_TKIP_PAIRWISE; +} + +static u8 fill_tkip_group(struct hif_tkip_group_key *msg, + struct ieee80211_key_conf *key, + struct ieee80211_key_seq *seq, + enum nl80211_iftype iftype) +{ + u8 *keybuf = key->key; + + WARN(key->keylen != sizeof(msg->tkip_key_data) + + 2 * sizeof(msg->rx_mic_key), "inconsistent data"); + msg->key_id = key->keyidx; + memcpy(msg->rx_sequence_counter, + &seq->tkip.iv16, sizeof(seq->tkip.iv16)); + memcpy(msg->rx_sequence_counter + sizeof(u16), + &seq->tkip.iv32, sizeof(seq->tkip.iv32)); + memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data)); + keybuf += sizeof(msg->tkip_key_data); + if (iftype == NL80211_IFTYPE_AP) + /* Use Tx MIC Key */ + memcpy(msg->rx_mic_key, keybuf + 0, sizeof(msg->rx_mic_key)); + else + /* Use Rx MIC Key */ + memcpy(msg->rx_mic_key, keybuf + 8, sizeof(msg->rx_mic_key)); + return HIF_KEY_TYPE_TKIP_GROUP; +} + +static u8 fill_ccmp_pair(struct hif_aes_pairwise_key *msg, + struct ieee80211_key_conf *key, u8 *peer_addr) +{ + WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data"); + ether_addr_copy(msg->peer_address, peer_addr); + memcpy(msg->aes_key_data, key->key, key->keylen); + return HIF_KEY_TYPE_AES_PAIRWISE; +} + +static u8 fill_ccmp_group(struct hif_aes_group_key *msg, + struct ieee80211_key_conf *key, + struct ieee80211_key_seq *seq) +{ + WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data"); + memcpy(msg->aes_key_data, key->key, key->keylen); + memcpy(msg->rx_sequence_counter, seq->ccmp.pn, sizeof(seq->ccmp.pn)); + memreverse(msg->rx_sequence_counter, sizeof(seq->ccmp.pn)); + msg->key_id = key->keyidx; + return HIF_KEY_TYPE_AES_GROUP; +} + +static u8 fill_sms4_pair(struct hif_wapi_pairwise_key *msg, + struct ieee80211_key_conf *key, u8 *peer_addr) +{ + u8 *keybuf = key->key; + + WARN(key->keylen != sizeof(msg->wapi_key_data) + + sizeof(msg->mic_key_data), "inconsistent data"); + ether_addr_copy(msg->peer_address, peer_addr); + memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data)); + keybuf += sizeof(msg->wapi_key_data); + memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data)); + msg->key_id = key->keyidx; + return HIF_KEY_TYPE_WAPI_PAIRWISE; +} + +static u8 fill_sms4_group(struct hif_wapi_group_key *msg, + struct ieee80211_key_conf *key) +{ + u8 *keybuf = key->key; + + WARN(key->keylen != sizeof(msg->wapi_key_data) + + sizeof(msg->mic_key_data), "inconsistent data"); + memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data)); + keybuf += sizeof(msg->wapi_key_data); + memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data)); + msg->key_id = key->keyidx; + return HIF_KEY_TYPE_WAPI_GROUP; +} + +static u8 fill_aes_cmac_group(struct hif_igtk_group_key *msg, + struct ieee80211_key_conf *key, + struct ieee80211_key_seq *seq) +{ + WARN(key->keylen != sizeof(msg->igtk_key_data), "inconsistent data"); + memcpy(msg->igtk_key_data, key->key, key->keylen); + memcpy(msg->ipn, seq->aes_cmac.pn, sizeof(seq->aes_cmac.pn)); + memreverse(msg->ipn, sizeof(seq->aes_cmac.pn)); + msg->key_id = key->keyidx; + return HIF_KEY_TYPE_IGTK_GROUP; +} + +static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + int ret; + struct hif_req_add_key k = { }; + struct ieee80211_key_seq seq; + struct wfx_dev *wdev = wvif->wdev; + int idx = wfx_alloc_key(wvif->wdev); + bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE; + + WARN(key->flags & IEEE80211_KEY_FLAG_PAIRWISE && !sta, "inconsistent data"); + ieee80211_get_key_rx_seq(key, 0, &seq); + if (idx < 0) + return -EINVAL; + k.int_id = wvif->id; + k.entry_index = idx; + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) { + if (pairwise) + k.type = fill_wep_pair(&k.key.wep_pairwise_key, key, + sta->addr); + else + k.type = fill_wep_group(&k.key.wep_group_key, key); + } else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { + if (pairwise) + k.type = fill_tkip_pair(&k.key.tkip_pairwise_key, key, + sta->addr); + else + k.type = fill_tkip_group(&k.key.tkip_group_key, key, + &seq, wvif->vif->type); + } else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) { + if (pairwise) + k.type = fill_ccmp_pair(&k.key.aes_pairwise_key, key, + sta->addr); + else + k.type = fill_ccmp_group(&k.key.aes_group_key, key, + &seq); + } else if (key->cipher == WLAN_CIPHER_SUITE_SMS4) { + if (pairwise) + k.type = fill_sms4_pair(&k.key.wapi_pairwise_key, key, + sta->addr); + else + k.type = fill_sms4_group(&k.key.wapi_group_key, key); + } else if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + k.type = fill_aes_cmac_group(&k.key.igtk_group_key, key, &seq); + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + } else { + dev_warn(wdev->dev, "unsupported key type %d\n", key->cipher); + wfx_free_key(wdev, idx); + return -EOPNOTSUPP; + } + ret = hif_add_key(wdev, &k); + if (ret) { + wfx_free_key(wdev, idx); + return -EOPNOTSUPP; + } + key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE | + IEEE80211_KEY_FLAG_RESERVE_TAILROOM; + key->hw_key_idx = idx; + return 0; +} + +static int wfx_remove_key(struct wfx_vif *wvif, struct ieee80211_key_conf *key) +{ + WARN(key->hw_key_idx >= MAX_KEY_ENTRIES, "corrupted hw_key_idx"); + wfx_free_key(wvif->wdev, key->hw_key_idx); + return hif_remove_key(wvif->wdev, key->hw_key_idx); +} + +int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + int ret = -EOPNOTSUPP; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + mutex_lock(&wvif->wdev->conf_mutex); + if (cmd == SET_KEY) + ret = wfx_add_key(wvif, sta, key); + if (cmd == DISABLE_KEY) + ret = wfx_remove_key(wvif, key); + mutex_unlock(&wvif->wdev->conf_mutex); + return ret; +} + diff --git a/drivers/net/wireless/silabs/wfx/key.h b/drivers/net/wireless/silabs/wfx/key.h new file mode 100644 index 000000000000..2d135eff7af2 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/key.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Key management related functions. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_KEY_H +#define WFX_KEY_H + +#include + +struct wfx_dev; +struct wfx_vif; + +int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); + +#endif From patchwork Mon Sep 20 16:11:27 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: 12505839 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=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 DE9DAC433EF for ; Mon, 20 Sep 2021 16:12:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C54086115B for ; Mon, 20 Sep 2021 16:12:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242454AbhITQOQ (ORCPT ); Mon, 20 Sep 2021 12:14:16 -0400 Received: from mail-bn7nam10on2076.outbound.protection.outlook.com ([40.107.92.76]:28992 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242836AbhITQOB (ORCPT ); Mon, 20 Sep 2021 12:14:01 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iPw4TZPcady7aZlzsdYINq2u/YlhowjD/BPphYwqTF4lPOJAIEoQNDK144Ee9x7YjdTdiTKU05IVVDU4V0NTVkrWG9Dus51CqT/gIh5crUvFoYtk4UF7As2ATgKOzw6Sx/SY9lUMyca5izaLvNnbyI8nSj9hZyQTsrROCkBmVeNM1fpLYtBl8VcRBUoIjXCRXYkzfW8q/ltbYgTz0tcQj0IfxX6TtjdDHkYCfojRubAWILtv/ihmI838yHhzmbHYQbYUUqALgasdSVxBc0uw51s/Nsc5dY57RVlBWN9mN2mdM3ZB+BdBy2m7E+wgMdr8HByJsFFLOvhoBi6VtOxxTQ== 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=ezy3MjvI3yi92gAj4tRKzzMs/rhPl2s12vEVz0oXbBM=; b=aoGwzT+XF35TCRK8e7V2bMsO/3SQL3pPoeTb+u7uW7/4roq/IyvMSDsTM6yTdzN2mn4PHjKXNfddoI4c9Fjf+RnbHy/ku+6+sDS2ZpeC8srOzPMeNxqRi4dbRAHBxCR8D3So+9JrHAWTxPnayvEKLCuWmiXd9Js0SVdjx0SSXENNpIoQBorjQOL3Msr2IJS2I/G9oB7WDsAnceqWZrzZ8t8DUr04a1gPr5MEHXweF+JlTHm/RUiag9bBc9I3as5s2fBV1UlapAmPZLBw76gIbcJVrP4pLjk26RbROKZn/D93ThOaJT+IjF5Yqt6GCoHy3PcT3HVRZYYyTirIYNCuaw== 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=ezy3MjvI3yi92gAj4tRKzzMs/rhPl2s12vEVz0oXbBM=; b=E3qNygiVM1x04J0IbrokVyJzm/c6KKZ8KtPvzFDXeWp3mKsRCYKG1GYtX2QHuZb9ppr2RM41NLVDfAp8oMs5pj1kPNS2VGE5DaZNsL1BkJMoyt5+Zpp1G7DEzS1S24eAKPT7Z2KzIeu6LBFGvE92K66Jq2SeTuC6hrzvt96jDwI= 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 SN6PR11MB2654.namprd11.prod.outlook.com (2603:10b6:805:54::31) 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:31 +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:31 +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 15/24] wfx: add hif_rx.c/hif_rx.h Date: Mon, 20 Sep 2021 18:11:27 +0200 Message-Id: <20210920161136.2398632-16-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:29 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 1e4a0e69-779f-48a2-2e32-08d97c5172cc X-MS-TrafficTypeDiagnostic: SN6PR11MB2654: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:2657; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: to9dRVcVkbR6YnkmDpQm6Co5ZyYJmvGwyfnMmQPu2x5j9GgAlzxD446LIiXTGcyQyB8dmq9+BWgdBLJSLrCJIqegSQH++vcDnxrIDanuAEajfuf1R5NdMJPdCjeDZdx99Y7QiECrGeMvs/trfZngFlsraIUr7w3EMRCyABgtmW+adeXD9btJCLE4TlVd4GMEJSBW+Nf9bjw7CVWp4soS03bB0MZO6Mku0oPud4+wh2M9ugkfxo+eTd4+5ddVI6INEtGaIEpFZEeUxgh2r3XD7rpc6kKNEuLG876NRP+m40Aki8Ns8vQ0Jt9NVyz3JMepuIgzotiwYmnV5okvTfcafNb/t/lt521RortOm+0BQU9i4Ex/0OcLpkq01raJqnP9tMxZFpmHGfup9VDTI0eNVoHaKKBVRyd2rqTG89gw3Z+ZyhQMTDrIA8jI8iiteAwycPlJ/dn/u6pt3HP1Q6tPbAHaKjf8n+h1x2LAJjNucrOMqc8/gJ24OWlI8hLy7+2h3UzGni6Xu7COSNdqZ4d+CtxuaboeaFfsQEN03hmzIrMEPJ9I8+6fdol+pVfSG/RjJhx4uosdOJr0wvbJxstiCaMYJGsNpJX80bXv6oTT/SrMBjlfFJAby/B7/PsnjUGtp06KnTcgkPRLazHgG3Zh8A== 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:(366004)(52116002)(36756003)(7696005)(30864003)(5660300002)(4326008)(316002)(107886003)(8676002)(2616005)(2906002)(66476007)(66946007)(66556008)(66574015)(7416002)(508600001)(86362001)(38100700002)(83380400001)(8936002)(1076003)(6486002)(186003)(6916009)(54906003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: YdvF1pZyl9C8wFf+F6dGDMTSRtvr49Qin1VxnoZTqXAX8WkVFeLPmGhxc3hTfv0pjtKkP620otEZC94oWafVcg1QADidMZvQL/cVA+0UoBIBtv2BzE4il+vB3GNpZdb2qkBe/uXQWB265UtCRLAmvQhWvc8a2oSyfYyq/EEyRwEUPB0+30Ak8kbj63NvBOdsv7pPNPufdqm4sFABZqCnV1l/jBKbRnI9mwAQbePmTqtVyjJkgXehKTPSiNv7tcwGrct8CMDoNQ8MwvnDH9AZ8l7Vf/BgSRNV5ZUJrLpdyhVsxuxZ86tmudykH5u+X7V5e9KKYnJKMD3McT0yhYPuEpTK/O6O8Ix7ZER8T2x9EysXRFxRB/X1/XZpAnXSdHatkhpRi6Bw+axC/NxbLxnbzh8UQ88LOy0l5flGhssG5p4cG9urzSDD07qYTTx3lPquotf5Qb4nqkDRgeXfP6TcrRXdTYgYaZ26ggA3ctYBo+0s5h5ByFsmnmp9J2NZAcCmRY1kPHQW1I0B+VpmEGOUGnX0ai8qJBRTesmNJSU21+DmJi/bQB5+IosmLU9BfuA0TiI7/LDhyBqSXWoRJJWC+1vu15lZP7muFBxee/b8Mzh8lox4EmQ6CLl3kTYih8IvoLtPqJ/pgi8nkJjC1r8XgiqFdX0LxVaCxDJ17I9Q0IiwmofA5TYnUX2eAtofiORtfnejDPAcJdMC+Hd5/oIAGqmooTotNr7mh8K/A1hj5Apgl6WzJ38kdWpcTd9JduvUgoMUrv7wawH4mR4RKRDIUPmCH9lL1o4CU9XIkunm3HZ/mtEsgdE7K4SzgEGk/mMF X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1e4a0e69-779f-48a2-2e32-08d97c5172cc 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:31.2573 (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: gALEHAEhJaPj0RnRoXDs61ClB9X6DzRubYNSvYaXB/PLVI7stcjlsAmExLZslRs+D/RkHp6sFSrr5BDIfhOQNg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB2654 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_rx.c | 415 +++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/hif_rx.h | 17 + 2 files changed, 432 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/hif_rx.c create mode 100644 drivers/net/wireless/silabs/wfx/hif_rx.h diff --git a/drivers/net/wireless/silabs/wfx/hif_rx.c b/drivers/net/wireless/silabs/wfx/hif_rx.c new file mode 100644 index 000000000000..2e6db5b99708 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_rx.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Handling of the chip-to-host events (aka indications) of the hardware API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "hif_rx.h" +#include "wfx.h" +#include "scan.h" +#include "bh.h" +#include "sta.h" +#include "data_rx.h" +#include "hif_api_cmd.h" + +static int hif_generic_confirm(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + /* All confirm messages start with status */ + int status = le32_to_cpup((__le32 *)buf); + int cmd = hif->id; + int len = le16_to_cpu(hif->len) - 4; /* drop header */ + + WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error"); + + if (!wdev->hif_cmd.buf_send) { + dev_warn(wdev->dev, "unexpected confirmation: 0x%.2x\n", cmd); + return -EINVAL; + } + + if (cmd != wdev->hif_cmd.buf_send->id) { + dev_warn(wdev->dev, + "chip response mismatch request: 0x%.2x vs 0x%.2x\n", + cmd, wdev->hif_cmd.buf_send->id); + return -EINVAL; + } + + if (wdev->hif_cmd.buf_recv) { + if (wdev->hif_cmd.len_recv >= len && len > 0) + memcpy(wdev->hif_cmd.buf_recv, buf, len); + else + status = -EIO; + } + wdev->hif_cmd.ret = status; + + complete(&wdev->hif_cmd.done); + return status; +} + +static int hif_tx_confirm(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + const struct hif_cnf_tx *body = buf; + + wfx_tx_confirm_cb(wdev, body); + return 0; +} + +static int hif_multi_tx_confirm(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + const struct hif_cnf_multi_transmit *body = buf; + int i; + + WARN(body->num_tx_confs <= 0, "corrupted message"); + for (i = 0; i < body->num_tx_confs; i++) + wfx_tx_confirm_cb(wdev, &body->tx_conf_payload[i]); + return 0; +} + +static int hif_startup_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + const struct hif_ind_startup *body = buf; + + if (body->status || body->firmware_type > 4) { + dev_err(wdev->dev, "received invalid startup indication"); + return -EINVAL; + } + memcpy(&wdev->hw_caps, body, sizeof(struct hif_ind_startup)); + le16_to_cpus((__le16 *)&wdev->hw_caps.hardware_id); + le16_to_cpus((__le16 *)&wdev->hw_caps.num_inp_ch_bufs); + le16_to_cpus((__le16 *)&wdev->hw_caps.size_inp_ch_buf); + le32_to_cpus((__le32 *)&wdev->hw_caps.supported_rate_mask); + + complete(&wdev->firmware_ready); + return 0; +} + +static int hif_wakeup_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + if (!wdev->pdata.gpio_wakeup || + gpiod_get_value(wdev->pdata.gpio_wakeup) == 0) { + dev_warn(wdev->dev, "unexpected wake-up indication\n"); + return -EIO; + } + return 0; +} + +static int hif_receive_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, + const void *buf, struct sk_buff *skb) +{ + struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); + const struct hif_ind_rx *body = buf; + + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + skb_pull(skb, sizeof(struct hif_msg) + sizeof(struct hif_ind_rx)); + wfx_rx_cb(wvif, body, skb); + + return 0; +} + +static int hif_event_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); + const struct hif_ind_event *body = buf; + int type = le32_to_cpu(body->event_id); + + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + + switch (type) { + case HIF_EVENT_IND_RCPI_RSSI: + wfx_event_report_rssi(wvif, body->event_data.rcpi_rssi); + break; + case HIF_EVENT_IND_BSSLOST: + schedule_delayed_work(&wvif->beacon_loss_work, 0); + break; + case HIF_EVENT_IND_BSSREGAINED: + cancel_delayed_work(&wvif->beacon_loss_work); + dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n"); + break; + case HIF_EVENT_IND_PS_MODE_ERROR: + dev_warn(wdev->dev, "error while processing power save request: %d\n", + le32_to_cpu(body->event_data.ps_mode_error)); + break; + default: + dev_warn(wdev->dev, "unhandled event indication: %.2x\n", + type); + break; + } + return 0; +} + +static int hif_pm_mode_complete_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, + const void *buf) +{ + struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); + + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + complete(&wvif->set_pm_mode_complete); + + return 0; +} + +static int hif_scan_complete_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, + const void *buf) +{ + struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); + const struct hif_ind_scan_cmpl *body = buf; + + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + + wfx_scan_complete(wvif, body->num_channels_completed); + + return 0; +} + +static int hif_join_complete_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, + const void *buf) +{ + struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); + + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + dev_warn(wdev->dev, "unattended JoinCompleteInd\n"); + + return 0; +} + +static int hif_suspend_resume_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, + const void *buf) +{ + const struct hif_ind_suspend_resume_tx *body = buf; + struct wfx_vif *wvif; + + if (body->bc_mc_only) { + wvif = wdev_to_wvif(wdev, hif->interface); + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + if (body->resume) + wfx_suspend_resume_mc(wvif, STA_NOTIFY_AWAKE); + else + wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP); + } else { + WARN(body->peer_sta_set, "misunderstood indication"); + WARN(hif->interface != 2, "misunderstood indication"); + if (body->resume) + wfx_suspend_hot_dev(wdev, STA_NOTIFY_AWAKE); + else + wfx_suspend_hot_dev(wdev, STA_NOTIFY_SLEEP); + } + + return 0; +} + +static int hif_generic_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + const struct hif_ind_generic *body = buf; + int type = le32_to_cpu(body->type); + + switch (type) { + case HIF_GENERIC_INDICATION_TYPE_RAW: + return 0; + case HIF_GENERIC_INDICATION_TYPE_STRING: + dev_info(wdev->dev, "firmware says: %s\n", (char *)&body->data); + return 0; + case HIF_GENERIC_INDICATION_TYPE_RX_STATS: + mutex_lock(&wdev->rx_stats_lock); + /* Older firmware send a generic indication beside RxStats */ + if (!wfx_api_older_than(wdev, 1, 4)) + dev_info(wdev->dev, "Rx test ongoing. Temperature: %d degrees C\n", + body->data.rx_stats.current_temp); + memcpy(&wdev->rx_stats, &body->data.rx_stats, + sizeof(wdev->rx_stats)); + mutex_unlock(&wdev->rx_stats_lock); + return 0; + case HIF_GENERIC_INDICATION_TYPE_TX_POWER_LOOP_INFO: + mutex_lock(&wdev->tx_power_loop_info_lock); + memcpy(&wdev->tx_power_loop_info, + &body->data.tx_power_loop_info, + sizeof(wdev->tx_power_loop_info)); + mutex_unlock(&wdev->tx_power_loop_info_lock); + return 0; + default: + dev_err(wdev->dev, "generic_indication: unknown indication type: %#.8x\n", + type); + return -EIO; + } +} + +static const struct { + int val; + const char *str; + bool has_param; +} hif_errors[] = { + { HIF_ERROR_FIRMWARE_ROLLBACK, + "rollback status" }, + { HIF_ERROR_FIRMWARE_DEBUG_ENABLED, + "debug feature enabled" }, + { HIF_ERROR_PDS_PAYLOAD, + "PDS version is not supported" }, + { HIF_ERROR_PDS_TESTFEATURE, + "PDS ask for an unknown test mode" }, + { HIF_ERROR_OOR_VOLTAGE, + "out-of-range power supply voltage", true }, + { HIF_ERROR_OOR_TEMPERATURE, + "out-of-range temperature", true }, + { HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE, + "secure link does not expect request during key exchange" }, + { HIF_ERROR_SLK_SESSION_KEY, + "secure link session key is invalid" }, + { HIF_ERROR_SLK_OVERFLOW, + "secure link overflow" }, + { HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE, + "secure link messages list does not match message encryption" }, + { HIF_ERROR_SLK_UNCONFIGURED, + "secure link not yet configured" }, + { HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW, + "bus clock is too slow (<1kHz)" }, + { HIF_ERROR_HIF_RX_DATA_TOO_LARGE, + "HIF message too large" }, + /* Following errors only exists in old firmware versions: */ + { HIF_ERROR_HIF_TX_QUEUE_FULL, + "HIF messages queue is full" }, + { HIF_ERROR_HIF_BUS, + "HIF bus" }, + { HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED, + "secure link does not support multi-tx confirmations" }, + { HIF_ERROR_SLK_OUTDATED_SESSION_KEY, + "secure link session key is outdated" }, + { HIF_ERROR_SLK_DECRYPTION, + "secure link params (nonce or tag) mismatch" }, +}; + +static int hif_error_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + const struct hif_ind_error *body = buf; + int type = le32_to_cpu(body->type); + int param = (s8)body->data[0]; + int i; + + for (i = 0; i < ARRAY_SIZE(hif_errors); i++) + if (type == hif_errors[i].val) + break; + if (i < ARRAY_SIZE(hif_errors)) + if (hif_errors[i].has_param) + dev_err(wdev->dev, "asynchronous error: %s: %d\n", + hif_errors[i].str, param); + else + dev_err(wdev->dev, "asynchronous error: %s\n", + hif_errors[i].str); + else + dev_err(wdev->dev, "asynchronous error: unknown: %08x\n", type); + print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, + 16, 1, hif, le16_to_cpu(hif->len), false); + wdev->chip_frozen = true; + + return 0; +}; + +static int hif_exception_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) +{ + const struct hif_ind_exception *body = buf; + int type = le32_to_cpu(body->type); + + if (type == 4) + dev_err(wdev->dev, "firmware assert %d\n", + le32_to_cpup((__le32 *)body->data)); + else + dev_err(wdev->dev, "firmware exception\n"); + print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, + 16, 1, hif, le16_to_cpu(hif->len), false); + wdev->chip_frozen = true; + + return -1; +} + +static const struct { + int msg_id; + int (*handler)(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf); +} hif_handlers[] = { + /* Confirmations */ + { HIF_CNF_ID_TX, hif_tx_confirm }, + { HIF_CNF_ID_MULTI_TRANSMIT, hif_multi_tx_confirm }, + /* Indications */ + { HIF_IND_ID_STARTUP, hif_startup_indication }, + { HIF_IND_ID_WAKEUP, hif_wakeup_indication }, + { HIF_IND_ID_JOIN_COMPLETE, hif_join_complete_indication }, + { HIF_IND_ID_SET_PM_MODE_CMPL, hif_pm_mode_complete_indication }, + { HIF_IND_ID_SCAN_CMPL, hif_scan_complete_indication }, + { HIF_IND_ID_SUSPEND_RESUME_TX, hif_suspend_resume_indication }, + { HIF_IND_ID_EVENT, hif_event_indication }, + { HIF_IND_ID_GENERIC, hif_generic_indication }, + { HIF_IND_ID_ERROR, hif_error_indication }, + { HIF_IND_ID_EXCEPTION, hif_exception_indication }, + /* FIXME: allocate skb_p from hif_receive_indication and make it generic */ + //{ HIF_IND_ID_RX, hif_receive_indication }, +}; + +void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb) +{ + int i; + const struct hif_msg *hif = (const struct hif_msg *)skb->data; + int hif_id = hif->id; + + if (hif_id == HIF_IND_ID_RX) { + /* hif_receive_indication take care of skb lifetime */ + hif_receive_indication(wdev, hif, hif->body, skb); + return; + } + /* Note: mutex_is_lock cause an implicit memory barrier that protect + * buf_send + */ + if (mutex_is_locked(&wdev->hif_cmd.lock) && + wdev->hif_cmd.buf_send && + wdev->hif_cmd.buf_send->id == hif_id) { + hif_generic_confirm(wdev, hif, hif->body); + goto free; + } + for (i = 0; i < ARRAY_SIZE(hif_handlers); i++) { + if (hif_handlers[i].msg_id == hif_id) { + if (hif_handlers[i].handler) + hif_handlers[i].handler(wdev, hif, hif->body); + goto free; + } + } + if (hif_id & 0x80) + dev_err(wdev->dev, "unsupported HIF indication: ID %02x\n", + hif_id); + else + dev_err(wdev->dev, "unexpected HIF confirmation: ID %02x\n", + hif_id); +free: + dev_kfree_skb(skb); +} diff --git a/drivers/net/wireless/silabs/wfx/hif_rx.h b/drivers/net/wireless/silabs/wfx/hif_rx.h new file mode 100644 index 000000000000..96543b81fa77 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/hif_rx.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Handling of the chip-to-host events (aka indications) of the hardware API. + * + * Copyright (c) 2017-2019, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + * Copyright (C) 2010, ST-Ericsson SA + */ +#ifndef WFX_HIF_RX_H +#define WFX_HIF_RX_H + +struct wfx_dev; +struct sk_buff; + +void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb); + +#endif From patchwork Mon Sep 20 16:11:28 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: 12505845 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 76B87C433EF for ; Mon, 20 Sep 2021 16:13:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4E14960F58 for ; Mon, 20 Sep 2021 16:13:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242927AbhITQOq (ORCPT ); Mon, 20 Sep 2021 12:14:46 -0400 Received: from mail-bn7nam10on2065.outbound.protection.outlook.com ([40.107.92.65]:4704 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242488AbhITQOD (ORCPT ); Mon, 20 Sep 2021 12:14:03 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=XfisY/rp0PhYT9gOpFjuy9Uk045UHLNEdDKWApYT0wziqgtjmG5Z8+Qcjuslxmv3Y3g9QfHcqBpfY4l5012hG3pyUoClzXVLNX4v/qKx4TNwK6QgXQoDtKAAj6gNb7IaO/J7MAg/yrbNH1eCEfF2VOxHrZppFHhVx/+FhqCskWXhoHX7sYZxnGWE4T0ucG8uBDCEBb7+ZHjtmRkIgSuKeNIy8tAFUbvFToEzXPG3AScZmQ8IggWboeKazCynfuPrawqiS4nZlgyvFmFYJS82OIicaQmgp4ZzI/h6B/tJ0C7M31EBKRquWbAxPUuOXicsVlG54U0zsYYYOgLfAZlgfA== 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=B060dwVEfeTW4dRn140ZNuQdsL6yUQFgWMlzSPffF14=; b=k3XEYUcEa0xsp4UHlp6XIp+URFi0TcTtaKyHSEe0NlUrYuqkCUXGvPVP2CQlewCy42JxbNbh+7yFt/WCE1adR+l9bycBlsUvQYasE9mBCu3eTMQmEFLkhuY4SCtYTnd7+nV4UWWwvlRN++f0IA/G0eq9dHPWuBMif3oUfrJU8N6tig9DGNA8dhndGrB0zqrBreR1Ux+NSZItkFRwhkIWAMcGOy/bPJ8k4OotRoRbHTXpRSiBpbkrE/piBL7H5tSrVKnbm8KjNoJE9wMzpqDuaQyAVzqilxj/rTVCz5r6pM7QU+FLUHkViLTOZK523f8k4k9dRsTDC0vpyl9DdCqYvw== 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=B060dwVEfeTW4dRn140ZNuQdsL6yUQFgWMlzSPffF14=; b=SPsjqo2sYZd4bNRpR6HnYIRLWBSvKdAQjXeWap5SFA27cVHv/f5Em8ttYqc9fbzTcnxKCuT2SD7ulRwi95yCiX1f/pv3y8d96xZ2mtjAb1zwFCv5iV9meXf48IKMPNbpD3bf3o35hKoRLAkQF7vDy7iTm8OImXaWeQF8JLkeoY0= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:33 +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:33 +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 16/24] wfx: add data_rx.c/data_rx.h Date: Mon, 20 Sep 2021 18:11:28 +0200 Message-Id: <20210920161136.2398632-17-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:31 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5ba37bf1-be34-434e-c9a2-08d97c517443 X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:644; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: qMZLNYJbLXeRkBoW1R57FH4pVX+Hd+rxAys2z6z6YKGPERJHEQf9GRNiWRkuUQE2aicstgeBbGlVa1Ts59kIGQJ+/aEznqUcGUqDxj/nCteBG2SK3VCn/ct7JJBVFPydJ2dbRPvUJg94QVlLZm9U5WZc7YsH53nfOJk03WonuV5+spz+94Qk/WymUeHmcosK7d6NuS/PO5cEGFyxJWEGz14zDVeBKi2ZVfq8UkCscmONgMYRwzU0wtqReCaUWEVA+X6HCgxlFgJP98bn7uE414es6GtlZabgzL/K+FOwB8LK0MIP5Sg0Cchrh0zD/uByNmewBlmVBJFwvL/v1oPmBgFGpQCwESdXQctdmZ23EcaYXFGoO6TwckinBxyGeo+IToWh0SMuRtFRhgrCRquhMYR3jPudOPhHaxE3tpEnk0Nu6HqtQwnDIp/Kb7u4vxQjU/KK+udQ3jaJp1QGA60nNlbKcFRIw+fSrCU3202x6kP2yo/zrAZiteDUjPkWPprLDA++2L/f8NKFmnqOg3Y0gfE09V/bdsLWDFsrg3tqTMTX8kLl5kyzqeT/XRZJkbr+9HFZT5r3MGmSkRcg5MpL8AX/ervVJTPHLR1sbZ/xQMz5LtEqWd8d4ZdKR0RYKvuuUBfzIfHmjp9ElzmyRUSJnQ== 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(7416002)(66556008)(7696005)(316002)(83380400001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: y9XphkNrew3dqm8kmObPi4QupnJb8i63DfrzvMPojOf2iDsLAKdOK/Shz6Z4bOB2BpU/QsC+7uY810BEKlOFpCJTbI0P+DSNdS7X70ofIE5mcxi6Kpcx/PC86AGH+2rj0LzuqTLZqxgt3yZAENO+x1QqVoN2biuVGkA4H2ffxAYlq2D/zkOATmItWxETEjLgqSCs2Y926VtG+iF71jtl87cdE4UZzMrNZMi16HPU6hrV/Nx5EOWeskESMjV7FCn68izAUCIUmhME1qIvlbRRslUyWSd4V2/O10qaIcOpml6EnhlsENN1rVM4O5GuO1MK0UyZNZ6LhIkImoedtUDIczlUy8mEsJUrmAjWY+Re1hFoBCFddlBw6wcBJ/pi+4LMoQzlIr9AZGnjyIf1mRnIefk/uXJbO60sK8A/BxYuaxNZI0bPGewfT+dL6fWDdajxua2b3YERtUmuxwUrm5HVNgmKw8M/lAF6yOXNnyd/ZphJAJNgg5OXnHVyIl9c2K7Nq287y96mN3PfhroBM5/0llZYk2GhHCn3iaZVJcKzy3+b7dGJV1zupo3OSrZvnNQSh/IJNOBTWHxvRrTKuZCaGmBdzQQMmb3yn91PveGSAzo8p1zRNZIl+UHN9mWdYBMj4IzR3j/u6/3APT4yU1Y6vooP27P7j2yYUjNlJlZliff3VbNhSQpt6l5/UAvK0iaMu0CGBb9CeXpfT/glNHF4ohE+Pk8L8wCmfsLshFREgW596yMeCRT9BVBfsowOpwslmiV/zTaYg4Bpf/EN57p7WXBlCBJOhndamZtt+grJLLC4ukH5ISGr4T0jKAhOJLvc X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5ba37bf1-be34-434e-c9a2-08d97c517443 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:33.7089 (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: QRi2RGdZU2KJSnZQQAVxcX70WmxLigozZaQNE0D6fij91QuYMJIRxduDLc04WEzC3Ng/Mt6NVrsaWPaMfRCDcQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 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/data_rx.c | 94 +++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/data_rx.h | 18 +++++ 2 files changed, 112 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/data_rx.c create mode 100644 drivers/net/wireless/silabs/wfx/data_rx.h diff --git a/drivers/net/wireless/silabs/wfx/data_rx.c b/drivers/net/wireless/silabs/wfx/data_rx.c new file mode 100644 index 000000000000..bfc3961b7b89 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/data_rx.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Data receiving implementation. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "data_rx.h" +#include "wfx.h" +#include "bh.h" +#include "sta.h" + +static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt) +{ + int params, tid; + + if (wfx_api_older_than(wvif->wdev, 3, 6)) + return; + + switch (mgmt->u.action.u.addba_req.action_code) { + case WLAN_ACTION_ADDBA_REQ: + params = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + ieee80211_start_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); + break; + case WLAN_ACTION_DELBA: + params = le16_to_cpu(mgmt->u.action.u.delba.params); + tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; + ieee80211_stop_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); + break; + } +} + +void wfx_rx_cb(struct wfx_vif *wvif, + const struct hif_ind_rx *arg, struct sk_buff *skb) +{ + struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb); + struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + + memset(hdr, 0, sizeof(*hdr)); + + if (arg->status == HIF_STATUS_RX_FAIL_MIC) + hdr->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_IV_STRIPPED; + else if (arg->status) + goto drop; + + if (skb->len < sizeof(struct ieee80211_pspoll)) { + dev_warn(wvif->wdev->dev, "malformed SDU received\n"); + goto drop; + } + + hdr->band = NL80211_BAND_2GHZ; + hdr->freq = ieee80211_channel_to_frequency(arg->channel_number, + hdr->band); + + if (arg->rxed_rate >= 14) { + hdr->encoding = RX_ENC_HT; + hdr->rate_idx = arg->rxed_rate - 14; + } else if (arg->rxed_rate >= 4) { + hdr->rate_idx = arg->rxed_rate - 2; + } else { + hdr->rate_idx = arg->rxed_rate; + } + + if (!arg->rcpi_rssi) { + hdr->flag |= RX_FLAG_NO_SIGNAL_VAL; + dev_info(wvif->wdev->dev, "received frame without RSSI data\n"); + } + hdr->signal = arg->rcpi_rssi / 2 - 110; + hdr->antenna = 0; + + if (arg->encryp) + hdr->flag |= RX_FLAG_DECRYPTED; + + /* Block ack negotiation is offloaded by the firmware. However, + * re-ordering must be done by the mac80211. + */ + if (ieee80211_is_action(frame->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_BACK && + skb->len > IEEE80211_MIN_ACTION_SIZE) { + wfx_rx_handle_ba(wvif, mgmt); + goto drop; + } + + ieee80211_rx_irqsafe(wvif->wdev->hw, skb); + return; + +drop: + dev_kfree_skb(skb); +} diff --git a/drivers/net/wireless/silabs/wfx/data_rx.h b/drivers/net/wireless/silabs/wfx/data_rx.h new file mode 100644 index 000000000000..84d0e3c0507b --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/data_rx.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Data receiving implementation. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_DATA_RX_H +#define WFX_DATA_RX_H + +struct wfx_vif; +struct sk_buff; +struct hif_ind_rx; + +void wfx_rx_cb(struct wfx_vif *wvif, + const struct hif_ind_rx *arg, struct sk_buff *skb); + +#endif From patchwork Mon Sep 20 16:11:29 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: 12505851 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 B2F74C433FE for ; Mon, 20 Sep 2021 16:13:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8DFC660F58 for ; Mon, 20 Sep 2021 16:13:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243357AbhITQPR (ORCPT ); Mon, 20 Sep 2021 12:15:17 -0400 Received: from mail-bn7nam10on2076.outbound.protection.outlook.com ([40.107.92.76]:28992 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S243021AbhITQOO (ORCPT ); Mon, 20 Sep 2021 12:14:14 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YoHESN1G+ITThc83v+8cGwfNc0uK8hhY+3QMvNfsg+LTZgQJzKznpjL+DsaoUEd2ANly9fx0vgU7UGSLj6JAqI3EbUbPzroK4Z1RNYCqvNu3GEzMtcIpFD5OY2AB1dV0EFdXYvilu2uszhTcRyfD2qcQZPzlJZCokWiM2sPlW8W9J3eexmv8hEDV6vXGcM88lTCC2l4XKfr/nhTwAE8XoxwmQXYLzI5RZK6S6vDr0GVdoJPUe2IibusFMkLEsn8IOBQll4eoU5AFqhnD6flBcQeWohcNrqpMpGtYa1l6EbueK2EkS+0p48eCfUmFCR/CpAHOjQsyPLoAYPEOl6yfhg== 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=6GL47d7QkI6cbgNydxd8mw6pRJ/9458hhnCA+qRmPKc=; b=DOgks9l3DfkewGt9ngmpxuZN6kmi+MzC800KP+itrZE8/oc4VAkLrfaD+ZEkKEK07u0kFvhleR77Z+s/SGvpe83695wDuXKBXqRMAQP6sG08nHqzhyaUkpNdeAgAZUbkuRoPBTdDL91gEKtS72LX8+qGqE1/3guwb2qlzeFZMvYvmJBGJuMjDJHcCYF7QaTzu3HLaz5ag0x6b+YYXPCBoTysU+2Cb1LlGpQ2lq7zkevPqSbf4A+bcz1QEMmDizC3FLiMisWEbM1jY3o4MRFwbD3JlYIQ/n2DA4poaym2jEGNrkmkmsBRISNCN2FM5Ls139SUuaCplAik6gWEYvv58Q== 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=6GL47d7QkI6cbgNydxd8mw6pRJ/9458hhnCA+qRmPKc=; b=SWVTh7/Bz9nuHBiZA6purq6MtXPRzUjKSDsM5D8cxaBZui1MG7WAKpfkK9rlTbbCQT4oaoFtvPvOslSZeq5sqgIfTFpsVKpnKeq1Si4284CgQ3PPq5XNsVMMe4+Qux6y/fUJHr597PB8Ezp89CLXwddIrM8JO+DgX4MxfFfdXtQ= 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 SN6PR11MB2654.namprd11.prod.outlook.com (2603:10b6:805:54::31) 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:36 +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:36 +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 17/24] wfx: add queue.c/queue.h Date: Mon, 20 Sep 2021 18:11:29 +0200 Message-Id: <20210920161136.2398632-18-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:34 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a6eedb13-3cc4-4ba2-9d65-08d97c5175bc X-MS-TrafficTypeDiagnostic: SN6PR11MB2654: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:4714; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ug8QnTvXDLqlzox3neqgYNBf3hx2b8cQMrdyJzKKFWTTW+9gDOSwsULqzqh8v0Q9lHWtJfb8q54S4tHPZ3tFTJduXlJ41xr+KKDYfYfqs4TzUkQst13QCQa5LGVun0hBj2w6UBFi/RKrK56z6259IG9farL2W2ZOvA9q9tAJMDmiBnlYerK/ghDg6Z9vXtE3BlQe/M9bCSjoNUM2s3Zhr1/1z1CfH8qCfpdHskNCPFpQNZ1b/W7Pr++gyiti7GPVRtq1HWGZdQB5MP/6KbO8ADJ4twUKn1+3GHTY23Gj+MdLE6/VVNcxpLFHMryRHXN6e8v3VaTHkOohn3c3TiNCEIsD67SSQDX1kq4f3hAz3Q9n2wWtoy6BqBb9MhLFYUWB6N2PigTaAAlp/OWdfXmdutuH3vBFsyASFvGClnd06yQaWb+t7GFLDuVqJOtKSJQISM7EsELpL0aOnjDhHXgD5Xf/wIZ/Y/jPftj0/qZnteu2XhbJgNcsy98EYxt7OAvWND3s8rUELfXRHx4fUcJaWa3izMMfrrDyrPiCULyjebPxAlKKoJoUmgvtDbGts27n1MqM1uTqUIVaPwC03vF2QeaAmS3HygDRRWwBZ34qlTgLuJXNG3v27rOVr63+4yrnMu87OqA9Lx/lUCE4MRApSA== 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:(366004)(52116002)(36756003)(7696005)(30864003)(5660300002)(4326008)(316002)(107886003)(8676002)(2616005)(2906002)(66476007)(66946007)(66556008)(66574015)(7416002)(508600001)(86362001)(38100700002)(83380400001)(8936002)(1076003)(6486002)(186003)(6916009)(6666004)(54906003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: RJvETKRyA5aotcXzBSdKGVpxUPGhTQsVHqQvdbQe4vQG8GBH70L3JcA3bQ0AHfcmmECsQKwln7/Rn05PP5KvhWT25ia64ROj2+/Aixqr9UybP09owvcfX2AJyX97vuM+eM2+fNTsvDocfAG9CzuiRN8MCpaEOWUlBX+xsvwIFJIDjjt+UMRNvqzFjo+RpT/i6hodJwvzhFRbJ5oI3ckkdLDDtRR694yP+jbK0jBeCFGia/YQ37EXDDf134vX30z4IXUSgj4UAl4KbN7zsNLm4k4Vgibm8nhFfxKEPYydYHTBIgrp5neS7NFZyH3ipB0YJrUsTbQ3OPHgW8vPGktYlL09sF8/3GpAwEVqkZv7OeP8QetNm18Vo5X1TolPQYB6aZeo+zI/WXyUaolURaz7tZup8FmhwYk2w2yxf8nBW3u40+pBNQEQvGSuYQpuIGgbJFJHbv8MBG/E67NbImdGJoWoVRPyuyDIN/G4f5KPwfA0fxgUJ8nirklA4/6qkVFhDQdqb6ldbrBJiUyRPigGXxRK+/fPeMcLRVn2T60SCfysNTZZzzDJdsnFx7RejEFD1cSSD4e9U57AhW0+IT5mRz6YKg7qrS9WlicxmU+/0+APhh34UQVp5A1Yf2IJ2Gr9Lrr4zCtV9N7Ui5Y3zylX4xcWSeRxfXA4cXNQhzxDvpZz14mdoUSfyWc6Y3iAk1DwiBt0tyY0tEXHW0DwDH8DT8hAG7nWnGvvp8jC6ccd2Xi3/881tOtTtKceoRQWU0sIETKodDd4pWDgwMb28fh95O1PGxI9TSgK5198WxozvcwKsvJXnlPIY4q2iDQKU08n X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: a6eedb13-3cc4-4ba2-9d65-08d97c5175bc 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:36.1335 (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: Omp58DeDXLYsCJSfHitCWuRjzsrrlVWSfv0mX5xlLBe/QAIQDuyTI6ktSRz4zt7zjwKq99Mxzi5fxVnUVWGrWw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB2654 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/queue.c | 307 ++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/queue.h | 45 ++++ 2 files changed, 352 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/queue.c create mode 100644 drivers/net/wireless/silabs/wfx/queue.h diff --git a/drivers/net/wireless/silabs/wfx/queue.c b/drivers/net/wireless/silabs/wfx/queue.c new file mode 100644 index 000000000000..7a3ba3c38925 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/queue.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Queue between the tx operation and the bh workqueue. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "queue.h" +#include "wfx.h" +#include "sta.h" +#include "data_tx.h" +#include "traces.h" + +void wfx_tx_lock(struct wfx_dev *wdev) +{ + atomic_inc(&wdev->tx_lock); +} + +void wfx_tx_unlock(struct wfx_dev *wdev) +{ + int tx_lock = atomic_dec_return(&wdev->tx_lock); + + WARN(tx_lock < 0, "inconsistent tx_lock value"); + if (!tx_lock) + wfx_bh_request_tx(wdev); +} + +void wfx_tx_flush(struct wfx_dev *wdev) +{ + int ret; + + /* Do not wait for any reply if chip is frozen */ + if (wdev->chip_frozen) + return; + + wfx_tx_lock(wdev); + mutex_lock(&wdev->hif_cmd.lock); + ret = wait_event_timeout(wdev->hif.tx_buffers_empty, + !wdev->hif.tx_buffers_used, + msecs_to_jiffies(3000)); + if (!ret) { + dev_warn(wdev->dev, "cannot flush tx buffers (%d still busy)\n", + wdev->hif.tx_buffers_used); + wfx_pending_dump_old_frames(wdev, 3000); + /* FIXME: drop pending frames here */ + wdev->chip_frozen = true; + } + mutex_unlock(&wdev->hif_cmd.lock); + wfx_tx_unlock(wdev); +} + +void wfx_tx_lock_flush(struct wfx_dev *wdev) +{ + wfx_tx_lock(wdev); + wfx_tx_flush(wdev); +} + +void wfx_tx_queues_init(struct wfx_vif *wvif) +{ + /* The device is in charge to respect the details of the QoS parameters. + * The driver just ensure that it roughtly respect the priorities to + * avoid any shortage. + */ + const int priorities[IEEE80211_NUM_ACS] = { 1, 2, 64, 128 }; + int i; + + for (i = 0; i < IEEE80211_NUM_ACS; ++i) { + skb_queue_head_init(&wvif->tx_queue[i].normal); + skb_queue_head_init(&wvif->tx_queue[i].cab); + wvif->tx_queue[i].priority = priorities[i]; + } +} + +bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue) +{ + return skb_queue_empty_lockless(&queue->normal) && + skb_queue_empty_lockless(&queue->cab); +} + +void wfx_tx_queues_check_empty(struct wfx_vif *wvif) +{ + int i; + + for (i = 0; i < IEEE80211_NUM_ACS; ++i) { + WARN_ON(atomic_read(&wvif->tx_queue[i].pending_frames)); + WARN_ON(!wfx_tx_queue_empty(wvif, &wvif->tx_queue[i])); + } +} + +static void __wfx_tx_queue_drop(struct wfx_vif *wvif, + struct sk_buff_head *skb_queue, + struct sk_buff_head *dropped) +{ + struct sk_buff *skb, *tmp; + + spin_lock_bh(&skb_queue->lock); + skb_queue_walk_safe(skb_queue, skb, tmp) { + __skb_unlink(skb, skb_queue); + skb_queue_head(dropped, skb); + } + spin_unlock_bh(&skb_queue->lock); +} + +void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, + struct sk_buff_head *dropped) +{ + __wfx_tx_queue_drop(wvif, &queue->cab, dropped); + __wfx_tx_queue_drop(wvif, &queue->normal, dropped); + wake_up(&wvif->wdev->tx_dequeue); +} + +void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb) +{ + struct wfx_queue *queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + skb_queue_tail(&queue->cab, skb); + else + skb_queue_tail(&queue->normal, skb); +} + +void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped) +{ + struct wfx_queue *queue; + struct wfx_vif *wvif; + struct hif_msg *hif; + struct sk_buff *skb; + + WARN(!wdev->chip_frozen, "%s should only be used to recover a frozen device", + __func__); + while ((skb = skb_dequeue(&wdev->tx_pending)) != NULL) { + hif = (struct hif_msg *)skb->data; + wvif = wdev_to_wvif(wdev, hif->interface); + if (wvif) { + queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; + WARN_ON(skb_get_queue_mapping(skb) > 3); + WARN_ON(!atomic_read(&queue->pending_frames)); + atomic_dec(&queue->pending_frames); + } + skb_queue_head(dropped, skb); + } +} + +struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id) +{ + struct wfx_queue *queue; + struct hif_req_tx *req; + struct wfx_vif *wvif; + struct hif_msg *hif; + struct sk_buff *skb; + + spin_lock_bh(&wdev->tx_pending.lock); + skb_queue_walk(&wdev->tx_pending, skb) { + hif = (struct hif_msg *)skb->data; + req = (struct hif_req_tx *)hif->body; + if (req->packet_id != packet_id) + continue; + spin_unlock_bh(&wdev->tx_pending.lock); + wvif = wdev_to_wvif(wdev, hif->interface); + if (wvif) { + queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; + WARN_ON(skb_get_queue_mapping(skb) > 3); + WARN_ON(!atomic_read(&queue->pending_frames)); + atomic_dec(&queue->pending_frames); + } + skb_unlink(skb, &wdev->tx_pending); + return skb; + } + spin_unlock_bh(&wdev->tx_pending.lock); + WARN(1, "cannot find packet in pending queue"); + return NULL; +} + +void wfx_pending_dump_old_frames(struct wfx_dev *wdev, unsigned int limit_ms) +{ + ktime_t now = ktime_get(); + struct wfx_tx_priv *tx_priv; + struct hif_req_tx *req; + struct sk_buff *skb; + bool first = true; + + spin_lock_bh(&wdev->tx_pending.lock); + skb_queue_walk(&wdev->tx_pending, skb) { + tx_priv = wfx_skb_tx_priv(skb); + req = wfx_skb_txreq(skb); + if (ktime_after(now, ktime_add_ms(tx_priv->xmit_timestamp, + limit_ms))) { + if (first) { + dev_info(wdev->dev, "frames stuck in firmware since %dms or more:\n", + limit_ms); + first = false; + } + dev_info(wdev->dev, " id %08x sent %lldms ago\n", + req->packet_id, + ktime_ms_delta(now, tx_priv->xmit_timestamp)); + } + } + spin_unlock_bh(&wdev->tx_pending.lock); +} + +unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, + struct sk_buff *skb) +{ + ktime_t now = ktime_get(); + struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb); + + return ktime_us_delta(now, tx_priv->xmit_timestamp); +} + +bool wfx_tx_queues_has_cab(struct wfx_vif *wvif) +{ + int i; + + if (wvif->vif->type != NL80211_IFTYPE_AP) + return false; + for (i = 0; i < IEEE80211_NUM_ACS; ++i) + /* Note: since only AP can have mcast frames in queue and only + * one vif can be AP, all queued frames has same interface id + */ + if (!skb_queue_empty_lockless(&wvif->tx_queue[i].cab)) + return true; + return false; +} + +static int wfx_tx_queue_get_weight(struct wfx_queue *queue) +{ + return atomic_read(&queue->pending_frames) * queue->priority; +} + +static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev) +{ + struct wfx_queue *queues[IEEE80211_NUM_ACS * ARRAY_SIZE(wdev->vif)]; + int i, j, num_queues = 0; + struct wfx_vif *wvif; + struct hif_msg *hif; + struct sk_buff *skb; + + /* sort the queues */ + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + WARN_ON(num_queues >= ARRAY_SIZE(queues)); + queues[num_queues] = &wvif->tx_queue[i]; + for (j = num_queues; j > 0; j--) + if (wfx_tx_queue_get_weight(queues[j]) < + wfx_tx_queue_get_weight(queues[j - 1])) + swap(queues[j - 1], queues[j]); + num_queues++; + } + } + + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + if (!wvif->after_dtim_tx_allowed) + continue; + for (i = 0; i < num_queues; i++) { + skb = skb_dequeue(&queues[i]->cab); + if (!skb) + continue; + /* Note: since only AP can have mcast frames in queue + * and only one vif can be AP, all queued frames has + * same interface id + */ + hif = (struct hif_msg *)skb->data; + WARN_ON(hif->interface != wvif->id); + WARN_ON(queues[i] != + &wvif->tx_queue[skb_get_queue_mapping(skb)]); + atomic_inc(&queues[i]->pending_frames); + trace_queues_stats(wdev, queues[i]); + return skb; + } + /* No more multicast to sent */ + wvif->after_dtim_tx_allowed = false; + schedule_work(&wvif->update_tim_work); + } + + for (i = 0; i < num_queues; i++) { + skb = skb_dequeue(&queues[i]->normal); + if (skb) { + atomic_inc(&queues[i]->pending_frames); + trace_queues_stats(wdev, queues[i]); + return skb; + } + } + return NULL; +} + +struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) +{ + struct wfx_tx_priv *tx_priv; + struct sk_buff *skb; + + if (atomic_read(&wdev->tx_lock)) + return NULL; + skb = wfx_tx_queues_get_skb(wdev); + if (!skb) + return NULL; + skb_queue_tail(&wdev->tx_pending, skb); + wake_up(&wdev->tx_dequeue); + tx_priv = wfx_skb_tx_priv(skb); + tx_priv->xmit_timestamp = ktime_get(); + return (struct hif_msg *)skb->data; +} diff --git a/drivers/net/wireless/silabs/wfx/queue.h b/drivers/net/wireless/silabs/wfx/queue.h new file mode 100644 index 000000000000..edd0d018b198 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/queue.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Queue between the tx operation and the bh workqueue. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_QUEUE_H +#define WFX_QUEUE_H + +#include +#include + +struct wfx_dev; +struct wfx_vif; + +struct wfx_queue { + struct sk_buff_head normal; + struct sk_buff_head cab; /* Content After (DTIM) Beacon */ + atomic_t pending_frames; + int priority; +}; + +void wfx_tx_lock(struct wfx_dev *wdev); +void wfx_tx_unlock(struct wfx_dev *wdev); +void wfx_tx_flush(struct wfx_dev *wdev); +void wfx_tx_lock_flush(struct wfx_dev *wdev); + +void wfx_tx_queues_init(struct wfx_vif *wvif); +void wfx_tx_queues_check_empty(struct wfx_vif *wvif); +bool wfx_tx_queues_has_cab(struct wfx_vif *wvif); +void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb); +struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev); + +bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue); +void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, + struct sk_buff_head *dropped); + +struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id); +void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped); +unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, + struct sk_buff *skb); +void wfx_pending_dump_old_frames(struct wfx_dev *wdev, unsigned int limit_ms); + +#endif From patchwork Mon Sep 20 16:11:30 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: 12505905 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 0F700C433EF for ; Mon, 20 Sep 2021 16:14:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EA63460F58 for ; Mon, 20 Sep 2021 16:14:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243436AbhITQPZ (ORCPT ); Mon, 20 Sep 2021 12:15:25 -0400 Received: from mail-bn7nam10on2065.outbound.protection.outlook.com ([40.107.92.65]:4704 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242686AbhITQOQ (ORCPT ); Mon, 20 Sep 2021 12:14:16 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=oFyG13FvhJCdycHE44FyMc6qsyHzcjrUfe/6/LNwvcxEvp7x8wcw1ZegtEJ8UohhMSdKiuTaXMwhIkT5dJERWPedOLO0YX/ztlpdOYHvrDejzeJFC89MQUU2OpIf2ulVEV642ttJ/e2HzW8D9a0hbK0LA4XsBAHC3M75m3inP50o6bNqQ9mo0Ib1eumKUGmjru3e8aMvIsCv0izjKWutf1Rer7M3RhdTBv+XxsgFfwrmCvjlsWkkIkrMVC2UtIQuo/0iusgKivp8Ub6g/ydz5QlEeipaMDyvZlLjaRBYDdMViJv/tzDQFq5NHnGfjIfsalGD/XWHkgf2LpzPfYNCGA== 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=MuASShjszN7CfB9ROyxndQjwwLy50CLbW8teiYyja/k=; b=SPjO+AVaEGUg1TR6TpexijonFfD9ECdRGVSu2taAI+Pn0Ipw9uIFSignTna4e/ZVdpwRLTekFNDiUmziowNyGAq0e39ZmTZ/G3T+oM/IcVS7clmYcHjpki6dzchj7qgqI1nPRswOW3osOge1T1blRq23Hkq/rOqH5rNh+ejCJiJrVS0vSX/+qM+i3QvkHPwGt7F/kYCaZ8j41HG/qSkeB0GAoXp3MUnK8h9mst+eWDuSrxyl8riyfAoPNEW4gCL88dMOuqFncSUOD+lu+HWY0fwObGX7meiaCUoKoYw82qcBsmXklHVGGIRNYFMFNnw4acDdZbrwDC1ssn5sVHKF5w== 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=MuASShjszN7CfB9ROyxndQjwwLy50CLbW8teiYyja/k=; b=WpCoXtCOwfDDMXY5PsauWOHDQKBkqYR4xBxJ6neJRqxNZSyAkvH4/dN/jteJWmC2zJ241qopu58QHqYtrWJwpmf69pXlFWyuVVXhsAn0BLc9nIrl0IhFKE0GjfGTNP33Wj+s2e+Hs7lovSFjreKjRTM1BSp/S6iYpqqNJDYS20k= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:38 +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:38 +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 18/24] wfx: add data_tx.c/data_tx.h Date: Mon, 20 Sep 2021 18:11:30 +0200 Message-Id: <20210920161136.2398632-19-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:36 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: abd4f4ce-388b-4221-efde-08d97c517728 X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5516; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Yx7MknBhkPiLyQBAHCBXZigphUcfD69G/5U0cxHJITRnLropCB2eQqgnrNBnHJd//BFis+uaqEfRVFwqhz5TIGQpJMCzYFtMJaTbHZvWs7ctEnByKJf6y8OuW+mfyYp8ctlrMW+6f3oesZPdBcH+xRKtiURZnPdn/okb3vdUYs/xk+s2ljFUesX5zI5lLAPVXGBxxJAGnFwh7cxWjyenq/4Nf7DBylr3hYF+WCjm+EKkzCa4lrwQNvVZWbhmuFaOncF7XB4oHtxBsRlpgGTd9+6JN3ymTLt4QvlvdBaUL4GdPgWTzrFSfRfL/dI8t/uAGui6y17XzUI7F6PooyTGPZRcYYCtQQsCP1n835NKodcpNNWxeB8S+zqe65b3qFs7Eyd4UnkKneN723qMe4hIFBy4yR5tAEWYGfHzAGBVdm0O7sx68paZVJgJFwlM7yTbYlrSL0zObPU4jvdXaz24OfHFhA9vefMeLZ55CXpag4aj8i4/Dp63+cXuo5IO27clQRMadAL+fzpfxlyOlJJ+jgExsmXjJqr3rVLbhBgMEg5myuWAEZL1lxZIx7kK2EcP/JiYFjfPvcJCIvb0HbjgirwZSqtPaTe4onUnMdeVSaM94s6+VY7bsJo0YSEFVwBKaVoYFhod/54lx7DiSUnXzw== 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(66574015)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(30864003)(7416002)(66556008)(7696005)(316002)(83380400001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 3uspjPJYOBaMQqRp2ILWjjcncbBl1OAWIgKA4nB4qXKceOONhwv2s8kjQK129qaOAxPHoOd1YB+Muxsoud0emo8XPGmUGmYyj0co4k3VurJ7btDTcN7COvGkYlwGefDlxZhzMP6RmY3iZLNqx8eoBPxUzjzJsV5hP3g/yEq8R3s6yXKk0h4+f5cXD9wteYvR4b3xr8PrMllSIYxq2jLRTD/k85JATFAJ6k5IW2bCeW/dzXZOkPodQhxplNcm5E1nUDMow27HptqnpFeG38Vy7IC5uHBAn2cHxb6+sb8vwl1bKxEHrURVuHnGeRj2p7AXPnTliTeWRuxRRsIEFndVmhqJenO/1q5pOG0ZBRL3bo/q2M0727JsSXftbzoM3fz5VfEeh5T2y9tL/QAWP/bxO2St0CRqvgKwNGX7MNy0mlhadg8IxfpyQhORFntx7gMqzBCqNxo9eJ+66LO0mNrXchhAsidZfazI+4BE1BD6jwiFREYuaAfbjowH+o8Qkspl3jPMDY1rfVMaamfTMmou6DOVnjRvROnYl1m5DXXQR/IwDKeOvMr1+kK9osPIWPOwQa346yZQnmBfJpqyFiEnNeyLNC7igUbiTNVSVQCtf2v9puoWFveUsDrzkLmMPz/B8yK97eJoh4HNaT7SKaq7YduvTqylGjnHVpz4cIK0hz1HY2v0/j2xyhj40LQvPuaEYDR4+g4JgtpN4RirbSylYKh6R6s3ZgNssHDfBJm6/+OMLBAR8voLoSVcN+1FU7C5RSOifK55CDKw9DYNRgIbtkDmbB2ZVTafYRKWSoiRM2OIs6Fo+LTqp1h4GA60ka8R X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: abd4f4ce-388b-4221-efde-08d97c517728 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:38.5491 (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: +f3OOskXJS41Rk7pM013pea/IfVPJ0b3s+kpL9Sl8GcJk4MzASJw3gURyvzdzQBd3MPW/6cAhSKwO/hBM0r/Eg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 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/data_tx.c | 596 ++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/data_tx.h | 68 +++ 2 files changed, 664 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/data_tx.c create mode 100644 drivers/net/wireless/silabs/wfx/data_tx.h diff --git a/drivers/net/wireless/silabs/wfx/data_tx.c b/drivers/net/wireless/silabs/wfx/data_tx.c new file mode 100644 index 000000000000..e258ef39df72 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/data_tx.c @@ -0,0 +1,596 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Data transmitting implementation. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "data_tx.h" +#include "wfx.h" +#include "bh.h" +#include "sta.h" +#include "queue.h" +#include "debug.h" +#include "traces.h" +#include "hif_tx_mib.h" + +static int wfx_get_hw_rate(struct wfx_dev *wdev, + const struct ieee80211_tx_rate *rate) +{ + struct ieee80211_supported_band *band; + + if (rate->idx < 0) + return -1; + if (rate->flags & IEEE80211_TX_RC_MCS) { + if (rate->idx > 7) { + WARN(1, "wrong rate->idx value: %d", rate->idx); + return -1; + } + return rate->idx + 14; + } + /* The device only support 2GHz, else band information should be + * retrieved from ieee80211_tx_info + */ + band = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]; + if (rate->idx >= band->n_bitrates) { + WARN(1, "wrong rate->idx value: %d", rate->idx); + return -1; + } + return band->bitrates[rate->idx].hw_value; +} + +/* TX policy cache implementation */ + +static void wfx_tx_policy_build(struct wfx_vif *wvif, struct tx_policy *policy, + struct ieee80211_tx_rate *rates) +{ + struct wfx_dev *wdev = wvif->wdev; + int i, rateid; + u8 count; + + WARN(rates[0].idx < 0, "invalid rate policy"); + memset(policy, 0, sizeof(*policy)); + for (i = 0; i < IEEE80211_TX_MAX_RATES; ++i) { + if (rates[i].idx < 0) + break; + WARN_ON(rates[i].count > 15); + rateid = wfx_get_hw_rate(wdev, &rates[i]); + /* Pack two values in each byte of policy->rates */ + count = rates[i].count; + if (rateid % 2) + count <<= 4; + policy->rates[rateid / 2] |= count; + } +} + +static bool tx_policy_is_equal(const struct tx_policy *a, + const struct tx_policy *b) +{ + return !memcmp(a->rates, b->rates, sizeof(a->rates)); +} + +static int wfx_tx_policy_find(struct tx_policy_cache *cache, + struct tx_policy *wanted) +{ + struct tx_policy *it; + + list_for_each_entry(it, &cache->used, link) + if (tx_policy_is_equal(wanted, it)) + return it - cache->cache; + list_for_each_entry(it, &cache->free, link) + if (tx_policy_is_equal(wanted, it)) + return it - cache->cache; + return -1; +} + +static void wfx_tx_policy_use(struct tx_policy_cache *cache, + struct tx_policy *entry) +{ + ++entry->usage_count; + list_move(&entry->link, &cache->used); +} + +static int wfx_tx_policy_release(struct tx_policy_cache *cache, + struct tx_policy *entry) +{ + int ret = --entry->usage_count; + + if (!ret) + list_move(&entry->link, &cache->free); + return ret; +} + +static int wfx_tx_policy_get(struct wfx_vif *wvif, + struct ieee80211_tx_rate *rates, bool *renew) +{ + int idx; + struct tx_policy_cache *cache = &wvif->tx_policy_cache; + struct tx_policy wanted; + struct tx_policy *entry; + + wfx_tx_policy_build(wvif, &wanted, rates); + + spin_lock_bh(&cache->lock); + if (list_empty(&cache->free)) { + WARN(1, "unable to get a valid Tx policy"); + spin_unlock_bh(&cache->lock); + return HIF_TX_RETRY_POLICY_INVALID; + } + idx = wfx_tx_policy_find(cache, &wanted); + if (idx >= 0) { + *renew = false; + } else { + /* If policy is not found create a new one using the oldest + * entry in "free" list + */ + *renew = true; + entry = list_entry(cache->free.prev, struct tx_policy, link); + memcpy(entry->rates, wanted.rates, sizeof(entry->rates)); + entry->uploaded = false; + entry->usage_count = 0; + idx = entry - cache->cache; + } + wfx_tx_policy_use(cache, &cache->cache[idx]); + if (list_empty(&cache->free)) + ieee80211_stop_queues(wvif->wdev->hw); + spin_unlock_bh(&cache->lock); + return idx; +} + +static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx) +{ + int usage, locked; + struct tx_policy_cache *cache = &wvif->tx_policy_cache; + + if (idx == HIF_TX_RETRY_POLICY_INVALID) + return; + spin_lock_bh(&cache->lock); + locked = list_empty(&cache->free); + usage = wfx_tx_policy_release(cache, &cache->cache[idx]); + if (locked && !usage) + ieee80211_wake_queues(wvif->wdev->hw); + spin_unlock_bh(&cache->lock); +} + +static int wfx_tx_policy_upload(struct wfx_vif *wvif) +{ + struct tx_policy *policies = wvif->tx_policy_cache.cache; + u8 tmp_rates[12]; + int i, is_used; + + do { + spin_lock_bh(&wvif->tx_policy_cache.lock); + for (i = 0; i < ARRAY_SIZE(wvif->tx_policy_cache.cache); ++i) { + is_used = memzcmp(policies[i].rates, + sizeof(policies[i].rates)); + if (!policies[i].uploaded && is_used) + break; + } + if (i < ARRAY_SIZE(wvif->tx_policy_cache.cache)) { + policies[i].uploaded = true; + memcpy(tmp_rates, policies[i].rates, sizeof(tmp_rates)); + spin_unlock_bh(&wvif->tx_policy_cache.lock); + hif_set_tx_rate_retry_policy(wvif, i, tmp_rates); + } else { + spin_unlock_bh(&wvif->tx_policy_cache.lock); + } + } while (i < ARRAY_SIZE(wvif->tx_policy_cache.cache)); + return 0; +} + +void wfx_tx_policy_upload_work(struct work_struct *work) +{ + struct wfx_vif *wvif = + container_of(work, struct wfx_vif, tx_policy_upload_work); + + wfx_tx_policy_upload(wvif); + wfx_tx_unlock(wvif->wdev); +} + +void wfx_tx_policy_init(struct wfx_vif *wvif) +{ + struct tx_policy_cache *cache = &wvif->tx_policy_cache; + int i; + + memset(cache, 0, sizeof(*cache)); + + spin_lock_init(&cache->lock); + INIT_LIST_HEAD(&cache->used); + INIT_LIST_HEAD(&cache->free); + + for (i = 0; i < ARRAY_SIZE(cache->cache); ++i) + list_add(&cache->cache[i].link, &cache->free); +} + +/* Tx implementation */ + +static bool wfx_is_action_back(struct ieee80211_hdr *hdr) +{ + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr; + + if (!ieee80211_is_action(mgmt->frame_control)) + return false; + if (mgmt->u.action.category != WLAN_CATEGORY_BACK) + return false; + return true; +} + +static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, + struct ieee80211_hdr *hdr) +{ + struct wfx_sta_priv *sta_priv = + sta ? (struct wfx_sta_priv *)&sta->drv_priv : NULL; + const u8 *da = ieee80211_get_DA(hdr); + + if (sta_priv && sta_priv->link_id) + return sta_priv->link_id; + if (wvif->vif->type != NL80211_IFTYPE_AP) + return 0; + if (is_multicast_ether_addr(da)) + return 0; + return HIF_LINK_ID_NOT_ASSOCIATED; +} + +static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) +{ + int i; + bool finished; + + /* Firmware is not able to mix rates with different flags */ + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI) + rates[i].flags |= IEEE80211_TX_RC_SHORT_GI; + if (!(rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) + rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; + if (!(rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)) + rates[i].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; + } + + /* Sort rates and remove duplicates */ + do { + finished = true; + for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) { + if (rates[i + 1].idx == rates[i].idx && + rates[i].idx != -1) { + rates[i].count += rates[i + 1].count; + if (rates[i].count > 15) + rates[i].count = 15; + rates[i + 1].idx = -1; + rates[i + 1].count = 0; + + finished = false; + } + if (rates[i + 1].idx > rates[i].idx) { + swap(rates[i + 1], rates[i]); + finished = false; + } + } + } while (!finished); + /* Ensure that MCS0 or 1Mbps is present at the end of the retry list */ + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + if (rates[i].idx == 0) + break; + if (rates[i].idx == -1) { + rates[i].idx = 0; + rates[i].count = 8; /* == hw->max_rate_tries */ + rates[i].flags = rates[i - 1].flags & + IEEE80211_TX_RC_MCS; + break; + } + } + /* All retries use long GI */ + for (i = 1; i < IEEE80211_TX_MAX_RATES; i++) + rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; +} + +static u8 wfx_tx_get_retry_policy_id(struct wfx_vif *wvif, + struct ieee80211_tx_info *tx_info) +{ + bool tx_policy_renew = false; + u8 ret; + + ret = wfx_tx_policy_get(wvif, tx_info->driver_rates, &tx_policy_renew); + if (ret == HIF_TX_RETRY_POLICY_INVALID) + dev_warn(wvif->wdev->dev, "unable to get a valid Tx policy"); + + if (tx_policy_renew) { + wfx_tx_lock(wvif->wdev); + if (!schedule_work(&wvif->tx_policy_upload_work)) + wfx_tx_unlock(wvif->wdev); + } + return ret; +} + +static int wfx_tx_get_frame_format(struct ieee80211_tx_info *tx_info) +{ + if (!(tx_info->driver_rates[0].flags & IEEE80211_TX_RC_MCS)) + return HIF_FRAME_FORMAT_NON_HT; + else if (!(tx_info->driver_rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) + return HIF_FRAME_FORMAT_MIXED_FORMAT_HT; + else + return HIF_FRAME_FORMAT_GF_HT_11N; +} + +static int wfx_tx_get_icv_len(struct ieee80211_key_conf *hw_key) +{ + int mic_space; + + if (!hw_key) + return 0; + if (hw_key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) + return 0; + mic_space = (hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) ? 8 : 0; + return hw_key->icv_len + mic_space; +} + +static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, + struct sk_buff *skb) +{ + struct hif_msg *hif_msg; + struct hif_req_tx *req; + struct wfx_tx_priv *tx_priv; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + int queue_id = skb_get_queue_mapping(skb); + size_t offset = (size_t)skb->data & 3; + int wmsg_len = sizeof(struct hif_msg) + + sizeof(struct hif_req_tx) + offset; + + WARN(queue_id >= IEEE80211_NUM_ACS, "unsupported queue_id"); + wfx_tx_fixup_rates(tx_info->driver_rates); + + /* From now tx_info->control is unusable */ + memset(tx_info->rate_driver_data, 0, sizeof(struct wfx_tx_priv)); + /* Fill tx_priv */ + tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data; + tx_priv->icv_size = wfx_tx_get_icv_len(hw_key); + + /* Fill hif_msg */ + WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb"); + WARN(offset & 1, "attempt to transmit an unaligned frame"); + skb_put(skb, tx_priv->icv_size); + skb_push(skb, wmsg_len); + memset(skb->data, 0, wmsg_len); + hif_msg = (struct hif_msg *)skb->data; + hif_msg->len = cpu_to_le16(skb->len); + hif_msg->id = HIF_REQ_ID_TX; + hif_msg->interface = wvif->id; + if (skb->len > wvif->wdev->hw_caps.size_inp_ch_buf) { + dev_warn(wvif->wdev->dev, + "requested frame size (%d) is larger than maximum supported (%d)\n", + skb->len, wvif->wdev->hw_caps.size_inp_ch_buf); + skb_pull(skb, wmsg_len); + return -EIO; + } + + /* Fill tx request */ + req = (struct hif_req_tx *)hif_msg->body; + /* packet_id just need to be unique on device. 32bits are more than + * necessary for that task, so we take advantage of it to add some extra + * data for debug. + */ + req->packet_id = atomic_add_return(1, &wvif->wdev->packet_id) & 0xFFFF; + req->packet_id |= IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)) << 16; + req->packet_id |= queue_id << 28; + + req->fc_offset = offset; + /* Queue index are inverted between firmware and Linux */ + req->queue_id = 3 - queue_id; + req->peer_sta_id = wfx_tx_get_link_id(wvif, sta, hdr); + req->retry_policy_index = wfx_tx_get_retry_policy_id(wvif, tx_info); + req->frame_format = wfx_tx_get_frame_format(tx_info); + if (tx_info->driver_rates[0].flags & IEEE80211_TX_RC_SHORT_GI) + req->short_gi = 1; + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + req->after_dtim = 1; + + /* Auxiliary operations */ + wfx_tx_queues_put(wvif, skb); + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + schedule_work(&wvif->update_tim_work); + wfx_bh_request_tx(wvif->wdev); + return 0; +} + +void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif; + struct ieee80211_sta *sta = control ? control->sta : NULL; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + size_t driver_data_room = sizeof_field(struct ieee80211_tx_info, + rate_driver_data); + + BUILD_BUG_ON_MSG(sizeof(struct wfx_tx_priv) > driver_data_room, + "struct tx_priv is too large"); + WARN(skb->next || skb->prev, "skb is already member of a list"); + /* control.vif can be NULL for injected frames */ + if (tx_info->control.vif) + wvif = (struct wfx_vif *)tx_info->control.vif->drv_priv; + else + wvif = wvif_iterate(wdev, NULL); + if (WARN_ON(!wvif)) + goto drop; + /* Because of TX_AMPDU_SETUP_IN_HW, mac80211 does not try to send any + * BlockAck session management frame. The check below exist just in case. + */ + if (wfx_is_action_back(hdr)) { + dev_info(wdev->dev, "drop BA action\n"); + goto drop; + } + if (wfx_tx_inner(wvif, sta, skb)) + goto drop; + + return; + +drop: + ieee80211_tx_status_irqsafe(wdev->hw, skb); +} + +static void wfx_skb_dtor(struct wfx_vif *wvif, struct sk_buff *skb) +{ + struct hif_msg *hif = (struct hif_msg *)skb->data; + struct hif_req_tx *req = (struct hif_req_tx *)hif->body; + unsigned int offset = sizeof(struct hif_msg) + + sizeof(struct hif_req_tx) + + req->fc_offset; + + if (!wvif) { + pr_warn("vif associated with the skb does not exist anymore\n"); + return; + } + wfx_tx_policy_put(wvif, req->retry_policy_index); + skb_pull(skb, offset); + ieee80211_tx_status_irqsafe(wvif->wdev->hw, skb); +} + +static void wfx_tx_fill_rates(struct wfx_dev *wdev, + struct ieee80211_tx_info *tx_info, + const struct hif_cnf_tx *arg) +{ + struct ieee80211_tx_rate *rate; + int tx_count; + int i; + + tx_count = arg->ack_failures; + if (!arg->status || arg->ack_failures) + tx_count += 1; /* Also report success */ + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + rate = &tx_info->status.rates[i]; + if (rate->idx < 0) + break; + if (tx_count < rate->count && + arg->status == HIF_STATUS_TX_FAIL_RETRIES && + arg->ack_failures) + dev_dbg(wdev->dev, "all retries were not consumed: %d != %d\n", + rate->count, tx_count); + if (tx_count <= rate->count && tx_count && + arg->txed_rate != wfx_get_hw_rate(wdev, rate)) + dev_dbg(wdev->dev, "inconsistent tx_info rates: %d != %d\n", + arg->txed_rate, wfx_get_hw_rate(wdev, rate)); + if (tx_count > rate->count) { + tx_count -= rate->count; + } else if (!tx_count) { + rate->count = 0; + rate->idx = -1; + } else { + rate->count = tx_count; + tx_count = 0; + } + } + if (tx_count) + dev_dbg(wdev->dev, "%d more retries than expected\n", tx_count); +} + +void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) +{ + const struct wfx_tx_priv *tx_priv; + struct ieee80211_tx_info *tx_info; + struct wfx_vif *wvif; + struct sk_buff *skb; + + skb = wfx_pending_get(wdev, arg->packet_id); + if (!skb) { + dev_warn(wdev->dev, "received unknown packet_id (%#.8x) from chip\n", + arg->packet_id); + return; + } + tx_info = IEEE80211_SKB_CB(skb); + tx_priv = wfx_skb_tx_priv(skb); + wvif = wdev_to_wvif(wdev, ((struct hif_msg *)skb->data)->interface); + WARN_ON(!wvif); + if (!wvif) + return; + + /* Note that wfx_pending_get_pkt_us_delay() get data from tx_info */ + _trace_tx_stats(arg, skb, wfx_pending_get_pkt_us_delay(wdev, skb)); + wfx_tx_fill_rates(wdev, tx_info, arg); + skb_trim(skb, skb->len - tx_priv->icv_size); + + /* From now, you can touch to tx_info->status, but do not touch to + * tx_priv anymore + */ + /* FIXME: use ieee80211_tx_info_clear_status() */ + memset(tx_info->rate_driver_data, 0, sizeof(tx_info->rate_driver_data)); + memset(tx_info->pad, 0, sizeof(tx_info->pad)); + + if (!arg->status) { + tx_info->status.tx_time = + le32_to_cpu(arg->media_delay) - + le32_to_cpu(arg->tx_queue_delay); + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) + tx_info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + else + tx_info->flags |= IEEE80211_TX_STAT_ACK; + } else if (arg->status == HIF_STATUS_TX_FAIL_REQUEUE) { + WARN(!arg->requeue, "incoherent status and result_flags"); + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + wvif->after_dtim_tx_allowed = false; /* DTIM period elapsed */ + schedule_work(&wvif->update_tim_work); + } + tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + } + wfx_skb_dtor(wvif, skb); +} + +static void wfx_flush_vif(struct wfx_vif *wvif, u32 queues, + struct sk_buff_head *dropped) +{ + struct wfx_queue *queue; + int i; + + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (!(BIT(i) & queues)) + continue; + queue = &wvif->tx_queue[i]; + if (dropped) + wfx_tx_queue_drop(wvif, queue, dropped); + } + if (wvif->wdev->chip_frozen) + return; + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (!(BIT(i) & queues)) + continue; + queue = &wvif->tx_queue[i]; + if (wait_event_timeout(wvif->wdev->tx_dequeue, + wfx_tx_queue_empty(wvif, queue), + msecs_to_jiffies(1000)) <= 0) + dev_warn(wvif->wdev->dev, + "frames queued while flushing tx queues?"); + } +} + +void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ + struct wfx_dev *wdev = hw->priv; + struct sk_buff_head dropped; + struct wfx_vif *wvif; + struct hif_msg *hif; + struct sk_buff *skb; + + skb_queue_head_init(&dropped); + if (vif) { + wvif = (struct wfx_vif *)vif->drv_priv; + wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); + } else { + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); + } + wfx_tx_flush(wdev); + if (wdev->chip_frozen) + wfx_pending_drop(wdev, &dropped); + while ((skb = skb_dequeue(&dropped)) != NULL) { + hif = (struct hif_msg *)skb->data; + wvif = wdev_to_wvif(wdev, hif->interface); + ieee80211_tx_info_clear_status(IEEE80211_SKB_CB(skb)); + wfx_skb_dtor(wvif, skb); + } +} diff --git a/drivers/net/wireless/silabs/wfx/data_tx.h b/drivers/net/wireless/silabs/wfx/data_tx.h new file mode 100644 index 000000000000..15590a8faefe --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/data_tx.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Data transmitting implementation. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_DATA_TX_H +#define WFX_DATA_TX_H + +#include +#include + +#include "hif_api_cmd.h" +#include "hif_api_mib.h" + +struct wfx_tx_priv; +struct wfx_dev; +struct wfx_vif; + +struct tx_policy { + struct list_head link; + int usage_count; + u8 rates[12]; + bool uploaded; +}; + +struct tx_policy_cache { + struct tx_policy cache[HIF_TX_RETRY_POLICY_MAX]; + /* FIXME: use a trees and drop hash from tx_policy */ + struct list_head used; + struct list_head free; + spinlock_t lock; +}; + +struct wfx_tx_priv { + ktime_t xmit_timestamp; + unsigned char icv_size; +}; + +void wfx_tx_policy_init(struct wfx_vif *wvif); +void wfx_tx_policy_upload_work(struct work_struct *work); + +void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb); +void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg); +void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); + +static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info; + + if (!skb) + return NULL; + tx_info = IEEE80211_SKB_CB(skb); + return (struct wfx_tx_priv *)tx_info->rate_driver_data; +} + +static inline struct hif_req_tx *wfx_skb_txreq(struct sk_buff *skb) +{ + struct hif_msg *hif = (struct hif_msg *)skb->data; + struct hif_req_tx *req = (struct hif_req_tx *)hif->body; + + return req; +} + +#endif From patchwork Mon Sep 20 16:11:31 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: 12505909 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 20D13C433FE for ; Mon, 20 Sep 2021 16:14:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0195E60F70 for ; Mon, 20 Sep 2021 16:14:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243530AbhITQP6 (ORCPT ); Mon, 20 Sep 2021 12:15:58 -0400 Received: from mail-mw2nam10on2075.outbound.protection.outlook.com ([40.107.94.75]:38624 "EHLO NAM10-MW2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242800AbhITQOZ (ORCPT ); Mon, 20 Sep 2021 12:14:25 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CdFtHj1aCRqXIoA58sak2nMOX2agBhrFs3TjVP4IGjeceKuo5wbrofdvuyQzvi/eJV8a/XyWc9D5xS0c5+9p1+SHeyqhJNxLG12Od3gRqk571ovVOdxJ9PkWJLAUOgyjnf7glSaukLPsiGzxLFMl6CUEkocPG8xtfO61k+IRfCI3uqMGH5I8ryTClQEwFWB32Fvabmh7zZblZ5ltUuPMG1iyJ8B2r6aF18hLC7RdyZzjOlOtkcpuYA4ba++fWsjPKmoILUEodFGER5CYUUqZNgJZ1oDJ6qS0RI8bxVDZmG0FVhxh5eEgccUhXglZy/Tur51H9Cv1fHDOTHnBIkGmfg== 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=ybgEuCsNV9bbyHcBBr4CpymIperNZ1kVekePC1cgfQg=; b=NvH9NPZhRvF+x5vyocr2CIK3s1iknXlgIvy9YL2tWm2CfhNW3jebXZ6IVx4HDN+1JAtJbkbBrRIsc/Rn6CyZ6Srr7aleJrIlSZIRTbuiLN62hKgVUDeBFeBJ5/SprtsLuD/w/634lFGFJMUD4zDhu+at0So1NaVKhz92TjHg4QAjGkf8wzmHcBatfo8oKogRyP9QJyQH0PjsALOhzVPA2idS6j2UXKIyjKUGh3YjeIeQZSjp3Cfm/tElk+yfQ36wwXCfy87xqYNRaJdzoDM0ydYBZN4s3L2SpszYjeXeocRDWSqJpZA6nKp3XSf74rTN/tFwarT/Rnj7HjIvAmEWlQ== 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=ybgEuCsNV9bbyHcBBr4CpymIperNZ1kVekePC1cgfQg=; b=SICZq/eQ0loABuXipZwkSEKbuYWz++cL45kqgPGxnurOkDqfPcKW2fgyc5888OLnP04l/fTiPNeZW+dlJUEfZb1+Hc62DVx44yGOACsN+jDtyomFWQqDh5B0VDBvNBy2r7CfVXVNYIfAiaXvfK/vXgrKAjiKljhsLLR32yguyCA= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:41 +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:41 +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 19/24] wfx: add sta.c/sta.h Date: Mon, 20 Sep 2021 18:11:31 +0200 Message-Id: <20210920161136.2398632-20-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:38 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2825e139-6c0f-408c-1259-08d97c517899 X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Q4l27SyrwU8W4m91tNpOyJ1RqS4hFJoc2bFfZzs4FUyj6PiTvpGSgrtK2FrbhzC0TL0FlUcAasIcYQuRnAyBgKpoDJ5zj+KZ6n/+OCy/XrXlKzQQBZhicjCDyUS7GfzlwBfOdoYxP1FVfJGk8OeppHMVoayCvpaBcmMm4lxJbz4q6QA5O4qsI5S2BNjRthEE8J4JAuOyw2tB4L3L+IaqqJ91NJb/PDxKAKhnLDIC9pLQwag51K5tU7cLLwbcFG5/iHHerGA7EwO244wJ0o5zsRLG6twGXZJCMcEy8hdJSRQngOyNtFOdkTHcabT0+JnxWm/DiP1MIEByvY6o2SFTzyyWwGbHjaW7THq7/PQs2zgYeppot7gZmnBjo8pHNMOhTDGvefyFb2139wCS/AzK2e5xDepaZVmkz0FiOYpGUEcaq6fzHt94wf2ugZ5YfN/Ui9P9fJwnZATwgA/Hm5qdhs5HaV3oVm57RTo3BNgFFtVOPIO+fAn2rRwJmbJ4t34jKzL4EPAD9U05gh3F/WSUoq3IIsACPIWJiQe8yrX5MaaOqBYGCxa9NpiyAazXLufwMOeXamkD5hshh0id+kWGOLhK6KiurNT8stlAwvx8TdaEVqc7I6A3W8NqjJ02T42IQTL7yS7bhaJautEsjD8Vkw== 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(66574015)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(30864003)(7416002)(66556008)(7696005)(316002)(83380400001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: Ag2GmHrnQPWJ3VkBre1lP7sMV0aC3uuDN8V/1HHS3ZCutlHuwUaDPnbNSJmE/LDcmDfgQiGlMMi05/7s9ChxwOL2WwbmgqA8dbZT2+Tti6TyZoq9tG6IDq7yS/1mz3ufM5aZlZKKkViW02+vAMEsHg/uI8MsL5whDp+/xh0kXOrd3AyS9W+XjPygzyvzI1hFUyOtbB68NBjaj24EikG72rzRE5615M/ubSqtMeyn2FpqPsAPp5S6/jBxxXgQNtZv53AoRns2FKwzxH7BHWmXKM5jdgXwbSLmEIpYQa+wWaQIy++srlYH2ZlamN9QgyfPlnRKgVqzPGu87zq1XdKAcFOBR+MY0DhLVaKvHvptq78VmSd+VmXRupOuiXKAzcSdhyYAGdyw3qNF0dkYNiejQ6FXZ/rJLhRZ2Wef1nz6aEXUBkcv5W81UN+YqWT/4Rd7GvD8esCc5qhn4qmTTukmi/Ec5xiqaXRjSirklUq+szsL7VRxyGmOInHyjWCd2H4Gdb7epG3HKKybFwc9+aHGC/pSf22sTbSsD57cbKdqlvFjdm+8dJzJtiAysGZxqfEcsxray+HGsXTwigYeoSswS5lHnFs6kmemm1+UaqNdV2Iozd0az2sY4DRSRkL37EuV6112Jn1CAu+DhJGPibEL3b3uwbD7w976LMMGyJ0vRFxy5p78tuTm2Vh9DQ6fbmeVXcXzndeENxwHSIeyTRWpyKhdbOJkahvhwQ46fbO+gE3v7LKl7GDxpWJH18htiKHM/WDBFRpD3c9Xne6WIJohW8633rfiuqj9zH1YKa98UsNHoFGx+tQA1EDMNkOPnp73 X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2825e139-6c0f-408c-1259-08d97c517899 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:40.9907 (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: NgfhmwaQT8pTr1qFHOECn03UJbjI4IOL6a8q3LhGnMCWcUrM2wF0XaAXmurJRVkyKQl4MSPA0Py2YYgq2p8jDg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 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/sta.c | 832 ++++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/sta.h | 73 +++ 2 files changed, 905 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/sta.c create mode 100644 drivers/net/wireless/silabs/wfx/sta.h diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c new file mode 100644 index 000000000000..b0aebe0e6c36 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/sta.c @@ -0,0 +1,832 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Implementation of mac80211 API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include + +#include "sta.h" +#include "wfx.h" +#include "fwio.h" +#include "bh.h" +#include "key.h" +#include "scan.h" +#include "debug.h" +#include "hif_tx.h" +#include "hif_tx_mib.h" + +#define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2 + +u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) +{ + int i; + u32 ret = 0; + /* The device only supports 2GHz */ + struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]; + + for (i = 0; i < sband->n_bitrates; i++) { + if (rates & BIT(i)) { + if (i >= sband->n_bitrates) + dev_warn(wdev->dev, "unsupported basic rate\n"); + else + ret |= BIT(sband->bitrates[i].hw_value); + } + } + return ret; +} + +void wfx_cooling_timeout_work(struct work_struct *work) +{ + struct wfx_dev *wdev = container_of(to_delayed_work(work), + struct wfx_dev, + cooling_timeout_work); + + wdev->chip_frozen = true; + wfx_tx_unlock(wdev); +} + +void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd) +{ + if (cmd == STA_NOTIFY_AWAKE) { + /* Device recover normal temperature */ + if (cancel_delayed_work(&wdev->cooling_timeout_work)) + wfx_tx_unlock(wdev); + } else { + /* Device is too hot */ + schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ); + wfx_tx_lock(wdev); + } +} + +static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon) +{ + static const struct hif_ie_table_entry filter_ies[] = { + { + .ie_id = WLAN_EID_VENDOR_SPECIFIC, + .has_changed = 1, + .no_longer = 1, + .has_appeared = 1, + .oui = { 0x50, 0x6F, 0x9A }, + }, { + .ie_id = WLAN_EID_HT_OPERATION, + .has_changed = 1, + .no_longer = 1, + .has_appeared = 1, + }, { + .ie_id = WLAN_EID_ERP_INFO, + .has_changed = 1, + .no_longer = 1, + .has_appeared = 1, + }, { + .ie_id = WLAN_EID_CHANNEL_SWITCH, + .has_changed = 1, + .no_longer = 1, + .has_appeared = 1, + } + }; + + if (!filter_beacon) { + hif_beacon_filter_control(wvif, 0, 1); + } else { + hif_set_beacon_filter_table(wvif, ARRAY_SIZE(filter_ies), filter_ies); + hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0); + } +} + +void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, + unsigned int *total_flags, u64 unused) +{ + struct wfx_vif *wvif = NULL; + struct wfx_dev *wdev = hw->priv; + bool filter_bssid, filter_prbreq, filter_beacon; + + /* Notes: + * - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered + * - PS-Poll (FIF_PSPOLL) are never filtered + * - RTS, CTS and Ack (FIF_CONTROL) are always filtered + * - Broken frames (FIF_FCSFAIL and FIF_PLCPFAIL) are always filtered + * - Firmware does (yet) allow to forward unicast traffic sent to + * other stations (aka. promiscuous mode) + */ + *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS | + FIF_PROBE_REQ | FIF_PSPOLL; + + mutex_lock(&wdev->conf_mutex); + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + mutex_lock(&wvif->scan_lock); + + /* Note: FIF_BCN_PRBRESP_PROMISC covers probe response and + * beacons from other BSS + */ + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + filter_beacon = false; + else + filter_beacon = true; + wfx_filter_beacon(wvif, filter_beacon); + + if (*total_flags & FIF_OTHER_BSS) + filter_bssid = false; + else + filter_bssid = true; + + /* In AP mode, chip can reply to probe request itself */ + if (*total_flags & FIF_PROBE_REQ && + wvif->vif->type == NL80211_IFTYPE_AP) { + dev_dbg(wdev->dev, "do not forward probe request in AP mode\n"); + *total_flags &= ~FIF_PROBE_REQ; + } + + if (*total_flags & FIF_PROBE_REQ) + filter_prbreq = false; + else + filter_prbreq = true; + hif_set_rx_filter(wvif, filter_bssid, filter_prbreq); + + mutex_unlock(&wvif->scan_lock); + } + mutex_unlock(&wdev->conf_mutex); +} + +static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) +{ + struct ieee80211_channel *chan0 = NULL, *chan1 = NULL; + struct ieee80211_conf *conf = &wvif->wdev->hw->conf; + + WARN(!wvif->vif->bss_conf.assoc && enable_ps, + "enable_ps is reliable only if associated"); + if (wdev_to_wvif(wvif->wdev, 0)) + chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan; + if (wdev_to_wvif(wvif->wdev, 1)) + chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan; + if (chan0 && chan1 && wvif->vif->type != NL80211_IFTYPE_AP) { + if (chan0->hw_value == chan1->hw_value) { + /* It is useless to enable PS if channels are the same. */ + if (enable_ps) + *enable_ps = false; + if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) + dev_info(wvif->wdev->dev, "ignoring requested PS mode"); + return -1; + } else { + /* It is necessary to enable PS if channels + * are different. + */ + if (enable_ps) + *enable_ps = true; + if (wvif->wdev->force_ps_timeout > -1) + return wvif->wdev->force_ps_timeout; + else if (wfx_api_older_than(wvif->wdev, 3, 2)) + return 0; + else + return 30; + } + } + if (enable_ps) + *enable_ps = wvif->vif->bss_conf.ps; + if (wvif->wdev->force_ps_timeout > -1) + return wvif->wdev->force_ps_timeout; + else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) + return conf->dynamic_ps_timeout; + else + return -1; +} + +int wfx_update_pm(struct wfx_vif *wvif) +{ + int ps_timeout; + bool ps; + + if (!wvif->vif->bss_conf.assoc) + return 0; + ps_timeout = wfx_get_ps_timeout(wvif, &ps); + if (!ps) + ps_timeout = 0; + WARN_ON(ps_timeout < 0); + if (wvif->uapsd_mask) + ps_timeout = 0; + + if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, + TU_TO_JIFFIES(512))) + dev_warn(wvif->wdev->dev, + "timeout while waiting of set_pm_mode_complete\n"); + return hif_set_pm(wvif, ps, ps_timeout); +} + +int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u16 queue, const struct ieee80211_tx_queue_params *params) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + int old_uapsd = wvif->uapsd_mask; + + WARN_ON(queue >= hw->queues); + + mutex_lock(&wdev->conf_mutex); + assign_bit(queue, &wvif->uapsd_mask, params->uapsd); + hif_set_edca_queue_params(wvif, queue, params); + if (wvif->vif->type == NL80211_IFTYPE_STATION && + old_uapsd != wvif->uapsd_mask) { + hif_set_uapsd_info(wvif, wvif->uapsd_mask); + wfx_update_pm(wvif); + } + mutex_unlock(&wdev->conf_mutex); + return 0; +} + +int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = NULL; + + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + hif_rts_threshold(wvif, value); + return 0; +} + +void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi) +{ + /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 + * RSSI = RCPI / 2 - 110 + */ + int rcpi_rssi; + int cqm_evt; + + rcpi_rssi = raw_rcpi_rssi / 2 - 110; + if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold) + cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; + else + cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; + ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL); +} + +static void wfx_beacon_loss_work(struct work_struct *work) +{ + struct wfx_vif *wvif = container_of(to_delayed_work(work), + struct wfx_vif, beacon_loss_work); + struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf; + + ieee80211_beacon_loss(wvif->vif); + schedule_delayed_work(to_delayed_work(work), + msecs_to_jiffies(bss_conf->beacon_int)); +} + +void wfx_set_default_unicast_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int idx) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + hif_wep_default_key_id(wvif, idx); +} + +void wfx_reset(struct wfx_vif *wvif) +{ + struct wfx_dev *wdev = wvif->wdev; + + wfx_tx_lock_flush(wdev); + hif_reset(wvif, false); + wfx_tx_policy_init(wvif); + if (wvif_count(wdev) <= 1) + hif_set_block_ack_policy(wvif, 0xFF, 0xFF); + wfx_tx_unlock(wdev); + wvif->join_in_progress = false; + cancel_delayed_work_sync(&wvif->beacon_loss_work); + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_update_pm(wvif); +} + +int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; + + sta_priv->vif_id = wvif->id; + + if (vif->type == NL80211_IFTYPE_STATION) + hif_set_mfp(wvif, sta->mfp, sta->mfp); + + /* In station mode, the firmware interprets new link-id as a TDLS peer */ + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) + return 0; + sta_priv->link_id = ffz(wvif->link_id_map); + wvif->link_id_map |= BIT(sta_priv->link_id); + WARN_ON(!sta_priv->link_id); + WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX); + hif_map_link(wvif, false, sta->addr, sta_priv->link_id, sta->mfp); + + return 0; +} + +int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; + + /* See note in wfx_sta_add() */ + if (!sta_priv->link_id) + return 0; + /* FIXME add a mutex? */ + hif_map_link(wvif, true, sta->addr, sta_priv->link_id, false); + wvif->link_id_map &= ~BIT(sta_priv->link_id); + return 0; +} + +static int wfx_upload_ap_templates(struct wfx_vif *wvif) +{ + struct sk_buff *skb; + + skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); + if (!skb) + return -ENOMEM; + hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, + API_RATE_INDEX_B_1MBPS); + dev_kfree_skb(skb); + + skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif); + if (!skb) + return -ENOMEM; + hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, + API_RATE_INDEX_B_1MBPS); + dev_kfree_skb(skb); + return 0; +} + +static void wfx_set_mfp_ap(struct wfx_vif *wvif) +{ + struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); + const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable); + const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, + skb->data + ieoffset, + skb->len - ieoffset); + const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16); + const int pairwise_cipher_suite_size = 4 / sizeof(u16); + const int akm_suite_size = 4 / sizeof(u16); + + if (ptr) { + ptr += pairwise_cipher_suite_count_offset; + if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) + return; + ptr += 1 + pairwise_cipher_suite_size * *ptr; + if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) + return; + ptr += 1 + akm_suite_size * *ptr; + if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) + return; + hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6)); + } +} + +int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + struct wfx_dev *wdev = wvif->wdev; + int ret; + + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_update_pm(wvif); + wvif = (struct wfx_vif *)vif->drv_priv; + wfx_upload_ap_templates(wvif); + ret = hif_start(wvif, &vif->bss_conf, wvif->channel); + if (ret > 0) + return -EIO; + wfx_set_mfp_ap(wvif); + return ret; +} + +void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wfx_reset(wvif); +} + +static void wfx_join(struct wfx_vif *wvif) +{ + int ret; + struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; + struct cfg80211_bss *bss = NULL; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + const u8 *ssidie = NULL; + int ssidlen = 0; + + wfx_tx_lock_flush(wvif->wdev); + + bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel, + conf->bssid, NULL, 0, + IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); + if (!bss && !conf->ibss_joined) { + wfx_tx_unlock(wvif->wdev); + return; + } + + rcu_read_lock(); /* protect ssidie */ + if (bss) + ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); + if (ssidie) { + ssidlen = ssidie[1]; + if (ssidlen > IEEE80211_MAX_SSID_LEN) + ssidlen = IEEE80211_MAX_SSID_LEN; + memcpy(ssid, &ssidie[2], ssidlen); + } + rcu_read_unlock(); + + cfg80211_put_bss(wvif->wdev->hw->wiphy, bss); + + wvif->join_in_progress = true; + ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen); + if (ret) { + ieee80211_connection_loss(wvif->vif); + wfx_reset(wvif); + } else { + /* Due to beacon filtering it is possible that the + * AP's beacon is not known for the mac80211 stack. + * Disable filtering temporary to make sure the stack + * receives at least one + */ + wfx_filter_beacon(wvif, false); + } + wfx_tx_unlock(wvif->wdev); +} + +static void wfx_join_finalize(struct wfx_vif *wvif, + struct ieee80211_bss_conf *info) +{ + struct ieee80211_sta *sta = NULL; + int ampdu_density = 0; + bool greenfield = false; + + rcu_read_lock(); /* protect sta */ + if (info->bssid && !info->ibss_joined) + sta = ieee80211_find_sta(wvif->vif, info->bssid); + if (sta && sta->ht_cap.ht_supported) + ampdu_density = sta->ht_cap.ampdu_density; + if (sta && sta->ht_cap.ht_supported && + !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) + greenfield = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); + rcu_read_unlock(); + + wvif->join_in_progress = false; + hif_set_association_mode(wvif, ampdu_density, greenfield, + info->use_short_preamble); + hif_keep_alive_period(wvif, 0); + /* beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use + * the same value. + */ + hif_set_bss_params(wvif, info->aid, 7); + hif_set_beacon_wakeup_period(wvif, 1, 1); + wfx_update_pm(wvif); +} + +int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wfx_upload_ap_templates(wvif); + wfx_join(wvif); + return 0; +} + +void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wfx_reset(wvif); +} + +static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable) +{ + /* Driver has Content After DTIM Beacon in queue. Driver is waiting for + * a signal from the firmware. Since we are going to stop to send + * beacons, this signal will never happens. See also + * wfx_suspend_resume_mc() + */ + if (!enable && wfx_tx_queues_has_cab(wvif)) { + wvif->after_dtim_tx_allowed = true; + wfx_bh_request_tx(wvif->wdev); + } + hif_beacon_transmit(wvif, enable); +} + +void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u32 changed) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + int i; + + mutex_lock(&wdev->conf_mutex); + + if (changed & BSS_CHANGED_BASIC_RATES || + changed & BSS_CHANGED_BEACON_INT || + changed & BSS_CHANGED_BSSID) { + if (vif->type == NL80211_IFTYPE_STATION) + wfx_join(wvif); + } + + if (changed & BSS_CHANGED_ASSOC) { + if (info->assoc || info->ibss_joined) + wfx_join_finalize(wvif, info); + else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION) + wfx_reset(wvif); + else + dev_warn(wdev->dev, "misunderstood change: ASSOC\n"); + } + + if (changed & BSS_CHANGED_BEACON_INFO) { + if (vif->type != NL80211_IFTYPE_STATION) + dev_warn(wdev->dev, "misunderstood change: BEACON_INFO\n"); + hif_set_beacon_wakeup_period(wvif, info->dtim_period, + info->dtim_period); + /* We temporary forwarded beacon for join process. It is now no + * more necessary. + */ + wfx_filter_beacon(wvif, true); + } + + if (changed & BSS_CHANGED_ARP_FILTER) { + for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) { + __be32 *arp_addr = &info->arp_addr_list[i]; + + if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES) + arp_addr = NULL; + if (i >= info->arp_addr_cnt) + arp_addr = NULL; + hif_set_arp_ipv4_filter(wvif, i, arp_addr); + } + } + + if (changed & BSS_CHANGED_AP_PROBE_RESP || + changed & BSS_CHANGED_BEACON) + wfx_upload_ap_templates(wvif); + + if (changed & BSS_CHANGED_BEACON_ENABLED) + wfx_enable_beacon(wvif, info->enable_beacon); + + if (changed & BSS_CHANGED_KEEP_ALIVE) + hif_keep_alive_period(wvif, info->max_idle_period * + USEC_PER_TU / USEC_PER_MSEC); + + if (changed & BSS_CHANGED_ERP_CTS_PROT) + hif_erp_use_protection(wvif, info->use_cts_prot); + + if (changed & BSS_CHANGED_ERP_SLOT) + hif_slot_time(wvif, info->use_short_slot ? 9 : 20); + + if (changed & BSS_CHANGED_CQM) + hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold, + info->cqm_rssi_hyst); + + if (changed & BSS_CHANGED_TXPOWER) + hif_set_output_power(wvif, info->txpower); + + if (changed & BSS_CHANGED_PS) + wfx_update_pm(wvif); + + mutex_unlock(&wdev->conf_mutex); +} + +static int wfx_update_tim(struct wfx_vif *wvif) +{ + struct sk_buff *skb; + u16 tim_offset, tim_length; + u8 *tim_ptr; + + skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif, + &tim_offset, &tim_length); + if (!skb) + return -ENOENT; + tim_ptr = skb->data + tim_offset; + + if (tim_offset && tim_length >= 6) { + /* Firmware handles DTIM counter internally */ + tim_ptr[2] = 0; + + /* Set/reset aid0 bit */ + if (wfx_tx_queues_has_cab(wvif)) + tim_ptr[4] |= 1; + else + tim_ptr[4] &= ~1; + } + + hif_update_ie_beacon(wvif, tim_ptr, tim_length); + dev_kfree_skb(skb); + + return 0; +} + +static void wfx_update_tim_work(struct work_struct *work) +{ + struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work); + + wfx_update_tim(wvif); +} + +int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv; + struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id); + + if (!wvif) { + dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); + return -EIO; + } + schedule_work(&wvif->update_tim_work); + return 0; +} + +void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) +{ + struct wfx_vif *wvif_it; + + if (notify_cmd != STA_NOTIFY_AWAKE) + return; + + /* Device won't be able to honor CAB if a scan is in progress on any + * interface. Prefer to skip this DTIM and wait for the next one. + */ + wvif_it = NULL; + while ((wvif_it = wvif_iterate(wvif->wdev, wvif_it)) != NULL) + if (mutex_is_locked(&wvif_it->scan_lock)) + return; + + if (!wfx_tx_queues_has_cab(wvif) || wvif->after_dtim_tx_allowed) + dev_warn(wvif->wdev->dev, "incorrect sequence (%d CAB in queue)", + wfx_tx_queues_has_cab(wvif)); + wvif->after_dtim_tx_allowed = true; + wfx_bh_request_tx(wvif->wdev); +} + +int wfx_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + /* Aggregation is implemented fully in firmware */ + switch (params->action) { + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + /* Just acknowledge it to enable frame re-ordering */ + return 0; + default: + /* Leave the firmware doing its business for tx aggregation */ + return -EOPNOTSUPP; + } +} + +int wfx_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf) +{ + return 0; +} + +void wfx_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf) +{ +} + +void wfx_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + u32 changed) +{ +} + +int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *conf) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + struct ieee80211_channel *ch = conf->def.chan; + + WARN(wvif->channel, "channel overwrite"); + wvif->channel = ch; + + return 0; +} + +void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *conf) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + struct ieee80211_channel *ch = conf->def.chan; + + WARN(wvif->channel != ch, "channel mismatch"); + wvif->channel = NULL; +} + +int wfx_config(struct ieee80211_hw *hw, u32 changed) +{ + return 0; +} + +int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + int i, ret = 0; + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | + IEEE80211_VIF_SUPPORTS_UAPSD | + IEEE80211_VIF_SUPPORTS_CQM_RSSI; + + mutex_lock(&wdev->conf_mutex); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + break; + default: + mutex_unlock(&wdev->conf_mutex); + return -EOPNOTSUPP; + } + + /* FIXME: prefer use of container_of() to get vif */ + wvif->vif = vif; + wvif->wdev = wdev; + + wvif->link_id_map = 1; /* link-id 0 is reserved for multicast */ + INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work); + INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work); + + init_completion(&wvif->set_pm_mode_complete); + complete(&wvif->set_pm_mode_complete); + INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); + + mutex_init(&wvif->scan_lock); + init_completion(&wvif->scan_complete); + INIT_WORK(&wvif->scan_work, wfx_hw_scan_work); + + wfx_tx_queues_init(wvif); + wfx_tx_policy_init(wvif); + + for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) { + if (!wdev->vif[i]) { + wdev->vif[i] = vif; + wvif->id = i; + break; + } + } + WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than supported"); + + hif_set_macaddr(wvif, vif->addr); + + mutex_unlock(&wdev->conf_mutex); + + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + /* Combo mode does not support Block Acks. We can re-enable them */ + if (wvif_count(wdev) == 1) + hif_set_block_ack_policy(wvif, 0xFF, 0xFF); + else + hif_set_block_ack_policy(wvif, 0x00, 0x00); + } + return ret; +} + +void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300)); + wfx_tx_queues_check_empty(wvif); + + mutex_lock(&wdev->conf_mutex); + WARN(wvif->link_id_map != 1, "corrupted state"); + + hif_reset(wvif, false); + hif_set_macaddr(wvif, NULL); + wfx_tx_policy_init(wvif); + + cancel_delayed_work_sync(&wvif->beacon_loss_work); + wdev->vif[wvif->id] = NULL; + wvif->vif = NULL; + + mutex_unlock(&wdev->conf_mutex); + + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + /* Combo mode does not support Block Acks. We can re-enable them */ + if (wvif_count(wdev) == 1) + hif_set_block_ack_policy(wvif, 0xFF, 0xFF); + else + hif_set_block_ack_policy(wvif, 0x00, 0x00); + } +} + +int wfx_start(struct ieee80211_hw *hw) +{ + return 0; +} + +void wfx_stop(struct ieee80211_hw *hw) +{ + struct wfx_dev *wdev = hw->priv; + + WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending)); +} diff --git a/drivers/net/wireless/silabs/wfx/sta.h b/drivers/net/wireless/silabs/wfx/sta.h new file mode 100644 index 000000000000..4d7e38be4235 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/sta.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Implementation of mac80211 API. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_STA_H +#define WFX_STA_H + +#include + +struct wfx_dev; +struct wfx_vif; + +struct wfx_sta_priv { + int link_id; + int vif_id; +}; + +/* mac80211 interface */ +int wfx_start(struct ieee80211_hw *hw); +void wfx_stop(struct ieee80211_hw *hw); +int wfx_config(struct ieee80211_hw *hw, u32 changed); +int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value); +void wfx_set_default_unicast_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int idx); +void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, + unsigned int *total_flags, u64 unused); + +int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u16 queue, const struct ieee80211_tx_queue_params *params); +void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u32 changed); +int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, struct ieee80211_sta *sta); +int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); +int wfx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params); +int wfx_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf); +void wfx_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf); +void wfx_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, u32 changed); +int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *conf); +void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *conf); + +/* Hardware API Callbacks */ +void wfx_cooling_timeout_work(struct work_struct *work); +void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd); +void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd); +void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi); +int wfx_update_pm(struct wfx_vif *wvif); + +/* Other Helpers */ +void wfx_reset(struct wfx_vif *wvif); +u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates); + +#endif From patchwork Mon Sep 20 16:11:32 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: 12505917 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 A73A9C433EF for ; Mon, 20 Sep 2021 16:15:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E68961166 for ; Mon, 20 Sep 2021 16:15:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243198AbhITQQr (ORCPT ); Mon, 20 Sep 2021 12:16:47 -0400 Received: from mail-bn7nam10on2058.outbound.protection.outlook.com ([40.107.92.58]:43040 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S243177AbhITQO4 (ORCPT ); Mon, 20 Sep 2021 12:14:56 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OcNpPUasR156CwNhHb92+ZV5i+WO5bFIWzlbpZ4mLT+kuPbGMboQSlPT4AblMfSqahTtXlGmvCAXkuPZE4HEWOwjHVEBVMrHV7TKNkLH2+MdXrapt+pLZ3wvi/SEY9gkClPtg3R62/O3Q9xxFBmQMMxcTrtgBnwI+9ldhruKkmBX3hs8sc2cQuWdI5NWG0gVJq2jivty4Vb1vgWyzc3pTPyjMMvbSBboZmq8qmjtrXb4YhLxQCWT+3hkL/aPc2WexcyxxKmo4TqmFaIEj2MmIA2R+zTiiLjuvYNq9MHY+Sb7r03d0/io1gJnE67ojWap7J32KLFY2qyCJVK+1vB7GA== 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=dEk3+qj4e1ksJvrrPFbprdR/znDZKjI5IcYfuaq0J5c=; b=dzrV5Zm7UVVLVlDa+iGcf/unJ+JX7BsixASfmHs26dvVWRjqCCxWAZ3RdGkwmcJQia9uHg3Nrn2a68xGg0HETVMtvPfibQKPGwxrYKNgmanSLgklAUo/vvsdaRuNz5LM8Jn8AjUOPOTdlNCCZz8grTrDczqV8jZuKalh1A5h4HZ3L/MQjwtk32/8SAQjIkDXAgFURq3sMJtuq8Bv5X7jMTgYLxddZn/EWNpGsVZE5PTxo6L4Iy5GwasT2S78iZLg+82HstgMvZrCWOr3nj3NK/0Gu4qiPB8jZBu/0Y4Poe0u+WSlP72zYZ6N3E9SLifzn2l9H6S2nHq7RsdRaqswgw== 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=dEk3+qj4e1ksJvrrPFbprdR/znDZKjI5IcYfuaq0J5c=; b=BO294GIqUn4AgVhyp54eq9tcV3+a+Vaonv+yhiDZTnC92uI+FCvXL0XjurehuiMpUxfRcxfhgqMyc/Vlw8FDO0XZ5agd0YUczedBELarwOA6FCt81yDcMkoBQqeGSA5pHmpzMxjgNjJrJ9xvKp1HQi1WuYLyukR/YDWeRMOftqs= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:43 +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:43 +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 20/24] wfx: add scan.c/scan.h Date: Mon, 20 Sep 2021 18:11:32 +0200 Message-Id: <20210920161136.2398632-21-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:41 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a3306306-46db-43cd-580b-08d97c517a02 X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:4303; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: edrMjC4vnRzxV1bWX7pWWyZimy6A7FTVqdiUD5rVAmw/utAnaqYNSnUiu1532Kh/6sk9eQ40dPDya+VN3e1ebQ4/tHs+2mO/cT7jfNrRWexl1TotTaowglbD+HoasvtQoxStOaKUnVlEscGKnIdy3Z2rsSs7YOQptOY2q/d9mvxrt7D1k8zxvu2Ge8RrK9UkgPLgIZmWMMBZmOEJfeoB4urL4sJn5/lKIEvUemjF8les9ae/gCrvsAgfN1pT7IgnGvs55PfYPxT3hSn8JZ3NDsBVaS5ffY+O4AYt8656K5sR/DzH3NdG2rIuAEPOJ9cjBOcY1zP18ete+BEqIDhOGUKHrdak0nAF+Ob8mU+pMZt3SihGvY60h7Z7kYAY4iHgZLKD+rhjmXLzal2jV2qHBBSUUgW3bgiyA5I6pDi+bceA8Sa3GpUI0i7Xwuy6zuOxtv0pC255Lo0H7Tqpv7+V/G4GEVbZO78d53XdggKVW2HmjbQJM0+e3aquNq4V3U74tNDHOKUo/6AJVKjkpX40ejUh1YNRpDeKvViThvZJLgfoYiNGKIXVabnmWCy2y24THp3GvQ/8w/3LvhvQgRi2QJmVQxmwwnbD2bPx9Ytri74Qt0I7+bh+zxIfWsVDWxDEPVkQmJJZhxgoa6yR90+izw== 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(66574015)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(7416002)(66556008)(7696005)(316002)(83380400001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: U+hvs9mVjQ1Ay4MEv+Io3REZh3h36j1kTagj5HdrLpfn+p+GRoYSgeT66Htflx6RzxJydYbgscb7njaLjHo6B25RreRLk6ao61m2axo8xgPiCz0mz0TTXDRdOBG3WiwsL0be260KUlIVJPKGsyyldpPeNMAk14i5+N+KGT0ylOzO28g3ppeFrgNT3yQBDrYQ9ayfEhkZBPm0bLoZBtdnJeOLQX4AyCOz6+z6q1N19GkLgru14IE51rrSj7286pM6A5wtfrUiYKQST5lEebUXcgA0sEVvSDhYhNIGdN+gEl1z85DOcpTRVyeAsKWKf1DaOuWjlBrf/8A/9eiqCBlM+sGdcrIlZ2+VV27rgfXtzAWYd/0Hl+iRvZd72IvTlvKu6uOphQ0NdhYEXXgU6Ji5B7yqidXk4nxDXBaM4ezpkEzywu3M8BtwA1MRcprNR5StlSa4WK61Klxpc1e4KZXbcZS3xJ8azBVn3RW/SPO7oHd7GOAc+QZyP2ptAlSNkfxs1kaDj7+f0rnbey97+P+yIi0pkWdPf9/RPXgkKoZCB3QoEKG2VSp89flcqRLudZ+UpOVqNt0GF9SR5PxRAaRpv6LhyNtDDXJTlD865ytNh/UBQzyoC+9YRhyL8SjDGVZBHkLwpzkEhZ6ivJ8kAwcBlxHLTrZYRRDTteA0OzHqEvEzD0phGxvviEMiKBkJgi6U704z6KU5iW2886xYnverrf5xdC3JLPUp8cPlyYAHgNJimm+NX4jWwIyp9S/l7F+1yuN7ZiJPgMGbiFO27B1DaB+zNQKthm5fubzJoX8q4QOEt7LQz0bzVsmGJLTzh6tQ X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: a3306306-46db-43cd-580b-08d97c517a02 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:43.2963 (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: CmLEXrQVDVvu/ldAC/d+3RAhaIL1CBTNn2p6kUejebhb+zipCs+R9GuXPLfRuy+hVbouuGYrefyEzHiGJXzUMw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 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/scan.c | 148 +++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/scan.h | 22 ++++ 2 files changed, 170 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/scan.c create mode 100644 drivers/net/wireless/silabs/wfx/scan.h diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c new file mode 100644 index 000000000000..0cc97dfac526 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/scan.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Scan related functions. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include + +#include "scan.h" +#include "wfx.h" +#include "sta.h" +#include "hif_tx_mib.h" + +static void __ieee80211_scan_completed_compat(struct ieee80211_hw *hw, + bool aborted) +{ + struct cfg80211_scan_info info = { + .aborted = aborted, + }; + + ieee80211_scan_completed(hw, &info); +} + +static int update_probe_tmpl(struct wfx_vif *wvif, + struct cfg80211_scan_request *req) +{ + struct sk_buff *skb; + + skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->vif->addr, + NULL, 0, req->ie_len); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, req->ie, req->ie_len); + hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBREQ, 0); + dev_kfree_skb(skb); + return 0; +} + +static int send_scan_req(struct wfx_vif *wvif, + struct cfg80211_scan_request *req, int start_idx) +{ + int i, ret; + struct ieee80211_channel *ch_start, *ch_cur; + + for (i = start_idx; i < req->n_channels; i++) { + ch_start = req->channels[start_idx]; + ch_cur = req->channels[i]; + WARN(ch_cur->band != NL80211_BAND_2GHZ, "band not supported"); + if (ch_cur->max_power != ch_start->max_power) + break; + if ((ch_cur->flags ^ ch_start->flags) & IEEE80211_CHAN_NO_IR) + break; + } + wfx_tx_lock_flush(wvif->wdev); + wvif->scan_abort = false; + reinit_completion(&wvif->scan_complete); + ret = hif_scan(wvif, req, start_idx, i - start_idx); + if (ret) { + wfx_tx_unlock(wvif->wdev); + return -EIO; + } + ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ); + if (!ret) { + hif_stop_scan(wvif); + ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ); + dev_dbg(wvif->wdev->dev, "scan timeout (%d channels done)\n", + wvif->scan_nb_chan_done); + } + if (!ret) { + dev_err(wvif->wdev->dev, "scan didn't stop\n"); + ret = -ETIMEDOUT; + } else if (wvif->scan_abort) { + dev_notice(wvif->wdev->dev, "scan abort\n"); + ret = -ECONNABORTED; + } else if (wvif->scan_nb_chan_done > i - start_idx) { + ret = -EIO; + } else { + ret = wvif->scan_nb_chan_done; + } + if (req->channels[start_idx]->max_power != wvif->vif->bss_conf.txpower) + hif_set_output_power(wvif, wvif->vif->bss_conf.txpower); + wfx_tx_unlock(wvif->wdev); + return ret; +} + +/* It is not really necessary to run scan request asynchronously. However, + * there is a bug in "iw scan" when ieee80211_scan_completed() is called before + * wfx_hw_scan() return + */ +void wfx_hw_scan_work(struct work_struct *work) +{ + struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan_work); + struct ieee80211_scan_request *hw_req = wvif->scan_req; + int chan_cur, ret, err; + + mutex_lock(&wvif->wdev->conf_mutex); + mutex_lock(&wvif->scan_lock); + if (wvif->join_in_progress) { + dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN"); + wfx_reset(wvif); + } + update_probe_tmpl(wvif, &hw_req->req); + chan_cur = 0; + err = 0; + do { + ret = send_scan_req(wvif, &hw_req->req, chan_cur); + if (ret > 0) { + chan_cur += ret; + err = 0; + } + if (!ret) + err++; + if (err > 2) { + dev_err(wvif->wdev->dev, "scan has not been able to start\n"); + ret = -ETIMEDOUT; + } + } while (ret >= 0 && chan_cur < hw_req->req.n_channels); + mutex_unlock(&wvif->scan_lock); + mutex_unlock(&wvif->wdev->conf_mutex); + __ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); +} + +int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + WARN_ON(hw_req->req.n_channels > HIF_API_MAX_NB_CHANNELS); + wvif->scan_req = hw_req; + schedule_work(&wvif->scan_work); + return 0; +} + +void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wvif->scan_abort = true; + hif_stop_scan(wvif); +} + +void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done) +{ + wvif->scan_nb_chan_done = nb_chan_done; + complete(&wvif->scan_complete); +} diff --git a/drivers/net/wireless/silabs/wfx/scan.h b/drivers/net/wireless/silabs/wfx/scan.h new file mode 100644 index 000000000000..78e3b984f375 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/scan.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Scan related functions. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#ifndef WFX_SCAN_H +#define WFX_SCAN_H + +#include + +struct wfx_dev; +struct wfx_vif; + +void wfx_hw_scan_work(struct work_struct *work); +int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *req); +void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done); + +#endif From patchwork Mon Sep 20 16:11:33 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: 12505915 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 2ACAFC433EF for ; Mon, 20 Sep 2021 16:15:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1561B60F70 for ; Mon, 20 Sep 2021 16:15:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243708AbhITQQ0 (ORCPT ); Mon, 20 Sep 2021 12:16:26 -0400 Received: from mail-bn7nam10on2062.outbound.protection.outlook.com ([40.107.92.62]:32097 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242945AbhITQOv (ORCPT ); Mon, 20 Sep 2021 12:14:51 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=EO02CzR5d4tyMc4UELSzpqMjL22cTT7PrxhLhycOQxzaiwLkS5IjDz88t/5K/iX1DUGjoxDHCsYsKF4INQnzZ89M4F7/9pmra9TqEJk/Fh/mhTxvYD8o0UuE465nYrNUb5tsZNZzRwWANG63ixgS8gKZ+5zMXn5rV4LbWumhWlecPbOeJKCrsOhGKdbZSxD+xSzid8ULPjmk6u15NyB4nEzEeWAhEAi3B4aH5f6VeCtU4V8RGtinCvnUsjWr1tz6mj60EIIP1l8gLaicBKFIaGauOGdN3Zi5sT3UwhWH3YxDYd2N9SfUFzrOzAzMuB6ilTFaPTVOzAoV9aSS8BEtFQ== 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=fZ2JaKzYlrdGaX+6E4MBhFuNexc43HZ2kCx0dbW2tZY=; b=NIppATt6E26d+sZ8X1j84lG5ypyO0gR9GnznwYWioltKKLHPNlUWouhOBAX++8t1egR44ZvYBR3TVzjtVqjACnt6+V8T0EgHqZ1h7fM+OSOWEIROeCJGWTKlTsmk87mHVulievPfG4lJsLCEaiy8Zl6+Y8HJwifMMXE6MqDjJ1B1yPRhHm+rOYSw0qHEAwsDLFTjDRwwbOkerSRLjXXmFWcyWs46hwHwiTUCmwDhrVUpYgpb9gifnc4BYqmPj7vFcflIeEnWCi27aw5Yfley9foJuHqQXk5ZiO4gnyc+64Xijuw7hNuUvmefwSiK0bOcTCGVasxTqlL8HtA5glbwXA== 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=fZ2JaKzYlrdGaX+6E4MBhFuNexc43HZ2kCx0dbW2tZY=; b=A6/DfwDMXjkb2KR1PKA+MqbMtWgHb5dGp390NFZYtSdcrFy5fXbs2bdPqTueK5BfsGZellgyRVh/oUdwJb3l+waxCcm3CkCsiIz5LWGVDX5+FBDfUVrCfQvBEZmx0pCR/nCL94X2LtfIRUOAvHwCbCrJPzbTHVRNxDuIRe2Y1sw= 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 SN6PR11MB2654.namprd11.prod.outlook.com (2603:10b6:805:54::31) 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:45 +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:45 +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 21/24] wfx: add debug.c/debug.h Date: Mon, 20 Sep 2021 18:11:33 +0200 Message-Id: <20210920161136.2398632-22-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:43 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 344e979e-0de9-42d9-aefe-08d97c517b6c X-MS-TrafficTypeDiagnostic: SN6PR11MB2654: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:989; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: pjC/EYYXametWwfKlvlA9jCCvXIspndYkO+qLr5PFEcIeA/wrYgzzVNbTIYRG61hcR8mj56GFMJ0BNrY3xvNm68Ox3W54k8MJAARa0+ubcSj2FrfDR859VC69wJLMU6I2tIRAYQiW08XTphZqVajYz+8Yif79O40SE6T0ftjyLaqJffxSxq5gyLY6IHn4Ze1Dyfu1NWDu4Hi6Sg0cvdEnn5opNa3T0xUmMp8EHI/zYBXa+upokeU1uZsv5HyMiXqZjrOqNl3noLQHtwZOvJXvJ3cwo876ts2fG+BYydRpVBUndpDGs/jSP4YLbctBjK1gdjKtwg+IEtvSYTUjzP8iOXTq8dAtgmlmY3FflOZ9/AglKLQ8KVIcbrtEDwO+Glt1jNAXvwiYHUp38RSamCnxYwbuOTE599tVPQhKwJ5aaKjuy44C7sHJGXx0WVXk0SETec19LHsnT/y+NFZLTDliln8Chm+0KiRKPnzf/WcQ7/AMwseRFw6radazktoas3t69rSlNAiJVOhuscLaRSVMLPocGIQI9usBE+dCYKY+IcerxwZPLnpWPte+OHg+y6Jxmdz/RWwp9OySqcvsE77fSIRkxQPkvQ1Qz7lcJDRmZ7gIzrlIsCcQUDNYjykCxD42mOpopXL6qiuOitT3Jjc5g== 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:(366004)(52116002)(36756003)(7696005)(30864003)(5660300002)(4326008)(316002)(107886003)(8676002)(2616005)(2906002)(66476007)(66946007)(66556008)(66574015)(7416002)(508600001)(86362001)(38100700002)(83380400001)(8936002)(1076003)(6486002)(186003)(6916009)(6666004)(54906003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: YCKh1wuEsa+K2LZ0IB0RXI9cYrYSDu264vy0RwLeZf9L/K0fT1zQuKj4vzmY1RnvpU2Q9/TeKhhIH7Hj5vEkB0fDH/sNnLuPJAU8H2aOutKTCGFpUQVgGAMVTIc4G9iV0K2PBgpGZhrCPZ50+N9tx1l+uLbLeDyQ2ndLjnYFQdhkrPUfncHiklJhuvAijtGgDUke3GuC8oWlBaJ4nFxo75aUY+LZDPlXhboi83Hvq+spJ9Zptc6Ll0TAchJWm0+83sBPqYP3Up3HntnENRK63lZqgMul/bq9gf8xUvAsSrOZF6jkxyEGDLWExA3qiB3XG0uz3ZLm/h6hEQcfqGjjK5//m/e6Naq7x9RXKYxysIxAmypWHCVe7rvGiduVPoywC6yDlQiKwWPMX7dfL4Z4LhkaXQarNGI7LRMFRsUoJL3n+9Ww3JgG8Xc3cyyeZeobuUmp4jV6NOwD6N77VgXMGSPkOZ/p3SzTuznmRBCPHQchwvEVpjDT4SN/PNHomJo0dFhd7avLDxxJezaYxZder8/PsYbv/54IvafBBHKOzakWFg4adxDpdmfffMe4jzTKBO0xPFT2fisGvWC1Jt8HAUJoA4IVmm7Qrl6E/9hPhUQI49IOVGtIYNDrokQTVlxSjTZCxzsOb5jDqR7/GQLrfD3cRYRyfVQfCZKPVB9Nm1zmKx9aAW2YTswh21v9sPNa0chygS8Y20I6/xSsjFoS3ua0EbDSD8ey6ezPS3MDJJdY3ZcWPNPXG5/9YsX+CUJOj1YhT1w4Yjb2HZRwtrcU7HT/r6Nmk2NZN3JUZdWF5ZbKpr8THlgXyy2KZceJD7Jx X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 344e979e-0de9-42d9-aefe-08d97c517b6c 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:45.6919 (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: Adii01UJSaGrng0Oa+SCwyA3EssSINHEZLBtyv2PXz6SUHPmBFMU6WVfmXcIb/UiITejnMG2fpfM1C5hgaXACw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB2654 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/debug.c | 365 ++++++++++++++++++++++++ drivers/net/wireless/silabs/wfx/debug.h | 19 ++ 2 files changed, 384 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/debug.c create mode 100644 drivers/net/wireless/silabs/wfx/debug.h diff --git a/drivers/net/wireless/silabs/wfx/debug.c b/drivers/net/wireless/silabs/wfx/debug.c new file mode 100644 index 000000000000..9f93268a3202 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/debug.c @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Debugfs interface. + * + * Copyright (c) 2017-2020, Silicon Laboratories, Inc. + * Copyright (c) 2010, ST-Ericsson + */ +#include +#include +#include + +#include "debug.h" +#include "wfx.h" +#include "sta.h" +#include "main.h" +#include "hif_tx.h" +#include "hif_tx_mib.h" + +#define CREATE_TRACE_POINTS +#include "traces.h" + +static const struct trace_print_flags hif_msg_print_map[] = { + hif_msg_list, +}; + +static const struct trace_print_flags hif_mib_print_map[] = { + hif_mib_list, +}; + +static const struct trace_print_flags wfx_reg_print_map[] = { + wfx_reg_list, +}; + +static const char *get_symbol(unsigned long val, + const struct trace_print_flags *symbol_array) +{ + int i; + + for (i = 0; symbol_array[i].mask != -1; i++) { + if (val == symbol_array[i].mask) + return symbol_array[i].name; + } + + return "unknown"; +} + +const char *get_hif_name(unsigned long id) +{ + return get_symbol(id, hif_msg_print_map); +} + +const char *get_mib_name(unsigned long id) +{ + return get_symbol(id, hif_mib_print_map); +} + +const char *get_reg_name(unsigned long id) +{ + return get_symbol(id, wfx_reg_print_map); +} + +static int wfx_counters_show(struct seq_file *seq, void *v) +{ + int ret, i; + struct wfx_dev *wdev = seq->private; + struct hif_mib_extended_count_table counters[3]; + + for (i = 0; i < ARRAY_SIZE(counters); i++) { + ret = hif_get_counters_table(wdev, i, counters + i); + if (ret < 0) + return ret; + if (ret > 0) + return -EIO; + } + + seq_printf(seq, "%-24s %12s %12s %12s\n", + "", "global", "iface 0", "iface 1"); + +#define PUT_COUNTER(name) \ + seq_printf(seq, "%-24s %12d %12d %12d\n", #name, \ + le32_to_cpu(counters[2].count_##name), \ + le32_to_cpu(counters[0].count_##name), \ + le32_to_cpu(counters[1].count_##name)) + + PUT_COUNTER(tx_frames); + PUT_COUNTER(tx_frames_multicast); + PUT_COUNTER(tx_frames_success); + PUT_COUNTER(tx_frames_retried); + PUT_COUNTER(tx_frames_multi_retried); + PUT_COUNTER(tx_frames_failed); + + PUT_COUNTER(ack_failed); + PUT_COUNTER(rts_success); + PUT_COUNTER(rts_failed); + + PUT_COUNTER(rx_frames); + PUT_COUNTER(rx_frames_multicast); + PUT_COUNTER(rx_frames_success); + PUT_COUNTER(rx_frames_failed); + PUT_COUNTER(drop_plcp); + PUT_COUNTER(drop_fcs); + PUT_COUNTER(drop_no_key); + PUT_COUNTER(drop_decryption); + PUT_COUNTER(drop_tkip_mic); + PUT_COUNTER(drop_bip_mic); + PUT_COUNTER(drop_cmac_icv); + PUT_COUNTER(drop_cmac_replay); + PUT_COUNTER(drop_ccmp_replay); + PUT_COUNTER(drop_duplicate); + + PUT_COUNTER(rx_bcn_miss); + PUT_COUNTER(rx_bcn_success); + PUT_COUNTER(rx_bcn_dtim); + PUT_COUNTER(rx_bcn_dtim_aid0_clr); + PUT_COUNTER(rx_bcn_dtim_aid0_set); + +#undef PUT_COUNTER + + for (i = 0; i < ARRAY_SIZE(counters[0].reserved); i++) + seq_printf(seq, "reserved[%02d]%12s %12d %12d %12d\n", i, "", + le32_to_cpu(counters[2].reserved[i]), + le32_to_cpu(counters[0].reserved[i]), + le32_to_cpu(counters[1].reserved[i])); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(wfx_counters); + +static const char * const channel_names[] = { + [0] = "1M", + [1] = "2M", + [2] = "5.5M", + [3] = "11M", + /* Entries 4 and 5 does not exist */ + [6] = "6M", + [7] = "9M", + [8] = "12M", + [9] = "18M", + [10] = "24M", + [11] = "36M", + [12] = "48M", + [13] = "54M", + [14] = "MCS0", + [15] = "MCS1", + [16] = "MCS2", + [17] = "MCS3", + [18] = "MCS4", + [19] = "MCS5", + [20] = "MCS6", + [21] = "MCS7", +}; + +static int wfx_rx_stats_show(struct seq_file *seq, void *v) +{ + struct wfx_dev *wdev = seq->private; + struct hif_rx_stats *st = &wdev->rx_stats; + int i; + + mutex_lock(&wdev->rx_stats_lock); + seq_printf(seq, "Timestamp: %dus\n", st->date); + seq_printf(seq, "Low power clock: frequency %uHz, external %s\n", + le32_to_cpu(st->pwr_clk_freq), + st->is_ext_pwr_clk ? "yes" : "no"); + seq_printf(seq, + "Num. of frames: %d, PER (x10e4): %d, Throughput: %dKbps/s\n", + st->nb_rx_frame, st->per_total, st->throughput); + seq_puts(seq, " Num. of PER RSSI SNR CFO\n"); + seq_puts(seq, " frames (x10e4) (dBm) (dB) (kHz)\n"); + for (i = 0; i < ARRAY_SIZE(channel_names); i++) { + if (channel_names[i]) + seq_printf(seq, "%5s %8d %8d %8d %8d %8d\n", + channel_names[i], + le32_to_cpu(st->nb_rx_by_rate[i]), + le16_to_cpu(st->per[i]), + (s16)le16_to_cpu(st->rssi[i]) / 100, + (s16)le16_to_cpu(st->snr[i]) / 100, + (s16)le16_to_cpu(st->cfo[i])); + } + mutex_unlock(&wdev->rx_stats_lock); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(wfx_rx_stats); + +static int wfx_tx_power_loop_show(struct seq_file *seq, void *v) +{ + struct wfx_dev *wdev = seq->private; + struct hif_tx_power_loop_info *st = &wdev->tx_power_loop_info; + int tmp; + + mutex_lock(&wdev->tx_power_loop_info_lock); + tmp = le16_to_cpu(st->tx_gain_dig); + seq_printf(seq, "Tx gain digital: %d\n", tmp); + tmp = le16_to_cpu(st->tx_gain_pa); + seq_printf(seq, "Tx gain PA: %d\n", tmp); + tmp = (s16)le16_to_cpu(st->target_pout); + seq_printf(seq, "Target Pout: %d.%02d dBm\n", tmp / 4, (tmp % 4) * 25); + tmp = (s16)le16_to_cpu(st->p_estimation); + seq_printf(seq, "FEM Pout: %d.%02d dBm\n", tmp / 4, (tmp % 4) * 25); + tmp = le16_to_cpu(st->vpdet); + seq_printf(seq, "Vpdet: %d mV\n", tmp); + seq_printf(seq, "Measure index: %d\n", st->measurement_index); + mutex_unlock(&wdev->tx_power_loop_info_lock); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(wfx_tx_power_loop); + +static ssize_t wfx_send_pds_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wfx_dev *wdev = file->private_data; + char *buf; + int ret; + + if (*ppos != 0) { + dev_dbg(wdev->dev, "PDS data must be written in one transaction"); + return -EBUSY; + } + buf = memdup_user(user_buf, count); + if (IS_ERR(buf)) + return PTR_ERR(buf); + *ppos = *ppos + count; + ret = wfx_send_pds(wdev, buf, count); + kfree(buf); + if (ret < 0) + return ret; + return count; +} + +static const struct file_operations wfx_send_pds_fops = { + .open = simple_open, + .write = wfx_send_pds_write, +}; + +struct dbgfs_hif_msg { + struct wfx_dev *wdev; + struct completion complete; + u8 reply[1024]; + int ret; +}; + +static ssize_t wfx_send_hif_msg_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct dbgfs_hif_msg *context = file->private_data; + struct wfx_dev *wdev = context->wdev; + struct hif_msg *request; + + if (completion_done(&context->complete)) { + dev_dbg(wdev->dev, "read previous result before start a new one\n"); + return -EBUSY; + } + if (count < sizeof(struct hif_msg)) + return -EINVAL; + + /* wfx_cmd_send() checks that reply buffer is wide enough, but does not + * return precise length read. User have to know how many bytes should + * be read. Filling reply buffer with a memory pattern may help user. + */ + memset(context->reply, 0xFF, sizeof(context->reply)); + request = memdup_user(user_buf, count); + if (IS_ERR(request)) + return PTR_ERR(request); + if (le16_to_cpu(request->len) != count) { + kfree(request); + return -EINVAL; + } + context->ret = wfx_cmd_send(wdev, request, context->reply, + sizeof(context->reply), false); + + kfree(request); + complete(&context->complete); + return count; +} + +static ssize_t wfx_send_hif_msg_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct dbgfs_hif_msg *context = file->private_data; + int ret; + + if (count > sizeof(context->reply)) + return -EINVAL; + ret = wait_for_completion_interruptible(&context->complete); + if (ret) + return ret; + if (context->ret < 0) + return context->ret; + /* Be careful, write() is waiting for a full message while read() + * only returns a payload + */ + if (copy_to_user(user_buf, context->reply, count)) + return -EFAULT; + + return count; +} + +static int wfx_send_hif_msg_open(struct inode *inode, struct file *file) +{ + struct dbgfs_hif_msg *context = kzalloc(sizeof(*context), GFP_KERNEL); + + if (!context) + return -ENOMEM; + context->wdev = inode->i_private; + init_completion(&context->complete); + file->private_data = context; + return 0; +} + +static int wfx_send_hif_msg_release(struct inode *inode, struct file *file) +{ + struct dbgfs_hif_msg *context = file->private_data; + + kfree(context); + return 0; +} + +static const struct file_operations wfx_send_hif_msg_fops = { + .open = wfx_send_hif_msg_open, + .release = wfx_send_hif_msg_release, + .write = wfx_send_hif_msg_write, + .read = wfx_send_hif_msg_read, +}; + +static int wfx_ps_timeout_set(void *data, u64 val) +{ + struct wfx_dev *wdev = (struct wfx_dev *)data; + struct wfx_vif *wvif; + + wdev->force_ps_timeout = val; + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_update_pm(wvif); + return 0; +} + +static int wfx_ps_timeout_get(void *data, u64 *val) +{ + struct wfx_dev *wdev = (struct wfx_dev *)data; + + *val = wdev->force_ps_timeout; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(wfx_ps_timeout_fops, wfx_ps_timeout_get, wfx_ps_timeout_set, "%lld\n"); + +int wfx_debug_init(struct wfx_dev *wdev) +{ + struct dentry *d; + + d = debugfs_create_dir("wfx", wdev->hw->wiphy->debugfsdir); + debugfs_create_file("counters", 0444, d, wdev, &wfx_counters_fops); + debugfs_create_file("rx_stats", 0444, d, wdev, &wfx_rx_stats_fops); + debugfs_create_file("tx_power_loop", 0444, d, wdev, + &wfx_tx_power_loop_fops); + debugfs_create_file("send_pds", 0200, d, wdev, &wfx_send_pds_fops); + debugfs_create_file("send_hif_msg", 0600, d, wdev, + &wfx_send_hif_msg_fops); + debugfs_create_file("ps_timeout", 0600, d, wdev, &wfx_ps_timeout_fops); + + return 0; +} diff --git a/drivers/net/wireless/silabs/wfx/debug.h b/drivers/net/wireless/silabs/wfx/debug.h new file mode 100644 index 000000000000..4b9c49a9fffb --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/debug.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Debugfs interface. + * + * Copyright (c) 2017-2019, Silicon Laboratories, Inc. + * Copyright (c) 2011, ST-Ericsson + */ +#ifndef WFX_DEBUG_H +#define WFX_DEBUG_H + +struct wfx_dev; + +int wfx_debug_init(struct wfx_dev *wdev); + +const char *get_hif_name(unsigned long id); +const char *get_mib_name(unsigned long id); +const char *get_reg_name(unsigned long id); + +#endif From patchwork Mon Sep 20 16:11:34 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: 12505919 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 D7D77C4332F for ; Mon, 20 Sep 2021 16:15:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B8EFE61175 for ; Mon, 20 Sep 2021 16:15:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243002AbhITQRU (ORCPT ); Mon, 20 Sep 2021 12:17:20 -0400 Received: from mail-bn7nam10on2065.outbound.protection.outlook.com ([40.107.92.65]:4704 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S239189AbhITQPU (ORCPT ); Mon, 20 Sep 2021 12:15:20 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iAuTn9bnQmJ1y8ixkcDgsuFpDI/M/juZYPNyFOtg48/bCeD3fILtnf1rfIgtDbrqpDQwZciQtzkthYxUB//aC2F8Hf6RjmLkorUvm98FkJUalLueXTL7/bYnKEKavWKl/UotWcMGaxH4fehcYR41TbXBkICvyvcyaHNHvbRSpr01eIa6rH/VTTO12ccEFtx4NKGyxLHcvOsD8k14hId1zISzmXrlGXJ6Kjhiy0a1TAM7cIG8YWnDtiF+zS4t3Df/ch47JdUO43TWFazvT+/JLzhPFb0K9yxrheF+RQPWnagJtxRB93x/eAcs6bG4pnSbtTI1+WDw5fLEHLnmUprmrQ== 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=BAezOkvJbcZwRz4eOVx5dT1/sgjmeA67Vtd9TVmp/Co=; b=ir8BqndMWQTVuxKoS+JlYfCW5YmKDhCblSQGYFknXFT0OQ29RcsbHQq6jlZ7Njn05ZDFKaFc+ZqwPc0CzX/6Sw20u4kzUjQSg3D8QZm1s3IYqvcGYCx75rbr/znygQ1x8jRRV4SVzAlwTJ+tLTvX/NT1g1qofkTCGZUKcNKnqEumvb2nYwUxfqq9b6PdkvZQtQan00XdyC64E66KJK7rD38yn/Kwp9Udf+bMWfUDYOAkOSDMqiTepouf5RibOGf6rtQE8jvO52HUc9+dCaUqRWfIkQIyRtSL8+/C98OS8kq7e63h8Az2XwMWJFdHS4I/5dUa04s39f3bMh65rdI7mw== 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=BAezOkvJbcZwRz4eOVx5dT1/sgjmeA67Vtd9TVmp/Co=; b=CY60IgbSPnpDNeoQyYqh7j+ZQaNnXGIFUtYDlICS3xXB1ujInW5zItGQqcnbXr+RpDRYgWydWrE6wSMdtmbzFqNTNbF4iC06reo4EmH9E8BlaGFtqjLYCHVU+wECiufZsgiAUmuJon+yBPARqLPWjCMw2XlrTPrcoKWIM0MQNw8= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:48 +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:48 +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 22/24] wfx: add traces.h Date: Mon, 20 Sep 2021 18:11:34 +0200 Message-Id: <20210920161136.2398632-23-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:45 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: bff3454d-d670-4ff8-3eee-08d97c517ccf X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:66; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: au75P/7nPSSxb2h6JLSY0xfu5clJy41yw93dx29X0Mx4uQ9gXlPO8DCPjoq+cAZMc2p1YWajCYwj0jX8xlZ6M/+lnx5jOfuJrosVMAklia7QAvvlxJJVBPdaaNYawrhUq6GlQEBzmcX0JqvmOAOv5W9QZiaa87ByT01e8LkC0Bq/fdohI+0e+WC6NjE97TCP3keLtzrs9v3wMhAIKeR2TE30j45ER6H3YHMiu4CfCgmQBwh1gYhjAGtaBHacMu3T0MN8KfzN8gw9LMJpgWuFWeKzJkI7yTmrU3S+8tAPGVP5i7GuQNAMtVKFikPoQuldmppfCEnx0LTgF/OEqSucsPSP46Iu9+sbhjxoARqtgWKO07QWiKh+PFb7WgrUgtmBdfiChLvqFpsM5OKJ/plgv2ZEMxu0pco+dd3s+cieGjx8BW4zyQyx81uoqpPuqeFE1A0eeQ38gVEg1ATQD6yYLn4B8UildLSFV+Um4w54QauLH0fSAvltNGHGO5jsnTQWZj/v/qpraWyFsKjwxEFevRYknGH7dVGqXsLLuhKZkJVyE9BaNhC6OKC4+4ZJhv7vvJ4ydby4z6ZRdZe3BWji8vewJFK5KqQP+N22jGyD8NUVshsH3BaaPpEHuz4vtM6xLzZU3RKSM4ojuIVmJozybc6hjY2W2Z0H5T1xd5NYapxlSPmBn3lwWPBHoYJioxA3 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(66574015)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(30864003)(7416002)(66556008)(7696005)(316002)(83380400001)(21314003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: DFNfz99x49nkNQFoShAdrKStlTXwgzLsBcRLr0lRzyUmVtEfFtqyldvc1UoCG1C3FKUiBvPqwp3Wc0GxI6pkaqpkc7nrv0JxkJOH9LaNA7jyX7EAKQSYK58Y38omV4Ogwz8uTP30aJzsSRETGibd9sb+VEFNn2xk61E7leplkW7Hb+Gbz3T5Bg/Ryhk/+wOFulLMN+hw+Zk6mhlBceQ0ZGu2xhFtmR8c0FzAG1BfMNAxvbYRomv7j15zssIuOwzl5Yby1lvDJ1DPEEcGUKXT4tSRP1LGpC29LW9aOkBWZ+EUJkx6qkzWyeq+KCnoALJgdJEtjLtLhAC78OZUMkgYrWan7ofck8uhG+jy3htORB7v8FKde04UgUi2OLAgCM6Yyc1Wd1VlGR+/ylhQtS6huUryCURH5xMBiUiPytqTCh5o+P4Hd+IJcc+yTXhnXdAT4yVHS1MQEUxCV5aIRMLtk+Br8h9rDYyjOYAfKz2hkUu1SucdKsrYOUo3V4wXKIrtob3zmmT9UkSqP55SFetNRcF23MaXjQdvCPvhEx5GrP03cEtb525KqYXBQAwdvzQjEOjzySDxLmsd7jKcfx4taVPkYjAnSFodFFUclmyL44BNEnyo0gDRPoZMv/RTQCt7nrMUbQ0lr6EH5OFOAViMlRqTjsZc8RrjiuEYmcAfb+SNfAX5jCI9LbNdHN0kR/Hbt41BpsPVu2ReEqN0gt4jCMsjMZVUP/OgXI/G9zqnHH0umSV9b7heoYZcn6gsRUQYSkbQuNtyNmImIdcu1olt38cp03hC1mc9b5xodYsFg9vEf5roFkDFb8FMxYWXxZT4 X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: bff3454d-d670-4ff8-3eee-08d97c517ccf 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:48.0356 (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: PhTeEhh0KvIXb6jkE7TbWYEzco9RoljU+T1tDdF5PkaLxWw1Xac3ZKvSBJznXke/C4sUuiQhJ7ApEU91zwo54g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 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/traces.h | 501 +++++++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 drivers/net/wireless/silabs/wfx/traces.h diff --git a/drivers/net/wireless/silabs/wfx/traces.h b/drivers/net/wireless/silabs/wfx/traces.h new file mode 100644 index 000000000000..e90dc73c4b01 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/traces.h @@ -0,0 +1,501 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Tracepoints definitions. + * + * Copyright (c) 2018-2020, Silicon Laboratories, Inc. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM wfx + +#if !defined(_WFX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _WFX_TRACE_H + +#include +#include + +#include "bus.h" +#include "hif_api_cmd.h" +#include "hif_api_mib.h" + +/* The hell below need some explanations. For each symbolic number, we need to + * define it with TRACE_DEFINE_ENUM() and in a list for __print_symbolic. + * + * 1. Define a new macro that call TRACE_DEFINE_ENUM(): + * + * #define xxx_name(sym) TRACE_DEFINE_ENUM(sym); + * + * 2. Define list of all symbols: + * + * #define list_names \ + * ... \ + * xxx_name(XXX) \ + * ... + * + * 3. Instantiate that list_names: + * + * list_names + * + * 4. Redefine xxx_name() as an entry of array for __print_symbolic() + * + * #undef xxx_name + * #define xxx_name(msg) { msg, #msg }, + * + * 5. list_name can now nearly be used with __print_symbolic() but, + * __print_symbolic() dislike last comma of list. So we define a new list + * with a dummy element: + * + * #define list_for_print_symbolic list_names { -1, NULL } + */ + +#define _hif_msg_list \ + hif_cnf_name(ADD_KEY) \ + hif_cnf_name(BEACON_TRANSMIT) \ + hif_cnf_name(EDCA_QUEUE_PARAMS) \ + hif_cnf_name(JOIN) \ + hif_cnf_name(MAP_LINK) \ + hif_cnf_name(READ_MIB) \ + hif_cnf_name(REMOVE_KEY) \ + hif_cnf_name(RESET) \ + hif_cnf_name(SET_BSS_PARAMS) \ + hif_cnf_name(SET_PM_MODE) \ + hif_cnf_name(START) \ + hif_cnf_name(START_SCAN) \ + hif_cnf_name(STOP_SCAN) \ + hif_cnf_name(TX) \ + hif_cnf_name(MULTI_TRANSMIT) \ + hif_cnf_name(UPDATE_IE) \ + hif_cnf_name(WRITE_MIB) \ + hif_cnf_name(CONFIGURATION) \ + hif_cnf_name(CONTROL_GPIO) \ + hif_cnf_name(PREVENT_ROLLBACK) \ + hif_cnf_name(SET_SL_MAC_KEY) \ + hif_cnf_name(SL_CONFIGURE) \ + hif_cnf_name(SL_EXCHANGE_PUB_KEYS) \ + hif_cnf_name(SHUT_DOWN) \ + hif_ind_name(EVENT) \ + hif_ind_name(JOIN_COMPLETE) \ + hif_ind_name(RX) \ + hif_ind_name(SCAN_CMPL) \ + hif_ind_name(SET_PM_MODE_CMPL) \ + hif_ind_name(SUSPEND_RESUME_TX) \ + hif_ind_name(SL_EXCHANGE_PUB_KEYS) \ + hif_ind_name(ERROR) \ + hif_ind_name(EXCEPTION) \ + hif_ind_name(GENERIC) \ + hif_ind_name(WAKEUP) \ + hif_ind_name(STARTUP) + +#define hif_msg_list_enum _hif_msg_list + +#undef hif_cnf_name +#undef hif_ind_name +#define hif_cnf_name(msg) TRACE_DEFINE_ENUM(HIF_CNF_ID_##msg); +#define hif_ind_name(msg) TRACE_DEFINE_ENUM(HIF_IND_ID_##msg); +hif_msg_list_enum +#undef hif_cnf_name +#undef hif_ind_name +#define hif_cnf_name(msg) { HIF_CNF_ID_##msg, #msg }, +#define hif_ind_name(msg) { HIF_IND_ID_##msg, #msg }, +#define hif_msg_list hif_msg_list_enum { -1, NULL } + +#define _hif_mib_list \ + hif_mib_name(ARP_IP_ADDRESSES_TABLE) \ + hif_mib_name(ARP_KEEP_ALIVE_PERIOD) \ + hif_mib_name(BEACON_FILTER_ENABLE) \ + hif_mib_name(BEACON_FILTER_TABLE) \ + hif_mib_name(BEACON_STATS) \ + hif_mib_name(BEACON_WAKEUP_PERIOD) \ + hif_mib_name(BLOCK_ACK_POLICY) \ + hif_mib_name(CCA_CONFIG) \ + hif_mib_name(CONFIG_DATA_FILTER) \ + hif_mib_name(COUNTERS_TABLE) \ + hif_mib_name(CURRENT_TX_POWER_LEVEL) \ + hif_mib_name(DOT11_MAC_ADDRESS) \ + hif_mib_name(DOT11_MAX_RECEIVE_LIFETIME) \ + hif_mib_name(DOT11_MAX_TRANSMIT_MSDU_LIFETIME) \ + hif_mib_name(DOT11_RTS_THRESHOLD) \ + hif_mib_name(DOT11_WEP_DEFAULT_KEY_ID) \ + hif_mib_name(ETHERTYPE_DATAFRAME_CONDITION) \ + hif_mib_name(EXTENDED_COUNTERS_TABLE) \ + hif_mib_name(GL_BLOCK_ACK_INFO) \ + hif_mib_name(GL_OPERATIONAL_POWER_MODE) \ + hif_mib_name(GL_SET_MULTI_MSG) \ + hif_mib_name(GRP_SEQ_COUNTER) \ + hif_mib_name(INACTIVITY_TIMER) \ + hif_mib_name(INTERFACE_PROTECTION) \ + hif_mib_name(IPV4_ADDR_DATAFRAME_CONDITION) \ + hif_mib_name(IPV6_ADDR_DATAFRAME_CONDITION) \ + hif_mib_name(KEEP_ALIVE_PERIOD) \ + hif_mib_name(MAC_ADDR_DATAFRAME_CONDITION) \ + hif_mib_name(MAGIC_DATAFRAME_CONDITION) \ + hif_mib_name(MAX_TX_POWER_LEVEL) \ + hif_mib_name(NON_ERP_PROTECTION) \ + hif_mib_name(NS_IP_ADDRESSES_TABLE) \ + hif_mib_name(OVERRIDE_INTERNAL_TX_RATE) \ + hif_mib_name(PORT_DATAFRAME_CONDITION) \ + hif_mib_name(PROTECTED_MGMT_POLICY) \ + hif_mib_name(RCPI_RSSI_THRESHOLD) \ + hif_mib_name(RX_FILTER) \ + hif_mib_name(SET_ASSOCIATION_MODE) \ + hif_mib_name(SET_DATA_FILTERING) \ + hif_mib_name(SET_HT_PROTECTION) \ + hif_mib_name(SET_TX_RATE_RETRY_POLICY) \ + hif_mib_name(SET_UAPSD_INFORMATION) \ + hif_mib_name(SLOT_TIME) \ + hif_mib_name(STATISTICS_TABLE) \ + hif_mib_name(TEMPLATE_FRAME) \ + hif_mib_name(TSF_COUNTER) \ + hif_mib_name(UC_MC_BC_DATAFRAME_CONDITION) + +#define hif_mib_list_enum _hif_mib_list + +#undef hif_mib_name +#define hif_mib_name(mib) TRACE_DEFINE_ENUM(HIF_MIB_ID_##mib); +hif_mib_list_enum +#undef hif_mib_name +#define hif_mib_name(mib) { HIF_MIB_ID_##mib, #mib }, +#define hif_mib_list hif_mib_list_enum { -1, NULL } + +DECLARE_EVENT_CLASS(hif_data, + TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), + TP_ARGS(hif, tx_fill_level, is_recv), + TP_STRUCT__entry( + __field(int, tx_fill_level) + __field(int, msg_id) + __field(const char *, msg_type) + __field(int, msg_len) + __field(int, buf_len) + __field(int, if_id) + __field(int, mib) + __array(u8, buf, 128) + ), + TP_fast_assign( + int header_len; + + __entry->tx_fill_level = tx_fill_level; + __entry->msg_len = le16_to_cpu(hif->len); + __entry->msg_id = hif->id; + __entry->if_id = hif->interface; + if (is_recv) + __entry->msg_type = __entry->msg_id & 0x80 ? "IND" : "CNF"; + else + __entry->msg_type = "REQ"; + if (!is_recv && + (__entry->msg_id == HIF_REQ_ID_READ_MIB || + __entry->msg_id == HIF_REQ_ID_WRITE_MIB)) { + __entry->mib = le16_to_cpup((__le16 *)hif->body); + header_len = 4; + } else { + __entry->mib = -1; + header_len = 0; + } + __entry->buf_len = min_t(int, __entry->msg_len, + sizeof(__entry->buf)) + - sizeof(struct hif_msg) - header_len; + memcpy(__entry->buf, hif->body + header_len, __entry->buf_len); + ), + TP_printk("%d:%d:%s_%s%s%s: %s%s (%d bytes)", + __entry->tx_fill_level, + __entry->if_id, + __entry->msg_type, + __print_symbolic(__entry->msg_id, hif_msg_list), + __entry->mib != -1 ? "/" : "", + __entry->mib != -1 ? __print_symbolic(__entry->mib, hif_mib_list) : "", + __print_hex(__entry->buf, __entry->buf_len), + __entry->msg_len > sizeof(__entry->buf) ? " ..." : "", + __entry->msg_len + ) +); +DEFINE_EVENT(hif_data, hif_send, + TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), + TP_ARGS(hif, tx_fill_level, is_recv)); +#define _trace_hif_send(hif, tx_fill_level)\ + trace_hif_send(hif, tx_fill_level, false) +DEFINE_EVENT(hif_data, hif_recv, + TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), + TP_ARGS(hif, tx_fill_level, is_recv)); +#define _trace_hif_recv(hif, tx_fill_level)\ + trace_hif_recv(hif, tx_fill_level, true) + +#define wfx_reg_list_enum \ + wfx_reg_name(WFX_REG_CONFIG, "CONFIG") \ + wfx_reg_name(WFX_REG_CONTROL, "CONTROL") \ + wfx_reg_name(WFX_REG_IN_OUT_QUEUE, "QUEUE") \ + wfx_reg_name(WFX_REG_AHB_DPORT, "AHB") \ + wfx_reg_name(WFX_REG_BASE_ADDR, "BASE_ADDR") \ + wfx_reg_name(WFX_REG_SRAM_DPORT, "SRAM") \ + wfx_reg_name(WFX_REG_SET_GEN_R_W, "SET_GEN_R_W") \ + wfx_reg_name(WFX_REG_FRAME_OUT, "FRAME_OUT") + +#undef wfx_reg_name +#define wfx_reg_name(sym, name) TRACE_DEFINE_ENUM(sym); +wfx_reg_list_enum +#undef wfx_reg_name +#define wfx_reg_name(sym, name) { sym, name }, +#define wfx_reg_list wfx_reg_list_enum { -1, NULL } + +DECLARE_EVENT_CLASS(io_data, + TP_PROTO(int reg, int addr, const void *io_buf, size_t len), + TP_ARGS(reg, addr, io_buf, len), + TP_STRUCT__entry( + __field(int, reg) + __field(int, addr) + __field(int, msg_len) + __field(int, buf_len) + __array(u8, buf, 32) + __array(u8, addr_str, 10) + ), + TP_fast_assign( + __entry->reg = reg; + __entry->addr = addr; + __entry->msg_len = len; + __entry->buf_len = min_t(int, sizeof(__entry->buf), + __entry->msg_len); + memcpy(__entry->buf, io_buf, __entry->buf_len); + if (addr >= 0) + snprintf(__entry->addr_str, 10, "/%08x", addr); + else + __entry->addr_str[0] = 0; + ), + TP_printk("%s%s: %s%s (%d bytes)", + __print_symbolic(__entry->reg, wfx_reg_list), + __entry->addr_str, + __print_hex(__entry->buf, __entry->buf_len), + __entry->msg_len > sizeof(__entry->buf) ? " ..." : "", + __entry->msg_len + ) +); +DEFINE_EVENT(io_data, io_write, + TP_PROTO(int reg, int addr, const void *io_buf, size_t len), + TP_ARGS(reg, addr, io_buf, len)); +#define _trace_io_ind_write(reg, addr, io_buf, len)\ + trace_io_write(reg, addr, io_buf, len) +#define _trace_io_write(reg, io_buf, len) trace_io_write(reg, -1, io_buf, len) +DEFINE_EVENT(io_data, io_read, + TP_PROTO(int reg, int addr, const void *io_buf, size_t len), + TP_ARGS(reg, addr, io_buf, len)); +#define _trace_io_ind_read(reg, addr, io_buf, len)\ + trace_io_read(reg, addr, io_buf, len) +#define _trace_io_read(reg, io_buf, len) trace_io_read(reg, -1, io_buf, len) + +DECLARE_EVENT_CLASS(io_data32, + TP_PROTO(int reg, int addr, u32 val), + TP_ARGS(reg, addr, val), + TP_STRUCT__entry( + __field(int, reg) + __field(int, addr) + __field(int, val) + __array(u8, addr_str, 10) + ), + TP_fast_assign( + __entry->reg = reg; + __entry->addr = addr; + __entry->val = val; + if (addr >= 0) + snprintf(__entry->addr_str, 10, "/%08x", addr); + else + __entry->addr_str[0] = 0; + ), + TP_printk("%s%s: %08x", + __print_symbolic(__entry->reg, wfx_reg_list), + __entry->addr_str, + __entry->val + ) +); +DEFINE_EVENT(io_data32, io_write32, + TP_PROTO(int reg, int addr, u32 val), + TP_ARGS(reg, addr, val)); +#define _trace_io_ind_write32(reg, addr, val) trace_io_write32(reg, addr, val) +#define _trace_io_write32(reg, val) trace_io_write32(reg, -1, val) +DEFINE_EVENT(io_data32, io_read32, + TP_PROTO(int reg, int addr, u32 val), + TP_ARGS(reg, addr, val)); +#define _trace_io_ind_read32(reg, addr, val) trace_io_read32(reg, addr, val) +#define _trace_io_read32(reg, val) trace_io_read32(reg, -1, val) + +DECLARE_EVENT_CLASS(piggyback, + TP_PROTO(u32 val, bool ignored), + TP_ARGS(val, ignored), + TP_STRUCT__entry( + __field(int, val) + __field(bool, ignored) + ), + TP_fast_assign( + __entry->val = val; + __entry->ignored = ignored; + ), + TP_printk("CONTROL: %08x%s", + __entry->val, + __entry->ignored ? " (ignored)" : "" + ) +); +DEFINE_EVENT(piggyback, piggyback, + TP_PROTO(u32 val, bool ignored), + TP_ARGS(val, ignored)); +#define _trace_piggyback(val, ignored) trace_piggyback(val, ignored) + +TRACE_EVENT(bh_stats, + TP_PROTO(int ind, int req, int cnf, int busy, bool release), + TP_ARGS(ind, req, cnf, busy, release), + TP_STRUCT__entry( + __field(int, ind) + __field(int, req) + __field(int, cnf) + __field(int, busy) + __field(bool, release) + ), + TP_fast_assign( + __entry->ind = ind; + __entry->req = req; + __entry->cnf = cnf; + __entry->busy = busy; + __entry->release = release; + ), + TP_printk("IND/REQ/CNF:%3d/%3d/%3d, REQ in progress:%3d, WUP: %s", + __entry->ind, + __entry->req, + __entry->cnf, + __entry->busy, + __entry->release ? "release" : "keep" + ) +); +#define _trace_bh_stats(ind, req, cnf, busy, release)\ + trace_bh_stats(ind, req, cnf, busy, release) + +TRACE_EVENT(tx_stats, + TP_PROTO(const struct hif_cnf_tx *tx_cnf, const struct sk_buff *skb, + int delay), + TP_ARGS(tx_cnf, skb, delay), + TP_STRUCT__entry( + __field(int, pkt_id) + __field(int, delay_media) + __field(int, delay_queue) + __field(int, delay_fw) + __field(int, ack_failures) + __field(int, flags) + __array(int, rate, 4) + __array(int, tx_count, 4) + ), + TP_fast_assign( + /* Keep sync with wfx_rates definition in main.c */ + static const int hw_rate[] = { 0, 1, 2, 3, 6, 7, 8, 9, + 10, 11, 12, 13 }; + const struct ieee80211_tx_info *tx_info = + (const struct ieee80211_tx_info *)skb->cb; + const struct ieee80211_tx_rate *rates = tx_info->driver_rates; + int i; + + __entry->pkt_id = tx_cnf->packet_id; + __entry->delay_media = le32_to_cpu(tx_cnf->media_delay); + __entry->delay_queue = le32_to_cpu(tx_cnf->tx_queue_delay); + __entry->delay_fw = delay; + __entry->ack_failures = tx_cnf->ack_failures; + if (!tx_cnf->status || __entry->ack_failures) + __entry->ack_failures += 1; + + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (rates[0].flags & IEEE80211_TX_RC_MCS) + __entry->rate[i] = rates[i].idx; + else + __entry->rate[i] = hw_rate[rates[i].idx]; + __entry->tx_count[i] = rates[i].count; + } + __entry->flags = 0; + if (rates[0].flags & IEEE80211_TX_RC_MCS) + __entry->flags |= 0x01; + if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI) + __entry->flags |= 0x02; + if (rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD) + __entry->flags |= 0x04; + if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) + __entry->flags |= 0x08; + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + __entry->flags |= 0x10; + if (tx_cnf->status) + __entry->flags |= 0x20; + if (tx_cnf->status == HIF_STATUS_TX_FAIL_REQUEUE) + __entry->flags |= 0x40; + ), + TP_printk("packet ID: %08x, rate policy: %s %d|%d %d|%d %d|%d %d|%d -> %d attempt, Delays media/queue/total: %4dus/%4dus/%4dus", + __entry->pkt_id, + __print_flags(__entry->flags, NULL, + { 0x01, "M" }, { 0x02, "S" }, { 0x04, "G" }, + { 0x08, "R" }, { 0x10, "D" }, { 0x20, "F" }, + { 0x40, "Q" }), + __entry->rate[0], + __entry->tx_count[0], + __entry->rate[1], + __entry->tx_count[1], + __entry->rate[2], + __entry->tx_count[2], + __entry->rate[3], + __entry->tx_count[3], + __entry->ack_failures, + __entry->delay_media, + __entry->delay_queue, + __entry->delay_fw + ) +); +#define _trace_tx_stats(tx_cnf, skb, delay) trace_tx_stats(tx_cnf, skb, delay) + +TRACE_EVENT(queues_stats, + TP_PROTO(struct wfx_dev *wdev, const struct wfx_queue *elected_queue), + TP_ARGS(wdev, elected_queue), + TP_STRUCT__entry( + __field(int, vif_id) + __field(int, queue_id) + __array(int, hw, IEEE80211_NUM_ACS * 2) + __array(int, drv, IEEE80211_NUM_ACS * 2) + __array(int, cab, IEEE80211_NUM_ACS * 2) + ), + TP_fast_assign( + const struct wfx_queue *queue; + struct wfx_vif *wvif; + int i, j; + + for (j = 0; j < IEEE80211_NUM_ACS * 2; j++) { + __entry->hw[j] = -1; + __entry->drv[j] = -1; + __entry->cab[j] = -1; + } + __entry->vif_id = -1; + __entry->queue_id = -1; + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + j = wvif->id * IEEE80211_NUM_ACS + i; + WARN_ON(j >= IEEE80211_NUM_ACS * 2); + queue = &wvif->tx_queue[i]; + __entry->hw[j] = atomic_read(&queue->pending_frames); + __entry->drv[j] = skb_queue_len(&queue->normal); + __entry->cab[j] = skb_queue_len(&queue->cab); + if (queue == elected_queue) { + __entry->vif_id = wvif->id; + __entry->queue_id = i; + } + } + } + ), + TP_printk("got skb from %d/%d, pend. hw/norm/cab: [ %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ] [ %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ]", + __entry->vif_id, __entry->queue_id, + __entry->hw[0], __entry->drv[0], __entry->cab[0], + __entry->hw[1], __entry->drv[1], __entry->cab[1], + __entry->hw[2], __entry->drv[2], __entry->cab[2], + __entry->hw[3], __entry->drv[3], __entry->cab[3], + __entry->hw[4], __entry->drv[4], __entry->cab[4], + __entry->hw[5], __entry->drv[5], __entry->cab[5], + __entry->hw[6], __entry->drv[6], __entry->cab[6], + __entry->hw[7], __entry->drv[7], __entry->cab[7] + ) +); + +#endif + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE traces + +#include From patchwork Mon Sep 20 16:11:35 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: 12505921 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=-21.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,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 902D8C433F5 for ; Mon, 20 Sep 2021 16:16:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5928161166 for ; Mon, 20 Sep 2021 16:16:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239325AbhITQRd (ORCPT ); Mon, 20 Sep 2021 12:17:33 -0400 Received: from mail-mw2nam10on2075.outbound.protection.outlook.com ([40.107.94.75]:38624 "EHLO NAM10-MW2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S243115AbhITQPo (ORCPT ); Mon, 20 Sep 2021 12:15:44 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mNRWp37S7O6dqVIjN9sr6OVwH1cN2W+ZU4WVG0wk8hIHTnlARTPkEZqNu8V+f02xha3MRmJHSq2XK1SeW5yk5w4Xrp2h5N8SmqP2mLkziWb8nLeExC3KKzcUnaeUO0K4tDfETfuafMeI42FKILKKhxQ85xeKrUkEF2NYh+Z8ZveDOax9UvIozqDjjXl1XYQoP9eFcODH+LkvXKLIIHnSe74x+mz3OnJ37MeWDjWrLFCGookBd7d7mfBsV7XB7pk0KWzycSNeREZzbj3S0yvh3yHGobDF5mwvwV+X8b3UK4tgc8UP8Ld2gJR+OwZl8mF2JTViMI8h8/CV5GDF8nATng== 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=DNeaguFg3Aqmlb53Xr4mhjs0uC1L1PwS4+F72Sw9Pw4=; b=fqmhW6WxG2NBsI0v0Jdh7LQtBsyR3KF2u/OZBeiX1mwR9EwE9EnxMb14aE25XYLfpDs0Z9tLLQ+E1daBn9MbDnLleVfvH0/4VaRGP/98hC4j14dvNL9D2uc2cxL0UOg7tIulHz2kf9wm0NqHTJ7vTXrsov3qzB3PRSAHz8ovTxpdrZyzAhFfuMebpbWDDGmoNNkCHDrwv9jfBGC3DnzxhS8/L0iAS7020y5DT2pIEDJ/MFk32GRcLl+wJlskse1dyV9QlPB63m68KSH6DrMlJ/UUFsuXhdn+XCDGs2bNOlN3BL1z8du047qyirzAm1w1/rT4XAtRZAxwBpaU6Gyrgg== 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=DNeaguFg3Aqmlb53Xr4mhjs0uC1L1PwS4+F72Sw9Pw4=; b=XYJh4/i6khTuJA4ZGR+VcbOButMQAfFLOU9TGIN4lAXAjXWtKW65diB3Rnrx4j62UPZ/MUUyhfYFXXJnZ8O26QHbT4VscZq+yL0dpJKg08VdaLQVhtsvVC5I44/VgnmlJLCxCXmoCig9O+oJvHlzf3lYikG45QizdhpYJPk6BvA= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:51 +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:51 +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 23/24] wfx: remove from the staging area Date: Mon, 20 Sep 2021 18:11:35 +0200 Message-Id: <20210920161136.2398632-24-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:48 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 362c7202-2435-4300-2547-08d97c517e37 X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5236; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: HuGCKQytQM/ON9tZDcxYZKU+l9nhn9rc7Aiuj91t5CwnGhTbWh/1zwxMOoTS9zUwoXsBtrFLgieLz9BVAWc/jQItiWpOopRs1NR9GxpoFbk7gRi9wGN/HarEj81Lis9ngnMomkORHSowM7O0LuyNZ5O3fSLqD81Eyh9y1JG2C7/KeT8r0FHrqlrOHzU4DrN8TysQPBFk1ayhukckAaCFsiGSXAyJBaXp3gq1nqkzTWF1esu3393ZpF04/IlNa0oHisNwZhShwuThR4xkzGksracAOVMoONNLCoyLiic6E4WNFJN0/oOA0aMSxAf2VoZBdaHp9eeP6tg2lHw2NT2P3duL5NsuWRFP+KOCiLy1vgTvPKV41qE5sUKTBPrp/lx6xWHYfWj/4UPbBGxUWSV2sZgSaeZ/d+DdXXSoDFPp5rmxBHZhVVgMYe9KsTqXGvhzB4yvnAcAtvbDsqepBXYOuMsPxNsrObY4aBiJCpI4C/hZMcfEYW6ymVUknEGRxFOBAcfCbdFCNSbBC3XpQmpP/cJwqWT8gFBIiW1/ooFV80Oh3k+TApLSyUw0qw8/OnQwp+il1tj0ZDsou+C5+Tr1cvU6p775hhHW3FVzgUouRIAjlImx5nbq9oJJBiBmHQ0W0Uf46LZK8pVWjkGkKDP6VF3sn/lHy4eE7vI3JPqriVnfAzN3D8q+o/LYvecMRtspIKUsbdaIklG4tWY9F4mFt/9E9CQDNkLBzhGb4VHIhCI8olAw81FE7LqeNkEyNKX4KwQMiBZQLjw0+XtlkknWbg== 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(66574015)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(30864003)(7416002)(66556008)(966005)(7696005)(316002)(83380400001)(21314003)(579004)(569008)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 0bXINjAQLTZcWtFy4HXI4h1V8j8l7z1Y7SFQ5Zlpz1XDGcf6Lsiz5MdzW8rw6YD/UufhtbmbSSplBLK7pypV+pG/EuoJPrgnjrlEYehUKaiz0qJvAgxRPj2Rx2wEGM98p0OA3FbImhE5NaLYr1TKEWadYoZ1BjcatDpI/0GQ8lDdzCs6XIxfa4wkhshU9slxb9ARO7BFTML0TogsJxH9H61kA8d3Yekzj3ddr4l74+1fVBfMeqVGZnDX/ZU25ptMh0oyi1nJJ3OAwuoEa3cVR+FOM3fRcEmT+Z0fejLSaDAf4zwLKrojARWTA7WFwoXQIcrp8ZtWqo/NkjJcZ3na9r/FsR/K+P/vLpjCCPz/3ujHh4A0Q/FQlUIOaYS9DGzVlBejvPWTYNV8Aph3pqujL+LqYz1fSoBd0Mevq2GP4+wwjdccOzcAPa6CogN/fykAV642k7LiFtyFAUyNkd93WUQsy4VfwF27tyP0+qRlbsveswmNtz2U+Y/qm1I228H/S4L1On1HmxoaRLODnpvFLUuKut8h7QkU5XiRFS6MrerhwdBy3oM9EZoIkMsBwMAnKftWQQ2Za0YgHtvpRSLuCT3GOKHaD0XotsVKz3xaidnbuQBPc6vbeW0ibnHSsBrmc5Z7wXSfT4R541iHEaT1KbTUMsI8th9Crpcb8874uTALNtGeZCTllsIpXzYLVXWPqpRvQSn2ftvjdVixk//VZadvXWES31o1aE3GuJgQ4frPn56cljy1FpM7GvywsVxAqrEdUCQg5XXtkQwzQWdibGsiNvRwQjtNu6CdZ/I4nXQNhtzlS2RDNUZA/R56MTD5 X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 362c7202-2435-4300-2547-08d97c517e37 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:50.8670 (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: xIf6dZSPp1eLw2nWx0S8JGvKsq1cjYIKuBnMK9p/15ctF5kFdpwwz5CrvNNRgWVxiRG311z4QClQxTJJKt2EKQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Jérôme Pouiller Signed-off-by: Jérôme Pouiller --- .../bindings/net/wireless/silabs,wfx.yaml | 125 --- drivers/staging/wfx/Kconfig | 8 - drivers/staging/wfx/Makefile | 25 - drivers/staging/wfx/bh.c | 330 ------- drivers/staging/wfx/bh.h | 33 - drivers/staging/wfx/bus.h | 38 - drivers/staging/wfx/bus_sdio.c | 272 ------ drivers/staging/wfx/bus_spi.c | 271 ------ drivers/staging/wfx/data_rx.c | 94 -- drivers/staging/wfx/data_rx.h | 18 - drivers/staging/wfx/data_tx.c | 596 ------------- drivers/staging/wfx/data_tx.h | 68 -- drivers/staging/wfx/debug.c | 365 -------- drivers/staging/wfx/debug.h | 19 - drivers/staging/wfx/fwio.c | 405 --------- drivers/staging/wfx/fwio.h | 15 - drivers/staging/wfx/hif_api_cmd.h | 555 ------------ drivers/staging/wfx/hif_api_general.h | 262 ------ drivers/staging/wfx/hif_api_mib.h | 346 -------- drivers/staging/wfx/hif_rx.c | 416 --------- drivers/staging/wfx/hif_rx.h | 17 - drivers/staging/wfx/hif_tx.c | 513 ----------- drivers/staging/wfx/hif_tx.h | 60 -- drivers/staging/wfx/hif_tx_mib.c | 324 ------- drivers/staging/wfx/hif_tx_mib.h | 49 - drivers/staging/wfx/hwio.c | 352 -------- drivers/staging/wfx/hwio.h | 75 -- drivers/staging/wfx/key.c | 241 ----- drivers/staging/wfx/key.h | 20 - drivers/staging/wfx/main.c | 506 ----------- drivers/staging/wfx/main.h | 43 - drivers/staging/wfx/queue.c | 307 ------- drivers/staging/wfx/queue.h | 45 - drivers/staging/wfx/scan.c | 149 ---- drivers/staging/wfx/scan.h | 22 - drivers/staging/wfx/sta.c | 834 ------------------ drivers/staging/wfx/sta.h | 73 -- drivers/staging/wfx/traces.h | 501 ----------- drivers/staging/wfx/wfx.h | 164 ---- 39 files changed, 8556 deletions(-) delete mode 100644 drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml delete mode 100644 drivers/staging/wfx/Kconfig delete mode 100644 drivers/staging/wfx/Makefile delete mode 100644 drivers/staging/wfx/bh.c delete mode 100644 drivers/staging/wfx/bh.h delete mode 100644 drivers/staging/wfx/bus.h delete mode 100644 drivers/staging/wfx/bus_sdio.c delete mode 100644 drivers/staging/wfx/bus_spi.c delete mode 100644 drivers/staging/wfx/data_rx.c delete mode 100644 drivers/staging/wfx/data_rx.h delete mode 100644 drivers/staging/wfx/data_tx.c delete mode 100644 drivers/staging/wfx/data_tx.h delete mode 100644 drivers/staging/wfx/debug.c delete mode 100644 drivers/staging/wfx/debug.h delete mode 100644 drivers/staging/wfx/fwio.c delete mode 100644 drivers/staging/wfx/fwio.h delete mode 100644 drivers/staging/wfx/hif_api_cmd.h delete mode 100644 drivers/staging/wfx/hif_api_general.h delete mode 100644 drivers/staging/wfx/hif_api_mib.h delete mode 100644 drivers/staging/wfx/hif_rx.c delete mode 100644 drivers/staging/wfx/hif_rx.h delete mode 100644 drivers/staging/wfx/hif_tx.c delete mode 100644 drivers/staging/wfx/hif_tx.h delete mode 100644 drivers/staging/wfx/hif_tx_mib.c delete mode 100644 drivers/staging/wfx/hif_tx_mib.h delete mode 100644 drivers/staging/wfx/hwio.c delete mode 100644 drivers/staging/wfx/hwio.h delete mode 100644 drivers/staging/wfx/key.c delete mode 100644 drivers/staging/wfx/key.h delete mode 100644 drivers/staging/wfx/main.c delete mode 100644 drivers/staging/wfx/main.h delete mode 100644 drivers/staging/wfx/queue.c delete mode 100644 drivers/staging/wfx/queue.h delete mode 100644 drivers/staging/wfx/scan.c delete mode 100644 drivers/staging/wfx/scan.h delete mode 100644 drivers/staging/wfx/sta.c delete mode 100644 drivers/staging/wfx/sta.h delete mode 100644 drivers/staging/wfx/traces.h delete mode 100644 drivers/staging/wfx/wfx.h diff --git a/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml b/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml deleted file mode 100644 index 510edd12ed19..000000000000 --- a/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml +++ /dev/null @@ -1,125 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -# Copyright (c) 2020, Silicon Laboratories, Inc. -%YAML 1.2 ---- - -$id: http://devicetree.org/schemas/net/wireless/silabs,wfx.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Silicon Labs WFxxx devicetree bindings - -maintainers: - - Jérôme Pouiller - -description: - The WFxxx chip series can be connected via SPI or via SDIO. - - For SDIO':' - - The driver is able to detect a WFxxx chip on SDIO bus by matching its Vendor - ID and Product ID. However, driver will only provide limited features in - this case. Thus declaring WFxxx chip in device tree is recommended (and may - become mandatory in the future). - - In addition, it is recommended to declare a mmc-pwrseq on SDIO host above - WFx. Without it, you may encounter issues with warm boot. The mmc-pwrseq - should be compatible with mmc-pwrseq-simple. Please consult - Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml for more - information. - - For SPI':' - - In add of the properties below, please consult - Documentation/devicetree/bindings/spi/spi-controller.yaml for optional SPI - related properties. - - Note that in add of the properties below, the WFx driver also supports - `mac-address` and `local-mac-address` as described in - Documentation/devicetree/bindings/net/ethernet.txt - -properties: - compatible: - const: silabs,wf200 - reg: - description: - When used on SDIO bus, must be set to 1. When used on SPI bus, it is - the chip select address of the device as defined in the SPI devices - bindings. - maxItems: 1 - spi-max-frequency: - description: (SPI only) Maximum SPI clocking speed of device in Hz. - maxItems: 1 - interrupts: - description: The interrupt line. Triggers IRQ_TYPE_LEVEL_HIGH and - IRQ_TYPE_EDGE_RISING are both supported by the chip and the driver. When - SPI is used, this property is required. When SDIO is used, the "in-band" - interrupt provided by the SDIO bus is used unless an interrupt is defined - in the Device Tree. - maxItems: 1 - reset-gpios: - description: (SPI only) Phandle of gpio that will be used to reset chip - during probe. Without this property, you may encounter issues with warm - boot. (For legacy purpose, the gpio in inverted when compatible == - "silabs,wfx-spi") - - For SDIO, the reset gpio should declared using a mmc-pwrseq. - maxItems: 1 - wakeup-gpios: - description: Phandle of gpio that will be used to wake-up chip. Without this - property, driver will disable most of power saving features. - maxItems: 1 - config-file: - description: Use an alternative file as PDS. Default is `wf200.pds`. Only - necessary for development/debug purpose. - maxItems: 1 - -required: - - compatible - - reg - -examples: - - | - #include - #include - - spi0 { - #address-cells = <1>; - #size-cells = <0>; - - wfx@0 { - compatible = "silabs,wf200"; - pinctrl-names = "default"; - pinctrl-0 = <&wfx_irq &wfx_gpios>; - reg = <0>; - interrupts-extended = <&gpio 16 IRQ_TYPE_EDGE_RISING>; - wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; - spi-max-frequency = <42000000>; - }; - }; - - - | - #include - #include - - wfx_pwrseq: wfx_pwrseq { - compatible = "mmc-pwrseq-simple"; - pinctrl-names = "default"; - pinctrl-0 = <&wfx_reset>; - reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; - }; - - mmc0 { - mmc-pwrseq = <&wfx_pwrseq>; - #address-cells = <1>; - #size-cells = <0>; - - mmc@1 { - compatible = "silabs,wf200"; - pinctrl-names = "default"; - pinctrl-0 = <&wfx_wakeup>; - reg = <1>; - wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; - }; - }; -... diff --git a/drivers/staging/wfx/Kconfig b/drivers/staging/wfx/Kconfig deleted file mode 100644 index 83ee4d0ca8c6..000000000000 --- a/drivers/staging/wfx/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -config WFX - tristate "Silicon Labs wireless chips WF200 and further" - depends on MAC80211 - depends on MMC || !MMC # do not allow WFX=y if MMC=m - depends on (SPI || MMC) - help - This is a driver for Silicons Labs WFxxx series (WF200 and further) - chipsets. This chip can be found on SPI or SDIO buses. diff --git a/drivers/staging/wfx/Makefile b/drivers/staging/wfx/Makefile deleted file mode 100644 index 0e0cc982ceab..000000000000 --- a/drivers/staging/wfx/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -# Necessary for CREATE_TRACE_POINTS -CFLAGS_debug.o = -I$(src) - -wfx-y := \ - bh.o \ - hwio.o \ - fwio.o \ - hif_tx_mib.o \ - hif_tx.o \ - hif_rx.o \ - queue.o \ - data_tx.o \ - data_rx.o \ - scan.o \ - sta.o \ - key.o \ - main.o \ - sta.o \ - debug.o -wfx-$(CONFIG_SPI) += bus_spi.o -wfx-$(subst m,y,$(CONFIG_MMC)) += bus_sdio.o - -obj-$(CONFIG_WFX) += wfx.o diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c deleted file mode 100644 index a0f9d1b53019..000000000000 --- a/drivers/staging/wfx/bh.c +++ /dev/null @@ -1,330 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Interrupt bottom half (BH). - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "bh.h" -#include "wfx.h" -#include "hwio.h" -#include "traces.h" -#include "hif_rx.h" -#include "hif_api_cmd.h" - -static void device_wakeup(struct wfx_dev *wdev) -{ - int max_retry = 3; - - if (!wdev->pdata.gpio_wakeup) - return; - if (gpiod_get_value_cansleep(wdev->pdata.gpio_wakeup) > 0) - return; - - if (wfx_api_older_than(wdev, 1, 4)) { - gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); - if (!completion_done(&wdev->hif.ctrl_ready)) - usleep_range(2000, 2500); - return; - } - for (;;) { - gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); - /* completion.h does not provide any function to wait - * completion without consume it (a kind of - * wait_for_completion_done_timeout()). So we have to emulate - * it. - */ - if (wait_for_completion_timeout(&wdev->hif.ctrl_ready, - msecs_to_jiffies(2))) { - complete(&wdev->hif.ctrl_ready); - return; - } else if (max_retry-- > 0) { - /* Older firmwares have a race in sleep/wake-up process. - * Redo the process is sufficient to unfreeze the - * chip. - */ - dev_err(wdev->dev, "timeout while wake up chip\n"); - gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0); - usleep_range(2000, 2500); - } else { - dev_err(wdev->dev, "max wake-up retries reached\n"); - return; - } - } -} - -static void device_release(struct wfx_dev *wdev) -{ - if (!wdev->pdata.gpio_wakeup) - return; - - gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0); -} - -static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf) -{ - struct sk_buff *skb; - struct hif_msg *hif; - size_t alloc_len; - size_t computed_len; - int release_count; - int piggyback = 0; - - WARN(read_len > round_down(0xFFF, 2) * sizeof(u16), - "%s: request exceed the chip capability", __func__); - - /* Add 2 to take into account piggyback size */ - alloc_len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, read_len + 2); - skb = dev_alloc_skb(alloc_len); - if (!skb) - return -ENOMEM; - - if (wfx_data_read(wdev, skb->data, alloc_len)) - goto err; - - piggyback = le16_to_cpup((__le16 *)(skb->data + alloc_len - 2)); - _trace_piggyback(piggyback, false); - - hif = (struct hif_msg *)skb->data; - WARN(hif->encrypted & 0x3, "encryption is unsupported"); - if (WARN(read_len < sizeof(struct hif_msg), "corrupted read")) - goto err; - computed_len = le16_to_cpu(hif->len); - computed_len = round_up(computed_len, 2); - if (computed_len != read_len) { - dev_err(wdev->dev, "inconsistent message length: %zu != %zu\n", - computed_len, read_len); - print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, 16, 1, - hif, read_len, true); - goto err; - } - - if (!(hif->id & HIF_ID_IS_INDICATION)) { - (*is_cnf)++; - if (hif->id == HIF_CNF_ID_MULTI_TRANSMIT) - release_count = ((struct hif_cnf_multi_transmit *)hif->body)->num_tx_confs; - else - release_count = 1; - WARN(wdev->hif.tx_buffers_used < release_count, "corrupted buffer counter"); - wdev->hif.tx_buffers_used -= release_count; - } - _trace_hif_recv(hif, wdev->hif.tx_buffers_used); - - if (hif->id != HIF_IND_ID_EXCEPTION && hif->id != HIF_IND_ID_ERROR) { - if (hif->seqnum != wdev->hif.rx_seqnum) - dev_warn(wdev->dev, "wrong message sequence: %d != %d\n", - hif->seqnum, wdev->hif.rx_seqnum); - wdev->hif.rx_seqnum = (hif->seqnum + 1) % (HIF_COUNTER_MAX + 1); - } - - skb_put(skb, le16_to_cpu(hif->len)); - /* wfx_handle_rx takes care on SKB livetime */ - wfx_handle_rx(wdev, skb); - if (!wdev->hif.tx_buffers_used) - wake_up(&wdev->hif.tx_buffers_empty); - - return piggyback; - -err: - if (skb) - dev_kfree_skb(skb); - return -EIO; -} - -static int bh_work_rx(struct wfx_dev *wdev, int max_msg, int *num_cnf) -{ - size_t len; - int i; - int ctrl_reg, piggyback; - - piggyback = 0; - for (i = 0; i < max_msg; i++) { - if (piggyback & CTRL_NEXT_LEN_MASK) - ctrl_reg = piggyback; - else if (try_wait_for_completion(&wdev->hif.ctrl_ready)) - ctrl_reg = atomic_xchg(&wdev->hif.ctrl_reg, 0); - else - ctrl_reg = 0; - if (!(ctrl_reg & CTRL_NEXT_LEN_MASK)) - return i; - /* ctrl_reg units are 16bits words */ - len = (ctrl_reg & CTRL_NEXT_LEN_MASK) * 2; - piggyback = rx_helper(wdev, len, num_cnf); - if (piggyback < 0) - return i; - if (!(piggyback & CTRL_WLAN_READY)) - dev_err(wdev->dev, "unexpected piggyback value: ready bit not set: %04x\n", - piggyback); - } - if (piggyback & CTRL_NEXT_LEN_MASK) { - ctrl_reg = atomic_xchg(&wdev->hif.ctrl_reg, piggyback); - complete(&wdev->hif.ctrl_ready); - if (ctrl_reg) - dev_err(wdev->dev, "unexpected IRQ happened: %04x/%04x\n", - ctrl_reg, piggyback); - } - return i; -} - -static void tx_helper(struct wfx_dev *wdev, struct hif_msg *hif) -{ - int ret; - void *data; - bool is_encrypted = false; - size_t len = le16_to_cpu(hif->len); - - WARN(len < sizeof(*hif), "try to send corrupted data"); - - hif->seqnum = wdev->hif.tx_seqnum; - wdev->hif.tx_seqnum = (wdev->hif.tx_seqnum + 1) % (HIF_COUNTER_MAX + 1); - - data = hif; - WARN(len > wdev->hw_caps.size_inp_ch_buf, - "%s: request exceed the chip capability: %zu > %d\n", __func__, - len, wdev->hw_caps.size_inp_ch_buf); - len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, len); - ret = wfx_data_write(wdev, data, len); - if (ret) - goto end; - - wdev->hif.tx_buffers_used++; - _trace_hif_send(hif, wdev->hif.tx_buffers_used); -end: - if (is_encrypted) - kfree(data); -} - -static int bh_work_tx(struct wfx_dev *wdev, int max_msg) -{ - struct hif_msg *hif; - int i; - - for (i = 0; i < max_msg; i++) { - hif = NULL; - if (wdev->hif.tx_buffers_used < wdev->hw_caps.num_inp_ch_bufs) { - if (try_wait_for_completion(&wdev->hif_cmd.ready)) { - WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error"); - hif = wdev->hif_cmd.buf_send; - } else { - hif = wfx_tx_queues_get(wdev); - } - } - if (!hif) - return i; - tx_helper(wdev, hif); - } - return i; -} - -/* In SDIO mode, it is necessary to make an access to a register to acknowledge - * last received message. It could be possible to restrict this acknowledge to - * SDIO mode and only if last operation was rx. - */ -static void ack_sdio_data(struct wfx_dev *wdev) -{ - u32 cfg_reg; - - config_reg_read(wdev, &cfg_reg); - if (cfg_reg & 0xFF) { - dev_warn(wdev->dev, "chip reports errors: %02x\n", - cfg_reg & 0xFF); - config_reg_write_bits(wdev, 0xFF, 0x00); - } -} - -static void bh_work(struct work_struct *work) -{ - struct wfx_dev *wdev = container_of(work, struct wfx_dev, hif.bh); - int stats_req = 0, stats_cnf = 0, stats_ind = 0; - bool release_chip = false, last_op_is_rx = false; - int num_tx, num_rx; - - device_wakeup(wdev); - do { - num_tx = bh_work_tx(wdev, 32); - stats_req += num_tx; - if (num_tx) - last_op_is_rx = false; - num_rx = bh_work_rx(wdev, 32, &stats_cnf); - stats_ind += num_rx; - if (num_rx) - last_op_is_rx = true; - } while (num_rx || num_tx); - stats_ind -= stats_cnf; - - if (last_op_is_rx) - ack_sdio_data(wdev); - if (!wdev->hif.tx_buffers_used && !work_pending(work)) { - device_release(wdev); - release_chip = true; - } - _trace_bh_stats(stats_ind, stats_req, stats_cnf, - wdev->hif.tx_buffers_used, release_chip); -} - -/* An IRQ from chip did occur */ -void wfx_bh_request_rx(struct wfx_dev *wdev) -{ - u32 cur, prev; - - control_reg_read(wdev, &cur); - prev = atomic_xchg(&wdev->hif.ctrl_reg, cur); - complete(&wdev->hif.ctrl_ready); - queue_work(system_highpri_wq, &wdev->hif.bh); - - if (!(cur & CTRL_NEXT_LEN_MASK)) - dev_err(wdev->dev, "unexpected control register value: length field is 0: %04x\n", - cur); - if (prev != 0) - dev_err(wdev->dev, "received IRQ but previous data was not (yet) read: %04x/%04x\n", - prev, cur); -} - -/* Driver want to send data */ -void wfx_bh_request_tx(struct wfx_dev *wdev) -{ - queue_work(system_highpri_wq, &wdev->hif.bh); -} - -/* If IRQ is not available, this function allow to manually poll the control - * register and simulate an IRQ ahen an event happened. - * - * Note that the device has a bug: If an IRQ raise while host read control - * register, the IRQ is lost. So, use this function carefully (only duing - * device initialisation). - */ -void wfx_bh_poll_irq(struct wfx_dev *wdev) -{ - ktime_t now, start; - u32 reg; - - WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ"); - start = ktime_get(); - for (;;) { - control_reg_read(wdev, ®); - now = ktime_get(); - if (reg & 0xFFF) - break; - if (ktime_after(now, ktime_add_ms(start, 1000))) { - dev_err(wdev->dev, "time out while polling control register\n"); - return; - } - udelay(200); - } - wfx_bh_request_rx(wdev); -} - -void wfx_bh_register(struct wfx_dev *wdev) -{ - INIT_WORK(&wdev->hif.bh, bh_work); - init_completion(&wdev->hif.ctrl_ready); - init_waitqueue_head(&wdev->hif.tx_buffers_empty); -} - -void wfx_bh_unregister(struct wfx_dev *wdev) -{ - flush_work(&wdev->hif.bh); -} diff --git a/drivers/staging/wfx/bh.h b/drivers/staging/wfx/bh.h deleted file mode 100644 index 6c121ce4dd3f..000000000000 --- a/drivers/staging/wfx/bh.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Interrupt bottom half (BH). - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_BH_H -#define WFX_BH_H - -#include -#include -#include - -struct wfx_dev; - -struct wfx_hif { - struct work_struct bh; - struct completion ctrl_ready; - wait_queue_head_t tx_buffers_empty; - atomic_t ctrl_reg; - int rx_seqnum; - int tx_seqnum; - int tx_buffers_used; -}; - -void wfx_bh_register(struct wfx_dev *wdev); -void wfx_bh_unregister(struct wfx_dev *wdev); -void wfx_bh_request_rx(struct wfx_dev *wdev); -void wfx_bh_request_tx(struct wfx_dev *wdev); -void wfx_bh_poll_irq(struct wfx_dev *wdev); - -#endif diff --git a/drivers/staging/wfx/bus.h b/drivers/staging/wfx/bus.h deleted file mode 100644 index ca04b3da6204..000000000000 --- a/drivers/staging/wfx/bus.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Common bus abstraction layer. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_BUS_H -#define WFX_BUS_H - -#include -#include - -#define WFX_REG_CONFIG 0x0 -#define WFX_REG_CONTROL 0x1 -#define WFX_REG_IN_OUT_QUEUE 0x2 -#define WFX_REG_AHB_DPORT 0x3 -#define WFX_REG_BASE_ADDR 0x4 -#define WFX_REG_SRAM_DPORT 0x5 -#define WFX_REG_SET_GEN_R_W 0x6 -#define WFX_REG_FRAME_OUT 0x7 - -struct hwbus_ops { - int (*copy_from_io)(void *bus_priv, unsigned int addr, - void *dst, size_t count); - int (*copy_to_io)(void *bus_priv, unsigned int addr, - const void *src, size_t count); - int (*irq_subscribe)(void *bus_priv); - int (*irq_unsubscribe)(void *bus_priv); - void (*lock)(void *bus_priv); - void (*unlock)(void *bus_priv); - size_t (*align_size)(void *bus_priv, size_t size); -}; - -extern struct sdio_driver wfx_sdio_driver; -extern struct spi_driver wfx_spi_driver; - -#endif diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c deleted file mode 100644 index a670176ba06f..000000000000 --- a/drivers/staging/wfx/bus_sdio.c +++ /dev/null @@ -1,272 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * SDIO interface. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include -#include -#include -#include -#include -#include - -#include "bus.h" -#include "wfx.h" -#include "hwio.h" -#include "main.h" -#include "bh.h" - -static const struct wfx_platform_data wfx_sdio_pdata = { - .file_fw = "wfm_wf200", - .file_pds = "wf200.pds", -}; - -struct wfx_sdio_priv { - struct sdio_func *func; - struct wfx_dev *core; - u8 buf_id_tx; - u8 buf_id_rx; - int of_irq; -}; - -static int wfx_sdio_copy_from_io(void *priv, unsigned int reg_id, - void *dst, size_t count) -{ - struct wfx_sdio_priv *bus = priv; - unsigned int sdio_addr = reg_id << 2; - int ret; - - WARN(reg_id > 7, "chip only has 7 registers"); - WARN(((uintptr_t)dst) & 3, "unaligned buffer size"); - WARN(count & 3, "unaligned buffer address"); - - /* Use queue mode buffers */ - if (reg_id == WFX_REG_IN_OUT_QUEUE) - sdio_addr |= (bus->buf_id_rx + 1) << 7; - ret = sdio_memcpy_fromio(bus->func, dst, sdio_addr, count); - if (!ret && reg_id == WFX_REG_IN_OUT_QUEUE) - bus->buf_id_rx = (bus->buf_id_rx + 1) % 4; - - return ret; -} - -static int wfx_sdio_copy_to_io(void *priv, unsigned int reg_id, - const void *src, size_t count) -{ - struct wfx_sdio_priv *bus = priv; - unsigned int sdio_addr = reg_id << 2; - int ret; - - WARN(reg_id > 7, "chip only has 7 registers"); - WARN(((uintptr_t)src) & 3, "unaligned buffer size"); - WARN(count & 3, "unaligned buffer address"); - - /* Use queue mode buffers */ - if (reg_id == WFX_REG_IN_OUT_QUEUE) - sdio_addr |= bus->buf_id_tx << 7; - /* FIXME: discards 'const' qualifier for src */ - ret = sdio_memcpy_toio(bus->func, sdio_addr, (void *)src, count); - if (!ret && reg_id == WFX_REG_IN_OUT_QUEUE) - bus->buf_id_tx = (bus->buf_id_tx + 1) % 32; - - return ret; -} - -static void wfx_sdio_lock(void *priv) -{ - struct wfx_sdio_priv *bus = priv; - - sdio_claim_host(bus->func); -} - -static void wfx_sdio_unlock(void *priv) -{ - struct wfx_sdio_priv *bus = priv; - - sdio_release_host(bus->func); -} - -static void wfx_sdio_irq_handler(struct sdio_func *func) -{ - struct wfx_sdio_priv *bus = sdio_get_drvdata(func); - - wfx_bh_request_rx(bus->core); -} - -static irqreturn_t wfx_sdio_irq_handler_ext(int irq, void *priv) -{ - struct wfx_sdio_priv *bus = priv; - - sdio_claim_host(bus->func); - wfx_bh_request_rx(bus->core); - sdio_release_host(bus->func); - return IRQ_HANDLED; -} - -static int wfx_sdio_irq_subscribe(void *priv) -{ - struct wfx_sdio_priv *bus = priv; - u32 flags; - int ret; - u8 cccr; - - if (!bus->of_irq) { - sdio_claim_host(bus->func); - ret = sdio_claim_irq(bus->func, wfx_sdio_irq_handler); - sdio_release_host(bus->func); - return ret; - } - - flags = irq_get_trigger_type(bus->of_irq); - if (!flags) - flags = IRQF_TRIGGER_HIGH; - flags |= IRQF_ONESHOT; - ret = devm_request_threaded_irq(&bus->func->dev, bus->of_irq, NULL, - wfx_sdio_irq_handler_ext, flags, - "wfx", bus); - if (ret) - return ret; - sdio_claim_host(bus->func); - cccr = sdio_f0_readb(bus->func, SDIO_CCCR_IENx, NULL); - cccr |= BIT(0); - cccr |= BIT(bus->func->num); - sdio_f0_writeb(bus->func, cccr, SDIO_CCCR_IENx, NULL); - sdio_release_host(bus->func); - return 0; -} - -static int wfx_sdio_irq_unsubscribe(void *priv) -{ - struct wfx_sdio_priv *bus = priv; - int ret; - - if (bus->of_irq) - devm_free_irq(&bus->func->dev, bus->of_irq, bus); - sdio_claim_host(bus->func); - ret = sdio_release_irq(bus->func); - sdio_release_host(bus->func); - return ret; -} - -static size_t wfx_sdio_align_size(void *priv, size_t size) -{ - struct wfx_sdio_priv *bus = priv; - - return sdio_align_size(bus->func, size); -} - -static const struct hwbus_ops wfx_sdio_hwbus_ops = { - .copy_from_io = wfx_sdio_copy_from_io, - .copy_to_io = wfx_sdio_copy_to_io, - .irq_subscribe = wfx_sdio_irq_subscribe, - .irq_unsubscribe = wfx_sdio_irq_unsubscribe, - .lock = wfx_sdio_lock, - .unlock = wfx_sdio_unlock, - .align_size = wfx_sdio_align_size, -}; - -static const struct of_device_id wfx_sdio_of_match[] = { - { .compatible = "silabs,wfx-sdio" }, - { .compatible = "silabs,wf200" }, - { }, -}; -MODULE_DEVICE_TABLE(of, wfx_sdio_of_match); - -static int wfx_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - struct device_node *np = func->dev.of_node; - struct wfx_sdio_priv *bus; - int ret; - - if (func->num != 1) { - dev_err(&func->dev, "SDIO function number is %d while it should always be 1 (unsupported chip?)\n", - func->num); - return -ENODEV; - } - - bus = devm_kzalloc(&func->dev, sizeof(*bus), GFP_KERNEL); - if (!bus) - return -ENOMEM; - - if (np) { - if (!of_match_node(wfx_sdio_of_match, np)) { - dev_warn(&func->dev, "no compatible device found in DT\n"); - return -ENODEV; - } - bus->of_irq = irq_of_parse_and_map(np, 0); - } else { - dev_warn(&func->dev, - "device is not declared in DT, features will be limited\n"); - /* FIXME: ignore VID/PID and only rely on device tree */ - // return -ENODEV; - } - - bus->func = func; - sdio_set_drvdata(func, bus); - func->card->quirks |= MMC_QUIRK_LENIENT_FN0 | - MMC_QUIRK_BLKSZ_FOR_BYTE_MODE | - MMC_QUIRK_BROKEN_BYTE_MODE_512; - - sdio_claim_host(func); - ret = sdio_enable_func(func); - /* Block of 64 bytes is more efficient than 512B for frame sizes < 4k */ - sdio_set_block_size(func, 64); - sdio_release_host(func); - if (ret) - goto err0; - - bus->core = wfx_init_common(&func->dev, &wfx_sdio_pdata, - &wfx_sdio_hwbus_ops, bus); - if (!bus->core) { - ret = -EIO; - goto err1; - } - - ret = wfx_probe(bus->core); - if (ret) - goto err1; - - return 0; - -err1: - sdio_claim_host(func); - sdio_disable_func(func); - sdio_release_host(func); -err0: - return ret; -} - -static void wfx_sdio_remove(struct sdio_func *func) -{ - struct wfx_sdio_priv *bus = sdio_get_drvdata(func); - - wfx_release(bus->core); - sdio_claim_host(func); - sdio_disable_func(func); - sdio_release_host(func); -} - -#define SDIO_VENDOR_ID_SILABS 0x0000 -#define SDIO_DEVICE_ID_SILABS_WF200 0x1000 -static const struct sdio_device_id wfx_sdio_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, SDIO_DEVICE_ID_SILABS_WF200) }, - /* FIXME: ignore VID/PID and only rely on device tree */ - // { SDIO_DEVICE(SDIO_ANY_ID, SDIO_ANY_ID) }, - { }, -}; -MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids); - -struct sdio_driver wfx_sdio_driver = { - .name = "wfx-sdio", - .id_table = wfx_sdio_ids, - .probe = wfx_sdio_probe, - .remove = wfx_sdio_remove, - .drv = { - .owner = THIS_MODULE, - .of_match_table = wfx_sdio_of_match, - } -}; diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c deleted file mode 100644 index 55ffcd7c42e2..000000000000 --- a/drivers/staging/wfx/bus_spi.c +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * SPI interface. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2011, Sagrad Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include -#include -#include -#include -#include -#include - -#include "bus.h" -#include "wfx.h" -#include "hwio.h" -#include "main.h" -#include "bh.h" - -#define SET_WRITE 0x7FFF /* usage: and operation */ -#define SET_READ 0x8000 /* usage: or operation */ - -#define WFX_RESET_INVERTED 1 - -static const struct wfx_platform_data wfx_spi_pdata = { - .file_fw = "wfm_wf200", - .file_pds = "wf200.pds", - .use_rising_clk = true, -}; - -struct wfx_spi_priv { - struct spi_device *func; - struct wfx_dev *core; - struct gpio_desc *gpio_reset; - bool need_swab; -}; - -/* The chip reads 16bits of data at time and place them directly into (little - * endian) CPU register. So, the chip expects bytes order to be "B1 B0 B3 B2" - * (while LE is "B0 B1 B2 B3" and BE is "B3 B2 B1 B0") - * - * A little endian host with bits_per_word == 16 should do the right job - * natively. The code below to support big endian host and commonly used SPI - * 8bits. - */ -static int wfx_spi_copy_from_io(void *priv, unsigned int addr, - void *dst, size_t count) -{ - struct wfx_spi_priv *bus = priv; - u16 regaddr = (addr << 12) | (count / 2) | SET_READ; - struct spi_message m; - struct spi_transfer t_addr = { - .tx_buf = ®addr, - .len = sizeof(regaddr), - }; - struct spi_transfer t_msg = { - .rx_buf = dst, - .len = count, - }; - u16 *dst16 = dst; - int ret, i; - - WARN(count % 2, "buffer size must be a multiple of 2"); - - cpu_to_le16s(®addr); - if (bus->need_swab) - swab16s(®addr); - - spi_message_init(&m); - spi_message_add_tail(&t_addr, &m); - spi_message_add_tail(&t_msg, &m); - ret = spi_sync(bus->func, &m); - - if (bus->need_swab && addr == WFX_REG_CONFIG) - for (i = 0; i < count / 2; i++) - swab16s(&dst16[i]); - return ret; -} - -static int wfx_spi_copy_to_io(void *priv, unsigned int addr, - const void *src, size_t count) -{ - struct wfx_spi_priv *bus = priv; - u16 regaddr = (addr << 12) | (count / 2); - /* FIXME: use a bounce buffer */ - u16 *src16 = (void *)src; - int ret, i; - struct spi_message m; - struct spi_transfer t_addr = { - .tx_buf = ®addr, - .len = sizeof(regaddr), - }; - struct spi_transfer t_msg = { - .tx_buf = src, - .len = count, - }; - - WARN(count % 2, "buffer size must be a multiple of 2"); - WARN(regaddr & SET_READ, "bad addr or size overflow"); - - cpu_to_le16s(®addr); - - /* Register address and CONFIG content always use 16bit big endian - * ("BADC" order) - */ - if (bus->need_swab) - swab16s(®addr); - if (bus->need_swab && addr == WFX_REG_CONFIG) - for (i = 0; i < count / 2; i++) - swab16s(&src16[i]); - - spi_message_init(&m); - spi_message_add_tail(&t_addr, &m); - spi_message_add_tail(&t_msg, &m); - ret = spi_sync(bus->func, &m); - - if (bus->need_swab && addr == WFX_REG_CONFIG) - for (i = 0; i < count / 2; i++) - swab16s(&src16[i]); - return ret; -} - -static void wfx_spi_lock(void *priv) -{ -} - -static void wfx_spi_unlock(void *priv) -{ -} - -static irqreturn_t wfx_spi_irq_handler(int irq, void *priv) -{ - struct wfx_spi_priv *bus = priv; - - wfx_bh_request_rx(bus->core); - return IRQ_HANDLED; -} - -static int wfx_spi_irq_subscribe(void *priv) -{ - struct wfx_spi_priv *bus = priv; - u32 flags; - - flags = irq_get_trigger_type(bus->func->irq); - if (!flags) - flags = IRQF_TRIGGER_HIGH; - flags |= IRQF_ONESHOT; - return devm_request_threaded_irq(&bus->func->dev, bus->func->irq, NULL, - wfx_spi_irq_handler, IRQF_ONESHOT, - "wfx", bus); -} - -static int wfx_spi_irq_unsubscribe(void *priv) -{ - struct wfx_spi_priv *bus = priv; - - devm_free_irq(&bus->func->dev, bus->func->irq, bus); - return 0; -} - -static size_t wfx_spi_align_size(void *priv, size_t size) -{ - /* Most of SPI controllers avoid DMA if buffer size is not 32bit aligned - */ - return ALIGN(size, 4); -} - -static const struct hwbus_ops wfx_spi_hwbus_ops = { - .copy_from_io = wfx_spi_copy_from_io, - .copy_to_io = wfx_spi_copy_to_io, - .irq_subscribe = wfx_spi_irq_subscribe, - .irq_unsubscribe = wfx_spi_irq_unsubscribe, - .lock = wfx_spi_lock, - .unlock = wfx_spi_unlock, - .align_size = wfx_spi_align_size, -}; - -static int wfx_spi_probe(struct spi_device *func) -{ - struct wfx_spi_priv *bus; - int ret; - - if (!func->bits_per_word) - func->bits_per_word = 16; - ret = spi_setup(func); - if (ret) - return ret; - /* Trace below is also displayed by spi_setup() if compiled with DEBUG */ - dev_dbg(&func->dev, "SPI params: CS=%d, mode=%d bits/word=%d speed=%d\n", - func->chip_select, func->mode, func->bits_per_word, - func->max_speed_hz); - if (func->bits_per_word != 16 && func->bits_per_word != 8) - dev_warn(&func->dev, "unusual bits/word value: %d\n", - func->bits_per_word); - if (func->max_speed_hz > 50000000) - dev_warn(&func->dev, "%dHz is a very high speed\n", - func->max_speed_hz); - - bus = devm_kzalloc(&func->dev, sizeof(*bus), GFP_KERNEL); - if (!bus) - return -ENOMEM; - bus->func = func; - if (func->bits_per_word == 8 || IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) - bus->need_swab = true; - spi_set_drvdata(func, bus); - - bus->gpio_reset = devm_gpiod_get_optional(&func->dev, "reset", - GPIOD_OUT_LOW); - if (IS_ERR(bus->gpio_reset)) - return PTR_ERR(bus->gpio_reset); - if (!bus->gpio_reset) { - dev_warn(&func->dev, - "gpio reset is not defined, trying to load firmware anyway\n"); - } else { - gpiod_set_consumer_name(bus->gpio_reset, "wfx reset"); - if (spi_get_device_id(func)->driver_data & WFX_RESET_INVERTED) - gpiod_toggle_active_low(bus->gpio_reset); - gpiod_set_value_cansleep(bus->gpio_reset, 1); - usleep_range(100, 150); - gpiod_set_value_cansleep(bus->gpio_reset, 0); - usleep_range(2000, 2500); - } - - bus->core = wfx_init_common(&func->dev, &wfx_spi_pdata, - &wfx_spi_hwbus_ops, bus); - if (!bus->core) - return -EIO; - - return wfx_probe(bus->core); -} - -static int wfx_spi_remove(struct spi_device *func) -{ - struct wfx_spi_priv *bus = spi_get_drvdata(func); - - wfx_release(bus->core); - return 0; -} - -/* For dynamic driver binding, kernel does not use OF to match driver. It only - * use modalias and modalias is a copy of 'compatible' DT node with vendor - * stripped. - */ -static const struct spi_device_id wfx_spi_id[] = { - { "wfx-spi", WFX_RESET_INVERTED }, - { "wf200", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, wfx_spi_id); - -#ifdef CONFIG_OF -static const struct of_device_id wfx_spi_of_match[] = { - { .compatible = "silabs,wfx-spi", .data = (void *)WFX_RESET_INVERTED }, - { .compatible = "silabs,wf200" }, - { }, -}; -MODULE_DEVICE_TABLE(of, wfx_spi_of_match); -#endif - -struct spi_driver wfx_spi_driver = { - .driver = { - .name = "wfx-spi", - .of_match_table = of_match_ptr(wfx_spi_of_match), - }, - .id_table = wfx_spi_id, - .probe = wfx_spi_probe, - .remove = wfx_spi_remove, -}; diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c deleted file mode 100644 index bfc3961b7b89..000000000000 --- a/drivers/staging/wfx/data_rx.c +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Data receiving implementation. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "data_rx.h" -#include "wfx.h" -#include "bh.h" -#include "sta.h" - -static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt) -{ - int params, tid; - - if (wfx_api_older_than(wvif->wdev, 3, 6)) - return; - - switch (mgmt->u.action.u.addba_req.action_code) { - case WLAN_ACTION_ADDBA_REQ: - params = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - ieee80211_start_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); - break; - case WLAN_ACTION_DELBA: - params = le16_to_cpu(mgmt->u.action.u.delba.params); - tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; - ieee80211_stop_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); - break; - } -} - -void wfx_rx_cb(struct wfx_vif *wvif, - const struct hif_ind_rx *arg, struct sk_buff *skb) -{ - struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb); - struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - - memset(hdr, 0, sizeof(*hdr)); - - if (arg->status == HIF_STATUS_RX_FAIL_MIC) - hdr->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_IV_STRIPPED; - else if (arg->status) - goto drop; - - if (skb->len < sizeof(struct ieee80211_pspoll)) { - dev_warn(wvif->wdev->dev, "malformed SDU received\n"); - goto drop; - } - - hdr->band = NL80211_BAND_2GHZ; - hdr->freq = ieee80211_channel_to_frequency(arg->channel_number, - hdr->band); - - if (arg->rxed_rate >= 14) { - hdr->encoding = RX_ENC_HT; - hdr->rate_idx = arg->rxed_rate - 14; - } else if (arg->rxed_rate >= 4) { - hdr->rate_idx = arg->rxed_rate - 2; - } else { - hdr->rate_idx = arg->rxed_rate; - } - - if (!arg->rcpi_rssi) { - hdr->flag |= RX_FLAG_NO_SIGNAL_VAL; - dev_info(wvif->wdev->dev, "received frame without RSSI data\n"); - } - hdr->signal = arg->rcpi_rssi / 2 - 110; - hdr->antenna = 0; - - if (arg->encryp) - hdr->flag |= RX_FLAG_DECRYPTED; - - /* Block ack negotiation is offloaded by the firmware. However, - * re-ordering must be done by the mac80211. - */ - if (ieee80211_is_action(frame->frame_control) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - skb->len > IEEE80211_MIN_ACTION_SIZE) { - wfx_rx_handle_ba(wvif, mgmt); - goto drop; - } - - ieee80211_rx_irqsafe(wvif->wdev->hw, skb); - return; - -drop: - dev_kfree_skb(skb); -} diff --git a/drivers/staging/wfx/data_rx.h b/drivers/staging/wfx/data_rx.h deleted file mode 100644 index 84d0e3c0507b..000000000000 --- a/drivers/staging/wfx/data_rx.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Data receiving implementation. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_DATA_RX_H -#define WFX_DATA_RX_H - -struct wfx_vif; -struct sk_buff; -struct hif_ind_rx; - -void wfx_rx_cb(struct wfx_vif *wvif, - const struct hif_ind_rx *arg, struct sk_buff *skb); - -#endif diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c deleted file mode 100644 index 052a19161dc5..000000000000 --- a/drivers/staging/wfx/data_tx.c +++ /dev/null @@ -1,596 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Data transmitting implementation. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "data_tx.h" -#include "wfx.h" -#include "bh.h" -#include "sta.h" -#include "queue.h" -#include "debug.h" -#include "traces.h" -#include "hif_tx_mib.h" - -static int wfx_get_hw_rate(struct wfx_dev *wdev, - const struct ieee80211_tx_rate *rate) -{ - struct ieee80211_supported_band *band; - - if (rate->idx < 0) - return -1; - if (rate->flags & IEEE80211_TX_RC_MCS) { - if (rate->idx > 7) { - WARN(1, "wrong rate->idx value: %d", rate->idx); - return -1; - } - return rate->idx + 14; - } - /* The device only support 2GHz, else band information should be - * retrieved from ieee80211_tx_info - */ - band = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]; - if (rate->idx >= band->n_bitrates) { - WARN(1, "wrong rate->idx value: %d", rate->idx); - return -1; - } - return band->bitrates[rate->idx].hw_value; -} - -/* TX policy cache implementation */ - -static void wfx_tx_policy_build(struct wfx_vif *wvif, struct tx_policy *policy, - struct ieee80211_tx_rate *rates) -{ - struct wfx_dev *wdev = wvif->wdev; - int i, rateid; - u8 count; - - WARN(rates[0].idx < 0, "invalid rate policy"); - memset(policy, 0, sizeof(*policy)); - for (i = 0; i < IEEE80211_TX_MAX_RATES; ++i) { - if (rates[i].idx < 0) - break; - WARN_ON(rates[i].count > 15); - rateid = wfx_get_hw_rate(wdev, &rates[i]); - /* Pack two values in each byte of policy->rates */ - count = rates[i].count; - if (rateid % 2) - count <<= 4; - policy->rates[rateid / 2] |= count; - } -} - -static bool tx_policy_is_equal(const struct tx_policy *a, - const struct tx_policy *b) -{ - return !memcmp(a->rates, b->rates, sizeof(a->rates)); -} - -static int wfx_tx_policy_find(struct tx_policy_cache *cache, - struct tx_policy *wanted) -{ - struct tx_policy *it; - - list_for_each_entry(it, &cache->used, link) - if (tx_policy_is_equal(wanted, it)) - return it - cache->cache; - list_for_each_entry(it, &cache->free, link) - if (tx_policy_is_equal(wanted, it)) - return it - cache->cache; - return -1; -} - -static void wfx_tx_policy_use(struct tx_policy_cache *cache, - struct tx_policy *entry) -{ - ++entry->usage_count; - list_move(&entry->link, &cache->used); -} - -static int wfx_tx_policy_release(struct tx_policy_cache *cache, - struct tx_policy *entry) -{ - int ret = --entry->usage_count; - - if (!ret) - list_move(&entry->link, &cache->free); - return ret; -} - -static int wfx_tx_policy_get(struct wfx_vif *wvif, - struct ieee80211_tx_rate *rates, bool *renew) -{ - int idx; - struct tx_policy_cache *cache = &wvif->tx_policy_cache; - struct tx_policy wanted; - struct tx_policy *entry; - - wfx_tx_policy_build(wvif, &wanted, rates); - - spin_lock_bh(&cache->lock); - if (list_empty(&cache->free)) { - WARN(1, "unable to get a valid Tx policy"); - spin_unlock_bh(&cache->lock); - return HIF_TX_RETRY_POLICY_INVALID; - } - idx = wfx_tx_policy_find(cache, &wanted); - if (idx >= 0) { - *renew = false; - } else { - /* If policy is not found create a new one using the oldest - * entry in "free" list - */ - *renew = true; - entry = list_entry(cache->free.prev, struct tx_policy, link); - memcpy(entry->rates, wanted.rates, sizeof(entry->rates)); - entry->uploaded = false; - entry->usage_count = 0; - idx = entry - cache->cache; - } - wfx_tx_policy_use(cache, &cache->cache[idx]); - if (list_empty(&cache->free)) - ieee80211_stop_queues(wvif->wdev->hw); - spin_unlock_bh(&cache->lock); - return idx; -} - -static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx) -{ - int usage, locked; - struct tx_policy_cache *cache = &wvif->tx_policy_cache; - - if (idx == HIF_TX_RETRY_POLICY_INVALID) - return; - spin_lock_bh(&cache->lock); - locked = list_empty(&cache->free); - usage = wfx_tx_policy_release(cache, &cache->cache[idx]); - if (locked && !usage) - ieee80211_wake_queues(wvif->wdev->hw); - spin_unlock_bh(&cache->lock); -} - -static int wfx_tx_policy_upload(struct wfx_vif *wvif) -{ - struct tx_policy *policies = wvif->tx_policy_cache.cache; - u8 tmp_rates[12]; - int i, is_used; - - do { - spin_lock_bh(&wvif->tx_policy_cache.lock); - for (i = 0; i < ARRAY_SIZE(wvif->tx_policy_cache.cache); ++i) { - is_used = memzcmp(policies[i].rates, - sizeof(policies[i].rates)); - if (!policies[i].uploaded && is_used) - break; - } - if (i < ARRAY_SIZE(wvif->tx_policy_cache.cache)) { - policies[i].uploaded = true; - memcpy(tmp_rates, policies[i].rates, sizeof(tmp_rates)); - spin_unlock_bh(&wvif->tx_policy_cache.lock); - hif_set_tx_rate_retry_policy(wvif, i, tmp_rates); - } else { - spin_unlock_bh(&wvif->tx_policy_cache.lock); - } - } while (i < ARRAY_SIZE(wvif->tx_policy_cache.cache)); - return 0; -} - -void wfx_tx_policy_upload_work(struct work_struct *work) -{ - struct wfx_vif *wvif = - container_of(work, struct wfx_vif, tx_policy_upload_work); - - wfx_tx_policy_upload(wvif); - wfx_tx_unlock(wvif->wdev); -} - -void wfx_tx_policy_init(struct wfx_vif *wvif) -{ - struct tx_policy_cache *cache = &wvif->tx_policy_cache; - int i; - - memset(cache, 0, sizeof(*cache)); - - spin_lock_init(&cache->lock); - INIT_LIST_HEAD(&cache->used); - INIT_LIST_HEAD(&cache->free); - - for (i = 0; i < ARRAY_SIZE(cache->cache); ++i) - list_add(&cache->cache[i].link, &cache->free); -} - -/* Tx implementation */ - -static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr; - - if (!ieee80211_is_action(mgmt->frame_control)) - return false; - if (mgmt->u.action.category != WLAN_CATEGORY_BACK) - return false; - return true; -} - -static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, - struct ieee80211_hdr *hdr) -{ - struct wfx_sta_priv *sta_priv = - sta ? (struct wfx_sta_priv *)&sta->drv_priv : NULL; - const u8 *da = ieee80211_get_DA(hdr); - - if (sta_priv && sta_priv->link_id) - return sta_priv->link_id; - if (wvif->vif->type != NL80211_IFTYPE_AP) - return 0; - if (is_multicast_ether_addr(da)) - return 0; - return HIF_LINK_ID_NOT_ASSOCIATED; -} - -static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) -{ - int i; - bool finished; - - /* Firmware is not able to mix rates with different flags */ - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI) - rates[i].flags |= IEEE80211_TX_RC_SHORT_GI; - if (!(rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) - rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; - if (!(rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)) - rates[i].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; - } - - /* Sort rates and remove duplicates */ - do { - finished = true; - for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) { - if (rates[i + 1].idx == rates[i].idx && - rates[i].idx != -1) { - rates[i].count += rates[i + 1].count; - if (rates[i].count > 15) - rates[i].count = 15; - rates[i + 1].idx = -1; - rates[i + 1].count = 0; - - finished = false; - } - if (rates[i + 1].idx > rates[i].idx) { - swap(rates[i + 1], rates[i]); - finished = false; - } - } - } while (!finished); - /* Ensure that MCS0 or 1Mbps is present at the end of the retry list */ - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (rates[i].idx == 0) - break; - if (rates[i].idx == -1) { - rates[i].idx = 0; - rates[i].count = 8; /* == hw->max_rate_tries */ - rates[i].flags = rates[i - 1].flags & - IEEE80211_TX_RC_MCS; - break; - } - } - /* All retries use long GI */ - for (i = 1; i < IEEE80211_TX_MAX_RATES; i++) - rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; -} - -static u8 wfx_tx_get_retry_policy_id(struct wfx_vif *wvif, - struct ieee80211_tx_info *tx_info) -{ - bool tx_policy_renew = false; - u8 ret; - - ret = wfx_tx_policy_get(wvif, tx_info->driver_rates, &tx_policy_renew); - if (ret == HIF_TX_RETRY_POLICY_INVALID) - dev_warn(wvif->wdev->dev, "unable to get a valid Tx policy"); - - if (tx_policy_renew) { - wfx_tx_lock(wvif->wdev); - if (!schedule_work(&wvif->tx_policy_upload_work)) - wfx_tx_unlock(wvif->wdev); - } - return ret; -} - -static int wfx_tx_get_frame_format(struct ieee80211_tx_info *tx_info) -{ - if (!(tx_info->driver_rates[0].flags & IEEE80211_TX_RC_MCS)) - return HIF_FRAME_FORMAT_NON_HT; - else if (!(tx_info->driver_rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) - return HIF_FRAME_FORMAT_MIXED_FORMAT_HT; - else - return HIF_FRAME_FORMAT_GF_HT_11N; -} - -static int wfx_tx_get_icv_len(struct ieee80211_key_conf *hw_key) -{ - int mic_space; - - if (!hw_key) - return 0; - if (hw_key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) - return 0; - mic_space = (hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) ? 8 : 0; - return hw_key->icv_len + mic_space; -} - -static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, - struct sk_buff *skb) -{ - struct hif_msg *hif_msg; - struct hif_req_tx *req; - struct wfx_tx_priv *tx_priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int queue_id = skb_get_queue_mapping(skb); - size_t offset = (size_t)skb->data & 3; - int wmsg_len = sizeof(struct hif_msg) + - sizeof(struct hif_req_tx) + offset; - - WARN(queue_id >= IEEE80211_NUM_ACS, "unsupported queue_id"); - wfx_tx_fixup_rates(tx_info->driver_rates); - - /* From now tx_info->control is unusable */ - memset(tx_info->rate_driver_data, 0, sizeof(struct wfx_tx_priv)); - /* Fill tx_priv */ - tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data; - tx_priv->icv_size = wfx_tx_get_icv_len(hw_key); - - /* Fill hif_msg */ - WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb"); - WARN(offset & 1, "attempt to transmit an unaligned frame"); - skb_put(skb, tx_priv->icv_size); - skb_push(skb, wmsg_len); - memset(skb->data, 0, wmsg_len); - hif_msg = (struct hif_msg *)skb->data; - hif_msg->len = cpu_to_le16(skb->len); - hif_msg->id = HIF_REQ_ID_TX; - hif_msg->interface = wvif->id; - if (skb->len > wvif->wdev->hw_caps.size_inp_ch_buf) { - dev_warn(wvif->wdev->dev, - "requested frame size (%d) is larger than maximum supported (%d)\n", - skb->len, wvif->wdev->hw_caps.size_inp_ch_buf); - skb_pull(skb, wmsg_len); - return -EIO; - } - - /* Fill tx request */ - req = (struct hif_req_tx *)hif_msg->body; - /* packet_id just need to be unique on device. 32bits are more than - * necessary for that task, so we tae advantage of it to add some extra - * data for debug. - */ - req->packet_id = atomic_add_return(1, &wvif->wdev->packet_id) & 0xFFFF; - req->packet_id |= IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)) << 16; - req->packet_id |= queue_id << 28; - - req->fc_offset = offset; - /* Queue index are inverted between firmware and Linux */ - req->queue_id = 3 - queue_id; - req->peer_sta_id = wfx_tx_get_link_id(wvif, sta, hdr); - req->retry_policy_index = wfx_tx_get_retry_policy_id(wvif, tx_info); - req->frame_format = wfx_tx_get_frame_format(tx_info); - if (tx_info->driver_rates[0].flags & IEEE80211_TX_RC_SHORT_GI) - req->short_gi = 1; - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) - req->after_dtim = 1; - - /* Auxiliary operations */ - wfx_tx_queues_put(wvif, skb); - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) - schedule_work(&wvif->update_tim_work); - wfx_bh_request_tx(wvif->wdev); - return 0; -} - -void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif; - struct ieee80211_sta *sta = control ? control->sta : NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - size_t driver_data_room = sizeof_field(struct ieee80211_tx_info, - rate_driver_data); - - compiletime_assert(sizeof(struct wfx_tx_priv) <= driver_data_room, - "struct tx_priv is too large"); - WARN(skb->next || skb->prev, "skb is already member of a list"); - /* control.vif can be NULL for injected frames */ - if (tx_info->control.vif) - wvif = (struct wfx_vif *)tx_info->control.vif->drv_priv; - else - wvif = wvif_iterate(wdev, NULL); - if (WARN_ON(!wvif)) - goto drop; - /* Because of TX_AMPDU_SETUP_IN_HW, mac80211 does not try to send any - * BlockAck session management frame. The check below exist just in case. - */ - if (ieee80211_is_action_back(hdr)) { - dev_info(wdev->dev, "drop BA action\n"); - goto drop; - } - if (wfx_tx_inner(wvif, sta, skb)) - goto drop; - - return; - -drop: - ieee80211_tx_status_irqsafe(wdev->hw, skb); -} - -static void wfx_skb_dtor(struct wfx_vif *wvif, struct sk_buff *skb) -{ - struct hif_msg *hif = (struct hif_msg *)skb->data; - struct hif_req_tx *req = (struct hif_req_tx *)hif->body; - unsigned int offset = sizeof(struct hif_msg) + - sizeof(struct hif_req_tx) + - req->fc_offset; - - if (!wvif) { - pr_warn("%s: vif associated with the skb does not exist anymore\n", __func__); - return; - } - wfx_tx_policy_put(wvif, req->retry_policy_index); - skb_pull(skb, offset); - ieee80211_tx_status_irqsafe(wvif->wdev->hw, skb); -} - -static void wfx_tx_fill_rates(struct wfx_dev *wdev, - struct ieee80211_tx_info *tx_info, - const struct hif_cnf_tx *arg) -{ - struct ieee80211_tx_rate *rate; - int tx_count; - int i; - - tx_count = arg->ack_failures; - if (!arg->status || arg->ack_failures) - tx_count += 1; /* Also report success */ - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - rate = &tx_info->status.rates[i]; - if (rate->idx < 0) - break; - if (tx_count < rate->count && - arg->status == HIF_STATUS_TX_FAIL_RETRIES && - arg->ack_failures) - dev_dbg(wdev->dev, "all retries were not consumed: %d != %d\n", - rate->count, tx_count); - if (tx_count <= rate->count && tx_count && - arg->txed_rate != wfx_get_hw_rate(wdev, rate)) - dev_dbg(wdev->dev, "inconsistent tx_info rates: %d != %d\n", - arg->txed_rate, wfx_get_hw_rate(wdev, rate)); - if (tx_count > rate->count) { - tx_count -= rate->count; - } else if (!tx_count) { - rate->count = 0; - rate->idx = -1; - } else { - rate->count = tx_count; - tx_count = 0; - } - } - if (tx_count) - dev_dbg(wdev->dev, "%d more retries than expected\n", tx_count); -} - -void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) -{ - const struct wfx_tx_priv *tx_priv; - struct ieee80211_tx_info *tx_info; - struct wfx_vif *wvif; - struct sk_buff *skb; - - skb = wfx_pending_get(wdev, arg->packet_id); - if (!skb) { - dev_warn(wdev->dev, "received unknown packet_id (%#.8x) from chip\n", - arg->packet_id); - return; - } - tx_info = IEEE80211_SKB_CB(skb); - tx_priv = wfx_skb_tx_priv(skb); - wvif = wdev_to_wvif(wdev, ((struct hif_msg *)skb->data)->interface); - WARN_ON(!wvif); - if (!wvif) - return; - - /* Note that wfx_pending_get_pkt_us_delay() get data from tx_info */ - _trace_tx_stats(arg, skb, wfx_pending_get_pkt_us_delay(wdev, skb)); - wfx_tx_fill_rates(wdev, tx_info, arg); - skb_trim(skb, skb->len - tx_priv->icv_size); - - /* From now, you can touch to tx_info->status, but do not touch to - * tx_priv anymore - */ - /* FIXME: use ieee80211_tx_info_clear_status() */ - memset(tx_info->rate_driver_data, 0, sizeof(tx_info->rate_driver_data)); - memset(tx_info->pad, 0, sizeof(tx_info->pad)); - - if (!arg->status) { - tx_info->status.tx_time = - le32_to_cpu(arg->media_delay) - - le32_to_cpu(arg->tx_queue_delay); - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) - tx_info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; - else - tx_info->flags |= IEEE80211_TX_STAT_ACK; - } else if (arg->status == HIF_STATUS_TX_FAIL_REQUEUE) { - WARN(!arg->requeue, "incoherent status and result_flags"); - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - wvif->after_dtim_tx_allowed = false; /* DTIM period elapsed */ - schedule_work(&wvif->update_tim_work); - } - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - } - wfx_skb_dtor(wvif, skb); -} - -static void wfx_flush_vif(struct wfx_vif *wvif, u32 queues, - struct sk_buff_head *dropped) -{ - struct wfx_queue *queue; - int i; - - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - if (!(BIT(i) & queues)) - continue; - queue = &wvif->tx_queue[i]; - if (dropped) - wfx_tx_queue_drop(wvif, queue, dropped); - } - if (wvif->wdev->chip_frozen) - return; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - if (!(BIT(i) & queues)) - continue; - queue = &wvif->tx_queue[i]; - if (wait_event_timeout(wvif->wdev->tx_dequeue, - wfx_tx_queue_empty(wvif, queue), - msecs_to_jiffies(1000)) <= 0) - dev_warn(wvif->wdev->dev, - "frames queued while flushing tx queues?"); - } -} - -void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop) -{ - struct wfx_dev *wdev = hw->priv; - struct sk_buff_head dropped; - struct wfx_vif *wvif; - struct hif_msg *hif; - struct sk_buff *skb; - - skb_queue_head_init(&dropped); - if (vif) { - wvif = (struct wfx_vif *)vif->drv_priv; - wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); - } else { - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); - } - wfx_tx_flush(wdev); - if (wdev->chip_frozen) - wfx_pending_drop(wdev, &dropped); - while ((skb = skb_dequeue(&dropped)) != NULL) { - hif = (struct hif_msg *)skb->data; - wvif = wdev_to_wvif(wdev, hif->interface); - ieee80211_tx_info_clear_status(IEEE80211_SKB_CB(skb)); - wfx_skb_dtor(wvif, skb); - } -} diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h deleted file mode 100644 index 15590a8faefe..000000000000 --- a/drivers/staging/wfx/data_tx.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Data transmitting implementation. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_DATA_TX_H -#define WFX_DATA_TX_H - -#include -#include - -#include "hif_api_cmd.h" -#include "hif_api_mib.h" - -struct wfx_tx_priv; -struct wfx_dev; -struct wfx_vif; - -struct tx_policy { - struct list_head link; - int usage_count; - u8 rates[12]; - bool uploaded; -}; - -struct tx_policy_cache { - struct tx_policy cache[HIF_TX_RETRY_POLICY_MAX]; - /* FIXME: use a trees and drop hash from tx_policy */ - struct list_head used; - struct list_head free; - spinlock_t lock; -}; - -struct wfx_tx_priv { - ktime_t xmit_timestamp; - unsigned char icv_size; -}; - -void wfx_tx_policy_init(struct wfx_vif *wvif); -void wfx_tx_policy_upload_work(struct work_struct *work); - -void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb); -void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg); -void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop); - -static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info; - - if (!skb) - return NULL; - tx_info = IEEE80211_SKB_CB(skb); - return (struct wfx_tx_priv *)tx_info->rate_driver_data; -} - -static inline struct hif_req_tx *wfx_skb_txreq(struct sk_buff *skb) -{ - struct hif_msg *hif = (struct hif_msg *)skb->data; - struct hif_req_tx *req = (struct hif_req_tx *)hif->body; - - return req; -} - -#endif diff --git a/drivers/staging/wfx/debug.c b/drivers/staging/wfx/debug.c deleted file mode 100644 index 9f93268a3202..000000000000 --- a/drivers/staging/wfx/debug.c +++ /dev/null @@ -1,365 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Debugfs interface. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include -#include - -#include "debug.h" -#include "wfx.h" -#include "sta.h" -#include "main.h" -#include "hif_tx.h" -#include "hif_tx_mib.h" - -#define CREATE_TRACE_POINTS -#include "traces.h" - -static const struct trace_print_flags hif_msg_print_map[] = { - hif_msg_list, -}; - -static const struct trace_print_flags hif_mib_print_map[] = { - hif_mib_list, -}; - -static const struct trace_print_flags wfx_reg_print_map[] = { - wfx_reg_list, -}; - -static const char *get_symbol(unsigned long val, - const struct trace_print_flags *symbol_array) -{ - int i; - - for (i = 0; symbol_array[i].mask != -1; i++) { - if (val == symbol_array[i].mask) - return symbol_array[i].name; - } - - return "unknown"; -} - -const char *get_hif_name(unsigned long id) -{ - return get_symbol(id, hif_msg_print_map); -} - -const char *get_mib_name(unsigned long id) -{ - return get_symbol(id, hif_mib_print_map); -} - -const char *get_reg_name(unsigned long id) -{ - return get_symbol(id, wfx_reg_print_map); -} - -static int wfx_counters_show(struct seq_file *seq, void *v) -{ - int ret, i; - struct wfx_dev *wdev = seq->private; - struct hif_mib_extended_count_table counters[3]; - - for (i = 0; i < ARRAY_SIZE(counters); i++) { - ret = hif_get_counters_table(wdev, i, counters + i); - if (ret < 0) - return ret; - if (ret > 0) - return -EIO; - } - - seq_printf(seq, "%-24s %12s %12s %12s\n", - "", "global", "iface 0", "iface 1"); - -#define PUT_COUNTER(name) \ - seq_printf(seq, "%-24s %12d %12d %12d\n", #name, \ - le32_to_cpu(counters[2].count_##name), \ - le32_to_cpu(counters[0].count_##name), \ - le32_to_cpu(counters[1].count_##name)) - - PUT_COUNTER(tx_frames); - PUT_COUNTER(tx_frames_multicast); - PUT_COUNTER(tx_frames_success); - PUT_COUNTER(tx_frames_retried); - PUT_COUNTER(tx_frames_multi_retried); - PUT_COUNTER(tx_frames_failed); - - PUT_COUNTER(ack_failed); - PUT_COUNTER(rts_success); - PUT_COUNTER(rts_failed); - - PUT_COUNTER(rx_frames); - PUT_COUNTER(rx_frames_multicast); - PUT_COUNTER(rx_frames_success); - PUT_COUNTER(rx_frames_failed); - PUT_COUNTER(drop_plcp); - PUT_COUNTER(drop_fcs); - PUT_COUNTER(drop_no_key); - PUT_COUNTER(drop_decryption); - PUT_COUNTER(drop_tkip_mic); - PUT_COUNTER(drop_bip_mic); - PUT_COUNTER(drop_cmac_icv); - PUT_COUNTER(drop_cmac_replay); - PUT_COUNTER(drop_ccmp_replay); - PUT_COUNTER(drop_duplicate); - - PUT_COUNTER(rx_bcn_miss); - PUT_COUNTER(rx_bcn_success); - PUT_COUNTER(rx_bcn_dtim); - PUT_COUNTER(rx_bcn_dtim_aid0_clr); - PUT_COUNTER(rx_bcn_dtim_aid0_set); - -#undef PUT_COUNTER - - for (i = 0; i < ARRAY_SIZE(counters[0].reserved); i++) - seq_printf(seq, "reserved[%02d]%12s %12d %12d %12d\n", i, "", - le32_to_cpu(counters[2].reserved[i]), - le32_to_cpu(counters[0].reserved[i]), - le32_to_cpu(counters[1].reserved[i])); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(wfx_counters); - -static const char * const channel_names[] = { - [0] = "1M", - [1] = "2M", - [2] = "5.5M", - [3] = "11M", - /* Entries 4 and 5 does not exist */ - [6] = "6M", - [7] = "9M", - [8] = "12M", - [9] = "18M", - [10] = "24M", - [11] = "36M", - [12] = "48M", - [13] = "54M", - [14] = "MCS0", - [15] = "MCS1", - [16] = "MCS2", - [17] = "MCS3", - [18] = "MCS4", - [19] = "MCS5", - [20] = "MCS6", - [21] = "MCS7", -}; - -static int wfx_rx_stats_show(struct seq_file *seq, void *v) -{ - struct wfx_dev *wdev = seq->private; - struct hif_rx_stats *st = &wdev->rx_stats; - int i; - - mutex_lock(&wdev->rx_stats_lock); - seq_printf(seq, "Timestamp: %dus\n", st->date); - seq_printf(seq, "Low power clock: frequency %uHz, external %s\n", - le32_to_cpu(st->pwr_clk_freq), - st->is_ext_pwr_clk ? "yes" : "no"); - seq_printf(seq, - "Num. of frames: %d, PER (x10e4): %d, Throughput: %dKbps/s\n", - st->nb_rx_frame, st->per_total, st->throughput); - seq_puts(seq, " Num. of PER RSSI SNR CFO\n"); - seq_puts(seq, " frames (x10e4) (dBm) (dB) (kHz)\n"); - for (i = 0; i < ARRAY_SIZE(channel_names); i++) { - if (channel_names[i]) - seq_printf(seq, "%5s %8d %8d %8d %8d %8d\n", - channel_names[i], - le32_to_cpu(st->nb_rx_by_rate[i]), - le16_to_cpu(st->per[i]), - (s16)le16_to_cpu(st->rssi[i]) / 100, - (s16)le16_to_cpu(st->snr[i]) / 100, - (s16)le16_to_cpu(st->cfo[i])); - } - mutex_unlock(&wdev->rx_stats_lock); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(wfx_rx_stats); - -static int wfx_tx_power_loop_show(struct seq_file *seq, void *v) -{ - struct wfx_dev *wdev = seq->private; - struct hif_tx_power_loop_info *st = &wdev->tx_power_loop_info; - int tmp; - - mutex_lock(&wdev->tx_power_loop_info_lock); - tmp = le16_to_cpu(st->tx_gain_dig); - seq_printf(seq, "Tx gain digital: %d\n", tmp); - tmp = le16_to_cpu(st->tx_gain_pa); - seq_printf(seq, "Tx gain PA: %d\n", tmp); - tmp = (s16)le16_to_cpu(st->target_pout); - seq_printf(seq, "Target Pout: %d.%02d dBm\n", tmp / 4, (tmp % 4) * 25); - tmp = (s16)le16_to_cpu(st->p_estimation); - seq_printf(seq, "FEM Pout: %d.%02d dBm\n", tmp / 4, (tmp % 4) * 25); - tmp = le16_to_cpu(st->vpdet); - seq_printf(seq, "Vpdet: %d mV\n", tmp); - seq_printf(seq, "Measure index: %d\n", st->measurement_index); - mutex_unlock(&wdev->tx_power_loop_info_lock); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(wfx_tx_power_loop); - -static ssize_t wfx_send_pds_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wfx_dev *wdev = file->private_data; - char *buf; - int ret; - - if (*ppos != 0) { - dev_dbg(wdev->dev, "PDS data must be written in one transaction"); - return -EBUSY; - } - buf = memdup_user(user_buf, count); - if (IS_ERR(buf)) - return PTR_ERR(buf); - *ppos = *ppos + count; - ret = wfx_send_pds(wdev, buf, count); - kfree(buf); - if (ret < 0) - return ret; - return count; -} - -static const struct file_operations wfx_send_pds_fops = { - .open = simple_open, - .write = wfx_send_pds_write, -}; - -struct dbgfs_hif_msg { - struct wfx_dev *wdev; - struct completion complete; - u8 reply[1024]; - int ret; -}; - -static ssize_t wfx_send_hif_msg_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct dbgfs_hif_msg *context = file->private_data; - struct wfx_dev *wdev = context->wdev; - struct hif_msg *request; - - if (completion_done(&context->complete)) { - dev_dbg(wdev->dev, "read previous result before start a new one\n"); - return -EBUSY; - } - if (count < sizeof(struct hif_msg)) - return -EINVAL; - - /* wfx_cmd_send() checks that reply buffer is wide enough, but does not - * return precise length read. User have to know how many bytes should - * be read. Filling reply buffer with a memory pattern may help user. - */ - memset(context->reply, 0xFF, sizeof(context->reply)); - request = memdup_user(user_buf, count); - if (IS_ERR(request)) - return PTR_ERR(request); - if (le16_to_cpu(request->len) != count) { - kfree(request); - return -EINVAL; - } - context->ret = wfx_cmd_send(wdev, request, context->reply, - sizeof(context->reply), false); - - kfree(request); - complete(&context->complete); - return count; -} - -static ssize_t wfx_send_hif_msg_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct dbgfs_hif_msg *context = file->private_data; - int ret; - - if (count > sizeof(context->reply)) - return -EINVAL; - ret = wait_for_completion_interruptible(&context->complete); - if (ret) - return ret; - if (context->ret < 0) - return context->ret; - /* Be careful, write() is waiting for a full message while read() - * only returns a payload - */ - if (copy_to_user(user_buf, context->reply, count)) - return -EFAULT; - - return count; -} - -static int wfx_send_hif_msg_open(struct inode *inode, struct file *file) -{ - struct dbgfs_hif_msg *context = kzalloc(sizeof(*context), GFP_KERNEL); - - if (!context) - return -ENOMEM; - context->wdev = inode->i_private; - init_completion(&context->complete); - file->private_data = context; - return 0; -} - -static int wfx_send_hif_msg_release(struct inode *inode, struct file *file) -{ - struct dbgfs_hif_msg *context = file->private_data; - - kfree(context); - return 0; -} - -static const struct file_operations wfx_send_hif_msg_fops = { - .open = wfx_send_hif_msg_open, - .release = wfx_send_hif_msg_release, - .write = wfx_send_hif_msg_write, - .read = wfx_send_hif_msg_read, -}; - -static int wfx_ps_timeout_set(void *data, u64 val) -{ - struct wfx_dev *wdev = (struct wfx_dev *)data; - struct wfx_vif *wvif; - - wdev->force_ps_timeout = val; - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - wfx_update_pm(wvif); - return 0; -} - -static int wfx_ps_timeout_get(void *data, u64 *val) -{ - struct wfx_dev *wdev = (struct wfx_dev *)data; - - *val = wdev->force_ps_timeout; - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(wfx_ps_timeout_fops, wfx_ps_timeout_get, wfx_ps_timeout_set, "%lld\n"); - -int wfx_debug_init(struct wfx_dev *wdev) -{ - struct dentry *d; - - d = debugfs_create_dir("wfx", wdev->hw->wiphy->debugfsdir); - debugfs_create_file("counters", 0444, d, wdev, &wfx_counters_fops); - debugfs_create_file("rx_stats", 0444, d, wdev, &wfx_rx_stats_fops); - debugfs_create_file("tx_power_loop", 0444, d, wdev, - &wfx_tx_power_loop_fops); - debugfs_create_file("send_pds", 0200, d, wdev, &wfx_send_pds_fops); - debugfs_create_file("send_hif_msg", 0600, d, wdev, - &wfx_send_hif_msg_fops); - debugfs_create_file("ps_timeout", 0600, d, wdev, &wfx_ps_timeout_fops); - - return 0; -} diff --git a/drivers/staging/wfx/debug.h b/drivers/staging/wfx/debug.h deleted file mode 100644 index 4b9c49a9fffb..000000000000 --- a/drivers/staging/wfx/debug.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Debugfs interface. - * - * Copyright (c) 2017-2019, Silicon Laboratories, Inc. - * Copyright (c) 2011, ST-Ericsson - */ -#ifndef WFX_DEBUG_H -#define WFX_DEBUG_H - -struct wfx_dev; - -int wfx_debug_init(struct wfx_dev *wdev); - -const char *get_hif_name(unsigned long id); -const char *get_mib_name(unsigned long id); -const char *get_reg_name(unsigned long id); - -#endif diff --git a/drivers/staging/wfx/fwio.c b/drivers/staging/wfx/fwio.c deleted file mode 100644 index 98a9391b2bee..000000000000 --- a/drivers/staging/wfx/fwio.c +++ /dev/null @@ -1,405 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Firmware loading. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include -#include -#include - -#include "fwio.h" -#include "wfx.h" -#include "hwio.h" - -/* Addresses below are in SRAM area */ -#define WFX_DNLD_FIFO 0x09004000 -#define DNLD_BLOCK_SIZE 0x0400 -#define DNLD_FIFO_SIZE 0x8000 /* (32 * DNLD_BLOCK_SIZE) */ -/* Download Control Area (DCA) */ -#define WFX_DCA_IMAGE_SIZE 0x0900C000 -#define WFX_DCA_PUT 0x0900C004 -#define WFX_DCA_GET 0x0900C008 -#define WFX_DCA_HOST_STATUS 0x0900C00C -#define HOST_READY 0x87654321 -#define HOST_INFO_READ 0xA753BD99 -#define HOST_UPLOAD_PENDING 0xABCDDCBA -#define HOST_UPLOAD_COMPLETE 0xD4C64A99 -#define HOST_OK_TO_JUMP 0x174FC882 -#define WFX_DCA_NCP_STATUS 0x0900C010 -#define NCP_NOT_READY 0x12345678 -#define NCP_READY 0x87654321 -#define NCP_INFO_READY 0xBD53EF99 -#define NCP_DOWNLOAD_PENDING 0xABCDDCBA -#define NCP_DOWNLOAD_COMPLETE 0xCAFEFECA -#define NCP_AUTH_OK 0xD4C64A99 -#define NCP_AUTH_FAIL 0x174FC882 -#define NCP_PUB_KEY_RDY 0x7AB41D19 -#define WFX_DCA_FW_SIGNATURE 0x0900C014 -#define FW_SIGNATURE_SIZE 0x40 -#define WFX_DCA_FW_HASH 0x0900C054 -#define FW_HASH_SIZE 0x08 -#define WFX_DCA_FW_VERSION 0x0900C05C -#define FW_VERSION_SIZE 0x04 -#define WFX_DCA_RESERVED 0x0900C060 -#define DCA_RESERVED_SIZE 0x20 -#define WFX_STATUS_INFO 0x0900C080 -#define WFX_BOOTLOADER_LABEL 0x0900C084 -#define BOOTLOADER_LABEL_SIZE 0x3C -#define WFX_PTE_INFO 0x0900C0C0 -#define PTE_INFO_KEYSET_IDX 0x0D -#define PTE_INFO_SIZE 0x10 -#define WFX_ERR_INFO 0x0900C0D0 -#define ERR_INVALID_SEC_TYPE 0x05 -#define ERR_SIG_VERIF_FAILED 0x0F -#define ERR_AES_CTRL_KEY 0x10 -#define ERR_ECC_PUB_KEY 0x11 -#define ERR_MAC_KEY 0x18 - -#define DCA_TIMEOUT 50 /* milliseconds */ -#define WAKEUP_TIMEOUT 200 /* milliseconds */ - -static const char * const fwio_errors[] = { - [ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption", - [ERR_SIG_VERIF_FAILED] = "Signature verification failed", - [ERR_AES_CTRL_KEY] = "AES control key not initialized", - [ERR_ECC_PUB_KEY] = "ECC public key not initialized", - [ERR_MAC_KEY] = "MAC key not initialized", -}; - -/* request_firmware() allocate data using vmalloc(). It is not compatible with - * underlying hardware that use DMA. Function below detect this case and - * allocate a bounce buffer if necessary. - * - * Notice that, in doubt, you can enable CONFIG_DEBUG_SG to ask kernel to - * detect this problem at runtime (else, kernel silently fail). - * - * NOTE: it may also be possible to use 'pages' from struct firmware and avoid - * bounce buffer - */ -static int sram_write_dma_safe(struct wfx_dev *wdev, u32 addr, const u8 *buf, - size_t len) -{ - int ret; - const u8 *tmp; - - if (!virt_addr_valid(buf)) { - tmp = kmemdup(buf, len, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - } else { - tmp = buf; - } - ret = sram_buf_write(wdev, addr, tmp, len); - if (tmp != buf) - kfree(tmp); - return ret; -} - -static int get_firmware(struct wfx_dev *wdev, u32 keyset_chip, - const struct firmware **fw, int *file_offset) -{ - int keyset_file; - char filename[256]; - const char *data; - int ret; - - snprintf(filename, sizeof(filename), "%s_%02X.sec", - wdev->pdata.file_fw, keyset_chip); - ret = firmware_request_nowarn(fw, filename, wdev->dev); - if (ret) { - dev_info(wdev->dev, "can't load %s, falling back to %s.sec\n", - filename, wdev->pdata.file_fw); - snprintf(filename, sizeof(filename), "%s.sec", - wdev->pdata.file_fw); - ret = request_firmware(fw, filename, wdev->dev); - if (ret) { - dev_err(wdev->dev, "can't load %s\n", filename); - *fw = NULL; - return ret; - } - } - - data = (*fw)->data; - if (memcmp(data, "KEYSET", 6) != 0) { - /* Legacy firmware format */ - *file_offset = 0; - keyset_file = 0x90; - } else { - *file_offset = 8; - keyset_file = (hex_to_bin(data[6]) * 16) | hex_to_bin(data[7]); - if (keyset_file < 0) { - dev_err(wdev->dev, "%s corrupted\n", filename); - release_firmware(*fw); - *fw = NULL; - return -EINVAL; - } - } - if (keyset_file != keyset_chip) { - dev_err(wdev->dev, "firmware keyset is incompatible with chip (file: 0x%02X, chip: 0x%02X)\n", - keyset_file, keyset_chip); - release_firmware(*fw); - *fw = NULL; - return -ENODEV; - } - wdev->keyset = keyset_file; - return 0; -} - -static int wait_ncp_status(struct wfx_dev *wdev, u32 status) -{ - ktime_t now, start; - u32 reg; - int ret; - - start = ktime_get(); - for (;;) { - ret = sram_reg_read(wdev, WFX_DCA_NCP_STATUS, ®); - if (ret < 0) - return -EIO; - now = ktime_get(); - if (reg == status) - break; - if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT))) - return -ETIMEDOUT; - } - if (ktime_compare(now, start)) - dev_dbg(wdev->dev, "chip answer after %lldus\n", - ktime_us_delta(now, start)); - else - dev_dbg(wdev->dev, "chip answer immediately\n"); - return 0; -} - -static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len) -{ - int ret; - u32 offs, bytes_done = 0; - ktime_t now, start; - - if (len % DNLD_BLOCK_SIZE) { - dev_err(wdev->dev, "firmware size is not aligned. Buffer overrun will occur\n"); - return -EIO; - } - offs = 0; - while (offs < len) { - start = ktime_get(); - for (;;) { - now = ktime_get(); - if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE) - break; - if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT))) - return -ETIMEDOUT; - ret = sram_reg_read(wdev, WFX_DCA_GET, &bytes_done); - if (ret < 0) - return ret; - } - if (ktime_compare(now, start)) - dev_dbg(wdev->dev, "answer after %lldus\n", - ktime_us_delta(now, start)); - - ret = sram_write_dma_safe(wdev, WFX_DNLD_FIFO + - (offs % DNLD_FIFO_SIZE), - data + offs, DNLD_BLOCK_SIZE); - if (ret < 0) - return ret; - - /* The device seems to not support writing 0 in this register - * during first loop - */ - offs += DNLD_BLOCK_SIZE; - ret = sram_reg_write(wdev, WFX_DCA_PUT, offs); - if (ret < 0) - return ret; - } - return 0; -} - -static void print_boot_status(struct wfx_dev *wdev) -{ - u32 reg; - - sram_reg_read(wdev, WFX_STATUS_INFO, ®); - if (reg == 0x12345678) - return; - sram_reg_read(wdev, WFX_ERR_INFO, ®); - if (reg < ARRAY_SIZE(fwio_errors) && fwio_errors[reg]) - dev_info(wdev->dev, "secure boot: %s\n", fwio_errors[reg]); - else - dev_info(wdev->dev, "secure boot: Error %#02x\n", reg); -} - -static int load_firmware_secure(struct wfx_dev *wdev) -{ - const struct firmware *fw = NULL; - int header_size; - int fw_offset; - ktime_t start; - u8 *buf; - int ret; - - BUILD_BUG_ON(PTE_INFO_SIZE > BOOTLOADER_LABEL_SIZE); - buf = kmalloc(BOOTLOADER_LABEL_SIZE + 1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_READY); - ret = wait_ncp_status(wdev, NCP_INFO_READY); - if (ret) - goto error; - - sram_buf_read(wdev, WFX_BOOTLOADER_LABEL, buf, BOOTLOADER_LABEL_SIZE); - buf[BOOTLOADER_LABEL_SIZE] = 0; - dev_dbg(wdev->dev, "bootloader: \"%s\"\n", buf); - - sram_buf_read(wdev, WFX_PTE_INFO, buf, PTE_INFO_SIZE); - ret = get_firmware(wdev, buf[PTE_INFO_KEYSET_IDX], &fw, &fw_offset); - if (ret) - goto error; - header_size = fw_offset + FW_SIGNATURE_SIZE + FW_HASH_SIZE; - - sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_INFO_READ); - ret = wait_ncp_status(wdev, NCP_READY); - if (ret) - goto error; - - sram_reg_write(wdev, WFX_DNLD_FIFO, 0xFFFFFFFF); /* Fifo init */ - sram_write_dma_safe(wdev, WFX_DCA_FW_VERSION, "\x01\x00\x00\x00", - FW_VERSION_SIZE); - sram_write_dma_safe(wdev, WFX_DCA_FW_SIGNATURE, fw->data + fw_offset, - FW_SIGNATURE_SIZE); - sram_write_dma_safe(wdev, WFX_DCA_FW_HASH, - fw->data + fw_offset + FW_SIGNATURE_SIZE, - FW_HASH_SIZE); - sram_reg_write(wdev, WFX_DCA_IMAGE_SIZE, fw->size - header_size); - sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_PENDING); - ret = wait_ncp_status(wdev, NCP_DOWNLOAD_PENDING); - if (ret) - goto error; - - start = ktime_get(); - ret = upload_firmware(wdev, fw->data + header_size, - fw->size - header_size); - if (ret) - goto error; - dev_dbg(wdev->dev, "firmware load after %lldus\n", - ktime_us_delta(ktime_get(), start)); - - sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_COMPLETE); - ret = wait_ncp_status(wdev, NCP_AUTH_OK); - /* Legacy ROM support */ - if (ret < 0) - ret = wait_ncp_status(wdev, NCP_PUB_KEY_RDY); - if (ret < 0) - goto error; - sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_OK_TO_JUMP); - -error: - kfree(buf); - if (fw) - release_firmware(fw); - if (ret) - print_boot_status(wdev); - return ret; -} - -static int init_gpr(struct wfx_dev *wdev) -{ - int ret, i; - static const struct { - int index; - u32 value; - } gpr_init[] = { - { 0x07, 0x208775 }, - { 0x08, 0x2EC020 }, - { 0x09, 0x3C3C3C }, - { 0x0B, 0x322C44 }, - { 0x0C, 0xA06497 }, - }; - - for (i = 0; i < ARRAY_SIZE(gpr_init); i++) { - ret = igpr_reg_write(wdev, gpr_init[i].index, - gpr_init[i].value); - if (ret < 0) - return ret; - dev_dbg(wdev->dev, " index %02x: %08x\n", - gpr_init[i].index, gpr_init[i].value); - } - return 0; -} - -int wfx_init_device(struct wfx_dev *wdev) -{ - int ret; - int hw_revision, hw_type; - int wakeup_timeout = 50; /* ms */ - ktime_t now, start; - u32 reg; - - reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_BYTE_ORDER_ABCD; - if (wdev->pdata.use_rising_clk) - reg |= CFG_CLK_RISE_EDGE; - ret = config_reg_write(wdev, reg); - if (ret < 0) { - dev_err(wdev->dev, "bus returned an error during first write access. Host configuration error?\n"); - return -EIO; - } - - ret = config_reg_read(wdev, ®); - if (ret < 0) { - dev_err(wdev->dev, "bus returned an error during first read access. Bus configuration error?\n"); - return -EIO; - } - if (reg == 0 || reg == ~0) { - dev_err(wdev->dev, "chip mute. Bus configuration error or chip wasn't reset?\n"); - return -EIO; - } - dev_dbg(wdev->dev, "initial config register value: %08x\n", reg); - - hw_revision = FIELD_GET(CFG_DEVICE_ID_MAJOR, reg); - if (hw_revision == 0) { - dev_err(wdev->dev, "bad hardware revision number: %d\n", - hw_revision); - return -ENODEV; - } - hw_type = FIELD_GET(CFG_DEVICE_ID_TYPE, reg); - if (hw_type == 1) { - dev_notice(wdev->dev, "development hardware detected\n"); - wakeup_timeout = 2000; - } - - ret = init_gpr(wdev); - if (ret < 0) - return ret; - - ret = control_reg_write(wdev, CTRL_WLAN_WAKEUP); - if (ret < 0) - return -EIO; - start = ktime_get(); - for (;;) { - ret = control_reg_read(wdev, ®); - now = ktime_get(); - if (reg & CTRL_WLAN_READY) - break; - if (ktime_after(now, ktime_add_ms(start, wakeup_timeout))) { - dev_err(wdev->dev, "chip didn't wake up. Chip wasn't reset?\n"); - return -ETIMEDOUT; - } - } - dev_dbg(wdev->dev, "chip wake up after %lldus\n", - ktime_us_delta(now, start)); - - ret = config_reg_write_bits(wdev, CFG_CPU_RESET, 0); - if (ret < 0) - return ret; - ret = load_firmware_secure(wdev); - if (ret < 0) - return ret; - return config_reg_write_bits(wdev, - CFG_DIRECT_ACCESS_MODE | - CFG_IRQ_ENABLE_DATA | - CFG_IRQ_ENABLE_WRDY, - CFG_IRQ_ENABLE_DATA); -} diff --git a/drivers/staging/wfx/fwio.h b/drivers/staging/wfx/fwio.h deleted file mode 100644 index eeea61210eca..000000000000 --- a/drivers/staging/wfx/fwio.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Firmware loading. - * - * Copyright (c) 2017-2019, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_FWIO_H -#define WFX_FWIO_H - -struct wfx_dev; - -int wfx_init_device(struct wfx_dev *wdev); - -#endif diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h deleted file mode 100644 index b0aa13b23a51..000000000000 --- a/drivers/staging/wfx/hif_api_cmd.h +++ /dev/null @@ -1,555 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ -/* - * WF200 hardware interface definitions - * - * Copyright (c) 2018-2020, Silicon Laboratories Inc. - */ - -#ifndef WFX_HIF_API_CMD_H -#define WFX_HIF_API_CMD_H - -#include - -#include "hif_api_general.h" - -enum hif_requests_ids { - HIF_REQ_ID_RESET = 0x0a, - HIF_REQ_ID_READ_MIB = 0x05, - HIF_REQ_ID_WRITE_MIB = 0x06, - HIF_REQ_ID_START_SCAN = 0x07, - HIF_REQ_ID_STOP_SCAN = 0x08, - HIF_REQ_ID_TX = 0x04, - HIF_REQ_ID_JOIN = 0x0b, - HIF_REQ_ID_SET_PM_MODE = 0x10, - HIF_REQ_ID_SET_BSS_PARAMS = 0x11, - HIF_REQ_ID_ADD_KEY = 0x0c, - HIF_REQ_ID_REMOVE_KEY = 0x0d, - HIF_REQ_ID_EDCA_QUEUE_PARAMS = 0x13, - HIF_REQ_ID_START = 0x17, - HIF_REQ_ID_BEACON_TRANSMIT = 0x18, - HIF_REQ_ID_UPDATE_IE = 0x1b, - HIF_REQ_ID_MAP_LINK = 0x1c, -}; - -enum hif_confirmations_ids { - HIF_CNF_ID_RESET = 0x0a, - HIF_CNF_ID_READ_MIB = 0x05, - HIF_CNF_ID_WRITE_MIB = 0x06, - HIF_CNF_ID_START_SCAN = 0x07, - HIF_CNF_ID_STOP_SCAN = 0x08, - HIF_CNF_ID_TX = 0x04, - HIF_CNF_ID_MULTI_TRANSMIT = 0x1e, - HIF_CNF_ID_JOIN = 0x0b, - HIF_CNF_ID_SET_PM_MODE = 0x10, - HIF_CNF_ID_SET_BSS_PARAMS = 0x11, - HIF_CNF_ID_ADD_KEY = 0x0c, - HIF_CNF_ID_REMOVE_KEY = 0x0d, - HIF_CNF_ID_EDCA_QUEUE_PARAMS = 0x13, - HIF_CNF_ID_START = 0x17, - HIF_CNF_ID_BEACON_TRANSMIT = 0x18, - HIF_CNF_ID_UPDATE_IE = 0x1b, - HIF_CNF_ID_MAP_LINK = 0x1c, -}; - -enum hif_indications_ids { - HIF_IND_ID_RX = 0x84, - HIF_IND_ID_SCAN_CMPL = 0x86, - HIF_IND_ID_JOIN_COMPLETE = 0x8f, - HIF_IND_ID_SET_PM_MODE_CMPL = 0x89, - HIF_IND_ID_SUSPEND_RESUME_TX = 0x8c, - HIF_IND_ID_EVENT = 0x85 -}; - -struct hif_req_reset { - u8 reset_stat:1; - u8 reset_all_int:1; - u8 reserved1:6; - u8 reserved2[3]; -} __packed; - -struct hif_cnf_reset { - __le32 status; -} __packed; - -struct hif_req_read_mib { - __le16 mib_id; - __le16 reserved; -} __packed; - -struct hif_cnf_read_mib { - __le32 status; - __le16 mib_id; - __le16 length; - u8 mib_data[]; -} __packed; - -struct hif_req_write_mib { - __le16 mib_id; - __le16 length; - u8 mib_data[]; -} __packed; - -struct hif_cnf_write_mib { - __le32 status; -} __packed; - -struct hif_req_update_ie { - u8 beacon:1; - u8 probe_resp:1; - u8 probe_req:1; - u8 reserved1:5; - u8 reserved2; - __le16 num_ies; - u8 ie[]; -} __packed; - -struct hif_cnf_update_ie { - __le32 status; -} __packed; - -struct hif_ssid_def { - __le32 ssid_length; - u8 ssid[IEEE80211_MAX_SSID_LEN]; -} __packed; - -#define HIF_API_MAX_NB_SSIDS 2 -#define HIF_API_MAX_NB_CHANNELS 14 - -struct hif_req_start_scan_alt { - u8 band; - u8 maintain_current_bss:1; - u8 periodic:1; - u8 reserved1:6; - u8 disallow_ps:1; - u8 reserved2:1; - u8 short_preamble:1; - u8 reserved3:5; - u8 max_transmit_rate; - __le16 periodic_interval; - u8 reserved4; - s8 periodic_rssi_thr; - u8 num_of_probe_requests; - u8 probe_delay; - u8 num_of_ssids; - u8 num_of_channels; - __le32 min_channel_time; - __le32 max_channel_time; - __le32 tx_power_level; /* signed value */ - struct hif_ssid_def ssid_def[HIF_API_MAX_NB_SSIDS]; - u8 channel_list[]; -} __packed; - -struct hif_cnf_start_scan { - __le32 status; -} __packed; - -struct hif_cnf_stop_scan { - __le32 status; -} __packed; - -enum hif_pm_mode_status { - HIF_PM_MODE_ACTIVE = 0x0, - HIF_PM_MODE_PS = 0x1, - HIF_PM_MODE_UNDETERMINED = 0x2 -}; - -struct hif_ind_scan_cmpl { - __le32 status; - u8 pm_mode; - u8 num_channels_completed; - __le16 reserved; -} __packed; - -enum hif_queue_id { - HIF_QUEUE_ID_BACKGROUND = 0x0, - HIF_QUEUE_ID_BESTEFFORT = 0x1, - HIF_QUEUE_ID_VIDEO = 0x2, - HIF_QUEUE_ID_VOICE = 0x3 -}; - -enum hif_frame_format { - HIF_FRAME_FORMAT_NON_HT = 0x0, - HIF_FRAME_FORMAT_MIXED_FORMAT_HT = 0x1, - HIF_FRAME_FORMAT_GF_HT_11N = 0x2 -}; - -struct hif_req_tx { - /* packet_id is not interpreted by the device, so it is not necessary to - * declare it little endian - */ - u32 packet_id; - u8 max_tx_rate; - u8 queue_id:2; - u8 peer_sta_id:4; - u8 reserved1:2; - u8 more:1; - u8 fc_offset:3; - u8 after_dtim:1; - u8 reserved2:3; - u8 start_exp:1; - u8 reserved3:3; - u8 retry_policy_index:4; - __le32 reserved4; - __le32 expire_time; - u8 frame_format:4; - u8 fec_coding:1; - u8 short_gi:1; - u8 reserved5:1; - u8 stbc:1; - u8 reserved6; - u8 aggregation:1; - u8 reserved7:7; - u8 reserved8; - u8 frame[]; -} __packed; - -enum hif_qos_ackplcy { - HIF_QOS_ACKPLCY_NORMAL = 0x0, - HIF_QOS_ACKPLCY_TXNOACK = 0x1, - HIF_QOS_ACKPLCY_NOEXPACK = 0x2, - HIF_QOS_ACKPLCY_BLCKACK = 0x3 -}; - -struct hif_cnf_tx { - __le32 status; - /* packet_id is copied from struct hif_req_tx without been interpreted - * by the device, so it is not necessary to declare it little endian - */ - u32 packet_id; - u8 txed_rate; - u8 ack_failures; - u8 aggr:1; - u8 requeue:1; - u8 ack_policy:2; - u8 txop_limit:1; - u8 reserved1:3; - u8 reserved2; - __le32 media_delay; - __le32 tx_queue_delay; -} __packed; - -struct hif_cnf_multi_transmit { - u8 num_tx_confs; - u8 reserved[3]; - struct hif_cnf_tx tx_conf_payload[]; -} __packed; - -enum hif_ri_flags_encrypt { - HIF_RI_FLAGS_UNENCRYPTED = 0x0, - HIF_RI_FLAGS_WEP_ENCRYPTED = 0x1, - HIF_RI_FLAGS_TKIP_ENCRYPTED = 0x2, - HIF_RI_FLAGS_AES_ENCRYPTED = 0x3, - HIF_RI_FLAGS_WAPI_ENCRYPTED = 0x4 -}; - -struct hif_ind_rx { - __le32 status; - u8 channel_number; - u8 reserved1; - u8 rxed_rate; - u8 rcpi_rssi; - u8 encryp:3; - u8 in_aggr:1; - u8 first_aggr:1; - u8 last_aggr:1; - u8 defrag:1; - u8 beacon:1; - u8 tim:1; - u8 bitmap:1; - u8 match_ssid:1; - u8 match_bssid:1; - u8 more:1; - u8 reserved2:1; - u8 ht:1; - u8 stbc:1; - u8 match_uc_addr:1; - u8 match_mc_addr:1; - u8 match_bc_addr:1; - u8 key_type:1; - u8 key_index:4; - u8 reserved3:1; - u8 peer_sta_id:4; - u8 reserved4:2; - u8 reserved5:1; - u8 frame[]; -} __packed; - -struct hif_req_edca_queue_params { - u8 queue_id; - u8 reserved1; - u8 aifsn; - u8 reserved2; - __le16 cw_min; - __le16 cw_max; - __le16 tx_op_limit; - __le16 allowed_medium_time; - __le32 reserved3; -} __packed; - -struct hif_cnf_edca_queue_params { - __le32 status; -} __packed; - -struct hif_req_join { - u8 infrastructure_bss_mode:1; - u8 reserved1:7; - u8 band; - u8 channel_number; - u8 reserved2; - u8 bssid[ETH_ALEN]; - __le16 atim_window; - u8 short_preamble:1; - u8 reserved3:7; - u8 probe_for_join; - u8 reserved4; - u8 reserved5:2; - u8 force_no_beacon:1; - u8 force_with_ind:1; - u8 reserved6:4; - __le32 ssid_length; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - __le32 beacon_interval; - __le32 basic_rate_set; -} __packed; - -struct hif_cnf_join { - __le32 status; -} __packed; - -struct hif_ind_join_complete { - __le32 status; -} __packed; - -struct hif_req_set_bss_params { - u8 lost_count_only:1; - u8 reserved:7; - u8 beacon_lost_count; - __le16 aid; - __le32 operational_rate_set; -} __packed; - -struct hif_cnf_set_bss_params { - __le32 status; -} __packed; - -struct hif_req_set_pm_mode { - u8 enter_psm:1; - u8 reserved:6; - u8 fast_psm:1; - u8 fast_psm_idle_period; - u8 ap_psm_change_period; - u8 min_auto_ps_poll_period; -} __packed; - -struct hif_cnf_set_pm_mode { - __le32 status; -} __packed; - -struct hif_ind_set_pm_mode_cmpl { - __le32 status; - u8 pm_mode; - u8 reserved[3]; -} __packed; - -struct hif_req_start { - u8 mode; - u8 band; - u8 channel_number; - u8 reserved1; - __le32 reserved2; - __le32 beacon_interval; - u8 dtim_period; - u8 short_preamble:1; - u8 reserved3:7; - u8 reserved4; - u8 ssid_length; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - __le32 basic_rate_set; -} __packed; - -struct hif_cnf_start { - __le32 status; -} __packed; - -struct hif_req_beacon_transmit { - u8 enable_beaconing; - u8 reserved[3]; -} __packed; - -struct hif_cnf_beacon_transmit { - __le32 status; -} __packed; - -#define HIF_LINK_ID_MAX 14 -#define HIF_LINK_ID_NOT_ASSOCIATED (HIF_LINK_ID_MAX + 1) - -struct hif_req_map_link { - u8 mac_addr[ETH_ALEN]; - u8 unmap:1; - u8 mfpc:1; - u8 reserved:6; - u8 peer_sta_id; -} __packed; - -struct hif_cnf_map_link { - __le32 status; -} __packed; - -struct hif_ind_suspend_resume_tx { - u8 resume:1; - u8 reserved1:2; - u8 bc_mc_only:1; - u8 reserved2:4; - u8 reserved3; - __le16 peer_sta_set; -} __packed; - - -#define MAX_KEY_ENTRIES 24 -#define HIF_API_WEP_KEY_DATA_SIZE 16 -#define HIF_API_TKIP_KEY_DATA_SIZE 16 -#define HIF_API_RX_MIC_KEY_SIZE 8 -#define HIF_API_TX_MIC_KEY_SIZE 8 -#define HIF_API_AES_KEY_DATA_SIZE 16 -#define HIF_API_WAPI_KEY_DATA_SIZE 16 -#define HIF_API_MIC_KEY_DATA_SIZE 16 -#define HIF_API_IGTK_KEY_DATA_SIZE 16 -#define HIF_API_RX_SEQUENCE_COUNTER_SIZE 8 -#define HIF_API_IPN_SIZE 8 - -enum hif_key_type { - HIF_KEY_TYPE_WEP_DEFAULT = 0x0, - HIF_KEY_TYPE_WEP_PAIRWISE = 0x1, - HIF_KEY_TYPE_TKIP_GROUP = 0x2, - HIF_KEY_TYPE_TKIP_PAIRWISE = 0x3, - HIF_KEY_TYPE_AES_GROUP = 0x4, - HIF_KEY_TYPE_AES_PAIRWISE = 0x5, - HIF_KEY_TYPE_WAPI_GROUP = 0x6, - HIF_KEY_TYPE_WAPI_PAIRWISE = 0x7, - HIF_KEY_TYPE_IGTK_GROUP = 0x8, - HIF_KEY_TYPE_NONE = 0x9 -}; - -struct hif_wep_pairwise_key { - u8 peer_address[ETH_ALEN]; - u8 reserved; - u8 key_length; - u8 key_data[HIF_API_WEP_KEY_DATA_SIZE]; -} __packed; - -struct hif_wep_group_key { - u8 key_id; - u8 key_length; - u8 reserved[2]; - u8 key_data[HIF_API_WEP_KEY_DATA_SIZE]; -} __packed; - -struct hif_tkip_pairwise_key { - u8 peer_address[ETH_ALEN]; - u8 reserved[2]; - u8 tkip_key_data[HIF_API_TKIP_KEY_DATA_SIZE]; - u8 rx_mic_key[HIF_API_RX_MIC_KEY_SIZE]; - u8 tx_mic_key[HIF_API_TX_MIC_KEY_SIZE]; -} __packed; - -struct hif_tkip_group_key { - u8 tkip_key_data[HIF_API_TKIP_KEY_DATA_SIZE]; - u8 rx_mic_key[HIF_API_RX_MIC_KEY_SIZE]; - u8 key_id; - u8 reserved[3]; - u8 rx_sequence_counter[HIF_API_RX_SEQUENCE_COUNTER_SIZE]; -} __packed; - -struct hif_aes_pairwise_key { - u8 peer_address[ETH_ALEN]; - u8 reserved[2]; - u8 aes_key_data[HIF_API_AES_KEY_DATA_SIZE]; -} __packed; - -struct hif_aes_group_key { - u8 aes_key_data[HIF_API_AES_KEY_DATA_SIZE]; - u8 key_id; - u8 reserved[3]; - u8 rx_sequence_counter[HIF_API_RX_SEQUENCE_COUNTER_SIZE]; -} __packed; - -struct hif_wapi_pairwise_key { - u8 peer_address[ETH_ALEN]; - u8 key_id; - u8 reserved; - u8 wapi_key_data[HIF_API_WAPI_KEY_DATA_SIZE]; - u8 mic_key_data[HIF_API_MIC_KEY_DATA_SIZE]; -} __packed; - -struct hif_wapi_group_key { - u8 wapi_key_data[HIF_API_WAPI_KEY_DATA_SIZE]; - u8 mic_key_data[HIF_API_MIC_KEY_DATA_SIZE]; - u8 key_id; - u8 reserved[3]; -} __packed; - -struct hif_igtk_group_key { - u8 igtk_key_data[HIF_API_IGTK_KEY_DATA_SIZE]; - u8 key_id; - u8 reserved[3]; - u8 ipn[HIF_API_IPN_SIZE]; -} __packed; - -struct hif_req_add_key { - u8 type; - u8 entry_index; - u8 int_id:2; - u8 reserved1:6; - u8 reserved2; - union { - struct hif_wep_pairwise_key wep_pairwise_key; - struct hif_wep_group_key wep_group_key; - struct hif_tkip_pairwise_key tkip_pairwise_key; - struct hif_tkip_group_key tkip_group_key; - struct hif_aes_pairwise_key aes_pairwise_key; - struct hif_aes_group_key aes_group_key; - struct hif_wapi_pairwise_key wapi_pairwise_key; - struct hif_wapi_group_key wapi_group_key; - struct hif_igtk_group_key igtk_group_key; - } key; -} __packed; - -struct hif_cnf_add_key { - __le32 status; -} __packed; - -struct hif_req_remove_key { - u8 entry_index; - u8 reserved[3]; -} __packed; - -struct hif_cnf_remove_key { - __le32 status; -} __packed; - -enum hif_event_ind { - HIF_EVENT_IND_BSSLOST = 0x1, - HIF_EVENT_IND_BSSREGAINED = 0x2, - HIF_EVENT_IND_RCPI_RSSI = 0x3, - HIF_EVENT_IND_PS_MODE_ERROR = 0x4, - HIF_EVENT_IND_INACTIVITY = 0x5 -}; - -enum hif_ps_mode_error { - HIF_PS_ERROR_NO_ERROR = 0, - HIF_PS_ERROR_AP_NOT_RESP_TO_POLL = 1, - HIF_PS_ERROR_AP_NOT_RESP_TO_UAPSD_TRIGGER = 2, - HIF_PS_ERROR_AP_SENT_UNICAST_IN_DOZE = 3, - HIF_PS_ERROR_AP_NO_DATA_AFTER_TIM = 4 -}; - -struct hif_ind_event { - __le32 event_id; - union { - u8 rcpi_rssi; - __le32 ps_mode_error; - __le32 peer_sta_set; - } event_data; -} __packed; - -#endif diff --git a/drivers/staging/wfx/hif_api_general.h b/drivers/staging/wfx/hif_api_general.h deleted file mode 100644 index 5f74f829b7df..000000000000 --- a/drivers/staging/wfx/hif_api_general.h +++ /dev/null @@ -1,262 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ -/* - * WF200 hardware interface definitions - * - * Copyright (c) 2018-2020, Silicon Laboratories Inc. - */ - -#ifndef WFX_HIF_API_GENERAL_H -#define WFX_HIF_API_GENERAL_H - -#ifdef __KERNEL__ -#include -#include -#else -#include -#include -#define __packed __attribute__((__packed__)) -#endif - -#define HIF_ID_IS_INDICATION 0x80 -#define HIF_COUNTER_MAX 7 - -struct hif_msg { - __le16 len; - u8 id; - u8 reserved:1; - u8 interface:2; - u8 seqnum:3; - u8 encrypted:2; - u8 body[]; -} __packed; - -enum hif_general_requests_ids { - HIF_REQ_ID_CONFIGURATION = 0x09, - HIF_REQ_ID_CONTROL_GPIO = 0x26, - HIF_REQ_ID_SET_SL_MAC_KEY = 0x27, - HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS = 0x28, - HIF_REQ_ID_SL_CONFIGURE = 0x29, - HIF_REQ_ID_PREVENT_ROLLBACK = 0x2a, - HIF_REQ_ID_PTA_SETTINGS = 0x2b, - HIF_REQ_ID_PTA_PRIORITY = 0x2c, - HIF_REQ_ID_PTA_STATE = 0x2d, - HIF_REQ_ID_SHUT_DOWN = 0x32, -}; - -enum hif_general_confirmations_ids { - HIF_CNF_ID_CONFIGURATION = 0x09, - HIF_CNF_ID_CONTROL_GPIO = 0x26, - HIF_CNF_ID_SET_SL_MAC_KEY = 0x27, - HIF_CNF_ID_SL_EXCHANGE_PUB_KEYS = 0x28, - HIF_CNF_ID_SL_CONFIGURE = 0x29, - HIF_CNF_ID_PREVENT_ROLLBACK = 0x2a, - HIF_CNF_ID_PTA_SETTINGS = 0x2b, - HIF_CNF_ID_PTA_PRIORITY = 0x2c, - HIF_CNF_ID_PTA_STATE = 0x2d, - HIF_CNF_ID_SHUT_DOWN = 0x32, -}; - -enum hif_general_indications_ids { - HIF_IND_ID_EXCEPTION = 0xe0, - HIF_IND_ID_STARTUP = 0xe1, - HIF_IND_ID_WAKEUP = 0xe2, - HIF_IND_ID_GENERIC = 0xe3, - HIF_IND_ID_ERROR = 0xe4, - HIF_IND_ID_SL_EXCHANGE_PUB_KEYS = 0xe5 -}; - -#define HIF_STATUS_SUCCESS (cpu_to_le32(0x0000)) -#define HIF_STATUS_FAIL (cpu_to_le32(0x0001)) -#define HIF_STATUS_INVALID_PARAMETER (cpu_to_le32(0x0002)) -#define HIF_STATUS_WARNING (cpu_to_le32(0x0003)) -#define HIF_STATUS_UNKNOWN_REQUEST (cpu_to_le32(0x0004)) -#define HIF_STATUS_RX_FAIL_DECRYPT (cpu_to_le32(0x0010)) -#define HIF_STATUS_RX_FAIL_MIC (cpu_to_le32(0x0011)) -#define HIF_STATUS_RX_FAIL_NO_KEY (cpu_to_le32(0x0012)) -#define HIF_STATUS_TX_FAIL_RETRIES (cpu_to_le32(0x0013)) -#define HIF_STATUS_TX_FAIL_TIMEOUT (cpu_to_le32(0x0014)) -#define HIF_STATUS_TX_FAIL_REQUEUE (cpu_to_le32(0x0015)) -#define HIF_STATUS_REFUSED (cpu_to_le32(0x0016)) -#define HIF_STATUS_BUSY (cpu_to_le32(0x0017)) -#define HIF_STATUS_SLK_SET_KEY_SUCCESS (cpu_to_le32(0x005A)) -#define HIF_STATUS_SLK_SET_KEY_ALREADY_BURNED (cpu_to_le32(0x006B)) -#define HIF_STATUS_SLK_SET_KEY_DISALLOWED_MODE (cpu_to_le32(0x007C)) -#define HIF_STATUS_SLK_SET_KEY_UNKNOWN_MODE (cpu_to_le32(0x008D)) -#define HIF_STATUS_SLK_NEGO_SUCCESS (cpu_to_le32(0x009E)) -#define HIF_STATUS_SLK_NEGO_FAILED (cpu_to_le32(0x00AF)) -#define HIF_STATUS_ROLLBACK_SUCCESS (cpu_to_le32(0x1234)) -#define HIF_STATUS_ROLLBACK_FAIL (cpu_to_le32(0x1256)) - -enum hif_api_rate_index { - API_RATE_INDEX_B_1MBPS = 0, - API_RATE_INDEX_B_2MBPS = 1, - API_RATE_INDEX_B_5P5MBPS = 2, - API_RATE_INDEX_B_11MBPS = 3, - API_RATE_INDEX_PBCC_22MBPS = 4, - API_RATE_INDEX_PBCC_33MBPS = 5, - API_RATE_INDEX_G_6MBPS = 6, - API_RATE_INDEX_G_9MBPS = 7, - API_RATE_INDEX_G_12MBPS = 8, - API_RATE_INDEX_G_18MBPS = 9, - API_RATE_INDEX_G_24MBPS = 10, - API_RATE_INDEX_G_36MBPS = 11, - API_RATE_INDEX_G_48MBPS = 12, - API_RATE_INDEX_G_54MBPS = 13, - API_RATE_INDEX_N_6P5MBPS = 14, - API_RATE_INDEX_N_13MBPS = 15, - API_RATE_INDEX_N_19P5MBPS = 16, - API_RATE_INDEX_N_26MBPS = 17, - API_RATE_INDEX_N_39MBPS = 18, - API_RATE_INDEX_N_52MBPS = 19, - API_RATE_INDEX_N_58P5MBPS = 20, - API_RATE_INDEX_N_65MBPS = 21, - API_RATE_NUM_ENTRIES = 22 -}; - -struct hif_ind_startup { - /* As the others, this struct is interpreted as little endian by the - * device. However, this struct is also used by the driver. We prefer to - * declare it in native order and doing byte swap on reception. - */ - __le32 status; - u16 hardware_id; - u8 opn[14]; - u8 uid[8]; - u16 num_inp_ch_bufs; - u16 size_inp_ch_buf; - u8 num_links_ap; - u8 num_interfaces; - u8 mac_addr[2][ETH_ALEN]; - u8 api_version_minor; - u8 api_version_major; - u8 link_mode:2; - u8 reserved1:6; - u8 reserved2; - u8 reserved3; - u8 reserved4; - u8 firmware_build; - u8 firmware_minor; - u8 firmware_major; - u8 firmware_type; - u8 disabled_channel_list[2]; - u8 region_sel_mode:4; - u8 reserved5:4; - u8 phy1_region:3; - u8 phy0_region:3; - u8 otp_phy_ver:2; - u32 supported_rate_mask; - u8 firmware_label[128]; -} __packed; - -struct hif_ind_wakeup { -} __packed; - -struct hif_req_configuration { - __le16 length; - u8 pds_data[]; -} __packed; - -struct hif_cnf_configuration { - __le32 status; -} __packed; - -enum hif_gpio_mode { - HIF_GPIO_MODE_D0 = 0x0, - HIF_GPIO_MODE_D1 = 0x1, - HIF_GPIO_MODE_OD0 = 0x2, - HIF_GPIO_MODE_OD1 = 0x3, - HIF_GPIO_MODE_TRISTATE = 0x4, - HIF_GPIO_MODE_TOGGLE = 0x5, - HIF_GPIO_MODE_READ = 0x6 -}; - -struct hif_req_control_gpio { - u8 gpio_label; - u8 gpio_mode; -} __packed; - -struct hif_cnf_control_gpio { - __le32 status; - __le32 value; -} __packed; - -enum hif_generic_indication_type { - HIF_GENERIC_INDICATION_TYPE_RAW = 0x0, - HIF_GENERIC_INDICATION_TYPE_STRING = 0x1, - HIF_GENERIC_INDICATION_TYPE_RX_STATS = 0x2, - HIF_GENERIC_INDICATION_TYPE_TX_POWER_LOOP_INFO = 0x3, -}; - -struct hif_rx_stats { - __le32 nb_rx_frame; - __le32 nb_crc_frame; - __le32 per_total; - __le32 throughput; - __le32 nb_rx_by_rate[API_RATE_NUM_ENTRIES]; - __le16 per[API_RATE_NUM_ENTRIES]; - __le16 snr[API_RATE_NUM_ENTRIES]; /* signed value */ - __le16 rssi[API_RATE_NUM_ENTRIES]; /* signed value */ - __le16 cfo[API_RATE_NUM_ENTRIES]; /* signed value */ - __le32 date; - __le32 pwr_clk_freq; - u8 is_ext_pwr_clk; - s8 current_temp; -} __packed; - -struct hif_tx_power_loop_info { - __le16 tx_gain_dig; - __le16 tx_gain_pa; - __le16 target_pout; /* signed value */ - __le16 p_estimation; /* signed value */ - __le16 vpdet; - u8 measurement_index; - u8 reserved; -} __packed; - -struct hif_ind_generic { - __le32 type; - union { - struct hif_rx_stats rx_stats; - struct hif_tx_power_loop_info tx_power_loop_info; - } data; -} __packed; - -enum hif_error { - HIF_ERROR_FIRMWARE_ROLLBACK = 0x00, - HIF_ERROR_FIRMWARE_DEBUG_ENABLED = 0x01, - HIF_ERROR_SLK_OUTDATED_SESSION_KEY = 0x02, - HIF_ERROR_SLK_SESSION_KEY = 0x03, - HIF_ERROR_OOR_VOLTAGE = 0x04, - HIF_ERROR_PDS_PAYLOAD = 0x05, - HIF_ERROR_OOR_TEMPERATURE = 0x06, - HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE = 0x07, - HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED = 0x08, - HIF_ERROR_SLK_OVERFLOW = 0x09, - HIF_ERROR_SLK_DECRYPTION = 0x0a, - HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE = 0x0b, - HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW = 0x0c, - HIF_ERROR_HIF_RX_DATA_TOO_LARGE = 0x0e, - HIF_ERROR_HIF_TX_QUEUE_FULL = 0x0d, - HIF_ERROR_HIF_BUS = 0x0f, - HIF_ERROR_PDS_TESTFEATURE = 0x10, - HIF_ERROR_SLK_UNCONFIGURED = 0x11, -}; - -struct hif_ind_error { - __le32 type; - u8 data[]; -} __packed; - -struct hif_ind_exception { - __le32 type; - u8 data[]; -} __packed; - -enum hif_secure_link_state { - SEC_LINK_UNAVAILABLE = 0x0, - SEC_LINK_RESERVED = 0x1, - SEC_LINK_EVAL = 0x2, - SEC_LINK_ENFORCED = 0x3 -}; - -#endif diff --git a/drivers/staging/wfx/hif_api_mib.h b/drivers/staging/wfx/hif_api_mib.h deleted file mode 100644 index da534f244757..000000000000 --- a/drivers/staging/wfx/hif_api_mib.h +++ /dev/null @@ -1,346 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ -/* - * WF200 hardware interface definitions - * - * Copyright (c) 2018-2020, Silicon Laboratories Inc. - */ - -#ifndef WFX_HIF_API_MIB_H -#define WFX_HIF_API_MIB_H - -#include "hif_api_general.h" - -#define HIF_API_IPV4_ADDRESS_SIZE 4 -#define HIF_API_IPV6_ADDRESS_SIZE 16 - -enum hif_mib_ids { - HIF_MIB_ID_GL_OPERATIONAL_POWER_MODE = 0x2000, - HIF_MIB_ID_GL_BLOCK_ACK_INFO = 0x2001, - HIF_MIB_ID_GL_SET_MULTI_MSG = 0x2002, - HIF_MIB_ID_CCA_CONFIG = 0x2003, - HIF_MIB_ID_ETHERTYPE_DATAFRAME_CONDITION = 0x2010, - HIF_MIB_ID_PORT_DATAFRAME_CONDITION = 0x2011, - HIF_MIB_ID_MAGIC_DATAFRAME_CONDITION = 0x2012, - HIF_MIB_ID_MAC_ADDR_DATAFRAME_CONDITION = 0x2013, - HIF_MIB_ID_IPV4_ADDR_DATAFRAME_CONDITION = 0x2014, - HIF_MIB_ID_IPV6_ADDR_DATAFRAME_CONDITION = 0x2015, - HIF_MIB_ID_UC_MC_BC_DATAFRAME_CONDITION = 0x2016, - HIF_MIB_ID_CONFIG_DATA_FILTER = 0x2017, - HIF_MIB_ID_SET_DATA_FILTERING = 0x2018, - HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE = 0x2019, - HIF_MIB_ID_NS_IP_ADDRESSES_TABLE = 0x201A, - HIF_MIB_ID_RX_FILTER = 0x201B, - HIF_MIB_ID_BEACON_FILTER_TABLE = 0x201C, - HIF_MIB_ID_BEACON_FILTER_ENABLE = 0x201D, - HIF_MIB_ID_GRP_SEQ_COUNTER = 0x2030, - HIF_MIB_ID_TSF_COUNTER = 0x2031, - HIF_MIB_ID_STATISTICS_TABLE = 0x2032, - HIF_MIB_ID_COUNTERS_TABLE = 0x2033, - HIF_MIB_ID_MAX_TX_POWER_LEVEL = 0x2034, - HIF_MIB_ID_EXTENDED_COUNTERS_TABLE = 0x2035, - HIF_MIB_ID_DOT11_MAC_ADDRESS = 0x2040, - HIF_MIB_ID_DOT11_MAX_TRANSMIT_MSDU_LIFETIME = 0x2041, - HIF_MIB_ID_DOT11_MAX_RECEIVE_LIFETIME = 0x2042, - HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID = 0x2043, - HIF_MIB_ID_DOT11_RTS_THRESHOLD = 0x2044, - HIF_MIB_ID_SLOT_TIME = 0x2045, - HIF_MIB_ID_CURRENT_TX_POWER_LEVEL = 0x2046, - HIF_MIB_ID_NON_ERP_PROTECTION = 0x2047, - HIF_MIB_ID_TEMPLATE_FRAME = 0x2048, - HIF_MIB_ID_BEACON_WAKEUP_PERIOD = 0x2049, - HIF_MIB_ID_RCPI_RSSI_THRESHOLD = 0x204A, - HIF_MIB_ID_BLOCK_ACK_POLICY = 0x204B, - HIF_MIB_ID_OVERRIDE_INTERNAL_TX_RATE = 0x204C, - HIF_MIB_ID_SET_ASSOCIATION_MODE = 0x204D, - HIF_MIB_ID_SET_UAPSD_INFORMATION = 0x204E, - HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY = 0x204F, - HIF_MIB_ID_PROTECTED_MGMT_POLICY = 0x2050, - HIF_MIB_ID_SET_HT_PROTECTION = 0x2051, - HIF_MIB_ID_KEEP_ALIVE_PERIOD = 0x2052, - HIF_MIB_ID_ARP_KEEP_ALIVE_PERIOD = 0x2053, - HIF_MIB_ID_INACTIVITY_TIMER = 0x2054, - HIF_MIB_ID_INTERFACE_PROTECTION = 0x2055, - HIF_MIB_ID_BEACON_STATS = 0x2056, -}; - -enum hif_op_power_mode { - HIF_OP_POWER_MODE_ACTIVE = 0x0, - HIF_OP_POWER_MODE_DOZE = 0x1, - HIF_OP_POWER_MODE_QUIESCENT = 0x2 -}; - -struct hif_mib_gl_operational_power_mode { - u8 power_mode:4; - u8 reserved1:3; - u8 wup_ind_activation:1; - u8 reserved2[3]; -} __packed; - -struct hif_mib_gl_set_multi_msg { - u8 enable_multi_tx_conf:1; - u8 reserved1:7; - u8 reserved2[3]; -} __packed; - -enum hif_arp_ns_frame_treatment { - HIF_ARP_NS_FILTERING_DISABLE = 0x0, - HIF_ARP_NS_FILTERING_ENABLE = 0x1, - HIF_ARP_NS_REPLY_ENABLE = 0x2 -}; - -struct hif_mib_arp_ip_addr_table { - u8 condition_idx; - u8 arp_enable; - u8 reserved[2]; - u8 ipv4_address[HIF_API_IPV4_ADDRESS_SIZE]; -} __packed; - -struct hif_mib_rx_filter { - u8 reserved1:1; - u8 bssid_filter:1; - u8 reserved2:1; - u8 fwd_probe_req:1; - u8 keep_alive_filter:1; - u8 reserved3:3; - u8 reserved4[3]; -} __packed; - -struct hif_ie_table_entry { - u8 ie_id; - u8 has_changed:1; - u8 no_longer:1; - u8 has_appeared:1; - u8 reserved:1; - u8 num_match_data:4; - u8 oui[3]; - u8 match_data[3]; -} __packed; - -struct hif_mib_bcn_filter_table { - __le32 num_of_info_elmts; - struct hif_ie_table_entry ie_table[]; -} __packed; - -enum hif_beacon_filter { - HIF_BEACON_FILTER_DISABLE = 0x0, - HIF_BEACON_FILTER_ENABLE = 0x1, - HIF_BEACON_FILTER_AUTO_ERP = 0x2 -}; - -struct hif_mib_bcn_filter_enable { - __le32 enable; - __le32 bcn_count; -} __packed; - -struct hif_mib_extended_count_table { - __le32 count_drop_plcp; - __le32 count_drop_fcs; - __le32 count_tx_frames; - __le32 count_rx_frames; - __le32 count_rx_frames_failed; - __le32 count_drop_decryption; - __le32 count_drop_tkip_mic; - __le32 count_drop_no_key; - __le32 count_tx_frames_multicast; - __le32 count_tx_frames_success; - __le32 count_tx_frames_failed; - __le32 count_tx_frames_retried; - __le32 count_tx_frames_multi_retried; - __le32 count_drop_duplicate; - __le32 count_rts_success; - __le32 count_rts_failed; - __le32 count_ack_failed; - __le32 count_rx_frames_multicast; - __le32 count_rx_frames_success; - __le32 count_drop_cmac_icv; - __le32 count_drop_cmac_replay; - __le32 count_drop_ccmp_replay; - __le32 count_drop_bip_mic; - __le32 count_rx_bcn_success; - __le32 count_rx_bcn_miss; - __le32 count_rx_bcn_dtim; - __le32 count_rx_bcn_dtim_aid0_clr; - __le32 count_rx_bcn_dtim_aid0_set; - __le32 reserved[12]; -} __packed; - -struct hif_mib_count_table { - __le32 count_drop_plcp; - __le32 count_drop_fcs; - __le32 count_tx_frames; - __le32 count_rx_frames; - __le32 count_rx_frames_failed; - __le32 count_drop_decryption; - __le32 count_drop_tkip_mic; - __le32 count_drop_no_key; - __le32 count_tx_frames_multicast; - __le32 count_tx_frames_success; - __le32 count_tx_frames_failed; - __le32 count_tx_frames_retried; - __le32 count_tx_frames_multi_retried; - __le32 count_drop_duplicate; - __le32 count_rts_success; - __le32 count_rts_failed; - __le32 count_ack_failed; - __le32 count_rx_frames_multicast; - __le32 count_rx_frames_success; - __le32 count_drop_cmac_icv; - __le32 count_drop_cmac_replay; - __le32 count_drop_ccmp_replay; - __le32 count_drop_bip_mic; -} __packed; - -struct hif_mib_mac_address { - u8 mac_addr[ETH_ALEN]; - __le16 reserved; -} __packed; - -struct hif_mib_wep_default_key_id { - u8 wep_default_key_id; - u8 reserved[3]; -} __packed; - -struct hif_mib_dot11_rts_threshold { - __le32 threshold; -} __packed; - -struct hif_mib_slot_time { - __le32 slot_time; -} __packed; - -struct hif_mib_current_tx_power_level { - __le32 power_level; /* signed value */ -} __packed; - -struct hif_mib_non_erp_protection { - u8 use_cts_to_self:1; - u8 reserved1:7; - u8 reserved2[3]; -} __packed; - -enum hif_tmplt { - HIF_TMPLT_PRBREQ = 0x0, - HIF_TMPLT_BCN = 0x1, - HIF_TMPLT_NULL = 0x2, - HIF_TMPLT_QOSNUL = 0x3, - HIF_TMPLT_PSPOLL = 0x4, - HIF_TMPLT_PRBRES = 0x5, - HIF_TMPLT_ARP = 0x6, - HIF_TMPLT_NA = 0x7 -}; - -#define HIF_API_MAX_TEMPLATE_FRAME_SIZE 700 - -struct hif_mib_template_frame { - u8 frame_type; - u8 init_rate:7; - u8 mode:1; - __le16 frame_length; - u8 frame[]; -} __packed; - -struct hif_mib_beacon_wake_up_period { - u8 wakeup_period_min; - u8 receive_dtim:1; - u8 reserved1:7; - u8 wakeup_period_max; - u8 reserved2; -} __packed; - -struct hif_mib_rcpi_rssi_threshold { - u8 detection:1; - u8 rcpi_rssi:1; - u8 upperthresh:1; - u8 lowerthresh:1; - u8 reserved:4; - u8 lower_threshold; - u8 upper_threshold; - u8 rolling_average_count; -} __packed; - -#define DEFAULT_BA_MAX_RX_BUFFER_SIZE 16 - -struct hif_mib_block_ack_policy { - u8 block_ack_tx_tid_policy; - u8 reserved1; - u8 block_ack_rx_tid_policy; - u8 block_ack_rx_max_buffer_size; -} __packed; - -enum hif_mpdu_start_spacing { - HIF_MPDU_START_SPACING_NO_RESTRIC = 0x0, - HIF_MPDU_START_SPACING_QUARTER = 0x1, - HIF_MPDU_START_SPACING_HALF = 0x2, - HIF_MPDU_START_SPACING_ONE = 0x3, - HIF_MPDU_START_SPACING_TWO = 0x4, - HIF_MPDU_START_SPACING_FOUR = 0x5, - HIF_MPDU_START_SPACING_EIGHT = 0x6, - HIF_MPDU_START_SPACING_SIXTEEN = 0x7 -}; - -struct hif_mib_set_association_mode { - u8 preambtype_use:1; - u8 mode:1; - u8 rateset:1; - u8 spacing:1; - u8 reserved1:4; - u8 short_preamble:1; - u8 reserved2:7; - u8 greenfield:1; - u8 reserved3:7; - u8 mpdu_start_spacing; - __le32 basic_rate_set; -} __packed; - -struct hif_mib_set_uapsd_information { - u8 trig_bckgrnd:1; - u8 trig_be:1; - u8 trig_video:1; - u8 trig_voice:1; - u8 reserved1:4; - u8 deliv_bckgrnd:1; - u8 deliv_be:1; - u8 deliv_video:1; - u8 deliv_voice:1; - u8 reserved2:4; - __le16 min_auto_trigger_interval; - __le16 max_auto_trigger_interval; - __le16 auto_trigger_step; -} __packed; - -struct hif_tx_rate_retry_policy { - u8 policy_index; - u8 short_retry_count; - u8 long_retry_count; - u8 first_rate_sel:2; - u8 terminate:1; - u8 count_init:1; - u8 reserved1:4; - u8 rate_recovery_count; - u8 reserved2[3]; - u8 rates[12]; -} __packed; - -#define HIF_TX_RETRY_POLICY_MAX 15 -#define HIF_TX_RETRY_POLICY_INVALID HIF_TX_RETRY_POLICY_MAX - -struct hif_mib_set_tx_rate_retry_policy { - u8 num_tx_rate_policies; - u8 reserved[3]; - struct hif_tx_rate_retry_policy tx_rate_retry_policy[]; -} __packed; - -struct hif_mib_protected_mgmt_policy { - u8 pmf_enable:1; - u8 unpmf_allowed:1; - u8 host_enc_auth_frames:1; - u8 reserved1:5; - u8 reserved2[3]; -} __packed; - -struct hif_mib_keep_alive_period { - __le16 keep_alive_period; - u8 reserved[2]; -} __packed; - -#endif diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c deleted file mode 100644 index 6963b54d5593..000000000000 --- a/drivers/staging/wfx/hif_rx.c +++ /dev/null @@ -1,416 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Handling of the chip-to-host events (aka indications) of the hardware API. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "hif_rx.h" -#include "wfx.h" -#include "scan.h" -#include "bh.h" -#include "sta.h" -#include "data_rx.h" -#include "hif_api_cmd.h" - -static int hif_generic_confirm(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - /* All confirm messages start with status */ - int status = le32_to_cpup((__le32 *)buf); - int cmd = hif->id; - int len = le16_to_cpu(hif->len) - 4; /* drop header */ - - WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error"); - - if (!wdev->hif_cmd.buf_send) { - dev_warn(wdev->dev, "unexpected confirmation: 0x%.2x\n", cmd); - return -EINVAL; - } - - if (cmd != wdev->hif_cmd.buf_send->id) { - dev_warn(wdev->dev, - "chip response mismatch request: 0x%.2x vs 0x%.2x\n", - cmd, wdev->hif_cmd.buf_send->id); - return -EINVAL; - } - - if (wdev->hif_cmd.buf_recv) { - if (wdev->hif_cmd.len_recv >= len && len > 0) - memcpy(wdev->hif_cmd.buf_recv, buf, len); - else - status = -EIO; - } - wdev->hif_cmd.ret = status; - - complete(&wdev->hif_cmd.done); - return status; -} - -static int hif_tx_confirm(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - const struct hif_cnf_tx *body = buf; - - wfx_tx_confirm_cb(wdev, body); - return 0; -} - -static int hif_multi_tx_confirm(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - const struct hif_cnf_multi_transmit *body = buf; - int i; - - WARN(body->num_tx_confs <= 0, "corrupted message"); - for (i = 0; i < body->num_tx_confs; i++) - wfx_tx_confirm_cb(wdev, &body->tx_conf_payload[i]); - return 0; -} - -static int hif_startup_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - const struct hif_ind_startup *body = buf; - - if (body->status || body->firmware_type > 4) { - dev_err(wdev->dev, "received invalid startup indication"); - return -EINVAL; - } - memcpy(&wdev->hw_caps, body, sizeof(struct hif_ind_startup)); - le16_to_cpus((__le16 *)&wdev->hw_caps.hardware_id); - le16_to_cpus((__le16 *)&wdev->hw_caps.num_inp_ch_bufs); - le16_to_cpus((__le16 *)&wdev->hw_caps.size_inp_ch_buf); - le32_to_cpus((__le32 *)&wdev->hw_caps.supported_rate_mask); - - complete(&wdev->firmware_ready); - return 0; -} - -static int hif_wakeup_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - if (!wdev->pdata.gpio_wakeup || - gpiod_get_value(wdev->pdata.gpio_wakeup) == 0) { - dev_warn(wdev->dev, "unexpected wake-up indication\n"); - return -EIO; - } - return 0; -} - -static int hif_receive_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, - const void *buf, struct sk_buff *skb) -{ - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - const struct hif_ind_rx *body = buf; - - if (!wvif) { - dev_warn(wdev->dev, "%s: ignore rx data for non-existent vif %d\n", - __func__, hif->interface); - return -EIO; - } - skb_pull(skb, sizeof(struct hif_msg) + sizeof(struct hif_ind_rx)); - wfx_rx_cb(wvif, body, skb); - - return 0; -} - -static int hif_event_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - const struct hif_ind_event *body = buf; - int type = le32_to_cpu(body->event_id); - - if (!wvif) { - dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); - return -EIO; - } - - switch (type) { - case HIF_EVENT_IND_RCPI_RSSI: - wfx_event_report_rssi(wvif, body->event_data.rcpi_rssi); - break; - case HIF_EVENT_IND_BSSLOST: - schedule_delayed_work(&wvif->beacon_loss_work, 0); - break; - case HIF_EVENT_IND_BSSREGAINED: - cancel_delayed_work(&wvif->beacon_loss_work); - dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n"); - break; - case HIF_EVENT_IND_PS_MODE_ERROR: - dev_warn(wdev->dev, "error while processing power save request: %d\n", - le32_to_cpu(body->event_data.ps_mode_error)); - break; - default: - dev_warn(wdev->dev, "unhandled event indication: %.2x\n", - type); - break; - } - return 0; -} - -static int hif_pm_mode_complete_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, - const void *buf) -{ - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - - if (!wvif) { - dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); - return -EIO; - } - complete(&wvif->set_pm_mode_complete); - - return 0; -} - -static int hif_scan_complete_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, - const void *buf) -{ - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - const struct hif_ind_scan_cmpl *body = buf; - - if (!wvif) { - dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); - return -EIO; - } - - wfx_scan_complete(wvif, body->num_channels_completed); - - return 0; -} - -static int hif_join_complete_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, - const void *buf) -{ - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - - if (!wvif) { - dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); - return -EIO; - } - dev_warn(wdev->dev, "unattended JoinCompleteInd\n"); - - return 0; -} - -static int hif_suspend_resume_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, - const void *buf) -{ - const struct hif_ind_suspend_resume_tx *body = buf; - struct wfx_vif *wvif; - - if (body->bc_mc_only) { - wvif = wdev_to_wvif(wdev, hif->interface); - if (!wvif) { - dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); - return -EIO; - } - if (body->resume) - wfx_suspend_resume_mc(wvif, STA_NOTIFY_AWAKE); - else - wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP); - } else { - WARN(body->peer_sta_set, "misunderstood indication"); - WARN(hif->interface != 2, "misunderstood indication"); - if (body->resume) - wfx_suspend_hot_dev(wdev, STA_NOTIFY_AWAKE); - else - wfx_suspend_hot_dev(wdev, STA_NOTIFY_SLEEP); - } - - return 0; -} - -static int hif_generic_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - const struct hif_ind_generic *body = buf; - int type = le32_to_cpu(body->type); - - switch (type) { - case HIF_GENERIC_INDICATION_TYPE_RAW: - return 0; - case HIF_GENERIC_INDICATION_TYPE_STRING: - dev_info(wdev->dev, "firmware says: %s\n", (char *)&body->data); - return 0; - case HIF_GENERIC_INDICATION_TYPE_RX_STATS: - mutex_lock(&wdev->rx_stats_lock); - /* Older firmware send a generic indication beside RxStats */ - if (!wfx_api_older_than(wdev, 1, 4)) - dev_info(wdev->dev, "Rx test ongoing. Temperature: %d degrees C\n", - body->data.rx_stats.current_temp); - memcpy(&wdev->rx_stats, &body->data.rx_stats, - sizeof(wdev->rx_stats)); - mutex_unlock(&wdev->rx_stats_lock); - return 0; - case HIF_GENERIC_INDICATION_TYPE_TX_POWER_LOOP_INFO: - mutex_lock(&wdev->tx_power_loop_info_lock); - memcpy(&wdev->tx_power_loop_info, - &body->data.tx_power_loop_info, - sizeof(wdev->tx_power_loop_info)); - mutex_unlock(&wdev->tx_power_loop_info_lock); - return 0; - default: - dev_err(wdev->dev, "generic_indication: unknown indication type: %#.8x\n", - type); - return -EIO; - } -} - -static const struct { - int val; - const char *str; - bool has_param; -} hif_errors[] = { - { HIF_ERROR_FIRMWARE_ROLLBACK, - "rollback status" }, - { HIF_ERROR_FIRMWARE_DEBUG_ENABLED, - "debug feature enabled" }, - { HIF_ERROR_PDS_PAYLOAD, - "PDS version is not supported" }, - { HIF_ERROR_PDS_TESTFEATURE, - "PDS ask for an unknown test mode" }, - { HIF_ERROR_OOR_VOLTAGE, - "out-of-range power supply voltage", true }, - { HIF_ERROR_OOR_TEMPERATURE, - "out-of-range temperature", true }, - { HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE, - "secure link does not expect request during key exchange" }, - { HIF_ERROR_SLK_SESSION_KEY, - "secure link session key is invalid" }, - { HIF_ERROR_SLK_OVERFLOW, - "secure link overflow" }, - { HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE, - "secure link messages list does not match message encryption" }, - { HIF_ERROR_SLK_UNCONFIGURED, - "secure link not yet configured" }, - { HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW, - "bus clock is too slow (<1kHz)" }, - { HIF_ERROR_HIF_RX_DATA_TOO_LARGE, - "HIF message too large" }, - /* Following errors only exists in old firmware versions: */ - { HIF_ERROR_HIF_TX_QUEUE_FULL, - "HIF messages queue is full" }, - { HIF_ERROR_HIF_BUS, - "HIF bus" }, - { HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED, - "secure link does not support multi-tx confirmations" }, - { HIF_ERROR_SLK_OUTDATED_SESSION_KEY, - "secure link session key is outdated" }, - { HIF_ERROR_SLK_DECRYPTION, - "secure link params (nonce or tag) mismatch" }, -}; - -static int hif_error_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - const struct hif_ind_error *body = buf; - int type = le32_to_cpu(body->type); - int param = (s8)body->data[0]; - int i; - - for (i = 0; i < ARRAY_SIZE(hif_errors); i++) - if (type == hif_errors[i].val) - break; - if (i < ARRAY_SIZE(hif_errors)) - if (hif_errors[i].has_param) - dev_err(wdev->dev, "asynchronous error: %s: %d\n", - hif_errors[i].str, param); - else - dev_err(wdev->dev, "asynchronous error: %s\n", - hif_errors[i].str); - else - dev_err(wdev->dev, "asynchronous error: unknown: %08x\n", type); - print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, - 16, 1, hif, le16_to_cpu(hif->len), false); - wdev->chip_frozen = true; - - return 0; -}; - -static int hif_exception_indication(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf) -{ - const struct hif_ind_exception *body = buf; - int type = le32_to_cpu(body->type); - - if (type == 4) - dev_err(wdev->dev, "firmware assert %d\n", - le32_to_cpup((__le32 *)body->data)); - else - dev_err(wdev->dev, "firmware exception\n"); - print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, - 16, 1, hif, le16_to_cpu(hif->len), false); - wdev->chip_frozen = true; - - return -1; -} - -static const struct { - int msg_id; - int (*handler)(struct wfx_dev *wdev, - const struct hif_msg *hif, const void *buf); -} hif_handlers[] = { - /* Confirmations */ - { HIF_CNF_ID_TX, hif_tx_confirm }, - { HIF_CNF_ID_MULTI_TRANSMIT, hif_multi_tx_confirm }, - /* Indications */ - { HIF_IND_ID_STARTUP, hif_startup_indication }, - { HIF_IND_ID_WAKEUP, hif_wakeup_indication }, - { HIF_IND_ID_JOIN_COMPLETE, hif_join_complete_indication }, - { HIF_IND_ID_SET_PM_MODE_CMPL, hif_pm_mode_complete_indication }, - { HIF_IND_ID_SCAN_CMPL, hif_scan_complete_indication }, - { HIF_IND_ID_SUSPEND_RESUME_TX, hif_suspend_resume_indication }, - { HIF_IND_ID_EVENT, hif_event_indication }, - { HIF_IND_ID_GENERIC, hif_generic_indication }, - { HIF_IND_ID_ERROR, hif_error_indication }, - { HIF_IND_ID_EXCEPTION, hif_exception_indication }, - /* FIXME: allocate skb_p from hif_receive_indication and make it generic */ - //{ HIF_IND_ID_RX, hif_receive_indication }, -}; - -void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb) -{ - int i; - const struct hif_msg *hif = (const struct hif_msg *)skb->data; - int hif_id = hif->id; - - if (hif_id == HIF_IND_ID_RX) { - /* hif_receive_indication take care of skb lifetime */ - hif_receive_indication(wdev, hif, hif->body, skb); - return; - } - /* Note: mutex_is_lock cause an implicit memory barrier that protect - * buf_send - */ - if (mutex_is_locked(&wdev->hif_cmd.lock) && - wdev->hif_cmd.buf_send && - wdev->hif_cmd.buf_send->id == hif_id) { - hif_generic_confirm(wdev, hif, hif->body); - goto free; - } - for (i = 0; i < ARRAY_SIZE(hif_handlers); i++) { - if (hif_handlers[i].msg_id == hif_id) { - if (hif_handlers[i].handler) - hif_handlers[i].handler(wdev, hif, hif->body); - goto free; - } - } - if (hif_id & 0x80) - dev_err(wdev->dev, "unsupported HIF indication: ID %02x\n", - hif_id); - else - dev_err(wdev->dev, "unexpected HIF confirmation: ID %02x\n", - hif_id); -free: - dev_kfree_skb(skb); -} diff --git a/drivers/staging/wfx/hif_rx.h b/drivers/staging/wfx/hif_rx.h deleted file mode 100644 index 96543b81fa77..000000000000 --- a/drivers/staging/wfx/hif_rx.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Handling of the chip-to-host events (aka indications) of the hardware API. - * - * Copyright (c) 2017-2019, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - * Copyright (C) 2010, ST-Ericsson SA - */ -#ifndef WFX_HIF_RX_H -#define WFX_HIF_RX_H - -struct wfx_dev; -struct sk_buff; - -void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb); - -#endif diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c deleted file mode 100644 index 2fd8bbd36e25..000000000000 --- a/drivers/staging/wfx/hif_tx.c +++ /dev/null @@ -1,513 +0,0 @@ -// 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(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/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h deleted file mode 100644 index e57eabdcfa77..000000000000 --- a/drivers/staging/wfx/hif_tx.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 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/staging/wfx/hif_tx_mib.c b/drivers/staging/wfx/hif_tx_mib.c deleted file mode 100644 index 97e961e6bcf6..000000000000 --- a/drivers/staging/wfx/hif_tx_mib.c +++ /dev/null @@ -1,324 +0,0 @@ -// 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/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h deleted file mode 100644 index 2a3b84868ee4..000000000000 --- a/drivers/staging/wfx/hif_tx_mib.h +++ /dev/null @@ -1,49 +0,0 @@ -/* 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 diff --git a/drivers/staging/wfx/hwio.c b/drivers/staging/wfx/hwio.c deleted file mode 100644 index 30eb888830d2..000000000000 --- a/drivers/staging/wfx/hwio.c +++ /dev/null @@ -1,352 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Low-level I/O functions. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include -#include - -#include "hwio.h" -#include "wfx.h" -#include "bus.h" -#include "traces.h" - -/* - * Internal helpers. - * - * About CONFIG_VMAP_STACK: - * When CONFIG_VMAP_STACK is enabled, it is not possible to run DMA on stack - * allocated data. Functions below that work with registers (aka functions - * ending with "32") automatically reallocate buffers with kmalloc. However, - * functions that work with arbitrary length buffers let's caller to handle - * memory location. In doubt, enable CONFIG_DEBUG_SG to detect badly located - * buffer. - */ - -static int read32(struct wfx_dev *wdev, int reg, u32 *val) -{ - int ret; - __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); - - *val = ~0; /* Never return undefined value */ - if (!tmp) - return -ENOMEM; - ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp, - sizeof(u32)); - if (ret >= 0) - *val = le32_to_cpu(*tmp); - kfree(tmp); - if (ret) - dev_err(wdev->dev, "%s: bus communication error: %d\n", - __func__, ret); - return ret; -} - -static int write32(struct wfx_dev *wdev, int reg, u32 val) -{ - int ret; - __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); - - if (!tmp) - return -ENOMEM; - *tmp = cpu_to_le32(val); - ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp, - sizeof(u32)); - kfree(tmp); - if (ret) - dev_err(wdev->dev, "%s: bus communication error: %d\n", - __func__, ret); - return ret; -} - -static int read32_locked(struct wfx_dev *wdev, int reg, u32 *val) -{ - int ret; - - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = read32(wdev, reg, val); - _trace_io_read32(reg, *val); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - return ret; -} - -static int write32_locked(struct wfx_dev *wdev, int reg, u32 val) -{ - int ret; - - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = write32(wdev, reg, val); - _trace_io_write32(reg, val); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - return ret; -} - -static int write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val) -{ - int ret; - u32 val_r, val_w; - - WARN_ON(~mask & val); - val &= mask; - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = read32(wdev, reg, &val_r); - _trace_io_read32(reg, val_r); - if (ret < 0) - goto err; - val_w = (val_r & ~mask) | val; - if (val_w != val_r) { - ret = write32(wdev, reg, val_w); - _trace_io_write32(reg, val_w); - } -err: - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - return ret; -} - -static int indirect_read(struct wfx_dev *wdev, int reg, u32 addr, - void *buf, size_t len) -{ - int ret; - int i; - u32 cfg; - u32 prefetch; - - WARN_ON(len >= 0x2000); - WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT); - - if (reg == WFX_REG_AHB_DPORT) - prefetch = CFG_PREFETCH_AHB; - else if (reg == WFX_REG_SRAM_DPORT) - prefetch = CFG_PREFETCH_SRAM; - else - return -ENODEV; - - ret = write32(wdev, WFX_REG_BASE_ADDR, addr); - if (ret < 0) - goto err; - - ret = read32(wdev, WFX_REG_CONFIG, &cfg); - if (ret < 0) - goto err; - - ret = write32(wdev, WFX_REG_CONFIG, cfg | prefetch); - if (ret < 0) - goto err; - - for (i = 0; i < 20; i++) { - ret = read32(wdev, WFX_REG_CONFIG, &cfg); - if (ret < 0) - goto err; - if (!(cfg & prefetch)) - break; - usleep_range(200, 250); - } - if (i == 20) { - ret = -ETIMEDOUT; - goto err; - } - - ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len); - -err: - if (ret < 0) - memset(buf, 0xFF, len); /* Never return undefined value */ - return ret; -} - -static int indirect_write(struct wfx_dev *wdev, int reg, u32 addr, - const void *buf, size_t len) -{ - int ret; - - WARN_ON(len >= 0x2000); - WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT); - ret = write32(wdev, WFX_REG_BASE_ADDR, addr); - if (ret < 0) - return ret; - - return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len); -} - -static int indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr, - void *buf, size_t len) -{ - int ret; - - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = indirect_read(wdev, reg, addr, buf, len); - _trace_io_ind_read(reg, addr, buf, len); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - return ret; -} - -static int indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr, - const void *buf, size_t len) -{ - int ret; - - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = indirect_write(wdev, reg, addr, buf, len); - _trace_io_ind_write(reg, addr, buf, len); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - return ret; -} - -static int indirect_read32_locked(struct wfx_dev *wdev, int reg, - u32 addr, u32 *val) -{ - int ret; - __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); - - if (!tmp) - return -ENOMEM; - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = indirect_read(wdev, reg, addr, tmp, sizeof(u32)); - *val = le32_to_cpu(*tmp); - _trace_io_ind_read32(reg, addr, *val); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - kfree(tmp); - return ret; -} - -static int indirect_write32_locked(struct wfx_dev *wdev, int reg, - u32 addr, u32 val) -{ - int ret; - __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL); - - if (!tmp) - return -ENOMEM; - *tmp = cpu_to_le32(val); - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = indirect_write(wdev, reg, addr, tmp, sizeof(u32)); - _trace_io_ind_write32(reg, addr, val); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - kfree(tmp); - return ret; -} - -int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len) -{ - int ret; - - WARN((long)buf & 3, "%s: unaligned buffer", __func__); - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, - WFX_REG_IN_OUT_QUEUE, buf, len); - _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - if (ret) - dev_err(wdev->dev, "%s: bus communication error: %d\n", - __func__, ret); - return ret; -} - -int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len) -{ - int ret; - - WARN((long)buf & 3, "%s: unaligned buffer", __func__); - wdev->hwbus_ops->lock(wdev->hwbus_priv); - ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, - WFX_REG_IN_OUT_QUEUE, buf, len); - _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len); - wdev->hwbus_ops->unlock(wdev->hwbus_priv); - if (ret) - dev_err(wdev->dev, "%s: bus communication error: %d\n", - __func__, ret); - return ret; -} - -int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len) -{ - return indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len); -} - -int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len) -{ - return indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len); -} - -int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len) -{ - return indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len); -} - -int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len) -{ - return indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len); -} - -int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val) -{ - return indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val); -} - -int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val) -{ - return indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val); -} - -int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val) -{ - return indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val); -} - -int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val) -{ - return indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val); -} - -int config_reg_read(struct wfx_dev *wdev, u32 *val) -{ - return read32_locked(wdev, WFX_REG_CONFIG, val); -} - -int config_reg_write(struct wfx_dev *wdev, u32 val) -{ - return write32_locked(wdev, WFX_REG_CONFIG, val); -} - -int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val) -{ - return write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val); -} - -int control_reg_read(struct wfx_dev *wdev, u32 *val) -{ - return read32_locked(wdev, WFX_REG_CONTROL, val); -} - -int control_reg_write(struct wfx_dev *wdev, u32 val) -{ - return write32_locked(wdev, WFX_REG_CONTROL, val); -} - -int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val) -{ - return write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val); -} - -int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val) -{ - int ret; - - *val = ~0; /* Never return undefined value */ - ret = write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24); - if (ret) - return ret; - ret = read32_locked(wdev, WFX_REG_SET_GEN_R_W, val); - if (ret) - return ret; - *val &= IGPR_VALUE; - return ret; -} - -int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val) -{ - return write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val); -} diff --git a/drivers/staging/wfx/hwio.h b/drivers/staging/wfx/hwio.h deleted file mode 100644 index ff09575dd1af..000000000000 --- a/drivers/staging/wfx/hwio.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Low-level I/O functions. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_HWIO_H -#define WFX_HWIO_H - -#include - -struct wfx_dev; - -int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t buf_len); -int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t buf_len); - -int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len); -int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len); - -int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len); -int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len); - -int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val); -int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val); - -int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val); -int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val); - -#define CFG_ERR_SPI_FRAME 0x00000001 /* only with SPI */ -#define CFG_ERR_SDIO_BUF_MISMATCH 0x00000001 /* only with SDIO */ -#define CFG_ERR_BUF_UNDERRUN 0x00000002 -#define CFG_ERR_DATA_IN_TOO_LARGE 0x00000004 -#define CFG_ERR_HOST_NO_OUT_QUEUE 0x00000008 -#define CFG_ERR_BUF_OVERRUN 0x00000010 -#define CFG_ERR_DATA_OUT_TOO_LARGE 0x00000020 -#define CFG_ERR_HOST_NO_IN_QUEUE 0x00000040 -#define CFG_ERR_HOST_CRC_MISS 0x00000080 /* only with SDIO */ -#define CFG_SPI_IGNORE_CS 0x00000080 /* only with SPI */ -#define CFG_BYTE_ORDER_MASK 0x00000300 /* only writable with SPI */ -#define CFG_BYTE_ORDER_BADC 0x00000000 -#define CFG_BYTE_ORDER_DCBA 0x00000100 -#define CFG_BYTE_ORDER_ABCD 0x00000200 /* SDIO always use this value */ -#define CFG_DIRECT_ACCESS_MODE 0x00000400 -#define CFG_PREFETCH_AHB 0x00000800 -#define CFG_DISABLE_CPU_CLK 0x00001000 -#define CFG_PREFETCH_SRAM 0x00002000 -#define CFG_CPU_RESET 0x00004000 -#define CFG_SDIO_DISABLE_IRQ 0x00008000 /* only with SDIO */ -#define CFG_IRQ_ENABLE_DATA 0x00010000 -#define CFG_IRQ_ENABLE_WRDY 0x00020000 -#define CFG_CLK_RISE_EDGE 0x00040000 -#define CFG_SDIO_DISABLE_CRC_CHK 0x00080000 /* only with SDIO */ -#define CFG_RESERVED 0x00F00000 -#define CFG_DEVICE_ID_MAJOR 0x07000000 -#define CFG_DEVICE_ID_RESERVED 0x78000000 -#define CFG_DEVICE_ID_TYPE 0x80000000 -int config_reg_read(struct wfx_dev *wdev, u32 *val); -int config_reg_write(struct wfx_dev *wdev, u32 val); -int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val); - -#define CTRL_NEXT_LEN_MASK 0x00000FFF -#define CTRL_WLAN_WAKEUP 0x00001000 -#define CTRL_WLAN_READY 0x00002000 -int control_reg_read(struct wfx_dev *wdev, u32 *val); -int control_reg_write(struct wfx_dev *wdev, u32 val); -int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val); - -#define IGPR_RW 0x80000000 -#define IGPR_INDEX 0x7F000000 -#define IGPR_VALUE 0x00FFFFFF -int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val); -int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val); - -#endif diff --git a/drivers/staging/wfx/key.c b/drivers/staging/wfx/key.c deleted file mode 100644 index 65134a174683..000000000000 --- a/drivers/staging/wfx/key.c +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Key management related functions. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "key.h" -#include "wfx.h" -#include "hif_tx_mib.h" - -static int wfx_alloc_key(struct wfx_dev *wdev) -{ - int idx; - - idx = ffs(~wdev->key_map) - 1; - if (idx < 0 || idx >= MAX_KEY_ENTRIES) - return -1; - - wdev->key_map |= BIT(idx); - return idx; -} - -static void wfx_free_key(struct wfx_dev *wdev, int idx) -{ - WARN(!(wdev->key_map & BIT(idx)), "inconsistent key allocation"); - wdev->key_map &= ~BIT(idx); -} - -static u8 fill_wep_pair(struct hif_wep_pairwise_key *msg, - struct ieee80211_key_conf *key, u8 *peer_addr) -{ - WARN(key->keylen > sizeof(msg->key_data), "inconsistent data"); - msg->key_length = key->keylen; - memcpy(msg->key_data, key->key, key->keylen); - ether_addr_copy(msg->peer_address, peer_addr); - return HIF_KEY_TYPE_WEP_PAIRWISE; -} - -static u8 fill_wep_group(struct hif_wep_group_key *msg, - struct ieee80211_key_conf *key) -{ - WARN(key->keylen > sizeof(msg->key_data), "inconsistent data"); - msg->key_id = key->keyidx; - msg->key_length = key->keylen; - memcpy(msg->key_data, key->key, key->keylen); - return HIF_KEY_TYPE_WEP_DEFAULT; -} - -static u8 fill_tkip_pair(struct hif_tkip_pairwise_key *msg, - struct ieee80211_key_conf *key, u8 *peer_addr) -{ - u8 *keybuf = key->key; - - WARN(key->keylen != sizeof(msg->tkip_key_data) - + sizeof(msg->tx_mic_key) - + sizeof(msg->rx_mic_key), "inconsistent data"); - memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data)); - keybuf += sizeof(msg->tkip_key_data); - memcpy(msg->tx_mic_key, keybuf, sizeof(msg->tx_mic_key)); - keybuf += sizeof(msg->tx_mic_key); - memcpy(msg->rx_mic_key, keybuf, sizeof(msg->rx_mic_key)); - ether_addr_copy(msg->peer_address, peer_addr); - return HIF_KEY_TYPE_TKIP_PAIRWISE; -} - -static u8 fill_tkip_group(struct hif_tkip_group_key *msg, - struct ieee80211_key_conf *key, - struct ieee80211_key_seq *seq, - enum nl80211_iftype iftype) -{ - u8 *keybuf = key->key; - - WARN(key->keylen != sizeof(msg->tkip_key_data) - + 2 * sizeof(msg->rx_mic_key), "inconsistent data"); - msg->key_id = key->keyidx; - memcpy(msg->rx_sequence_counter, - &seq->tkip.iv16, sizeof(seq->tkip.iv16)); - memcpy(msg->rx_sequence_counter + sizeof(u16), - &seq->tkip.iv32, sizeof(seq->tkip.iv32)); - memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data)); - keybuf += sizeof(msg->tkip_key_data); - if (iftype == NL80211_IFTYPE_AP) - /* Use Tx MIC Key */ - memcpy(msg->rx_mic_key, keybuf + 0, sizeof(msg->rx_mic_key)); - else - /* Use Rx MIC Key */ - memcpy(msg->rx_mic_key, keybuf + 8, sizeof(msg->rx_mic_key)); - return HIF_KEY_TYPE_TKIP_GROUP; -} - -static u8 fill_ccmp_pair(struct hif_aes_pairwise_key *msg, - struct ieee80211_key_conf *key, u8 *peer_addr) -{ - WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data"); - ether_addr_copy(msg->peer_address, peer_addr); - memcpy(msg->aes_key_data, key->key, key->keylen); - return HIF_KEY_TYPE_AES_PAIRWISE; -} - -static u8 fill_ccmp_group(struct hif_aes_group_key *msg, - struct ieee80211_key_conf *key, - struct ieee80211_key_seq *seq) -{ - WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data"); - memcpy(msg->aes_key_data, key->key, key->keylen); - memcpy(msg->rx_sequence_counter, seq->ccmp.pn, sizeof(seq->ccmp.pn)); - memreverse(msg->rx_sequence_counter, sizeof(seq->ccmp.pn)); - msg->key_id = key->keyidx; - return HIF_KEY_TYPE_AES_GROUP; -} - -static u8 fill_sms4_pair(struct hif_wapi_pairwise_key *msg, - struct ieee80211_key_conf *key, u8 *peer_addr) -{ - u8 *keybuf = key->key; - - WARN(key->keylen != sizeof(msg->wapi_key_data) - + sizeof(msg->mic_key_data), "inconsistent data"); - ether_addr_copy(msg->peer_address, peer_addr); - memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data)); - keybuf += sizeof(msg->wapi_key_data); - memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data)); - msg->key_id = key->keyidx; - return HIF_KEY_TYPE_WAPI_PAIRWISE; -} - -static u8 fill_sms4_group(struct hif_wapi_group_key *msg, - struct ieee80211_key_conf *key) -{ - u8 *keybuf = key->key; - - WARN(key->keylen != sizeof(msg->wapi_key_data) - + sizeof(msg->mic_key_data), "inconsistent data"); - memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data)); - keybuf += sizeof(msg->wapi_key_data); - memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data)); - msg->key_id = key->keyidx; - return HIF_KEY_TYPE_WAPI_GROUP; -} - -static u8 fill_aes_cmac_group(struct hif_igtk_group_key *msg, - struct ieee80211_key_conf *key, - struct ieee80211_key_seq *seq) -{ - WARN(key->keylen != sizeof(msg->igtk_key_data), "inconsistent data"); - memcpy(msg->igtk_key_data, key->key, key->keylen); - memcpy(msg->ipn, seq->aes_cmac.pn, sizeof(seq->aes_cmac.pn)); - memreverse(msg->ipn, sizeof(seq->aes_cmac.pn)); - msg->key_id = key->keyidx; - return HIF_KEY_TYPE_IGTK_GROUP; -} - -static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - int ret; - struct hif_req_add_key k = { }; - struct ieee80211_key_seq seq; - struct wfx_dev *wdev = wvif->wdev; - int idx = wfx_alloc_key(wvif->wdev); - bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE; - - WARN(key->flags & IEEE80211_KEY_FLAG_PAIRWISE && !sta, "inconsistent data"); - ieee80211_get_key_rx_seq(key, 0, &seq); - if (idx < 0) - return -EINVAL; - k.int_id = wvif->id; - k.entry_index = idx; - if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || - key->cipher == WLAN_CIPHER_SUITE_WEP104) { - if (pairwise) - k.type = fill_wep_pair(&k.key.wep_pairwise_key, key, - sta->addr); - else - k.type = fill_wep_group(&k.key.wep_group_key, key); - } else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { - if (pairwise) - k.type = fill_tkip_pair(&k.key.tkip_pairwise_key, key, - sta->addr); - else - k.type = fill_tkip_group(&k.key.tkip_group_key, key, - &seq, wvif->vif->type); - } else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) { - if (pairwise) - k.type = fill_ccmp_pair(&k.key.aes_pairwise_key, key, - sta->addr); - else - k.type = fill_ccmp_group(&k.key.aes_group_key, key, - &seq); - } else if (key->cipher == WLAN_CIPHER_SUITE_SMS4) { - if (pairwise) - k.type = fill_sms4_pair(&k.key.wapi_pairwise_key, key, - sta->addr); - else - k.type = fill_sms4_group(&k.key.wapi_group_key, key); - } else if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { - k.type = fill_aes_cmac_group(&k.key.igtk_group_key, key, &seq); - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; - } else { - dev_warn(wdev->dev, "unsupported key type %d\n", key->cipher); - wfx_free_key(wdev, idx); - return -EOPNOTSUPP; - } - ret = hif_add_key(wdev, &k); - if (ret) { - wfx_free_key(wdev, idx); - return -EOPNOTSUPP; - } - key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE | - IEEE80211_KEY_FLAG_RESERVE_TAILROOM; - key->hw_key_idx = idx; - return 0; -} - -static int wfx_remove_key(struct wfx_vif *wvif, struct ieee80211_key_conf *key) -{ - WARN(key->hw_key_idx >= MAX_KEY_ENTRIES, "corrupted hw_key_idx"); - wfx_free_key(wvif->wdev, key->hw_key_idx); - return hif_remove_key(wvif->wdev, key->hw_key_idx); -} - -int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - int ret = -EOPNOTSUPP; - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - mutex_lock(&wvif->wdev->conf_mutex); - if (cmd == SET_KEY) - ret = wfx_add_key(wvif, sta, key); - if (cmd == DISABLE_KEY) - ret = wfx_remove_key(wvif, key); - mutex_unlock(&wvif->wdev->conf_mutex); - return ret; -} - diff --git a/drivers/staging/wfx/key.h b/drivers/staging/wfx/key.h deleted file mode 100644 index 2d135eff7af2..000000000000 --- a/drivers/staging/wfx/key.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Key management related functions. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_KEY_H -#define WFX_KEY_H - -#include - -struct wfx_dev; -struct wfx_vif; - -int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); - -#endif diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c deleted file mode 100644 index 858d778cc589..000000000000 --- a/drivers/staging/wfx/main.c +++ /dev/null @@ -1,506 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Device probe and register. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - * Copyright (c) 2008, Johannes Berg - * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). - * Copyright (c) 2007-2009, Christian Lamparter - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2004-2006 Jean-Baptiste Note , et al. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" -#include "wfx.h" -#include "fwio.h" -#include "hwio.h" -#include "bus.h" -#include "bh.h" -#include "sta.h" -#include "key.h" -#include "scan.h" -#include "debug.h" -#include "data_tx.h" -#include "hif_tx_mib.h" -#include "hif_api_cmd.h" - -#define WFX_PDS_MAX_SIZE 1500 - -MODULE_DESCRIPTION("Silicon Labs 802.11 Wireless LAN driver for WF200"); -MODULE_AUTHOR("Jérôme Pouiller "); -MODULE_LICENSE("GPL"); - -#define RATETAB_ENT(_rate, _rateid, _flags) { \ - .bitrate = (_rate), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ -} - -static struct ieee80211_rate wfx_rates[] = { - RATETAB_ENT(10, 0, 0), - RATETAB_ENT(20, 1, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(55, 2, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(110, 3, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(60, 6, 0), - RATETAB_ENT(90, 7, 0), - RATETAB_ENT(120, 8, 0), - RATETAB_ENT(180, 9, 0), - RATETAB_ENT(240, 10, 0), - RATETAB_ENT(360, 11, 0), - RATETAB_ENT(480, 12, 0), - RATETAB_ENT(540, 13, 0), -}; - -#define CHAN2G(_channel, _freq, _flags) { \ - .band = NL80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -static struct ieee80211_channel wfx_2ghz_chantable[] = { - CHAN2G(1, 2412, 0), - CHAN2G(2, 2417, 0), - CHAN2G(3, 2422, 0), - CHAN2G(4, 2427, 0), - CHAN2G(5, 2432, 0), - CHAN2G(6, 2437, 0), - CHAN2G(7, 2442, 0), - CHAN2G(8, 2447, 0), - CHAN2G(9, 2452, 0), - CHAN2G(10, 2457, 0), - CHAN2G(11, 2462, 0), - CHAN2G(12, 2467, 0), - CHAN2G(13, 2472, 0), - CHAN2G(14, 2484, 0), -}; - -static const struct ieee80211_supported_band wfx_band_2ghz = { - .channels = wfx_2ghz_chantable, - .n_channels = ARRAY_SIZE(wfx_2ghz_chantable), - .bitrates = wfx_rates, - .n_bitrates = ARRAY_SIZE(wfx_rates), - .ht_cap = { - /* Receive caps */ - .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_MAX_AMSDU | - (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), - .ht_supported = 1, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, - .mcs = { - .rx_mask = { 0xFF }, /* MCS0 to MCS7 */ - .rx_highest = cpu_to_le16(72), - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, - }, - }, -}; - -static const struct ieee80211_iface_limit wdev_iface_limits[] = { - { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) }, - { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, -}; - -static const struct ieee80211_iface_combination wfx_iface_combinations[] = { - { - .num_different_channels = 2, - .max_interfaces = 2, - .limits = wdev_iface_limits, - .n_limits = ARRAY_SIZE(wdev_iface_limits), - } -}; - -static const struct ieee80211_ops wfx_ops = { - .start = wfx_start, - .stop = wfx_stop, - .add_interface = wfx_add_interface, - .remove_interface = wfx_remove_interface, - .config = wfx_config, - .tx = wfx_tx, - .join_ibss = wfx_join_ibss, - .leave_ibss = wfx_leave_ibss, - .conf_tx = wfx_conf_tx, - .hw_scan = wfx_hw_scan, - .cancel_hw_scan = wfx_cancel_hw_scan, - .start_ap = wfx_start_ap, - .stop_ap = wfx_stop_ap, - .sta_add = wfx_sta_add, - .sta_remove = wfx_sta_remove, - .set_tim = wfx_set_tim, - .set_key = wfx_set_key, - .set_rts_threshold = wfx_set_rts_threshold, - .set_default_unicast_key = wfx_set_default_unicast_key, - .bss_info_changed = wfx_bss_info_changed, - .configure_filter = wfx_configure_filter, - .ampdu_action = wfx_ampdu_action, - .flush = wfx_flush, - .add_chanctx = wfx_add_chanctx, - .remove_chanctx = wfx_remove_chanctx, - .change_chanctx = wfx_change_chanctx, - .assign_vif_chanctx = wfx_assign_vif_chanctx, - .unassign_vif_chanctx = wfx_unassign_vif_chanctx, -}; - -bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor) -{ - if (wdev->hw_caps.api_version_major < major) - return true; - if (wdev->hw_caps.api_version_major > major) - return false; - if (wdev->hw_caps.api_version_minor < minor) - return true; - return false; -} - -/* The device needs data about the antenna configuration. This information in - * provided by PDS (Platform Data Set, this is the wording used in WF200 - * documentation) files. For hardware integrators, the full process to create - * PDS files is described here: - * https:github.com/SiliconLabs/wfx-firmware/blob/master/PDS/README.md - * - * So this function aims to send PDS to the device. However, the PDS file is - * often bigger than Rx buffers of the chip, so it has to be sent in multiple - * parts. - * - * In add, the PDS data cannot be split anywhere. The PDS files contains tree - * structures. Braces are used to enter/leave a level of the tree (in a JSON - * fashion). PDS files can only been split between root nodes. - */ -int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len) -{ - int ret; - int start, brace_level, i; - - start = 0; - brace_level = 0; - if (buf[0] != '{') { - dev_err(wdev->dev, "valid PDS start with '{'. Did you forget to compress it?\n"); - return -EINVAL; - } - for (i = 1; i < len - 1; i++) { - if (buf[i] == '{') - brace_level++; - if (buf[i] == '}') - brace_level--; - if (buf[i] == '}' && !brace_level) { - i++; - if (i - start + 1 > WFX_PDS_MAX_SIZE) - return -EFBIG; - buf[start] = '{'; - buf[i] = 0; - dev_dbg(wdev->dev, "send PDS '%s}'\n", buf + start); - buf[i] = '}'; - ret = hif_configuration(wdev, buf + start, - i - start + 1); - if (ret > 0) { - dev_err(wdev->dev, "PDS bytes %d to %d: invalid data (unsupported options?)\n", - start, i); - return -EINVAL; - } - if (ret == -ETIMEDOUT) { - dev_err(wdev->dev, "PDS bytes %d to %d: chip didn't reply (corrupted file?)\n", - start, i); - return ret; - } - if (ret) { - dev_err(wdev->dev, "PDS bytes %d to %d: chip returned an unknown error\n", - start, i); - return -EIO; - } - buf[i] = ','; - start = i; - } - } - return 0; -} - -static int wfx_send_pdata_pds(struct wfx_dev *wdev) -{ - int ret = 0; - const struct firmware *pds; - u8 *tmp_buf; - - ret = request_firmware(&pds, wdev->pdata.file_pds, wdev->dev); - if (ret) { - dev_err(wdev->dev, "can't load antenna parameters (PDS file %s). The device may be unstable.\n", - wdev->pdata.file_pds); - goto err1; - } - tmp_buf = kmemdup(pds->data, pds->size, GFP_KERNEL); - if (!tmp_buf) { - ret = -ENOMEM; - goto err2; - } - ret = wfx_send_pds(wdev, tmp_buf, pds->size); - kfree(tmp_buf); -err2: - release_firmware(pds); -err1: - return ret; -} - -static void wfx_free_common(void *data) -{ - struct wfx_dev *wdev = data; - - mutex_destroy(&wdev->tx_power_loop_info_lock); - mutex_destroy(&wdev->rx_stats_lock); - mutex_destroy(&wdev->conf_mutex); - ieee80211_free_hw(wdev->hw); -} - -struct wfx_dev *wfx_init_common(struct device *dev, - const struct wfx_platform_data *pdata, - const struct hwbus_ops *hwbus_ops, - void *hwbus_priv) -{ - struct ieee80211_hw *hw; - struct wfx_dev *wdev; - - hw = ieee80211_alloc_hw(sizeof(struct wfx_dev), &wfx_ops); - if (!hw) - return NULL; - - SET_IEEE80211_DEV(hw, dev); - - ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); - ieee80211_hw_set(hw, AMPDU_AGGREGATION); - ieee80211_hw_set(hw, CONNECTION_MONITOR); - ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); - ieee80211_hw_set(hw, SIGNAL_DBM); - ieee80211_hw_set(hw, SUPPORTS_PS); - ieee80211_hw_set(hw, MFP_CAPABLE); - - hw->vif_data_size = sizeof(struct wfx_vif); - hw->sta_data_size = sizeof(struct wfx_sta_priv); - hw->queues = 4; - hw->max_rates = 8; - hw->max_rate_tries = 8; - hw->extra_tx_headroom = sizeof(struct hif_msg) - + sizeof(struct hif_req_tx) - + 4 /* alignment */ + 8 /* TKIP IV */; - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); - hw->wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; - hw->wiphy->features |= NL80211_FEATURE_AP_SCAN; - hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; - hw->wiphy->max_ap_assoc_sta = HIF_LINK_ID_MAX; - hw->wiphy->max_scan_ssids = 2; - hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; - hw->wiphy->n_iface_combinations = ARRAY_SIZE(wfx_iface_combinations); - hw->wiphy->iface_combinations = wfx_iface_combinations; - hw->wiphy->bands[NL80211_BAND_2GHZ] = devm_kmalloc(dev, sizeof(wfx_band_2ghz), GFP_KERNEL); - /* FIXME: also copy wfx_rates and wfx_2ghz_chantable */ - memcpy(hw->wiphy->bands[NL80211_BAND_2GHZ], &wfx_band_2ghz, - sizeof(wfx_band_2ghz)); - - wdev = hw->priv; - wdev->hw = hw; - wdev->dev = dev; - wdev->hwbus_ops = hwbus_ops; - wdev->hwbus_priv = hwbus_priv; - memcpy(&wdev->pdata, pdata, sizeof(*pdata)); - of_property_read_string(dev->of_node, "config-file", - &wdev->pdata.file_pds); - wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup", - GPIOD_OUT_LOW); - if (IS_ERR(wdev->pdata.gpio_wakeup)) - return NULL; - if (wdev->pdata.gpio_wakeup) - gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); - - mutex_init(&wdev->conf_mutex); - mutex_init(&wdev->rx_stats_lock); - mutex_init(&wdev->tx_power_loop_info_lock); - init_completion(&wdev->firmware_ready); - INIT_DELAYED_WORK(&wdev->cooling_timeout_work, - wfx_cooling_timeout_work); - skb_queue_head_init(&wdev->tx_pending); - init_waitqueue_head(&wdev->tx_dequeue); - wfx_init_hif_cmd(&wdev->hif_cmd); - wdev->force_ps_timeout = -1; - - if (devm_add_action_or_reset(dev, wfx_free_common, wdev)) - return NULL; - - return wdev; -} - -int wfx_probe(struct wfx_dev *wdev) -{ - int i; - int err; - struct gpio_desc *gpio_saved; - - /* During first part of boot, gpio_wakeup cannot yet been used. So - * prevent bh() to touch it. - */ - gpio_saved = wdev->pdata.gpio_wakeup; - wdev->pdata.gpio_wakeup = NULL; - wdev->poll_irq = true; - - wfx_bh_register(wdev); - - err = wfx_init_device(wdev); - if (err) - goto err0; - - wfx_bh_poll_irq(wdev); - err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ); - if (err <= 0) { - if (err == 0) { - dev_err(wdev->dev, "timeout while waiting for startup indication\n"); - err = -ETIMEDOUT; - } else if (err == -ERESTARTSYS) { - dev_info(wdev->dev, "probe interrupted by user\n"); - } - goto err0; - } - - /* FIXME: fill wiphy::hw_version */ - dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n", - wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor, - wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label, - wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor, - wdev->keyset, wdev->hw_caps.link_mode); - snprintf(wdev->hw->wiphy->fw_version, - sizeof(wdev->hw->wiphy->fw_version), - "%d.%d.%d", - wdev->hw_caps.firmware_major, - wdev->hw_caps.firmware_minor, - wdev->hw_caps.firmware_build); - - if (wfx_api_older_than(wdev, 1, 0)) { - dev_err(wdev->dev, - "unsupported firmware API version (expect 1 while firmware returns %d)\n", - wdev->hw_caps.api_version_major); - err = -ENOTSUPP; - goto err0; - } - - if (wdev->hw_caps.link_mode == SEC_LINK_ENFORCED) { - dev_err(wdev->dev, - "chip require secure_link, but can't negotiate it\n"); - goto err0; - } - - if (wdev->hw_caps.region_sel_mode) { - wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[11].flags |= IEEE80211_CHAN_NO_IR; - wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[12].flags |= IEEE80211_CHAN_NO_IR; - wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[13].flags |= IEEE80211_CHAN_DISABLED; - } - - dev_dbg(wdev->dev, "sending configuration file %s\n", - wdev->pdata.file_pds); - err = wfx_send_pdata_pds(wdev); - if (err < 0 && err != -ENOENT) - goto err0; - - wdev->poll_irq = false; - err = wdev->hwbus_ops->irq_subscribe(wdev->hwbus_priv); - if (err) - goto err0; - - err = hif_use_multi_tx_conf(wdev, true); - if (err) - dev_err(wdev->dev, "misconfigured IRQ?\n"); - - wdev->pdata.gpio_wakeup = gpio_saved; - if (wdev->pdata.gpio_wakeup) { - dev_dbg(wdev->dev, - "enable 'quiescent' power mode with wakeup GPIO and PDS file %s\n", - wdev->pdata.file_pds); - gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); - control_reg_write(wdev, 0); - hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT); - } else { - hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE); - } - - for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { - eth_zero_addr(wdev->addresses[i].addr); - err = of_get_mac_address(wdev->dev->of_node, - wdev->addresses[i].addr); - if (!err) { - wdev->addresses[i].addr[ETH_ALEN - 1] += i; - } else { - ether_addr_copy(wdev->addresses[i].addr, - wdev->hw_caps.mac_addr[i]); - } - if (!is_valid_ether_addr(wdev->addresses[i].addr)) { - dev_warn(wdev->dev, "using random MAC address\n"); - eth_random_addr(wdev->addresses[i].addr); - } - dev_info(wdev->dev, "MAC address %d: %pM\n", i, - wdev->addresses[i].addr); - } - wdev->hw->wiphy->n_addresses = ARRAY_SIZE(wdev->addresses); - wdev->hw->wiphy->addresses = wdev->addresses; - - if (!wfx_api_older_than(wdev, 3, 8)) - wdev->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; - - err = ieee80211_register_hw(wdev->hw); - if (err) - goto err1; - - err = wfx_debug_init(wdev); - if (err) - goto err2; - - return 0; - -err2: - ieee80211_unregister_hw(wdev->hw); -err1: - wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); -err0: - wfx_bh_unregister(wdev); - return err; -} - -void wfx_release(struct wfx_dev *wdev) -{ - ieee80211_unregister_hw(wdev->hw); - hif_shutdown(wdev); - wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); - wfx_bh_unregister(wdev); -} - -static int __init wfx_core_init(void) -{ - int ret = 0; - - if (IS_ENABLED(CONFIG_SPI)) - ret = spi_register_driver(&wfx_spi_driver); - if (IS_ENABLED(CONFIG_MMC) && !ret) - ret = sdio_register_driver(&wfx_sdio_driver); - return ret; -} -module_init(wfx_core_init); - -static void __exit wfx_core_exit(void) -{ - if (IS_ENABLED(CONFIG_MMC)) - sdio_unregister_driver(&wfx_sdio_driver); - if (IS_ENABLED(CONFIG_SPI)) - spi_unregister_driver(&wfx_spi_driver); -} -module_exit(wfx_core_exit); diff --git a/drivers/staging/wfx/main.h b/drivers/staging/wfx/main.h deleted file mode 100644 index 115abd2d4378..000000000000 --- a/drivers/staging/wfx/main.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Device probe and register. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - * Copyright (c) 2006, Michael Wu - * Copyright 2004-2006 Jean-Baptiste Note , et al. - */ -#ifndef WFX_MAIN_H -#define WFX_MAIN_H - -#include -#include - -#include "hif_api_general.h" - -struct wfx_dev; -struct hwbus_ops; - -struct wfx_platform_data { - /* Keyset and ".sec" extension will be appended to this string */ - const char *file_fw; - const char *file_pds; - struct gpio_desc *gpio_wakeup; - /* if true HIF D_out is sampled on the rising edge of the clock - * (intended to be used in 50Mhz SDIO) - */ - bool use_rising_clk; -}; - -struct wfx_dev *wfx_init_common(struct device *dev, - const struct wfx_platform_data *pdata, - const struct hwbus_ops *hwbus_ops, - void *hwbus_priv); - -int wfx_probe(struct wfx_dev *wdev); -void wfx_release(struct wfx_dev *wdev); - -bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor); -int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len); - -#endif diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c deleted file mode 100644 index 7a3ba3c38925..000000000000 --- a/drivers/staging/wfx/queue.c +++ /dev/null @@ -1,307 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Queue between the tx operation and the bh workqueue. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "queue.h" -#include "wfx.h" -#include "sta.h" -#include "data_tx.h" -#include "traces.h" - -void wfx_tx_lock(struct wfx_dev *wdev) -{ - atomic_inc(&wdev->tx_lock); -} - -void wfx_tx_unlock(struct wfx_dev *wdev) -{ - int tx_lock = atomic_dec_return(&wdev->tx_lock); - - WARN(tx_lock < 0, "inconsistent tx_lock value"); - if (!tx_lock) - wfx_bh_request_tx(wdev); -} - -void wfx_tx_flush(struct wfx_dev *wdev) -{ - int ret; - - /* Do not wait for any reply if chip is frozen */ - if (wdev->chip_frozen) - return; - - wfx_tx_lock(wdev); - mutex_lock(&wdev->hif_cmd.lock); - ret = wait_event_timeout(wdev->hif.tx_buffers_empty, - !wdev->hif.tx_buffers_used, - msecs_to_jiffies(3000)); - if (!ret) { - dev_warn(wdev->dev, "cannot flush tx buffers (%d still busy)\n", - wdev->hif.tx_buffers_used); - wfx_pending_dump_old_frames(wdev, 3000); - /* FIXME: drop pending frames here */ - wdev->chip_frozen = true; - } - mutex_unlock(&wdev->hif_cmd.lock); - wfx_tx_unlock(wdev); -} - -void wfx_tx_lock_flush(struct wfx_dev *wdev) -{ - wfx_tx_lock(wdev); - wfx_tx_flush(wdev); -} - -void wfx_tx_queues_init(struct wfx_vif *wvif) -{ - /* The device is in charge to respect the details of the QoS parameters. - * The driver just ensure that it roughtly respect the priorities to - * avoid any shortage. - */ - const int priorities[IEEE80211_NUM_ACS] = { 1, 2, 64, 128 }; - int i; - - for (i = 0; i < IEEE80211_NUM_ACS; ++i) { - skb_queue_head_init(&wvif->tx_queue[i].normal); - skb_queue_head_init(&wvif->tx_queue[i].cab); - wvif->tx_queue[i].priority = priorities[i]; - } -} - -bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue) -{ - return skb_queue_empty_lockless(&queue->normal) && - skb_queue_empty_lockless(&queue->cab); -} - -void wfx_tx_queues_check_empty(struct wfx_vif *wvif) -{ - int i; - - for (i = 0; i < IEEE80211_NUM_ACS; ++i) { - WARN_ON(atomic_read(&wvif->tx_queue[i].pending_frames)); - WARN_ON(!wfx_tx_queue_empty(wvif, &wvif->tx_queue[i])); - } -} - -static void __wfx_tx_queue_drop(struct wfx_vif *wvif, - struct sk_buff_head *skb_queue, - struct sk_buff_head *dropped) -{ - struct sk_buff *skb, *tmp; - - spin_lock_bh(&skb_queue->lock); - skb_queue_walk_safe(skb_queue, skb, tmp) { - __skb_unlink(skb, skb_queue); - skb_queue_head(dropped, skb); - } - spin_unlock_bh(&skb_queue->lock); -} - -void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, - struct sk_buff_head *dropped) -{ - __wfx_tx_queue_drop(wvif, &queue->cab, dropped); - __wfx_tx_queue_drop(wvif, &queue->normal, dropped); - wake_up(&wvif->wdev->tx_dequeue); -} - -void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb) -{ - struct wfx_queue *queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) - skb_queue_tail(&queue->cab, skb); - else - skb_queue_tail(&queue->normal, skb); -} - -void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped) -{ - struct wfx_queue *queue; - struct wfx_vif *wvif; - struct hif_msg *hif; - struct sk_buff *skb; - - WARN(!wdev->chip_frozen, "%s should only be used to recover a frozen device", - __func__); - while ((skb = skb_dequeue(&wdev->tx_pending)) != NULL) { - hif = (struct hif_msg *)skb->data; - wvif = wdev_to_wvif(wdev, hif->interface); - if (wvif) { - queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; - WARN_ON(skb_get_queue_mapping(skb) > 3); - WARN_ON(!atomic_read(&queue->pending_frames)); - atomic_dec(&queue->pending_frames); - } - skb_queue_head(dropped, skb); - } -} - -struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id) -{ - struct wfx_queue *queue; - struct hif_req_tx *req; - struct wfx_vif *wvif; - struct hif_msg *hif; - struct sk_buff *skb; - - spin_lock_bh(&wdev->tx_pending.lock); - skb_queue_walk(&wdev->tx_pending, skb) { - hif = (struct hif_msg *)skb->data; - req = (struct hif_req_tx *)hif->body; - if (req->packet_id != packet_id) - continue; - spin_unlock_bh(&wdev->tx_pending.lock); - wvif = wdev_to_wvif(wdev, hif->interface); - if (wvif) { - queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; - WARN_ON(skb_get_queue_mapping(skb) > 3); - WARN_ON(!atomic_read(&queue->pending_frames)); - atomic_dec(&queue->pending_frames); - } - skb_unlink(skb, &wdev->tx_pending); - return skb; - } - spin_unlock_bh(&wdev->tx_pending.lock); - WARN(1, "cannot find packet in pending queue"); - return NULL; -} - -void wfx_pending_dump_old_frames(struct wfx_dev *wdev, unsigned int limit_ms) -{ - ktime_t now = ktime_get(); - struct wfx_tx_priv *tx_priv; - struct hif_req_tx *req; - struct sk_buff *skb; - bool first = true; - - spin_lock_bh(&wdev->tx_pending.lock); - skb_queue_walk(&wdev->tx_pending, skb) { - tx_priv = wfx_skb_tx_priv(skb); - req = wfx_skb_txreq(skb); - if (ktime_after(now, ktime_add_ms(tx_priv->xmit_timestamp, - limit_ms))) { - if (first) { - dev_info(wdev->dev, "frames stuck in firmware since %dms or more:\n", - limit_ms); - first = false; - } - dev_info(wdev->dev, " id %08x sent %lldms ago\n", - req->packet_id, - ktime_ms_delta(now, tx_priv->xmit_timestamp)); - } - } - spin_unlock_bh(&wdev->tx_pending.lock); -} - -unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, - struct sk_buff *skb) -{ - ktime_t now = ktime_get(); - struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb); - - return ktime_us_delta(now, tx_priv->xmit_timestamp); -} - -bool wfx_tx_queues_has_cab(struct wfx_vif *wvif) -{ - int i; - - if (wvif->vif->type != NL80211_IFTYPE_AP) - return false; - for (i = 0; i < IEEE80211_NUM_ACS; ++i) - /* Note: since only AP can have mcast frames in queue and only - * one vif can be AP, all queued frames has same interface id - */ - if (!skb_queue_empty_lockless(&wvif->tx_queue[i].cab)) - return true; - return false; -} - -static int wfx_tx_queue_get_weight(struct wfx_queue *queue) -{ - return atomic_read(&queue->pending_frames) * queue->priority; -} - -static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev) -{ - struct wfx_queue *queues[IEEE80211_NUM_ACS * ARRAY_SIZE(wdev->vif)]; - int i, j, num_queues = 0; - struct wfx_vif *wvif; - struct hif_msg *hif; - struct sk_buff *skb; - - /* sort the queues */ - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - WARN_ON(num_queues >= ARRAY_SIZE(queues)); - queues[num_queues] = &wvif->tx_queue[i]; - for (j = num_queues; j > 0; j--) - if (wfx_tx_queue_get_weight(queues[j]) < - wfx_tx_queue_get_weight(queues[j - 1])) - swap(queues[j - 1], queues[j]); - num_queues++; - } - } - - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - if (!wvif->after_dtim_tx_allowed) - continue; - for (i = 0; i < num_queues; i++) { - skb = skb_dequeue(&queues[i]->cab); - if (!skb) - continue; - /* Note: since only AP can have mcast frames in queue - * and only one vif can be AP, all queued frames has - * same interface id - */ - hif = (struct hif_msg *)skb->data; - WARN_ON(hif->interface != wvif->id); - WARN_ON(queues[i] != - &wvif->tx_queue[skb_get_queue_mapping(skb)]); - atomic_inc(&queues[i]->pending_frames); - trace_queues_stats(wdev, queues[i]); - return skb; - } - /* No more multicast to sent */ - wvif->after_dtim_tx_allowed = false; - schedule_work(&wvif->update_tim_work); - } - - for (i = 0; i < num_queues; i++) { - skb = skb_dequeue(&queues[i]->normal); - if (skb) { - atomic_inc(&queues[i]->pending_frames); - trace_queues_stats(wdev, queues[i]); - return skb; - } - } - return NULL; -} - -struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) -{ - struct wfx_tx_priv *tx_priv; - struct sk_buff *skb; - - if (atomic_read(&wdev->tx_lock)) - return NULL; - skb = wfx_tx_queues_get_skb(wdev); - if (!skb) - return NULL; - skb_queue_tail(&wdev->tx_pending, skb); - wake_up(&wdev->tx_dequeue); - tx_priv = wfx_skb_tx_priv(skb); - tx_priv->xmit_timestamp = ktime_get(); - return (struct hif_msg *)skb->data; -} diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h deleted file mode 100644 index edd0d018b198..000000000000 --- a/drivers/staging/wfx/queue.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Queue between the tx operation and the bh workqueue. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_QUEUE_H -#define WFX_QUEUE_H - -#include -#include - -struct wfx_dev; -struct wfx_vif; - -struct wfx_queue { - struct sk_buff_head normal; - struct sk_buff_head cab; /* Content After (DTIM) Beacon */ - atomic_t pending_frames; - int priority; -}; - -void wfx_tx_lock(struct wfx_dev *wdev); -void wfx_tx_unlock(struct wfx_dev *wdev); -void wfx_tx_flush(struct wfx_dev *wdev); -void wfx_tx_lock_flush(struct wfx_dev *wdev); - -void wfx_tx_queues_init(struct wfx_vif *wvif); -void wfx_tx_queues_check_empty(struct wfx_vif *wvif); -bool wfx_tx_queues_has_cab(struct wfx_vif *wvif); -void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb); -struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev); - -bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue); -void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, - struct sk_buff_head *dropped); - -struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id); -void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped); -unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, - struct sk_buff *skb); -void wfx_pending_dump_old_frames(struct wfx_dev *wdev, unsigned int limit_ms); - -#endif diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c deleted file mode 100644 index 668ef2c60837..000000000000 --- a/drivers/staging/wfx/scan.c +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Scan related functions. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include - -#include "scan.h" -#include "wfx.h" -#include "sta.h" -#include "hif_tx_mib.h" - -static void __ieee80211_scan_completed_compat(struct ieee80211_hw *hw, - bool aborted) -{ - struct cfg80211_scan_info info = { - .aborted = aborted, - }; - - ieee80211_scan_completed(hw, &info); -} - -static int update_probe_tmpl(struct wfx_vif *wvif, - struct cfg80211_scan_request *req) -{ - struct sk_buff *skb; - - skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->vif->addr, - NULL, 0, req->ie_len); - if (!skb) - return -ENOMEM; - - skb_put_data(skb, req->ie, req->ie_len); - hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBREQ, 0); - dev_kfree_skb(skb); - return 0; -} - -static int send_scan_req(struct wfx_vif *wvif, - struct cfg80211_scan_request *req, int start_idx) -{ - int i, ret; - struct ieee80211_channel *ch_start, *ch_cur; - - for (i = start_idx; i < req->n_channels; i++) { - ch_start = req->channels[start_idx]; - ch_cur = req->channels[i]; - WARN(ch_cur->band != NL80211_BAND_2GHZ, "band not supported"); - if (ch_cur->max_power != ch_start->max_power) - break; - if ((ch_cur->flags ^ ch_start->flags) & IEEE80211_CHAN_NO_IR) - break; - } - wfx_tx_lock_flush(wvif->wdev); - wvif->scan_abort = false; - reinit_completion(&wvif->scan_complete); - ret = hif_scan(wvif, req, start_idx, i - start_idx); - if (ret) { - wfx_tx_unlock(wvif->wdev); - return -EIO; - } - ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ); - if (!ret) { - hif_stop_scan(wvif); - ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ); - dev_dbg(wvif->wdev->dev, "scan timeout (%d channels done)\n", - wvif->scan_nb_chan_done); - } - if (!ret) { - dev_err(wvif->wdev->dev, "scan didn't stop\n"); - ret = -ETIMEDOUT; - } else if (wvif->scan_abort) { - dev_notice(wvif->wdev->dev, "scan abort\n"); - ret = -ECONNABORTED; - } else if (wvif->scan_nb_chan_done > i - start_idx) { - ret = -EIO; - } else { - ret = wvif->scan_nb_chan_done; - } - if (req->channels[start_idx]->max_power != wvif->vif->bss_conf.txpower) - hif_set_output_power(wvif, wvif->vif->bss_conf.txpower); - wfx_tx_unlock(wvif->wdev); - return ret; -} - -/* It is not really necessary to run scan request asynchronously. However, - * there is a bug in "iw scan" when ieee80211_scan_completed() is called before - * wfx_hw_scan() return - */ -void wfx_hw_scan_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan_work); - struct ieee80211_scan_request *hw_req = wvif->scan_req; - int chan_cur, ret, err; - - mutex_lock(&wvif->wdev->conf_mutex); - mutex_lock(&wvif->scan_lock); - if (wvif->join_in_progress) { - dev_info(wvif->wdev->dev, "%s: abort in-progress REQ_JOIN", - __func__); - wfx_reset(wvif); - } - update_probe_tmpl(wvif, &hw_req->req); - chan_cur = 0; - err = 0; - do { - ret = send_scan_req(wvif, &hw_req->req, chan_cur); - if (ret > 0) { - chan_cur += ret; - err = 0; - } - if (!ret) - err++; - if (err > 2) { - dev_err(wvif->wdev->dev, "scan has not been able to start\n"); - ret = -ETIMEDOUT; - } - } while (ret >= 0 && chan_cur < hw_req->req.n_channels); - mutex_unlock(&wvif->scan_lock); - mutex_unlock(&wvif->wdev->conf_mutex); - __ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); -} - -int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_scan_request *hw_req) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - WARN_ON(hw_req->req.n_channels > HIF_API_MAX_NB_CHANNELS); - wvif->scan_req = hw_req; - schedule_work(&wvif->scan_work); - return 0; -} - -void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - wvif->scan_abort = true; - hif_stop_scan(wvif); -} - -void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done) -{ - wvif->scan_nb_chan_done = nb_chan_done; - complete(&wvif->scan_complete); -} diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h deleted file mode 100644 index 78e3b984f375..000000000000 --- a/drivers/staging/wfx/scan.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Scan related functions. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_SCAN_H -#define WFX_SCAN_H - -#include - -struct wfx_dev; -struct wfx_vif; - -void wfx_hw_scan_work(struct work_struct *work); -int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_scan_request *req); -void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done); - -#endif diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c deleted file mode 100644 index aceb18a1f54b..000000000000 --- a/drivers/staging/wfx/sta.c +++ /dev/null @@ -1,834 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Implementation of mac80211 API. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#include -#include - -#include "sta.h" -#include "wfx.h" -#include "fwio.h" -#include "bh.h" -#include "key.h" -#include "scan.h" -#include "debug.h" -#include "hif_tx.h" -#include "hif_tx_mib.h" - -#define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2 - -u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) -{ - int i; - u32 ret = 0; - /* The device only supports 2GHz */ - struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]; - - for (i = 0; i < sband->n_bitrates; i++) { - if (rates & BIT(i)) { - if (i >= sband->n_bitrates) - dev_warn(wdev->dev, "unsupported basic rate\n"); - else - ret |= BIT(sband->bitrates[i].hw_value); - } - } - return ret; -} - -void wfx_cooling_timeout_work(struct work_struct *work) -{ - struct wfx_dev *wdev = container_of(to_delayed_work(work), - struct wfx_dev, - cooling_timeout_work); - - wdev->chip_frozen = true; - wfx_tx_unlock(wdev); -} - -void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd) -{ - if (cmd == STA_NOTIFY_AWAKE) { - /* Device recover normal temperature */ - if (cancel_delayed_work(&wdev->cooling_timeout_work)) - wfx_tx_unlock(wdev); - } else { - /* Device is too hot */ - schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ); - wfx_tx_lock(wdev); - } -} - -static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon) -{ - static const struct hif_ie_table_entry filter_ies[] = { - { - .ie_id = WLAN_EID_VENDOR_SPECIFIC, - .has_changed = 1, - .no_longer = 1, - .has_appeared = 1, - .oui = { 0x50, 0x6F, 0x9A }, - }, { - .ie_id = WLAN_EID_HT_OPERATION, - .has_changed = 1, - .no_longer = 1, - .has_appeared = 1, - }, { - .ie_id = WLAN_EID_ERP_INFO, - .has_changed = 1, - .no_longer = 1, - .has_appeared = 1, - }, { - .ie_id = WLAN_EID_CHANNEL_SWITCH, - .has_changed = 1, - .no_longer = 1, - .has_appeared = 1, - } - }; - - if (!filter_beacon) { - hif_beacon_filter_control(wvif, 0, 1); - } else { - hif_set_beacon_filter_table(wvif, ARRAY_SIZE(filter_ies), filter_ies); - hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0); - } -} - -void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, u64 unused) -{ - struct wfx_vif *wvif = NULL; - struct wfx_dev *wdev = hw->priv; - bool filter_bssid, filter_prbreq, filter_beacon; - - /* Notes: - * - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered - * - PS-Poll (FIF_PSPOLL) are never filtered - * - RTS, CTS and Ack (FIF_CONTROL) are always filtered - * - Broken frames (FIF_FCSFAIL and FIF_PLCPFAIL) are always filtered - * - Firmware does (yet) allow to forward unicast traffic sent to - * other stations (aka. promiscuous mode) - */ - *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS | - FIF_PROBE_REQ | FIF_PSPOLL; - - mutex_lock(&wdev->conf_mutex); - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - mutex_lock(&wvif->scan_lock); - - /* Note: FIF_BCN_PRBRESP_PROMISC covers probe response and - * beacons from other BSS - */ - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - filter_beacon = false; - else - filter_beacon = true; - wfx_filter_beacon(wvif, filter_beacon); - - if (*total_flags & FIF_OTHER_BSS) - filter_bssid = false; - else - filter_bssid = true; - - /* In AP mode, chip can reply to probe request itself */ - if (*total_flags & FIF_PROBE_REQ && - wvif->vif->type == NL80211_IFTYPE_AP) { - dev_dbg(wdev->dev, "do not forward probe request in AP mode\n"); - *total_flags &= ~FIF_PROBE_REQ; - } - - if (*total_flags & FIF_PROBE_REQ) - filter_prbreq = false; - else - filter_prbreq = true; - hif_set_rx_filter(wvif, filter_bssid, filter_prbreq); - - mutex_unlock(&wvif->scan_lock); - } - mutex_unlock(&wdev->conf_mutex); -} - -static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) -{ - struct ieee80211_channel *chan0 = NULL, *chan1 = NULL; - struct ieee80211_conf *conf = &wvif->wdev->hw->conf; - - WARN(!wvif->vif->bss_conf.assoc && enable_ps, - "enable_ps is reliable only if associated"); - if (wdev_to_wvif(wvif->wdev, 0)) - chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan; - if (wdev_to_wvif(wvif->wdev, 1)) - chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan; - if (chan0 && chan1 && wvif->vif->type != NL80211_IFTYPE_AP) { - if (chan0->hw_value == chan1->hw_value) { - /* It is useless to enable PS if channels are the same. */ - if (enable_ps) - *enable_ps = false; - if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) - dev_info(wvif->wdev->dev, "ignoring requested PS mode"); - return -1; - } else { - /* It is necessary to enable PS if channels - * are different. - */ - if (enable_ps) - *enable_ps = true; - if (wvif->wdev->force_ps_timeout > -1) - return wvif->wdev->force_ps_timeout; - else if (wfx_api_older_than(wvif->wdev, 3, 2)) - return 0; - else - return 30; - } - } - if (enable_ps) - *enable_ps = wvif->vif->bss_conf.ps; - if (wvif->wdev->force_ps_timeout > -1) - return wvif->wdev->force_ps_timeout; - else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) - return conf->dynamic_ps_timeout; - else - return -1; -} - -int wfx_update_pm(struct wfx_vif *wvif) -{ - int ps_timeout; - bool ps; - - if (!wvif->vif->bss_conf.assoc) - return 0; - ps_timeout = wfx_get_ps_timeout(wvif, &ps); - if (!ps) - ps_timeout = 0; - WARN_ON(ps_timeout < 0); - if (wvif->uapsd_mask) - ps_timeout = 0; - - if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, - TU_TO_JIFFIES(512))) - dev_warn(wvif->wdev->dev, - "timeout while waiting of set_pm_mode_complete\n"); - return hif_set_pm(wvif, ps, ps_timeout); -} - -int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params) -{ - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - int old_uapsd = wvif->uapsd_mask; - - WARN_ON(queue >= hw->queues); - - mutex_lock(&wdev->conf_mutex); - assign_bit(queue, &wvif->uapsd_mask, params->uapsd); - hif_set_edca_queue_params(wvif, queue, params); - if (wvif->vif->type == NL80211_IFTYPE_STATION && - old_uapsd != wvif->uapsd_mask) { - hif_set_uapsd_info(wvif, wvif->uapsd_mask); - wfx_update_pm(wvif); - } - mutex_unlock(&wdev->conf_mutex); - return 0; -} - -int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif = NULL; - - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - hif_rts_threshold(wvif, value); - return 0; -} - -void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi) -{ - /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 - * RSSI = RCPI / 2 - 110 - */ - int rcpi_rssi; - int cqm_evt; - - rcpi_rssi = raw_rcpi_rssi / 2 - 110; - if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold) - cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; - else - cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; - ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL); -} - -static void wfx_beacon_loss_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(to_delayed_work(work), - struct wfx_vif, beacon_loss_work); - struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf; - - ieee80211_beacon_loss(wvif->vif); - schedule_delayed_work(to_delayed_work(work), - msecs_to_jiffies(bss_conf->beacon_int)); -} - -void wfx_set_default_unicast_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int idx) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - hif_wep_default_key_id(wvif, idx); -} - -void wfx_reset(struct wfx_vif *wvif) -{ - struct wfx_dev *wdev = wvif->wdev; - - wfx_tx_lock_flush(wdev); - hif_reset(wvif, false); - wfx_tx_policy_init(wvif); - if (wvif_count(wdev) <= 1) - hif_set_block_ack_policy(wvif, 0xFF, 0xFF); - wfx_tx_unlock(wdev); - wvif->join_in_progress = false; - cancel_delayed_work_sync(&wvif->beacon_loss_work); - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - wfx_update_pm(wvif); -} - -int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - - sta_priv->vif_id = wvif->id; - - if (vif->type == NL80211_IFTYPE_STATION) - hif_set_mfp(wvif, sta->mfp, sta->mfp); - - /* In station mode, the firmware interprets new link-id as a TDLS peer */ - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - return 0; - sta_priv->link_id = ffz(wvif->link_id_map); - wvif->link_id_map |= BIT(sta_priv->link_id); - WARN_ON(!sta_priv->link_id); - WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX); - hif_map_link(wvif, false, sta->addr, sta_priv->link_id, sta->mfp); - - return 0; -} - -int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - - /* See note in wfx_sta_add() */ - if (!sta_priv->link_id) - return 0; - /* FIXME add a mutex? */ - hif_map_link(wvif, true, sta->addr, sta_priv->link_id, false); - wvif->link_id_map &= ~BIT(sta_priv->link_id); - return 0; -} - -static int wfx_upload_ap_templates(struct wfx_vif *wvif) -{ - struct sk_buff *skb; - - skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); - if (!skb) - return -ENOMEM; - hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, - API_RATE_INDEX_B_1MBPS); - dev_kfree_skb(skb); - - skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif); - if (!skb) - return -ENOMEM; - hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, - API_RATE_INDEX_B_1MBPS); - dev_kfree_skb(skb); - return 0; -} - -static void wfx_set_mfp_ap(struct wfx_vif *wvif) -{ - struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); - const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable); - const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, - skb->data + ieoffset, - skb->len - ieoffset); - const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16); - const int pairwise_cipher_suite_size = 4 / sizeof(u16); - const int akm_suite_size = 4 / sizeof(u16); - - if (ptr) { - ptr += pairwise_cipher_suite_count_offset; - if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) - return; - ptr += 1 + pairwise_cipher_suite_size * *ptr; - if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) - return; - ptr += 1 + akm_suite_size * *ptr; - if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb))) - return; - hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6)); - } -} - -int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - struct wfx_dev *wdev = wvif->wdev; - int ret; - - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - wfx_update_pm(wvif); - wvif = (struct wfx_vif *)vif->drv_priv; - wfx_upload_ap_templates(wvif); - ret = hif_start(wvif, &vif->bss_conf, wvif->channel); - if (ret > 0) - return -EIO; - wfx_set_mfp_ap(wvif); - return ret; -} - -void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - wfx_reset(wvif); -} - -static void wfx_join(struct wfx_vif *wvif) -{ - int ret; - struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; - struct cfg80211_bss *bss = NULL; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - const u8 *ssidie = NULL; - int ssidlen = 0; - - wfx_tx_lock_flush(wvif->wdev); - - bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel, - conf->bssid, NULL, 0, - IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); - if (!bss && !conf->ibss_joined) { - wfx_tx_unlock(wvif->wdev); - return; - } - - rcu_read_lock(); /* protect ssidie */ - if (bss) - ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); - if (ssidie) { - ssidlen = ssidie[1]; - if (ssidlen > IEEE80211_MAX_SSID_LEN) - ssidlen = IEEE80211_MAX_SSID_LEN; - memcpy(ssid, &ssidie[2], ssidlen); - } - rcu_read_unlock(); - - cfg80211_put_bss(wvif->wdev->hw->wiphy, bss); - - wvif->join_in_progress = true; - ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen); - if (ret) { - ieee80211_connection_loss(wvif->vif); - wfx_reset(wvif); - } else { - /* Due to beacon filtering it is possible that the - * AP's beacon is not known for the mac80211 stack. - * Disable filtering temporary to make sure the stack - * receives at least one - */ - wfx_filter_beacon(wvif, false); - } - wfx_tx_unlock(wvif->wdev); -} - -static void wfx_join_finalize(struct wfx_vif *wvif, - struct ieee80211_bss_conf *info) -{ - struct ieee80211_sta *sta = NULL; - int ampdu_density = 0; - bool greenfield = false; - - rcu_read_lock(); /* protect sta */ - if (info->bssid && !info->ibss_joined) - sta = ieee80211_find_sta(wvif->vif, info->bssid); - if (sta && sta->ht_cap.ht_supported) - ampdu_density = sta->ht_cap.ampdu_density; - if (sta && sta->ht_cap.ht_supported && - !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) - greenfield = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); - rcu_read_unlock(); - - wvif->join_in_progress = false; - hif_set_association_mode(wvif, ampdu_density, greenfield, - info->use_short_preamble); - hif_keep_alive_period(wvif, 0); - /* beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use - * the same value. - */ - hif_set_bss_params(wvif, info->aid, 7); - hif_set_beacon_wakeup_period(wvif, 1, 1); - wfx_update_pm(wvif); -} - -int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - wfx_upload_ap_templates(wvif); - wfx_join(wvif); - return 0; -} - -void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - wfx_reset(wvif); -} - -static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable) -{ - /* Driver has Content After DTIM Beacon in queue. Driver is waiting for - * a signal from the firmware. Since we are going to stop to send - * beacons, this signal will never happens. See also - * wfx_suspend_resume_mc() - */ - if (!enable && wfx_tx_queues_has_cab(wvif)) { - wvif->after_dtim_tx_allowed = true; - wfx_bh_request_tx(wvif->wdev); - } - hif_beacon_transmit(wvif, enable); -} - -void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u32 changed) -{ - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - int i; - - mutex_lock(&wdev->conf_mutex); - - if (changed & BSS_CHANGED_BASIC_RATES || - changed & BSS_CHANGED_BEACON_INT || - changed & BSS_CHANGED_BSSID) { - if (vif->type == NL80211_IFTYPE_STATION) - wfx_join(wvif); - } - - if (changed & BSS_CHANGED_ASSOC) { - if (info->assoc || info->ibss_joined) - wfx_join_finalize(wvif, info); - else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION) - wfx_reset(wvif); - else - dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n", - __func__); - } - - if (changed & BSS_CHANGED_BEACON_INFO) { - if (vif->type != NL80211_IFTYPE_STATION) - dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n", - __func__); - hif_set_beacon_wakeup_period(wvif, info->dtim_period, - info->dtim_period); - /* We temporary forwarded beacon for join process. It is now no - * more necessary. - */ - wfx_filter_beacon(wvif, true); - } - - if (changed & BSS_CHANGED_ARP_FILTER) { - for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) { - __be32 *arp_addr = &info->arp_addr_list[i]; - - if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES) - arp_addr = NULL; - if (i >= info->arp_addr_cnt) - arp_addr = NULL; - hif_set_arp_ipv4_filter(wvif, i, arp_addr); - } - } - - if (changed & BSS_CHANGED_AP_PROBE_RESP || - changed & BSS_CHANGED_BEACON) - wfx_upload_ap_templates(wvif); - - if (changed & BSS_CHANGED_BEACON_ENABLED) - wfx_enable_beacon(wvif, info->enable_beacon); - - if (changed & BSS_CHANGED_KEEP_ALIVE) - hif_keep_alive_period(wvif, info->max_idle_period * - USEC_PER_TU / USEC_PER_MSEC); - - if (changed & BSS_CHANGED_ERP_CTS_PROT) - hif_erp_use_protection(wvif, info->use_cts_prot); - - if (changed & BSS_CHANGED_ERP_SLOT) - hif_slot_time(wvif, info->use_short_slot ? 9 : 20); - - if (changed & BSS_CHANGED_CQM) - hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold, - info->cqm_rssi_hyst); - - if (changed & BSS_CHANGED_TXPOWER) - hif_set_output_power(wvif, info->txpower); - - if (changed & BSS_CHANGED_PS) - wfx_update_pm(wvif); - - mutex_unlock(&wdev->conf_mutex); -} - -static int wfx_update_tim(struct wfx_vif *wvif) -{ - struct sk_buff *skb; - u16 tim_offset, tim_length; - u8 *tim_ptr; - - skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif, - &tim_offset, &tim_length); - if (!skb) - return -ENOENT; - tim_ptr = skb->data + tim_offset; - - if (tim_offset && tim_length >= 6) { - /* Firmware handles DTIM counter internally */ - tim_ptr[2] = 0; - - /* Set/reset aid0 bit */ - if (wfx_tx_queues_has_cab(wvif)) - tim_ptr[4] |= 1; - else - tim_ptr[4] &= ~1; - } - - hif_update_ie_beacon(wvif, tim_ptr, tim_length); - dev_kfree_skb(skb); - - return 0; -} - -static void wfx_update_tim_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work); - - wfx_update_tim(wvif); -} - -int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) -{ - struct wfx_dev *wdev = hw->priv; - struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv; - struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id); - - if (!wvif) { - dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); - return -EIO; - } - schedule_work(&wvif->update_tim_work); - return 0; -} - -void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) -{ - struct wfx_vif *wvif_it; - - if (notify_cmd != STA_NOTIFY_AWAKE) - return; - - /* Device won't be able to honor CAB if a scan is in progress on any - * interface. Prefer to skip this DTIM and wait for the next one. - */ - wvif_it = NULL; - while ((wvif_it = wvif_iterate(wvif->wdev, wvif_it)) != NULL) - if (mutex_is_locked(&wvif_it->scan_lock)) - return; - - if (!wfx_tx_queues_has_cab(wvif) || wvif->after_dtim_tx_allowed) - dev_warn(wvif->wdev->dev, "incorrect sequence (%d CAB in queue)", - wfx_tx_queues_has_cab(wvif)); - wvif->after_dtim_tx_allowed = true; - wfx_bh_request_tx(wvif->wdev); -} - -int wfx_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) -{ - /* Aggregation is implemented fully in firmware */ - switch (params->action) { - case IEEE80211_AMPDU_RX_START: - case IEEE80211_AMPDU_RX_STOP: - /* Just acknowledge it to enable frame re-ordering */ - return 0; - default: - /* Leave the firmware doing its business for tx aggregation */ - return -EOPNOTSUPP; - } -} - -int wfx_add_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *conf) -{ - return 0; -} - -void wfx_remove_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *conf) -{ -} - -void wfx_change_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *conf, - u32 changed) -{ -} - -int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_chanctx_conf *conf) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - struct ieee80211_channel *ch = conf->def.chan; - - WARN(wvif->channel, "channel overwrite"); - wvif->channel = ch; - - return 0; -} - -void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_chanctx_conf *conf) -{ - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - struct ieee80211_channel *ch = conf->def.chan; - - WARN(wvif->channel != ch, "channel mismatch"); - wvif->channel = NULL; -} - -int wfx_config(struct ieee80211_hw *hw, u32 changed) -{ - return 0; -} - -int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - int i, ret = 0; - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | - IEEE80211_VIF_SUPPORTS_UAPSD | - IEEE80211_VIF_SUPPORTS_CQM_RSSI; - - mutex_lock(&wdev->conf_mutex); - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - break; - default: - mutex_unlock(&wdev->conf_mutex); - return -EOPNOTSUPP; - } - - /* FIXME: prefer use of container_of() to get vif */ - wvif->vif = vif; - wvif->wdev = wdev; - - wvif->link_id_map = 1; /* link-id 0 is reserved for multicast */ - INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work); - INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work); - - init_completion(&wvif->set_pm_mode_complete); - complete(&wvif->set_pm_mode_complete); - INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); - - mutex_init(&wvif->scan_lock); - init_completion(&wvif->scan_complete); - INIT_WORK(&wvif->scan_work, wfx_hw_scan_work); - - wfx_tx_queues_init(wvif); - wfx_tx_policy_init(wvif); - - for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) { - if (!wdev->vif[i]) { - wdev->vif[i] = vif; - wvif->id = i; - break; - } - } - WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than supported"); - - hif_set_macaddr(wvif, vif->addr); - - mutex_unlock(&wdev->conf_mutex); - - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - /* Combo mode does not support Block Acks. We can re-enable them */ - if (wvif_count(wdev) == 1) - hif_set_block_ack_policy(wvif, 0xFF, 0xFF); - else - hif_set_block_ack_policy(wvif, 0x00, 0x00); - } - return ret; -} - -void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; - - wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300)); - wfx_tx_queues_check_empty(wvif); - - mutex_lock(&wdev->conf_mutex); - WARN(wvif->link_id_map != 1, "corrupted state"); - - hif_reset(wvif, false); - hif_set_macaddr(wvif, NULL); - wfx_tx_policy_init(wvif); - - cancel_delayed_work_sync(&wvif->beacon_loss_work); - wdev->vif[wvif->id] = NULL; - wvif->vif = NULL; - - mutex_unlock(&wdev->conf_mutex); - - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - /* Combo mode does not support Block Acks. We can re-enable them */ - if (wvif_count(wdev) == 1) - hif_set_block_ack_policy(wvif, 0xFF, 0xFF); - else - hif_set_block_ack_policy(wvif, 0x00, 0x00); - } -} - -int wfx_start(struct ieee80211_hw *hw) -{ - return 0; -} - -void wfx_stop(struct ieee80211_hw *hw) -{ - struct wfx_dev *wdev = hw->priv; - - WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending)); -} diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h deleted file mode 100644 index 4d7e38be4235..000000000000 --- a/drivers/staging/wfx/sta.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Implementation of mac80211 API. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - */ -#ifndef WFX_STA_H -#define WFX_STA_H - -#include - -struct wfx_dev; -struct wfx_vif; - -struct wfx_sta_priv { - int link_id; - int vif_id; -}; - -/* mac80211 interface */ -int wfx_start(struct ieee80211_hw *hw); -void wfx_stop(struct ieee80211_hw *hw); -int wfx_config(struct ieee80211_hw *hw, u32 changed); -int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value); -void wfx_set_default_unicast_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int idx); -void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, u64 unused); - -int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params); -void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u32 changed); -int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, struct ieee80211_sta *sta); -int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); -int wfx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params); -int wfx_add_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *conf); -void wfx_remove_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *conf); -void wfx_change_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *conf, u32 changed); -int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_chanctx_conf *conf); -void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_chanctx_conf *conf); - -/* Hardware API Callbacks */ -void wfx_cooling_timeout_work(struct work_struct *work); -void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd); -void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd); -void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi); -int wfx_update_pm(struct wfx_vif *wvif); - -/* Other Helpers */ -void wfx_reset(struct wfx_vif *wvif); -u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates); - -#endif diff --git a/drivers/staging/wfx/traces.h b/drivers/staging/wfx/traces.h deleted file mode 100644 index e90dc73c4b01..000000000000 --- a/drivers/staging/wfx/traces.h +++ /dev/null @@ -1,501 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Tracepoints definitions. - * - * Copyright (c) 2018-2020, Silicon Laboratories, Inc. - */ - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM wfx - -#if !defined(_WFX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define _WFX_TRACE_H - -#include -#include - -#include "bus.h" -#include "hif_api_cmd.h" -#include "hif_api_mib.h" - -/* The hell below need some explanations. For each symbolic number, we need to - * define it with TRACE_DEFINE_ENUM() and in a list for __print_symbolic. - * - * 1. Define a new macro that call TRACE_DEFINE_ENUM(): - * - * #define xxx_name(sym) TRACE_DEFINE_ENUM(sym); - * - * 2. Define list of all symbols: - * - * #define list_names \ - * ... \ - * xxx_name(XXX) \ - * ... - * - * 3. Instantiate that list_names: - * - * list_names - * - * 4. Redefine xxx_name() as an entry of array for __print_symbolic() - * - * #undef xxx_name - * #define xxx_name(msg) { msg, #msg }, - * - * 5. list_name can now nearly be used with __print_symbolic() but, - * __print_symbolic() dislike last comma of list. So we define a new list - * with a dummy element: - * - * #define list_for_print_symbolic list_names { -1, NULL } - */ - -#define _hif_msg_list \ - hif_cnf_name(ADD_KEY) \ - hif_cnf_name(BEACON_TRANSMIT) \ - hif_cnf_name(EDCA_QUEUE_PARAMS) \ - hif_cnf_name(JOIN) \ - hif_cnf_name(MAP_LINK) \ - hif_cnf_name(READ_MIB) \ - hif_cnf_name(REMOVE_KEY) \ - hif_cnf_name(RESET) \ - hif_cnf_name(SET_BSS_PARAMS) \ - hif_cnf_name(SET_PM_MODE) \ - hif_cnf_name(START) \ - hif_cnf_name(START_SCAN) \ - hif_cnf_name(STOP_SCAN) \ - hif_cnf_name(TX) \ - hif_cnf_name(MULTI_TRANSMIT) \ - hif_cnf_name(UPDATE_IE) \ - hif_cnf_name(WRITE_MIB) \ - hif_cnf_name(CONFIGURATION) \ - hif_cnf_name(CONTROL_GPIO) \ - hif_cnf_name(PREVENT_ROLLBACK) \ - hif_cnf_name(SET_SL_MAC_KEY) \ - hif_cnf_name(SL_CONFIGURE) \ - hif_cnf_name(SL_EXCHANGE_PUB_KEYS) \ - hif_cnf_name(SHUT_DOWN) \ - hif_ind_name(EVENT) \ - hif_ind_name(JOIN_COMPLETE) \ - hif_ind_name(RX) \ - hif_ind_name(SCAN_CMPL) \ - hif_ind_name(SET_PM_MODE_CMPL) \ - hif_ind_name(SUSPEND_RESUME_TX) \ - hif_ind_name(SL_EXCHANGE_PUB_KEYS) \ - hif_ind_name(ERROR) \ - hif_ind_name(EXCEPTION) \ - hif_ind_name(GENERIC) \ - hif_ind_name(WAKEUP) \ - hif_ind_name(STARTUP) - -#define hif_msg_list_enum _hif_msg_list - -#undef hif_cnf_name -#undef hif_ind_name -#define hif_cnf_name(msg) TRACE_DEFINE_ENUM(HIF_CNF_ID_##msg); -#define hif_ind_name(msg) TRACE_DEFINE_ENUM(HIF_IND_ID_##msg); -hif_msg_list_enum -#undef hif_cnf_name -#undef hif_ind_name -#define hif_cnf_name(msg) { HIF_CNF_ID_##msg, #msg }, -#define hif_ind_name(msg) { HIF_IND_ID_##msg, #msg }, -#define hif_msg_list hif_msg_list_enum { -1, NULL } - -#define _hif_mib_list \ - hif_mib_name(ARP_IP_ADDRESSES_TABLE) \ - hif_mib_name(ARP_KEEP_ALIVE_PERIOD) \ - hif_mib_name(BEACON_FILTER_ENABLE) \ - hif_mib_name(BEACON_FILTER_TABLE) \ - hif_mib_name(BEACON_STATS) \ - hif_mib_name(BEACON_WAKEUP_PERIOD) \ - hif_mib_name(BLOCK_ACK_POLICY) \ - hif_mib_name(CCA_CONFIG) \ - hif_mib_name(CONFIG_DATA_FILTER) \ - hif_mib_name(COUNTERS_TABLE) \ - hif_mib_name(CURRENT_TX_POWER_LEVEL) \ - hif_mib_name(DOT11_MAC_ADDRESS) \ - hif_mib_name(DOT11_MAX_RECEIVE_LIFETIME) \ - hif_mib_name(DOT11_MAX_TRANSMIT_MSDU_LIFETIME) \ - hif_mib_name(DOT11_RTS_THRESHOLD) \ - hif_mib_name(DOT11_WEP_DEFAULT_KEY_ID) \ - hif_mib_name(ETHERTYPE_DATAFRAME_CONDITION) \ - hif_mib_name(EXTENDED_COUNTERS_TABLE) \ - hif_mib_name(GL_BLOCK_ACK_INFO) \ - hif_mib_name(GL_OPERATIONAL_POWER_MODE) \ - hif_mib_name(GL_SET_MULTI_MSG) \ - hif_mib_name(GRP_SEQ_COUNTER) \ - hif_mib_name(INACTIVITY_TIMER) \ - hif_mib_name(INTERFACE_PROTECTION) \ - hif_mib_name(IPV4_ADDR_DATAFRAME_CONDITION) \ - hif_mib_name(IPV6_ADDR_DATAFRAME_CONDITION) \ - hif_mib_name(KEEP_ALIVE_PERIOD) \ - hif_mib_name(MAC_ADDR_DATAFRAME_CONDITION) \ - hif_mib_name(MAGIC_DATAFRAME_CONDITION) \ - hif_mib_name(MAX_TX_POWER_LEVEL) \ - hif_mib_name(NON_ERP_PROTECTION) \ - hif_mib_name(NS_IP_ADDRESSES_TABLE) \ - hif_mib_name(OVERRIDE_INTERNAL_TX_RATE) \ - hif_mib_name(PORT_DATAFRAME_CONDITION) \ - hif_mib_name(PROTECTED_MGMT_POLICY) \ - hif_mib_name(RCPI_RSSI_THRESHOLD) \ - hif_mib_name(RX_FILTER) \ - hif_mib_name(SET_ASSOCIATION_MODE) \ - hif_mib_name(SET_DATA_FILTERING) \ - hif_mib_name(SET_HT_PROTECTION) \ - hif_mib_name(SET_TX_RATE_RETRY_POLICY) \ - hif_mib_name(SET_UAPSD_INFORMATION) \ - hif_mib_name(SLOT_TIME) \ - hif_mib_name(STATISTICS_TABLE) \ - hif_mib_name(TEMPLATE_FRAME) \ - hif_mib_name(TSF_COUNTER) \ - hif_mib_name(UC_MC_BC_DATAFRAME_CONDITION) - -#define hif_mib_list_enum _hif_mib_list - -#undef hif_mib_name -#define hif_mib_name(mib) TRACE_DEFINE_ENUM(HIF_MIB_ID_##mib); -hif_mib_list_enum -#undef hif_mib_name -#define hif_mib_name(mib) { HIF_MIB_ID_##mib, #mib }, -#define hif_mib_list hif_mib_list_enum { -1, NULL } - -DECLARE_EVENT_CLASS(hif_data, - TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), - TP_ARGS(hif, tx_fill_level, is_recv), - TP_STRUCT__entry( - __field(int, tx_fill_level) - __field(int, msg_id) - __field(const char *, msg_type) - __field(int, msg_len) - __field(int, buf_len) - __field(int, if_id) - __field(int, mib) - __array(u8, buf, 128) - ), - TP_fast_assign( - int header_len; - - __entry->tx_fill_level = tx_fill_level; - __entry->msg_len = le16_to_cpu(hif->len); - __entry->msg_id = hif->id; - __entry->if_id = hif->interface; - if (is_recv) - __entry->msg_type = __entry->msg_id & 0x80 ? "IND" : "CNF"; - else - __entry->msg_type = "REQ"; - if (!is_recv && - (__entry->msg_id == HIF_REQ_ID_READ_MIB || - __entry->msg_id == HIF_REQ_ID_WRITE_MIB)) { - __entry->mib = le16_to_cpup((__le16 *)hif->body); - header_len = 4; - } else { - __entry->mib = -1; - header_len = 0; - } - __entry->buf_len = min_t(int, __entry->msg_len, - sizeof(__entry->buf)) - - sizeof(struct hif_msg) - header_len; - memcpy(__entry->buf, hif->body + header_len, __entry->buf_len); - ), - TP_printk("%d:%d:%s_%s%s%s: %s%s (%d bytes)", - __entry->tx_fill_level, - __entry->if_id, - __entry->msg_type, - __print_symbolic(__entry->msg_id, hif_msg_list), - __entry->mib != -1 ? "/" : "", - __entry->mib != -1 ? __print_symbolic(__entry->mib, hif_mib_list) : "", - __print_hex(__entry->buf, __entry->buf_len), - __entry->msg_len > sizeof(__entry->buf) ? " ..." : "", - __entry->msg_len - ) -); -DEFINE_EVENT(hif_data, hif_send, - TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), - TP_ARGS(hif, tx_fill_level, is_recv)); -#define _trace_hif_send(hif, tx_fill_level)\ - trace_hif_send(hif, tx_fill_level, false) -DEFINE_EVENT(hif_data, hif_recv, - TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), - TP_ARGS(hif, tx_fill_level, is_recv)); -#define _trace_hif_recv(hif, tx_fill_level)\ - trace_hif_recv(hif, tx_fill_level, true) - -#define wfx_reg_list_enum \ - wfx_reg_name(WFX_REG_CONFIG, "CONFIG") \ - wfx_reg_name(WFX_REG_CONTROL, "CONTROL") \ - wfx_reg_name(WFX_REG_IN_OUT_QUEUE, "QUEUE") \ - wfx_reg_name(WFX_REG_AHB_DPORT, "AHB") \ - wfx_reg_name(WFX_REG_BASE_ADDR, "BASE_ADDR") \ - wfx_reg_name(WFX_REG_SRAM_DPORT, "SRAM") \ - wfx_reg_name(WFX_REG_SET_GEN_R_W, "SET_GEN_R_W") \ - wfx_reg_name(WFX_REG_FRAME_OUT, "FRAME_OUT") - -#undef wfx_reg_name -#define wfx_reg_name(sym, name) TRACE_DEFINE_ENUM(sym); -wfx_reg_list_enum -#undef wfx_reg_name -#define wfx_reg_name(sym, name) { sym, name }, -#define wfx_reg_list wfx_reg_list_enum { -1, NULL } - -DECLARE_EVENT_CLASS(io_data, - TP_PROTO(int reg, int addr, const void *io_buf, size_t len), - TP_ARGS(reg, addr, io_buf, len), - TP_STRUCT__entry( - __field(int, reg) - __field(int, addr) - __field(int, msg_len) - __field(int, buf_len) - __array(u8, buf, 32) - __array(u8, addr_str, 10) - ), - TP_fast_assign( - __entry->reg = reg; - __entry->addr = addr; - __entry->msg_len = len; - __entry->buf_len = min_t(int, sizeof(__entry->buf), - __entry->msg_len); - memcpy(__entry->buf, io_buf, __entry->buf_len); - if (addr >= 0) - snprintf(__entry->addr_str, 10, "/%08x", addr); - else - __entry->addr_str[0] = 0; - ), - TP_printk("%s%s: %s%s (%d bytes)", - __print_symbolic(__entry->reg, wfx_reg_list), - __entry->addr_str, - __print_hex(__entry->buf, __entry->buf_len), - __entry->msg_len > sizeof(__entry->buf) ? " ..." : "", - __entry->msg_len - ) -); -DEFINE_EVENT(io_data, io_write, - TP_PROTO(int reg, int addr, const void *io_buf, size_t len), - TP_ARGS(reg, addr, io_buf, len)); -#define _trace_io_ind_write(reg, addr, io_buf, len)\ - trace_io_write(reg, addr, io_buf, len) -#define _trace_io_write(reg, io_buf, len) trace_io_write(reg, -1, io_buf, len) -DEFINE_EVENT(io_data, io_read, - TP_PROTO(int reg, int addr, const void *io_buf, size_t len), - TP_ARGS(reg, addr, io_buf, len)); -#define _trace_io_ind_read(reg, addr, io_buf, len)\ - trace_io_read(reg, addr, io_buf, len) -#define _trace_io_read(reg, io_buf, len) trace_io_read(reg, -1, io_buf, len) - -DECLARE_EVENT_CLASS(io_data32, - TP_PROTO(int reg, int addr, u32 val), - TP_ARGS(reg, addr, val), - TP_STRUCT__entry( - __field(int, reg) - __field(int, addr) - __field(int, val) - __array(u8, addr_str, 10) - ), - TP_fast_assign( - __entry->reg = reg; - __entry->addr = addr; - __entry->val = val; - if (addr >= 0) - snprintf(__entry->addr_str, 10, "/%08x", addr); - else - __entry->addr_str[0] = 0; - ), - TP_printk("%s%s: %08x", - __print_symbolic(__entry->reg, wfx_reg_list), - __entry->addr_str, - __entry->val - ) -); -DEFINE_EVENT(io_data32, io_write32, - TP_PROTO(int reg, int addr, u32 val), - TP_ARGS(reg, addr, val)); -#define _trace_io_ind_write32(reg, addr, val) trace_io_write32(reg, addr, val) -#define _trace_io_write32(reg, val) trace_io_write32(reg, -1, val) -DEFINE_EVENT(io_data32, io_read32, - TP_PROTO(int reg, int addr, u32 val), - TP_ARGS(reg, addr, val)); -#define _trace_io_ind_read32(reg, addr, val) trace_io_read32(reg, addr, val) -#define _trace_io_read32(reg, val) trace_io_read32(reg, -1, val) - -DECLARE_EVENT_CLASS(piggyback, - TP_PROTO(u32 val, bool ignored), - TP_ARGS(val, ignored), - TP_STRUCT__entry( - __field(int, val) - __field(bool, ignored) - ), - TP_fast_assign( - __entry->val = val; - __entry->ignored = ignored; - ), - TP_printk("CONTROL: %08x%s", - __entry->val, - __entry->ignored ? " (ignored)" : "" - ) -); -DEFINE_EVENT(piggyback, piggyback, - TP_PROTO(u32 val, bool ignored), - TP_ARGS(val, ignored)); -#define _trace_piggyback(val, ignored) trace_piggyback(val, ignored) - -TRACE_EVENT(bh_stats, - TP_PROTO(int ind, int req, int cnf, int busy, bool release), - TP_ARGS(ind, req, cnf, busy, release), - TP_STRUCT__entry( - __field(int, ind) - __field(int, req) - __field(int, cnf) - __field(int, busy) - __field(bool, release) - ), - TP_fast_assign( - __entry->ind = ind; - __entry->req = req; - __entry->cnf = cnf; - __entry->busy = busy; - __entry->release = release; - ), - TP_printk("IND/REQ/CNF:%3d/%3d/%3d, REQ in progress:%3d, WUP: %s", - __entry->ind, - __entry->req, - __entry->cnf, - __entry->busy, - __entry->release ? "release" : "keep" - ) -); -#define _trace_bh_stats(ind, req, cnf, busy, release)\ - trace_bh_stats(ind, req, cnf, busy, release) - -TRACE_EVENT(tx_stats, - TP_PROTO(const struct hif_cnf_tx *tx_cnf, const struct sk_buff *skb, - int delay), - TP_ARGS(tx_cnf, skb, delay), - TP_STRUCT__entry( - __field(int, pkt_id) - __field(int, delay_media) - __field(int, delay_queue) - __field(int, delay_fw) - __field(int, ack_failures) - __field(int, flags) - __array(int, rate, 4) - __array(int, tx_count, 4) - ), - TP_fast_assign( - /* Keep sync with wfx_rates definition in main.c */ - static const int hw_rate[] = { 0, 1, 2, 3, 6, 7, 8, 9, - 10, 11, 12, 13 }; - const struct ieee80211_tx_info *tx_info = - (const struct ieee80211_tx_info *)skb->cb; - const struct ieee80211_tx_rate *rates = tx_info->driver_rates; - int i; - - __entry->pkt_id = tx_cnf->packet_id; - __entry->delay_media = le32_to_cpu(tx_cnf->media_delay); - __entry->delay_queue = le32_to_cpu(tx_cnf->tx_queue_delay); - __entry->delay_fw = delay; - __entry->ack_failures = tx_cnf->ack_failures; - if (!tx_cnf->status || __entry->ack_failures) - __entry->ack_failures += 1; - - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - if (rates[0].flags & IEEE80211_TX_RC_MCS) - __entry->rate[i] = rates[i].idx; - else - __entry->rate[i] = hw_rate[rates[i].idx]; - __entry->tx_count[i] = rates[i].count; - } - __entry->flags = 0; - if (rates[0].flags & IEEE80211_TX_RC_MCS) - __entry->flags |= 0x01; - if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI) - __entry->flags |= 0x02; - if (rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD) - __entry->flags |= 0x04; - if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - __entry->flags |= 0x08; - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) - __entry->flags |= 0x10; - if (tx_cnf->status) - __entry->flags |= 0x20; - if (tx_cnf->status == HIF_STATUS_TX_FAIL_REQUEUE) - __entry->flags |= 0x40; - ), - TP_printk("packet ID: %08x, rate policy: %s %d|%d %d|%d %d|%d %d|%d -> %d attempt, Delays media/queue/total: %4dus/%4dus/%4dus", - __entry->pkt_id, - __print_flags(__entry->flags, NULL, - { 0x01, "M" }, { 0x02, "S" }, { 0x04, "G" }, - { 0x08, "R" }, { 0x10, "D" }, { 0x20, "F" }, - { 0x40, "Q" }), - __entry->rate[0], - __entry->tx_count[0], - __entry->rate[1], - __entry->tx_count[1], - __entry->rate[2], - __entry->tx_count[2], - __entry->rate[3], - __entry->tx_count[3], - __entry->ack_failures, - __entry->delay_media, - __entry->delay_queue, - __entry->delay_fw - ) -); -#define _trace_tx_stats(tx_cnf, skb, delay) trace_tx_stats(tx_cnf, skb, delay) - -TRACE_EVENT(queues_stats, - TP_PROTO(struct wfx_dev *wdev, const struct wfx_queue *elected_queue), - TP_ARGS(wdev, elected_queue), - TP_STRUCT__entry( - __field(int, vif_id) - __field(int, queue_id) - __array(int, hw, IEEE80211_NUM_ACS * 2) - __array(int, drv, IEEE80211_NUM_ACS * 2) - __array(int, cab, IEEE80211_NUM_ACS * 2) - ), - TP_fast_assign( - const struct wfx_queue *queue; - struct wfx_vif *wvif; - int i, j; - - for (j = 0; j < IEEE80211_NUM_ACS * 2; j++) { - __entry->hw[j] = -1; - __entry->drv[j] = -1; - __entry->cab[j] = -1; - } - __entry->vif_id = -1; - __entry->queue_id = -1; - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - j = wvif->id * IEEE80211_NUM_ACS + i; - WARN_ON(j >= IEEE80211_NUM_ACS * 2); - queue = &wvif->tx_queue[i]; - __entry->hw[j] = atomic_read(&queue->pending_frames); - __entry->drv[j] = skb_queue_len(&queue->normal); - __entry->cab[j] = skb_queue_len(&queue->cab); - if (queue == elected_queue) { - __entry->vif_id = wvif->id; - __entry->queue_id = i; - } - } - } - ), - TP_printk("got skb from %d/%d, pend. hw/norm/cab: [ %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ] [ %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ]", - __entry->vif_id, __entry->queue_id, - __entry->hw[0], __entry->drv[0], __entry->cab[0], - __entry->hw[1], __entry->drv[1], __entry->cab[1], - __entry->hw[2], __entry->drv[2], __entry->cab[2], - __entry->hw[3], __entry->drv[3], __entry->cab[3], - __entry->hw[4], __entry->drv[4], __entry->cab[4], - __entry->hw[5], __entry->drv[5], __entry->cab[5], - __entry->hw[6], __entry->drv[6], __entry->cab[6], - __entry->hw[7], __entry->drv[7], __entry->cab[7] - ) -); - -#endif - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE traces - -#include diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h deleted file mode 100644 index f8df59ad1639..000000000000 --- a/drivers/staging/wfx/wfx.h +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Common private data. - * - * Copyright (c) 2017-2020, Silicon Laboratories, Inc. - * Copyright (c) 2010, ST-Ericsson - * Copyright (c) 2006, Michael Wu - * Copyright 2004-2006 Jean-Baptiste Note , et al. - */ -#ifndef WFX_H -#define WFX_H - -#include -#include -#include -#include -#include - -#include "bh.h" -#include "data_tx.h" -#include "main.h" -#include "queue.h" -#include "hif_tx.h" - -#define USEC_PER_TXOP 32 /* see struct ieee80211_tx_queue_params */ -#define USEC_PER_TU 1024 - -struct hwbus_ops; - -struct wfx_dev { - struct wfx_platform_data pdata; - struct device *dev; - struct ieee80211_hw *hw; - struct ieee80211_vif *vif[2]; - struct mac_address addresses[2]; - const struct hwbus_ops *hwbus_ops; - void *hwbus_priv; - - u8 keyset; - struct completion firmware_ready; - struct hif_ind_startup hw_caps; - struct wfx_hif hif; - struct delayed_work cooling_timeout_work; - bool poll_irq; - bool chip_frozen; - struct mutex conf_mutex; - - struct wfx_hif_cmd hif_cmd; - struct sk_buff_head tx_pending; - wait_queue_head_t tx_dequeue; - atomic_t tx_lock; - - atomic_t packet_id; - u32 key_map; - - struct hif_rx_stats rx_stats; - struct mutex rx_stats_lock; - struct hif_tx_power_loop_info tx_power_loop_info; - struct mutex tx_power_loop_info_lock; - int force_ps_timeout; -}; - -struct wfx_vif { - struct wfx_dev *wdev; - struct ieee80211_vif *vif; - struct ieee80211_channel *channel; - int id; - - u32 link_id_map; - - bool after_dtim_tx_allowed; - bool join_in_progress; - - struct delayed_work beacon_loss_work; - - struct wfx_queue tx_queue[4]; - struct tx_policy_cache tx_policy_cache; - struct work_struct tx_policy_upload_work; - - struct work_struct update_tim_work; - - unsigned long uapsd_mask; - - /* avoid some operations in parallel with scan */ - struct mutex scan_lock; - struct work_struct scan_work; - struct completion scan_complete; - int scan_nb_chan_done; - bool scan_abort; - struct ieee80211_scan_request *scan_req; - - struct completion set_pm_mode_complete; -}; - -static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id) -{ - if (vif_id >= ARRAY_SIZE(wdev->vif)) { - dev_dbg(wdev->dev, "requesting non-existent vif: %d\n", vif_id); - return NULL; - } - vif_id = array_index_nospec(vif_id, ARRAY_SIZE(wdev->vif)); - if (!wdev->vif[vif_id]) - return NULL; - return (struct wfx_vif *)wdev->vif[vif_id]->drv_priv; -} - -static inline struct wfx_vif *wvif_iterate(struct wfx_dev *wdev, - struct wfx_vif *cur) -{ - int i; - int mark = 0; - struct wfx_vif *tmp; - - if (!cur) - mark = 1; - for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) { - tmp = wdev_to_wvif(wdev, i); - if (mark && tmp) - return tmp; - if (tmp == cur) - mark = 1; - } - return NULL; -} - -static inline int wvif_count(struct wfx_dev *wdev) -{ - int i; - int ret = 0; - struct wfx_vif *wvif; - - for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) { - wvif = wdev_to_wvif(wdev, i); - if (wvif) - ret++; - } - return ret; -} - -static inline void memreverse(u8 *src, u8 length) -{ - u8 *lo = src; - u8 *hi = src + length - 1; - u8 swap; - - while (lo < hi) { - swap = *lo; - *lo++ = *hi; - *hi-- = swap; - } -} - -static inline int memzcmp(void *src, unsigned int size) -{ - u8 *buf = src; - - if (!size) - return 0; - if (*buf) - return 1; - return memcmp(buf, buf + 1, size - 1); -} - -#endif From patchwork Mon Sep 20 16:11:36 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: 12505923 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 35579C4332F for ; Mon, 20 Sep 2021 16:16:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1EBFA60F58 for ; Mon, 20 Sep 2021 16:16:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242738AbhITQSN (ORCPT ); Mon, 20 Sep 2021 12:18:13 -0400 Received: from mail-bn7nam10on2086.outbound.protection.outlook.com ([40.107.92.86]:38017 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S243655AbhITQQQ (ORCPT ); Mon, 20 Sep 2021 12:16:16 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LEwTOG1lmVLIgMOrLaCRiQ8zS12oTCN9bXIcdCv/73mEE4e7CFsKfW8YpdyE6xqES642YzJWCuYJxhnJfKZZmGa6ojlVsbudUMDVP1ZvQ1mhzGRpR4wMxKhLyAqe6d4j4BV9MAjVM0tzoHd3mqsZaWCujWJDLG50N1gfE3vYZhiaGwbKwnSJVgFXu86nf2Xkbg4HnGQsTTCP5OLdudnRcIhsF7XFnstuXg4cJLJYtj781IslEBLdAPhPOrST1oqpHm+RGUsgdZYGyVyTaTWqb4i3TeV5/dBirYXSG5WloXh2V+vFMaJFDUZmhEsozt2nKJdGZRLm+TWU7m3FYGMnkQ== 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=mUblQj3HYl3up8TQr4oInUGypnja+FbX2pQYP1SXPC0=; b=cTKEQ6gnTEo37oDUxYfSx/xZkn8fR1Ic7t/AY5A0rItDLNxJbWwFNgm4w07/gmLLaQUFEg/HJv+MqFMXkhqucJAUq0nRIFuR0kQ74yG2ZnCh9qhsrgXTMoUVYjx7JMhDFvIPY3ccE1rN+lfttkGQm/5H4U9TMdBicL+jUm3jKQaOkBPxAU8gkUtiBYWK6snDaX1dTt6WSHMRNzxZnmfZ8mFXEoRUbwswXeKdubcf0sE2s62v9EC8GaGOkyY/dXEzP7e8i7kLaqGYivKQz/T8udhdxC460CxQfvStcKOo2kDOE40QEzDiTTzXqvmq5apgiTcFfYq6ch6BdXTKABAbuw== 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=mUblQj3HYl3up8TQr4oInUGypnja+FbX2pQYP1SXPC0=; b=CBT7XMPEtFUZ5Eu5do5SpZfnrJUw7e5IUY3p/pf7hGB5tBVKtkNULlfsH+YEgY7qA1FcrEIGdK+Zrut3OzzBMx8qs4x3TW6HBpV7v/8ryTNzw06UHUXjujsuM1TEtYfaTPQQP8b6OvDdHttGCrqjNrxBuDiZguS9sPgZqwBBJa4= 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 SN6PR11MB3168.namprd11.prod.outlook.com (2603:10b6:805:c4::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.18; Mon, 20 Sep 2021 16:12:53 +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:53 +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 24/24] wfx: get out from the staging area Date: Mon, 20 Sep 2021 18:11:36 +0200 Message-Id: <20210920161136.2398632-25-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:51 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 37f59b47-26d0-4cdf-433c-08d97c517fe6 X-MS-TrafficTypeDiagnostic: SN6PR11MB3168: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:6430; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: hns0E1RxdzQJLafL3GOFFJmBwUihFO4+7NiwoilOy5MHYEroL2ITozvI2BSrWYlYsi4skYNL0P2a3OZD6LYTZ0TWkzWKP/m8FkOPdqM5CKw5oDhuUAi/H1URXISzk9djQ7fDA59/uJwFU4LKAJMqgXF1wa/wf12PwG5A9euOCdfeddiD7kYwhJ55jZQx32Dn/DMxzy9pb7vmQuFzK2cLXepeIR5Y4t9G/f/9nSaTt3bSdsS+bWyibt4zkPCTndcK+wDyv9h+HKwtmBZbZi7vWTMGePzEiWCE6uYKMxIaRGaGIpHGe4FyJPjZHcU82WoQEJOSqm+y4a7k8lAC3tWyEjEmEcyOVbTqSiofmuW79qJK1fNZRPIpzn0L+GjNf1b9pwPD/CBZfTB5WWt0ZeJrnJhLd2vBRS053HldXsuU1GGqvTvrxVdNuWPzrHWbXNBqybNro0vQ+6paSPrWKQ/pO1nvaSYCLiPti12FuV02VIxvK7qmaYKwO39Ve9Qe8dR91BilnVYaUNeAYs465BLQVEh7twQifOIYmEIeYXFyS63jMl2vYjf8f5ZURO0EMS/jGyEwdHlwRYDFrmLPxDDRGtixwCqxztSo3JoJuYwtNPFBQ3Zgjtv1iK9ZKkQrcc+hvW0Z7QMZ257MzH5AbFHR2rCc55Glvpl9YONdExRqCi9tK/0tPmMsvF1b9M7MZVgGE1NbRRihYhypIS7Oppv1HXVzIVSzR1vx+TK2ikBl4qI= 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:(366004)(86362001)(1076003)(6666004)(54906003)(5660300002)(8676002)(6916009)(2906002)(38100700002)(8936002)(107886003)(52116002)(186003)(66946007)(66574015)(6486002)(66476007)(4326008)(36756003)(2616005)(508600001)(7416002)(66556008)(966005)(7696005)(316002)(83380400001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: h8i+qqkR9JNsnXXulfIYdCeWuJgQiKLzhtzxP5vDeG08eG4XgggSDfBsf/UgfBntzj3LUWF0P5HCJlpSRzjtp/cqBgivGzBkGybVa81/d869V81JTMSZ8qhCRi0BFP6boYX/5o6vF7hfW5gTwZap9VKGpZ/ml7tLkMDuSICgfVECbTmPBVb0+sgzvgwfOdT1DtUjdJEcalcjTzeDDtRhH4iliiwIwrV/kkiQyzHc87em2UFVAMKEyL9Z5hFi7pwKynEP7V4v7aRidegNfnAHnwhm0xJKwHDgbJkiWldGvDkHPJw2EmxgsNBJfX65UP5TfCLlfRgQWJb2zKs0TJaqrR+51v5PXEDjGfTCqpemCPjORCBqiDQokC/iRA5czoHbjP/v6rzX37cQksohxqXY9Hy9REfF3/732cex7x8BA9lys4stc+ADBE0mlNbr8dmRHFk1ACHjDgoME7OQEvRDcy54kArF83sPctAtKH5m0p9PaBcpdAd0vVMBhNb5ONgwkZyg6I1wemD6kjZgGPuvgO8sBX9ccm3MAbGQIplOLxKVTzW91I+8JLmAmDzhChOq0ExQadWo7Mg/2JQgvj2nisdmhmC/4HGJyh8Jy4fiLGcAECWfB+885hAiDX9wQO4eCqvHNtaFYyMVCb+5gTPGzYvl2Xr3nvt9RydyOWCSr405ZDWBGWhe8sCKyg0WBRsvx1g3ZB+NZ2YYmULBaQTBzzLtnWonKwJzph8/mzpy0Zu4uzLolQQQvkECyZjiWwgBIV4NmJ9fqX2qEbR4o7mu2iCLCWSVfRAMxM/mLxk58xl62EcvSaMx8PXfOlYuw7Yb X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 37f59b47-26d0-4cdf-433c-08d97c517fe6 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:53.2026 (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: wthccZNlrKXLP+WuN21oQlvC977jlekzt/u9tjMKWGYQIWRRkE/osvhPVeoaJGwSc0q8OBodpTQwKdZotxT3vw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR11MB3168 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Jérôme Pouiller The wfx driver is now mature enough to leave the staging area. Signed-off-by: Jérôme Pouiller --- MAINTAINERS | 3 ++- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 1 + drivers/net/wireless/silabs/Kconfig | 18 ++++++++++++++++++ drivers/net/wireless/silabs/Makefile | 3 +++ drivers/staging/Kconfig | 1 - drivers/staging/Makefile | 1 - drivers/staging/wfx/TODO | 6 ------ 8 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 drivers/net/wireless/silabs/Kconfig create mode 100644 drivers/net/wireless/silabs/Makefile delete mode 100644 drivers/staging/wfx/TODO diff --git a/MAINTAINERS b/MAINTAINERS index eeb4c70b3d5b..51993f68379a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17099,7 +17099,8 @@ F: drivers/platform/x86/touchscreen_dmi.c SILICON LABS WIRELESS DRIVERS (for WFxxx series) M: Jérôme Pouiller S: Supported -F: drivers/staging/wfx/ +F: Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml +F: drivers/net/wireless/silabs/wfx/ SILICON MOTION SM712 FRAME BUFFER DRIVER M: Sudip Mukherjee diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7add2002ff4c..e78ff7af6517 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -31,6 +31,7 @@ source "drivers/net/wireless/microchip/Kconfig" source "drivers/net/wireless/ralink/Kconfig" source "drivers/net/wireless/realtek/Kconfig" source "drivers/net/wireless/rsi/Kconfig" +source "drivers/net/wireless/silabs/Kconfig" source "drivers/net/wireless/st/Kconfig" source "drivers/net/wireless/ti/Kconfig" source "drivers/net/wireless/zydas/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 80b324499786..76885e5f0ea7 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_WLAN_VENDOR_MICROCHIP) += microchip/ obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/ obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/ obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/ +obj-$(CONFIG_WLAN_VENDOR_SILABS) += silabs/ obj-$(CONFIG_WLAN_VENDOR_ST) += st/ obj-$(CONFIG_WLAN_VENDOR_TI) += ti/ obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/ diff --git a/drivers/net/wireless/silabs/Kconfig b/drivers/net/wireless/silabs/Kconfig new file mode 100644 index 000000000000..6262a799bf36 --- /dev/null +++ b/drivers/net/wireless/silabs/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 + +config WLAN_VENDOR_SILABS + bool "Silicon Laboratories devices" + default y + help + If you have a wireless card belonging to this class, say Y. + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all the + questions about these cards. If you say Y, you will be asked for + your specific card in the following questions. + +if WLAN_VENDOR_SILABS + +source "drivers/net/wireless/silabs/wfx/Kconfig" + +endif # WLAN_VENDOR_SILABS diff --git a/drivers/net/wireless/silabs/Makefile b/drivers/net/wireless/silabs/Makefile new file mode 100644 index 000000000000..c2263ee21006 --- /dev/null +++ b/drivers/net/wireless/silabs/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_WFX) += wfx/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e03627ad4460..666e23a3ce7e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -100,6 +100,5 @@ source "drivers/staging/fieldbus/Kconfig" source "drivers/staging/qlge/Kconfig" -source "drivers/staging/wfx/Kconfig" endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c7f8d8d8dd11..52a0ae1e1a52 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -40,4 +40,3 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_QLGE) += qlge/ -obj-$(CONFIG_WFX) += wfx/ diff --git a/drivers/staging/wfx/TODO b/drivers/staging/wfx/TODO deleted file mode 100644 index 1b4bc2af94b6..000000000000 --- a/drivers/staging/wfx/TODO +++ /dev/null @@ -1,6 +0,0 @@ -This is a list of things that need to be done to get this driver out of the -staging directory. - - - As suggested by Felix, rate control could be improved following this idea: - https://lore.kernel.org/lkml/3099559.gv3Q75KnN1@pc-42/ -