Dominik Behr has uploaded a new change for review.
https://chromium-review.googlesource.com/351010
Change subject: frecon: keep master while frecon is active
......................................................................
frecon: keep master while frecon is active
This change switches back to old frecon behavior where it would keep
DRM master for whole time it was active. I thought we could only keep
it for mode switch but it is also needed for framebuffer invalidation
which is necessary on some hardware so we would need to set and drop it
on every screen update.
This change also centralizes DRM master set and drop in term foreground
and background functions making it clear where it is set and dropped.
There was also situation where. when Chrome is under high load it becomes
confused and still sends page flip requests even though frecon is active.
In this case, if when frecon dropped master page flip succeeds and it
appears the system is hanging (frecon is still processing keyboard events
but static Chrome window is visible).
BUG=chromium:610790,chromium:588425,chromium:616594,chromeo-os-partner:51058
TEST=quickly switch between Chrome and frecon using ctrl-alt-< and
ctrl-alt->\
while system is under high load.
Change-Id: I651a89b307dcf31396ba52e2dcb605d2a7617cd9
Signed-off-by: Dominik Behr <
db...@chromium.org>
---
M drm.c
M drm.h
M fb.c
M main.c
M term.c
5 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/drm.c b/drm.c
index a3d0a95..2196e32 100644
--- a/drm.c
+++ b/drm.c
@@ -19,7 +19,7 @@
#include "input.h"
#include "util.h"
-static drm_t* drm = NULL;
+static drm_t* g_drm = NULL;
static void drm_disable_crtc(drm_t* drm, drmModeCrtc* crtc)
{
@@ -401,18 +401,18 @@
void drm_set(drm_t* drm_)
{
- if (drm) {
- drm_delref(drm);
- drm = NULL;
+ if (g_drm) {
+ drm_delref(g_drm);
+ g_drm = NULL;
}
- drm = drm_;
+ g_drm = drm_;
}
void drm_close(void)
{
- if (drm) {
- drm_delref(drm);
- drm = NULL;
+ if (g_drm) {
+ drm_delref(g_drm);
+ g_drm = NULL;
}
}
@@ -434,19 +434,34 @@
drm_t* drm_addref(void)
{
- if (drm) {
- drm->refcount++;
- return drm;
+ if (g_drm) {
+ g_drm->refcount++;
+ return g_drm;
}
return NULL;
}
-void drm_dropmaster(drm_t* drm)
+int drm_dropmaster(drm_t* drm)
{
- if (drm) {
- drmDropMaster(drm->fd);
- }
+ int ret = 0;
+
+ if (!drm)
+ drm = g_drm;
+ if (drm)
+ ret = drmDropMaster(drm->fd);
+ return ret;
+}
+
+int drm_setmaster(drm_t* drm)
+{
+ int ret = 0;
+
+ if (!drm)
+ drm = g_drm;
+ if (drm)
+ ret = drmSetMaster(drm->fd);
+ return ret;
}
/*
@@ -457,20 +472,22 @@
drm_t* ndrm;
/* In case we had master, drop master so the newly created object could
have it. */
- drm_dropmaster(drm);
+ drm_dropmaster(g_drm);
ndrm = drm_scan();
if (ndrm) {
- if (drm_equal(ndrm, drm)) {
+ if (drm_equal(ndrm, g_drm)) {
drm_fini(ndrm);
+ /* Regain master we dropped. */
+ drm_setmaster(g_drm);
} else {
- drm_delref(drm);
- drm = ndrm;
+ drm_delref(g_drm);
+ g_drm = ndrm;
return true;
}
} else {
- if (drm) {
- drm_delref(drm); /* No usable monitor/drm object. */
- drm = NULL;
+ if (g_drm) {
+ drm_delref(g_drm); /* No usable monitor/drm object. */
+ g_drm = NULL;
return true;
}
}
@@ -485,10 +502,9 @@
{
int32_t ret;
- ret = drmSetMaster(drm->fd);
+ ret = drm_setmaster(drm);
if (ret)
- LOG(ERROR, "drmSetMaster failed: %m");
-
+ LOG(ERROR, "drmSetMaster failed in setmode: %m");
ret = drmModeSetCrtc(drm->fd, drm->crtc->crtc_id,
fb_id,
0, 0, // x,y
@@ -498,7 +514,6 @@
if (ret) {
LOG(ERROR, "Unable to set crtc: %m");
- drm_dropmaster(drm);
return ret;
}
@@ -510,7 +525,6 @@
drm_disable_non_primary_planes(drm);
drm_disable_non_main_crtcs(drm);
- drm_dropmaster(drm);
return ret;
}
diff --git a/drm.h b/drm.h
index 9a68922..342fa5f 100644
--- a/drm.h
+++ b/drm.h
@@ -31,7 +31,8 @@
void drm_close(void);
drm_t* drm_addref(void);
void drm_delref(drm_t* drm);
-void drm_dropmaster(drm_t* drm);
+int drm_dropmaster(drm_t* drm);
+int drm_setmaster(drm_t* drm);
bool drm_rescan(void);
bool drm_valid(drm_t* drm);
int32_t drm_setmode(drm_t* drm, uint32_t fb_id);
diff --git a/fb.c b/fb.c
index 8e31dfe..6ee8b62 100644
--- a/fb.c
+++ b/fb.c
@@ -259,13 +259,9 @@
0, 0, fb->buffer_properties.width, fb->buffer_properties.height
};
munmap(fb->lock.map, fb->buffer_properties.size);
- ret = drmSetMaster(fb->drm->fd);
- if (ret)
- LOG(ERROR, "drmSetMaster failed: %m");
ret = drmModeDirtyFB(fb->drm->fd, fb->fb_id, &clip_rect, 1);
if (ret)
LOG(ERROR, "drmModeDirtyFB failed: %m");
- drm_dropmaster(fb->drm);
}
}
diff --git a/main.c b/main.c
index 0950351..2f0e942 100644
--- a/main.c
+++ b/main.c
@@ -379,7 +379,6 @@
if (command_flags.daemon) {
if (command_flags.enable_vts)
set_drm_master_relax(); /* TODO(dbehr) Remove when Chrome is fixed to
actually release master. */
- drm_dropmaster(drm);
term_background();
} else {
/* Create and switch to first term in interactve mode. */
diff --git a/term.c b/term.c
index c716dd1..80505aa 100644
--- a/term.c
+++ b/term.c
@@ -811,11 +811,13 @@
if (in_background)
return;
in_background = true;
+ drm_dropmaster(NULL);
dbus_take_display_ownership();
}
void term_foreground(void)
{
+ int ret;
if (!in_background)
return;
in_background = false;
@@ -823,6 +825,19 @@
LOG(ERROR, "Chrome did not release master. Frecon will try to steal
it.");
set_drm_master_relax();
}
+
+ ret = drm_setmaster(NULL);
+ if (ret < 0) {
+ /*
+ * In case there is high system load give Chrome some time
+ * and try again. */
+ usleep(500*1000);
+ ret = drm_setmaster(NULL);
+ }
+ if (ret < 0) {
+ LOG(ERROR, "Could not set master when switching to foreground %m.");
+ }
+
if (hotplug_occured) {
hotplug_occured = false;
term_monitor_hotplug();
--
To view, visit
https://chromium-review.googlesource.com/351010
To unsubscribe, visit
https://chromium-review.googlesource.com/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I651a89b307dcf31396ba52e2dcb605d2a7617cd9
Gerrit-PatchSet: 1
Gerrit-Project: chromiumos/platform/frecon
Gerrit-Branch: master
Gerrit-Owner: Dominik Behr <
db...@chromium.org>