summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2007-07-19 11:38:56 -0700
committerIan Romanick <idr@us.ibm.com>2007-07-19 11:38:56 -0700
commit15245b670e5359a7dbf9151aa9f160e929e0b46b (patch)
tree7d5cfcad5dfdb667183ce66bea61aec10f3b55d7
parent2f53ce4af2f7db911d908ff382738f30be004e8b (diff)
Rework xgi_(pcie|fb)_free_all to prevent deadlock.
-rw-r--r--linux-core/xgi_fb.c2
-rw-r--r--linux-core/xgi_pcie.c24
2 files changed, 19 insertions, 7 deletions
diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c
index ce689847..a5885198 100644
--- a/linux-core/xgi_fb.c
+++ b/linux-core/xgi_fb.c
@@ -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);
diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c
index 49c531fc..9dee888b 100644
--- a/linux-core/xgi_pcie.c
+++ b/linux-core/xgi_pcie.c
@@ -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;
}