mirror of
https://github.com/archr-linux/Arch-R.git
synced 2026-07-12 18:19:42 -07:00
Sync RK3326 + 6.12-LTS bugfixes from ROCKNIX
mali-bifrost (RK3326): replace patch 003 with the clean RK3576-style version. Drops the dead BSP-style probe-defer dance, balances the regulator refcount during probe (mirrors the clock prepare/enable), and removes the regulator_is_enabled guard that was silently skipping the disable on suspend. Frees the kernel log of the "missed warnings" sunshineinabox flagged. iwd (network): ControlPortOverNL80211=true so 802.1X EAPOL frames go through nl80211 instead of the legacy raw socket. Some clones with modern wifi firmware fail association otherwise. linux 6.12-LTS: add 0020-usb-gadget-u_ether-guard-NULL-gadget upstream fix. Without it, querying ethtool on the surviving NCM interface during gadget detach dereferences a NULL dev->gadget pointer and panics. Affects anyone who flips USB gadget mode at runtime. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+28
-188
@@ -1,199 +1,39 @@
|
||||
From 5b1c50b3e181a57f5ce0a7d8c50f0f0823ac1609 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Reioux <reioux@gmail.com>
|
||||
Date: Wed, 12 Jun 2024 07:36:52 -0700
|
||||
Subject: [PATCH] midgard: refactor power init and fixed unbalanced runtime PM
|
||||
calls
|
||||
midgard: balance mali probe regulator refcount + drop regulator is_enabled guard
|
||||
|
||||
Signed-off-by: Paul Reioux <reioux@gmail.com>
|
||||
---
|
||||
.../gpu/arm/midgard/mali_kbase_core_linux.c | 124 ++++++++++++------
|
||||
.../platform/meson/mali_kbase_runtime_pm.c | 11 +-
|
||||
2 files changed, 88 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
|
||||
index 0ad8a70..8db0c13 100644
|
||||
--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
|
||||
+++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
|
||||
@@ -4507,31 +4507,44 @@ int power_control_init(struct kbase_device *kbdev)
|
||||
|
||||
pdev = to_platform_device(kbdev->dev);
|
||||
|
||||
-#if defined(CONFIG_REGULATOR)
|
||||
- /* Since the error code EPROBE_DEFER causes the entire probing
|
||||
- * procedure to be restarted from scratch at a later time,
|
||||
- * all regulators will be released before returning.
|
||||
- *
|
||||
- * Any other error is ignored and the driver will continue
|
||||
- * operating with a partial initialization of regulators.
|
||||
- */
|
||||
- for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
|
||||
- kbdev->regulators[i] = regulator_get_optional(kbdev->dev, regulator_names[i]);
|
||||
- if (IS_ERR(kbdev->regulators[i])) {
|
||||
- err = PTR_ERR(kbdev->regulators[i]);
|
||||
- kbdev->regulators[i] = NULL;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- if (err == -EPROBE_DEFER) {
|
||||
- while (i > 0)
|
||||
- regulator_put(kbdev->regulators[--i]);
|
||||
- return err;
|
||||
+// #if defined(CONFIG_REGULATOR)
|
||||
+// /* Since the error code EPROBE_DEFER causes the entire probing
|
||||
+// * procedure to be restarted from scratch at a later time,
|
||||
+// * all regulators will be released before returning.
|
||||
+// *
|
||||
+// * Any other error is ignored and the driver will continue
|
||||
+// * operating with a partial initialization of regulators.
|
||||
+// */
|
||||
+// for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
|
||||
+// kbdev->regulators[i] = regulator_get_optional(kbdev->dev, regulator_names[i]);
|
||||
+// if (IS_ERR(kbdev->regulators[i])) {
|
||||
+// err = PTR_ERR(kbdev->regulators[i]);
|
||||
+// kbdev->regulators[i] = NULL;
|
||||
+// break;
|
||||
+// }
|
||||
+// }
|
||||
+// if (err == -EPROBE_DEFER) {
|
||||
+// while (i > 0)
|
||||
+// regulator_put(kbdev->regulators[--i]);
|
||||
+// return err;
|
||||
+// }
|
||||
+ kbdev->regulators[0] = devm_regulator_get_optional(kbdev->dev, regulator_names[0]);
|
||||
+
|
||||
+ if (IS_ERR(kbdev->regulators[0])) {
|
||||
+ err = PTR_ERR(kbdev->regulators[0]);
|
||||
+ kbdev->regulators[0] = NULL;
|
||||
+ kbdev->nr_regulators = 0;
|
||||
+ } else {
|
||||
+ kbdev->nr_regulators = 1;
|
||||
+
|
||||
+ err = regulator_enable(kbdev->regulators[0]);
|
||||
+ if (err)
|
||||
+ dev_dbg(&pdev->dev, "regulator_enable failed\n");
|
||||
}
|
||||
|
||||
- kbdev->nr_regulators = i;
|
||||
@@ -4607,6 +4607,15 @@
|
||||
|
||||
kbdev->nr_regulators = i;
|
||||
dev_dbg(&pdev->dev, "Regulators probed: %u\n", kbdev->nr_regulators);
|
||||
-#endif
|
||||
+
|
||||
+// #endif
|
||||
|
||||
+ /* Enable regulators during probe to balance the first runtime suspend's
|
||||
+ * regulator_disable() call — mirrors what clocks already do with
|
||||
+ * clk_prepare_enable() below.
|
||||
+ */
|
||||
+ for (i = 0; i < kbdev->nr_regulators; i++) {
|
||||
+ if (kbdev->regulators[i])
|
||||
+ WARN_ON(regulator_enable(kbdev->regulators[i]));
|
||||
+ }
|
||||
#endif
|
||||
|
||||
/* Having more clocks than regulators is acceptable, while the
|
||||
* opposite shall not happen.
|
||||
@@ -4543,30 +4556,55 @@ int power_control_init(struct kbase_device *kbdev)
|
||||
* Any other error is ignored and the driver will continue
|
||||
* operating with a partial initialization of clocks.
|
||||
*/
|
||||
- for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
|
||||
- kbdev->clocks[i] = of_clk_get_by_name(kbdev->dev->of_node, "bus");
|
||||
- if (IS_ERR(kbdev->clocks[i])) {
|
||||
- err = PTR_ERR(kbdev->clocks[i]);
|
||||
- kbdev->clocks[i] = NULL;
|
||||
- break;
|
||||
- }
|
||||
|
||||
- err = clk_prepare_enable(kbdev->clocks[i]);
|
||||
- if (err) {
|
||||
- dev_err(kbdev->dev, "Failed to prepare and enable clock (%d)\n", err);
|
||||
- clk_put(kbdev->clocks[i]);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- if (err == -EPROBE_DEFER) {
|
||||
- while (i > 0) {
|
||||
- clk_disable_unprepare(kbdev->clocks[--i]);
|
||||
- clk_put(kbdev->clocks[i]);
|
||||
- }
|
||||
- goto clocks_probe_defer;
|
||||
+ kbdev->clocks[0] = devm_clk_get_optional(kbdev->dev, NULL);
|
||||
+ if (!IS_ERR(kbdev->clocks[0]))
|
||||
+ dev_dbg(kbdev->dev, "clk_get: %s\n", __clk_get_name(kbdev->clocks[0]));
|
||||
+ else
|
||||
+ dev_err(kbdev->dev, "clk_get: is NULL");
|
||||
+
|
||||
+ /* if platform device is enabled, disable it now */
|
||||
+ //if (__clk_is_enabled(kbdev->clocks[0])) {
|
||||
+ // clk_disable(kbdev->clocks[0]);
|
||||
+ //}
|
||||
+ /* delete from clk tree */
|
||||
+ //clk_unprepare(kbdev->clocks[0]);
|
||||
+ //clk_put(kbdev->clocks[0]);
|
||||
+
|
||||
+ /* now grab the gpu clock node from device tree definition */
|
||||
+ //kbdev->clocks[0] = of_clk_get_by_name(kbdev->dev->of_node, "gpu");
|
||||
+
|
||||
+ /* we are kinda commited here.. if this fails, the system will lock up */
|
||||
+ err = clk_prepare_enable(kbdev->clocks[0]);
|
||||
+ if (err) {
|
||||
+ dev_err(kbdev->dev, "Failed to prepare and enable clock (%d)\n", err);
|
||||
+ clk_put(kbdev->clocks[0]);
|
||||
}
|
||||
|
||||
- kbdev->nr_clocks = i;
|
||||
+ // for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
|
||||
+ // kbdev->clocks[i] = of_clk_get(kbdev->dev->of_node, (int)i);
|
||||
+ // if (IS_ERR(kbdev->clocks[i])) {
|
||||
+ // err = PTR_ERR(kbdev->clocks[i]);
|
||||
+ // kbdev->clocks[i] = NULL;
|
||||
+ // break;
|
||||
+ // }
|
||||
+
|
||||
+ // err = clk_prepare_enable(kbdev->clocks[i]);
|
||||
+ // if (err) {
|
||||
+ // dev_err(kbdev->dev, "Failed to prepare and enable clock (%d)\n", err);
|
||||
+ // clk_put(kbdev->clocks[i]);
|
||||
+ // break;
|
||||
+ // }
|
||||
+ // }
|
||||
+ // if (err == -EPROBE_DEFER) {
|
||||
+ // while (i > 0) {
|
||||
+ // clk_disable_unprepare(kbdev->clocks[--i]);
|
||||
+ // clk_put(kbdev->clocks[i]);
|
||||
+ // }
|
||||
+ // goto clocks_probe_defer;
|
||||
+ // }
|
||||
+
|
||||
+ kbdev->nr_clocks = 1;
|
||||
dev_dbg(&pdev->dev, "Clocks probed: %u\n", kbdev->nr_clocks);
|
||||
|
||||
/* Any error in parsing the OPP table from the device file
|
||||
diff --git a/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c b/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c
|
||||
index bd3b4b5..33a24bb 100644
|
||||
--- a/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c
|
||||
+++ b/product/kernel/drivers/gpu/arm/midgard/platform/meson/mali_kbase_runtime_pm.c
|
||||
@@ -113,7 +113,8 @@ static void enable_gpu_power_control(struct kbase_device *kbdev)
|
||||
if (WARN_ON(kbdev->clocks[i] == NULL))
|
||||
;
|
||||
else if (!__clk_is_enabled(kbdev->clocks[i]))
|
||||
- WARN_ON(clk_prepare_enable(kbdev->clocks[i]));
|
||||
+ //WARN_ON(clk_prepare_enable(kbdev->clocks[i]));
|
||||
+ ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,8 +126,9 @@ static void disable_gpu_power_control(struct kbase_device *kbdev)
|
||||
if (WARN_ON(kbdev->clocks[i] == NULL))
|
||||
;
|
||||
else if (__clk_is_enabled(kbdev->clocks[i])) {
|
||||
- clk_disable_unprepare(kbdev->clocks[i]);
|
||||
- WARN_ON(__clk_is_enabled(kbdev->clocks[i]));
|
||||
+ //clk_disable_unprepare(kbdev->clocks[i]);
|
||||
+ //WARN_ON(__clk_is_enabled(kbdev->clocks[i]));
|
||||
+ ;
|
||||
@@ -4731,6 +4740,7 @@
|
||||
#if defined(CONFIG_OF) && defined(CONFIG_REGULATOR)
|
||||
for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
|
||||
if (kbdev->regulators[i]) {
|
||||
+ regulator_disable(kbdev->regulators[i]);
|
||||
regulator_put(kbdev->regulators[i]);
|
||||
kbdev->regulators[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +137,8 @@ static void disable_gpu_power_control(struct kbase_device *kbdev)
|
||||
--- a/product/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c
|
||||
+++ b/product/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c
|
||||
@@ -38,7 +38,7 @@ static void enable_gpu_power_control(struct kbase_device *kbdev)
|
||||
for (i = 0; i < kbdev->nr_regulators; i++) {
|
||||
if (WARN_ON(kbdev->regulators[i] == NULL))
|
||||
;
|
||||
else if (regulator_is_enabled(kbdev->regulators[i]))
|
||||
- WARN_ON(regulator_disable(kbdev->regulators[i]));
|
||||
+ //WARN_ON(regulator_disable(kbdev->regulators[i]));
|
||||
+ ;
|
||||
- else if (!regulator_is_enabled(kbdev->regulators[i]))
|
||||
+ else
|
||||
WARN_ON(regulator_enable(kbdev->regulators[i]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
From: Kuen-Han Tsai <khtsai@google.com>
|
||||
Date: Mon, 16 Mar 2026 15:49:09 +0800
|
||||
Subject: [PATCH] usb: gadget: u_ether: Fix NULL pointer deref in eth_get_drvinfo
|
||||
|
||||
Commit ec35c1969650 ("usb: gadget: f_ncm: Fix net_device lifecycle with
|
||||
device_move") reparents the gadget device to /sys/devices/virtual during
|
||||
unbind, clearing the gadget pointer. If the userspace tool queries on
|
||||
the surviving interface during this detached window, this leads to a
|
||||
NULL pointer dereference.
|
||||
|
||||
Unable to handle kernel NULL pointer dereference
|
||||
Call trace:
|
||||
eth_get_drvinfo+0x50/0x90
|
||||
ethtool_get_drvinfo+0x5c/0x1f0
|
||||
__dev_ethtool+0xaec/0x1fe0
|
||||
dev_ethtool+0x134/0x2e0
|
||||
dev_ioctl+0x338/0x560
|
||||
|
||||
Add a NULL check for dev->gadget in eth_get_drvinfo(). When detached,
|
||||
skip copying the fw_version and bus_info strings, which is natively
|
||||
handled by ethtool_get_drvinfo for empty strings.
|
||||
|
||||
Suggested-by: Val Packett <val@packett.cool>
|
||||
Reported-by: Val Packett <val@packett.cool>
|
||||
Closes: https://lore.kernel.org/linux-usb/10890524-cf83-4a71-b879-93e2b2cc1fcc@packett.cool/
|
||||
Fixes: ec35c1969650 ("usb: gadget: f_ncm: Fix net_device lifecycle with device_move")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
|
||||
Link: https://lore.kernel.org/linux-usb/20260316-eth-null-deref-v1-1-07005f33be85@google.com/
|
||||
|
||||
---
|
||||
drivers/usb/gadget/function/u_ether.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
|
||||
index 1a9e7c495e2e..a653fae9c0cb 100644
|
||||
--- a/drivers/usb/gadget/function/u_ether.c
|
||||
+++ b/drivers/usb/gadget/function/u_ether.c
|
||||
@@ -113,8 +113,10 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
|
||||
|
||||
strscpy(p->driver, "g_ether", sizeof(p->driver));
|
||||
strscpy(p->version, UETH__VERSION, sizeof(p->version));
|
||||
- strscpy(p->fw_version, dev->gadget->name, sizeof(p->fw_version));
|
||||
- strscpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof(p->bus_info));
|
||||
+ if (dev->gadget) {
|
||||
+ strscpy(p->fw_version, dev->gadget->name, sizeof(p->fw_version));
|
||||
+ strscpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof(p->bus_info));
|
||||
+ }
|
||||
}
|
||||
|
||||
/* REVISIT can also support:
|
||||
@@ -1,7 +1,7 @@
|
||||
# use built-in dhcp client
|
||||
[General]
|
||||
EnableNetworkConfiguration=true
|
||||
ControlPortOverNL80211=false
|
||||
ControlPortOverNL80211=true
|
||||
UseDefaultInterface=true
|
||||
AddressRandomization=disabled
|
||||
AddressRandomizationRange=full
|
||||
|
||||
Reference in New Issue
Block a user