Skip to content

Commit 439bdef

Browse files
committed
d4xx: defer SERDES pipe release and remove serializer init from light path
The previous commit (8b6430d) made SERDES recovery conditional but still called max9295_init_settings() on the light path and eagerly released deserializer pipes in Step 2. Both cause IMU test failures (extrinsics-imu, intrinsics-motion, d400-mipi-motion): 1. max9295_init_settings() at ~22ms post-0xDEAD gets overwritten by the D457 FW which continues reconfiguring the MAX9295 serializer for ~50-100ms after reporting ready. The FW's final state does not configure pipe 3 (IMU), so IMU streaming breaks. 2. Eager release_pipe() during HW reset invalidation frees deserializer pipe slots immediately. Re-allocation in ds5_configure() then races with the FW's ongoing serializer init. Fix: match v1.0.1.33's proven zero-touch approach: - Remove max9295_init_settings() from the light path entirely. The FW's natural serializer config is sufficient when the GMSL link recovers on its own. ds5_setup_pipeline() writes per-pipe settings at stream-start time, seconds later, on top of the FW's stable state. - Defer pipe release from ds5_invalidate_sensor() / Step 2 to ds5_configure(). Clear pipe_data_type to force ds5_configure() into the re-allocation path, where it release-then-reallocates with the FW fully initialized. - Keep full SERDES recovery (init_settings + stability + Phase 2) for the broken-link case (D401, edge cases).
1 parent 8b6430d commit 439bdef

1 file changed

Lines changed: 32 additions & 49 deletions

File tree

kernel/realsense/d4xx.c

Lines changed: 32 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,14 +1756,13 @@ static struct ds5_sensor *ds5_get_active_sensor(struct ds5 *state)
17561756
static void ds5_invalidate_sensor(struct ds5 *state, struct ds5_sensor *sensor)
17571757
{
17581758
ds5_config_cache_clear(sensor);
1759-
#ifdef CONFIG_VIDEO_D4XX_SERDES
1760-
if (sensor->pipe_id >= 0 && state->dser_dev) {
1761-
mutex_lock(&serdes_lock__);
1762-
state->dser_ops->release_pipe(state->dser_dev, sensor->pipe_id);
1763-
mutex_unlock(&serdes_lock__);
1764-
}
1765-
#endif
1766-
sensor->pipe_id = PIPE_NOT_CONFIGURED;
1759+
/* Do NOT release SERDES pipes or clear pipe_id here.
1760+
* Preserve the existing pipe_id so that ds5_configure() can
1761+
* release-then-reallocate the pipe at stream-start time, when
1762+
* the camera FW has finished its post-boot serializer init.
1763+
* Clearing pipe_data_type forces ds5_configure() to enter the
1764+
* re-allocation path (data_type mismatch triggers pipe setup).
1765+
*/
17671766
sensor->pipe_data_type1 = 0;
17681767
sensor->pipe_data_type2 = 0;
17691768
sensor->pipe_vc_id = 0;
@@ -2720,11 +2719,18 @@ static int ds5_hw_reset_with_recovery(struct ds5 *state)
27202719
}
27212720
#endif
27222721

2723-
/* 2. Invalidate sensor state and release SERDES pipes.
2722+
/* 2. Invalidate sensor state (defer SERDES pipe release).
27242723
* After HW reset the device loses all configuration, so driver
27252724
* state must be brought in sync. Clear streaming flags so that
27262725
* ds5_mux_s_stream() won't silently skip the next stream-start.
27272726
* Covers this instance AND all peer instances of the same camera.
2727+
*
2728+
* Do NOT release SERDES pipes here — the D457 FW is still
2729+
* reconfiguring the MAX9295 serializer after reporting 0xDEAD.
2730+
* Releasing + re-allocating pipes now would race with FW init.
2731+
* Instead, clear pipe_data_type to force ds5_configure() to
2732+
* release-then-reallocate at stream-start time, when the FW
2733+
* has long finished its init (matching v1.0.1.33 behavior).
27282734
*/
27292735
{
27302736
struct ds5_sensor *active = ds5_get_active_sensor(state);
@@ -2733,18 +2739,6 @@ static int ds5_hw_reset_with_recovery(struct ds5 *state)
27332739
ds5_config_cache_clear(active);
27342740
active->streaming = false;
27352741
#ifdef CONFIG_VIDEO_D4XX_SERDES
2736-
if (active->pipe_id >= 0 && state->dser_dev) {
2737-
int release_ret;
2738-
2739-
mutex_lock(&serdes_lock__);
2740-
release_ret = state->dser_ops->release_pipe(
2741-
state->dser_dev, active->pipe_id);
2742-
mutex_unlock(&serdes_lock__);
2743-
dev_info(&state->client->dev,
2744-
"%s(): released pipe %d (%d)\n",
2745-
__func__, active->pipe_id, release_ret);
2746-
active->pipe_id = PIPE_NOT_CONFIGURED;
2747-
}
27482742
active->pipe_data_type1 = 0;
27492743
active->pipe_data_type2 = 0;
27502744
active->pipe_vc_id = 0;
@@ -2845,40 +2839,29 @@ static int ds5_hw_reset_with_recovery(struct ds5 *state)
28452839
}
28462840

28472841
#ifdef CONFIG_VIDEO_D4XX_SERDES
2848-
/* 6. Tiered SERDES recovery (conditional).
2842+
/* 6. SERDES recovery (conditional).
28492843
* Step 5 polled the device over I2C until 0xDEAD was returned,
2850-
* which means the GMSL link was already up at that point. Probe
2851-
* the I2C link once more: if it is still alive, the GMSL link
2852-
* recovered naturally and full SERDES recovery (Phase 1 stability
2853-
* dance + potential Phase 2 escalation) is unnecessary — this is
2854-
* the common case for D457.
2844+
* which means the GMSL link is up. Probe once more: if the
2845+
* link is still alive, the GMSL link recovered naturally — no
2846+
* SERDES intervention needed (the common case for D457).
28552847
*
2856-
* However, we must ALWAYS call max9295_init_settings() to restore
2857-
* the serializer's global pipe-enable, CSI port selection, and
2858-
* data-source registers. The D457 FW reconfigures the MAX9295
2859-
* during its post-boot sequence, potentially overwriting these
2860-
* global registers. Without re-init, per-pipe setup later in
2861-
* ds5_setup_pipeline() may fail — especially for pipe 3 (IMU)
2862-
* which the FW does not configure for its own use.
2848+
* Do NOT call max9295_init_settings() on the light path.
2849+
* The D457 FW continues reconfiguring the MAX9295 serializer
2850+
* for ~50-100ms after reporting 0xDEAD. Calling init_settings
2851+
* now gets overwritten by the FW's ongoing init. Instead,
2852+
* let the FW finish naturally; ds5_setup_pipeline() will write
2853+
* per-pipe settings at stream-start time (seconds later) on
2854+
* top of the FW's stable final state. This matches v1.0.1.33
2855+
* behavior where HW reset was fire-and-forget with zero SERDES
2856+
* intervention and all CI tests passed.
28632857
*
2864-
* Only run the FULL tiered recovery (with stability checks and
2865-
* Phase 2 escalation) when the I2C link is actually broken —
2866-
* e.g. the camera FW's secondary init phase dropped the bus
2867-
* between Step 5 and now (observed on D401, occasionally D457).
2858+
* Only run full tiered recovery (including init_settings +
2859+
* stability checks + Phase 2 escalation) when the I2C link
2860+
* is actually broken.
28682861
*/
28692862
{
28702863
u16 link_probe = 0;
28712864

2872-
/* Always restore serializer global state (pipe enables, port
2873-
* selection, data sources). This is a lightweight I2C write
2874-
* sequence with no sleeps — ~0ms overhead.
2875-
*/
2876-
ret = max9295_init_settings(state->ser_dev);
2877-
if (ret < 0)
2878-
dev_warn(&state->client->dev,
2879-
"%s(): serializer init_settings failed: %d (continuing)\n",
2880-
__func__, ret);
2881-
28822865
ret = ds5_read(state, DS5_FW_VERSION, &link_probe);
28832866
if (ret < 0 || link_probe == 0) {
28842867
dev_info(&state->client->dev,
@@ -2894,7 +2877,7 @@ static int ds5_hw_reset_with_recovery(struct ds5 *state)
28942877
serdes_recovery_ran = true;
28952878
} else {
28962879
dev_info(&state->client->dev,
2897-
"%s(): GMSL link recovered naturally (FW ver 0x%04x), skipping full SERDES recovery\n",
2880+
"%s(): GMSL link recovered naturally (FW ver 0x%04x), no SERDES intervention needed\n",
28982881
__func__, link_probe);
28992882
}
29002883
}

0 commit comments

Comments
 (0)