Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
commit
1609186976
@ -1,30 +1,40 @@
|
||||
BPF_DEPENDS := @HAS_BPF_TOOLCHAIN +@NEED_BPF_TOOLCHAIN
|
||||
LLVM_VER:=
|
||||
|
||||
CLANG_MIN_VER:=12
|
||||
|
||||
ifneq ($(CONFIG_USE_LLVM_HOST),)
|
||||
find-llvm-tool=$(firstword $(shell PATH='$(BPF_PATH)' command -v $(1) || echo '$(firstword $(1))-not-found'))
|
||||
|
||||
BPF_TOOLCHAIN_HOST_PATH:=$(call qstrip,$(CONFIG_BPF_TOOLCHAIN_HOST_PATH))
|
||||
ifneq ($(BPF_TOOLCHAIN_HOST_PATH),)
|
||||
BPF_PATH:=$(BPF_TOOLCHAIN_HOST_PATH)/bin:$(PATH)
|
||||
else
|
||||
BPF_PATH:=$(PATH)
|
||||
endif
|
||||
CLANG:=$(firstword $(shell PATH='$(BPF_PATH)' command -v clang clang-13 clang-12 clang-11))
|
||||
CLANG:=$(call find-llvm-tool,clang clang-13 clang-12)
|
||||
LLVM_VER:=$(subst clang,,$(notdir $(CLANG)))
|
||||
endif
|
||||
ifneq ($(CONFIG_USE_LLVM_PREBUILT),)
|
||||
CLANG:=$(TOPDIR)/llvm-bpf/bin/clang
|
||||
endif
|
||||
ifneq ($(CONFIG_USE_LLVM_BUILD),)
|
||||
CLANG:=$(STAGING_DIR_HOST)/llvm-bpf/bin/clang
|
||||
endif
|
||||
|
||||
LLVM_PATH:=$(dir $(CLANG))
|
||||
LLVM_LLC:=$(LLVM_PATH)/llc$(LLVM_VER)
|
||||
LLVM_DIS:=$(LLVM_PATH)/llvm-dis$(LLVM_VER)
|
||||
LLVM_OPT:=$(LLVM_PATH)/opt$(LLVM_VER)
|
||||
LLVM_STRIP:=$(LLVM_PATH)/llvm-strip$(LLVM_VER)
|
||||
BPF_PATH:=$(dir $(CLANG)):$(BPF_PATH)
|
||||
LLVM_LLC:=$(call find-llvm-tool,llc$(LLVM_VER))
|
||||
LLVM_DIS:=$(call find-llvm-tool,llvm-dis$(LLVM_VER))
|
||||
LLVM_OPT:=$(call find-llvm-tool,opt$(LLVM_VER))
|
||||
LLVM_STRIP:=$(call find-llvm-tool,llvm-strip$(LLVM_VER))
|
||||
else
|
||||
LLVM_PATH:=/invalid
|
||||
|
||||
ifneq ($(CONFIG_USE_LLVM_PREBUILT),)
|
||||
LLVM_PATH:=$(TOPDIR)/llvm-bpf/bin
|
||||
endif
|
||||
ifneq ($(CONFIG_USE_LLVM_BUILD),)
|
||||
LLVM_PATH:=$(STAGING_DIR_HOST)/llvm-bpf/bin
|
||||
endif
|
||||
|
||||
CLANG:=$(LLVM_PATH)/clang
|
||||
LLVM_LLC:=$(LLVM_PATH)/llc
|
||||
LLVM_DIS:=$(LLVM_PATH)/llvm-dis
|
||||
LLVM_OPT:=$(LLVM_PATH)/opt
|
||||
LLVM_STRIP:=$(LLVM_PATH)/llvm-strip
|
||||
endif
|
||||
|
||||
BPF_KARCH:=mips
|
||||
BPF_ARCH:=mips$(if $(CONFIG_ARCH_64BIT),64)$(if $(CONFIG_BIG_ENDIAN),,el)
|
||||
|
@ -28,7 +28,8 @@ linksys,mr7500)
|
||||
netgear,wax214|\
|
||||
netgear,wax610|\
|
||||
netgear,wax610y|\
|
||||
tplink,eap610-outdoor)
|
||||
tplink,eap610-outdoor|\
|
||||
tplink,eap623od-hd-v1)
|
||||
ubootenv_add_mtd "0:appsblenv" "0x0" "0x40000" "0x20000"
|
||||
;;
|
||||
yuncore,fap650)
|
||||
|
@ -6,9 +6,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git
|
||||
PKG_SOURCE_DATE:=2025-04-01
|
||||
PKG_SOURCE_VERSION:=c220fac7fdb35628ba53ff53ed36cf883a401161
|
||||
PKG_MIRROR_HASH:=26338b4f165eb2e90273cd61ed26715b99e496ccf738167e22ff9213ca42c973
|
||||
PKG_SOURCE_DATE:=2025-04-08
|
||||
PKG_SOURCE_VERSION:=9591c9b7578af3548c35bb80cd6c37978669f7c9
|
||||
PKG_MIRROR_HASH:=b5c0024a0c0ebeb61ad6bc037f897685d161f1578aca5a1366dd33603661338b
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
@ -68,6 +68,7 @@ ALLWIFIBOARDS:= \
|
||||
spectrum_sax1v1k \
|
||||
tplink_eap610-outdoor \
|
||||
tplink_eap620hd-v1 \
|
||||
tplink_eap623od-hd-v1 \
|
||||
tplink_eap660hd-v1 \
|
||||
wallys_dr40x9 \
|
||||
xiaomi_ax3600 \
|
||||
@ -216,6 +217,7 @@ $(eval $(call generate-ipq-wifi-package,skspruce_wia3300-20,SKSpruce WIA3300-20)
|
||||
$(eval $(call generate-ipq-wifi-package,spectrum_sax1v1k,Spectrum SAX1V1K))
|
||||
$(eval $(call generate-ipq-wifi-package,tplink_eap610-outdoor,TPLink EAP610-Outdoor))
|
||||
$(eval $(call generate-ipq-wifi-package,tplink_eap620hd-v1,TP-Link EAP620 HD v1))
|
||||
$(eval $(call generate-ipq-wifi-package,tplink_eap623od-hd-v1,TP-Link EAP623-Outdoor HD v1))
|
||||
$(eval $(call generate-ipq-wifi-package,tplink_eap660hd-v1,TP-Link EAP660 HD v1))
|
||||
$(eval $(call generate-ipq-wifi-package,wallys_dr40x9,Wallys DR40X9))
|
||||
$(eval $(call generate-ipq-wifi-package,xiaomi_ax3600,Xiaomi AX3600))
|
||||
|
@ -0,0 +1,273 @@
|
||||
From patchwork Tue Apr 23 12:12:33 2024
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Linus Walleij <linus.walleij@linaro.org>
|
||||
X-Patchwork-Id: 1926515
|
||||
Return-Path:
|
||||
<linux-gpio+bounces-5755-incoming=patchwork.ozlabs.org@vger.kernel.org>
|
||||
X-Original-To: incoming@patchwork.ozlabs.org
|
||||
Delivered-To: patchwork-incoming@legolas.ozlabs.org
|
||||
Authentication-Results: legolas.ozlabs.org;
|
||||
dkim=pass (2048-bit key;
|
||||
unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256
|
||||
header.s=google header.b=qX99TQMM;
|
||||
dkim-atps=neutral
|
||||
Authentication-Results: legolas.ozlabs.org;
|
||||
spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org
|
||||
(client-ip=2604:1380:45e3:2400::1; helo=sv.mirrors.kernel.org;
|
||||
envelope-from=linux-gpio+bounces-5755-incoming=patchwork.ozlabs.org@vger.kernel.org;
|
||||
receiver=patchwork.ozlabs.org)
|
||||
Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org
|
||||
[IPv6:2604:1380:45e3:2400::1])
|
||||
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
|
||||
key-exchange X25519 server-signature ECDSA (secp384r1))
|
||||
(No client certificate requested)
|
||||
by legolas.ozlabs.org (Postfix) with ESMTPS id 4VP1Gc6RZKz1yZP
|
||||
for <incoming@patchwork.ozlabs.org>; Tue, 23 Apr 2024 22:12:56 +1000 (AEST)
|
||||
Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org
|
||||
[52.25.139.140])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
|
||||
(No client certificate requested)
|
||||
by sv.mirrors.kernel.org (Postfix) with ESMTPS id 5BB9C28522A
|
||||
for <incoming@patchwork.ozlabs.org>; Tue, 23 Apr 2024 12:12:55 +0000 (UTC)
|
||||
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
|
||||
by smtp.subspace.kernel.org (Postfix) with ESMTP id 2F83B8563D;
|
||||
Tue, 23 Apr 2024 12:12:41 +0000 (UTC)
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org
|
||||
header.b="qX99TQMM"
|
||||
X-Original-To: linux-gpio@vger.kernel.org
|
||||
Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com
|
||||
[209.85.208.179])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
|
||||
(No client certificate requested)
|
||||
by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8F3C82865
|
||||
for <linux-gpio@vger.kernel.org>; Tue, 23 Apr 2024 12:12:37 +0000 (UTC)
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
arc=none smtp.client-ip=209.85.208.179
|
||||
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
|
||||
t=1713874361; cv=none;
|
||||
b=d6RcvcAu8hBYAK8Io489ZHQpJVXPwuokP6iMcAkbvElCerbXD6jAdqdi+RjDlo5C49GHGO4FQ19UwQn/VE//qSwiK1ulTSBp3OkvAmyb7yYAFnDs9AVNWRw+5/NxeFNn3fj5PyvqVymIbaJKabfrOVNwkz/5JMHxEIJtr6Crmog=
|
||||
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
|
||||
s=arc-20240116; t=1713874361; c=relaxed/simple;
|
||||
bh=0eXJ5AIjzz1TBGZ8SlshIPrEHZaZwZfYEdof+dSpu4Y=;
|
||||
h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc;
|
||||
b=EfFtruUxRIGy+jylEiJ2rPEyPCjGCc8ptT9FVxe6s0O/kW38Y6196xVQeiSV2tSKVCEOIO+9HoqmpgdKsJE7gU9++EcrasP96MYpsklYpc2zsWW3b8QEhfxfZ9Ai/idyYihE2u9dQ7a143P/Ij/twDrZTt24wO/mtHDrE5XcCFI=
|
||||
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
|
||||
dmarc=pass (p=none dis=none) header.from=linaro.org;
|
||||
spf=pass smtp.mailfrom=linaro.org;
|
||||
dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org
|
||||
header.b=qX99TQMM; arc=none smtp.client-ip=209.85.208.179
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
dmarc=pass (p=none dis=none) header.from=linaro.org
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
spf=pass smtp.mailfrom=linaro.org
|
||||
Received: by mail-lj1-f179.google.com with SMTP id
|
||||
38308e7fff4ca-2dd041acff1so40839131fa.1
|
||||
for <linux-gpio@vger.kernel.org>;
|
||||
Tue, 23 Apr 2024 05:12:37 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=linaro.org; s=google; t=1713874356; x=1714479156;
|
||||
darn=vger.kernel.org;
|
||||
h=cc:to:message-id:content-transfer-encoding:mime-version:subject
|
||||
:date:from:from:to:cc:subject:date:message-id:reply-to;
|
||||
bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=;
|
||||
b=qX99TQMMdHbskFYUaw8c93sIJsUhKmj/WPdyahHcupUhwn5wol4aVoPczkOKYwJZhE
|
||||
eoInxzjAHIl3UNKyvPPrD4MrbLcSoFT6mTFMsgRQYUghsLattmGcqIebu9XT556dBhsf
|
||||
DydmpqGgnTOIa+IEknFxg24mo8Xn2LVmDC7LSGEYykUy1xLHd1NSq56YEaYXC7641xeZ
|
||||
9TOL0rZszeGld5cCS3013EmEeXQGCC3lAP83Eb48vbFXjPojkN0s40rZ2s8YpVsGT0iP
|
||||
LeLVtP/E8XJqi4YipKryKSgbgOvQ1Bclle5+s+2qcJQNnSEjekMwR59BIRs3OZH2SRfN
|
||||
gQdQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20230601; t=1713874356; x=1714479156;
|
||||
h=cc:to:message-id:content-transfer-encoding:mime-version:subject
|
||||
:date:from:x-gm-message-state:from:to:cc:subject:date:message-id
|
||||
:reply-to;
|
||||
bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=;
|
||||
b=jEBH4NQ7SzFi2tnb1lgL06IchnBJoscNgKesjlorvou6X/9wDE/VbgxNFKR0zWwdTk
|
||||
BEjG/ifFJxLmM9jdaCKu5cJc4yiDNXp7yZd48D71V34zJ4aINAGAx4hcOKqf95neFknx
|
||||
nsFPpBFnTYFEpCLF0TebVoL6h6ehPzSojmkArzsrMppNvW2cwJ5gDlkqy2y4SezLanmM
|
||||
6iU0ksnwE0bb2iLkahhgo00Ejt33yqxwa+3xBfhOe9oYKSSZYnY7qVq055SSwt9IAq+H
|
||||
REGyJN+GrvupTHagiioYe3LPXDPdOui9ZixXXDllw1t1yGUy+TkJu8xSqtvHEfg81FHP
|
||||
AxtA==
|
||||
X-Forwarded-Encrypted: i=1;
|
||||
AJvYcCUbxzPklfPYrLgyY1I0ycuj7Dh04dcGVonYocA2mzxzlAEV107o0ELlFqr3O9Td+tV/t0eV9ly9YAbTY6n1XPnFXS5dsYYAZw6RHw==
|
||||
X-Gm-Message-State: AOJu0YxsC7zdakTzntbiRFnN2A7yTrR0x+IpR6ce6eGn5kHeqIBi1km+
|
||||
zTVpRulbch3JsmzVDbCbbAAYoBkNgEA568YL6zdjVARnvFwNz1cqatOrR1AXUm0=
|
||||
X-Google-Smtp-Source:
|
||||
AGHT+IHBRMGvaJM98f86Z6m/RfVhK2XejjNGF3EvcRq/4x3oGM0DKpd2PbeCJdgmzHjLPVVbdsNzJg==
|
||||
X-Received: by 2002:a2e:9852:0:b0:2d8:a98d:18e with SMTP id
|
||||
e18-20020a2e9852000000b002d8a98d018emr7955886ljj.8.1713874355700;
|
||||
Tue, 23 Apr 2024 05:12:35 -0700 (PDT)
|
||||
Received: from [192.168.1.140] ([85.235.12.238])
|
||||
by smtp.gmail.com with ESMTPSA id
|
||||
x6-20020a2e7c06000000b002da179d8d25sm1628982ljc.64.2024.04.23.05.12.33
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Tue, 23 Apr 2024 05:12:35 -0700 (PDT)
|
||||
From: Linus Walleij <linus.walleij@linaro.org>
|
||||
Date: Tue, 23 Apr 2024 14:12:33 +0200
|
||||
Subject: [PATCH v2] wifi: ath9k: Obtain system GPIOS from descriptors
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-gpio@vger.kernel.org
|
||||
List-Id: <linux-gpio.vger.kernel.org>
|
||||
List-Subscribe: <mailto:linux-gpio+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:linux-gpio+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
Message-Id: <20240423-descriptors-wireless-v2-1-6d1d03b30bfa@linaro.org>
|
||||
X-B4-Tracking: v=1; b=H4sIALClJ2YC/22Nyw6CMBBFf4XM2hpanrLyPwyL0o4wCaFkxqCG9
|
||||
N+txKXLc5Nz7g6CTCjQZTswbiQUlgTmlIGb7DKiIp8YTG7KXBujPIpjWh+BRT2JcUYRNbTeXir
|
||||
v7FBUkNSV8U6vI3vrE08kSXgfL5v+rr9gof8HN61yhdo1rvJ125T1dabFcjgHHqGPMX4Ao4iiN
|
||||
LkAAAA=
|
||||
To: Kalle Valo <kvalo@kernel.org>,
|
||||
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
|
||||
Arnd Bergmann <arnd@arndb.de>, Alban Bedel <albeu@free.fr>,
|
||||
Bartosz Golaszewski <brgl@bgdev.pl>, =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rg?=
|
||||
=?utf-8?q?ensen?= <toke@toke.dk>
|
||||
Cc: linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com,
|
||||
linux-gpio@vger.kernel.org, Linus Walleij <linus.walleij@linaro.org>
|
||||
X-Mailer: b4 0.13.0
|
||||
|
||||
The ath9k has an odd use of system-wide GPIOs: if the chip
|
||||
does not have internal GPIO capability, it will try to obtain a
|
||||
GPIO line from the system GPIO controller:
|
||||
|
||||
if (BIT(gpio) & ah->caps.gpio_mask)
|
||||
ath9k_hw_gpio_cfg_wmac(...);
|
||||
else if (AR_SREV_SOC(ah))
|
||||
ath9k_hw_gpio_cfg_soc(ah, gpio, out, label);
|
||||
|
||||
Where ath9k_hw_gpio_cfg_soc() will attempt to issue
|
||||
gpio_request_one() passing the local GPIO number of the controller
|
||||
(0..31) to gpio_request_one().
|
||||
|
||||
This is somewhat peculiar and possibly even dangerous: there is
|
||||
nowadays no guarantee of the numbering of these system-wide
|
||||
GPIOs, and assuming that GPIO 0..31 as used by ath9k would
|
||||
correspond to GPIOs 0..31 on the system as a whole seems a bit
|
||||
wild.
|
||||
|
||||
Register all 32 GPIOs at index 0..31 directly in the ATH79K
|
||||
GPIO driver and associate with WIFI if and only if we are probing
|
||||
ATH79K wifi from the AHB bus (used for SoCs).
|
||||
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
Changes in v2:
|
||||
- Define all the descriptors directly in the ATH79K
|
||||
GPIO driver in case the driver want to request them directly.
|
||||
- Link to v1: https://lore.kernel.org/r/20240131-descriptors-wireless-v1-0-e1c7c5d68746@linaro.org
|
||||
---
|
||||
drivers/net/wireless/ath/ath9k/hw.c | 29 ++++++++++++-----------
|
||||
drivers/net/wireless/ath/ath9k/hw.h | 3 ++-
|
||||
2 files changed, 32 insertions(+), 15 deletions(-)
|
||||
|
||||
|
||||
---
|
||||
base-commit: 4cece764965020c22cff7665b18a012006359095
|
||||
change-id: 20240122-descriptors-wireless-b8da95dcab35
|
||||
|
||||
Best regards,
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/etherdevice.h>
|
||||
-#include <linux/gpio.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include "hw.h"
|
||||
@@ -2727,19 +2727,25 @@ static void ath9k_hw_gpio_cfg_output_mux
|
||||
static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
|
||||
const char *label)
|
||||
{
|
||||
+ enum gpiod_flags flags = out ? GPIOD_OUT_LOW : GPIOD_IN;
|
||||
+ struct gpio_desc *gpiod;
|
||||
int err;
|
||||
|
||||
- if (ah->caps.gpio_requested & BIT(gpio))
|
||||
+ if (ah->gpiods[gpio])
|
||||
return;
|
||||
|
||||
- err = devm_gpio_request_one(ah->dev, gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label);
|
||||
- if (err) {
|
||||
+ /* Obtains a system specific GPIO descriptor from another GPIO controller */
|
||||
+ gpiod = gpiod_get_index(NULL, "ath9k", gpio, flags);
|
||||
+
|
||||
+ if (IS_ERR(gpiod)) {
|
||||
+ err = PTR_ERR(gpiod);
|
||||
ath_err(ath9k_hw_common(ah), "request GPIO%d failed:%d\n",
|
||||
gpio, err);
|
||||
return;
|
||||
}
|
||||
|
||||
- ah->caps.gpio_requested |= BIT(gpio);
|
||||
+ gpiod_set_consumer_name(gpiod, label);
|
||||
+ ah->gpiods[gpio] = gpiod;
|
||||
}
|
||||
|
||||
static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out,
|
||||
@@ -2801,8 +2807,10 @@ void ath9k_hw_gpio_free(struct ath_hw *a
|
||||
|
||||
WARN_ON(gpio >= ah->caps.num_gpio_pins);
|
||||
|
||||
- if (ah->caps.gpio_requested & BIT(gpio))
|
||||
- ah->caps.gpio_requested &= ~BIT(gpio);
|
||||
+ if (ah->gpiods[gpio]) {
|
||||
+ gpiod_put(ah->gpiods[gpio]);
|
||||
+ ah->gpiods[gpio] = NULL;
|
||||
+ }
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_gpio_free);
|
||||
|
||||
@@ -2830,8 +2838,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah,
|
||||
val = REG_READ(ah, AR_GPIO_IN(ah)) & BIT(gpio);
|
||||
else
|
||||
val = MS_REG_READ(AR, gpio);
|
||||
- } else if (BIT(gpio) & ah->caps.gpio_requested) {
|
||||
- val = gpio_get_value(gpio) & BIT(gpio);
|
||||
+ } else if (ah->gpiods[gpio]) {
|
||||
+ val = gpiod_get_value(ah->gpiods[gpio]);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
@@ -2854,8 +2862,8 @@ void ath9k_hw_set_gpio(struct ath_hw *ah
|
||||
AR7010_GPIO_OUT : AR_GPIO_IN_OUT(ah);
|
||||
|
||||
REG_RMW(ah, out_addr, val << gpio, BIT(gpio));
|
||||
- } else if (BIT(gpio) & ah->caps.gpio_requested) {
|
||||
- gpio_set_value(gpio, val);
|
||||
+ } else if (ah->gpiods[gpio]) {
|
||||
+ gpiod_set_value(ah->gpiods[gpio], val);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/delay.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
@@ -302,7 +303,6 @@ struct ath9k_hw_capabilities {
|
||||
u8 max_rxchains;
|
||||
u8 num_gpio_pins;
|
||||
u32 gpio_mask;
|
||||
- u32 gpio_requested;
|
||||
u8 rx_hp_qdepth;
|
||||
u8 rx_lp_qdepth;
|
||||
u8 rx_status_len;
|
||||
@@ -783,6 +783,7 @@ struct ath_hw {
|
||||
struct ath9k_hw_capabilities caps;
|
||||
struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
|
||||
struct ath9k_channel *curchan;
|
||||
+ struct gpio_desc *gpiods[32];
|
||||
|
||||
union {
|
||||
struct ar5416_eeprom_def def;
|
@ -8,7 +8,7 @@ This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411.
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -2975,7 +2975,8 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
@@ -2983,7 +2983,8 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
{
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
struct ieee80211_channel *channel;
|
||||
@ -18,7 +18,7 @@ This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411.
|
||||
u16 ctl = NO_CTL;
|
||||
|
||||
if (!chan)
|
||||
@@ -2987,9 +2988,14 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
@@ -2995,9 +2996,14 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
channel = chan->chan;
|
||||
chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER);
|
||||
new_pwr = min_t(int, chan_pwr, reg->power_limit);
|
||||
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -2994,6 +2994,10 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
@@ -3002,6 +3002,10 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
if (ant_gain > max_gain)
|
||||
ant_reduction = ant_gain - max_gain;
|
||||
|
||||
|
@ -0,0 +1,127 @@
|
||||
From da57e63c91ce11a640b1d38412be8c0d8655b8d9 Mon Sep 17 00:00:00 2001
|
||||
From: Rosen Penev <rosenp@gmail.com>
|
||||
Date: Sat, 4 Jan 2025 14:24:46 -0800
|
||||
Subject: [PATCH] ath9k: use devm for irq and ioremap resource
|
||||
|
||||
Avoids having to manually free. Both of these get called and removed in
|
||||
probe only and are safe to convert.
|
||||
|
||||
devm_platform_ioremap_resource is different as it also calls
|
||||
devm_request_memory_region, which requires non overlapping memory
|
||||
regions. Luckily, that seems to be the case.
|
||||
|
||||
Tested on a TP-Link Archer C7v2.
|
||||
|
||||
Signed-off-by: Rosen Penev <rosenp@gmail.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath9k/ahb.c | 22 ++++++----------------
|
||||
drivers/net/wireless/ath/ath9k/pci.c | 9 +++------
|
||||
2 files changed, 9 insertions(+), 22 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ahb.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
|
||||
@@ -74,7 +74,6 @@ static int ath_ahb_probe(struct platform
|
||||
void __iomem *mem;
|
||||
struct ath_softc *sc;
|
||||
struct ieee80211_hw *hw;
|
||||
- struct resource *res;
|
||||
const struct platform_device_id *id = platform_get_device_id(pdev);
|
||||
int irq;
|
||||
int ret = 0;
|
||||
@@ -86,16 +85,10 @@ static int ath_ahb_probe(struct platform
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- if (res == NULL) {
|
||||
- dev_err(&pdev->dev, "no memory resource found\n");
|
||||
- return -ENXIO;
|
||||
- }
|
||||
-
|
||||
- mem = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
- if (mem == NULL) {
|
||||
+ mem = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(mem)) {
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
- return -ENOMEM;
|
||||
+ return PTR_ERR(mem);
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
@@ -118,16 +111,16 @@ static int ath_ahb_probe(struct platform
|
||||
sc->mem = mem;
|
||||
sc->irq = irq;
|
||||
|
||||
- ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
+ ret = devm_request_irq(&pdev->dev, irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "request_irq failed\n");
|
||||
- goto err_free_hw;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize device\n");
|
||||
- goto err_irq;
|
||||
+ goto err_free_hw;
|
||||
}
|
||||
|
||||
ah = sc->sc_ah;
|
||||
@@ -137,8 +130,6 @@ static int ath_ahb_probe(struct platform
|
||||
|
||||
return 0;
|
||||
|
||||
- err_irq:
|
||||
- free_irq(irq, sc);
|
||||
err_free_hw:
|
||||
ieee80211_free_hw(hw);
|
||||
return ret;
|
||||
@@ -152,7 +143,6 @@ static void ath_ahb_remove(struct platfo
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
ath9k_deinit_device(sc);
|
||||
- free_irq(sc->irq, sc);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
}
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/pci.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/pci.c
|
||||
@@ -965,9 +965,9 @@ static int ath_pci_probe(struct pci_dev
|
||||
}
|
||||
|
||||
if (!msi_enabled)
|
||||
- ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
+ ret = devm_request_irq(&pdev->dev, pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
else
|
||||
- ret = request_irq(pdev->irq, ath_isr, 0, "ath9k", sc);
|
||||
+ ret = devm_request_irq(&pdev->dev, pdev->irq, ath_isr, 0, "ath9k", sc);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "request_irq failed\n");
|
||||
@@ -979,7 +979,7 @@ static int ath_pci_probe(struct pci_dev
|
||||
ret = ath9k_init_device(id->device, sc, &ath_pci_bus_ops);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to initialize device\n");
|
||||
- goto err_init;
|
||||
+ goto err_irq;
|
||||
}
|
||||
|
||||
sc->sc_ah->msi_enabled = msi_enabled;
|
||||
@@ -991,8 +991,6 @@ static int ath_pci_probe(struct pci_dev
|
||||
|
||||
return 0;
|
||||
|
||||
-err_init:
|
||||
- free_irq(sc->irq, sc);
|
||||
err_irq:
|
||||
ieee80211_free_hw(hw);
|
||||
return ret;
|
||||
@@ -1006,7 +1004,6 @@ static void ath_pci_remove(struct pci_de
|
||||
if (!is_ath9k_unloaded)
|
||||
sc->sc_ah->ah_flags |= AH_UNPLUGGED;
|
||||
ath9k_deinit_device(sc);
|
||||
- free_irq(sc->irq, sc);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
case AR5416_AR9100_DEVID:
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -36,6 +36,7 @@
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#define ATHEROS_VENDOR_ID 0x168c
|
||||
|
||||
|
@ -1,64 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
+#include <linux/ath9k_platform.h>
|
||||
|
||||
/********************************/
|
||||
/* LED functions */
|
||||
@@ -108,6 +109,24 @@ int ath_create_gpio_led(struct ath_softc
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int ath_create_platform_led(struct ath_softc *sc,
|
||||
+ const struct gpio_led *gpio)
|
||||
+{
|
||||
+ struct ath_led *led;
|
||||
+ int ret;
|
||||
+
|
||||
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
|
||||
+ if (!led)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ led->gpio = gpio;
|
||||
+ ret = ath_add_led(sc, led);
|
||||
+ if (ret < 0)
|
||||
+ kfree(led);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void ath_deinit_leds(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_led *led;
|
||||
@@ -124,8 +143,10 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
|
||||
void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
char led_name[32];
|
||||
const char *trigger;
|
||||
+ int i;
|
||||
|
||||
INIT_LIST_HEAD(&sc->leds);
|
||||
|
||||
@@ -134,6 +155,17 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
|
||||
ath_fill_led_pin(sc);
|
||||
|
||||
+ if (pdata && pdata->leds && pdata->num_leds)
|
||||
+ for (i = 0; i < pdata->num_leds; i++) {
|
||||
+ if (pdata->leds[i].gpio == sc->sc_ah->led_pin)
|
||||
+ sc->sc_ah->led_pin = -1;
|
||||
+
|
||||
+ ath_create_platform_led(sc, &pdata->leds[i]);
|
||||
+ }
|
||||
+
|
||||
+ if (sc->sc_ah->led_pin < 0)
|
||||
+ return;
|
||||
+
|
||||
snprintf(led_name, sizeof(led_name), "ath9k-%s",
|
||||
wiphy_name(sc->hw->wiphy));
|
||||
|
@ -75,7 +75,7 @@
|
||||
struct ath9k_hw_version {
|
||||
u32 magic;
|
||||
u16 devid;
|
||||
@@ -810,6 +816,8 @@ struct ath_hw {
|
||||
@@ -811,6 +817,8 @@ struct ath_hw {
|
||||
u32 ah_flags;
|
||||
s16 nf_override;
|
||||
|
||||
@ -84,7 +84,7 @@
|
||||
bool reset_power_on;
|
||||
bool htc_reset_init;
|
||||
|
||||
@@ -1079,6 +1087,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
|
||||
@@ -1080,6 +1088,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
|
||||
bool ath9k_hw_check_alive(struct ath_hw *ah);
|
||||
|
||||
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
|
||||
|
@ -13,7 +13,7 @@ Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc
|
||||
@@ -73,8 +73,11 @@ static int ath_add_led(struct ath_softc
|
||||
ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
|
||||
|
@ -10,47 +10,32 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -25,6 +25,7 @@
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/hw_random.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
@@ -991,6 +992,14 @@ struct ath_led {
|
||||
struct led_classdev cdev;
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_GPIOLIB
|
||||
+struct ath9k_gpio_chip {
|
||||
+ struct ath_softc *sc;
|
||||
+ char label[32];
|
||||
+ struct gpio_chip gchip;
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@@ -1046,6 +1055,9 @@ struct ath_softc {
|
||||
@@ -1046,6 +1048,10 @@ struct ath_softc {
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
const char *led_default_trigger;
|
||||
struct list_head leds;
|
||||
+#ifdef CONFIG_GPIOLIB
|
||||
+ struct ath9k_gpio_chip *gpiochip;
|
||||
+ struct gpio_chip *gpiochip;
|
||||
+ struct gpio_desc *gpiodesc;
|
||||
+#endif
|
||||
#endif
|
||||
|
||||
#ifdef CPTCFG_ATH9K_DEBUGFS
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -16,13 +16,135 @@
|
||||
@@ -16,12 +16,120 @@
|
||||
|
||||
#include "ath9k.h"
|
||||
#include <linux/ath9k_platform.h>
|
||||
+#include <linux/gpio.h>
|
||||
+
|
||||
|
||||
+#ifdef CPTCFG_MAC80211_LEDS
|
||||
+
|
||||
+#ifdef CONFIG_GPIOLIB
|
||||
@ -62,10 +47,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+/* gpio_chip handler : set GPIO to input */
|
||||
+static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||
+ gchip);
|
||||
+ struct ath_softc *sc = gpiochip_get_data(chip);
|
||||
+
|
||||
+ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio");
|
||||
+ ath9k_hw_gpio_request_in(sc->sc_ah, offset, "ath9k-gpio");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
@ -74,12 +58,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
|
||||
+ int value)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||
+ gchip);
|
||||
+ struct ath_softc *sc = gpiochip_get_data(chip);
|
||||
+
|
||||
+ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio",
|
||||
+ ath9k_hw_gpio_request_out(sc->sc_ah, offset, "ath9k-gpio",
|
||||
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||
+ ath9k_hw_set_gpio(sc->sc_ah, offset, value);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
@ -87,9 +70,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
|
||||
+static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||
+ gchip);
|
||||
+ struct ath_hw *ah = gc->sc->sc_ah;
|
||||
+ struct ath_softc *sc = gpiochip_get_data(chip);
|
||||
+ struct ath_hw *ah = sc->sc_ah;
|
||||
+
|
||||
+ return !((REG_READ(ah, AR_GPIO_OE_OUT(ah)) >> (offset * 2)) & 3);
|
||||
+}
|
||||
@ -97,69 +79,59 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+/* gpio_chip handler : get GPIO pin value */
|
||||
+static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||
+ gchip);
|
||||
+ struct ath_softc *sc = gpiochip_get_data(chip);
|
||||
+
|
||||
+ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
|
||||
+ return ath9k_hw_gpio_get(sc->sc_ah, offset);
|
||||
+}
|
||||
+
|
||||
+/* gpio_chip handler : set GPIO pin to value */
|
||||
+static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
|
||||
+ int value)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||
+ gchip);
|
||||
+ struct ath_softc *sc = gpiochip_get_data(chip);
|
||||
+
|
||||
+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||
+ ath9k_hw_set_gpio(sc->sc_ah, offset, value);
|
||||
+}
|
||||
+
|
||||
+/* register GPIO chip */
|
||||
+static void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc;
|
||||
+ struct gpio_chip *gc = sc->gpiochip;
|
||||
+ struct ath_hw *ah = sc->sc_ah;
|
||||
+
|
||||
+ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
|
||||
+ gc = kzalloc(sizeof(struct gpio_chip), GFP_KERNEL);
|
||||
+ if (!gc)
|
||||
+ return;
|
||||
+
|
||||
+ gc->sc = sc;
|
||||
+ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
|
||||
+ wiphy_name(sc->hw->wiphy));
|
||||
+#ifdef CONFIG_OF
|
||||
+ gc->gchip.parent = sc->dev;
|
||||
+#endif
|
||||
+ gc->gchip.label = gc->label;
|
||||
+ gc->gchip.base = -1; /* determine base automatically */
|
||||
+ gc->gchip.ngpio = ah->caps.num_gpio_pins;
|
||||
+ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
|
||||
+ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
|
||||
+ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
|
||||
+ gc->gchip.get = ath9k_gpio_pin_get;
|
||||
+ gc->gchip.set = ath9k_gpio_pin_set;
|
||||
+ gc->label = kasprintf(GFP_KERNEL, "ath9k-%s",
|
||||
+ wiphy_name(sc->hw->wiphy));
|
||||
+ gc->parent = sc->dev;
|
||||
+ gc->base = -1; /* determine base automatically */
|
||||
+ gc->ngpio = ah->caps.num_gpio_pins;
|
||||
+ gc->direction_input = ath9k_gpio_pin_cfg_input;
|
||||
+ gc->direction_output = ath9k_gpio_pin_cfg_output;
|
||||
+ gc->get_direction = ath9k_gpio_pin_get_dir;
|
||||
+ gc->get = ath9k_gpio_pin_get;
|
||||
+ gc->set = ath9k_gpio_pin_set;
|
||||
+
|
||||
+ if (gpiochip_add(&gc->gchip)) {
|
||||
+ if (gpiochip_add_data(gc, sc)) {
|
||||
+ kfree(gc->label);
|
||||
+ kfree(gc);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+ gc->gchip.owner = NULL;
|
||||
+#endif
|
||||
+ sc->gpiochip = gc;
|
||||
+}
|
||||
+
|
||||
+/* remove GPIO chip */
|
||||
+static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||
+{
|
||||
+ struct ath9k_gpio_chip *gc = sc->gpiochip;
|
||||
+ struct gpio_chip *gc = sc->gpiochip;
|
||||
+
|
||||
+ if (!gc)
|
||||
+ return;
|
||||
+
|
||||
+ gpiochip_remove(&gc->gchip);
|
||||
+ gpiochip_remove(gc);
|
||||
+ kfree(gc->label);
|
||||
+ kfree(gc);
|
||||
+ sc->gpiochip = NULL;
|
||||
+}
|
||||
+
|
||||
+#else /* CONFIG_GPIOLIB */
|
||||
@ -173,7 +145,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+}
|
||||
+
|
||||
+#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
+
|
||||
/********************************/
|
||||
/* LED functions */
|
||||
/********************************/
|
||||
@ -183,27 +155,27 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static void ath_fill_led_pin(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@@ -80,6 +202,12 @@ static int ath_add_led(struct ath_softc
|
||||
@@ -79,6 +187,12 @@ static int ath_add_led(struct ath_softc
|
||||
else
|
||||
ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||
|
||||
+#ifdef CONFIG_GPIOLIB
|
||||
+ /* If there is GPIO chip configured, reserve LED pin */
|
||||
+ if (sc->gpiochip)
|
||||
+ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
|
||||
+ sc->gpiodesc = gpiod_get(sc->dev, gpio->name, GPIOD_ASIS);
|
||||
+#endif
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -136,17 +264,24 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
@@ -117,16 +231,23 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
|
||||
while (!list_empty(&sc->leds)) {
|
||||
led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||
+#ifdef CONFIG_GPIOLIB
|
||||
+ /* If there is GPIO chip configured, free LED pin */
|
||||
+ if (sc->gpiochip)
|
||||
+ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
|
||||
+ gpiod_put(sc->gpiodesc);
|
||||
+#endif
|
||||
list_del(&led->list);
|
||||
ath_led_brightness(&led->cdev, LED_OFF);
|
||||
@ -216,12 +188,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
+ struct device_node *np = sc->dev->of_node;
|
||||
char led_name[32];
|
||||
const char *trigger;
|
||||
int i;
|
||||
@@ -156,6 +291,15 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
|
||||
@@ -135,6 +256,15 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
if (AR_SREV_9100(sc->sc_ah))
|
||||
return;
|
||||
|
||||
@ -236,12 +207,4 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+
|
||||
ath_fill_led_pin(sc);
|
||||
|
||||
if (pdata && pdata->leds && pdata->num_leds)
|
||||
@@ -180,6 +324,7 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
|
||||
!sc->sc_ah->config.led_active_high);
|
||||
}
|
||||
+
|
||||
#endif
|
||||
|
||||
/*******************/
|
||||
snprintf(led_name, sizeof(led_name), "ath9k-%s",
|
||||
|
@ -1,130 +0,0 @@
|
||||
From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||
Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
|
||||
|
||||
Enable platform-defined GPIO button support for ath9k device.
|
||||
Key poller is activated for attached platform buttons.
|
||||
Requires ath9k GPIO chip access.
|
||||
|
||||
Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -1057,6 +1057,7 @@ struct ath_softc {
|
||||
struct list_head leds;
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct ath9k_gpio_chip *gpiochip;
|
||||
+ struct platform_device *btnpdev; /* gpio-keys-polled */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "ath9k.h"
|
||||
#include <linux/ath9k_platform.h>
|
||||
#include <linux/gpio.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/gpio_keys.h>
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
|
||||
@@ -129,6 +131,67 @@ static void ath9k_unregister_gpio_chip(s
|
||||
sc->gpiochip = NULL;
|
||||
}
|
||||
|
||||
+/******************/
|
||||
+/* GPIO Buttons */
|
||||
+/******************/
|
||||
+
|
||||
+/* add GPIO buttons */
|
||||
+static void ath9k_init_buttons(struct ath_softc *sc)
|
||||
+{
|
||||
+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
+ struct platform_device *pdev;
|
||||
+ struct gpio_keys_platform_data gkpdata;
|
||||
+ struct gpio_keys_button *bt;
|
||||
+ int i;
|
||||
+
|
||||
+ if (!sc->gpiochip)
|
||||
+ return;
|
||||
+
|
||||
+ if (!pdata || !pdata->btns || !pdata->num_btns)
|
||||
+ return;
|
||||
+
|
||||
+ bt = devm_kmemdup(sc->dev, pdata->btns,
|
||||
+ pdata->num_btns * sizeof(struct gpio_keys_button),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!bt)
|
||||
+ return;
|
||||
+
|
||||
+ for (i = 0; i < pdata->num_btns; i++) {
|
||||
+ if (pdata->btns[i].gpio == sc->sc_ah->led_pin)
|
||||
+ sc->sc_ah->led_pin = -1;
|
||||
+
|
||||
+ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio,
|
||||
+ "ath9k-gpio");
|
||||
+ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
|
||||
+ }
|
||||
+
|
||||
+ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
|
||||
+ gkpdata.buttons = bt;
|
||||
+ gkpdata.nbuttons = pdata->num_btns;
|
||||
+ gkpdata.poll_interval = pdata->btn_poll_interval;
|
||||
+
|
||||
+ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
|
||||
+ PLATFORM_DEVID_AUTO, &gkpdata,
|
||||
+ sizeof(gkpdata));
|
||||
+ if (!IS_ERR_OR_NULL(pdev))
|
||||
+ sc->btnpdev = pdev;
|
||||
+ else {
|
||||
+ sc->btnpdev = NULL;
|
||||
+ devm_kfree(sc->dev, bt);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* remove GPIO buttons */
|
||||
+static void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||
+{
|
||||
+ if (!sc->gpiochip || !sc->btnpdev)
|
||||
+ return;
|
||||
+
|
||||
+ platform_device_unregister(sc->btnpdev);
|
||||
+
|
||||
+ sc->btnpdev = NULL;
|
||||
+}
|
||||
+
|
||||
#else /* CONFIG_GPIOLIB */
|
||||
|
||||
static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||
@@ -139,6 +202,14 @@ static inline void ath9k_unregister_gpio
|
||||
{
|
||||
}
|
||||
|
||||
+static inline void ath9k_init_buttons(struct ath_softc *sc)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
/********************************/
|
||||
@@ -262,6 +333,7 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
{
|
||||
struct ath_led *led;
|
||||
|
||||
+ ath9k_deinit_buttons(sc);
|
||||
while (!list_empty(&sc->leds)) {
|
||||
led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
@@ -301,6 +373,7 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
}
|
||||
|
||||
ath_fill_led_pin(sc);
|
||||
+ ath9k_init_buttons(sc);
|
||||
|
||||
if (pdata && pdata->leds && pdata->num_leds)
|
||||
for (i = 0; i < pdata->num_leds; i++) {
|
@ -209,7 +209,7 @@
|
||||
static int ath_ahb_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *mem;
|
||||
@@ -80,6 +274,17 @@ static int ath_ahb_probe(struct platform
|
||||
@@ -79,6 +273,17 @@ static int ath_ahb_probe(struct platform
|
||||
int ret = 0;
|
||||
struct ath_hw *ah;
|
||||
char hw_name[64];
|
||||
@ -227,24 +227,24 @@
|
||||
|
||||
if (!dev_get_platdata(&pdev->dev)) {
|
||||
dev_err(&pdev->dev, "no platform data specified\n");
|
||||
@@ -118,17 +323,23 @@ static int ath_ahb_probe(struct platform
|
||||
@@ -111,17 +316,23 @@ static int ath_ahb_probe(struct platform
|
||||
sc->mem = mem;
|
||||
sc->irq = irq;
|
||||
|
||||
+#ifdef CONFIG_OF
|
||||
+ dev_id = of_ath_ahb_probe(pdev);
|
||||
+#endif
|
||||
ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
ret = devm_request_irq(&pdev->dev, irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "request_irq failed\n");
|
||||
goto err_free_hw;
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
|
||||
+ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize device\n");
|
||||
goto err_irq;
|
||||
goto err_free_hw;
|
||||
}
|
||||
+#ifdef CONFIG_OF
|
||||
+ pdev->dev.platform_data = NULL;
|
||||
@ -252,7 +252,7 @@
|
||||
|
||||
ah = sc->sc_ah;
|
||||
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
|
||||
@@ -162,6 +373,9 @@ static struct platform_driver ath_ahb_dr
|
||||
@@ -152,6 +363,9 @@ static struct platform_driver ath_ahb_dr
|
||||
.remove_new = ath_ahb_remove,
|
||||
.driver = {
|
||||
.name = "ath9k",
|
||||
@ -264,15 +264,15 @@
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/time.h>
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
+#include <linux/reset.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
@@ -1013,6 +1014,9 @@ struct ath_softc {
|
||||
@@ -1006,6 +1007,9 @@ struct ath_softc {
|
||||
struct ath_hw *sc_ah;
|
||||
void __iomem *mem;
|
||||
int irq;
|
||||
|
@ -816,7 +816,7 @@
|
||||
|
||||
gsw_phy2_led1: gsw-phy2-led1@1 {
|
||||
reg = <1>;
|
||||
function = "phy1_led1";
|
||||
function = "phy2_led1";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,233 @@
|
||||
From patchwork Tue Apr 23 12:12:33 2024
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Linus Walleij <linus.walleij@linaro.org>
|
||||
X-Patchwork-Id: 1926515
|
||||
Return-Path:
|
||||
<linux-gpio+bounces-5755-incoming=patchwork.ozlabs.org@vger.kernel.org>
|
||||
X-Original-To: incoming@patchwork.ozlabs.org
|
||||
Delivered-To: patchwork-incoming@legolas.ozlabs.org
|
||||
Authentication-Results: legolas.ozlabs.org;
|
||||
dkim=pass (2048-bit key;
|
||||
unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256
|
||||
header.s=google header.b=qX99TQMM;
|
||||
dkim-atps=neutral
|
||||
Authentication-Results: legolas.ozlabs.org;
|
||||
spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org
|
||||
(client-ip=2604:1380:45e3:2400::1; helo=sv.mirrors.kernel.org;
|
||||
envelope-from=linux-gpio+bounces-5755-incoming=patchwork.ozlabs.org@vger.kernel.org;
|
||||
receiver=patchwork.ozlabs.org)
|
||||
Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org
|
||||
[IPv6:2604:1380:45e3:2400::1])
|
||||
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
|
||||
key-exchange X25519 server-signature ECDSA (secp384r1))
|
||||
(No client certificate requested)
|
||||
by legolas.ozlabs.org (Postfix) with ESMTPS id 4VP1Gc6RZKz1yZP
|
||||
for <incoming@patchwork.ozlabs.org>; Tue, 23 Apr 2024 22:12:56 +1000 (AEST)
|
||||
Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org
|
||||
[52.25.139.140])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
|
||||
(No client certificate requested)
|
||||
by sv.mirrors.kernel.org (Postfix) with ESMTPS id 5BB9C28522A
|
||||
for <incoming@patchwork.ozlabs.org>; Tue, 23 Apr 2024 12:12:55 +0000 (UTC)
|
||||
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
|
||||
by smtp.subspace.kernel.org (Postfix) with ESMTP id 2F83B8563D;
|
||||
Tue, 23 Apr 2024 12:12:41 +0000 (UTC)
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org
|
||||
header.b="qX99TQMM"
|
||||
X-Original-To: linux-gpio@vger.kernel.org
|
||||
Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com
|
||||
[209.85.208.179])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
|
||||
(No client certificate requested)
|
||||
by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8F3C82865
|
||||
for <linux-gpio@vger.kernel.org>; Tue, 23 Apr 2024 12:12:37 +0000 (UTC)
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
arc=none smtp.client-ip=209.85.208.179
|
||||
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
|
||||
t=1713874361; cv=none;
|
||||
b=d6RcvcAu8hBYAK8Io489ZHQpJVXPwuokP6iMcAkbvElCerbXD6jAdqdi+RjDlo5C49GHGO4FQ19UwQn/VE//qSwiK1ulTSBp3OkvAmyb7yYAFnDs9AVNWRw+5/NxeFNn3fj5PyvqVymIbaJKabfrOVNwkz/5JMHxEIJtr6Crmog=
|
||||
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
|
||||
s=arc-20240116; t=1713874361; c=relaxed/simple;
|
||||
bh=0eXJ5AIjzz1TBGZ8SlshIPrEHZaZwZfYEdof+dSpu4Y=;
|
||||
h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc;
|
||||
b=EfFtruUxRIGy+jylEiJ2rPEyPCjGCc8ptT9FVxe6s0O/kW38Y6196xVQeiSV2tSKVCEOIO+9HoqmpgdKsJE7gU9++EcrasP96MYpsklYpc2zsWW3b8QEhfxfZ9Ai/idyYihE2u9dQ7a143P/Ij/twDrZTt24wO/mtHDrE5XcCFI=
|
||||
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
|
||||
dmarc=pass (p=none dis=none) header.from=linaro.org;
|
||||
spf=pass smtp.mailfrom=linaro.org;
|
||||
dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org
|
||||
header.b=qX99TQMM; arc=none smtp.client-ip=209.85.208.179
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
dmarc=pass (p=none dis=none) header.from=linaro.org
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
spf=pass smtp.mailfrom=linaro.org
|
||||
Received: by mail-lj1-f179.google.com with SMTP id
|
||||
38308e7fff4ca-2dd041acff1so40839131fa.1
|
||||
for <linux-gpio@vger.kernel.org>;
|
||||
Tue, 23 Apr 2024 05:12:37 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=linaro.org; s=google; t=1713874356; x=1714479156;
|
||||
darn=vger.kernel.org;
|
||||
h=cc:to:message-id:content-transfer-encoding:mime-version:subject
|
||||
:date:from:from:to:cc:subject:date:message-id:reply-to;
|
||||
bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=;
|
||||
b=qX99TQMMdHbskFYUaw8c93sIJsUhKmj/WPdyahHcupUhwn5wol4aVoPczkOKYwJZhE
|
||||
eoInxzjAHIl3UNKyvPPrD4MrbLcSoFT6mTFMsgRQYUghsLattmGcqIebu9XT556dBhsf
|
||||
DydmpqGgnTOIa+IEknFxg24mo8Xn2LVmDC7LSGEYykUy1xLHd1NSq56YEaYXC7641xeZ
|
||||
9TOL0rZszeGld5cCS3013EmEeXQGCC3lAP83Eb48vbFXjPojkN0s40rZ2s8YpVsGT0iP
|
||||
LeLVtP/E8XJqi4YipKryKSgbgOvQ1Bclle5+s+2qcJQNnSEjekMwR59BIRs3OZH2SRfN
|
||||
gQdQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20230601; t=1713874356; x=1714479156;
|
||||
h=cc:to:message-id:content-transfer-encoding:mime-version:subject
|
||||
:date:from:x-gm-message-state:from:to:cc:subject:date:message-id
|
||||
:reply-to;
|
||||
bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=;
|
||||
b=jEBH4NQ7SzFi2tnb1lgL06IchnBJoscNgKesjlorvou6X/9wDE/VbgxNFKR0zWwdTk
|
||||
BEjG/ifFJxLmM9jdaCKu5cJc4yiDNXp7yZd48D71V34zJ4aINAGAx4hcOKqf95neFknx
|
||||
nsFPpBFnTYFEpCLF0TebVoL6h6ehPzSojmkArzsrMppNvW2cwJ5gDlkqy2y4SezLanmM
|
||||
6iU0ksnwE0bb2iLkahhgo00Ejt33yqxwa+3xBfhOe9oYKSSZYnY7qVq055SSwt9IAq+H
|
||||
REGyJN+GrvupTHagiioYe3LPXDPdOui9ZixXXDllw1t1yGUy+TkJu8xSqtvHEfg81FHP
|
||||
AxtA==
|
||||
X-Forwarded-Encrypted: i=1;
|
||||
AJvYcCUbxzPklfPYrLgyY1I0ycuj7Dh04dcGVonYocA2mzxzlAEV107o0ELlFqr3O9Td+tV/t0eV9ly9YAbTY6n1XPnFXS5dsYYAZw6RHw==
|
||||
X-Gm-Message-State: AOJu0YxsC7zdakTzntbiRFnN2A7yTrR0x+IpR6ce6eGn5kHeqIBi1km+
|
||||
zTVpRulbch3JsmzVDbCbbAAYoBkNgEA568YL6zdjVARnvFwNz1cqatOrR1AXUm0=
|
||||
X-Google-Smtp-Source:
|
||||
AGHT+IHBRMGvaJM98f86Z6m/RfVhK2XejjNGF3EvcRq/4x3oGM0DKpd2PbeCJdgmzHjLPVVbdsNzJg==
|
||||
X-Received: by 2002:a2e:9852:0:b0:2d8:a98d:18e with SMTP id
|
||||
e18-20020a2e9852000000b002d8a98d018emr7955886ljj.8.1713874355700;
|
||||
Tue, 23 Apr 2024 05:12:35 -0700 (PDT)
|
||||
Received: from [192.168.1.140] ([85.235.12.238])
|
||||
by smtp.gmail.com with ESMTPSA id
|
||||
x6-20020a2e7c06000000b002da179d8d25sm1628982ljc.64.2024.04.23.05.12.33
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Tue, 23 Apr 2024 05:12:35 -0700 (PDT)
|
||||
From: Linus Walleij <linus.walleij@linaro.org>
|
||||
Date: Tue, 23 Apr 2024 14:12:33 +0200
|
||||
Subject: [PATCH v2] wifi: ath9k: Obtain system GPIOS from descriptors
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-gpio@vger.kernel.org
|
||||
List-Id: <linux-gpio.vger.kernel.org>
|
||||
List-Subscribe: <mailto:linux-gpio+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:linux-gpio+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
Message-Id: <20240423-descriptors-wireless-v2-1-6d1d03b30bfa@linaro.org>
|
||||
X-B4-Tracking: v=1; b=H4sIALClJ2YC/22Nyw6CMBBFf4XM2hpanrLyPwyL0o4wCaFkxqCG9
|
||||
N+txKXLc5Nz7g6CTCjQZTswbiQUlgTmlIGb7DKiIp8YTG7KXBujPIpjWh+BRT2JcUYRNbTeXir
|
||||
v7FBUkNSV8U6vI3vrE08kSXgfL5v+rr9gof8HN61yhdo1rvJ125T1dabFcjgHHqGPMX4Ao4iiN
|
||||
LkAAAA=
|
||||
To: Kalle Valo <kvalo@kernel.org>,
|
||||
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
|
||||
Arnd Bergmann <arnd@arndb.de>, Alban Bedel <albeu@free.fr>,
|
||||
Bartosz Golaszewski <brgl@bgdev.pl>, =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rg?=
|
||||
=?utf-8?q?ensen?= <toke@toke.dk>
|
||||
Cc: linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com,
|
||||
linux-gpio@vger.kernel.org, Linus Walleij <linus.walleij@linaro.org>
|
||||
X-Mailer: b4 0.13.0
|
||||
|
||||
The ath9k has an odd use of system-wide GPIOs: if the chip
|
||||
does not have internal GPIO capability, it will try to obtain a
|
||||
GPIO line from the system GPIO controller:
|
||||
|
||||
if (BIT(gpio) & ah->caps.gpio_mask)
|
||||
ath9k_hw_gpio_cfg_wmac(...);
|
||||
else if (AR_SREV_SOC(ah))
|
||||
ath9k_hw_gpio_cfg_soc(ah, gpio, out, label);
|
||||
|
||||
Where ath9k_hw_gpio_cfg_soc() will attempt to issue
|
||||
gpio_request_one() passing the local GPIO number of the controller
|
||||
(0..31) to gpio_request_one().
|
||||
|
||||
This is somewhat peculiar and possibly even dangerous: there is
|
||||
nowadays no guarantee of the numbering of these system-wide
|
||||
GPIOs, and assuming that GPIO 0..31 as used by ath9k would
|
||||
correspond to GPIOs 0..31 on the system as a whole seems a bit
|
||||
wild.
|
||||
|
||||
Register all 32 GPIOs at index 0..31 directly in the ATH79K
|
||||
GPIO driver and associate with WIFI if and only if we are probing
|
||||
ATH79K wifi from the AHB bus (used for SoCs).
|
||||
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
Changes in v2:
|
||||
- Define all the descriptors directly in the ATH79K
|
||||
GPIO driver in case the driver want to request them directly.
|
||||
- Link to v1: https://lore.kernel.org/r/20240131-descriptors-wireless-v1-0-e1c7c5d68746@linaro.org
|
||||
---
|
||||
drivers/gpio/gpio-ath79.c | 47 ++++++++++++++++++++++++++++++++++++-
|
||||
drivers/net/wireless/ath/ath9k/hw.c | 29 ++++++++++++-----------
|
||||
drivers/net/wireless/ath/ath9k/hw.h | 3 ++-
|
||||
3 files changed, 63 insertions(+), 16 deletions(-)
|
||||
|
||||
|
||||
---
|
||||
base-commit: 4cece764965020c22cff7665b18a012006359095
|
||||
change-id: 20240122-descriptors-wireless-b8da95dcab35
|
||||
|
||||
Best regards,
|
||||
|
||||
--- a/drivers/gpio/gpio-ath79.c
|
||||
+++ b/drivers/gpio/gpio-ath79.c
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
+#include <linux/gpio/machine.h> /* For WLAN GPIOs */
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/gpio-ath79.h>
|
||||
#include <linux/of.h>
|
||||
@@ -222,6 +223,37 @@ static const struct of_device_id ath79_g
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ath79_gpio_of_match);
|
||||
|
||||
+/*
|
||||
+ * This registers all of the ath79k GPIOs as descriptors to be picked
|
||||
+ * directly from the ATH79K wifi driver if the two are jitted together
|
||||
+ * in the same SoC.
|
||||
+ */
|
||||
+#define ATH79K_WIFI_DESCS 32
|
||||
+static int ath79_gpio_register_wifi_descriptors(struct device *dev,
|
||||
+ const char *label)
|
||||
+{
|
||||
+ struct gpiod_lookup_table *lookup;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Create a gpiod lookup using gpiochip-local offsets + 1 for NULL */
|
||||
+ lookup = devm_kzalloc(dev,
|
||||
+ struct_size(lookup, table, ATH79K_WIFI_DESCS + 1),
|
||||
+ GFP_KERNEL);
|
||||
+
|
||||
+ if (!lookup)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ for (i = 0; i < ATH79K_WIFI_DESCS; i++) {
|
||||
+ lookup->table[i] = (struct gpiod_lookup)
|
||||
+ GPIO_LOOKUP_IDX(label, i, "ath9k", i,
|
||||
+ GPIO_ACTIVE_HIGH);
|
||||
+ }
|
||||
+
|
||||
+ gpiod_add_lookup_table(lookup);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ath79_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
@@ -289,7 +321,11 @@ static int ath79_gpio_probe(struct platf
|
||||
girq->handler = handle_simple_irq;
|
||||
}
|
||||
|
||||
- return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
|
||||
+ err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return ath79_gpio_register_wifi_descriptors(dev, ctrl->gc.label);
|
||||
}
|
||||
|
||||
static struct platform_driver ath79_gpio_driver = {
|
@ -0,0 +1,58 @@
|
||||
From e85d3e6fea05c8ae21a40809a3c6b7adc97411c7 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
|
||||
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Date: Thu, 20 Jun 2024 19:25:48 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: do not write port mask twice in bridge
|
||||
join/leave
|
||||
|
||||
qca8k_port_bridge_join() set QCA8K_PORT_LOOKUP_CTRL() for i == port twice,
|
||||
once in the loop handling all other port's masks, and finally at the end
|
||||
with the accumulated port_mask.
|
||||
|
||||
The first time it would incorrectly set the port's own bit in the mask,
|
||||
only to correct the mistake a moment later. qca8k_port_bridge_leave() had
|
||||
the same issue, but here the regmap_clear_bits() was a no-op rather than
|
||||
setting an unintended value.
|
||||
|
||||
Remove the duplicate assignment by skipping the whole loop iteration for
|
||||
i == port. The unintended bit setting doesn't seem to have any negative
|
||||
effects (even when not reverted right away), so the change is submitted
|
||||
as a simple cleanup rather than a fix.
|
||||
|
||||
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-common.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-common.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
||||
@@ -654,6 +654,8 @@ int qca8k_port_bridge_join(struct dsa_sw
|
||||
port_mask = BIT(cpu_port);
|
||||
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ if (i == port)
|
||||
+ continue;
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
|
||||
@@ -666,8 +668,7 @@ int qca8k_port_bridge_join(struct dsa_sw
|
||||
BIT(port));
|
||||
if (ret)
|
||||
return ret;
|
||||
- if (i != port)
|
||||
- port_mask |= BIT(i);
|
||||
+ port_mask |= BIT(i);
|
||||
}
|
||||
|
||||
/* Add all other ports to this ports portvlan mask */
|
||||
@@ -686,6 +687,8 @@ void qca8k_port_bridge_leave(struct dsa_
|
||||
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ if (i == port)
|
||||
+ continue;
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
|
@ -0,0 +1,153 @@
|
||||
From 412e1775f413c944b8c51bdadb675be957d83dc8 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <412e1775f413c944b8c51bdadb675be957d83dc8.1728674648.git.mschiffer@universe-factory.net>
|
||||
In-Reply-To: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
|
||||
References: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
|
||||
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Date: Thu, 20 Jun 2024 19:25:49 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: factor out bridge join/leave logic
|
||||
|
||||
Most of the logic in qca8k_port_bridge_join() and qca8k_port_bridge_leave()
|
||||
is the same. Refactor to reduce duplication and prepare for reusing the
|
||||
code for implementing bridge port isolation.
|
||||
|
||||
dsa_port_offloads_bridge_dev() is used instead of
|
||||
dsa_port_offloads_bridge(), passing the bridge in as a struct netdevice *,
|
||||
as we won't have a struct dsa_bridge in qca8k_port_bridge_flags().
|
||||
|
||||
The error handling is changed slightly in the bridge leave case,
|
||||
returning early and emitting an error message when a regmap access fails.
|
||||
This shouldn't matter in practice, as there isn't much we can do if
|
||||
communication with the switch breaks down in the middle of reconfiguration.
|
||||
|
||||
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-common.c | 101 ++++++++++++++---------------
|
||||
1 file changed, 50 insertions(+), 51 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-common.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
||||
@@ -615,6 +615,49 @@ void qca8k_port_stp_state_set(struct dsa
|
||||
qca8k_port_configure_learning(ds, port, learning);
|
||||
}
|
||||
|
||||
+static int qca8k_update_port_member(struct qca8k_priv *priv, int port,
|
||||
+ const struct net_device *bridge_dev,
|
||||
+ bool join)
|
||||
+{
|
||||
+ struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp;
|
||||
+ u32 port_mask = BIT(dp->cpu_dp->index);
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ if (i == port)
|
||||
+ continue;
|
||||
+ if (dsa_is_cpu_port(priv->ds, i))
|
||||
+ continue;
|
||||
+
|
||||
+ other_dp = dsa_to_port(priv->ds, i);
|
||||
+ if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev))
|
||||
+ continue;
|
||||
+
|
||||
+ /* Add/remove this port to/from the portvlan mask of the other
|
||||
+ * ports in the bridge
|
||||
+ */
|
||||
+ if (join) {
|
||||
+ port_mask |= BIT(i);
|
||||
+ ret = regmap_set_bits(priv->regmap,
|
||||
+ QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ BIT(port));
|
||||
+ } else {
|
||||
+ ret = regmap_clear_bits(priv->regmap,
|
||||
+ QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ BIT(port));
|
||||
+ }
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Add/remove all other ports to/from this port's portvlan mask */
|
||||
+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER, port_mask);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
|
||||
struct switchdev_brport_flags flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
@@ -647,65 +690,21 @@ int qca8k_port_bridge_join(struct dsa_sw
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
- int port_mask, cpu_port;
|
||||
- int i, ret;
|
||||
-
|
||||
- cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
- port_mask = BIT(cpu_port);
|
||||
|
||||
- for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
- if (i == port)
|
||||
- continue;
|
||||
- if (dsa_is_cpu_port(ds, i))
|
||||
- continue;
|
||||
- if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
|
||||
- continue;
|
||||
- /* Add this port to the portvlan mask of the other ports
|
||||
- * in the bridge
|
||||
- */
|
||||
- ret = regmap_set_bits(priv->regmap,
|
||||
- QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- BIT(port));
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- port_mask |= BIT(i);
|
||||
- }
|
||||
-
|
||||
- /* Add all other ports to this ports portvlan mask */
|
||||
- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
- QCA8K_PORT_LOOKUP_MEMBER, port_mask);
|
||||
-
|
||||
- return ret;
|
||||
+ return qca8k_update_port_member(priv, port, bridge.dev, true);
|
||||
}
|
||||
|
||||
void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
|
||||
struct dsa_bridge bridge)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
- int cpu_port, i;
|
||||
-
|
||||
- cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
-
|
||||
- for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
- if (i == port)
|
||||
- continue;
|
||||
- if (dsa_is_cpu_port(ds, i))
|
||||
- continue;
|
||||
- if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
|
||||
- continue;
|
||||
- /* Remove this port to the portvlan mask of the other ports
|
||||
- * in the bridge
|
||||
- */
|
||||
- regmap_clear_bits(priv->regmap,
|
||||
- QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- BIT(port));
|
||||
- }
|
||||
+ int err;
|
||||
|
||||
- /* Set the cpu port to be the only one in the portvlan mask of
|
||||
- * this port
|
||||
- */
|
||||
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
- QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
|
||||
+ err = qca8k_update_port_member(priv, port, bridge.dev, false);
|
||||
+ if (err)
|
||||
+ dev_err(priv->dev,
|
||||
+ "Failed to update switch config for bridge leave: %d\n",
|
||||
+ err);
|
||||
}
|
||||
|
||||
void qca8k_port_fast_age(struct dsa_switch *ds, int port)
|
@ -0,0 +1,91 @@
|
||||
From 422b64025ec10981c48f9367311846bf4bd38042 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <422b64025ec10981c48f9367311846bf4bd38042.1728674648.git.mschiffer@universe-factory.net>
|
||||
In-Reply-To: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
|
||||
References: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
|
||||
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Date: Thu, 20 Jun 2024 19:25:50 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add support for bridge port isolation
|
||||
|
||||
Remove a pair of ports from the port matrix when both ports have the
|
||||
isolated flag set.
|
||||
|
||||
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-common.c | 22 ++++++++++++++++++++--
|
||||
drivers/net/dsa/qca/qca8k.h | 1 +
|
||||
2 files changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-common.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
||||
@@ -619,6 +619,7 @@ static int qca8k_update_port_member(stru
|
||||
const struct net_device *bridge_dev,
|
||||
bool join)
|
||||
{
|
||||
+ bool isolated = !!(priv->port_isolated_map & BIT(port)), other_isolated;
|
||||
struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp;
|
||||
u32 port_mask = BIT(dp->cpu_dp->index);
|
||||
int i, ret;
|
||||
@@ -633,10 +634,12 @@ static int qca8k_update_port_member(stru
|
||||
if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev))
|
||||
continue;
|
||||
|
||||
+ other_isolated = !!(priv->port_isolated_map & BIT(i));
|
||||
+
|
||||
/* Add/remove this port to/from the portvlan mask of the other
|
||||
* ports in the bridge
|
||||
*/
|
||||
- if (join) {
|
||||
+ if (join && !(isolated && other_isolated)) {
|
||||
port_mask |= BIT(i);
|
||||
ret = regmap_set_bits(priv->regmap,
|
||||
QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
@@ -662,7 +665,7 @@ int qca8k_port_pre_bridge_flags(struct d
|
||||
struct switchdev_brport_flags flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
- if (flags.mask & ~BR_LEARNING)
|
||||
+ if (flags.mask & ~(BR_LEARNING | BR_ISOLATED))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -672,6 +675,7 @@ int qca8k_port_bridge_flags(struct dsa_s
|
||||
struct switchdev_brport_flags flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
int ret;
|
||||
|
||||
if (flags.mask & BR_LEARNING) {
|
||||
@@ -680,6 +684,20 @@ int qca8k_port_bridge_flags(struct dsa_s
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ if (flags.mask & BR_ISOLATED) {
|
||||
+ struct dsa_port *dp = dsa_to_port(ds, port);
|
||||
+ struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp);
|
||||
+
|
||||
+ if (flags.val & BR_ISOLATED)
|
||||
+ priv->port_isolated_map |= BIT(port);
|
||||
+ else
|
||||
+ priv->port_isolated_map &= ~BIT(port);
|
||||
+
|
||||
+ ret = qca8k_update_port_member(priv, port, bridge_dev, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/dsa/qca/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca/qca8k.h
|
||||
@@ -451,6 +451,7 @@ struct qca8k_priv {
|
||||
* Bit 1: port enabled. Bit 0: port disabled.
|
||||
*/
|
||||
u8 port_enabled_map;
|
||||
+ u8 port_isolated_map;
|
||||
struct qca8k_ports_config ports_config;
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
@ -0,0 +1,445 @@
|
||||
From 04597c8dd6c4b55e946fec50dc3b14a5d9d54501 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 21 Sep 2023 13:48:11 +0200
|
||||
Subject: [PATCH] crypto: jitter - add RCT/APT support for different OSRs
|
||||
|
||||
The oversampling rate (OSR) value specifies the heuristically implied
|
||||
entropy in the recorded data - H_submitter = 1/osr. A different entropy
|
||||
estimate implies a different APT/RCT cutoff value. This change adds
|
||||
support for OSRs 1 through 15. This OSR can be selected by the caller
|
||||
of the Jitter RNG.
|
||||
|
||||
For this patch, the caller still uses one hard-coded OSR. A subsequent
|
||||
patch allows this value to be configured.
|
||||
|
||||
In addition, the power-up self test is adjusted as follows:
|
||||
|
||||
* It allows the caller to provide an oversampling rate that should be
|
||||
tested with - commonly it should be the same as used for the actual
|
||||
runtime operation. This makes the power-up testing therefore consistent
|
||||
with the runtime operation.
|
||||
|
||||
* It calls now jent_measure_jitter (i.e. collects the full entropy
|
||||
that can possibly be harvested by the Jitter RNG) instead of only
|
||||
jent_condition_data (which only returns the entropy harvested from
|
||||
the conditioning component). This should now alleviate reports where
|
||||
the Jitter RNG initialization thinks there is too little entropy.
|
||||
|
||||
* The power-up test now solely relies on the (enhanced) APT and RCT
|
||||
test that is used as a health test at runtime.
|
||||
|
||||
The code allowing the different OSRs as well as the power-up test
|
||||
changes are present in the user space version of the Jitter RNG 3.4.1
|
||||
and thus was already in production use for some time.
|
||||
|
||||
Reported-by "Ospan, Abylay" <aospan@amazon.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy-kcapi.c | 4 +-
|
||||
crypto/jitterentropy.c | 233 ++++++++++++++++++-----------------
|
||||
crypto/jitterentropy.h | 3 +-
|
||||
3 files changed, 123 insertions(+), 117 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -245,7 +245,7 @@ static int jent_kcapi_init(struct crypto
|
||||
crypto_shash_init(sdesc);
|
||||
rng->sdesc = sdesc;
|
||||
|
||||
- rng->entropy_collector = jent_entropy_collector_alloc(1, 0, sdesc);
|
||||
+ rng->entropy_collector = jent_entropy_collector_alloc(0, 0, sdesc);
|
||||
if (!rng->entropy_collector) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
@@ -334,7 +334,7 @@ static int __init jent_mod_init(void)
|
||||
|
||||
desc->tfm = tfm;
|
||||
crypto_shash_init(desc);
|
||||
- ret = jent_entropy_init(desc);
|
||||
+ ret = jent_entropy_init(0, 0, desc);
|
||||
shash_desc_zero(desc);
|
||||
crypto_free_shash(tfm);
|
||||
if (ret) {
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -72,6 +72,8 @@ struct rand_data {
|
||||
__u64 prev_time; /* SENSITIVE Previous time stamp */
|
||||
__u64 last_delta; /* SENSITIVE stuck test */
|
||||
__s64 last_delta2; /* SENSITIVE stuck test */
|
||||
+
|
||||
+ unsigned int flags; /* Flags used to initialize */
|
||||
unsigned int osr; /* Oversample rate */
|
||||
#define JENT_MEMORY_BLOCKS 64
|
||||
#define JENT_MEMORY_BLOCKSIZE 32
|
||||
@@ -88,16 +90,9 @@ struct rand_data {
|
||||
/* Repetition Count Test */
|
||||
unsigned int rct_count; /* Number of stuck values */
|
||||
|
||||
- /* Intermittent health test failure threshold of 2^-30 */
|
||||
- /* From an SP800-90B perspective, this RCT cutoff value is equal to 31. */
|
||||
- /* However, our RCT implementation starts at 1, so we subtract 1 here. */
|
||||
-#define JENT_RCT_CUTOFF (31 - 1) /* Taken from SP800-90B sec 4.4.1 */
|
||||
-#define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
|
||||
- /* Permanent health test failure threshold of 2^-60 */
|
||||
- /* From an SP800-90B perspective, this RCT cutoff value is equal to 61. */
|
||||
- /* However, our RCT implementation starts at 1, so we subtract 1 here. */
|
||||
-#define JENT_RCT_CUTOFF_PERMANENT (61 - 1)
|
||||
-#define JENT_APT_CUTOFF_PERMANENT 355
|
||||
+ /* Adaptive Proportion Test cutoff values */
|
||||
+ unsigned int apt_cutoff; /* Intermittent health test failure */
|
||||
+ unsigned int apt_cutoff_permanent; /* Permanent health test failure */
|
||||
#define JENT_APT_WINDOW_SIZE 512 /* Data window size */
|
||||
/* LSB of time stamp to process */
|
||||
#define JENT_APT_LSB 16
|
||||
@@ -122,6 +117,9 @@ struct rand_data {
|
||||
* zero). */
|
||||
#define JENT_ESTUCK 8 /* Too many stuck results during init. */
|
||||
#define JENT_EHEALTH 9 /* Health test failed during initialization */
|
||||
+#define JENT_ERCT 10 /* RCT failed during initialization */
|
||||
+#define JENT_EHASH 11 /* Hash self test failed */
|
||||
+#define JENT_EMEM 12 /* Can't allocate memory for initialization */
|
||||
|
||||
/*
|
||||
* The output n bits can receive more than n bits of min entropy, of course,
|
||||
@@ -148,6 +146,48 @@ struct rand_data {
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
+ * See the SP 800-90B comment #10b for the corrected cutoff for the SP 800-90B
|
||||
+ * APT.
|
||||
+ * http://www.untruth.org/~josh/sp80090b/UL%20SP800-90B-final%20comments%20v1.9%2020191212.pdf
|
||||
+ * In in the syntax of R, this is C = 2 + qbinom(1 − 2^(−30), 511, 2^(-1/osr)).
|
||||
+ * (The original formula wasn't correct because the first symbol must
|
||||
+ * necessarily have been observed, so there is no chance of observing 0 of these
|
||||
+ * symbols.)
|
||||
+ *
|
||||
+ * For the alpha < 2^-53, R cannot be used as it uses a float data type without
|
||||
+ * arbitrary precision. A SageMath script is used to calculate those cutoff
|
||||
+ * values.
|
||||
+ *
|
||||
+ * For any value above 14, this yields the maximal allowable value of 512
|
||||
+ * (by FIPS 140-2 IG 7.19 Resolution # 16, we cannot choose a cutoff value that
|
||||
+ * renders the test unable to fail).
|
||||
+ */
|
||||
+static const unsigned int jent_apt_cutoff_lookup[15] = {
|
||||
+ 325, 422, 459, 477, 488, 494, 499, 502,
|
||||
+ 505, 507, 508, 509, 510, 511, 512 };
|
||||
+static const unsigned int jent_apt_cutoff_permanent_lookup[15] = {
|
||||
+ 355, 447, 479, 494, 502, 507, 510, 512,
|
||||
+ 512, 512, 512, 512, 512, 512, 512 };
|
||||
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
+
|
||||
+static void jent_apt_init(struct rand_data *ec, unsigned int osr)
|
||||
+{
|
||||
+ /*
|
||||
+ * Establish the apt_cutoff based on the presumed entropy rate of
|
||||
+ * 1/osr.
|
||||
+ */
|
||||
+ if (osr >= ARRAY_SIZE(jent_apt_cutoff_lookup)) {
|
||||
+ ec->apt_cutoff = jent_apt_cutoff_lookup[
|
||||
+ ARRAY_SIZE(jent_apt_cutoff_lookup) - 1];
|
||||
+ ec->apt_cutoff_permanent = jent_apt_cutoff_permanent_lookup[
|
||||
+ ARRAY_SIZE(jent_apt_cutoff_permanent_lookup) - 1];
|
||||
+ } else {
|
||||
+ ec->apt_cutoff = jent_apt_cutoff_lookup[osr - 1];
|
||||
+ ec->apt_cutoff_permanent =
|
||||
+ jent_apt_cutoff_permanent_lookup[osr - 1];
|
||||
+ }
|
||||
+}
|
||||
+/*
|
||||
* Reset the APT counter
|
||||
*
|
||||
* @ec [in] Reference to entropy collector
|
||||
@@ -187,12 +227,12 @@ static void jent_apt_insert(struct rand_
|
||||
/* APT health test failure detection */
|
||||
static int jent_apt_permanent_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->apt_count >= JENT_APT_CUTOFF_PERMANENT) ? 1 : 0;
|
||||
+ return (ec->apt_count >= ec->apt_cutoff_permanent) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int jent_apt_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->apt_count >= JENT_APT_CUTOFF) ? 1 : 0;
|
||||
+ return (ec->apt_count >= ec->apt_cutoff) ? 1 : 0;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -275,15 +315,28 @@ static int jent_stuck(struct rand_data *
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* RCT health test failure detection */
|
||||
+/*
|
||||
+ * The cutoff value is based on the following consideration:
|
||||
+ * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
|
||||
+ * In addition, we require an entropy value H of 1/osr as this is the minimum
|
||||
+ * entropy required to provide full entropy.
|
||||
+ * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr deltas for
|
||||
+ * inserting them into the entropy pool which should then have (close to)
|
||||
+ * DATA_SIZE_BITS bits of entropy in the conditioned output.
|
||||
+ *
|
||||
+ * Note, ec->rct_count (which equals to value B in the pseudo code of SP800-90B
|
||||
+ * section 4.4.1) starts with zero. Hence we need to subtract one from the
|
||||
+ * cutoff value as calculated following SP800-90B. Thus
|
||||
+ * C = ceil(-log_2(alpha)/H) = 30*osr or 60*osr.
|
||||
+ */
|
||||
static int jent_rct_permanent_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->rct_count >= JENT_RCT_CUTOFF_PERMANENT) ? 1 : 0;
|
||||
+ return (ec->rct_count >= (60 * ec->osr)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int jent_rct_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->rct_count >= JENT_RCT_CUTOFF) ? 1 : 0;
|
||||
+ return (ec->rct_count >= (30 * ec->osr)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Report of health test failures */
|
||||
@@ -448,7 +501,7 @@ static void jent_memaccess(struct rand_d
|
||||
*
|
||||
* @return result of stuck test
|
||||
*/
|
||||
-static int jent_measure_jitter(struct rand_data *ec)
|
||||
+static int jent_measure_jitter(struct rand_data *ec, __u64 *ret_current_delta)
|
||||
{
|
||||
__u64 time = 0;
|
||||
__u64 current_delta = 0;
|
||||
@@ -472,6 +525,10 @@ static int jent_measure_jitter(struct ra
|
||||
if (jent_condition_data(ec, current_delta, stuck))
|
||||
stuck = 1;
|
||||
|
||||
+ /* return the raw entropy value */
|
||||
+ if (ret_current_delta)
|
||||
+ *ret_current_delta = current_delta;
|
||||
+
|
||||
return stuck;
|
||||
}
|
||||
|
||||
@@ -489,11 +546,11 @@ static void jent_gen_entropy(struct rand
|
||||
safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
|
||||
|
||||
/* priming of the ->prev_time value */
|
||||
- jent_measure_jitter(ec);
|
||||
+ jent_measure_jitter(ec, NULL);
|
||||
|
||||
while (!jent_health_failure(ec)) {
|
||||
/* If a stuck measurement is received, repeat measurement */
|
||||
- if (jent_measure_jitter(ec))
|
||||
+ if (jent_measure_jitter(ec, NULL))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -554,7 +611,8 @@ int jent_read_entropy(struct rand_data *
|
||||
* Perform startup health tests and return permanent
|
||||
* error if it fails.
|
||||
*/
|
||||
- if (jent_entropy_init(ec->hash_state))
|
||||
+ if (jent_entropy_init(ec->osr, ec->flags,
|
||||
+ ec->hash_state))
|
||||
return -3;
|
||||
|
||||
return -2;
|
||||
@@ -604,11 +662,15 @@ struct rand_data *jent_entropy_collector
|
||||
|
||||
/* verify and set the oversampling rate */
|
||||
if (osr == 0)
|
||||
- osr = 1; /* minimum sampling rate is 1 */
|
||||
+ osr = 1; /* H_submitter = 1 / osr */
|
||||
entropy_collector->osr = osr;
|
||||
+ entropy_collector->flags = flags;
|
||||
|
||||
entropy_collector->hash_state = hash_state;
|
||||
|
||||
+ /* Initialize the APT */
|
||||
+ jent_apt_init(entropy_collector, osr);
|
||||
+
|
||||
/* fill the data pad with non-zero values */
|
||||
jent_gen_entropy(entropy_collector);
|
||||
|
||||
@@ -622,20 +684,14 @@ void jent_entropy_collector_free(struct
|
||||
jent_zfree(entropy_collector);
|
||||
}
|
||||
|
||||
-int jent_entropy_init(void *hash_state)
|
||||
+int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state)
|
||||
{
|
||||
- int i;
|
||||
- __u64 delta_sum = 0;
|
||||
- __u64 old_delta = 0;
|
||||
- unsigned int nonstuck = 0;
|
||||
- int time_backwards = 0;
|
||||
- int count_mod = 0;
|
||||
- int count_stuck = 0;
|
||||
- struct rand_data ec = { 0 };
|
||||
-
|
||||
- /* Required for RCT */
|
||||
- ec.osr = 1;
|
||||
- ec.hash_state = hash_state;
|
||||
+ struct rand_data *ec;
|
||||
+ int i, time_backwards = 0, ret = 0;
|
||||
+
|
||||
+ ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
+ if (!ec)
|
||||
+ return JENT_EMEM;
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
* that we only have a few loop counts to do testing. These
|
||||
@@ -664,31 +720,28 @@ int jent_entropy_init(void *hash_state)
|
||||
#define TESTLOOPCOUNT 1024
|
||||
#define CLEARCACHE 100
|
||||
for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
|
||||
- __u64 time = 0;
|
||||
- __u64 time2 = 0;
|
||||
- __u64 delta = 0;
|
||||
- unsigned int lowdelta = 0;
|
||||
- int stuck;
|
||||
+ __u64 start_time = 0, end_time = 0, delta = 0;
|
||||
|
||||
/* Invoke core entropy collection logic */
|
||||
- jent_get_nstime(&time);
|
||||
- ec.prev_time = time;
|
||||
- jent_condition_data(&ec, time, 0);
|
||||
- jent_get_nstime(&time2);
|
||||
+ jent_measure_jitter(ec, &delta);
|
||||
+ end_time = ec->prev_time;
|
||||
+ start_time = ec->prev_time - delta;
|
||||
|
||||
/* test whether timer works */
|
||||
- if (!time || !time2)
|
||||
- return JENT_ENOTIME;
|
||||
- delta = jent_delta(time, time2);
|
||||
+ if (!start_time || !end_time) {
|
||||
+ ret = JENT_ENOTIME;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* test whether timer is fine grained enough to provide
|
||||
* delta even when called shortly after each other -- this
|
||||
* implies that we also have a high resolution timer
|
||||
*/
|
||||
- if (!delta)
|
||||
- return JENT_ECOARSETIME;
|
||||
-
|
||||
- stuck = jent_stuck(&ec, delta);
|
||||
+ if (!delta || (end_time == start_time)) {
|
||||
+ ret = JENT_ECOARSETIME;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* up to here we did not modify any variable that will be
|
||||
@@ -700,49 +753,9 @@ int jent_entropy_init(void *hash_state)
|
||||
if (i < CLEARCACHE)
|
||||
continue;
|
||||
|
||||
- if (stuck)
|
||||
- count_stuck++;
|
||||
- else {
|
||||
- nonstuck++;
|
||||
-
|
||||
- /*
|
||||
- * Ensure that the APT succeeded.
|
||||
- *
|
||||
- * With the check below that count_stuck must be less
|
||||
- * than 10% of the overall generated raw entropy values
|
||||
- * it is guaranteed that the APT is invoked at
|
||||
- * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
|
||||
- */
|
||||
- if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
|
||||
- jent_apt_reset(&ec,
|
||||
- delta & JENT_APT_WORD_MASK);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Validate health test result */
|
||||
- if (jent_health_failure(&ec))
|
||||
- return JENT_EHEALTH;
|
||||
-
|
||||
/* test whether we have an increasing timer */
|
||||
- if (!(time2 > time))
|
||||
+ if (!(end_time > start_time))
|
||||
time_backwards++;
|
||||
-
|
||||
- /* use 32 bit value to ensure compilation on 32 bit arches */
|
||||
- lowdelta = time2 - time;
|
||||
- if (!(lowdelta % 100))
|
||||
- count_mod++;
|
||||
-
|
||||
- /*
|
||||
- * ensure that we have a varying delta timer which is necessary
|
||||
- * for the calculation of entropy -- perform this check
|
||||
- * only after the first loop is executed as we need to prime
|
||||
- * the old_data value
|
||||
- */
|
||||
- if (delta > old_delta)
|
||||
- delta_sum += (delta - old_delta);
|
||||
- else
|
||||
- delta_sum += (old_delta - delta);
|
||||
- old_delta = delta;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -752,31 +765,23 @@ int jent_entropy_init(void *hash_state)
|
||||
* should not fail. The value of 3 should cover the NTP case being
|
||||
* performed during our test run.
|
||||
*/
|
||||
- if (time_backwards > 3)
|
||||
- return JENT_ENOMONOTONIC;
|
||||
-
|
||||
- /*
|
||||
- * Variations of deltas of time must on average be larger
|
||||
- * than 1 to ensure the entropy estimation
|
||||
- * implied with 1 is preserved
|
||||
- */
|
||||
- if ((delta_sum) <= 1)
|
||||
- return JENT_EVARVAR;
|
||||
+ if (time_backwards > 3) {
|
||||
+ ret = JENT_ENOMONOTONIC;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * Ensure that we have variations in the time stamp below 10 for at
|
||||
- * least 10% of all checks -- on some platforms, the counter increments
|
||||
- * in multiples of 100, but not always
|
||||
- */
|
||||
- if ((TESTLOOPCOUNT/10 * 9) < count_mod)
|
||||
- return JENT_ECOARSETIME;
|
||||
+ /* Did we encounter a health test failure? */
|
||||
+ if (jent_rct_failure(ec)) {
|
||||
+ ret = JENT_ERCT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (jent_apt_failure(ec)) {
|
||||
+ ret = JENT_EHEALTH;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * If we have more than 90% stuck results, then this Jitter RNG is
|
||||
- * likely to not work well.
|
||||
- */
|
||||
- if ((TESTLOOPCOUNT/10 * 9) < count_stuck)
|
||||
- return JENT_ESTUCK;
|
||||
+out:
|
||||
+ jent_entropy_collector_free(ec);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
--- a/crypto/jitterentropy.h
|
||||
+++ b/crypto/jitterentropy.h
|
||||
@@ -9,7 +9,8 @@ extern int jent_hash_time(void *hash_sta
|
||||
int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len);
|
||||
|
||||
struct rand_data;
|
||||
-extern int jent_entropy_init(void *hash_state);
|
||||
+extern int jent_entropy_init(unsigned int osr, unsigned int flags,
|
||||
+ void *hash_state);
|
||||
extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
|
||||
unsigned int len);
|
||||
|
@ -0,0 +1,159 @@
|
||||
From 59bcfd788552504606e3eb774ae68052379396b6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 21 Sep 2023 13:48:33 +0200
|
||||
Subject: [PATCH] crypto: jitter - Allow configuration of memory size
|
||||
|
||||
The memory size consumed by the Jitter RNG is one contributing factor in
|
||||
the amount of entropy that is gathered. As the amount of entropy
|
||||
directly correlates with the distance of the memory from the CPU, the
|
||||
caches that are possibly present on a given system have an impact on the
|
||||
collected entropy.
|
||||
|
||||
Thus, the kernel compile time should offer a means to configure the
|
||||
amount of memory used by the Jitter RNG. Although this option could be
|
||||
turned into a runtime option (e.g. a kernel command line option), it
|
||||
should remain a compile time option as otherwise adminsitrators who may
|
||||
not have performed an entropy assessment may select a value that is
|
||||
inappropriate.
|
||||
|
||||
The default value selected by the configuration is identical to the
|
||||
current Jitter RNG value. Thus, the patch should not lead to any change
|
||||
in the Jitter RNG behavior.
|
||||
|
||||
To accommodate larger memory buffers, kvzalloc / kvfree is used.
|
||||
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 43 ++++++++++++++++++++++++++++++++++++
|
||||
crypto/jitterentropy-kcapi.c | 11 +++++++++
|
||||
crypto/jitterentropy.c | 16 ++++++++------
|
||||
crypto/jitterentropy.h | 2 ++
|
||||
4 files changed, 65 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1297,6 +1297,49 @@ config CRYPTO_JITTERENTROPY
|
||||
|
||||
See https://www.chronox.de/jent/
|
||||
|
||||
+choice
|
||||
+ prompt "CPU Jitter RNG Memory Size"
|
||||
+ default CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ depends on CRYPTO_JITTERENTROPY
|
||||
+ help
|
||||
+ The Jitter RNG measures the execution time of memory accesses.
|
||||
+ Multiple consecutive memory accesses are performed. If the memory
|
||||
+ size fits into a cache (e.g. L1), only the memory access timing
|
||||
+ to that cache is measured. The closer the cache is to the CPU
|
||||
+ the less variations are measured and thus the less entropy is
|
||||
+ obtained. Thus, if the memory size fits into the L1 cache, the
|
||||
+ obtained entropy is less than if the memory size fits within
|
||||
+ L1 + L2, which in turn is less if the memory fits into
|
||||
+ L1 + L2 + L3. Thus, by selecting a different memory size,
|
||||
+ the entropy rate produced by the Jitter RNG can be modified.
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ bool "2048 Bytes (default)"
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_128
|
||||
+ bool "128 kBytes"
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
+ bool "1024 kBytes"
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
+ bool "8192 kBytes"
|
||||
+endchoice
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKS
|
||||
+ int
|
||||
+ default 64 if CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ default 512 if CRYPTO_JITTERENTROPY_MEMSIZE_128
|
||||
+ default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
+ default 4096 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE
|
||||
+ int
|
||||
+ default 32 if CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ default 256 if CRYPTO_JITTERENTROPY_MEMSIZE_128
|
||||
+ default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
+ default 2048 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
+
|
||||
config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
bool "CPU Jitter RNG Test Interface"
|
||||
depends on CRYPTO_JITTERENTROPY
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -54,6 +54,17 @@
|
||||
* Helper function
|
||||
***************************************************************************/
|
||||
|
||||
+void *jent_kvzalloc(unsigned int len)
|
||||
+{
|
||||
+ return kvzalloc(len, GFP_KERNEL);
|
||||
+}
|
||||
+
|
||||
+void jent_kvzfree(void *ptr, unsigned int len)
|
||||
+{
|
||||
+ memzero_explicit(ptr, len);
|
||||
+ kvfree(ptr);
|
||||
+}
|
||||
+
|
||||
void *jent_zalloc(unsigned int len)
|
||||
{
|
||||
return kzalloc(len, GFP_KERNEL);
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -75,10 +75,10 @@ struct rand_data {
|
||||
|
||||
unsigned int flags; /* Flags used to initialize */
|
||||
unsigned int osr; /* Oversample rate */
|
||||
-#define JENT_MEMORY_BLOCKS 64
|
||||
-#define JENT_MEMORY_BLOCKSIZE 32
|
||||
#define JENT_MEMORY_ACCESSLOOPS 128
|
||||
-#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
|
||||
+#define JENT_MEMORY_SIZE \
|
||||
+ (CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS * \
|
||||
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE)
|
||||
unsigned char *mem; /* Memory access location with size of
|
||||
* memblocks * memblocksize */
|
||||
unsigned int memlocation; /* Pointer to byte in *mem */
|
||||
@@ -650,13 +650,15 @@ struct rand_data *jent_entropy_collector
|
||||
/* Allocate memory for adding variations based on memory
|
||||
* access
|
||||
*/
|
||||
- entropy_collector->mem = jent_zalloc(JENT_MEMORY_SIZE);
|
||||
+ entropy_collector->mem = jent_kvzalloc(JENT_MEMORY_SIZE);
|
||||
if (!entropy_collector->mem) {
|
||||
jent_zfree(entropy_collector);
|
||||
return NULL;
|
||||
}
|
||||
- entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
|
||||
- entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
|
||||
+ entropy_collector->memblocksize =
|
||||
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE;
|
||||
+ entropy_collector->memblocks =
|
||||
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS;
|
||||
entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
|
||||
}
|
||||
|
||||
@@ -679,7 +681,7 @@ struct rand_data *jent_entropy_collector
|
||||
|
||||
void jent_entropy_collector_free(struct rand_data *entropy_collector)
|
||||
{
|
||||
- jent_zfree(entropy_collector->mem);
|
||||
+ jent_kvzfree(entropy_collector->mem, JENT_MEMORY_SIZE);
|
||||
entropy_collector->mem = NULL;
|
||||
jent_zfree(entropy_collector);
|
||||
}
|
||||
--- a/crypto/jitterentropy.h
|
||||
+++ b/crypto/jitterentropy.h
|
||||
@@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
+extern void *jent_kvzalloc(unsigned int len);
|
||||
+extern void jent_kvzfree(void *ptr, unsigned int len);
|
||||
extern void *jent_zalloc(unsigned int len);
|
||||
extern void jent_zfree(void *ptr);
|
||||
extern void jent_get_nstime(__u64 *out);
|
@ -0,0 +1,75 @@
|
||||
From 0baa8fab334a4d7017235b72fa8a547433572109 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 21 Sep 2023 13:48:59 +0200
|
||||
Subject: [PATCH] crypto: jitter - Allow configuration of oversampling rate
|
||||
|
||||
The oversampling rate used by the Jitter RNG allows the configuration of
|
||||
the heuristically implied entropy in one timing measurement. This
|
||||
entropy rate is (1 / OSR) bits of entropy per time stamp.
|
||||
|
||||
Considering that the Jitter RNG now support APT/RCT health tests for
|
||||
different OSRs, allow this value to be configured at compile time to
|
||||
support systems with limited amount of entropy in their timer.
|
||||
|
||||
The allowed range of OSR values complies with the APT/RCT cutoff health
|
||||
test values which range from 1 through 15.
|
||||
|
||||
The default value of the OSR selection support is left at 1 which is the
|
||||
current default. Thus, the addition of the configuration support does
|
||||
not alter the default Jitter RNG behavior.
|
||||
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 17 +++++++++++++++++
|
||||
crypto/jitterentropy-kcapi.c | 6 ++++--
|
||||
2 files changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1340,6 +1340,23 @@ config CRYPTO_JITTERENTROPY_MEMORY_BLOCK
|
||||
default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
default 2048 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
|
||||
+config CRYPTO_JITTERENTROPY_OSR
|
||||
+ int "CPU Jitter RNG Oversampling Rate"
|
||||
+ range 1 15
|
||||
+ default 1
|
||||
+ depends on CRYPTO_JITTERENTROPY
|
||||
+ help
|
||||
+ The Jitter RNG allows the specification of an oversampling rate (OSR).
|
||||
+ The Jitter RNG operation requires a fixed amount of timing
|
||||
+ measurements to produce one output block of random numbers. The
|
||||
+ OSR value is multiplied with the amount of timing measurements to
|
||||
+ generate one output block. Thus, the timing measurement is oversampled
|
||||
+ by the OSR factor. The oversampling allows the Jitter RNG to operate
|
||||
+ on hardware whose timers deliver limited amount of entropy (e.g.
|
||||
+ the timer is coarse) by setting the OSR to a higher value. The
|
||||
+ trade-off, however, is that the Jitter RNG now requires more time
|
||||
+ to generate random numbers.
|
||||
+
|
||||
config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
bool "CPU Jitter RNG Test Interface"
|
||||
depends on CRYPTO_JITTERENTROPY
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -256,7 +256,9 @@ static int jent_kcapi_init(struct crypto
|
||||
crypto_shash_init(sdesc);
|
||||
rng->sdesc = sdesc;
|
||||
|
||||
- rng->entropy_collector = jent_entropy_collector_alloc(0, 0, sdesc);
|
||||
+ rng->entropy_collector =
|
||||
+ jent_entropy_collector_alloc(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0,
|
||||
+ sdesc);
|
||||
if (!rng->entropy_collector) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
@@ -345,7 +347,7 @@ static int __init jent_mod_init(void)
|
||||
|
||||
desc->tfm = tfm;
|
||||
crypto_shash_init(desc);
|
||||
- ret = jent_entropy_init(0, 0, desc);
|
||||
+ ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc);
|
||||
shash_desc_zero(desc);
|
||||
crypto_free_shash(tfm);
|
||||
if (ret) {
|
@ -0,0 +1,117 @@
|
||||
From 8405ec8e3c02df8b3720874c3e2169fef4553868 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Sat, 7 Oct 2023 09:10:43 +0200
|
||||
Subject: [PATCH] crypto: jitter - reuse allocated entropy collector
|
||||
|
||||
In case a health test error occurs during runtime, the power-up health
|
||||
tests are rerun to verify that the noise source is still good and
|
||||
that the reported health test error was an outlier. For performing this
|
||||
power-up health test, the already existing entropy collector instance
|
||||
is used instead of allocating a new one. This change has the following
|
||||
implications:
|
||||
|
||||
* The noise that is collected as part of the newly run health tests is
|
||||
inserted into the entropy collector and thus stirs the existing
|
||||
data present in there further. Thus, the entropy collected during
|
||||
the health test is not wasted. This is also allowed by SP800-90B.
|
||||
|
||||
* The power-on health test is not affected by the state of the entropy
|
||||
collector, because it resets the APT / RCT state. The remainder of
|
||||
the state is unrelated to the health test as it is only applied to
|
||||
newly obtained time stamps.
|
||||
|
||||
This change also fixes a bug report about an allocation while in an
|
||||
atomic lock (the lock is taken in jent_kcapi_random, jent_read_entropy
|
||||
is called and this can call jent_entropy_init).
|
||||
|
||||
Fixes: 04597c8dd6c4 ("jitter - add RCT/APT support for different OSRs")
|
||||
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy-kcapi.c | 2 +-
|
||||
crypto/jitterentropy.c | 36 ++++++++++++++++++++++++++----------
|
||||
crypto/jitterentropy.h | 2 +-
|
||||
3 files changed, 28 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -347,7 +347,7 @@ static int __init jent_mod_init(void)
|
||||
|
||||
desc->tfm = tfm;
|
||||
crypto_shash_init(desc);
|
||||
- ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc);
|
||||
+ ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc, NULL);
|
||||
shash_desc_zero(desc);
|
||||
crypto_free_shash(tfm);
|
||||
if (ret) {
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -611,8 +611,7 @@ int jent_read_entropy(struct rand_data *
|
||||
* Perform startup health tests and return permanent
|
||||
* error if it fails.
|
||||
*/
|
||||
- if (jent_entropy_init(ec->osr, ec->flags,
|
||||
- ec->hash_state))
|
||||
+ if (jent_entropy_init(0, 0, NULL, ec))
|
||||
return -3;
|
||||
|
||||
return -2;
|
||||
@@ -686,14 +685,30 @@ void jent_entropy_collector_free(struct
|
||||
jent_zfree(entropy_collector);
|
||||
}
|
||||
|
||||
-int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state)
|
||||
+int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state,
|
||||
+ struct rand_data *p_ec)
|
||||
{
|
||||
- struct rand_data *ec;
|
||||
- int i, time_backwards = 0, ret = 0;
|
||||
+ /*
|
||||
+ * If caller provides an allocated ec, reuse it which implies that the
|
||||
+ * health test entropy data is used to further still the available
|
||||
+ * entropy pool.
|
||||
+ */
|
||||
+ struct rand_data *ec = p_ec;
|
||||
+ int i, time_backwards = 0, ret = 0, ec_free = 0;
|
||||
|
||||
- ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
- if (!ec)
|
||||
- return JENT_EMEM;
|
||||
+ if (!ec) {
|
||||
+ ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
+ if (!ec)
|
||||
+ return JENT_EMEM;
|
||||
+ ec_free = 1;
|
||||
+ } else {
|
||||
+ /* Reset the APT */
|
||||
+ jent_apt_reset(ec, 0);
|
||||
+ /* Ensure that a new APT base is obtained */
|
||||
+ ec->apt_base_set = 0;
|
||||
+ /* Reset the RCT */
|
||||
+ ec->rct_count = 0;
|
||||
+ }
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
* that we only have a few loop counts to do testing. These
|
||||
@@ -783,7 +798,8 @@ int jent_entropy_init(unsigned int osr,
|
||||
}
|
||||
|
||||
out:
|
||||
- jent_entropy_collector_free(ec);
|
||||
+ if (ec_free)
|
||||
+ jent_entropy_collector_free(ec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
--- a/crypto/jitterentropy.h
|
||||
+++ b/crypto/jitterentropy.h
|
||||
@@ -12,7 +12,7 @@ int jent_read_random_block(void *hash_st
|
||||
|
||||
struct rand_data;
|
||||
extern int jent_entropy_init(unsigned int osr, unsigned int flags,
|
||||
- void *hash_state);
|
||||
+ void *hash_state, struct rand_data *p_ec);
|
||||
extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
|
||||
unsigned int len);
|
||||
|
@ -0,0 +1,242 @@
|
||||
From cf27d9475f37fb69b5bc293e6e6d6c1d03cf7cc6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 19 Oct 2023 09:40:42 +0200
|
||||
Subject: [PATCH] crypto: jitter - use permanent health test storage
|
||||
|
||||
The health test result in the current code is only given for the currently
|
||||
processed raw time stamp. This implies to react on the health test error,
|
||||
the result must be checked after each raw time stamp being processed. To
|
||||
avoid this constant checking requirement, any health test error is recorded
|
||||
and stored to be analyzed at a later time, if needed.
|
||||
|
||||
This change ensures that the power-up test catches any health test error.
|
||||
Without that patch, the power-up health test result is not enforced.
|
||||
|
||||
The introduced changes are already in use with the user space version of
|
||||
the Jitter RNG.
|
||||
|
||||
Fixes: 04597c8dd6c4 ("jitter - add RCT/APT support for different OSRs")
|
||||
Reported-by: Joachim Vandersmissen <git@jvdsn.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy.c | 125 ++++++++++++++++++++++++-----------------
|
||||
1 file changed, 74 insertions(+), 51 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -100,6 +100,8 @@ struct rand_data {
|
||||
unsigned int apt_observations; /* Number of collected observations */
|
||||
unsigned int apt_count; /* APT counter */
|
||||
unsigned int apt_base; /* APT base reference */
|
||||
+ unsigned int health_failure; /* Record health failure */
|
||||
+
|
||||
unsigned int apt_base_set:1; /* APT base reference set? */
|
||||
};
|
||||
|
||||
@@ -121,6 +123,13 @@ struct rand_data {
|
||||
#define JENT_EHASH 11 /* Hash self test failed */
|
||||
#define JENT_EMEM 12 /* Can't allocate memory for initialization */
|
||||
|
||||
+#define JENT_RCT_FAILURE 1 /* Failure in RCT health test. */
|
||||
+#define JENT_APT_FAILURE 2 /* Failure in APT health test. */
|
||||
+#define JENT_PERMANENT_FAILURE_SHIFT 16
|
||||
+#define JENT_PERMANENT_FAILURE(x) (x << JENT_PERMANENT_FAILURE_SHIFT)
|
||||
+#define JENT_RCT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_RCT_FAILURE)
|
||||
+#define JENT_APT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_APT_FAILURE)
|
||||
+
|
||||
/*
|
||||
* The output n bits can receive more than n bits of min entropy, of course,
|
||||
* but the fixed output of the conditioning function can only asymptotically
|
||||
@@ -215,26 +224,22 @@ static void jent_apt_insert(struct rand_
|
||||
return;
|
||||
}
|
||||
|
||||
- if (delta_masked == ec->apt_base)
|
||||
+ if (delta_masked == ec->apt_base) {
|
||||
ec->apt_count++;
|
||||
|
||||
+ /* Note, ec->apt_count starts with one. */
|
||||
+ if (ec->apt_count >= ec->apt_cutoff_permanent)
|
||||
+ ec->health_failure |= JENT_APT_FAILURE_PERMANENT;
|
||||
+ else if (ec->apt_count >= ec->apt_cutoff)
|
||||
+ ec->health_failure |= JENT_APT_FAILURE;
|
||||
+ }
|
||||
+
|
||||
ec->apt_observations++;
|
||||
|
||||
if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
|
||||
jent_apt_reset(ec, delta_masked);
|
||||
}
|
||||
|
||||
-/* APT health test failure detection */
|
||||
-static int jent_apt_permanent_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->apt_count >= ec->apt_cutoff_permanent) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
-static int jent_apt_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->apt_count >= ec->apt_cutoff) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
/***************************************************************************
|
||||
* Stuck Test and its use as Repetition Count Test
|
||||
*
|
||||
@@ -261,6 +266,30 @@ static void jent_rct_insert(struct rand_
|
||||
{
|
||||
if (stuck) {
|
||||
ec->rct_count++;
|
||||
+
|
||||
+ /*
|
||||
+ * The cutoff value is based on the following consideration:
|
||||
+ * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
|
||||
+ * In addition, we require an entropy value H of 1/osr as this
|
||||
+ * is the minimum entropy required to provide full entropy.
|
||||
+ * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr
|
||||
+ * deltas for inserting them into the entropy pool which should
|
||||
+ * then have (close to) DATA_SIZE_BITS bits of entropy in the
|
||||
+ * conditioned output.
|
||||
+ *
|
||||
+ * Note, ec->rct_count (which equals to value B in the pseudo
|
||||
+ * code of SP800-90B section 4.4.1) starts with zero. Hence
|
||||
+ * we need to subtract one from the cutoff value as calculated
|
||||
+ * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr
|
||||
+ * or 60*osr.
|
||||
+ */
|
||||
+ if ((unsigned int)ec->rct_count >= (60 * ec->osr)) {
|
||||
+ ec->rct_count = -1;
|
||||
+ ec->health_failure |= JENT_RCT_FAILURE_PERMANENT;
|
||||
+ } else if ((unsigned int)ec->rct_count >= (30 * ec->osr)) {
|
||||
+ ec->rct_count = -1;
|
||||
+ ec->health_failure |= JENT_RCT_FAILURE;
|
||||
+ }
|
||||
} else {
|
||||
/* Reset RCT */
|
||||
ec->rct_count = 0;
|
||||
@@ -316,38 +345,24 @@ static int jent_stuck(struct rand_data *
|
||||
}
|
||||
|
||||
/*
|
||||
- * The cutoff value is based on the following consideration:
|
||||
- * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
|
||||
- * In addition, we require an entropy value H of 1/osr as this is the minimum
|
||||
- * entropy required to provide full entropy.
|
||||
- * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr deltas for
|
||||
- * inserting them into the entropy pool which should then have (close to)
|
||||
- * DATA_SIZE_BITS bits of entropy in the conditioned output.
|
||||
+ * Report any health test failures
|
||||
*
|
||||
- * Note, ec->rct_count (which equals to value B in the pseudo code of SP800-90B
|
||||
- * section 4.4.1) starts with zero. Hence we need to subtract one from the
|
||||
- * cutoff value as calculated following SP800-90B. Thus
|
||||
- * C = ceil(-log_2(alpha)/H) = 30*osr or 60*osr.
|
||||
- */
|
||||
-static int jent_rct_permanent_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->rct_count >= (60 * ec->osr)) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
-static int jent_rct_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->rct_count >= (30 * ec->osr)) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
-/* Report of health test failures */
|
||||
-static int jent_health_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return jent_rct_failure(ec) | jent_apt_failure(ec);
|
||||
-}
|
||||
+ * @ec [in] Reference to entropy collector
|
||||
+ *
|
||||
+ * @return a bitmask indicating which tests failed
|
||||
+ * 0 No health test failure
|
||||
+ * 1 RCT failure
|
||||
+ * 2 APT failure
|
||||
+ * 1<<JENT_PERMANENT_FAILURE_SHIFT RCT permanent failure
|
||||
+ * 2<<JENT_PERMANENT_FAILURE_SHIFT APT permanent failure
|
||||
+ */
|
||||
+static unsigned int jent_health_failure(struct rand_data *ec)
|
||||
+{
|
||||
+ /* Test is only enabled in FIPS mode */
|
||||
+ if (!fips_enabled)
|
||||
+ return 0;
|
||||
|
||||
-static int jent_permanent_health_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
|
||||
+ return ec->health_failure;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -594,11 +609,12 @@ int jent_read_entropy(struct rand_data *
|
||||
return -1;
|
||||
|
||||
while (len > 0) {
|
||||
- unsigned int tocopy;
|
||||
+ unsigned int tocopy, health_test_result;
|
||||
|
||||
jent_gen_entropy(ec);
|
||||
|
||||
- if (jent_permanent_health_failure(ec)) {
|
||||
+ health_test_result = jent_health_failure(ec);
|
||||
+ if (health_test_result > JENT_PERMANENT_FAILURE_SHIFT) {
|
||||
/*
|
||||
* At this point, the Jitter RNG instance is considered
|
||||
* as a failed instance. There is no rerun of the
|
||||
@@ -606,13 +622,18 @@ int jent_read_entropy(struct rand_data *
|
||||
* is assumed to not further use this instance.
|
||||
*/
|
||||
return -3;
|
||||
- } else if (jent_health_failure(ec)) {
|
||||
+ } else if (health_test_result) {
|
||||
/*
|
||||
* Perform startup health tests and return permanent
|
||||
* error if it fails.
|
||||
*/
|
||||
- if (jent_entropy_init(0, 0, NULL, ec))
|
||||
+ if (jent_entropy_init(0, 0, NULL, ec)) {
|
||||
+ /* Mark the permanent error */
|
||||
+ ec->health_failure &=
|
||||
+ JENT_RCT_FAILURE_PERMANENT |
|
||||
+ JENT_APT_FAILURE_PERMANENT;
|
||||
return -3;
|
||||
+ }
|
||||
|
||||
return -2;
|
||||
}
|
||||
@@ -695,6 +716,7 @@ int jent_entropy_init(unsigned int osr,
|
||||
*/
|
||||
struct rand_data *ec = p_ec;
|
||||
int i, time_backwards = 0, ret = 0, ec_free = 0;
|
||||
+ unsigned int health_test_result;
|
||||
|
||||
if (!ec) {
|
||||
ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
@@ -708,6 +730,9 @@ int jent_entropy_init(unsigned int osr,
|
||||
ec->apt_base_set = 0;
|
||||
/* Reset the RCT */
|
||||
ec->rct_count = 0;
|
||||
+ /* Reset intermittent, leave permanent health test result */
|
||||
+ ec->health_failure &= (~JENT_RCT_FAILURE);
|
||||
+ ec->health_failure &= (~JENT_APT_FAILURE);
|
||||
}
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
@@ -788,12 +813,10 @@ int jent_entropy_init(unsigned int osr,
|
||||
}
|
||||
|
||||
/* Did we encounter a health test failure? */
|
||||
- if (jent_rct_failure(ec)) {
|
||||
- ret = JENT_ERCT;
|
||||
- goto out;
|
||||
- }
|
||||
- if (jent_apt_failure(ec)) {
|
||||
- ret = JENT_EHEALTH;
|
||||
+ health_test_result = jent_health_failure(ec);
|
||||
+ if (health_test_result) {
|
||||
+ ret = (health_test_result & JENT_RCT_FAILURE) ? JENT_ERCT :
|
||||
+ JENT_EHEALTH;
|
||||
goto out;
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
From e7ed6473c2c8c4e45dd861bfa06e96189b11d8db Mon Sep 17 00:00:00 2001
|
||||
From: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Date: Mon, 6 Nov 2023 18:00:08 +0800
|
||||
Subject: [PATCH] crypto: jitterentropy - Hide esoteric Kconfig options under
|
||||
FIPS and EXPERT
|
||||
|
||||
As JITTERENTROPY is selected by default if you enable the CRYPTO
|
||||
API, any Kconfig options added there will show up for every single
|
||||
user. Hide the esoteric options under EXPERT as well as FIPS so
|
||||
that only distro makers will see them.
|
||||
|
||||
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Reviewed-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 28 +++++++++++++++++++++++++---
|
||||
1 file changed, 25 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1297,10 +1297,12 @@ config CRYPTO_JITTERENTROPY
|
||||
|
||||
See https://www.chronox.de/jent/
|
||||
|
||||
+if CRYPTO_JITTERENTROPY
|
||||
+if CRYPTO_FIPS && EXPERT
|
||||
+
|
||||
choice
|
||||
prompt "CPU Jitter RNG Memory Size"
|
||||
default CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
- depends on CRYPTO_JITTERENTROPY
|
||||
help
|
||||
The Jitter RNG measures the execution time of memory accesses.
|
||||
Multiple consecutive memory accesses are performed. If the memory
|
||||
@@ -1344,7 +1346,6 @@ config CRYPTO_JITTERENTROPY_OSR
|
||||
int "CPU Jitter RNG Oversampling Rate"
|
||||
range 1 15
|
||||
default 1
|
||||
- depends on CRYPTO_JITTERENTROPY
|
||||
help
|
||||
The Jitter RNG allows the specification of an oversampling rate (OSR).
|
||||
The Jitter RNG operation requires a fixed amount of timing
|
||||
@@ -1359,7 +1360,6 @@ config CRYPTO_JITTERENTROPY_OSR
|
||||
|
||||
config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
bool "CPU Jitter RNG Test Interface"
|
||||
- depends on CRYPTO_JITTERENTROPY
|
||||
help
|
||||
The test interface allows a privileged process to capture
|
||||
the raw unconditioned high resolution time stamp noise that
|
||||
@@ -1377,6 +1377,28 @@ config CRYPTO_JITTERENTROPY_TESTINTERFAC
|
||||
|
||||
If unsure, select N.
|
||||
|
||||
+endif # if CRYPTO_FIPS && EXPERT
|
||||
+
|
||||
+if !(CRYPTO_FIPS && EXPERT)
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKS
|
||||
+ int
|
||||
+ default 64
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE
|
||||
+ int
|
||||
+ default 32
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_OSR
|
||||
+ int
|
||||
+ default 1
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
+ bool
|
||||
+
|
||||
+endif # if !(CRYPTO_FIPS && EXPERT)
|
||||
+endif # if CRYPTO_JITTERENTROPY
|
||||
+
|
||||
config CRYPTO_KDF800108_CTR
|
||||
tristate
|
||||
select CRYPTO_HMAC
|
@ -0,0 +1,30 @@
|
||||
From 6e61ee1ca551292d8714c35c92a019c41db79e4e Mon Sep 17 00:00:00 2001
|
||||
From: Thorsten Blum <thorsten.blum@toblux.com>
|
||||
Date: Wed, 27 Mar 2024 23:25:09 +0100
|
||||
Subject: [PATCH] crypto: jitter - Use kvfree_sensitive() to fix Coccinelle
|
||||
warning
|
||||
|
||||
Replace memzero_explicit() and kvfree() with kvfree_sensitive() to fix
|
||||
the following Coccinelle/coccicheck warning reported by
|
||||
kfree_sensitive.cocci:
|
||||
|
||||
WARNING opportunity for kfree_sensitive/kvfree_sensitive
|
||||
|
||||
Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy-kcapi.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -61,8 +61,7 @@ void *jent_kvzalloc(unsigned int len)
|
||||
|
||||
void jent_kvzfree(void *ptr, unsigned int len)
|
||||
{
|
||||
- memzero_explicit(ptr, len);
|
||||
- kvfree(ptr);
|
||||
+ kvfree_sensitive(ptr, len);
|
||||
}
|
||||
|
||||
void *jent_zalloc(unsigned int len)
|
@ -0,0 +1,36 @@
|
||||
From 95a798d20060d2b648dd604321e347c85edfd783 Mon Sep 17 00:00:00 2001
|
||||
From: Stephan Mueller <smueller@chronox.de>
|
||||
Date: Mon, 12 Aug 2024 08:25:42 +0200
|
||||
Subject: [PATCH] crypto: jitter - set default OSR to 3
|
||||
|
||||
The user space Jitter RNG library uses the oversampling rate of 3 which
|
||||
implies that each time stamp is credited with 1/3 bit of entropy. To
|
||||
obtain 256 bits of entropy, 768 time stamps need to be sampled. The
|
||||
increase in OSR is applied based on a report where the Jitter RNG is
|
||||
used on a system exhibiting a challenging environment to collect
|
||||
entropy.
|
||||
|
||||
This OSR default value is now applied to the Linux kernel version of
|
||||
the Jitter RNG as well.
|
||||
|
||||
The increase in the OSR from 1 to 3 also implies that the Jitter RNG is
|
||||
now slower by default.
|
||||
|
||||
Reported-by: Jeff Barnes <jeffbarnes@microsoft.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1345,7 +1345,7 @@ config CRYPTO_JITTERENTROPY_MEMORY_BLOCK
|
||||
config CRYPTO_JITTERENTROPY_OSR
|
||||
int "CPU Jitter RNG Oversampling Rate"
|
||||
range 1 15
|
||||
- default 1
|
||||
+ default 3
|
||||
help
|
||||
The Jitter RNG allows the specification of an oversampling rate (OSR).
|
||||
The Jitter RNG operation requires a fixed amount of timing
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Atheros Communications Inc.
|
||||
* Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
|
||||
* Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_ATH9K_PLATFORM_H
|
||||
#define _LINUX_ATH9K_PLATFORM_H
|
||||
|
||||
#define ATH9K_PLAT_EEP_MAX_WORDS 2048
|
||||
|
||||
struct ath9k_platform_data {
|
||||
const char *eeprom_name;
|
||||
|
||||
u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
|
||||
u8 *macaddr;
|
||||
|
||||
int led_pin;
|
||||
u32 gpio_mask;
|
||||
u32 gpio_val;
|
||||
|
||||
u32 bt_active_pin;
|
||||
u32 bt_priority_pin;
|
||||
u32 wlan_active_pin;
|
||||
|
||||
bool endian_check;
|
||||
bool is_clk_25mhz;
|
||||
bool tx_gain_buffalo;
|
||||
bool disable_2ghz;
|
||||
bool disable_5ghz;
|
||||
bool led_active_high;
|
||||
|
||||
int (*get_mac_revision)(void);
|
||||
int (*external_reset)(void);
|
||||
|
||||
bool use_eeprom;
|
||||
|
||||
int num_leds;
|
||||
const struct gpio_led *leds;
|
||||
|
||||
unsigned num_btns;
|
||||
const struct gpio_keys_button *btns;
|
||||
unsigned btn_poll_interval;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_ATH9K_PLATFORM_H */
|
@ -27,7 +27,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
.port_mirror_add = qca8k_port_mirror_add,
|
||||
--- a/drivers/net/dsa/qca/qca8k-common.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
||||
@@ -1215,6 +1215,42 @@ int qca8k_port_lag_leave(struct dsa_swit
|
||||
@@ -1235,6 +1235,42 @@ int qca8k_port_lag_leave(struct dsa_swit
|
||||
return qca8k_lag_refresh_portmap(ds, port, lag, true);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
u32 val;
|
||||
--- a/drivers/net/dsa/qca/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca/qca8k.h
|
||||
@@ -590,5 +590,11 @@ int qca8k_port_lag_join(struct dsa_switc
|
||||
@@ -591,5 +591,11 @@ int qca8k_port_lag_join(struct dsa_switc
|
||||
struct netlink_ext_ack *extack);
|
||||
int qca8k_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
struct dsa_lag lag);
|
||||
|
@ -67,27 +67,18 @@ Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i);
|
||||
|
||||
if ((reg & mask) != mask) {
|
||||
@@ -653,7 +653,7 @@ int qca8k_port_bridge_join(struct dsa_sw
|
||||
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
port_mask = BIT(cpu_port);
|
||||
@@ -624,7 +624,7 @@ static int qca8k_update_port_member(stru
|
||||
u32 port_mask = BIT(dp->cpu_dp->index);
|
||||
int i, ret;
|
||||
|
||||
- for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ for (i = 0; i < ds->num_ports; i++) {
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
+ for (i = 0; i < priv->ds->num_ports; i++) {
|
||||
if (i == port)
|
||||
continue;
|
||||
if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
|
||||
@@ -685,7 +685,7 @@ void qca8k_port_bridge_leave(struct dsa_
|
||||
|
||||
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
|
||||
- for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ for (i = 0; i < ds->num_ports; i++) {
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
|
||||
if (dsa_is_cpu_port(priv->ds, i))
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/qca/qca8k-ipq4019.c
|
||||
@@ -0,0 +1,948 @@
|
||||
@@ -0,0 +1,950 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
|
||||
@ -879,6 +870,8 @@ Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
+ .port_change_mtu = qca8k_port_change_mtu,
|
||||
+ .port_max_mtu = qca8k_port_max_mtu,
|
||||
+ .port_stp_state_set = qca8k_port_stp_state_set,
|
||||
+ .port_pre_bridge_flags = qca8k_port_pre_bridge_flags,
|
||||
+ .port_bridge_flags = qca8k_port_bridge_flags,
|
||||
+ .port_bridge_join = qca8k_port_bridge_join,
|
||||
+ .port_bridge_leave = qca8k_port_bridge_leave,
|
||||
+ .port_fast_age = qca8k_port_fast_age,
|
||||
@ -1119,7 +1112,7 @@ Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
enum {
|
||||
QCA8K_PORT_SPEED_10M = 0,
|
||||
QCA8K_PORT_SPEED_100M = 1,
|
||||
@@ -466,6 +518,10 @@ struct qca8k_priv {
|
||||
@@ -467,6 +519,10 @@ struct qca8k_priv {
|
||||
struct qca8k_pcs pcs_port_6;
|
||||
const struct qca8k_match_data *info;
|
||||
struct qca8k_led ports_led[QCA8K_LED_COUNT];
|
||||
|
@ -0,0 +1,151 @@
|
||||
// SPDX-License-Identifier: MIT, GPL-2.0 or later
|
||||
/* Copyright (c) 2025, Yang Xiwen <forbidden405@outlook.com> */
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "ipq6018.dtsi"
|
||||
#include "ipq6018-cp-cpu.dtsi"
|
||||
#include "ipq6018-ess.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
model = "TP-Link EAP623-Outdoor HD V1.0";
|
||||
compatible = "tplink,eap623od-hd-v1", "qcom,ipq6018";
|
||||
|
||||
aliases {
|
||||
serial0 = &blsp1_uart3;
|
||||
led-boot = &led_system;
|
||||
led-failsafe = &led_system;
|
||||
led-running = &led_system;
|
||||
led-upgrade = &led_system;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
bootargs-append = " root=/dev/ubiblock0_1";
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&tlmm 9 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_system: system {
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
wlan {
|
||||
color = <LED_COLOR_ID_YELLOW>;
|
||||
function = LED_FUNCTION_WLAN;
|
||||
gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp1_uart3 {
|
||||
pinctrl-0 = <&serial_3_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
mdio_pins: mdio-pins {
|
||||
mdc {
|
||||
pins = "gpio64";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mdio {
|
||||
pins = "gpio65";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_pins: phy-reset-pin {
|
||||
pins = "gpio77";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
&mdio {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&mdio_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
rtl8211f: ethernet-phy@4 {
|
||||
compatible = "ethernet-phy-id001c.c916";
|
||||
reg = <4>;
|
||||
reset-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-0 = <&phy_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
realtek,clkout-disable;
|
||||
realtek,aldps-enable;
|
||||
};
|
||||
};
|
||||
|
||||
&switch {
|
||||
status = "okay";
|
||||
switch_lan_bmp = <ESS_PORT5>; /* lan port bitmap */
|
||||
switch_mac_mode1 = <MAC_MODE_SGMII_PLUS>; /* mac mode for uniphy instance0*/
|
||||
|
||||
qcom,port_phyinfo {
|
||||
port@5 {
|
||||
port_id = <5>;
|
||||
phy_address = <4>;
|
||||
port_mac_sel = "QGMAC_PORT";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&edma {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dp5 {
|
||||
status = "okay";
|
||||
phy-handle = <&rtl8211f>;
|
||||
phy-mode = "sgmii";
|
||||
label = "lan";
|
||||
};
|
||||
|
||||
&qpic_bam {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qpic_nand {
|
||||
status = "okay";
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
nand-ecc-strength = <4>;
|
||||
nand-ecc-step-size = <512>;
|
||||
nand-bus-width = <8>;
|
||||
|
||||
partitions {
|
||||
compatible = "qcom,smem-part";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&wifi {
|
||||
qcom,ath11k-calibration-variant = "TPLink-EAP623-Outdoor-HD-v1";
|
||||
status = "okay";
|
||||
};
|
@ -167,6 +167,22 @@ define Device/tplink_eap610-outdoor
|
||||
endef
|
||||
TARGET_DEVICES += tplink_eap610-outdoor
|
||||
|
||||
define Device/tplink_eap623od-hd-v1
|
||||
$(call Device/FitImage)
|
||||
$(call Device/UbiFit)
|
||||
DEVICE_VENDOR := TP-Link
|
||||
DEVICE_MODEL := EAP623-Outdoor HD
|
||||
DEVICE_VARIANT := v1
|
||||
BLOCKSIZE := 128k
|
||||
PAGESIZE := 2048
|
||||
SOC := ipq6018
|
||||
DEVICE_PACKAGES := ipq-wifi-tplink_eap623od-hd-v1 kmod-phy-realtek
|
||||
IMAGES += web-ui-factory.bin
|
||||
IMAGE/web-ui-factory.bin := append-ubi | tplink-image-2022
|
||||
TPLINK_SUPPORT_STRING := SupportList:\r\nEAP623-Outdoor HD(TP-Link|UN|AX1800-D):1.0\r\n
|
||||
endef
|
||||
TARGET_DEVICES += tplink_eap623od-hd-v1
|
||||
|
||||
define Device/yuncore_fap650
|
||||
$(call Device/FitImage)
|
||||
$(call Device/UbiFit)
|
||||
|
@ -32,7 +32,8 @@ ipq60xx_setup_interfaces()
|
||||
;;
|
||||
netgear,wax610|\
|
||||
netgear,wax610y|\
|
||||
tplink,eap610-outdoor)
|
||||
tplink,eap610-outdoor|\
|
||||
tplink,eap623od-hd-v1)
|
||||
ucidef_set_interface_lan "lan" "dhcp"
|
||||
;;
|
||||
*)
|
||||
@ -54,7 +55,8 @@ ipq60xx_setup_macs()
|
||||
wan_mac=$(macaddr_add "$lan_mac" 1)
|
||||
label_mac=$lan_mac
|
||||
;;
|
||||
tplink,eap610-outdoor)
|
||||
tplink,eap610-outdoor|\
|
||||
tplink,eap623od-hd-v1)
|
||||
label_mac=$(get_mac_binary /tmp/factory_data/default-mac 0)
|
||||
lan_mac=$label_mac
|
||||
;;
|
||||
|
@ -50,7 +50,8 @@ case "$FIRMWARE" in
|
||||
ath11k_patch_mac $(macaddr_add $label_mac 2) 1
|
||||
ath11k_set_macflag
|
||||
;;
|
||||
tplink,eap610-outdoor)
|
||||
tplink,eap610-outdoor|\
|
||||
tplink,eap623od-hd-v1)
|
||||
caldata_from_file "/tmp/factory_data/radio" 0 0x10000
|
||||
label_mac=$(get_mac_binary /tmp/factory_data/default-mac 0)
|
||||
ath11k_patch_mac $label_mac 1
|
||||
|
@ -7,7 +7,8 @@ preinit_mount_factory_data() {
|
||||
. /lib/functions/system.sh
|
||||
|
||||
case $(board_name) in
|
||||
tplink,eap610-outdoor)
|
||||
tplink,eap610-outdoor|\
|
||||
tplink,eap623od-hd-v1)
|
||||
mtd_path=$(find_mtd_chardev "factory_data")
|
||||
ubiattach --dev-path="$mtd_path" --devn=1
|
||||
mkdir /tmp/factory_data
|
||||
|
@ -133,7 +133,8 @@ platform_do_upgrade() {
|
||||
fw_setenv auto_recovery yes
|
||||
nand_do_upgrade "$1"
|
||||
;;
|
||||
tplink,eap610-outdoor)
|
||||
tplink,eap610-outdoor|\
|
||||
tplink,eap623od-hd-v1)
|
||||
tplink_do_upgrade "$1"
|
||||
;;
|
||||
yuncore,fap650)
|
||||
|
Loading…
x
Reference in New Issue
Block a user