# DF-4446 — DF i2c bit-bang shim is a stub: all radeon bit-bang DDC/EDID transfers are silent no-ops; the entire bit-bang block of radeon_i2c.c is dead code on DragonFly

## Verdict

**Status: untested** (Info severity — skipped per contract; also
hardware-gated). Static analysis: certain.

## Line-cited trace

1. `radeon_i2c_create()` bit-bus branch
   (`sys/dev/drm/radeon/radeon_i2c.c:955-978`): sets
   `i2c->adapter.algo_data = &i2c->bit;` and the six callbacks
   (`pre_xfer/post_xfer/set_clock/set_data/get_clock/get_data`), then calls
   `i2c_bit_add_bus(&i2c->adapter)`.
2. DF's shim `i2c_bit_add_bus()` (`sys/dev/drm/linux_i2c.c:127-134`) does
   `adapter->algo = &i2c_bit_algo; adapter->retries = 2; return 0;` —
   **overwriting nothing that matters, because `i2c_bit_algo.master_xfer`
   is `bit_xfer()`** (`linux_i2c.c:106-111`):
   `/* XXX Linux really does try to transfer some data here */ return 0;`
   — it never looks at `algo_data`, so none of radeon's GPIO bit-bang
   callbacks (radeon_i2c.c:90-232) ever execute.
3. With the module default `radeon_hw_i2c == 0`, the selection logic at
   `radeon_i2c.c:933-955` routes every non-`mm_i2c` bus (i.e. every DDC bus)
   to this bit branch; only `radeon_hw_i2c=1` (explicitly discouraged by
   `radeon_i2c_init()`'s own warning at `:999-1000`) selects the real
   r100/r500/atom hardware engines.
4. Effect: `i2c_transfer()` (`linux_i2c.c:91-104`) calls `bit_xfer` → 0;
   callers require `ret == num`: `radeon_ddc_probe()`
   (`radeon_i2c.c:66-74`) always returns false;
   `drm_do_probe_ddc_edid()` (`sys/dev/drm/drm_edid.c:1513-1558`) always
   fails → no EDID on any bit-path bus → connector reports disconnected.
   (Contrast i915: `intel_i2c.c` keeps the real GMBUS algorithm and only
   uses the stub as a rare fallback, so i915 DDC works.)

Also noted (no independent finding): the DF-only
`i2c_add_adapter(&i2c->adapter)` call placed between `i2c_bit_add_bus()`
and its error check (`radeon_i2c.c:970-973`) is a latent UAF pattern
(adapter registered then chan freed on `bit_add_bus` failure), but on the
current shim both functions unconditionally return 0, so the path is
unreachable — recorded here for when the shim grows real error returns.

## Impact

Functional: display hotplug/EDID detection dead for bit-banged buses
(pre-DCE3 radeon, and any bus on the bit path) on DragonFly. No memory
safety, no attacker primitive → Info.

## Fix direction

Port Linux's `drivers/i2c/algos/i2c-algo-bit.c` `bit_xfer()` into
`sys/dev/drm/linux_i2c.c` (it only needs the `i2c_algo_bit_data` callbacks
already declared in `sys/dev/drm/include/linux/i2c-algo-bit.h`), or bypass
the shim for radeon buses. i915 is unaffected either way.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

(No fix.diff for this item: documented recommendation only - see Fix above.)
