xf86-video-ati: Branch 'master' - 2 commits

Michel Dänzer daenzer at kemper.freedesktop.org
Tue Mar 6 06:53:03 PST 2012


 src/drmmode_display.c |   18 ++++++++++++------
 src/drmmode_display.h |    1 +
 src/radeon_dri2.c     |   41 ++++++++++++++++++++++-------------------
 src/radeon_kms.c      |    2 ++
 src/radeon_probe.h    |    2 +-
 5 files changed, 38 insertions(+), 26 deletions(-)

New commits:
commit 355dc4295912c153f5333421594fa90aa119a056
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Mar 6 15:52:40 2012 +0100

    DRI2: Unreference buffers immediately when event wait info is invalidated.
    
    Deferring this could result in trying to unreference buffers from a previous
    server generation, i.e. accessing freed memory.
    
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Tested-by: Christian König <Christian.koenig at amd.com>

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index cf905a1..8bd3f66 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -571,6 +571,22 @@ ListDelDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
 }
 
 static void
+radeon_dri2_ref_buffer(BufferPtr buffer)
+{
+    struct dri2_buffer_priv *private = buffer->driverPrivate;
+    private->refcnt++;
+}
+
+static void
+radeon_dri2_unref_buffer(BufferPtr buffer)
+{
+    if (buffer) {
+        struct dri2_buffer_priv *private = buffer->driverPrivate;
+        radeon_dri2_destroy_buffer(&(private->pixmap->drawable), buffer);
+    }
+}
+
+static void
 radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer data, pointer calldata)
 {
     DRI2ClientEventsPtr pClientEventsPriv;
@@ -591,6 +607,8 @@ radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer d
         if (pClientEventsPriv) {
             xorg_list_for_each_entry(ref, &pClientEventsPriv->reference_list, link) {
                 ref->valid = FALSE;
+                radeon_dri2_unref_buffer(ref->front);
+                radeon_dri2_unref_buffer(ref->back);
             }
         }
         break;
@@ -599,22 +617,6 @@ radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer d
     }
 }
 
-static void
-radeon_dri2_ref_buffer(BufferPtr buffer)
-{
-    struct dri2_buffer_priv *private = buffer->driverPrivate;
-    private->refcnt++;
-}
-
-static void
-radeon_dri2_unref_buffer(BufferPtr buffer)
-{
-    if (buffer) {
-        struct dri2_buffer_priv *private = buffer->driverPrivate;
-        radeon_dri2_destroy_buffer(&(private->pixmap->drawable), buffer);
-    }
-}
-
 static int radeon_dri2_drawable_crtc(DrawablePtr pDraw)
 {
     ScreenPtr pScreen = pDraw->pScreen;
@@ -849,10 +851,11 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
     }
 
 cleanup:
-    radeon_dri2_unref_buffer(event->front);
-    radeon_dri2_unref_buffer(event->back);
-    if (event->valid)
+    if (event->valid) {
+        radeon_dri2_unref_buffer(event->front);
+        radeon_dri2_unref_buffer(event->back);
         ListDelDRI2ClientEvents(event->client, &event->link);
+    }
     free(event);
 }
 
commit fe51469b2e02e4d565050bab077985270fb58a9b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Mar 6 15:52:40 2012 +0100

    Re-register DRM FD wakeup handler for each server generation.
    
    Fixes hang when trying to use DRI2 swap scheduling after a server reset.
    
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Tested-by: Christian König <Christian.koenig at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3a23474..38f9940 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1479,9 +1479,7 @@ drm_wakeup_handler(pointer data, int err, pointer p)
 
 Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 {
-	RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
 	xf86CrtcConfigPtr xf86_config;
-	RADEONInfoPtr info = RADEONPTR(pScrn);
 	int i, num_dvi = 0, num_hdmi = 0;
 
 	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
@@ -1509,14 +1507,22 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
 	drmmode->event_context.vblank_handler = drmmode_vblank_handler;
 	drmmode->event_context.page_flip_handler = drmmode_flip_handler;
-	if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) {
+
+	return TRUE;
+}
+
+void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+
+	if (pRADEONEnt->fd_wakeup_registered != serverGeneration &&
+	    info->dri->pKernelDRMVersion->version_minor >= 4) {
 		AddGeneralSocket(drmmode->fd);
 		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
 				drm_wakeup_handler, drmmode);
-		pRADEONEnt->fd_wakeup_registered = TRUE;
+		pRADEONEnt->fd_wakeup_registered = serverGeneration;
 	}
-
-	return TRUE;
 }
 
 Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index eb271f5..dff0392 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -99,6 +99,7 @@ typedef struct {
 
 
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
+extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr);
 extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo);
 void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 124ce80..c094bea 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -1136,6 +1136,8 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
     if (serverGeneration == 1)
 	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
 
+    drmmode_init(pScrn, &info->drmmode);
+
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONScreenInit finished\n");
 
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 8ba7214..3123bcc 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -750,7 +750,7 @@ typedef struct
     void              *FB;              /* Map of FB region                  */
     int               FB_cnt;           /* Map of FB region refcount         */
     int fd;                             /* for sharing across zaphod heads   */
-    Bool              fd_wakeup_registered; /* fd has already been registered for wakeup handling */
+    unsigned long     fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */
     int dri2_info_cnt;
 } RADEONEntRec, *RADEONEntPtr;
 


More information about the xorg-commit mailing list