mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
intel_fb: handle rapid config change gracefully
In case of very rapid config ROM change (<300ms), the linux driver may still be in progress of applying the previous change (e.g. switching connector on/off). During this progress all tasks may become not runnable (waiting for IRQ/timeouts until hardware state settles), the newest config ROM change/signal gets dispatched, which lead to continuing the previous change request, but not to re-starting/re-applying the new config change. To avoid this situation, explicitly track whether a previous config change was finished and track if an interim config change request came in. If so, re-start the lx_user task with the newest config change. Fixes #4721
This commit is contained in:
parent
41ebf3bd94
commit
5f0ba7d722
@ -35,5 +35,6 @@ void lx_emul_i915_report_connector(void * lx_data, void * genode_xml,
|
||||
void lx_emul_i915_iterate_modes(void *lx_data, void * genode_data);
|
||||
void lx_emul_i915_report_modes(void * genode_xml, struct genode_mode *);
|
||||
void lx_emul_i915_connector_config(char * name, struct genode_mode *);
|
||||
int lx_emul_i915_config_done_and_block(void);
|
||||
|
||||
#endif /* _LX_I915_H_ */
|
||||
|
@ -397,7 +397,8 @@ static int configure_connectors(void * data)
|
||||
|
||||
retry_count = 0;
|
||||
|
||||
lx_emul_task_schedule(true);
|
||||
if (lx_emul_i915_config_done_and_block())
|
||||
lx_emul_task_schedule(true /* block task */);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -53,6 +53,9 @@ struct Framebuffer::Driver
|
||||
Signal_handler<Driver> timer_handler { env.ep(), *this,
|
||||
&Driver::handle_timer };
|
||||
|
||||
bool update_in_progress { false };
|
||||
bool new_config_rom { false };
|
||||
|
||||
class Fb
|
||||
{
|
||||
private:
|
||||
@ -148,6 +151,11 @@ void Framebuffer::Driver::config_update()
|
||||
if (!config.valid() || !lx_user_task)
|
||||
return;
|
||||
|
||||
if (update_in_progress)
|
||||
new_config_rom = true;
|
||||
else
|
||||
update_in_progress = true;
|
||||
|
||||
lx_emul_task_unblock(lx_user_task);
|
||||
Lx_kit::env().scheduler.schedule();
|
||||
}
|
||||
@ -178,6 +186,8 @@ void Framebuffer::Driver::generate_report(void *lx_data)
|
||||
{
|
||||
lx_emul_i915_report(lx_data, &xml);
|
||||
});
|
||||
|
||||
driver(Lx_kit::env().env).report_updated();
|
||||
} catch (...) {
|
||||
Genode::warning("Failed to generate report");
|
||||
}
|
||||
@ -288,8 +298,6 @@ void lx_emul_i915_report_connector(void * lx_data, void * genode_xml,
|
||||
|
||||
lx_emul_i915_iterate_modes(lx_data, &xml);
|
||||
});
|
||||
|
||||
driver(Lx_kit::env().env).report_updated();
|
||||
}
|
||||
|
||||
|
||||
@ -323,6 +331,20 @@ void lx_emul_i915_connector_config(char * name, struct genode_mode * mode)
|
||||
}
|
||||
|
||||
|
||||
int lx_emul_i915_config_done_and_block(void)
|
||||
{
|
||||
auto &state = driver(Lx_kit::env().env);
|
||||
|
||||
bool const new_config = state.new_config_rom;
|
||||
|
||||
state.update_in_progress = false;
|
||||
state.new_config_rom = false;
|
||||
|
||||
/* true if linux task should block, otherwise continue due to new config */
|
||||
return !new_config;
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
driver(env).start();
|
||||
|
Loading…
Reference in New Issue
Block a user