From: Sasha Levin Date: Sat, 26 Apr 2025 13:23:11 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v5.4.293~86 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f52e9a0b9fd07d3fe348d79745b0cbedd44608ed;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/backlight-led_bl-convert-to-platform-remove-callback.patch b/queue-5.10/backlight-led_bl-convert-to-platform-remove-callback.patch new file mode 100644 index 0000000000..2051e9ab60 --- /dev/null +++ b/queue-5.10/backlight-led_bl-convert-to-platform-remove-callback.patch @@ -0,0 +1,67 @@ +From 1e8aad01d355754c5ec31df0bc8297af773c77da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Mar 2023 08:39:38 +0100 +Subject: backlight: led_bl: Convert to platform remove callback returning void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit c4c4fa57fd3cc00020152baa169337521f90b2ad ] + +The .remove() callback for a platform driver returns an int which makes +many driver authors wrongly assume it's possible to do error handling by +returning an error code. However the value returned is (mostly) ignored +and this typically results in resource leaks. To improve here there is a +quest to make the remove callback return void. In the first step of this +quest all drivers are converted to .remove_new() which already returns +void. + +Trivially convert this driver from always returning zero in the remove +callback to the void returning variant. + +Signed-off-by: Uwe Kleine-König +Reviewed-by: Daniel Thompson +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230308073945.2336302-7-u.kleine-koenig@pengutronix.de +Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()") +Signed-off-by: Sasha Levin +--- + drivers/video/backlight/led_bl.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c +index f54d256e2d548..a1b6a2ad73a07 100644 +--- a/drivers/video/backlight/led_bl.c ++++ b/drivers/video/backlight/led_bl.c +@@ -217,7 +217,7 @@ static int led_bl_probe(struct platform_device *pdev) + return 0; + } + +-static int led_bl_remove(struct platform_device *pdev) ++static void led_bl_remove(struct platform_device *pdev) + { + struct led_bl_data *priv = platform_get_drvdata(pdev); + struct backlight_device *bl = priv->bl_dev; +@@ -228,8 +228,6 @@ static int led_bl_remove(struct platform_device *pdev) + led_bl_power_off(priv); + for (i = 0; i < priv->nb_leds; i++) + led_sysfs_enable(priv->leds[i]); +- +- return 0; + } + + static const struct of_device_id led_bl_of_match[] = { +@@ -245,7 +243,7 @@ static struct platform_driver led_bl_driver = { + .of_match_table = of_match_ptr(led_bl_of_match), + }, + .probe = led_bl_probe, +- .remove = led_bl_remove, ++ .remove_new = led_bl_remove, + }; + + module_platform_driver(led_bl_driver); +-- +2.39.5 + diff --git a/queue-5.10/backlight-led_bl-hold-led_access-lock-when-calling-l.patch b/queue-5.10/backlight-led_bl-hold-led_access-lock-when-calling-l.patch new file mode 100644 index 0000000000..a89e398a6b --- /dev/null +++ b/queue-5.10/backlight-led_bl-hold-led_access-lock-when-calling-l.patch @@ -0,0 +1,56 @@ +From f52c59ee0d0e00936d200fa5fa2c7052ec019397 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 10:19:14 +0100 +Subject: backlight: led_bl: Hold led_access lock when calling + led_sysfs_disable() + +From: Herve Codina + +[ Upstream commit 276822a00db3c1061382b41e72cafc09d6a0ec30 ] + +Lockdep detects the following issue on led-backlight removal: + [ 142.315935] ------------[ cut here ]------------ + [ 142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80 + ... + [ 142.500725] Call trace: + [ 142.503176] led_sysfs_enable+0x54/0x80 (P) + [ 142.507370] led_bl_remove+0x80/0xa8 [led_bl] + [ 142.511742] platform_remove+0x30/0x58 + [ 142.515501] device_remove+0x54/0x90 + ... + +Indeed, led_sysfs_enable() has to be called with the led_access +lock held. + +Hold the lock when calling led_sysfs_disable(). + +Fixes: ae232e45acf9 ("backlight: add led-backlight driver") +Cc: stable@vger.kernel.org +Signed-off-by: Herve Codina +Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/video/backlight/led_bl.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c +index a1b6a2ad73a07..589dae9ebb638 100644 +--- a/drivers/video/backlight/led_bl.c ++++ b/drivers/video/backlight/led_bl.c +@@ -226,8 +226,11 @@ static void led_bl_remove(struct platform_device *pdev) + backlight_device_unregister(bl); + + led_bl_power_off(priv); +- for (i = 0; i < priv->nb_leds; i++) ++ for (i = 0; i < priv->nb_leds; i++) { ++ mutex_lock(&priv->leds[i]->led_access); + led_sysfs_enable(priv->leds[i]); ++ mutex_unlock(&priv->leds[i]->led_access); ++ } + } + + static const struct of_device_id led_bl_of_match[] = { +-- +2.39.5 + diff --git a/queue-5.10/cifs-avoid-null-pointer-dereference-in-dbg-call.patch b/queue-5.10/cifs-avoid-null-pointer-dereference-in-dbg-call.patch new file mode 100644 index 0000000000..0d73472926 --- /dev/null +++ b/queue-5.10/cifs-avoid-null-pointer-dereference-in-dbg-call.patch @@ -0,0 +1,47 @@ +From 94b2f11a89b3370e68571e93cd3a557cc78d3fa9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 17:28:58 +0300 +Subject: cifs: avoid NULL pointer dereference in dbg call + +From: Alexandra Diupina + +[ Upstream commit b4885bd5935bb26f0a414ad55679a372e53f9b9b ] + +cifs_server_dbg() implies server to be non-NULL so +move call under condition to avoid NULL pointer dereference. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: e79b0332ae06 ("cifs: ignore cached share root handle closing errors") +Cc: stable@vger.kernel.org +Signed-off-by: Alexandra Diupina +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2misc.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c +index d21b27e68f2a8..c0b80ba8875af 100644 +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -809,11 +809,12 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, + WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); + spin_unlock(&cifs_tcp_ses_lock); + +- if (tcon->ses) ++ if (tcon->ses) { + server = tcon->ses->server; +- +- cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", +- tcon->tid, persistent_fid, volatile_fid); ++ cifs_server_dbg(FYI, ++ "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", ++ tcon->tid, persistent_fid, volatile_fid); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-5.10/cifs-print-tids-as-hex.patch b/queue-5.10/cifs-print-tids-as-hex.patch new file mode 100644 index 0000000000..7bd7c42764 --- /dev/null +++ b/queue-5.10/cifs-print-tids-as-hex.patch @@ -0,0 +1,50 @@ +From ca33e943102697ae4996cb90123cd0fdfdb488ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 May 2022 11:41:04 -0300 +Subject: cifs: print TIDs as hex + +From: Enzo Matsumiya + +[ Upstream commit 71081e7ac16c93acdd18afa65daa468620bb1b64 ] + +Makes these debug messages easier to read + +Signed-off-by: Enzo Matsumiya +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Stable-dep-of: b4885bd5935b ("cifs: avoid NULL pointer dereference in dbg call") +Signed-off-by: Sasha Levin +--- + fs/cifs/connect.c | 2 +- + fs/cifs/smb2misc.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index a3c0e6a4e4847..2c0522d97e037 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -2770,7 +2770,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) + goto out; + } + +- cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid); ++ cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid); + + ses->tcon_ipc = tcon; + out: +diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c +index 64887856331ae..d21b27e68f2a8 100644 +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -812,7 +812,7 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, + if (tcon->ses) + server = tcon->ses->server; + +- cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu\n", ++ cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", + tcon->tid, persistent_fid, volatile_fid); + + return 0; +-- +2.39.5 + diff --git a/queue-5.10/driver-core-platform-change-logic-implementing-platf.patch b/queue-5.10/driver-core-platform-change-logic-implementing-platf.patch new file mode 100644 index 0000000000..92a89de60b --- /dev/null +++ b/queue-5.10/driver-core-platform-change-logic-implementing-platf.patch @@ -0,0 +1,83 @@ +From 5cae0e026c8b364f338819cb26b34cb3ecc51fad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Nov 2020 13:46:10 +0100 +Subject: driver core: platform: change logic implementing + platform_driver_probe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 16085668eacdc56c46652d0f3bfef81ecace57de ] + +Instead of overwriting the core driver's probe function handle probing +devices for drivers loaded by platform_driver_probe() in the platform +driver probe function. + +The intended goal is to not have to change the probe function to +simplify converting the platform bus to use bus functions. + +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20201119124611.2573057-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()") +Signed-off-by: Sasha Levin +--- + drivers/base/platform.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index fa023cf80dc48..16426eb934632 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -743,12 +743,25 @@ struct platform_device *platform_device_register_full( + } + EXPORT_SYMBOL_GPL(platform_device_register_full); + ++static int platform_probe_fail(struct platform_device *pdev); ++ + static int platform_drv_probe(struct device *_dev) + { + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + int ret; + ++ /* ++ * A driver registered using platform_driver_probe() cannot be bound ++ * again later because the probe function usually lives in __init code ++ * and so is gone. For these drivers .probe is set to ++ * platform_probe_fail in __platform_driver_probe(). Don't even ++ * prepare clocks and PM domains for these to match the traditional ++ * behaviour. ++ */ ++ if (unlikely(drv->probe == platform_probe_fail)) ++ return -ENXIO; ++ + ret = of_clk_set_defaults(_dev->of_node, false); + if (ret < 0) + return ret; +@@ -822,7 +835,7 @@ void platform_driver_unregister(struct platform_driver *drv) + } + EXPORT_SYMBOL_GPL(platform_driver_unregister); + +-static int platform_drv_probe_fail(struct device *_dev) ++static int platform_probe_fail(struct platform_device *pdev) + { + return -ENXIO; + } +@@ -887,10 +900,9 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, + * new devices fail. + */ + spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); +- drv->probe = NULL; ++ drv->probe = platform_probe_fail; + if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) + retval = -ENODEV; +- drv->driver.probe = platform_drv_probe_fail; + spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); + + if (code != retval) +-- +2.39.5 + diff --git a/queue-5.10/driver-core-platform-emit-a-warning-if-a-remove-call.patch b/queue-5.10/driver-core-platform-emit-a-warning-if-a-remove-call.patch new file mode 100644 index 0000000000..00ab6dbbb2 --- /dev/null +++ b/queue-5.10/driver-core-platform-emit-a-warning-if-a-remove-call.patch @@ -0,0 +1,60 @@ +From be789066e7a8cf1d42fae45038e28a7663cbc213 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Feb 2021 22:15:37 +0100 +Subject: driver core: platform: Emit a warning if a remove callback returned + non-zero +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit e5e1c209788138f33ca6558bf9f572f6904f486d ] + +The driver core ignores the return value of a bus' remove callback. However +a driver returning an error code is a hint that there is a problem, +probably a driver author who expects that returning e.g. -EBUSY has any +effect. + +The right thing to do would be to make struct platform_driver::remove() +return void. With the immense number of platform drivers this is however a +big quest and I hope to prevent at least a few new drivers that return an +error code here. + +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20210207211537.19992-1-uwe@kleine-koenig.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()") +Signed-off-by: Sasha Levin +--- + drivers/base/platform.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 90166535a5c05..d0b15cbab0ff0 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -1305,13 +1305,16 @@ static int platform_remove(struct device *_dev) + { + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); +- int ret = 0; + +- if (drv->remove) +- ret = drv->remove(dev); ++ if (drv->remove) { ++ int ret = drv->remove(dev); ++ ++ if (ret) ++ dev_warn(_dev, "remove callback returned a non-zero value. This will be ignored.\n"); ++ } + dev_pm_domain_detach(_dev, true); + +- return ret; ++ return 0; + } + + static void platform_shutdown(struct device *_dev) +-- +2.39.5 + diff --git a/queue-5.10/driver-core-platform-reorder-functions.patch b/queue-5.10/driver-core-platform-reorder-functions.patch new file mode 100644 index 0000000000..934cbdaf39 --- /dev/null +++ b/queue-5.10/driver-core-platform-reorder-functions.patch @@ -0,0 +1,361 @@ +From 755c0725a3eaa804db5be07cd930b3d0e59648fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Nov 2020 13:46:09 +0100 +Subject: driver core: platform: reorder functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit e21d740a3fe5ad2db7b5f5c2331fe2b713b1edba ] + +This way all callbacks and structures used to initialize +platform_bus_type are defined just before platform_bus_type and in the +same order. Also move platform_drv_probe_fail just before it's only +user. + +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20201119124611.2573057-1-u.kleine-koenig@pengutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()") +Signed-off-by: Sasha Levin +--- + drivers/base/platform.c | 293 ++++++++++++++++++++-------------------- + 1 file changed, 147 insertions(+), 146 deletions(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 647066229fec3..fa023cf80dc48 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -772,11 +772,6 @@ static int platform_drv_probe(struct device *_dev) + return ret; + } + +-static int platform_drv_probe_fail(struct device *_dev) +-{ +- return -ENXIO; +-} +- + static int platform_drv_remove(struct device *_dev) + { + struct platform_driver *drv = to_platform_driver(_dev->driver); +@@ -827,6 +822,11 @@ void platform_driver_unregister(struct platform_driver *drv) + } + EXPORT_SYMBOL_GPL(platform_driver_unregister); + ++static int platform_drv_probe_fail(struct device *_dev) ++{ ++ return -ENXIO; ++} ++ + /** + * __platform_driver_probe - register driver for non-hotpluggable device + * @drv: platform driver structure +@@ -1017,109 +1017,6 @@ void platform_unregister_drivers(struct platform_driver * const *drivers, + } + EXPORT_SYMBOL_GPL(platform_unregister_drivers); + +-/* modalias support enables more hands-off userspace setup: +- * (a) environment variable lets new-style hotplug events work once system is +- * fully running: "modprobe $MODALIAS" +- * (b) sysfs attribute lets new-style coldplug recover from hotplug events +- * mishandled before system is fully running: "modprobe $(cat modalias)" +- */ +-static ssize_t modalias_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- int len; +- +- len = of_device_modalias(dev, buf, PAGE_SIZE); +- if (len != -ENODEV) +- return len; +- +- len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); +- if (len != -ENODEV) +- return len; +- +- return sysfs_emit(buf, "platform:%s\n", pdev->name); +-} +-static DEVICE_ATTR_RO(modalias); +- +-static ssize_t driver_override_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- int ret; +- +- ret = driver_set_override(dev, &pdev->driver_override, buf, count); +- if (ret) +- return ret; +- +- return count; +-} +- +-static ssize_t driver_override_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- ssize_t len; +- +- device_lock(dev); +- len = sysfs_emit(buf, "%s\n", pdev->driver_override); +- device_unlock(dev); +- +- return len; +-} +-static DEVICE_ATTR_RW(driver_override); +- +-static ssize_t numa_node_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- return sysfs_emit(buf, "%d\n", dev_to_node(dev)); +-} +-static DEVICE_ATTR_RO(numa_node); +- +-static umode_t platform_dev_attrs_visible(struct kobject *kobj, struct attribute *a, +- int n) +-{ +- struct device *dev = container_of(kobj, typeof(*dev), kobj); +- +- if (a == &dev_attr_numa_node.attr && +- dev_to_node(dev) == NUMA_NO_NODE) +- return 0; +- +- return a->mode; +-} +- +-static struct attribute *platform_dev_attrs[] = { +- &dev_attr_modalias.attr, +- &dev_attr_numa_node.attr, +- &dev_attr_driver_override.attr, +- NULL, +-}; +- +-static struct attribute_group platform_dev_group = { +- .attrs = platform_dev_attrs, +- .is_visible = platform_dev_attrs_visible, +-}; +-__ATTRIBUTE_GROUPS(platform_dev); +- +-static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- int rc; +- +- /* Some devices have extra OF data and an OF-style MODALIAS */ +- rc = of_device_uevent_modalias(dev, env); +- if (rc != -ENODEV) +- return rc; +- +- rc = acpi_device_uevent_modalias(dev, env); +- if (rc != -ENODEV) +- return rc; +- +- add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, +- pdev->name); +- return 0; +-} +- + static const struct platform_device_id *platform_match_id( + const struct platform_device_id *id, + struct platform_device *pdev) +@@ -1134,44 +1031,6 @@ static const struct platform_device_id *platform_match_id( + return NULL; + } + +-/** +- * platform_match - bind platform device to platform driver. +- * @dev: device. +- * @drv: driver. +- * +- * Platform device IDs are assumed to be encoded like this: +- * "", where is a short description of the type of +- * device, like "pci" or "floppy", and is the enumerated +- * instance of the device, like '0' or '42'. Driver IDs are simply +- * "". So, extract the from the platform_device structure, +- * and compare it against the name of the driver. Return whether they match +- * or not. +- */ +-static int platform_match(struct device *dev, struct device_driver *drv) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- struct platform_driver *pdrv = to_platform_driver(drv); +- +- /* When driver_override is set, only bind to the matching driver */ +- if (pdev->driver_override) +- return !strcmp(pdev->driver_override, drv->name); +- +- /* Attempt an OF style match first */ +- if (of_driver_match_device(dev, drv)) +- return 1; +- +- /* Then try ACPI style match */ +- if (acpi_driver_match_device(dev, drv)) +- return 1; +- +- /* Then try to match against the id table */ +- if (pdrv->id_table) +- return platform_match_id(pdrv->id_table, pdev) != NULL; +- +- /* fall-back to driver name match */ +- return (strcmp(pdev->name, drv->name) == 0); +-} +- + #ifdef CONFIG_PM_SLEEP + + static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) +@@ -1316,6 +1175,148 @@ int platform_pm_restore(struct device *dev) + + #endif /* CONFIG_HIBERNATE_CALLBACKS */ + ++/* modalias support enables more hands-off userspace setup: ++ * (a) environment variable lets new-style hotplug events work once system is ++ * fully running: "modprobe $MODALIAS" ++ * (b) sysfs attribute lets new-style coldplug recover from hotplug events ++ * mishandled before system is fully running: "modprobe $(cat modalias)" ++ */ ++static ssize_t modalias_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ int len; ++ ++ len = of_device_modalias(dev, buf, PAGE_SIZE); ++ if (len != -ENODEV) ++ return len; ++ ++ len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); ++ if (len != -ENODEV) ++ return len; ++ ++ return sysfs_emit(buf, "platform:%s\n", pdev->name); ++} ++static DEVICE_ATTR_RO(modalias); ++ ++static ssize_t numa_node_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sysfs_emit(buf, "%d\n", dev_to_node(dev)); ++} ++static DEVICE_ATTR_RO(numa_node); ++ ++static ssize_t driver_override_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ ssize_t len; ++ ++ device_lock(dev); ++ len = sysfs_emit(buf, "%s\n", pdev->driver_override); ++ device_unlock(dev); ++ ++ return len; ++} ++ ++static ssize_t driver_override_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ int ret; ++ ++ ret = driver_set_override(dev, &pdev->driver_override, buf, count); ++ if (ret) ++ return ret; ++ ++ return count; ++} ++static DEVICE_ATTR_RW(driver_override); ++ ++static struct attribute *platform_dev_attrs[] = { ++ &dev_attr_modalias.attr, ++ &dev_attr_numa_node.attr, ++ &dev_attr_driver_override.attr, ++ NULL, ++}; ++ ++static umode_t platform_dev_attrs_visible(struct kobject *kobj, struct attribute *a, ++ int n) ++{ ++ struct device *dev = container_of(kobj, typeof(*dev), kobj); ++ ++ if (a == &dev_attr_numa_node.attr && ++ dev_to_node(dev) == NUMA_NO_NODE) ++ return 0; ++ ++ return a->mode; ++} ++ ++static struct attribute_group platform_dev_group = { ++ .attrs = platform_dev_attrs, ++ .is_visible = platform_dev_attrs_visible, ++}; ++__ATTRIBUTE_GROUPS(platform_dev); ++ ++ ++/** ++ * platform_match - bind platform device to platform driver. ++ * @dev: device. ++ * @drv: driver. ++ * ++ * Platform device IDs are assumed to be encoded like this: ++ * "", where is a short description of the type of ++ * device, like "pci" or "floppy", and is the enumerated ++ * instance of the device, like '0' or '42'. Driver IDs are simply ++ * "". So, extract the from the platform_device structure, ++ * and compare it against the name of the driver. Return whether they match ++ * or not. ++ */ ++static int platform_match(struct device *dev, struct device_driver *drv) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct platform_driver *pdrv = to_platform_driver(drv); ++ ++ /* When driver_override is set, only bind to the matching driver */ ++ if (pdev->driver_override) ++ return !strcmp(pdev->driver_override, drv->name); ++ ++ /* Attempt an OF style match first */ ++ if (of_driver_match_device(dev, drv)) ++ return 1; ++ ++ /* Then try ACPI style match */ ++ if (acpi_driver_match_device(dev, drv)) ++ return 1; ++ ++ /* Then try to match against the id table */ ++ if (pdrv->id_table) ++ return platform_match_id(pdrv->id_table, pdev) != NULL; ++ ++ /* fall-back to driver name match */ ++ return (strcmp(pdev->name, drv->name) == 0); ++} ++ ++static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ int rc; ++ ++ /* Some devices have extra OF data and an OF-style MODALIAS */ ++ rc = of_device_uevent_modalias(dev, env); ++ if (rc != -ENODEV) ++ return rc; ++ ++ rc = acpi_device_uevent_modalias(dev, env); ++ if (rc != -ENODEV) ++ return rc; ++ ++ add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, ++ pdev->name); ++ return 0; ++} ++ + int platform_dma_configure(struct device *dev) + { + enum dev_dma_attr attr; +-- +2.39.5 + diff --git a/queue-5.10/driver-core-platform-use-bus_type-functions.patch b/queue-5.10/driver-core-platform-use-bus_type-functions.patch new file mode 100644 index 0000000000..e73fab0a54 --- /dev/null +++ b/queue-5.10/driver-core-platform-use-bus_type-functions.patch @@ -0,0 +1,194 @@ +From 9d1ddcb33799b6b3c278d2c440ec242db06cc644 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Nov 2020 13:46:11 +0100 +Subject: driver core: platform: use bus_type functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 9c30921fe7994907e0b3e0637b2c8c0fc4b5171f ] + +This works towards the goal mentioned in 2006 in commit 594c8281f905 +("[PATCH] Add bus_type probe, remove, shutdown methods."). + +The functions are moved to where the other bus_type functions are +defined and renamed to match the already established naming scheme. + +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20201119124611.2573057-3-u.kleine-koenig@pengutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()") +Signed-off-by: Sasha Levin +--- + drivers/base/platform.c | 132 ++++++++++++++++++++-------------------- + 1 file changed, 65 insertions(+), 67 deletions(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 16426eb934632..90166535a5c05 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -743,70 +743,6 @@ struct platform_device *platform_device_register_full( + } + EXPORT_SYMBOL_GPL(platform_device_register_full); + +-static int platform_probe_fail(struct platform_device *pdev); +- +-static int platform_drv_probe(struct device *_dev) +-{ +- struct platform_driver *drv = to_platform_driver(_dev->driver); +- struct platform_device *dev = to_platform_device(_dev); +- int ret; +- +- /* +- * A driver registered using platform_driver_probe() cannot be bound +- * again later because the probe function usually lives in __init code +- * and so is gone. For these drivers .probe is set to +- * platform_probe_fail in __platform_driver_probe(). Don't even +- * prepare clocks and PM domains for these to match the traditional +- * behaviour. +- */ +- if (unlikely(drv->probe == platform_probe_fail)) +- return -ENXIO; +- +- ret = of_clk_set_defaults(_dev->of_node, false); +- if (ret < 0) +- return ret; +- +- ret = dev_pm_domain_attach(_dev, true); +- if (ret) +- goto out; +- +- if (drv->probe) { +- ret = drv->probe(dev); +- if (ret) +- dev_pm_domain_detach(_dev, true); +- } +- +-out: +- if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { +- dev_warn(_dev, "probe deferral not supported\n"); +- ret = -ENXIO; +- } +- +- return ret; +-} +- +-static int platform_drv_remove(struct device *_dev) +-{ +- struct platform_driver *drv = to_platform_driver(_dev->driver); +- struct platform_device *dev = to_platform_device(_dev); +- int ret = 0; +- +- if (drv->remove) +- ret = drv->remove(dev); +- dev_pm_domain_detach(_dev, true); +- +- return ret; +-} +- +-static void platform_drv_shutdown(struct device *_dev) +-{ +- struct platform_driver *drv = to_platform_driver(_dev->driver); +- struct platform_device *dev = to_platform_device(_dev); +- +- if (drv->shutdown) +- drv->shutdown(dev); +-} +- + /** + * __platform_driver_register - register a driver for platform-level devices + * @drv: platform driver structure +@@ -817,9 +753,6 @@ int __platform_driver_register(struct platform_driver *drv, + { + drv->driver.owner = owner; + drv->driver.bus = &platform_bus_type; +- drv->driver.probe = platform_drv_probe; +- drv->driver.remove = platform_drv_remove; +- drv->driver.shutdown = platform_drv_shutdown; + + return driver_register(&drv->driver); + } +@@ -1329,6 +1262,68 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) + return 0; + } + ++static int platform_probe(struct device *_dev) ++{ ++ struct platform_driver *drv = to_platform_driver(_dev->driver); ++ struct platform_device *dev = to_platform_device(_dev); ++ int ret; ++ ++ /* ++ * A driver registered using platform_driver_probe() cannot be bound ++ * again later because the probe function usually lives in __init code ++ * and so is gone. For these drivers .probe is set to ++ * platform_probe_fail in __platform_driver_probe(). Don't even prepare ++ * clocks and PM domains for these to match the traditional behaviour. ++ */ ++ if (unlikely(drv->probe == platform_probe_fail)) ++ return -ENXIO; ++ ++ ret = of_clk_set_defaults(_dev->of_node, false); ++ if (ret < 0) ++ return ret; ++ ++ ret = dev_pm_domain_attach(_dev, true); ++ if (ret) ++ goto out; ++ ++ if (drv->probe) { ++ ret = drv->probe(dev); ++ if (ret) ++ dev_pm_domain_detach(_dev, true); ++ } ++ ++out: ++ if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { ++ dev_warn(_dev, "probe deferral not supported\n"); ++ ret = -ENXIO; ++ } ++ ++ return ret; ++} ++ ++static int platform_remove(struct device *_dev) ++{ ++ struct platform_driver *drv = to_platform_driver(_dev->driver); ++ struct platform_device *dev = to_platform_device(_dev); ++ int ret = 0; ++ ++ if (drv->remove) ++ ret = drv->remove(dev); ++ dev_pm_domain_detach(_dev, true); ++ ++ return ret; ++} ++ ++static void platform_shutdown(struct device *_dev) ++{ ++ struct platform_driver *drv = to_platform_driver(_dev->driver); ++ struct platform_device *dev = to_platform_device(_dev); ++ ++ if (drv->shutdown) ++ drv->shutdown(dev); ++} ++ ++ + int platform_dma_configure(struct device *dev) + { + enum dev_dma_attr attr; +@@ -1355,6 +1350,9 @@ struct bus_type platform_bus_type = { + .dev_groups = platform_dev_groups, + .match = platform_match, + .uevent = platform_uevent, ++ .probe = platform_probe, ++ .remove = platform_remove, ++ .shutdown = platform_shutdown, + .dma_configure = platform_dma_configure, + .pm = &platform_dev_pm_ops, + }; +-- +2.39.5 + diff --git a/queue-5.10/drm-amd-amdgpu-amdgpu_vram_mgr-add-missing-descripti.patch b/queue-5.10/drm-amd-amdgpu-amdgpu_vram_mgr-add-missing-descripti.patch new file mode 100644 index 0000000000..9523634bc6 --- /dev/null +++ b/queue-5.10/drm-amd-amdgpu-amdgpu_vram_mgr-add-missing-descripti.patch @@ -0,0 +1,48 @@ +From a9c47f8b5efe42ca3ceb81a9e8d70006ba9ca05f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Nov 2020 13:49:17 +0000 +Subject: drm/amd/amdgpu/amdgpu_vram_mgr: Add missing descriptions for 'dev' + and 'dir' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lee Jones + +[ Upstream commit 2c8645b7a6974b33744b677e9ddc89650776af46 ] + +Fixes the following W=1 kernel build warning(s): + + drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:648: warning: Function parameter or member 'dev' not described in 'amdgpu_vram_mgr_free_sgt' + drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:648: warning: Function parameter or member 'dir' not described in 'amdgpu_vram_mgr_free_sgt' + +Cc: Alex Deucher +Cc: "Christian König" +Cc: David Airlie +Cc: Daniel Vetter +Cc: amd-gfx@lists.freedesktop.org +Cc: dri-devel@lists.freedesktop.org +Signed-off-by: Lee Jones +Signed-off-by: Alex Deucher +Stable-dep-of: c0dd8a9253fa ("drm/amdgpu/dma_buf: fix page_link check") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +index 0c6b7c5ecfec8..2c3a94e939bab 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +@@ -531,6 +531,8 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, + * amdgpu_vram_mgr_alloc_sgt - allocate and fill a sg table + * + * @adev: amdgpu device pointer ++ * @dev: device pointer ++ * @dir: data direction of resource to unmap + * @sgt: sg table to free + * + * Free a previously allocate sg table. +-- +2.39.5 + diff --git a/queue-5.10/drm-amdgpu-dma_buf-fix-page_link-check.patch b/queue-5.10/drm-amdgpu-dma_buf-fix-page_link-check.patch new file mode 100644 index 0000000000..494880e9a0 --- /dev/null +++ b/queue-5.10/drm-amdgpu-dma_buf-fix-page_link-check.patch @@ -0,0 +1,45 @@ +From 7e694c1f9f11eed69047faa76f75378475bcc265 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Apr 2025 15:18:25 +0100 +Subject: drm/amdgpu/dma_buf: fix page_link check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Auld + +[ Upstream commit c0dd8a9253fadfb8e5357217d085f1989da4ef0a ] + +The page_link lower bits of the first sg could contain something like +SG_END, if we are mapping a single VRAM page or contiguous blob which +fits into one sg entry. Rather pull out the struct page, and use that in +our check to know if we mapped struct pages vs VRAM. + +Fixes: f44ffd677fb3 ("drm/amdgpu: add support for exporting VRAM using DMA-buf v3") +Signed-off-by: Matthew Auld +Cc: Christian König +Cc: amd-gfx@lists.freedesktop.org +Cc: # v5.8+ +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +index bbbacc7b6c463..e4d0a9377e712 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +@@ -357,7 +357,7 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach, + struct sg_table *sgt, + enum dma_data_direction dir) + { +- if (sgt->sgl->page_link) { ++ if (sg_page(sgt->sgl)) { + dma_unmap_sgtable(attach->dev, sgt, dir, 0); + sg_free_table(sgt); + kfree(sgt); +-- +2.39.5 + diff --git a/queue-5.10/drm-amdgpu-remove-amdgpu_device-arg-from-free_sgt-ap.patch b/queue-5.10/drm-amdgpu-remove-amdgpu_device-arg-from-free_sgt-ap.patch new file mode 100644 index 0000000000..68991082b7 --- /dev/null +++ b/queue-5.10/drm-amdgpu-remove-amdgpu_device-arg-from-free_sgt-ap.patch @@ -0,0 +1,90 @@ +From 09a1b6ca7c7d9c07c702479646a0a8cfa2329e11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Feb 2021 20:48:06 -0600 +Subject: drm/amdgpu: Remove amdgpu_device arg from free_sgt api (v2) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ramesh Errabolu + +[ Upstream commit 5392b2af97dc5802991f953eb2687e538da4688c ] + +Currently callers have to provide handle of amdgpu_device, +which is not used by the implementation. It is unlikely this +parameter will become useful in future, thus removing it + +v2: squash in unused variable fix + +Reviewed-by: Christian König +Signed-off-by: Ramesh Errabolu +Signed-off-by: Alex Deucher +Stable-dep-of: c0dd8a9253fa ("drm/amdgpu/dma_buf: fix page_link check") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 7 +------ + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 3 +-- + drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 4 +--- + 3 files changed, 3 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +index e93ccdc5faf4e..bbbacc7b6c463 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +@@ -357,17 +357,12 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach, + struct sg_table *sgt, + enum dma_data_direction dir) + { +- struct dma_buf *dma_buf = attach->dmabuf; +- struct drm_gem_object *obj = dma_buf->priv; +- struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); +- struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); +- + if (sgt->sgl->page_link) { + dma_unmap_sgtable(attach->dev, sgt, dir, 0); + sg_free_table(sgt); + kfree(sgt); + } else { +- amdgpu_vram_mgr_free_sgt(adev, attach->dev, dir, sgt); ++ amdgpu_vram_mgr_free_sgt(attach->dev, dir, sgt); + } + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +index a87951b2f06dd..bd873b1b760cf 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +@@ -113,8 +113,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, + struct device *dev, + enum dma_data_direction dir, + struct sg_table **sgt); +-void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev, +- struct device *dev, ++void amdgpu_vram_mgr_free_sgt(struct device *dev, + enum dma_data_direction dir, + struct sg_table *sgt); + uint64_t amdgpu_vram_mgr_usage(struct ttm_resource_manager *man); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +index 2c3a94e939bab..ad72db21b8d62 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +@@ -530,15 +530,13 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, + /** + * amdgpu_vram_mgr_alloc_sgt - allocate and fill a sg table + * +- * @adev: amdgpu device pointer + * @dev: device pointer + * @dir: data direction of resource to unmap + * @sgt: sg table to free + * + * Free a previously allocate sg table. + */ +-void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev, +- struct device *dev, ++void amdgpu_vram_mgr_free_sgt(struct device *dev, + enum dma_data_direction dir, + struct sg_table *sgt) + { +-- +2.39.5 + diff --git a/queue-5.10/iio-adc-ad7768-1-fix-conversion-result-sign.patch b/queue-5.10/iio-adc-ad7768-1-fix-conversion-result-sign.patch new file mode 100644 index 0000000000..541c4f1421 --- /dev/null +++ b/queue-5.10/iio-adc-ad7768-1-fix-conversion-result-sign.patch @@ -0,0 +1,55 @@ +From 5d51c142998785ea086034e7f5fabba2331aa344 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 18:00:29 -0300 +Subject: iio: adc: ad7768-1: Fix conversion result sign + +From: Sergiu Cuciurean + +[ Upstream commit 8236644f5ecb180e80ad92d691c22bc509b747bb ] + +The ad7768-1 ADC output code is two's complement, meaning that the voltage +conversion result is a signed value.. Since the value is a 24 bit one, +stored in a 32 bit variable, the sign should be extended in order to get +the correct representation. + +Also the channel description has been updated to signed representation, +to match the ADC specifications. + +Fixes: a5f8c7da3dbe ("iio: adc: Add AD7768-1 ADC basic support") +Reviewed-by: David Lechner +Reviewed-by: Marcelo Schmitt +Signed-off-by: Sergiu Cuciurean +Signed-off-by: Jonathan Santos +Cc: +Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7768-1.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index c409b498fc313..2445ebc551dd1 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -142,7 +142,7 @@ static const struct iio_chan_spec ad7768_channels[] = { + .channel = 0, + .scan_index = 0, + .scan_type = { +- .sign = 'u', ++ .sign = 's', + .realbits = 24, + .storagebits = 32, + .shift = 8, +@@ -373,7 +373,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev, + iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; +- *val = ret; ++ *val = sign_extend32(ret, chan->scan_type.realbits - 1); + + return IIO_VAL_INT; + +-- +2.39.5 + diff --git a/queue-5.10/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch b/queue-5.10/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch new file mode 100644 index 0000000000..50ef7c9f53 --- /dev/null +++ b/queue-5.10/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch @@ -0,0 +1,47 @@ +From 33e1e987e03b89ac7f1a1aa4a8bf84efe2d7527d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:16:12 +0000 +Subject: iio: adc: ad7768-1: Move setting of val a bit later to avoid + unnecessary return value check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jonathan Cameron + +[ Upstream commit 0af1c801a15225304a6328258efbf2bee245c654 ] + +The data used is all in local variables so there is no advantage +in setting *val = ret with the direct mode claim held. +Move it later to after error check. + +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign") +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7768-1.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index 4afa50e5c058a..c409b498fc313 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -369,12 +369,11 @@ static int ad7768_read_raw(struct iio_dev *indio_dev, + return ret; + + ret = ad7768_scan_direct(indio_dev); +- if (ret >= 0) +- *val = ret; + + iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; ++ *val = ret; + + return IIO_VAL_INT; + +-- +2.39.5 + diff --git a/queue-5.10/media-streamzap-fix-race-between-device-disconnectio.patch b/queue-5.10/media-streamzap-fix-race-between-device-disconnectio.patch new file mode 100644 index 0000000000..a30d1d9fa9 --- /dev/null +++ b/queue-5.10/media-streamzap-fix-race-between-device-disconnectio.patch @@ -0,0 +1,54 @@ +From d5b00259ac8d78bd8858d2e94ef40c63d7691cbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 13:51:30 +0300 +Subject: media: streamzap: fix race between device disconnection and urb + callback + +From: Murad Masimov + +[ Upstream commit f656cfbc7a293a039d6a0c7100e1c846845148c1 ] + +Syzkaller has reported a general protection fault at function +ir_raw_event_store_with_filter(). This crash is caused by a NULL pointer +dereference of dev->raw pointer, even though it is checked for NULL in +the same function, which means there is a race condition. It occurs due +to the incorrect order of actions in the streamzap_disconnect() function: +rc_unregister_device() is called before usb_kill_urb(). The dev->raw +pointer is freed and set to NULL in rc_unregister_device(), and only +after that usb_kill_urb() waits for in-progress requests to finish. + +If rc_unregister_device() is called while streamzap_callback() handler is +not finished, this can lead to accessing freed resources. Thus +rc_unregister_device() should be called after usb_kill_urb(). + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 8e9e60640067 ("V4L/DVB: staging/lirc: port lirc_streamzap to ir-core") +Cc: stable@vger.kernel.org +Reported-by: syzbot+34008406ee9a31b13c73@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=34008406ee9a31b13c73 +Signed-off-by: Murad Masimov +Signed-off-by: Sean Young +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/rc/streamzap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c +index cd994e27362eb..c0a48f991d9d2 100644 +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -433,8 +433,8 @@ static void streamzap_disconnect(struct usb_interface *interface) + if (!sz) + return; + +- rc_unregister_device(sz->rdev); + usb_kill_urb(sz->urb_in); ++ rc_unregister_device(sz->rdev); + usb_free_urb(sz->urb_in); + usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); + +-- +2.39.5 + diff --git a/queue-5.10/media-streamzap-less-chatter.patch b/queue-5.10/media-streamzap-less-chatter.patch new file mode 100644 index 0000000000..42649478d7 --- /dev/null +++ b/queue-5.10/media-streamzap-less-chatter.patch @@ -0,0 +1,82 @@ +From 6bc7009d9eadddd40c2c174b7e88d677d3a88733 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Dec 2021 22:38:20 +0100 +Subject: media: streamzap: less chatter + +From: Sean Young + +[ Upstream commit 35088717ad24140b6ab0ec00ef357709be607526 ] + +Remove superfluous messages which add no information. + +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + drivers/media/rc/streamzap.c | 20 +------------------- + 1 file changed, 1 insertion(+), 19 deletions(-) + +diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c +index b6391ad383143..e862a866b9b0f 100644 +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -26,7 +26,6 @@ + #include + #include + +-#define DRIVER_VERSION "1.61" + #define DRIVER_NAME "streamzap" + #define DRIVER_DESC "Streamzap Remote Control driver" + +@@ -281,10 +280,8 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) + int ret; + + rdev = rc_allocate_device(RC_DRIVER_IR_RAW); +- if (!rdev) { +- dev_err(dev, "remote dev allocation failed\n"); ++ if (!rdev) + goto out; +- } + + usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); + strlcat(sz->phys, "/input0", sizeof(sz->phys)); +@@ -324,7 +321,6 @@ static int streamzap_probe(struct usb_interface *intf, + struct usb_device *usbdev = interface_to_usbdev(intf); + struct usb_host_interface *iface_host; + struct streamzap_ir *sz = NULL; +- char buf[63], name[128] = ""; + int retval = -ENOMEM; + int pipe, maxp; + +@@ -383,17 +379,6 @@ static int streamzap_probe(struct usb_interface *intf, + sz->dev = &intf->dev; + sz->buf_in_len = maxp; + +- if (usbdev->descriptor.iManufacturer +- && usb_string(usbdev, usbdev->descriptor.iManufacturer, +- buf, sizeof(buf)) > 0) +- strscpy(name, buf, sizeof(name)); +- +- if (usbdev->descriptor.iProduct +- && usb_string(usbdev, usbdev->descriptor.iProduct, +- buf, sizeof(buf)) > 0) +- snprintf(name + strlen(name), sizeof(name) - strlen(name), +- " %s", buf); +- + sz->rdev = streamzap_init_rc_dev(sz); + if (!sz->rdev) + goto rc_dev_fail; +@@ -424,9 +409,6 @@ static int streamzap_probe(struct usb_interface *intf, + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) + dev_err(sz->dev, "urb submit failed\n"); + +- dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, +- usbdev->bus->busnum, usbdev->devnum); +- + return 0; + + rc_dev_fail: +-- +2.39.5 + diff --git a/queue-5.10/media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch b/queue-5.10/media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch new file mode 100644 index 0000000000..066b3dfb77 --- /dev/null +++ b/queue-5.10/media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch @@ -0,0 +1,50 @@ +From b3896ae1ac76c9b0870e211a28f2cdea2b7a86d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Dec 2021 18:10:36 +0100 +Subject: media: streamzap: no need for usb pid/vid in device name + +From: Sean Young + +[ Upstream commit 7a25e6849ad73de5aa01d62da43071bc02b8530c ] + +The usb pid/vid can be found elsewhere, the idVendor/idProduct usb sysfs +files for example. + +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + drivers/media/rc/streamzap.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c +index cd4bb605a7614..b6391ad383143 100644 +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -88,7 +88,6 @@ struct streamzap_ir { + ktime_t signal_start; + bool timeout_enabled; + +- char name[128]; + char phys[64]; + }; + +@@ -287,13 +286,10 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) + goto out; + } + +- snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared Receiver (%04x:%04x)", +- le16_to_cpu(sz->usbdev->descriptor.idVendor), +- le16_to_cpu(sz->usbdev->descriptor.idProduct)); + usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); + strlcat(sz->phys, "/input0", sizeof(sz->phys)); + +- rdev->device_name = sz->name; ++ rdev->device_name = "Streamzap PC Remote Infrared Receiver"; + rdev->input_phys = sz->phys; + usb_to_input_id(sz->usbdev, &rdev->input_id); + rdev->dev.parent = dev; +-- +2.39.5 + diff --git a/queue-5.10/media-streamzap-remove-unnecessary-ir_raw_event_rese.patch b/queue-5.10/media-streamzap-remove-unnecessary-ir_raw_event_rese.patch new file mode 100644 index 0000000000..047ae58a98 --- /dev/null +++ b/queue-5.10/media-streamzap-remove-unnecessary-ir_raw_event_rese.patch @@ -0,0 +1,38 @@ +From 898eeec1c636914231d739ee44e005aae3bc9995 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Dec 2021 18:06:30 +0100 +Subject: media: streamzap: remove unnecessary ir_raw_event_reset and handle + +From: Sean Young + +[ Upstream commit 4bed9306050497f49cbe77b842f0d812f4f27593 ] + +There is no reason to have a reset after an IR timeout. +Calling ir_raw_event_handle() twice for the same interrupt has no +affect. + +Fixes: 56b0ec30c4bc ("[media] rc/streamzap: fix reporting response times") +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + drivers/media/rc/streamzap.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c +index b6bd3cbec7c7c..cd4bb605a7614 100644 +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -215,8 +215,6 @@ static void sz_process_ir_data(struct streamzap_ir *sz, int len) + sz->idle = true; + if (sz->timeout_enabled) + sz_push(sz, rawir); +- ir_raw_event_handle(sz->rdev); +- ir_raw_event_reset(sz->rdev); + } else { + sz_push_full_space(sz, sz->buf_in[i]); + } +-- +2.39.5 + diff --git a/queue-5.10/media-streamzap-remove-unused-struct-members.patch b/queue-5.10/media-streamzap-remove-unused-struct-members.patch new file mode 100644 index 0000000000..18ac4e9802 --- /dev/null +++ b/queue-5.10/media-streamzap-remove-unused-struct-members.patch @@ -0,0 +1,160 @@ +From 40924984f233b4448773a81cb80848f9a4163eac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Dec 2021 11:59:41 +0100 +Subject: media: streamzap: remove unused struct members + +From: Sean Young + +[ Upstream commit 4df69e46c352df9bdbe859824da33428a3ce8a1d ] + +These struct members do not serve any purpose. + +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f656cfbc7a29 ("media: streamzap: fix race between device disconnection and urb callback") +Signed-off-by: Sasha Levin +--- + drivers/media/rc/streamzap.c | 37 ++++++++++++++---------------------- + 1 file changed, 14 insertions(+), 23 deletions(-) + +diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c +index e862a866b9b0f..cd994e27362eb 100644 +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -66,9 +66,6 @@ struct streamzap_ir { + struct device *dev; + + /* usb */ +- struct usb_device *usbdev; +- struct usb_interface *interface; +- struct usb_endpoint_descriptor *endpoint; + struct urb *urb_in; + + /* buffer & dma */ +@@ -85,7 +82,6 @@ struct streamzap_ir { + /* start time of signal; necessary for gap tracking */ + ktime_t signal_last; + ktime_t signal_start; +- bool timeout_enabled; + + char phys[64]; + }; +@@ -211,8 +207,7 @@ static void sz_process_ir_data(struct streamzap_ir *sz, int len) + .duration = sz->rdev->timeout + }; + sz->idle = true; +- if (sz->timeout_enabled) +- sz_push(sz, rawir); ++ sz_push(sz, rawir); + } else { + sz_push_full_space(sz, sz->buf_in[i]); + } +@@ -273,7 +268,8 @@ static void streamzap_callback(struct urb *urb) + return; + } + +-static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) ++static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz, ++ struct usb_device *usbdev) + { + struct rc_dev *rdev; + struct device *dev = sz->dev; +@@ -283,12 +279,12 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) + if (!rdev) + goto out; + +- usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); ++ usb_make_path(usbdev, sz->phys, sizeof(sz->phys)); + strlcat(sz->phys, "/input0", sizeof(sz->phys)); + + rdev->device_name = "Streamzap PC Remote Infrared Receiver"; + rdev->input_phys = sz->phys; +- usb_to_input_id(sz->usbdev, &rdev->input_id); ++ usb_to_input_id(usbdev, &rdev->input_id); + rdev->dev.parent = dev; + rdev->priv = sz; + rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; +@@ -319,6 +315,7 @@ static int streamzap_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { + struct usb_device *usbdev = interface_to_usbdev(intf); ++ struct usb_endpoint_descriptor *endpoint; + struct usb_host_interface *iface_host; + struct streamzap_ir *sz = NULL; + int retval = -ENOMEM; +@@ -329,9 +326,6 @@ static int streamzap_probe(struct usb_interface *intf, + if (!sz) + return -ENOMEM; + +- sz->usbdev = usbdev; +- sz->interface = intf; +- + /* Check to ensure endpoint information matches requirements */ + iface_host = intf->cur_altsetting; + +@@ -342,22 +336,22 @@ static int streamzap_probe(struct usb_interface *intf, + goto free_sz; + } + +- sz->endpoint = &(iface_host->endpoint[0].desc); +- if (!usb_endpoint_dir_in(sz->endpoint)) { ++ endpoint = &iface_host->endpoint[0].desc; ++ if (!usb_endpoint_dir_in(endpoint)) { + dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n", +- __func__, sz->endpoint->bEndpointAddress); ++ __func__, endpoint->bEndpointAddress); + retval = -ENODEV; + goto free_sz; + } + +- if (!usb_endpoint_xfer_int(sz->endpoint)) { ++ if (!usb_endpoint_xfer_int(endpoint)) { + dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n", +- __func__, sz->endpoint->bmAttributes); ++ __func__, endpoint->bmAttributes); + retval = -ENODEV; + goto free_sz; + } + +- pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress); ++ pipe = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe)); + + if (maxp == 0) { +@@ -379,14 +373,13 @@ static int streamzap_probe(struct usb_interface *intf, + sz->dev = &intf->dev; + sz->buf_in_len = maxp; + +- sz->rdev = streamzap_init_rc_dev(sz); ++ sz->rdev = streamzap_init_rc_dev(sz, usbdev); + if (!sz->rdev) + goto rc_dev_fail; + + sz->idle = true; + sz->decoder_state = PulseSpace; + /* FIXME: don't yet have a way to set this */ +- sz->timeout_enabled = true; + sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION; + #if 0 + /* not yet supported, depends on patches from maxim */ +@@ -399,8 +392,7 @@ static int streamzap_probe(struct usb_interface *intf, + + /* Complete final initialisations */ + usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, +- maxp, (usb_complete_t)streamzap_callback, +- sz, sz->endpoint->bInterval); ++ maxp, streamzap_callback, sz, endpoint->bInterval); + sz->urb_in->transfer_dma = sz->dma_in; + sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + +@@ -441,7 +433,6 @@ static void streamzap_disconnect(struct usb_interface *interface) + if (!sz) + return; + +- sz->usbdev = NULL; + rc_unregister_device(sz->rdev); + usb_kill_urb(sz->urb_in); + usb_free_urb(sz->urb_in); +-- +2.39.5 + diff --git a/queue-5.10/media-venus-create-hfi-platform-and-move-vpp-vsp-the.patch b/queue-5.10/media-venus-create-hfi-platform-and-move-vpp-vsp-the.patch new file mode 100644 index 0000000000..56fb855b94 --- /dev/null +++ b/queue-5.10/media-venus-create-hfi-platform-and-move-vpp-vsp-the.patch @@ -0,0 +1,488 @@ +From 4438dabf3e3dfa5894370f1bd66b855bc1d7d948 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Aug 2020 09:36:06 +0200 +Subject: media: venus: Create hfi platform and move vpp/vsp there + +From: Stanimir Varbanov + +[ Upstream commit aa6033892b1d8ea956ce0358867806e171a620d1 ] + +Introduce a new hfi platform to cover differences between hfi +versions. As a start move vpp/vsp freq data in that hfi +platform, more platform data will come later. + +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/Makefile | 3 +- + drivers/media/platform/qcom/venus/core.c | 17 ------ + drivers/media/platform/qcom/venus/core.h | 12 +--- + drivers/media/platform/qcom/venus/helpers.c | 54 ++++++++--------- + drivers/media/platform/qcom/venus/helpers.h | 2 +- + .../media/platform/qcom/venus/hfi_platform.c | 49 +++++++++++++++ + .../media/platform/qcom/venus/hfi_platform.h | 34 +++++++++++ + .../platform/qcom/venus/hfi_platform_v4.c | 60 +++++++++++++++++++ + .../media/platform/qcom/venus/pm_helpers.c | 9 +-- + drivers/media/platform/qcom/venus/vdec.c | 6 +- + drivers/media/platform/qcom/venus/venc.c | 6 +- + 11 files changed, 179 insertions(+), 73 deletions(-) + create mode 100644 drivers/media/platform/qcom/venus/hfi_platform.c + create mode 100644 drivers/media/platform/qcom/venus/hfi_platform.h + create mode 100644 drivers/media/platform/qcom/venus/hfi_platform_v4.c + +diff --git a/drivers/media/platform/qcom/venus/Makefile b/drivers/media/platform/qcom/venus/Makefile +index dfc6368657091..09ebf46716925 100644 +--- a/drivers/media/platform/qcom/venus/Makefile ++++ b/drivers/media/platform/qcom/venus/Makefile +@@ -3,7 +3,8 @@ + + venus-core-objs += core.o helpers.o firmware.o \ + hfi_venus.o hfi_msgs.o hfi_cmds.o hfi.o \ +- hfi_parser.o pm_helpers.o dbgfs.o ++ hfi_parser.o pm_helpers.o dbgfs.o \ ++ hfi_platform.o hfi_platform_v4.o \ + + venus-dec-objs += vdec.o vdec_ctrls.o + venus-enc-objs += venc.o venc_ctrls.o +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index 1859dd3f7f546..987b1d010c047 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -529,17 +529,6 @@ static const struct freq_tbl sdm845_freq_table[] = { + { 244800, 100000000 }, /* 1920x1080@30 */ + }; + +-static const struct codec_freq_data sdm845_codec_freq_data[] = { +- { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 }, +- { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 }, +- { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 }, +- { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10 }, +- { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10 }, +- { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10 }, +- { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10 }, +- { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10 }, +-}; +- + static const struct bw_tbl sdm845_bw_table_enc[] = { + { 1944000, 1612000, 0, 2416000, 0 }, /* 3840x2160@60 */ + { 972000, 951000, 0, 1434000, 0 }, /* 3840x2160@30 */ +@@ -561,8 +550,6 @@ static const struct venus_resources sdm845_res = { + .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), + .bw_tbl_dec = sdm845_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), +- .codec_freq_data = sdm845_codec_freq_data, +- .codec_freq_data_size = ARRAY_SIZE(sdm845_codec_freq_data), + .clks = {"core", "iface", "bus" }, + .clks_num = 3, + .vcodec0_clks = { "core", "bus" }, +@@ -584,8 +571,6 @@ static const struct venus_resources sdm845_res_v2 = { + .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), + .bw_tbl_dec = sdm845_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), +- .codec_freq_data = sdm845_codec_freq_data, +- .codec_freq_data_size = ARRAY_SIZE(sdm845_codec_freq_data), + .clks = {"core", "iface", "bus" }, + .clks_num = 3, + .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, +@@ -635,8 +620,6 @@ static const struct venus_resources sc7180_res = { + .bw_tbl_enc_size = ARRAY_SIZE(sc7180_bw_table_enc), + .bw_tbl_dec = sc7180_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sc7180_bw_table_dec), +- .codec_freq_data = sdm845_codec_freq_data, +- .codec_freq_data_size = ARRAY_SIZE(sdm845_codec_freq_data), + .clks = {"core", "iface", "bus" }, + .clks_num = 3, + .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, +diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h +index e56d7b8142152..53d3202460ae9 100644 +--- a/drivers/media/platform/qcom/venus/core.h ++++ b/drivers/media/platform/qcom/venus/core.h +@@ -36,13 +36,6 @@ struct reg_val { + u32 value; + }; + +-struct codec_freq_data { +- u32 pixfmt; +- u32 session_type; +- unsigned long vpp_freq; +- unsigned long vsp_freq; +-}; +- + struct bw_tbl { + u32 mbs_per_sec; + u32 avg; +@@ -61,8 +54,6 @@ struct venus_resources { + unsigned int bw_tbl_dec_size; + const struct reg_val *reg_tbl; + unsigned int reg_tbl_size; +- const struct codec_freq_data *codec_freq_data; +- unsigned int codec_freq_data_size; + const char * const clks[VIDC_CLKS_NUM_MAX]; + unsigned int clks_num; + const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX]; +@@ -280,7 +271,8 @@ struct venus_buffer { + struct clock_data { + u32 core_id; + unsigned long freq; +- const struct codec_freq_data *codec_freq_data; ++ unsigned long vpp_freq; ++ unsigned long vsp_freq; + }; + + #define to_venus_buffer(ptr) container_of(ptr, struct venus_buffer, vb) +diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c +index 5fdce5f07364e..9ad8abdc4d4f2 100644 +--- a/drivers/media/platform/qcom/venus/helpers.c ++++ b/drivers/media/platform/qcom/venus/helpers.c +@@ -15,6 +15,7 @@ + #include "helpers.h" + #include "hfi_helper.h" + #include "pm_helpers.h" ++#include "hfi_platform.h" + + struct intbuf { + struct list_head list; +@@ -1040,36 +1041,6 @@ int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode) + } + EXPORT_SYMBOL_GPL(venus_helper_set_work_mode); + +-int venus_helper_init_codec_freq_data(struct venus_inst *inst) +-{ +- const struct codec_freq_data *data; +- unsigned int i, data_size; +- u32 pixfmt; +- int ret = 0; +- +- if (!IS_V4(inst->core)) +- return 0; +- +- data = inst->core->res->codec_freq_data; +- data_size = inst->core->res->codec_freq_data_size; +- pixfmt = inst->session_type == VIDC_SESSION_TYPE_DEC ? +- inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt; +- +- for (i = 0; i < data_size; i++) { +- if (data[i].pixfmt == pixfmt && +- data[i].session_type == inst->session_type) { +- inst->clk_data.codec_freq_data = &data[i]; +- break; +- } +- } +- +- if (!inst->clk_data.codec_freq_data) +- ret = -EINVAL; +- +- return ret; +-} +-EXPORT_SYMBOL_GPL(venus_helper_init_codec_freq_data); +- + int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, + unsigned int output_bufs, + unsigned int output2_bufs) +@@ -1535,6 +1506,29 @@ void venus_helper_m2m_job_abort(void *priv) + } + EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort); + ++int venus_helper_session_init(struct venus_inst *inst) ++{ ++ enum hfi_version version = inst->core->res->hfi_version; ++ u32 session_type = inst->session_type; ++ u32 codec; ++ int ret; ++ ++ codec = inst->session_type == VIDC_SESSION_TYPE_DEC ? ++ inst->fmt_out->pixfmt : inst->fmt_cap->pixfmt; ++ ++ ret = hfi_session_init(inst, codec); ++ if (ret) ++ return ret; ++ ++ inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec, ++ session_type); ++ inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec, ++ session_type); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(venus_helper_session_init); ++ + void venus_helper_init_instance(struct venus_inst *inst) + { + if (inst->session_type == VIDC_SESSION_TYPE_DEC) { +diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h +index a4a0562bc83f5..5407979bf234b 100644 +--- a/drivers/media/platform/qcom/venus/helpers.h ++++ b/drivers/media/platform/qcom/venus/helpers.h +@@ -33,7 +33,6 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, + unsigned int width, unsigned int height, + u32 buftype); + int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode); +-int venus_helper_init_codec_freq_data(struct venus_inst *inst); + int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, + unsigned int output_bufs, + unsigned int output2_bufs); +@@ -48,6 +47,7 @@ unsigned int venus_helper_get_opb_size(struct venus_inst *inst); + void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); + void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); + void venus_helper_init_instance(struct venus_inst *inst); ++int venus_helper_session_init(struct venus_inst *inst); + int venus_helper_get_out_fmts(struct venus_inst *inst, u32 fmt, u32 *out_fmt, + u32 *out2_fmt, bool ubwc); + int venus_helper_alloc_dpb_bufs(struct venus_inst *inst); +diff --git a/drivers/media/platform/qcom/venus/hfi_platform.c b/drivers/media/platform/qcom/venus/hfi_platform.c +new file mode 100644 +index 0000000000000..65559cae21aaa +--- /dev/null ++++ b/drivers/media/platform/qcom/venus/hfi_platform.c +@@ -0,0 +1,49 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2020, The Linux Foundation. All rights reserved. ++ */ ++#include "hfi_platform.h" ++ ++const struct hfi_platform *hfi_platform_get(enum hfi_version version) ++{ ++ switch (version) { ++ case HFI_VERSION_4XX: ++ return &hfi_plat_v4; ++ default: ++ break; ++ } ++ ++ return NULL; ++} ++ ++unsigned long ++hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session_type) ++{ ++ const struct hfi_platform *plat; ++ unsigned long freq = 0; ++ ++ plat = hfi_platform_get(version); ++ if (!plat) ++ return 0; ++ ++ if (plat->codec_vpp_freq) ++ freq = plat->codec_vpp_freq(session_type, codec); ++ ++ return freq; ++} ++ ++unsigned long ++hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session_type) ++{ ++ const struct hfi_platform *plat; ++ unsigned long freq = 0; ++ ++ plat = hfi_platform_get(version); ++ if (!plat) ++ return 0; ++ ++ if (plat->codec_vpp_freq) ++ freq = plat->codec_vsp_freq(session_type, codec); ++ ++ return freq; ++} +diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h +new file mode 100644 +index 0000000000000..8b07ecbb4c825 +--- /dev/null ++++ b/drivers/media/platform/qcom/venus/hfi_platform.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2020, The Linux Foundation. All rights reserved. ++ */ ++ ++#ifndef __HFI_PLATFORM_H__ ++#define __HFI_PLATFORM_H__ ++ ++#include ++#include ++ ++#include "hfi.h" ++#include "hfi_helper.h" ++ ++struct hfi_platform_codec_freq_data { ++ u32 pixfmt; ++ u32 session_type; ++ unsigned long vpp_freq; ++ unsigned long vsp_freq; ++}; ++ ++struct hfi_platform { ++ unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec); ++ unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec); ++}; ++ ++extern const struct hfi_platform hfi_plat_v4; ++ ++const struct hfi_platform *hfi_platform_get(enum hfi_version version); ++unsigned long hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, ++ u32 session_type); ++unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, ++ u32 session_type); ++#endif +diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v4.c b/drivers/media/platform/qcom/venus/hfi_platform_v4.c +new file mode 100644 +index 0000000000000..4fc2fd04ca9d1 +--- /dev/null ++++ b/drivers/media/platform/qcom/venus/hfi_platform_v4.c +@@ -0,0 +1,60 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2020, The Linux Foundation. All rights reserved. ++ */ ++#include "hfi_platform.h" ++ ++static const struct hfi_platform_codec_freq_data codec_freq_data[] = { ++ { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 }, ++ { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 }, ++ { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 }, ++ { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10 }, ++ { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10 }, ++ { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10 }, ++ { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10 }, ++ { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10 }, ++}; ++ ++static const struct hfi_platform_codec_freq_data * ++get_codec_freq_data(u32 session_type, u32 pixfmt) ++{ ++ const struct hfi_platform_codec_freq_data *data = codec_freq_data; ++ unsigned int i, data_size = ARRAY_SIZE(codec_freq_data); ++ const struct hfi_platform_codec_freq_data *found = NULL; ++ ++ for (i = 0; i < data_size; i++) { ++ if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) { ++ found = &data[i]; ++ break; ++ } ++ } ++ ++ return found; ++} ++ ++static unsigned long codec_vpp_freq(u32 session_type, u32 codec) ++{ ++ const struct hfi_platform_codec_freq_data *data; ++ ++ data = get_codec_freq_data(session_type, codec); ++ if (data) ++ return data->vpp_freq; ++ ++ return 0; ++} ++ ++static unsigned long codec_vsp_freq(u32 session_type, u32 codec) ++{ ++ const struct hfi_platform_codec_freq_data *data; ++ ++ data = get_codec_freq_data(session_type, codec); ++ if (data) ++ return data->vsp_freq; ++ ++ return 0; ++} ++ ++const struct hfi_platform hfi_plat_v4 = { ++ .codec_vpp_freq = codec_vpp_freq, ++ .codec_vsp_freq = codec_vsp_freq, ++}; +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index 12c5811fefdf9..7c3541c35ab69 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -18,6 +18,7 @@ + #include "hfi_parser.h" + #include "hfi_venus_io.h" + #include "pm_helpers.h" ++#include "hfi_platform.h" + + static bool legacy_binding; + +@@ -506,7 +507,7 @@ min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load) + if (inst_pos->state != INST_START) + continue; + +- vpp_freq = inst_pos->clk_data.codec_freq_data->vpp_freq; ++ vpp_freq = inst_pos->clk_data.vpp_freq; + coreid = inst_pos->clk_data.core_id; + + mbs_per_sec = load_per_instance(inst_pos); +@@ -555,7 +556,7 @@ static int decide_core(struct venus_inst *inst) + return 0; + + inst_load = load_per_instance(inst); +- inst_load *= inst->clk_data.codec_freq_data->vpp_freq; ++ inst_load *= inst->clk_data.vpp_freq; + max_freq = core->res->freq_tbl[0].freq; + + min_loaded_core(inst, &min_coreid, &min_load); +@@ -940,10 +941,10 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst, + if (inst->state != INST_START) + return 0; + +- vpp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vpp_freq; ++ vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq; + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; +- vsp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vsp_freq; ++ vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq; + + /* 10 / 7 is overhead factor */ + if (inst->session_type == VIDC_SESSION_TYPE_ENC) +diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c +index 6e9b62645e917..68390143d37df 100644 +--- a/drivers/media/platform/qcom/venus/vdec.c ++++ b/drivers/media/platform/qcom/venus/vdec.c +@@ -767,7 +767,7 @@ static int vdec_session_init(struct venus_inst *inst) + { + int ret; + +- ret = hfi_session_init(inst, inst->fmt_out->pixfmt); ++ ret = venus_helper_session_init(inst); + if (ret == -EALREADY) + return 0; + else if (ret) +@@ -778,10 +778,6 @@ static int vdec_session_init(struct venus_inst *inst) + if (ret) + goto deinit; + +- ret = venus_helper_init_codec_freq_data(inst); +- if (ret) +- goto deinit; +- + return 0; + deinit: + hfi_session_deinit(inst); +diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c +index 9f1b02e31b98c..bc62cb02458c9 100644 +--- a/drivers/media/platform/qcom/venus/venc.c ++++ b/drivers/media/platform/qcom/venus/venc.c +@@ -726,7 +726,7 @@ static int venc_init_session(struct venus_inst *inst) + { + int ret; + +- ret = hfi_session_init(inst, inst->fmt_cap->pixfmt); ++ ret = venus_helper_session_init(inst); + if (ret == -EALREADY) + return 0; + else if (ret) +@@ -747,10 +747,6 @@ static int venc_init_session(struct venus_inst *inst) + if (ret) + goto deinit; + +- ret = venus_helper_init_codec_freq_data(inst); +- if (ret) +- goto deinit; +- + ret = venc_set_properties(inst); + if (ret) + goto deinit; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-get-codecs-and-capabilities-from-hfi-pla.patch b/queue-5.10/media-venus-get-codecs-and-capabilities-from-hfi-pla.patch new file mode 100644 index 0000000000..f5569bb8d3 --- /dev/null +++ b/queue-5.10/media-venus-get-codecs-and-capabilities-from-hfi-pla.patch @@ -0,0 +1,77 @@ +From b72aa94cdf7b6f5002476e6cb28fb452466fd926 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Aug 2020 14:39:13 +0200 +Subject: media: venus: Get codecs and capabilities from hfi platform + +From: Stanimir Varbanov + +[ Upstream commit e29929266be1ac0e40121f56b5c13b52c281db06 ] + +Wire up hfi platform codec and capabilities instead of +getting them from firmware. + +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + .../media/platform/qcom/venus/hfi_parser.c | 38 +++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c +index be9a58ef04d86..7a2915befdb83 100644 +--- a/drivers/media/platform/qcom/venus/hfi_parser.c ++++ b/drivers/media/platform/qcom/venus/hfi_parser.c +@@ -245,11 +245,49 @@ static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain) + } + } + ++static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) ++{ ++ const struct hfi_platform *plat; ++ const struct hfi_plat_caps *caps = NULL; ++ u32 enc_codecs, dec_codecs, count; ++ unsigned int entries; ++ ++ if (inst) ++ return 0; ++ ++ plat = hfi_platform_get(core->res->hfi_version); ++ if (!plat) ++ return -EINVAL; ++ ++ if (plat->codecs) ++ plat->codecs(&enc_codecs, &dec_codecs, &count); ++ ++ if (plat->capabilities) ++ caps = plat->capabilities(&entries); ++ ++ if (!caps || !entries || !count) ++ return -EINVAL; ++ ++ core->enc_codecs = enc_codecs; ++ core->dec_codecs = dec_codecs; ++ core->codecs_count = count; ++ core->max_sessions_supported = MAX_SESSIONS; ++ memset(core->caps, 0, sizeof(*caps) * MAX_CODEC_NUM); ++ memcpy(core->caps, caps, sizeof(*caps) * entries); ++ ++ return 0; ++} ++ + u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, + u32 size) + { + unsigned int words_count = size >> 2; + u32 *word = buf, *data, codecs = 0, domain = 0; ++ int ret; ++ ++ ret = hfi_platform_parser(core, inst); ++ if (!ret) ++ return HFI_ERR_NONE; + + if (size % 4) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-hfi-correct-session-init-return-error.patch b/queue-5.10/media-venus-hfi-correct-session-init-return-error.patch new file mode 100644 index 0000000000..3f60d05a5b --- /dev/null +++ b/queue-5.10/media-venus-hfi-correct-session-init-return-error.patch @@ -0,0 +1,68 @@ +From 9ed7bb77a925d0cf613d008ab9a8c0dbde56dc67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Dec 2020 11:01:39 +0100 +Subject: media: venus: hfi: Correct session init return error + +From: Stanimir Varbanov + +[ Upstream commit e922a33e0228fa314ffc4f70b3b9ffbc4aad1bbe ] + +The hfi_session_init can be called many times and it returns +EINVAL when the session was already initialized. This error code +(EINVAL) is confusing for the callers. Change hfi_session_init to +return EALREADY error code when the session has been already +initialized. + +Tested-by: Fritz Koenig +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/hfi.c | 2 +- + drivers/media/platform/qcom/venus/vdec.c | 2 +- + drivers/media/platform/qcom/venus/venc.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c +index 17da555905e98..5fd53227c2c0b 100644 +--- a/drivers/media/platform/qcom/venus/hfi.c ++++ b/drivers/media/platform/qcom/venus/hfi.c +@@ -212,7 +212,7 @@ int hfi_session_init(struct venus_inst *inst, u32 pixfmt) + int ret; + + if (inst->state != INST_UNINIT) +- return -EINVAL; ++ return -EALREADY; + + inst->hfi_codec = to_codec_type(pixfmt); + reinit_completion(&inst->done); +diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c +index d91030a134c0e..6e9b62645e917 100644 +--- a/drivers/media/platform/qcom/venus/vdec.c ++++ b/drivers/media/platform/qcom/venus/vdec.c +@@ -768,7 +768,7 @@ static int vdec_session_init(struct venus_inst *inst) + int ret; + + ret = hfi_session_init(inst, inst->fmt_out->pixfmt); +- if (ret == -EINVAL) ++ if (ret == -EALREADY) + return 0; + else if (ret) + return ret; +diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c +index 18d20b4ca2cfd..9f1b02e31b98c 100644 +--- a/drivers/media/platform/qcom/venus/venc.c ++++ b/drivers/media/platform/qcom/venus/venc.c +@@ -727,7 +727,7 @@ static int venc_init_session(struct venus_inst *inst) + int ret; + + ret = hfi_session_init(inst, inst->fmt_cap->pixfmt); +- if (ret == -EINVAL) ++ if (ret == -EALREADY) + return 0; + else if (ret) + return ret; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-hfi_parser-refactor-hfi-packet-parsing-l.patch b/queue-5.10/media-venus-hfi_parser-refactor-hfi-packet-parsing-l.patch new file mode 100644 index 0000000000..758effcb47 --- /dev/null +++ b/queue-5.10/media-venus-hfi_parser-refactor-hfi-packet-parsing-l.patch @@ -0,0 +1,275 @@ +From c3e8b918fb5a42bb217d552a8e3bbcbf9bdda9e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 22:50:09 +0530 +Subject: media: venus: hfi_parser: refactor hfi packet parsing logic + +From: Vikash Garodia + +[ Upstream commit 9edaaa8e3e15aab1ca413ab50556de1975bcb329 ] + +words_count denotes the number of words in total payload, while data +points to payload of various property within it. When words_count +reaches last word, data can access memory beyond the total payload. This +can lead to OOB access. With this patch, the utility api for handling +individual properties now returns the size of data consumed. Accordingly +remaining bytes are calculated before parsing the payload, thereby +eliminates the OOB access possibilities. + +Cc: stable@vger.kernel.org +Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") +Signed-off-by: Vikash Garodia +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + .../media/platform/qcom/venus/hfi_parser.c | 98 ++++++++++++++----- + 1 file changed, 72 insertions(+), 26 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c +index 7a2915befdb83..c6be1564c876d 100644 +--- a/drivers/media/platform/qcom/venus/hfi_parser.c ++++ b/drivers/media/platform/qcom/venus/hfi_parser.c +@@ -64,7 +64,7 @@ fill_buf_mode(struct hfi_plat_caps *cap, const void *data, unsigned int num) + cap->cap_bufs_mode_dynamic = true; + } + +-static void ++static int + parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) + { + struct hfi_buffer_alloc_mode_supported *mode = data; +@@ -72,7 +72,7 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) + u32 *type; + + if (num_entries > MAX_ALLOC_MODE_ENTRIES) +- return; ++ return -EINVAL; + + type = mode->data; + +@@ -84,6 +84,8 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) + + type++; + } ++ ++ return sizeof(*mode); + } + + static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, +@@ -98,7 +100,7 @@ static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, + cap->num_pl += num; + } + +-static void ++static int + parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) + { + struct hfi_profile_level_supported *pl = data; +@@ -106,12 +108,14 @@ parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) + struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {}; + + if (pl->profile_count > HFI_MAX_PROFILE_COUNT) +- return; ++ return -EINVAL; + + memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel)); + + for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, + fill_profile_level, pl_arr, pl->profile_count); ++ ++ return pl->profile_count * sizeof(*proflevel) + sizeof(u32); + } + + static void +@@ -126,7 +130,7 @@ fill_caps(struct hfi_plat_caps *cap, const void *data, unsigned int num) + cap->num_caps += num; + } + +-static void ++static int + parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) + { + struct hfi_capabilities *caps = data; +@@ -135,12 +139,14 @@ parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) + struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {}; + + if (num_caps > MAX_CAP_ENTRIES) +- return; ++ return -EINVAL; + + memcpy(caps_arr, cap, num_caps * sizeof(*cap)); + + for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, + fill_caps, caps_arr, num_caps); ++ ++ return sizeof(*caps); + } + + static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, +@@ -155,7 +161,7 @@ static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, + cap->num_fmts += num_fmts; + } + +-static void ++static int + parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) + { + struct hfi_uncompressed_format_supported *fmt = data; +@@ -164,7 +170,8 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) + struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {}; + u32 entries = fmt->format_entries; + unsigned int i = 0; +- u32 num_planes; ++ u32 num_planes = 0; ++ u32 size; + + while (entries) { + num_planes = pinfo->num_planes; +@@ -174,7 +181,7 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) + i++; + + if (i >= MAX_FMT_ENTRIES) +- return; ++ return -EINVAL; + + if (pinfo->num_planes > MAX_PLANES) + break; +@@ -186,9 +193,13 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) + + for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, + fill_raw_fmts, rawfmts, i); ++ size = fmt->format_entries * (sizeof(*constr) * num_planes + 2 * sizeof(u32)) ++ + 2 * sizeof(u32); ++ ++ return size; + } + +-static void parse_codecs(struct venus_core *core, void *data) ++static int parse_codecs(struct venus_core *core, void *data) + { + struct hfi_codec_supported *codecs = data; + +@@ -200,21 +211,27 @@ static void parse_codecs(struct venus_core *core, void *data) + core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK; + core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC; + } ++ ++ return sizeof(*codecs); + } + +-static void parse_max_sessions(struct venus_core *core, const void *data) ++static int parse_max_sessions(struct venus_core *core, const void *data) + { + const struct hfi_max_sessions_supported *sessions = data; + + core->max_sessions_supported = sessions->max_sessions; ++ ++ return sizeof(*sessions); + } + +-static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data) ++static int parse_codecs_mask(u32 *codecs, u32 *domain, void *data) + { + struct hfi_codec_mask_supported *mask = data; + + *codecs = mask->codecs; + *domain = mask->video_domains; ++ ++ return sizeof(*mask); + } + + static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain) +@@ -281,8 +298,9 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) + u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, + u32 size) + { +- unsigned int words_count = size >> 2; +- u32 *word = buf, *data, codecs = 0, domain = 0; ++ u32 *words = buf, *payload, codecs = 0, domain = 0; ++ u32 *frame_size = buf + size; ++ u32 rem_bytes = size; + int ret; + + ret = hfi_platform_parser(core, inst); +@@ -299,38 +317,66 @@ u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, + memset(core->caps, 0, sizeof(core->caps)); + } + +- while (words_count) { +- data = word + 1; ++ while (words < frame_size) { ++ payload = words + 1; + +- switch (*word) { ++ switch (*words) { + case HFI_PROPERTY_PARAM_CODEC_SUPPORTED: +- parse_codecs(core, data); ++ if (rem_bytes <= sizeof(struct hfi_codec_supported)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_codecs(core, payload); ++ if (ret < 0) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ + init_codecs(core); + break; + case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED: +- parse_max_sessions(core, data); ++ if (rem_bytes <= sizeof(struct hfi_max_sessions_supported)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_max_sessions(core, payload); + break; + case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED: +- parse_codecs_mask(&codecs, &domain, data); ++ if (rem_bytes <= sizeof(struct hfi_codec_mask_supported)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_codecs_mask(&codecs, &domain, payload); + break; + case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: +- parse_raw_formats(core, codecs, domain, data); ++ if (rem_bytes <= sizeof(struct hfi_uncompressed_format_supported)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_raw_formats(core, codecs, domain, payload); + break; + case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: +- parse_caps(core, codecs, domain, data); ++ if (rem_bytes <= sizeof(struct hfi_capabilities)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_caps(core, codecs, domain, payload); + break; + case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: +- parse_profile_level(core, codecs, domain, data); ++ if (rem_bytes <= sizeof(struct hfi_profile_level_supported)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_profile_level(core, codecs, domain, payload); + break; + case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: +- parse_alloc_mode(core, codecs, domain, data); ++ if (rem_bytes <= sizeof(struct hfi_buffer_alloc_mode_supported)) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ ret = parse_alloc_mode(core, codecs, domain, payload); + break; + default: ++ ret = sizeof(u32); + break; + } + +- word++; +- words_count--; ++ if (ret < 0) ++ return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; ++ ++ words += ret / sizeof(u32); ++ rem_bytes -= ret; + } + + if (!core->max_sessions_supported) +-- +2.39.5 + diff --git a/queue-5.10/media-venus-hfi_plat-add-codecs-and-capabilities-ops.patch b/queue-5.10/media-venus-hfi_plat-add-codecs-and-capabilities-ops.patch new file mode 100644 index 0000000000..014996ad62 --- /dev/null +++ b/queue-5.10/media-venus-hfi_plat-add-codecs-and-capabilities-ops.patch @@ -0,0 +1,35 @@ +From 68a66cb6387a8f56b5f459c22b806055c0cb844d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Aug 2020 13:07:07 +0200 +Subject: media: venus: hfi_plat: Add codecs and capabilities ops + +From: Stanimir Varbanov + +[ Upstream commit 9822291e031f6d7149ae4f3fc00bd9c33ac2a084 ] + +Add ops to get the supported by the platform codecs and capabilities. + +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/hfi_platform.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h +index 6794232322557..50512d142662f 100644 +--- a/drivers/media/platform/qcom/venus/hfi_platform.h ++++ b/drivers/media/platform/qcom/venus/hfi_platform.h +@@ -47,6 +47,8 @@ struct hfi_platform_codec_freq_data { + struct hfi_platform { + unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec); + unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec); ++ void (*codecs)(u32 *enc_codecs, u32 *dec_codecs, u32 *count); ++ const struct hfi_plat_caps *(*capabilities)(unsigned int *entries); + }; + + extern const struct hfi_platform hfi_plat_v4; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-limit-hfi-sessions-to-the-maximum-suppor.patch b/queue-5.10/media-venus-limit-hfi-sessions-to-the-maximum-suppor.patch new file mode 100644 index 0000000000..4f825d5847 --- /dev/null +++ b/queue-5.10/media-venus-limit-hfi-sessions-to-the-maximum-suppor.patch @@ -0,0 +1,93 @@ +From 5fa4bedb0fda21cc926aa9f51e594f44cf9870ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Dec 2020 11:01:37 +0100 +Subject: media: venus: Limit HFI sessions to the maximum supported + +From: Stanimir Varbanov + +[ Upstream commit 20891170f339a8754312a877f3d17f0e5dadd599 ] + +Currently we rely on firmware to return error when we reach the maximum +supported number of sessions. But this errors are happened at reqbuf +time which is a bit later. The more reasonable way looks like is to +return the error on driver open. + +To achieve that modify hfi_session_create to return error when we reach +maximum count of sessions and thus refuse open. + +Tested-by: Fritz Koenig +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/core.h | 1 + + drivers/media/platform/qcom/venus/hfi.c | 16 +++++++++++++--- + drivers/media/platform/qcom/venus/hfi_parser.c | 3 +++ + 3 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h +index 75d0068033276..e56d7b8142152 100644 +--- a/drivers/media/platform/qcom/venus/core.h ++++ b/drivers/media/platform/qcom/venus/core.h +@@ -96,6 +96,7 @@ struct venus_format { + #define MAX_CAP_ENTRIES 32 + #define MAX_ALLOC_MODE_ENTRIES 16 + #define MAX_CODEC_NUM 32 ++#define MAX_SESSIONS 16 + + struct raw_formats { + u32 buftype; +diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c +index 966b4d9b57a97..17da555905e98 100644 +--- a/drivers/media/platform/qcom/venus/hfi.c ++++ b/drivers/media/platform/qcom/venus/hfi.c +@@ -178,6 +178,8 @@ static int wait_session_msg(struct venus_inst *inst) + int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops) + { + struct venus_core *core = inst->core; ++ bool max; ++ int ret; + + if (!ops) + return -EINVAL; +@@ -187,11 +189,19 @@ int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops) + inst->ops = ops; + + mutex_lock(&core->lock); +- list_add_tail(&inst->list, &core->instances); +- atomic_inc(&core->insts_count); ++ ++ max = atomic_add_unless(&core->insts_count, 1, ++ core->max_sessions_supported); ++ if (!max) { ++ ret = -EAGAIN; ++ } else { ++ list_add_tail(&inst->list, &core->instances); ++ ret = 0; ++ } ++ + mutex_unlock(&core->lock); + +- return 0; ++ return ret; + } + EXPORT_SYMBOL_GPL(hfi_session_create); + +diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c +index 32d2a9ed44003..94981a5e8e9af 100644 +--- a/drivers/media/platform/qcom/venus/hfi_parser.c ++++ b/drivers/media/platform/qcom/venus/hfi_parser.c +@@ -295,6 +295,9 @@ u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, + words_count--; + } + ++ if (!core->max_sessions_supported) ++ core->max_sessions_supported = MAX_SESSIONS; ++ + parser_fini(inst, codecs, domain); + + return HFI_ERR_NONE; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-pm_helpers-check-instance-state-when-cal.patch b/queue-5.10/media-venus-pm_helpers-check-instance-state-when-cal.patch new file mode 100644 index 0000000000..42730ff274 --- /dev/null +++ b/queue-5.10/media-venus-pm_helpers-check-instance-state-when-cal.patch @@ -0,0 +1,37 @@ +From 68e451c45fec58515c724f58edf6ed8379db22dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Nov 2020 15:37:52 +0100 +Subject: media: venus: pm_helpers: Check instance state when calculate + instance frequency + +From: Stanimir Varbanov + +[ Upstream commit d33a94412ed1081f30d904cab54faea7c7b839fc ] + +Skip calculating instance frequency if it is not in running state. + +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/pm_helpers.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index fd55352d743ee..12c5811fefdf9 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -937,6 +937,9 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst, + + mbs_per_sec = load_per_instance(inst) / fps; + ++ if (inst->state != INST_START) ++ return 0; ++ + vpp_freq = mbs_per_sec * inst->clk_data.codec_freq_data->vpp_freq; + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-rename-venus_caps-to-hfi_plat_caps.patch b/queue-5.10/media-venus-rename-venus_caps-to-hfi_plat_caps.patch new file mode 100644 index 0000000000..aad697a4ea --- /dev/null +++ b/queue-5.10/media-venus-rename-venus_caps-to-hfi_plat_caps.patch @@ -0,0 +1,247 @@ +From 6c806d43c85d131b4af7df4c82d644baa0cb6337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Aug 2020 13:04:09 +0200 +Subject: media: venus: Rename venus_caps to hfi_plat_caps + +From: Stanimir Varbanov + +[ Upstream commit 8f3b41dcfb9a0fa2d2ca0af51c3eebd670dc153b ] + +Now when we have hfi platform make venus capabilities an +hfi platform capabilities. + +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/core.h | 30 ++----------------- + drivers/media/platform/qcom/venus/helpers.c | 6 ++-- + .../media/platform/qcom/venus/hfi_parser.c | 18 +++++------ + .../media/platform/qcom/venus/hfi_parser.h | 2 +- + .../media/platform/qcom/venus/hfi_platform.h | 25 ++++++++++++++++ + 5 files changed, 41 insertions(+), 40 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h +index 53d3202460ae9..785a5bbb19c3c 100644 +--- a/drivers/media/platform/qcom/venus/core.h ++++ b/drivers/media/platform/qcom/venus/core.h +@@ -14,6 +14,7 @@ + + #include "dbgfs.h" + #include "hfi.h" ++#include "hfi_platform.h" + + #define VDBGL "VenusLow : " + #define VDBGM "VenusMed : " +@@ -82,31 +83,6 @@ struct venus_format { + u32 flags; + }; + +-#define MAX_PLANES 4 +-#define MAX_FMT_ENTRIES 32 +-#define MAX_CAP_ENTRIES 32 +-#define MAX_ALLOC_MODE_ENTRIES 16 +-#define MAX_CODEC_NUM 32 +-#define MAX_SESSIONS 16 +- +-struct raw_formats { +- u32 buftype; +- u32 fmt; +-}; +- +-struct venus_caps { +- u32 codec; +- u32 domain; +- bool cap_bufs_mode_dynamic; +- unsigned int num_caps; +- struct hfi_capability caps[MAX_CAP_ENTRIES]; +- unsigned int num_pl; +- struct hfi_profile_level pl[HFI_MAX_PROFILE_COUNT]; +- unsigned int num_fmts; +- struct raw_formats fmts[MAX_FMT_ENTRIES]; +- bool valid; /* used only for Venus v1xx */ +-}; +- + /** + * struct venus_core - holds core parameters valid for all instances + * +@@ -199,7 +175,7 @@ struct venus_core { + void *priv; + const struct hfi_ops *ops; + struct delayed_work work; +- struct venus_caps caps[MAX_CODEC_NUM]; ++ struct hfi_plat_caps caps[MAX_CODEC_NUM]; + unsigned int codecs_count; + unsigned int core0_usage_count; + unsigned int core1_usage_count; +@@ -434,7 +410,7 @@ static inline void *to_hfi_priv(struct venus_core *core) + return core->priv; + } + +-static inline struct venus_caps * ++static inline struct hfi_plat_caps * + venus_caps_by_codec(struct venus_core *core, u32 codec, u32 domain) + { + unsigned int c; +diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c +index 9ad8abdc4d4f2..dcf9fc0da1ce4 100644 +--- a/drivers/media/platform/qcom/venus/helpers.c ++++ b/drivers/media/platform/qcom/venus/helpers.c +@@ -481,7 +481,7 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) + static bool is_dynamic_bufmode(struct venus_inst *inst) + { + struct venus_core *core = inst->core; +- struct venus_caps *caps; ++ struct hfi_plat_caps *caps; + + /* + * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports +@@ -1539,7 +1539,7 @@ void venus_helper_init_instance(struct venus_inst *inst) + } + EXPORT_SYMBOL_GPL(venus_helper_init_instance); + +-static bool find_fmt_from_caps(struct venus_caps *caps, u32 buftype, u32 fmt) ++static bool find_fmt_from_caps(struct hfi_plat_caps *caps, u32 buftype, u32 fmt) + { + unsigned int i; + +@@ -1556,7 +1556,7 @@ int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt, + u32 *out_fmt, u32 *out2_fmt, bool ubwc) + { + struct venus_core *core = inst->core; +- struct venus_caps *caps; ++ struct hfi_plat_caps *caps; + u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt); + bool found, found_ubwc; + +diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c +index 94981a5e8e9af..be9a58ef04d86 100644 +--- a/drivers/media/platform/qcom/venus/hfi_parser.c ++++ b/drivers/media/platform/qcom/venus/hfi_parser.c +@@ -11,12 +11,12 @@ + #include "hfi_helper.h" + #include "hfi_parser.h" + +-typedef void (*func)(struct venus_caps *cap, const void *data, ++typedef void (*func)(struct hfi_plat_caps *cap, const void *data, + unsigned int size); + + static void init_codecs(struct venus_core *core) + { +- struct venus_caps *caps = core->caps, *cap; ++ struct hfi_plat_caps *caps = core->caps, *cap; + unsigned long bit; + + core->codecs_count = 0; +@@ -39,11 +39,11 @@ static void init_codecs(struct venus_core *core) + } + } + +-static void for_each_codec(struct venus_caps *caps, unsigned int caps_num, ++static void for_each_codec(struct hfi_plat_caps *caps, unsigned int caps_num, + u32 codecs, u32 domain, func cb, void *data, + unsigned int size) + { +- struct venus_caps *cap; ++ struct hfi_plat_caps *cap; + unsigned int i; + + for (i = 0; i < caps_num; i++) { +@@ -56,7 +56,7 @@ static void for_each_codec(struct venus_caps *caps, unsigned int caps_num, + } + + static void +-fill_buf_mode(struct venus_caps *cap, const void *data, unsigned int num) ++fill_buf_mode(struct hfi_plat_caps *cap, const void *data, unsigned int num) + { + const u32 *type = data; + +@@ -86,7 +86,7 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) + } + } + +-static void fill_profile_level(struct venus_caps *cap, const void *data, ++static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, + unsigned int num) + { + const struct hfi_profile_level *pl = data; +@@ -115,7 +115,7 @@ parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) + } + + static void +-fill_caps(struct venus_caps *cap, const void *data, unsigned int num) ++fill_caps(struct hfi_plat_caps *cap, const void *data, unsigned int num) + { + const struct hfi_capability *caps = data; + +@@ -143,7 +143,7 @@ parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) + fill_caps, caps_arr, num_caps); + } + +-static void fill_raw_fmts(struct venus_caps *cap, const void *fmts, ++static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, + unsigned int num_fmts) + { + const struct raw_formats *formats = fmts; +@@ -228,7 +228,7 @@ static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain) + + static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain) + { +- struct venus_caps *caps, *cap; ++ struct hfi_plat_caps *caps, *cap; + unsigned int i; + u32 dom; + +diff --git a/drivers/media/platform/qcom/venus/hfi_parser.h b/drivers/media/platform/qcom/venus/hfi_parser.h +index 264e6dd2415fe..7f59d82110f9c 100644 +--- a/drivers/media/platform/qcom/venus/hfi_parser.h ++++ b/drivers/media/platform/qcom/venus/hfi_parser.h +@@ -16,7 +16,7 @@ static inline u32 get_cap(struct venus_inst *inst, u32 type, u32 which) + { + struct venus_core *core = inst->core; + struct hfi_capability *cap = NULL; +- struct venus_caps *caps; ++ struct hfi_plat_caps *caps; + unsigned int i; + + caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); +diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h +index 8b07ecbb4c825..6794232322557 100644 +--- a/drivers/media/platform/qcom/venus/hfi_platform.h ++++ b/drivers/media/platform/qcom/venus/hfi_platform.h +@@ -12,6 +12,31 @@ + #include "hfi.h" + #include "hfi_helper.h" + ++#define MAX_PLANES 4 ++#define MAX_FMT_ENTRIES 32 ++#define MAX_CAP_ENTRIES 32 ++#define MAX_ALLOC_MODE_ENTRIES 16 ++#define MAX_CODEC_NUM 32 ++#define MAX_SESSIONS 16 ++ ++struct raw_formats { ++ u32 buftype; ++ u32 fmt; ++}; ++ ++struct hfi_plat_caps { ++ u32 codec; ++ u32 domain; ++ bool cap_bufs_mode_dynamic; ++ unsigned int num_caps; ++ struct hfi_capability caps[MAX_CAP_ENTRIES]; ++ unsigned int num_pl; ++ struct hfi_profile_level pl[HFI_MAX_PROFILE_COUNT]; ++ unsigned int num_fmts; ++ struct raw_formats fmts[MAX_FMT_ENTRIES]; ++ bool valid; /* used only for Venus v1xx */ ++}; ++ + struct hfi_platform_codec_freq_data { + u32 pixfmt; + u32 session_type; +-- +2.39.5 + diff --git a/queue-5.10/media-venus-venc-init-the-session-only-once-in-queue.patch b/queue-5.10/media-venus-venc-init-the-session-only-once-in-queue.patch new file mode 100644 index 0000000000..1e1ad85a6f --- /dev/null +++ b/queue-5.10/media-venus-venc-init-the-session-only-once-in-queue.patch @@ -0,0 +1,187 @@ +From 1c4c7eb8c7717549ac62b7ad29d72e6bf937997e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Dec 2020 11:01:36 +0100 +Subject: media: venus: venc: Init the session only once in queue_setup + +From: Stanimir Varbanov + +[ Upstream commit 5f2ca73dcca96c3de96a0e4d9ea24ebb46c55d2e ] + +Init the hfi session only once in queue_setup and also cover that +with inst->lock. + +Tested-by: Fritz Koenig +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 9edaaa8e3e15 ("media: venus: hfi_parser: refactor hfi packet parsing logic") +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/venc.c | 85 ++++++++++++++++++------ + 1 file changed, 64 insertions(+), 21 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c +index e2d0fd5eaf29a..18d20b4ca2cfd 100644 +--- a/drivers/media/platform/qcom/venus/venc.c ++++ b/drivers/media/platform/qcom/venus/venc.c +@@ -727,7 +727,9 @@ static int venc_init_session(struct venus_inst *inst) + int ret; + + ret = hfi_session_init(inst, inst->fmt_cap->pixfmt); +- if (ret) ++ if (ret == -EINVAL) ++ return 0; ++ else if (ret) + return ret; + + ret = venus_helper_set_input_resolution(inst, inst->width, +@@ -764,17 +766,13 @@ static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num) + struct hfi_buffer_requirements bufreq; + int ret; + +- ret = venc_init_session(inst); ++ ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); + if (ret) + return ret; + +- ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); +- + *num = bufreq.count_actual; + +- hfi_session_deinit(inst); +- +- return ret; ++ return 0; + } + + static int venc_queue_setup(struct vb2_queue *q, +@@ -783,7 +781,7 @@ static int venc_queue_setup(struct vb2_queue *q, + { + struct venus_inst *inst = vb2_get_drv_priv(q); + unsigned int num, min = 4; +- int ret = 0; ++ int ret; + + if (*num_planes) { + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && +@@ -805,6 +803,13 @@ static int venc_queue_setup(struct vb2_queue *q, + return 0; + } + ++ mutex_lock(&inst->lock); ++ ret = venc_init_session(inst); ++ mutex_unlock(&inst->lock); ++ ++ if (ret) ++ return ret; ++ + switch (q->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + *num_planes = inst->fmt_out->num_planes; +@@ -840,6 +845,49 @@ static int venc_queue_setup(struct vb2_queue *q, + return ret; + } + ++static int venc_buf_init(struct vb2_buffer *vb) ++{ ++ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); ++ ++ inst->buf_count++; ++ ++ return venus_helper_vb2_buf_init(vb); ++} ++ ++static void venc_release_session(struct venus_inst *inst) ++{ ++ int ret; ++ ++ mutex_lock(&inst->lock); ++ ++ ret = hfi_session_deinit(inst); ++ if (ret || inst->session_error) ++ hfi_session_abort(inst); ++ ++ mutex_unlock(&inst->lock); ++ ++ venus_pm_load_scale(inst); ++ INIT_LIST_HEAD(&inst->registeredbufs); ++ venus_pm_release_core(inst); ++} ++ ++static void venc_buf_cleanup(struct vb2_buffer *vb) ++{ ++ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct venus_buffer *buf = to_venus_buffer(vbuf); ++ ++ mutex_lock(&inst->lock); ++ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ++ if (!list_empty(&inst->registeredbufs)) ++ list_del_init(&buf->reg_list); ++ mutex_unlock(&inst->lock); ++ ++ inst->buf_count--; ++ if (!inst->buf_count) ++ venc_release_session(inst); ++} ++ + static int venc_verify_conf(struct venus_inst *inst) + { + enum hfi_version ver = inst->core->res->hfi_version; +@@ -890,38 +938,32 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count) + inst->sequence_cap = 0; + inst->sequence_out = 0; + +- ret = venc_init_session(inst); +- if (ret) +- goto bufs_done; +- + ret = venus_pm_acquire_core(inst); + if (ret) +- goto deinit_sess; ++ goto error; + + ret = venc_set_properties(inst); + if (ret) +- goto deinit_sess; ++ goto error; + + ret = venc_verify_conf(inst); + if (ret) +- goto deinit_sess; ++ goto error; + + ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, + inst->num_output_bufs, 0); + if (ret) +- goto deinit_sess; ++ goto error; + + ret = venus_helper_vb2_start_streaming(inst); + if (ret) +- goto deinit_sess; ++ goto error; + + mutex_unlock(&inst->lock); + + return 0; + +-deinit_sess: +- hfi_session_deinit(inst); +-bufs_done: ++error: + venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + inst->streamon_out = 0; +@@ -933,7 +975,8 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count) + + static const struct vb2_ops venc_vb2_ops = { + .queue_setup = venc_queue_setup, +- .buf_init = venus_helper_vb2_buf_init, ++ .buf_init = venc_buf_init, ++ .buf_cleanup = venc_buf_cleanup, + .buf_prepare = venus_helper_vb2_buf_prepare, + .start_streaming = venc_start_streaming, + .stop_streaming = venus_helper_vb2_stop_streaming, +-- +2.39.5 + diff --git a/queue-5.10/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch b/queue-5.10/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch new file mode 100644 index 0000000000..b95eccf05c --- /dev/null +++ b/queue-5.10/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch @@ -0,0 +1,55 @@ +From 2403bbf5473c0afbd398d66c28cda3f3a367dff4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:32:44 +0100 +Subject: net: dsa: mv88e6xxx: fix VTU methods for 6320 family +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit f9a457722cf5e3534be5ffab549d6b49737fca72 ] + +The VTU registers of the 6320 family use the 6352 semantics, not 6185. +Fix it. + +Fixes: b8fee9571063 ("net: dsa: mv88e6xxx: add VLAN Get Next support") +Signed-off-by: Marek Behún +Cc: # 5.15.x +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index e590ea87b6ea2..ebc8580873940 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -4170,8 +4170,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, + .reset = mv88e6352_g1_reset, +- .vtu_getnext = mv88e6185_g1_vtu_getnext, +- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, ++ .vtu_getnext = mv88e6352_g1_vtu_getnext, ++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +@@ -4212,8 +4212,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .reset = mv88e6352_g1_reset, +- .vtu_getnext = mv88e6185_g1_vtu_getnext, +- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, ++ .vtu_getnext = mv88e6352_g1_vtu_getnext, ++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +-- +2.39.5 + diff --git a/queue-5.10/pci-assign-pci-domain-ids-by-ida_alloc.patch b/queue-5.10/pci-assign-pci-domain-ids-by-ida_alloc.patch new file mode 100644 index 0000000000..62a5eccd0f --- /dev/null +++ b/queue-5.10/pci-assign-pci-domain-ids-by-ida_alloc.patch @@ -0,0 +1,227 @@ +From 986e2a9c8da3498840d7113f1984acb946e2a000 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 20:41:30 +0200 +Subject: PCI: Assign PCI domain IDs by ida_alloc() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit c14f7ccc9f5dcf9d06ddeec706f85405b2c80600 ] + +Replace assignment of PCI domain IDs from atomic_inc_return() to +ida_alloc(). + +Use two IDAs, one for static domain allocations (those which are defined in +device tree) and second for dynamic allocations (all other). + +During removal of root bus / host bridge, also release the domain ID. The +released ID can be reused again, for example when dynamically loading and +unloading native PCI host bridge drivers. + +This change also allows to mix static device tree assignment and dynamic by +kernel as all static allocations are reserved in dynamic pool. + +[bhelgaas: set "err" if "bus->domain_nr < 0"] +Link: https://lore.kernel.org/r/20220714184130.5436-1-pali@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Bjorn Helgaas +Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()") +Signed-off-by: Sasha Levin +--- + drivers/pci/pci.c | 103 +++++++++++++++++++++++++------------------ + drivers/pci/probe.c | 7 +++ + drivers/pci/remove.c | 6 +++ + include/linux/pci.h | 1 + + 4 files changed, 74 insertions(+), 43 deletions(-) + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 1d4585b07de3b..24916e78c507c 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -6467,60 +6467,70 @@ static void pci_no_domains(void) + } + + #ifdef CONFIG_PCI_DOMAINS_GENERIC +-static atomic_t __domain_nr = ATOMIC_INIT(-1); ++static DEFINE_IDA(pci_domain_nr_static_ida); ++static DEFINE_IDA(pci_domain_nr_dynamic_ida); + +-static int pci_get_new_domain_nr(void) ++static void of_pci_reserve_static_domain_nr(void) + { +- return atomic_inc_return(&__domain_nr); ++ struct device_node *np; ++ int domain_nr; ++ ++ for_each_node_by_type(np, "pci") { ++ domain_nr = of_get_pci_domain_nr(np); ++ if (domain_nr < 0) ++ continue; ++ /* ++ * Permanently allocate domain_nr in dynamic_ida ++ * to prevent it from dynamic allocation. ++ */ ++ ida_alloc_range(&pci_domain_nr_dynamic_ida, ++ domain_nr, domain_nr, GFP_KERNEL); ++ } + } + + static int of_pci_bus_find_domain_nr(struct device *parent) + { +- static int use_dt_domains = -1; +- int domain = -1; ++ static bool static_domains_reserved = false; ++ int domain_nr; + +- if (parent) +- domain = of_get_pci_domain_nr(parent->of_node); ++ /* On the first call scan device tree for static allocations. */ ++ if (!static_domains_reserved) { ++ of_pci_reserve_static_domain_nr(); ++ static_domains_reserved = true; ++ } ++ ++ if (parent) { ++ /* ++ * If domain is in DT, allocate it in static IDA. This ++ * prevents duplicate static allocations in case of errors ++ * in DT. ++ */ ++ domain_nr = of_get_pci_domain_nr(parent->of_node); ++ if (domain_nr >= 0) ++ return ida_alloc_range(&pci_domain_nr_static_ida, ++ domain_nr, domain_nr, ++ GFP_KERNEL); ++ } + + /* +- * Check DT domain and use_dt_domains values. +- * +- * If DT domain property is valid (domain >= 0) and +- * use_dt_domains != 0, the DT assignment is valid since this means +- * we have not previously allocated a domain number by using +- * pci_get_new_domain_nr(); we should also update use_dt_domains to +- * 1, to indicate that we have just assigned a domain number from +- * DT. +- * +- * If DT domain property value is not valid (ie domain < 0), and we +- * have not previously assigned a domain number from DT +- * (use_dt_domains != 1) we should assign a domain number by +- * using the: +- * +- * pci_get_new_domain_nr() +- * +- * API and update the use_dt_domains value to keep track of method we +- * are using to assign domain numbers (use_dt_domains = 0). +- * +- * All other combinations imply we have a platform that is trying +- * to mix domain numbers obtained from DT and pci_get_new_domain_nr(), +- * which is a recipe for domain mishandling and it is prevented by +- * invalidating the domain value (domain = -1) and printing a +- * corresponding error. ++ * If domain was not specified in DT, choose a free ID from dynamic ++ * allocations. All domain numbers from DT are permanently in ++ * dynamic allocations to prevent assigning them to other DT nodes ++ * without static domain. + */ +- if (domain >= 0 && use_dt_domains) { +- use_dt_domains = 1; +- } else if (domain < 0 && use_dt_domains != 1) { +- use_dt_domains = 0; +- domain = pci_get_new_domain_nr(); +- } else { +- if (parent) +- pr_err("Node %pOF has ", parent->of_node); +- pr_err("Inconsistent \"linux,pci-domain\" property in DT\n"); +- domain = -1; +- } ++ return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL); ++} + +- return domain; ++static void of_pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent) ++{ ++ if (bus->domain_nr < 0) ++ return; ++ ++ /* Release domain from IDA where it was allocated. */ ++ if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr) ++ ida_free(&pci_domain_nr_static_ida, bus->domain_nr); ++ else ++ ida_free(&pci_domain_nr_dynamic_ida, bus->domain_nr); + } + + int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) +@@ -6528,6 +6538,13 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) + return acpi_disabled ? of_pci_bus_find_domain_nr(parent) : + acpi_pci_bus_find_domain_nr(bus); + } ++ ++void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent) ++{ ++ if (!acpi_disabled) ++ return; ++ of_pci_bus_release_domain_nr(bus, parent); ++} + #endif + + /** +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index a2c53f6d1848a..012ca242bedf4 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -904,6 +904,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + bus->domain_nr = pci_bus_find_domain_nr(bus, parent); + else + bus->domain_nr = bridge->domain_nr; ++ if (bus->domain_nr < 0) { ++ err = bus->domain_nr; ++ goto free; ++ } + #endif + + b = pci_find_bus(pci_domain_nr(bus), bridge->busnr); +@@ -1022,6 +1026,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + device_del(&bridge->dev); + + free: ++#ifdef CONFIG_PCI_DOMAINS_GENERIC ++ pci_bus_release_domain_nr(bus, parent); ++#endif + kfree(bus); + return err; + } +diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c +index 95dec03d9f2a9..611547b52b46d 100644 +--- a/drivers/pci/remove.c ++++ b/drivers/pci/remove.c +@@ -159,6 +159,12 @@ void pci_remove_root_bus(struct pci_bus *bus) + pci_remove_bus(bus); + host_bridge->bus = NULL; + ++#ifdef CONFIG_PCI_DOMAINS_GENERIC ++ /* Release domain_nr if it was dynamically allocated */ ++ if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET) ++ pci_bus_release_domain_nr(bus, host_bridge->dev.parent); ++#endif ++ + /* remove the host bridge */ + device_del(&host_bridge->dev); + } +diff --git a/include/linux/pci.h b/include/linux/pci.h +index a0fd1fe4189e4..d3d84eb466f02 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -1667,6 +1667,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) + { return 0; } + #endif + int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent); ++void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent); + #endif + + /* Some architectures require additional setup to direct VGA traffic */ +-- +2.39.5 + diff --git a/queue-5.10/pci-coalesce-host-bridge-contiguous-apertures.patch b/queue-5.10/pci-coalesce-host-bridge-contiguous-apertures.patch new file mode 100644 index 0000000000..1bc3be2592 --- /dev/null +++ b/queue-5.10/pci-coalesce-host-bridge-contiguous-apertures.patch @@ -0,0 +1,99 @@ +From 490e7fc8f363468103dd2ac020913a6bec7f2bdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Jul 2021 20:50:07 +0800 +Subject: PCI: Coalesce host bridge contiguous apertures + +From: Kai-Heng Feng + +[ Upstream commit 65db04053efea3f3e412a7e0cc599962999c96b4 ] + +Built-in graphics on HP EliteDesk 805 G6 doesn't work because graphics +can't get the BAR it needs: + + pci_bus 0000:00: root bus resource [mem 0x10020200000-0x100303fffff window] + pci_bus 0000:00: root bus resource [mem 0x10030400000-0x100401fffff window] + + pci 0000:00:08.1: bridge window [mem 0xd2000000-0xd23fffff] + pci 0000:00:08.1: bridge window [mem 0x10030000000-0x100401fffff 64bit pref] + pci 0000:00:08.1: can't claim BAR 15 [mem 0x10030000000-0x100401fffff 64bit pref]: no compatible bridge window + pci 0000:00:08.1: [mem 0x10030000000-0x100401fffff 64bit pref] clipped to [mem 0x10030000000-0x100303fffff 64bit pref] + pci 0000:00:08.1: bridge window [mem 0x10030000000-0x100303fffff 64bit pref] + pci 0000:07:00.0: can't claim BAR 0 [mem 0x10030000000-0x1003fffffff 64bit pref]: no compatible bridge window + pci 0000:07:00.0: can't claim BAR 2 [mem 0x10040000000-0x100401fffff 64bit pref]: no compatible bridge window + +However, the root bus has two contiguous apertures that can contain the +child resource requested. + +Coalesce contiguous apertures so we can allocate from the entire contiguous +region. + +[bhelgaas: fold in https://lore.kernel.org/r/20210528170242.1564038-1-kai.heng.feng@canonical.com] +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=212013 +Suggested-by: Bjorn Helgaas +Link: https://lore.kernel.org/r/20210401131252.531935-1-kai.heng.feng@canonical.com +Signed-off-by: Kai-Heng Feng +Signed-off-by: Bjorn Helgaas +Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()") +Signed-off-by: Sasha Levin +--- + drivers/pci/probe.c | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index be7973e249cd7..a2c53f6d1848a 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -878,11 +878,11 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus) + static int pci_register_host_bridge(struct pci_host_bridge *bridge) + { + struct device *parent = bridge->dev.parent; +- struct resource_entry *window, *n; ++ struct resource_entry *window, *next, *n; + struct pci_bus *bus, *b; +- resource_size_t offset; ++ resource_size_t offset, next_offset; + LIST_HEAD(resources); +- struct resource *res; ++ struct resource *res, *next_res; + char addr[64], *fmt; + const char *name; + int err; +@@ -962,11 +962,34 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE) + dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n"); + ++ /* Coalesce contiguous windows */ ++ resource_list_for_each_entry_safe(window, n, &resources) { ++ if (list_is_last(&window->node, &resources)) ++ break; ++ ++ next = list_next_entry(window, node); ++ offset = window->offset; ++ res = window->res; ++ next_offset = next->offset; ++ next_res = next->res; ++ ++ if (res->flags != next_res->flags || offset != next_offset) ++ continue; ++ ++ if (res->end + 1 == next_res->start) { ++ next_res->start = res->start; ++ res->flags = res->start = res->end = 0; ++ } ++ } ++ + /* Add initial resources to the bus */ + resource_list_for_each_entry_safe(window, n, &resources) { +- list_move_tail(&window->node, &bridge->windows); + offset = window->offset; + res = window->res; ++ if (!res->end) ++ continue; ++ ++ list_move_tail(&window->node, &bridge->windows); + + if (res->flags & IORESOURCE_BUS) + pci_bus_insert_busn_res(bus, bus->number, res->end); +-- +2.39.5 + diff --git a/queue-5.10/pci-fix-reference-leak-in-pci_register_host_bridge.patch b/queue-5.10/pci-fix-reference-leak-in-pci_register_host_bridge.patch new file mode 100644 index 0000000000..220382d70c --- /dev/null +++ b/queue-5.10/pci-fix-reference-leak-in-pci_register_host_bridge.patch @@ -0,0 +1,67 @@ +From 3679a05ddfeba7a765cdca0ffbb597b086ebeaf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 10:14:40 +0800 +Subject: PCI: Fix reference leak in pci_register_host_bridge() + +From: Ma Ke + +[ Upstream commit 804443c1f27883926de94c849d91f5b7d7d696e9 ] + +If device_register() fails, call put_device() to give up the reference to +avoid a memory leak, per the comment at device_register(). + +Found by code review. + +Link: https://lore.kernel.org/r/20250225021440.3130264-1-make24@iscas.ac.cn +Fixes: 37d6a0a6f470 ("PCI: Add pci_register_host_bridge() interface") +Signed-off-by: Ma Ke +[bhelgaas: squash Dan Carpenter's double free fix from +https://lore.kernel.org/r/db806a6c-a91b-4e5a-a84b-6b7e01bdac85@stanley.mountain] +Signed-off-by: Bjorn Helgaas +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/probe.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 012ca242bedf4..7f3d10957eca7 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -883,6 +883,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + resource_size_t offset, next_offset; + LIST_HEAD(resources); + struct resource *res, *next_res; ++ bool bus_registered = false; + char addr[64], *fmt; + const char *name; + int err; +@@ -944,6 +945,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + name = dev_name(&bus->dev); + + err = device_register(&bus->dev); ++ bus_registered = true; + if (err) + goto unregister; + +@@ -1024,12 +1026,15 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + unregister: + put_device(&bridge->dev); + device_del(&bridge->dev); +- + free: + #ifdef CONFIG_PCI_DOMAINS_GENERIC + pci_bus_release_domain_nr(bus, parent); + #endif +- kfree(bus); ++ if (bus_registered) ++ put_device(&bus->dev); ++ else ++ kfree(bus); ++ + return err; + } + +-- +2.39.5 + diff --git a/queue-5.10/pci-introduce-domain_nr-in-pci_host_bridge.patch b/queue-5.10/pci-introduce-domain_nr-in-pci_host_bridge.patch new file mode 100644 index 0000000000..f11feefb6f --- /dev/null +++ b/queue-5.10/pci-introduce-domain_nr-in-pci_host_bridge.patch @@ -0,0 +1,91 @@ +From ac5ff084ef8a10127a512e26532d6078d903aaf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jul 2021 02:06:50 +0800 +Subject: PCI: Introduce domain_nr in pci_host_bridge + +From: Boqun Feng + +[ Upstream commit 15d82ca23c996d50062286d27ed6a42a8105c04a ] + +Currently we retrieve the PCI domain number of the host bridge from the +bus sysdata (or pci_config_window if PCI_DOMAINS_GENERIC=y). Actually +we have the information at PCI host bridge probing time, and it makes +sense that we store it into pci_host_bridge. One benefit of doing so is +the requirement for supporting PCI on Hyper-V for ARM64, because the +host bridge of Hyper-V doesn't have pci_config_window, whereas ARM64 is +a PCI_DOMAINS_GENERIC=y arch, so we cannot retrieve the PCI domain +number from pci_config_window on ARM64 Hyper-V guest. + +As the preparation for ARM64 Hyper-V PCI support, we introduce the +domain_nr in pci_host_bridge and a sentinel value to allow drivers to +set domain numbers properly at probing time. Currently +CONFIG_PCI_DOMAINS_GENERIC=y archs are only users of this +newly-introduced field. + +Link: https://lore.kernel.org/r/20210726180657.142727-2-boqun.feng@gmail.com +Signed-off-by: Boqun Feng +Signed-off-by: Lorenzo Pieralisi +Acked-by: Bjorn Helgaas +Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()") +Signed-off-by: Sasha Levin +--- + drivers/pci/probe.c | 6 +++++- + include/linux/pci.h | 11 +++++++++++ + 2 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 6439fc2e526c7..be7973e249cd7 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -595,6 +595,7 @@ static void pci_init_host_bridge(struct pci_host_bridge *bridge) + bridge->native_pme = 1; + bridge->native_ltr = 1; + bridge->native_dpc = 1; ++ bridge->domain_nr = PCI_DOMAIN_NR_NOT_SET; + + device_initialize(&bridge->dev); + } +@@ -899,7 +900,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + bus->ops = bridge->ops; + bus->number = bus->busn_res.start = bridge->busnr; + #ifdef CONFIG_PCI_DOMAINS_GENERIC +- bus->domain_nr = pci_bus_find_domain_nr(bus, parent); ++ if (bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET) ++ bus->domain_nr = pci_bus_find_domain_nr(bus, parent); ++ else ++ bus->domain_nr = bridge->domain_nr; + #endif + + b = pci_find_bus(pci_domain_nr(bus), bridge->busnr); +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 30bc462fb1964..a0fd1fe4189e4 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -538,6 +538,16 @@ static inline int pci_channel_offline(struct pci_dev *pdev) + return (pdev->error_state != pci_channel_io_normal); + } + ++/* ++ * Currently in ACPI spec, for each PCI host bridge, PCI Segment ++ * Group number is limited to a 16-bit value, therefore (int)-1 is ++ * not a valid PCI domain number, and can be used as a sentinel ++ * value indicating ->domain_nr is not set by the driver (and ++ * CONFIG_PCI_DOMAINS_GENERIC=y archs will set it with ++ * pci_bus_find_domain_nr()). ++ */ ++#define PCI_DOMAIN_NR_NOT_SET (-1) ++ + struct pci_host_bridge { + struct device dev; + struct pci_bus *bus; /* Root bus */ +@@ -545,6 +555,7 @@ struct pci_host_bridge { + struct pci_ops *child_ops; + void *sysdata; + int busnr; ++ int domain_nr; + struct list_head windows; /* resource_entry */ + struct list_head dma_ranges; /* dma ranges resource list */ + u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ +-- +2.39.5 + diff --git a/queue-5.10/platform-provide-a-remove-callback-that-returns-no-v.patch b/queue-5.10/platform-provide-a-remove-callback-that-returns-no-v.patch new file mode 100644 index 0000000000..44a6c7527d --- /dev/null +++ b/queue-5.10/platform-provide-a-remove-callback-that-returns-no-v.patch @@ -0,0 +1,86 @@ +From 9a4cc968fa1d50ae1ce704b5813a2e70f0fa1192 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 16:09:14 +0100 +Subject: platform: Provide a remove callback that returns no value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 5c5a7680e67ba6fbbb5f4d79fa41485450c1985c ] + +struct platform_driver::remove returning an integer made driver authors +expect that returning an error code was proper error handling. However +the driver core ignores the error and continues to remove the device +because there is nothing the core could do anyhow and reentering the +remove callback again is only calling for trouble. + +So this is an source for errors typically yielding resource leaks in the +error path. + +As there are too many platform drivers to neatly convert them all to +return void in a single go, do it in several steps after this patch: + + a) Convert all drivers to implement .remove_new() returning void instead + of .remove() returning int; + b) Change struct platform_driver::remove() to return void and so make + it identical to .remove_new(); + c) Change all drivers back to .remove() now with the better prototype; + d) drop struct platform_driver::remove_new(). + +While this touches all drivers eventually twice, steps a) and c) can be +done one driver after another and so reduces coordination efforts +immensely and simplifies review. + +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20221209150914.3557650-1-u.kleine-koenig@pengutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()") +Signed-off-by: Sasha Levin +--- + drivers/base/platform.c | 4 +++- + include/linux/platform_device.h | 11 +++++++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index d0b15cbab0ff0..e07043d85c65c 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -1306,7 +1306,9 @@ static int platform_remove(struct device *_dev) + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + +- if (drv->remove) { ++ if (drv->remove_new) { ++ drv->remove_new(dev); ++ } else if (drv->remove) { + int ret = drv->remove(dev); + + if (ret) +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index e7a83b0218077..870a918aa251c 100644 +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -203,7 +203,18 @@ extern void platform_device_put(struct platform_device *pdev); + + struct platform_driver { + int (*probe)(struct platform_device *); ++ ++ /* ++ * Traditionally the remove callback returned an int which however is ++ * ignored by the driver core. This led to wrong expectations by driver ++ * authors who thought returning an error code was a valid error ++ * handling strategy. To convert to a callback returning void, new ++ * drivers should implement .remove_new() until the conversion it done ++ * that eventually makes .remove() return void. ++ */ + int (*remove)(struct platform_device *); ++ void (*remove_new)(struct platform_device *); ++ + void (*shutdown)(struct platform_device *); + int (*suspend)(struct platform_device *, pm_message_t state); + int (*resume)(struct platform_device *); +-- +2.39.5 + diff --git a/queue-5.10/platform-x86-isst-correct-command-storage-data-lengt.patch b/queue-5.10/platform-x86-isst-correct-command-storage-data-lengt.patch new file mode 100644 index 0000000000..78d77a8b82 --- /dev/null +++ b/queue-5.10/platform-x86-isst-correct-command-storage-data-lengt.patch @@ -0,0 +1,50 @@ +From abbdca9f84caf3e2493ec477b9387d3678e6f4ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 15:47:49 -0700 +Subject: platform/x86: ISST: Correct command storage data length +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivas Pandruvada + +[ Upstream commit 9462e74c5c983cce34019bfb27f734552bebe59f ] + +After resume/online turbo limit ratio (TRL) is restored partially if +the admin explicitly changed TRL from user space. + +A hash table is used to store SST mail box and MSR settings when modified +to restore those settings after resume or online. This uses a struct +isst_cmd field "data" to store these settings. This is a 64 bit field. +But isst_store_new_cmd() is only assigning as u32. This results in +truncation of 32 bits. + +Change the argument to u64 from u32. + +Fixes: f607874f35cb ("platform/x86: ISST: Restore state on resume") +Signed-off-by: Srinivas Pandruvada +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20250328224749.2691272-1-srinivas.pandruvada@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel_speed_select_if/isst_if_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_common.c b/drivers/platform/x86/intel_speed_select_if/isst_if_common.c +index 407afafc7e83f..e0f7368e7e3e9 100644 +--- a/drivers/platform/x86/intel_speed_select_if/isst_if_common.c ++++ b/drivers/platform/x86/intel_speed_select_if/isst_if_common.c +@@ -77,7 +77,7 @@ static DECLARE_HASHTABLE(isst_hash, 8); + static DEFINE_MUTEX(isst_hash_lock); + + static int isst_store_new_cmd(int cmd, u32 cpu, int mbox_cmd_type, u32 param, +- u32 data) ++ u64 data) + { + struct isst_cmd *sst_cmd; + +-- +2.39.5 + diff --git a/queue-5.10/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch b/queue-5.10/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch new file mode 100644 index 0000000000..b04d0fc039 --- /dev/null +++ b/queue-5.10/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch @@ -0,0 +1,79 @@ +From c0a06ddf4d69e17c258ec4f171bdac9d6960254e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Apr 2025 17:42:32 +0100 +Subject: selftests/mm: generate a temporary mountpoint for cgroup filesystem + +From: Mark Brown + +[ Upstream commit 9c02223e2d9df5cb37c51aedb78f3960294e09b5 ] + +Currently if the filesystem for the cgroups version it wants to use is not +mounted charge_reserved_hugetlb.sh and hugetlb_reparenting_test.sh tests +will attempt to mount it on the hard coded path /dev/cgroup/memory, +deleting that directory when the test finishes. This will fail if there +is not a preexisting directory at that path, and since the directory is +deleted subsequent runs of the test will fail. Instead of relying on this +hard coded directory name use mktemp to generate a temporary directory to +use as a mountpoint, fixing both the assumption and the disruption caused +by deleting a preexisting directory. + +This means that if the relevant cgroup filesystem is not already mounted +then we rely on having coreutils (which provides mktemp) installed. I +suspect that many current users are relying on having things automounted +by default, and given that the script relies on bash it's probably not an +unreasonable requirement. + +Link: https://lkml.kernel.org/r/20250404-kselftest-mm-cgroup2-detection-v1-1-3dba6d32ba8c@kernel.org +Fixes: 209376ed2a84 ("selftests/vm: make charge_reserved_hugetlb.sh work with existing cgroup setting") +Signed-off-by: Mark Brown +Cc: Aishwarya TCV +Cc: Mark Brown +Cc: Mina Almasry +Cc: Shuah Khan +Cc: Waiman Long +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/vm/charge_reserved_hugetlb.sh | 4 ++-- + tools/testing/selftests/vm/hugetlb_reparenting_test.sh | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh +index 28192ec98498f..c44226b4e0bfb 100644 +--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh ++++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh +@@ -24,7 +24,7 @@ fi + if [[ $cgroup2 ]]; then + cgroup_path=$(mount -t cgroup2 | head -1 | awk '{print $3}') + if [[ -z "$cgroup_path" ]]; then +- cgroup_path=/dev/cgroup/memory ++ cgroup_path=$(mktemp -d) + mount -t cgroup2 none $cgroup_path + do_umount=1 + fi +@@ -32,7 +32,7 @@ if [[ $cgroup2 ]]; then + else + cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') + if [[ -z "$cgroup_path" ]]; then +- cgroup_path=/dev/cgroup/memory ++ cgroup_path=$(mktemp -d) + mount -t cgroup memory,hugetlb $cgroup_path + do_umount=1 + fi +diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh +index c665b16f1e370..a4123632942dd 100644 +--- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh ++++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh +@@ -19,7 +19,7 @@ fi + if [[ $cgroup2 ]]; then + CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}') + if [[ -z "$CGROUP_ROOT" ]]; then +- CGROUP_ROOT=/dev/cgroup/memory ++ CGROUP_ROOT=$(mktemp -d) + mount -t cgroup2 none $CGROUP_ROOT + do_umount=1 + fi +-- +2.39.5 + diff --git a/queue-5.10/series b/queue-5.10/series index f85612522c..3f58b36e8c 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -191,3 +191,45 @@ drivers-staging-rtl8723bs-fix-deadlock-in-rtw_surveydone_event_callback.patch s390-dasd-fix-double-module-refcount-decrement.patch pmdomain-ti-add-a-null-pointer-check-to-the-omap_prm_domain_init.patch drivers-staging-rtl8723bs-fix-locking-in-rtw_scan_timeout_handler.patch +platform-x86-isst-correct-command-storage-data-lengt.patch +tracing-allow-synthetic-events-to-pass-around-stackt.patch +tracing-fix-synth-event-printk-format-for-str-fields.patch +media-streamzap-remove-unnecessary-ir_raw_event_rese.patch +media-streamzap-no-need-for-usb-pid-vid-in-device-na.patch +media-streamzap-less-chatter.patch +media-streamzap-remove-unused-struct-members.patch +media-streamzap-fix-race-between-device-disconnectio.patch +media-venus-venc-init-the-session-only-once-in-queue.patch +media-venus-limit-hfi-sessions-to-the-maximum-suppor.patch +media-venus-hfi-correct-session-init-return-error.patch +media-venus-pm_helpers-check-instance-state-when-cal.patch +media-venus-create-hfi-platform-and-move-vpp-vsp-the.patch +media-venus-rename-venus_caps-to-hfi_plat_caps.patch +media-venus-hfi_plat-add-codecs-and-capabilities-ops.patch +media-venus-get-codecs-and-capabilities-from-hfi-pla.patch +media-venus-hfi_parser-refactor-hfi-packet-parsing-l.patch +net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch +soc-samsung-exynos-chipid-initialize-later-with-arch.patch +soc-samsung-exynos-chipid-convert-to-driver-and-merg.patch +soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch +soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch +soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch +iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch +iio-adc-ad7768-1-fix-conversion-result-sign.patch +driver-core-platform-reorder-functions.patch +driver-core-platform-change-logic-implementing-platf.patch +driver-core-platform-use-bus_type-functions.patch +driver-core-platform-emit-a-warning-if-a-remove-call.patch +platform-provide-a-remove-callback-that-returns-no-v.patch +backlight-led_bl-convert-to-platform-remove-callback.patch +backlight-led_bl-hold-led_access-lock-when-calling-l.patch +cifs-print-tids-as-hex.patch +cifs-avoid-null-pointer-dereference-in-dbg-call.patch +pci-introduce-domain_nr-in-pci_host_bridge.patch +pci-coalesce-host-bridge-contiguous-apertures.patch +pci-assign-pci-domain-ids-by-ida_alloc.patch +pci-fix-reference-leak-in-pci_register_host_bridge.patch +selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch +drm-amd-amdgpu-amdgpu_vram_mgr-add-missing-descripti.patch +drm-amdgpu-remove-amdgpu_device-arg-from-free_sgt-ap.patch +drm-amdgpu-dma_buf-fix-page_link-check.patch diff --git a/queue-5.10/soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch b/queue-5.10/soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch new file mode 100644 index 0000000000..fb463322cb --- /dev/null +++ b/queue-5.10/soc-samsung-exynos-chipid-add-null-pointer-check-in-.patch @@ -0,0 +1,43 @@ +From b002eeb638cdba75a661d928059e4770ce106557 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 15:35:18 -0600 +Subject: soc: samsung: exynos-chipid: Add NULL pointer check in + exynos_chipid_probe() + +From: Chenyuan Yang + +[ Upstream commit c8222ef6cf29dd7cad21643228f96535cc02b327 ] + +soc_dev_attr->revision could be NULL, thus, +a pointer check is added to prevent potential NULL pointer dereference. +This is similar to the fix in commit 3027e7b15b02 +("ice: Fix some null pointer dereference issues in ice_ptp.c"). + +This issue is found by our static analysis tool. + +Signed-off-by: Chenyuan Yang +Link: https://lore.kernel.org/r/20250212213518.69432-1-chenyuan0y@gmail.com +Fixes: 3253b7b7cd44 ("soc: samsung: Add exynos chipid driver support") +Cc: +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + drivers/soc/samsung/exynos-chipid.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index a2d163a1b4e11..fb9e80b63b917 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -124,6 +124,8 @@ static int exynos_chipid_probe(struct platform_device *pdev) + + soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%x", soc_info.revision); ++ if (!soc_dev_attr->revision) ++ return -ENOMEM; + soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id); + if (!soc_dev_attr->soc_id) { + pr_err("Unknown SoC\n"); +-- +2.39.5 + diff --git a/queue-5.10/soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch b/queue-5.10/soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch new file mode 100644 index 0000000000..0e6702b27b --- /dev/null +++ b/queue-5.10/soc-samsung-exynos-chipid-avoid-soc_device_to_device.patch @@ -0,0 +1,45 @@ +From 6e7007923ae880de6d1f758136d7cc00590e02cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Sep 2021 11:31:12 +0200 +Subject: soc: samsung: exynos-chipid: avoid soc_device_to_device() + +From: Krzysztof Kozlowski + +[ Upstream commit d1141886c8d72ad77920e6e4b617d366e6e3ee8a ] + +soc_device_to_device() seems to be discouraged [1] so remove it in favor +of printing info message with platform device. This will only change +the prefix in the info message from "soc soc0: " to "exynos-chipid +10000000.chipid:". + +[1] https://lore.kernel.org/lkml/20191111052741.GB3176397@kroah.com/ + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Sylwester Nawrocki +Tested-by: Sylwester Nawrocki +Reviewed-by: Alim Akhtar +Tested-by: Alim Akhtar +Link: https://lore.kernel.org/r/20210919093114.35987-2-krzysztof.kozlowski@canonical.com +Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()") +Signed-off-by: Sasha Levin +--- + drivers/soc/samsung/exynos-chipid.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index 2ab6ce71e9be5..2b02af5d2faff 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -103,8 +103,7 @@ static int exynos_chipid_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, soc_dev); + +- dev_info(soc_device_to_device(soc_dev), +- "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", ++ dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", + soc_dev_attr->soc_id, product_id, revision); + + return 0; +-- +2.39.5 + diff --git a/queue-5.10/soc-samsung-exynos-chipid-convert-to-driver-and-merg.patch b/queue-5.10/soc-samsung-exynos-chipid-convert-to-driver-and-merg.patch new file mode 100644 index 0000000000..526e4762d7 --- /dev/null +++ b/queue-5.10/soc-samsung-exynos-chipid-convert-to-driver-and-merg.patch @@ -0,0 +1,370 @@ +From 755165359792d34158f7497441d44801256b3472 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Dec 2020 19:54:57 +0100 +Subject: soc: samsung: exynos-chipid: convert to driver and merge exynos-asv + +From: Krzysztof Kozlowski + +[ Upstream commit 352bfbb3e0230c96b2bce00d2ac3f0de303cc7b6 ] + +The Exynos Chip ID driver on Exynos SoCs has so far only informational +purpose - to expose the SoC device in sysfs. No other drivers depend on +it so there is really no benefit of initializing it early. + +The code would be the most flexible if converted to a regular driver. +However there is already another driver - Exynos ASV (Adaptive Supply +Voltage) - which binds to the device node of Chip ID. + +The solution is to convert the Exynos Chip ID to a built in driver and +merge the Exynos ASV into it. + +This has several benefits: +1. Although the Exynos ASV driver binds to a device node present in all + Exynos DTS (generic compatible), it fails to probe except on the + supported ones (only Exynos5422). This means that the regular boot + process has a planned/normal device probe failure. + + Merging the ASV into Chip ID will remove this probe failure because + the final driver will always bind, just with disabled ASV features. + +2. Allows to use dev_info() as the SoC bus is present (since + core_initcall). + +3. Could speed things up because of execution of Chip ID code in a SMP + environment (after bringing up secondary CPUs, unlike early_initcall), + This reduces the amount of work to be done early, when the kernel has + to bring up critical devices. + +5. Makes the Chip ID code defer-probe friendly, + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20201207190517.262051-5-krzk@kernel.org +Reviewed-by: Pankaj Dubey +Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()") +Signed-off-by: Sasha Levin +--- + arch/arm/mach-exynos/Kconfig | 1 - + drivers/soc/samsung/Kconfig | 12 +++-- + drivers/soc/samsung/Makefile | 3 +- + drivers/soc/samsung/exynos-asv.c | 45 +++++-------------- + drivers/soc/samsung/exynos-asv.h | 2 + + drivers/soc/samsung/exynos-chipid.c | 69 ++++++++++++++++++++--------- + 6 files changed, 67 insertions(+), 65 deletions(-) + +diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig +index b5df98ee5d176..4b554cc8fa58a 100644 +--- a/arch/arm/mach-exynos/Kconfig ++++ b/arch/arm/mach-exynos/Kconfig +@@ -13,7 +13,6 @@ menuconfig ARCH_EXYNOS + select ARM_GIC + select EXYNOS_IRQ_COMBINER + select COMMON_CLK_SAMSUNG +- select EXYNOS_ASV + select EXYNOS_CHIPID + select EXYNOS_THERMAL + select EXYNOS_PMU +diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig +index fc7f48a922881..5745d7e5908e9 100644 +--- a/drivers/soc/samsung/Kconfig ++++ b/drivers/soc/samsung/Kconfig +@@ -7,21 +7,19 @@ menuconfig SOC_SAMSUNG + + if SOC_SAMSUNG + +-config EXYNOS_ASV +- bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST +- depends on (ARCH_EXYNOS && EXYNOS_CHIPID) || COMPILE_TEST +- select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS +- + # There is no need to enable these drivers for ARMv8 + config EXYNOS_ASV_ARM + bool "Exynos ASV ARMv7-specific driver extensions" if COMPILE_TEST +- depends on EXYNOS_ASV ++ depends on EXYNOS_CHIPID + + config EXYNOS_CHIPID +- bool "Exynos Chipid controller driver" if COMPILE_TEST ++ bool "Exynos ChipID controller and ASV driver" if COMPILE_TEST + depends on ARCH_EXYNOS || COMPILE_TEST ++ select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS + select MFD_SYSCON + select SOC_BUS ++ help ++ Support for Samsung Exynos SoC ChipID and Adaptive Supply Voltage. + + config EXYNOS_PMU + bool "Exynos PMU controller driver" if COMPILE_TEST +diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile +index 59e8e9453f27c..0c523a8de4ebf 100644 +--- a/drivers/soc/samsung/Makefile ++++ b/drivers/soc/samsung/Makefile +@@ -1,9 +1,8 @@ + # SPDX-License-Identifier: GPL-2.0 + +-obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o + obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o + +-obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o ++obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o exynos-asv.o + obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o + + obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \ +diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c +index 5daeadc363829..d60af8acc3916 100644 +--- a/drivers/soc/samsung/exynos-asv.c ++++ b/drivers/soc/samsung/exynos-asv.c +@@ -2,7 +2,9 @@ + /* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ ++ * Copyright (c) 2020 Krzysztof Kozlowski + * Author: Sylwester Nawrocki ++ * Author: Krzysztof Kozlowski + * + * Samsung Exynos SoC Adaptive Supply Voltage support + */ +@@ -10,12 +12,7 @@ + #include + #include + #include +-#include +-#include +-#include + #include +-#include +-#include + #include + #include + #include +@@ -111,7 +108,7 @@ static int exynos_asv_update_opps(struct exynos_asv *asv) + return 0; + } + +-static int exynos_asv_probe(struct platform_device *pdev) ++int exynos_asv_init(struct device *dev, struct regmap *regmap) + { + int (*probe_func)(struct exynos_asv *asv); + struct exynos_asv *asv; +@@ -119,21 +116,16 @@ static int exynos_asv_probe(struct platform_device *pdev) + u32 product_id = 0; + int ret, i; + +- asv = devm_kzalloc(&pdev->dev, sizeof(*asv), GFP_KERNEL); ++ asv = devm_kzalloc(dev, sizeof(*asv), GFP_KERNEL); + if (!asv) + return -ENOMEM; + +- asv->chipid_regmap = device_node_to_regmap(pdev->dev.of_node); +- if (IS_ERR(asv->chipid_regmap)) { +- dev_err(&pdev->dev, "Could not find syscon regmap\n"); +- return PTR_ERR(asv->chipid_regmap); +- } +- ++ asv->chipid_regmap = regmap; ++ asv->dev = dev; + ret = regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PRO_ID, + &product_id); + if (ret < 0) { +- dev_err(&pdev->dev, "Cannot read revision from ChipID: %d\n", +- ret); ++ dev_err(dev, "Cannot read revision from ChipID: %d\n", ret); + return -ENODEV; + } + +@@ -142,7 +134,9 @@ static int exynos_asv_probe(struct platform_device *pdev) + probe_func = exynos5422_asv_init; + break; + default: +- return -ENODEV; ++ dev_dbg(dev, "No ASV support for this SoC\n"); ++ devm_kfree(dev, asv); ++ return 0; + } + + cpu_dev = get_cpu_device(0); +@@ -150,14 +144,11 @@ static int exynos_asv_probe(struct platform_device *pdev) + if (ret < 0) + return -EPROBE_DEFER; + +- ret = of_property_read_u32(pdev->dev.of_node, "samsung,asv-bin", ++ ret = of_property_read_u32(dev->of_node, "samsung,asv-bin", + &asv->of_bin); + if (ret < 0) + asv->of_bin = -EINVAL; + +- asv->dev = &pdev->dev; +- dev_set_drvdata(&pdev->dev, asv); +- + for (i = 0; i < ARRAY_SIZE(asv->subsys); i++) + asv->subsys[i].asv = asv; + +@@ -167,17 +158,3 @@ static int exynos_asv_probe(struct platform_device *pdev) + + return exynos_asv_update_opps(asv); + } +- +-static const struct of_device_id exynos_asv_of_device_ids[] = { +- { .compatible = "samsung,exynos4210-chipid" }, +- {} +-}; +- +-static struct platform_driver exynos_asv_driver = { +- .driver = { +- .name = "exynos-asv", +- .of_match_table = exynos_asv_of_device_ids, +- }, +- .probe = exynos_asv_probe, +-}; +-module_platform_driver(exynos_asv_driver); +diff --git a/drivers/soc/samsung/exynos-asv.h b/drivers/soc/samsung/exynos-asv.h +index 3fd1f2acd9995..dcbe154db31e0 100644 +--- a/drivers/soc/samsung/exynos-asv.h ++++ b/drivers/soc/samsung/exynos-asv.h +@@ -68,4 +68,6 @@ static inline u32 exynos_asv_opp_get_frequency(const struct exynos_asv_subsys *s + return __asv_get_table_entry(&subsys->table, level, 0); + } + ++int exynos_asv_init(struct device *dev, struct regmap *regmap); ++ + #endif /* __LINUX_SOC_EXYNOS_ASV_H */ +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index 0f2de1b016a59..2ab6ce71e9be5 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -2,20 +2,28 @@ + /* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ ++ * Copyright (c) 2020 Krzysztof Kozlowski + * + * Exynos - CHIP ID support + * Author: Pankaj Dubey + * Author: Bartlomiej Zolnierkiewicz ++ * Author: Krzysztof Kozlowski ++ * ++ * Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support + */ + +-#include ++#include ++#include + #include + #include ++#include + #include + #include + #include + #include + ++#include "exynos-asv.h" ++ + static const struct exynos_soc_id { + const char *name; + unsigned int id; +@@ -45,25 +53,17 @@ static const char * __init product_id_to_soc_id(unsigned int product_id) + return NULL; + } + +-static int __init exynos_chipid_early_init(void) ++static int exynos_chipid_probe(struct platform_device *pdev) + { + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device_node *root; +- struct device_node *syscon; + struct regmap *regmap; + u32 product_id; + u32 revision; + int ret; + +- syscon = of_find_compatible_node(NULL, NULL, +- "samsung,exynos4210-chipid"); +- if (!syscon) +- return -ENODEV; +- +- regmap = device_node_to_regmap(syscon); +- of_node_put(syscon); +- ++ regmap = device_node_to_regmap(pdev->dev.of_node); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +@@ -73,7 +73,8 @@ static int __init exynos_chipid_early_init(void) + + revision = product_id & EXYNOS_REV_MASK; + +- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); ++ soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), ++ GFP_KERNEL); + if (!soc_dev_attr) + return -ENOMEM; + +@@ -83,20 +84,24 @@ static int __init exynos_chipid_early_init(void) + of_property_read_string(root, "model", &soc_dev_attr->machine); + of_node_put(root); + +- soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision); ++ soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "%x", revision); + soc_dev_attr->soc_id = product_id_to_soc_id(product_id); + if (!soc_dev_attr->soc_id) { + pr_err("Unknown SoC\n"); +- ret = -ENODEV; +- goto err; ++ return -ENODEV; + } + + /* please note that the actual registration will be deferred */ + soc_dev = soc_device_register(soc_dev_attr); +- if (IS_ERR(soc_dev)) { +- ret = PTR_ERR(soc_dev); ++ if (IS_ERR(soc_dev)) ++ return PTR_ERR(soc_dev); ++ ++ ret = exynos_asv_init(&pdev->dev, regmap); ++ if (ret) + goto err; +- } ++ ++ platform_set_drvdata(pdev, soc_dev); + + dev_info(soc_device_to_device(soc_dev), + "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", +@@ -105,9 +110,31 @@ static int __init exynos_chipid_early_init(void) + return 0; + + err: +- kfree(soc_dev_attr->revision); +- kfree(soc_dev_attr); ++ soc_device_unregister(soc_dev); ++ + return ret; + } + +-arch_initcall(exynos_chipid_early_init); ++static int exynos_chipid_remove(struct platform_device *pdev) ++{ ++ struct soc_device *soc_dev = platform_get_drvdata(pdev); ++ ++ soc_device_unregister(soc_dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id exynos_chipid_of_device_ids[] = { ++ { .compatible = "samsung,exynos4210-chipid" }, ++ {} ++}; ++ ++static struct platform_driver exynos_chipid_driver = { ++ .driver = { ++ .name = "exynos-chipid", ++ .of_match_table = exynos_chipid_of_device_ids, ++ }, ++ .probe = exynos_chipid_probe, ++ .remove = exynos_chipid_remove, ++}; ++builtin_platform_driver(exynos_chipid_driver); +-- +2.39.5 + diff --git a/queue-5.10/soc-samsung-exynos-chipid-initialize-later-with-arch.patch b/queue-5.10/soc-samsung-exynos-chipid-initialize-later-with-arch.patch new file mode 100644 index 0000000000..9e341f86d5 --- /dev/null +++ b/queue-5.10/soc-samsung-exynos-chipid-initialize-later-with-arch.patch @@ -0,0 +1,55 @@ +From 5d8266c978cf8b7ac0930fcf1fc70a5d15541e47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Dec 2020 21:59:55 +0200 +Subject: soc: samsung: exynos-chipid: initialize later - with arch_initcall + +From: Krzysztof Kozlowski + +[ Upstream commit 3b4c362e5ef102ca2d70d33f4e8cf0780053a7db ] + +The Exynos ChipID driver on Exynos SoCs has only informational +purpose - to expose the SoC device in sysfs. No other drivers +depend on it so there is really no benefit of initializing it early. + +Instead, initialize everything with arch_initcall which: +1. Allows to use dev_info() as the SoC bus is present (since + core_initcall), +2. Could speed things up because of execution in a SMP environment + (after bringing up secondary CPUs, unlike early_initcall), +3. Reduces the amount of work to be done early, when the kernel has to + bring up critical devices. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20201202195955.128633-2-krzk@kernel.org +Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()") +Signed-off-by: Sasha Levin +--- + drivers/soc/samsung/exynos-chipid.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index 8d4d050869068..0f2de1b016a59 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -98,9 +98,9 @@ static int __init exynos_chipid_early_init(void) + goto err; + } + +- /* it is too early to use dev_info() here (soc_dev is NULL) */ +- pr_info("soc soc0: Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", +- soc_dev_attr->soc_id, product_id, revision); ++ dev_info(soc_device_to_device(soc_dev), ++ "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", ++ soc_dev_attr->soc_id, product_id, revision); + + return 0; + +@@ -110,4 +110,4 @@ static int __init exynos_chipid_early_init(void) + return ret; + } + +-early_initcall(exynos_chipid_early_init); ++arch_initcall(exynos_chipid_early_init); +-- +2.39.5 + diff --git a/queue-5.10/soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch b/queue-5.10/soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch new file mode 100644 index 0000000000..d14c9ad925 --- /dev/null +++ b/queue-5.10/soc-samsung-exynos-chipid-pass-revision-reg-offsets.patch @@ -0,0 +1,196 @@ +From 2c0af2c4721c4f25b917681cb1eaeba5064a5489 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Oct 2021 16:35:06 +0300 +Subject: soc: samsung: exynos-chipid: Pass revision reg offsets + +From: Sam Protsenko + +[ Upstream commit c072c4ef7ef09e1d6470c48cf52570487589b76a ] + +Old Exynos SoCs have both Product ID and Revision ID in one single +register, while new SoCs tend to have two separate registers for those +IDs. Implement handling of both cases by passing Revision ID register +offsets in driver data. + +Previously existing macros for Exynos4210 (removed in this patch) were +incorrect: + + #define EXYNOS_SUBREV_MASK (0xf << 4) + #define EXYNOS_MAINREV_MASK (0xf << 0) + +Actual format of PRO_ID register in Exynos4210 (offset 0x0): + + [31:12] Product ID + [9:8] Package information + [7:4] Main Revision Number + [3:0] Sub Revision Number + +This patch doesn't change the behavior on existing platforms, so +'/sys/devices/soc0/revision' will show the same string as before. + +Signed-off-by: Sam Protsenko +Tested-by: Henrik Grimler +Link: https://lore.kernel.org/r/20211014133508.1210-1-semen.protsenko@linaro.org +Signed-off-by: Krzysztof Kozlowski +Stable-dep-of: c8222ef6cf29 ("soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()") +Signed-off-by: Sasha Levin +--- + drivers/soc/samsung/exynos-chipid.c | 69 +++++++++++++++++++---- + include/linux/soc/samsung/exynos-chipid.h | 6 +- + 2 files changed, 60 insertions(+), 15 deletions(-) + +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index 2b02af5d2faff..a2d163a1b4e11 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -24,6 +25,17 @@ + + #include "exynos-asv.h" + ++struct exynos_chipid_variant { ++ unsigned int rev_reg; /* revision register offset */ ++ unsigned int main_rev_shift; /* main revision offset in rev_reg */ ++ unsigned int sub_rev_shift; /* sub revision offset in rev_reg */ ++}; ++ ++struct exynos_chipid_info { ++ u32 product_id; ++ u32 revision; ++}; ++ + static const struct exynos_soc_id { + const char *name; + unsigned int id; +@@ -48,31 +60,57 @@ static const char * __init product_id_to_soc_id(unsigned int product_id) + int i; + + for (i = 0; i < ARRAY_SIZE(soc_ids); i++) +- if ((product_id & EXYNOS_MASK) == soc_ids[i].id) ++ if (product_id == soc_ids[i].id) + return soc_ids[i].name; + return NULL; + } + ++static int exynos_chipid_get_chipid_info(struct regmap *regmap, ++ const struct exynos_chipid_variant *data, ++ struct exynos_chipid_info *soc_info) ++{ ++ int ret; ++ unsigned int val, main_rev, sub_rev; ++ ++ ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &val); ++ if (ret < 0) ++ return ret; ++ soc_info->product_id = val & EXYNOS_MASK; ++ ++ if (data->rev_reg != EXYNOS_CHIPID_REG_PRO_ID) { ++ ret = regmap_read(regmap, data->rev_reg, &val); ++ if (ret < 0) ++ return ret; ++ } ++ main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK; ++ sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK; ++ soc_info->revision = (main_rev << EXYNOS_REV_PART_SHIFT) | sub_rev; ++ ++ return 0; ++} ++ + static int exynos_chipid_probe(struct platform_device *pdev) + { ++ const struct exynos_chipid_variant *drv_data; ++ struct exynos_chipid_info soc_info; + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device_node *root; + struct regmap *regmap; +- u32 product_id; +- u32 revision; + int ret; + ++ drv_data = of_device_get_match_data(&pdev->dev); ++ if (!drv_data) ++ return -EINVAL; ++ + regmap = device_node_to_regmap(pdev->dev.of_node); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +- ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id); ++ ret = exynos_chipid_get_chipid_info(regmap, drv_data, &soc_info); + if (ret < 0) + return ret; + +- revision = product_id & EXYNOS_REV_MASK; +- + soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), + GFP_KERNEL); + if (!soc_dev_attr) +@@ -85,8 +123,8 @@ static int exynos_chipid_probe(struct platform_device *pdev) + of_node_put(root); + + soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, +- "%x", revision); +- soc_dev_attr->soc_id = product_id_to_soc_id(product_id); ++ "%x", soc_info.revision); ++ soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id); + if (!soc_dev_attr->soc_id) { + pr_err("Unknown SoC\n"); + return -ENODEV; +@@ -104,7 +142,7 @@ static int exynos_chipid_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, soc_dev); + + dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", +- soc_dev_attr->soc_id, product_id, revision); ++ soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision); + + return 0; + +@@ -123,9 +161,18 @@ static int exynos_chipid_remove(struct platform_device *pdev) + return 0; + } + ++static const struct exynos_chipid_variant exynos4210_chipid_drv_data = { ++ .rev_reg = 0x0, ++ .main_rev_shift = 4, ++ .sub_rev_shift = 0, ++}; ++ + static const struct of_device_id exynos_chipid_of_device_ids[] = { +- { .compatible = "samsung,exynos4210-chipid" }, +- {} ++ { ++ .compatible = "samsung,exynos4210-chipid", ++ .data = &exynos4210_chipid_drv_data, ++ }, ++ { } + }; + + static struct platform_driver exynos_chipid_driver = { +diff --git a/include/linux/soc/samsung/exynos-chipid.h b/include/linux/soc/samsung/exynos-chipid.h +index 8bca6763f99c1..62f0e25310687 100644 +--- a/include/linux/soc/samsung/exynos-chipid.h ++++ b/include/linux/soc/samsung/exynos-chipid.h +@@ -9,10 +9,8 @@ + #define __LINUX_SOC_EXYNOS_CHIPID_H + + #define EXYNOS_CHIPID_REG_PRO_ID 0x00 +-#define EXYNOS_SUBREV_MASK (0xf << 4) +-#define EXYNOS_MAINREV_MASK (0xf << 0) +-#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \ +- EXYNOS_MAINREV_MASK) ++#define EXYNOS_REV_PART_MASK 0xf ++#define EXYNOS_REV_PART_SHIFT 4 + #define EXYNOS_MASK 0xfffff000 + + #define EXYNOS_CHIPID_REG_PKG_ID 0x04 +-- +2.39.5 + diff --git a/queue-5.10/tracing-allow-synthetic-events-to-pass-around-stackt.patch b/queue-5.10/tracing-allow-synthetic-events-to-pass-around-stackt.patch new file mode 100644 index 0000000000..161ce83f3f --- /dev/null +++ b/queue-5.10/tracing-allow-synthetic-events-to-pass-around-stackt.patch @@ -0,0 +1,282 @@ +From f85226030cd1bf402c8fde3022124a03c07b1db1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Jan 2023 10:21:28 -0500 +Subject: tracing: Allow synthetic events to pass around stacktraces + +From: Steven Rostedt (Google) + +[ Upstream commit 00cf3d672a9dd409418647e9f98784c339c3ff63 ] + +Allow a stacktrace from one event to be displayed by the end event of a +synthetic event. This is very useful when looking for the longest latency +of a sleep or something blocked on I/O. + + # cd /sys/kernel/tracing/ + # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events + # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 1||prev_state == 2' > events/sched/sched_switch/trigger + # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger + +The above creates a "block_lat" synthetic event that take the stacktrace of +when a task schedules out in either the interruptible or uninterruptible +states, and on a new per process max $delta (the time it was scheduled +out), will print the process id and the stacktrace. + + # echo 1 > events/synthetic/block_lat/enable + # cat trace + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + kworker/u16:0-767 [006] d..4. 560.645045: block_lat: pid=767 delta=66 stack=STACK: + => __schedule + => schedule + => pipe_read + => vfs_read + => ksys_read + => do_syscall_64 + => 0x966000aa + + -0 [003] d..4. 561.132117: block_lat: pid=0 delta=413787 stack=STACK: + => __schedule + => schedule + => schedule_hrtimeout_range_clock + => do_sys_poll + => __x64_sys_poll + => do_syscall_64 + => 0x966000aa + + <...>-153 [006] d..4. 562.068407: block_lat: pid=153 delta=54 stack=STACK: + => __schedule + => schedule + => io_schedule + => rq_qos_wait + => wbt_wait + => __rq_qos_throttle + => blk_mq_submit_bio + => submit_bio_noacct_nocheck + => ext4_bio_write_page + => mpage_submit_page + => mpage_process_page_bufs + => mpage_prepare_extent_to_map + => ext4_do_writepages + => ext4_writepages + => do_writepages + => __writeback_single_inode + +Link: https://lkml.kernel.org/r/20230117152236.010941267@goodmis.org + +Cc: Masami Hiramatsu +Cc: Andrew Morton +Cc: Tom Zanussi +Cc: Ross Zwisler +Cc: Ching-lin Yu +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: 4d38328eb442 ("tracing: Fix synth event printk format for str fields") +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 4 ++ + kernel/trace/trace_events_hist.c | 7 ++- + kernel/trace/trace_events_synth.c | 80 ++++++++++++++++++++++++++++++- + kernel/trace/trace_synth.h | 1 + + 4 files changed, 87 insertions(+), 5 deletions(-) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 7c90872f2435d..f47938d8401a2 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -109,6 +109,10 @@ enum trace_type { + unlikely(__ret_warn_once); \ + }) + ++#define HIST_STACKTRACE_DEPTH 16 ++#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) ++#define HIST_STACKTRACE_SKIP 5 ++ + /* + * syscalls are special, and need special handling, this is why + * they are not included in trace_entries.h +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 059a106e62bec..a0342b45a06da 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -282,10 +282,6 @@ DEFINE_HIST_FIELD_FN(u8); + #define for_each_hist_key_field(i, hist_data) \ + for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++) + +-#define HIST_STACKTRACE_DEPTH 16 +-#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) +-#define HIST_STACKTRACE_SKIP 5 +- + #define HITCOUNT_IDX 0 + #define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE) + +@@ -3356,6 +3352,9 @@ static int check_synth_field(struct synth_event *event, + && field->is_dynamic) + return 0; + ++ if (strstr(hist_field->type, "long[") && field->is_stack) ++ return 0; ++ + if (strcmp(field->type, hist_field->type) != 0) { + if (field->size != hist_field->size || + (!field->is_string && field->is_signed != hist_field->is_signed)) +diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c +index e43426aa12830..4878758ceea2a 100644 +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -162,6 +162,14 @@ static int synth_field_is_string(char *type) + return false; + } + ++static int synth_field_is_stack(char *type) ++{ ++ if (strstr(type, "long[") != NULL) ++ return true; ++ ++ return false; ++} ++ + static int synth_field_string_size(char *type) + { + char buf[4], *end, *start; +@@ -237,6 +245,8 @@ static int synth_field_size(char *type) + size = sizeof(gfp_t); + else if (synth_field_is_string(type)) + size = synth_field_string_size(type); ++ else if (synth_field_is_stack(type)) ++ size = 0; + + return size; + } +@@ -281,6 +291,8 @@ static const char *synth_field_fmt(char *type) + fmt = "%x"; + else if (synth_field_is_string(type)) + fmt = "%.*s"; ++ else if (synth_field_is_stack(type)) ++ fmt = "%s"; + + return fmt; + } +@@ -360,6 +372,23 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter, + i == se->n_fields - 1 ? "" : " "); + n_u64 += STR_VAR_LEN_MAX / sizeof(u64); + } ++ } else if (se->fields[i]->is_stack) { ++ u32 offset, data_offset, len; ++ unsigned long *p, *end; ++ ++ offset = (u32)entry->fields[n_u64]; ++ data_offset = offset & 0xffff; ++ len = offset >> 16; ++ ++ p = (void *)entry + data_offset; ++ end = (void *)p + len - (sizeof(long) - 1); ++ ++ trace_seq_printf(s, "%s=STACK:\n", se->fields[i]->name); ++ ++ for (; *p && p < end; p++) ++ trace_seq_printf(s, "=> %pS\n", (void *)*p); ++ n_u64++; ++ + } else { + struct trace_print_flags __flags[] = { + __def_gfpflag_names, {-1, NULL} }; +@@ -427,6 +456,43 @@ static unsigned int trace_string(struct synth_trace_event *entry, + return len; + } + ++static unsigned int trace_stack(struct synth_trace_event *entry, ++ struct synth_event *event, ++ long *stack, ++ unsigned int data_size, ++ unsigned int *n_u64) ++{ ++ unsigned int len; ++ u32 data_offset; ++ void *data_loc; ++ ++ data_offset = struct_size(entry, fields, event->n_u64); ++ data_offset += data_size; ++ ++ for (len = 0; len < HIST_STACKTRACE_DEPTH; len++) { ++ if (!stack[len]) ++ break; ++ } ++ ++ /* Include the zero'd element if it fits */ ++ if (len < HIST_STACKTRACE_DEPTH) ++ len++; ++ ++ len *= sizeof(long); ++ ++ /* Find the dynamic section to copy the stack into. */ ++ data_loc = (void *)entry + data_offset; ++ memcpy(data_loc, stack, len); ++ ++ /* Fill in the field that holds the offset/len combo */ ++ data_offset |= len << 16; ++ *(u32 *)&entry->fields[*n_u64] = data_offset; ++ ++ (*n_u64)++; ++ ++ return len; ++} ++ + static notrace void trace_event_raw_event_synth(void *__data, + u64 *var_ref_vals, + unsigned int *var_ref_idx) +@@ -479,6 +545,12 @@ static notrace void trace_event_raw_event_synth(void *__data, + event->fields[i]->is_dynamic, + data_size, &n_u64); + data_size += len; /* only dynamic string increments */ ++ } if (event->fields[i]->is_stack) { ++ long *stack = (long *)(long)var_ref_vals[val_idx]; ++ ++ len = trace_stack(entry, event, stack, ++ data_size, &n_u64); ++ data_size += len; + } else { + struct synth_field *field = event->fields[i]; + u64 val = var_ref_vals[val_idx]; +@@ -541,6 +613,9 @@ static int __set_synth_event_print_fmt(struct synth_event *event, + event->fields[i]->is_dynamic) + pos += snprintf(buf + pos, LEN_OR_ZERO, + ", __get_str(%s)", event->fields[i]->name); ++ else if (event->fields[i]->is_stack) ++ pos += snprintf(buf + pos, LEN_OR_ZERO, ++ ", __get_stacktrace(%s)", event->fields[i]->name); + else + pos += snprintf(buf + pos, LEN_OR_ZERO, + ", REC->%s", event->fields[i]->name); +@@ -660,7 +735,8 @@ static struct synth_field *parse_synth_field(int argc, const char **argv, + ret = -EINVAL; + goto free; + } else if (size == 0) { +- if (synth_field_is_string(field->type)) { ++ if (synth_field_is_string(field->type) || ++ synth_field_is_stack(field->type)) { + char *type; + + len = sizeof("__data_loc ") + strlen(field->type) + 1; +@@ -691,6 +767,8 @@ static struct synth_field *parse_synth_field(int argc, const char **argv, + + if (synth_field_is_string(field->type)) + field->is_string = true; ++ else if (synth_field_is_stack(field->type)) ++ field->is_stack = true; + + field->is_signed = synth_field_signed(field->type); + out: +diff --git a/kernel/trace/trace_synth.h b/kernel/trace/trace_synth.h +index 4007fe95cf42c..077c748a8b3a6 100644 +--- a/kernel/trace/trace_synth.h ++++ b/kernel/trace/trace_synth.h +@@ -18,6 +18,7 @@ struct synth_field { + bool is_signed; + bool is_string; + bool is_dynamic; ++ bool is_stack; + }; + + struct synth_event { +-- +2.39.5 + diff --git a/queue-5.10/tracing-fix-synth-event-printk-format-for-str-fields.patch b/queue-5.10/tracing-fix-synth-event-printk-format-for-str-fields.patch new file mode 100644 index 0000000000..4c607fb9d4 --- /dev/null +++ b/queue-5.10/tracing-fix-synth-event-printk-format-for-str-fields.patch @@ -0,0 +1,46 @@ +From df3e73ad1909a8e4ae012c85b8b55abae2885bee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 16:52:02 +0000 +Subject: tracing: Fix synth event printk format for str fields + +From: Douglas Raillard + +[ Upstream commit 4d38328eb442dc06aec4350fd9594ffa6488af02 ] + +The printk format for synth event uses "%.*s" to print string fields, +but then only passes the pointer part as var arg. + +Replace %.*s with %s as the C string is guaranteed to be null-terminated. + +The output in print fmt should never have been updated as __get_str() +handles the string limit because it can access the length of the string in +the string meta data that is saved in the ring buffer. + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mathieu Desnoyers +Fixes: 8db4d6bfbbf92 ("tracing: Change synthetic event string format to limit printed length") +Link: https://lore.kernel.org/20250325165202.541088-1-douglas.raillard@arm.com +Signed-off-by: Douglas Raillard +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_events_synth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c +index 4878758ceea2a..613d45e7b608d 100644 +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -290,7 +290,7 @@ static const char *synth_field_fmt(char *type) + else if (strcmp(type, "gfp_t") == 0) + fmt = "%x"; + else if (synth_field_is_string(type)) +- fmt = "%.*s"; ++ fmt = "%s"; + else if (synth_field_is_stack(type)) + fmt = "%s"; + +-- +2.39.5 +