Changing the enable/disable sequence in commit c9b1150a68d9
("drm/atomic-helper: Re-order bridge chain pre-enable and post-disable")
has caused regressions on multiple platforms: R-Car, MCDE, Rockchip.
This is an alternate series to Linus' series:
https://lore.kernel.org/all/20251202-mcde-drm-regression-thirdfix-v6-0-f1bf…
This series first reverts the original commit and reverts a fix for
mediatek which is no longer needed. It then exposes helper functions
from DRM core, and finally implements the new sequence only in the tidss
driver.
There is one more fix in upstream for the original commit, commit
5d91394f2361 ("drm/exynos: fimd: Guard display clock control with
runtime PM calls"), but I have not reverted that one as it looks like a
valid patch in its own.
I added Cc stable v6.17+ to all patches, but I didn't add Fixes tags, as
I wasn't sure what should they point to. But I could perhaps add Fixes:
<original commit> to all of these.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen(a)ideasonboard.com>
---
Linus Walleij (1):
drm/atomic-helper: Export and namespace some functions
Tomi Valkeinen (3):
Revert "drm/atomic-helper: Re-order bridge chain pre-enable and post-disable"
Revert "drm/mediatek: dsi: Fix DSI host and panel bridge pre-enable order"
drm/tidss: Fix enable/disable order
drivers/gpu/drm/drm_atomic_helper.c | 122 ++++++++++++++----
drivers/gpu/drm/mediatek/mtk_dsi.c | 6 -
drivers/gpu/drm/tidss/tidss_kms.c | 30 ++++-
include/drm/drm_atomic_helper.h | 22 ++++
include/drm/drm_bridge.h | 249 ++++++++++--------------------------
5 files changed, 214 insertions(+), 215 deletions(-)
---
base-commit: 88e721ab978a86426aa08da520de77430fa7bb84
change-id: 20251205-drm-seq-fix-b4ed1f56604b
Best regards,
--
Tomi Valkeinen <tomi.valkeinen(a)ideasonboard.com>
The acpi_get_first_physical_node() function can return NULL, in which
case the get_device() function also returns NULL, but this value is
then dereferenced without checking,so add a check to prevent a crash.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: 7b2f3eb492da ("ALSA: hda: cs35l41: Add support for CS35L41 in HDA systems")
Cc: stable(a)vger.kernel.org
Signed-off-by: Denis Arefev <arefev(a)swemel.ru>
---
sound/hda/codecs/side-codecs/cs35l41_hda.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c
index c0f2a3ff77a1..21e00055c0c4 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c
@@ -1901,6 +1901,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
cs35l41->dacpi = adev;
physdev = get_device(acpi_get_first_physical_node(adev));
+ if (!physdev)
+ return -ENODEV;
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
if (IS_ERR(sub))
--
2.43.0
From: Maciej Wieczor-Retman <maciej.wieczor-retman(a)intel.com>
A KASAN tag mismatch, possibly causing a kernel panic, can be observed
on systems with a tag-based KASAN enabled and with multiple NUMA nodes.
It was reported on arm64 and reproduced on x86. It can be explained in
the following points:
1. There can be more than one virtual memory chunk.
2. Chunk's base address has a tag.
3. The base address points at the first chunk and thus inherits
the tag of the first chunk.
4. The subsequent chunks will be accessed with the tag from the
first chunk.
5. Thus, the subsequent chunks need to have their tag set to
match that of the first chunk.
Use the new vmalloc flag that disables random tag assignment in
__kasan_unpoison_vmalloc() - pass the same random tag to all the
vm_structs by tagging the pointers before they go inside
__kasan_unpoison_vmalloc(). Assigning a common tag resolves the pcpu
chunk address mismatch.
Fixes: 1d96320f8d53 ("kasan, vmalloc: add vmalloc tagging for SW_TAGS")
Cc: <stable(a)vger.kernel.org> # 6.1+
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman(a)intel.com>
---
Changelog v3:
- Redo the patch by using a flag instead of a new argument in
__kasan_unpoison_vmalloc() (Andrey Konovalov)
Changelog v2:
- Revise the whole patch to match the fixed refactorization from the
first patch.
Changelog v1:
- Rewrite the patch message to point at the user impact of the issue.
- Move helper to common.c so it can be compiled in all KASAN modes.
mm/kasan/common.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 1ed6289d471a..496bb2c56911 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -591,11 +591,28 @@ void __kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms,
unsigned long size;
void *addr;
int area;
+ u8 tag;
+
+ /*
+ * If KASAN_VMALLOC_KEEP_TAG was set at this point, all vms[] pointers
+ * would be unpoisoned with the KASAN_TAG_KERNEL which would disable
+ * KASAN checks down the line.
+ */
+ if (flags & KASAN_VMALLOC_KEEP_TAG) {
+ pr_warn("KASAN_VMALLOC_KEEP_TAG flag shouldn't be already set!\n");
+ return;
+ }
+
+ size = vms[0]->size;
+ addr = vms[0]->addr;
+ vms[0]->addr = __kasan_unpoison_vmalloc(addr, size, flags);
+ tag = get_tag(vms[0]->addr);
- for (area = 0 ; area < nr_vms ; area++) {
+ for (area = 1 ; area < nr_vms ; area++) {
size = vms[area]->size;
- addr = vms[area]->addr;
- vms[area]->addr = __kasan_unpoison_vmalloc(addr, size, flags);
+ addr = set_tag(vms[area]->addr, tag);
+ vms[area]->addr =
+ __kasan_unpoison_vmalloc(addr, size, flags | KASAN_VMALLOC_KEEP_TAG);
}
}
#endif
--
2.52.0
The recent refactoring of where runtime PM is enabled done in commit
f1eb4e792bb1 ("spi: spi-cadence-quadspi: Enable pm runtime earlier to
avoid imbalance") made the fact that when we do a pm_runtime_disable()
in the error paths of probe() we can trigger a runtime disable which in
turn results in duplicate clock disables. Early on in the probe function
we do a pm_runtime_get_noresume() since the probe function leaves the
device in a powered up state but in the error path we can't assume that PM
is enabled so we also manually disable everything, including clocks. This
means that when runtime PM is active both it and the probe function release
the same reference to the main clock for the IP, triggering warnings from
the clock subsystem:
[ 8.693719] clk:75:7 already disabled
[ 8.693791] WARNING: CPU: 1 PID: 185 at /usr/src/kernel/drivers/clk/clk.c:1188 clk_core_disable+0xa0/0xb
...
[ 8.694261] clk_core_disable+0xa0/0xb4 (P)
[ 8.694272] clk_disable+0x38/0x60
[ 8.694283] cqspi_probe+0x7c8/0xc5c [spi_cadence_quadspi]
[ 8.694309] platform_probe+0x5c/0xa4
Avoid this confused ownership by moving the pm_runtime_get_noresume() to
after the last point at which the probe() function can fail.
Reported-by: Francesco Dolcini <francesco(a)dolcini.it>
Closes: https://lore.kernel.org/r/20251201072844.GA6785@francesco-nb
Signed-off-by: Mark Brown <broonie(a)kernel.org>
Cc: stable(a)vger.kernel.org
---
drivers/spi/spi-cadence-quadspi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index af6d050da1c8..0833b6f666d0 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -1985,7 +1985,6 @@ static int cqspi_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(dev);
- pm_runtime_get_noresume(dev);
}
ret = cqspi_setup_flash(cqspi);
@@ -2012,6 +2011,7 @@ static int cqspi_probe(struct platform_device *pdev)
}
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
+ pm_runtime_get_noresume(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
---
base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
change-id: 20251202-spi-cadence-qspi-runtime-pm-imbalance-657740cf7eae
Best regards,
--
Mark Brown <broonie(a)kernel.org>
Xorg fails to start with defaults on AMD KV260, /var/log/Xorg.0.log:
[ 23.491] (II) Loading /usr/lib/xorg/modules/drivers/fbdev_drv.so
[ 23.491] (II) Module fbdev: vendor="X.Org Foundation"
[ 23.491] compiled for 1.21.1.18, module version = 0.5.1
[ 23.491] Module class: X.Org Video Driver
[ 23.491] ABI class: X.Org Video Driver, version 25.2
[ 23.491] (II) modesetting: Driver for Modesetting Kernel Drivers:
kms
[ 23.491] (II) FBDEV: driver for framebuffer: fbdev
[ 23.510] (II) modeset(0): using drv /dev/dri/card1
[ 23.511] (WW) Falling back to old probe method for fbdev
[ 23.511] (II) Loading sub module "fbdevhw"
[ 23.511] (II) LoadModule: "fbdevhw"
[ 23.511] (II) Loading /usr/lib/xorg/modules/libfbdevhw.so
[ 23.511] (II) Module fbdevhw: vendor="X.Org Foundation"
[ 23.511] compiled for 1.21.1.18, module version = 0.0.2
[ 23.511] ABI class: X.Org Video Driver, version 25.2
[ 23.512] (II) modeset(0): Creating default Display subsection in
Screen section
"Default Screen Section" for depth/fbbpp 24/32
[ 23.512] (==) modeset(0): Depth 24, (==) framebuffer bpp 32
[ 23.512] (==) modeset(0): RGB weight 888
[ 23.512] (==) modeset(0): Default visual is TrueColor
...
[ 23.911] (II) Loading sub module "fb"
[ 23.911] (II) LoadModule: "fb"
[ 23.911] (II) Module "fb" already built-in
[ 23.911] (II) UnloadModule: "fbdev"
[ 23.911] (II) Unloading fbdev
[ 23.912] (II) UnloadSubModule: "fbdevhw"
[ 23.912] (II) Unloading fbdevhw
[ 24.238] (==) modeset(0): Backing store enabled
[ 24.238] (==) modeset(0): Silken mouse enabled
[ 24.249] (II) modeset(0): Initializing kms color map for depth 24, 8
bpc.
[ 24.250] (==) modeset(0): DPMS enabled
[ 24.250] (II) modeset(0): [DRI2] Setup complete
[ 24.250] (II) modeset(0): [DRI2] DRI driver: kms_swrast
[ 24.250] (II) modeset(0): [DRI2] VDPAU driver: kms_swrast
...
[ 24.770] (II) modeset(0): Disabling kernel dirty updates, not
required.
[ 24.770] (EE) modeset(0): failed to set mode: Invalid argument
xorg tries to use 24 and 32 bpp which pass on the fb API but which
don't actually work on AMD KV260 when Xorg starts. As a workaround
Xorg config can set color depth to 16 using /etc/X11/xorg.conf snippet:
Section "Screen"
Identifier "Default Screen"
Monitor "Configured Monitor"
Device "Configured Video Device"
DefaultDepth 16
EndSection
But this is cumbersome on images meant for multiple different arm64
devices and boards. So instead set 16 bpp as preferred depth
in zynqmp_kms fb driver which is used by Xorg in the logic to find
out a working depth.
Now Xorg startup and bpp query using fb API works and HDMI display
shows graphics. /var/log/Xorg.0.log shows:
[ 23.219] (II) LoadModule: "fbdev"
[ 23.219] (II) Loading /usr/lib/xorg/modules/drivers/fbdev_drv.so
[ 23.219] (II) Module fbdev: vendor="X.Org Foundation"
[ 23.219] compiled for 1.21.1.18, module version = 0.5.1
[ 23.219] Module class: X.Org Video Driver
[ 23.219] ABI class: X.Org Video Driver, version 25.2
[ 23.219] (II) modesetting: Driver for Modesetting Kernel Drivers:
kms
[ 23.219] (II) FBDEV: driver for framebuffer: fbdev
[ 23.238] (II) modeset(0): using drv /dev/dri/card1
[ 23.238] (WW) Falling back to old probe method for fbdev
[ 23.238] (II) Loading sub module "fbdevhw"
[ 23.238] (II) LoadModule: "fbdevhw"
[ 23.239] (II) Loading /usr/lib/xorg/modules/libfbdevhw.so
[ 23.239] (II) Module fbdevhw: vendor="X.Org Foundation"
[ 23.239] compiled for 1.21.1.18, module version = 0.0.2
[ 23.239] ABI class: X.Org Video Driver, version 25.2
[ 23.240] (II) modeset(0): Creating default Display subsection in Screen section
"Default Screen Section" for depth/fbbpp 16/16
[ 23.240] (==) modeset(0): Depth 16, (==) framebuffer bpp 16
[ 23.240] (==) modeset(0): RGB weight 565
[ 23.240] (==) modeset(0): Default visual is TrueColor
...
[ 24.015] (==) modeset(0): Backing store enabled
[ 24.015] (==) modeset(0): Silken mouse enabled
[ 24.027] (II) modeset(0): Initializing kms color map for depth 16, 6 bpc.
[ 24.028] (==) modeset(0): DPMS enabled
[ 24.028] (II) modeset(0): [DRI2] Setup complete
[ 24.028] (II) modeset(0): [DRI2] DRI driver: kms_swrast
[ 24.028] (II) modeset(0): [DRI2] VDPAU driver: kms_swrast
Cc: Bill Mills <bill.mills(a)linaro.org>
Cc: Ilias Apalodimas <ilias.apalodimas(a)linaro.org>
Cc: Anatoliy Klymenko <anatoliy.klymenko(a)amd.com>
Cc: stable(a)vger.kernel.org
Signed-off-by: Mikko Rapeli <mikko.rapeli(a)linaro.org>
---
drivers/gpu/drm/xlnx/zynqmp_kms.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
index ccc35cacd10cb..a42192c827af0 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -506,6 +506,7 @@ int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
drm->mode_config.min_height = 0;
drm->mode_config.max_width = ZYNQMP_DISP_MAX_WIDTH;
drm->mode_config.max_height = ZYNQMP_DISP_MAX_HEIGHT;
+ drm->mode_config.preferred_depth = 16;
ret = drm_vblank_init(drm, 1);
if (ret)
--
2.34.1
From: Anatoliy Klymenko <anatoliy.klymenko(a)amd.com>
Use RG16 buffer format for fbdev emulation. Fbdev backend is being used
by Mali 400 userspace driver which expects 16 bit RGB pixel color format.
This change should not affect console or other fbdev applications as we
still have plenty of colors left.
Cc: Bill Mills <bill.mills(a)linaro.org>
Cc: Ilias Apalodimas <ilias.apalodimas(a)linaro.org>
Cc: stable(a)vger.kernel.org
Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko(a)amd.com>
Signed-off-by: Mikko Rapeli <mikko.rapeli(a)linaro.org>
---
drivers/gpu/drm/xlnx/zynqmp_kms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
index 2bee0a2275ede..ccc35cacd10cb 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -525,7 +525,7 @@ int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
goto err_poll_fini;
/* Initialize fbdev generic emulation. */
- drm_client_setup_with_fourcc(drm, DRM_FORMAT_RGB888);
+ drm_client_setup_with_fourcc(drm, DRM_FORMAT_RGB565);
return 0;
--
2.34.1
Originally, the notification for connector change will be enabled after
the first read of the connector status. Therefore, if the event happens
during this window, it will be missing and make the status unsynced.
Get the connector status only after enabling the notification for
connector change to ensure the status is synced.
Fixes: c1b0bc2dabfa ("usb: typec: Add support for UCSI interface")
Cc: stable(a)vger.kernel.org # v4.13+
Signed-off-by: Hsin-Te Yuan <yuanhsinte(a)chromium.org>
---
Changes in v6:
- Free the locks in error path.
- Link to v5: https://lore.kernel.org/r/20251205-ucsi-v5-1-488eb89bc9b8@chromium.org
Changes in v5:
- Hold the lock of each connector during the initialization to avoid
race condition between initialization and other event handler
- Add Fixes tag
- Link to v4: https://lore.kernel.org/r/20251125-ucsi-v4-1-8c94568ddaa5@chromium.org
Changes in v4:
- Handle a single connector in ucsi_init_port() and call it in a loop
- Link to v3: https://lore.kernel.org/r/20251121-ucsi-v3-1-b1047ca371b8@chromium.org
Changes in v3:
- Seperate the status checking part into a new function called
ucsi_init_port() and call it after enabling the notifications
- Link to v2: https://lore.kernel.org/r/20251118-ucsi-v2-1-d314d50333e2@chromium.org
Changes in v2:
- Remove unnecessary braces.
- Link to v1: https://lore.kernel.org/r/20251117-ucsi-v1-1-1dcbc5ea642b@chromium.org
---
drivers/usb/typec/ucsi/ucsi.c | 131 +++++++++++++++++++++++-------------------
1 file changed, 73 insertions(+), 58 deletions(-)
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 3f568f790f39b0271667e80816270274b8dd3008..3a0471fa4cc980c0512bc71776e3984e6cd2cdb7 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1560,11 +1560,70 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
return NULL;
}
+static void ucsi_init_port(struct ucsi *ucsi, struct ucsi_connector *con)
+{
+ enum usb_role u_role = USB_ROLE_NONE;
+ int ret;
+
+ /* Get the status */
+ ret = ucsi_get_connector_status(con, false);
+ if (ret) {
+ dev_err(ucsi->dev, "con%d: failed to get status\n", con->num);
+ return;
+ }
+
+ if (ucsi->ops->connector_status)
+ ucsi->ops->connector_status(con);
+
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
+ case UCSI_CONSTAT_PARTNER_TYPE_UFP:
+ case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
+ u_role = USB_ROLE_HOST;
+ fallthrough;
+ case UCSI_CONSTAT_PARTNER_TYPE_CABLE:
+ typec_set_data_role(con->port, TYPEC_HOST);
+ break;
+ case UCSI_CONSTAT_PARTNER_TYPE_DFP:
+ u_role = USB_ROLE_DEVICE;
+ typec_set_data_role(con->port, TYPEC_DEVICE);
+ break;
+ default:
+ break;
+ }
+
+ /* Check if there is already something connected */
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR));
+ ucsi_register_partner(con);
+ ucsi_pwr_opmode_change(con);
+ ucsi_port_psy_changed(con);
+ if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
+ ucsi_get_partner_identity(con);
+ if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
+ ucsi_check_cable(con);
+ }
+
+ /* Only notify USB controller if partner supports USB data */
+ if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
+ u_role = USB_ROLE_NONE;
+
+ ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
+ if (ret)
+ dev_err(ucsi->dev, "con:%d: failed to set usb role:%d\n",
+ con->num, u_role);
+
+ if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
+ ucsi_register_device_pdos(con);
+ ucsi_get_src_pdos(con);
+ ucsi_check_altmodes(con);
+ ucsi_check_connector_capability(con);
+ }
+}
+
static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
{
struct typec_capability *cap = &con->typec_cap;
enum typec_accessory *accessory = cap->accessory;
- enum usb_role u_role = USB_ROLE_NONE;
u64 command;
char *name;
int ret;
@@ -1659,62 +1718,6 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
goto out;
}
- /* Get the status */
- ret = ucsi_get_connector_status(con, false);
- if (ret) {
- dev_err(ucsi->dev, "con%d: failed to get status\n", con->num);
- goto out;
- }
-
- if (ucsi->ops->connector_status)
- ucsi->ops->connector_status(con);
-
- switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
- case UCSI_CONSTAT_PARTNER_TYPE_UFP:
- case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
- u_role = USB_ROLE_HOST;
- fallthrough;
- case UCSI_CONSTAT_PARTNER_TYPE_CABLE:
- typec_set_data_role(con->port, TYPEC_HOST);
- break;
- case UCSI_CONSTAT_PARTNER_TYPE_DFP:
- u_role = USB_ROLE_DEVICE;
- typec_set_data_role(con->port, TYPEC_DEVICE);
- break;
- default:
- break;
- }
-
- /* Check if there is already something connected */
- if (UCSI_CONSTAT(con, CONNECTED)) {
- typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR));
- ucsi_register_partner(con);
- ucsi_pwr_opmode_change(con);
- ucsi_port_psy_changed(con);
- if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
- ucsi_get_partner_identity(con);
- if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
- ucsi_check_cable(con);
- }
-
- /* Only notify USB controller if partner supports USB data */
- if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
- u_role = USB_ROLE_NONE;
-
- ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
- if (ret) {
- dev_err(ucsi->dev, "con:%d: failed to set usb role:%d\n",
- con->num, u_role);
- ret = 0;
- }
-
- if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
- ucsi_register_device_pdos(con);
- ucsi_get_src_pdos(con);
- ucsi_check_altmodes(con);
- ucsi_check_connector_capability(con);
- }
-
trace_ucsi_register_port(con->num, con);
out:
@@ -1823,16 +1826,28 @@ static int ucsi_init(struct ucsi *ucsi)
goto err_unregister;
}
+ /* Delay other interactions with each connector until ucsi_init_port is done */
+ for (i = 0; i < ucsi->cap.num_connectors; i++)
+ mutex_lock(&connector[i].lock);
+
/* Enable all supported notifications */
ntfy = ucsi_get_supported_notifications(ucsi);
command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
ret = ucsi_send_command(ucsi, command, NULL, 0);
- if (ret < 0)
+ if (ret < 0) {
+ for (i = 0; i < ucsi->cap.num_connectors; i++)
+ mutex_unlock(&connector[i].lock);
goto err_unregister;
+ }
ucsi->connector = connector;
ucsi->ntfy = ntfy;
+ for (i = 0; i < ucsi->cap.num_connectors; i++) {
+ ucsi_init_port(ucsi, &connector[i]);
+ mutex_unlock(&connector[i].lock);
+ }
+
mutex_lock(&ucsi->ppm_lock);
ret = ucsi->ops->read_cci(ucsi, &cci);
mutex_unlock(&ucsi->ppm_lock);
---
base-commit: 2061f18ad76ecaddf8ed17df81b8611ea88dbddd
change-id: 20251117-ucsi-c2dfe8c006d7
Best regards,
--
Hsin-Te Yuan <yuanhsinte(a)chromium.org>
On hardware based on Toradex Verdin AM62 the recovery mechanism added by
commit ad5c6ecef27e ("drm: bridge: ti-sn65dsi83: Add error recovery
mechanism") has been reported [0] to make the display turn on and off and
and the kernel logging "Unexpected link status 0x01".
According to the report, the error recovery mechanism is triggered by the
PLL_UNLOCK error going active. Analysis suggested the board is unable to
provide the correct DSI clock neede by the SN65DSI84, to which the TI
SN65DSI84 reacts by raising the PLL_UNLOCK, while the display still works
apparently without issues.
On other hardware, where all the clocks are within the components
specifications, the PLL_UNLOCK bit does not trigger while the display is in
normal use. It can trigger for e.g. electromagnetic interference, which is
a transient event and exactly the reason why the error recovery mechanism
has been implemented.
Idelly the PLL_UNLOCK bit could be ignored when working out of
specification, but this requires to detect in software whether it triggers
because the device is working out of specification but visually correctly
for the user or for good reasons (e.g. EMI, or even because working out of
specifications but compromising the visual output).
The ongoing analysis as of this writing [1][2] has not yet found a way for
the driver to discriminate among the two cases. So as a temporary measure
mask the PLL_UNLOCK error bit unconditionally.
[0] https://lore.kernel.org/r/bhkn6hley4xrol5o3ytn343h4unkwsr26p6s6ltcwexnrsjsd…
[1] https://lore.kernel.org/all/b71e941c-fc8a-4ac1-9407-0fe7df73b412@gmail.com/
[2] https://lore.kernel.org/all/20251125103900.31750-1-francesco@dolcini.it/
Closes: https://lore.kernel.org/r/bhkn6hley4xrol5o3ytn343h4unkwsr26p6s6ltcwexnrsjsd…
Cc: stable(a)vger.kernel.org # 6.15+
Co-developed-by: Hervé Codina <herve.codina(a)bootlin.com>
Signed-off-by: Hervé Codina <herve.codina(a)bootlin.com>
Signed-off-by: Luca Ceresoli <luca.ceresoli(a)bootlin.com>
---
Francesco, Emanuele, João: can you please apply this patch and report
whether the display on the affected boards gets back to working as before?
Cc: João Paulo Gonçalves <jpaulo.silvagoncalves(a)gmail.com>
Cc: Francesco Dolcini <francesco(a)dolcini.it>
Cc: Emanuele Ghidoli <ghidoliemanuele(a)gmail.com>
---
drivers/gpu/drm/bridge/ti-sn65dsi83.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 033c44326552..fffb47b62f43 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -429,7 +429,14 @@ static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
*/
ret = regmap_read(ctx->regmap, REG_IRQ_STAT, &irq_stat);
- if (ret || irq_stat) {
+
+ /*
+ * Some hardware (Toradex Verdin AM62) is known to report the
+ * PLL_UNLOCK error interrupt while working without visible
+ * problems. In lack of a reliable way to discriminate such cases
+ * from user-visible PLL_UNLOCK cases, ignore that bit entirely.
+ */
+ if (ret || irq_stat & ~REG_IRQ_STAT_CHA_PLL_UNLOCK) {
/*
* IRQ acknowledged is not always possible (the bridge can be in
* a state where it doesn't answer anymore). To prevent an
@@ -654,7 +661,7 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
if (ctx->irq) {
/* Enable irq to detect errors */
regmap_write(ctx->regmap, REG_IRQ_GLOBAL, REG_IRQ_GLOBAL_IRQ_EN);
- regmap_write(ctx->regmap, REG_IRQ_EN, 0xff);
+ regmap_write(ctx->regmap, REG_IRQ_EN, 0xff & ~REG_IRQ_EN_CHA_PLL_UNLOCK_EN);
} else {
/* Use the polling task */
sn65dsi83_monitor_start(ctx);
---
base-commit: c884ee70b15a8d63184d7c1e02eba99676a6fcf7
change-id: 20251126-drm-ti-sn65dsi83-ignore-pll-unlock-4a28aa29eb5c
Best regards,
--
Luca Ceresoli <luca.ceresoli(a)bootlin.com>