mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +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_iterate_modes(void *lx_data, void * genode_data);
|
||||||
void lx_emul_i915_report_modes(void * genode_xml, struct genode_mode *);
|
void lx_emul_i915_report_modes(void * genode_xml, struct genode_mode *);
|
||||||
void lx_emul_i915_connector_config(char * name, 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_ */
|
#endif /* _LX_I915_H_ */
|
||||||
|
@ -397,7 +397,8 @@ static int configure_connectors(void * data)
|
|||||||
|
|
||||||
retry_count = 0;
|
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;
|
return 0;
|
||||||
|
@ -53,6 +53,9 @@ struct Framebuffer::Driver
|
|||||||
Signal_handler<Driver> timer_handler { env.ep(), *this,
|
Signal_handler<Driver> timer_handler { env.ep(), *this,
|
||||||
&Driver::handle_timer };
|
&Driver::handle_timer };
|
||||||
|
|
||||||
|
bool update_in_progress { false };
|
||||||
|
bool new_config_rom { false };
|
||||||
|
|
||||||
class Fb
|
class Fb
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -148,6 +151,11 @@ void Framebuffer::Driver::config_update()
|
|||||||
if (!config.valid() || !lx_user_task)
|
if (!config.valid() || !lx_user_task)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (update_in_progress)
|
||||||
|
new_config_rom = true;
|
||||||
|
else
|
||||||
|
update_in_progress = true;
|
||||||
|
|
||||||
lx_emul_task_unblock(lx_user_task);
|
lx_emul_task_unblock(lx_user_task);
|
||||||
Lx_kit::env().scheduler.schedule();
|
Lx_kit::env().scheduler.schedule();
|
||||||
}
|
}
|
||||||
@ -178,6 +186,8 @@ void Framebuffer::Driver::generate_report(void *lx_data)
|
|||||||
{
|
{
|
||||||
lx_emul_i915_report(lx_data, &xml);
|
lx_emul_i915_report(lx_data, &xml);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
driver(Lx_kit::env().env).report_updated();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Genode::warning("Failed to generate report");
|
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);
|
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)
|
void Component::construct(Genode::Env &env)
|
||||||
{
|
{
|
||||||
driver(env).start();
|
driver(env).start();
|
||||||
|
Loading…
Reference in New Issue
Block a user