Rework xgi_(pcie|fb)_free_all to prevent deadlock.
authorIan Romanick <idr@us.ibm.com>
Thu, 19 Jul 2007 18:38:56 +0000 (11:38 -0700)
committerIan Romanick <idr@us.ibm.com>
Thu, 19 Jul 2007 18:38:56 +0000 (11:38 -0700)
linux-core/xgi_fb.c
linux-core/xgi_pcie.c

index ce68984..a588519 100644 (file)
@@ -365,7 +365,7 @@ void xgi_fb_free_all(struct xgi_info * info, DRMFILE filp)
                        break;
                }
 
-               (void) xgi_fb_free(info, block->offset, filp);
+               (void) xgi_mem_free(&info->fb_heap, block->offset, filp);
        } while(1);
 
        up(&info->fb_sem);
index 49c531f..9dee888 100644 (file)
@@ -34,6 +34,9 @@ static struct xgi_mem_block *xgi_pcie_vertex_block = NULL;
 static struct xgi_mem_block *xgi_pcie_cmdlist_block = NULL;
 static struct xgi_mem_block *xgi_pcie_scratchpad_block = NULL;
 
+static int xgi_pcie_free_locked(struct xgi_info * info,
+        unsigned long offset, DRMFILE filp);
+
 static int xgi_pcie_lut_init(struct xgi_info * info)
 {
        u8 temp = 0;
@@ -248,30 +251,39 @@ void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp)
                        break;
                }
 
-               (void) xgi_pcie_free(info, block->offset, filp);
+               (void) xgi_pcie_free_locked(info, block->offset, filp);
        } while(1);
 
        up(&info->pcie_sem);
 }
 
 
-int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp)
+int xgi_pcie_free_locked(struct xgi_info * info,
+                        unsigned long offset, DRMFILE filp)
 {
        const bool isvertex = (xgi_pcie_vertex_block
                               && (xgi_pcie_vertex_block->offset == offset));
+       int err = xgi_mem_free(&info->pcie_heap, offset, filp);
+
+       if (!err && isvertex)
+               xgi_pcie_vertex_block = NULL;
+
+       return err;
+}
+
+
+int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp)
+{
        int err;
 
        down(&info->pcie_sem);
-       err = xgi_mem_free(&info->pcie_heap, offset, filp);
+       err = xgi_pcie_free_locked(info, offset, filp);
        up(&info->pcie_sem);
 
        if (err) {
                DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset);
        }
 
-       if (isvertex)
-               xgi_pcie_vertex_block = NULL;
-
        return err;
 }