summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-06-22 16:34:20 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-06-22 17:39:39 +0100
commit41badce186fe0f6e8f49e30b6c1c251027161e35 (patch)
tree911cf606da6f3169105089b6854ec0809ba2e82a
parent81b35092c39bf6d9851ac37da4b20358405cf314 (diff)
sna: Add reference counting to drmMaster for Zaphod
With Zaphod enabled, we will try to acquire/release the drmMaster several times on each enter/leave VT. This obviously flags an error (and drops the master too early), so track the number of references we still hold for drmMaster. References: https://bugs.freedesktop.org/show_bug.cgi?id=66041 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_driver.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index b48ab30d..013e27a9 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -78,6 +78,9 @@ DevPrivateKeyRec sna_gc_key;
DevPrivateKeyRec sna_window_key;
DevPrivateKeyRec sna_glyph_key;
+static int sna_put_drm_master(ScrnInfoPtr scrn);
+static int sna_get_drm_master(ScrnInfoPtr scrn);
+
static void
sna_load_palette(ScrnInfoPtr scrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
@@ -197,7 +200,7 @@ static Bool sna_become_master(struct sna *sna)
DBG(("%s\n", __FUNCTION__));
- if (drmSetMaster(sna->kgem.fd)) {
+ if (sna_get_drm_master(scrn)) {
sleep(2); /* XXX wait for the current master to decease */
if (drmSetMaster(sna->kgem.fd)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -293,6 +296,7 @@ static void PreInitCleanup(ScrnInfoPtr scrn)
struct sna_device {
int fd;
int open_count;
+ int master_count;
};
static int sna_device_key = -1;
@@ -323,9 +327,10 @@ static int sna_open_drm_master(ScrnInfoPtr scrn)
dev = sna_device(scrn);
if (dev) {
+ DBG(("%s: reusing device, count=%d (master=%d)\n",
+ __FUNCTION__, dev->open_count, dev->master_count));
+ assert(dev->open_count);
dev->open_count++;
- DBG(("%s: reusing device, count=%d\n",
- __FUNCTION__, dev->open_count));
return dev->fd;
}
@@ -375,6 +380,36 @@ static int sna_open_drm_master(ScrnInfoPtr scrn)
return fd;
}
+static int sna_get_drm_master(ScrnInfoPtr scrn)
+{
+ struct sna_device *dev = sna_device(scrn);
+ int ret;
+
+ if (dev == NULL)
+ return -1;
+
+ ret = 0;
+ if (dev->master_count++ == 0)
+ ret = drmSetMaster(dev->fd);
+ return ret;
+}
+
+static int sna_put_drm_master(ScrnInfoPtr scrn)
+{
+ struct sna_device *dev = sna_device(scrn);
+ int ret;
+
+ if (dev == NULL)
+ return -1;
+
+ ret = 0;
+ assert(dev->master_count);
+ if (--dev->master_count == 0)
+ ret = drmDropMaster(dev->fd);
+
+ return ret;
+}
+
static void sna_close_drm_master(ScrnInfoPtr scrn)
{
struct sna_device *dev = sna_device(scrn);
@@ -825,13 +860,12 @@ static void sna_uevent_fini(ScrnInfoPtr scrn) { }
static void sna_leave_vt(VT_FUNC_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
- struct sna *sna = to_sna(scrn);
DBG(("%s\n", __FUNCTION__));
xf86_hide_cursors(scrn);
- if (drmDropMaster(sna->kgem.fd))
+ if (sna_put_drm_master(scrn))
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"drmDropMaster failed: %s\n", strerror(errno));
}