Deadlock in intel_enable_pipe_a()

Thomas Richter
2014-06-08T23:14:29Z

Hi Ville, hi Daniel, dear intel experts,

just went through the problem I send around, and I guess I understand
now what happens here. The reason *why* resume fails is that there is a
deadlock situation in intel_display.c:

*) loading the module calls intel_modeset_init()
*) intel_modeset_init() calls intel_modeset_setup_hw_state(), but
protects access to it with a global lock.
*) intel_modeset_setup_hw_state() calls intel_sanitize_crtc()
*) intel_sanitize_crtc() finds that the pipe-a quirk is enabled and
calls intel_enable_pipe_a()
*) intel_enable_pipe_a() calls intel_release_load_detect_pipe(), however
not using the same mutex context as the caller (intel_modeset_init()).
*) intel_release_load_detect_pipe() again gets the mutex of the crtc.

Unfortunately, at this time, the caller (intel_modeset_init()) had
already everything locked.

Needless to say, this deadlocks and blocks the kernel completely,
causing the problem I found above.

To verify my hypothesis, I removed the locks in
intel_release_load_detect_pipe(), (obviously risking race conditions,
but never mind for the test).

The result is that the machine is responsive after the resume. It still
does not show a display (apparently, intel_sanitize_crtc() is
insufficient and does not sanitize enough), but at least one can
force-enable it again.

Thus, two bugs:

1) attempting to lock the same lock twice, nested, causing a deadlock.
The pipe A quirk is not working correctly by requiring a call into a
method that requires a lock that is already held.

2) not sanitizing the chipset sufficiently, still keeping the display
black. (This, being, of course a side effect of the buggy bios).

Hope this helps!

Thomas