diff mbox

[v2] staging: tidspbridge: protect dmm_map properly

Message ID AANLkTikisHaAMZphRJVYdcokVbaZXVF9COrwkdGTDg__@mail.gmail.com (mailing list archive)
State New, archived
Delegated to:
Headers show

Commit Message

Ohad Ben Cohen Dec. 21, 2010, 2:06 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/staging/tidspbridge/include/dspbridge/drv.h
b/drivers/staging/tidspbridge/include/dspbridge/drv.h
index c1f363e..cad0626 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/drv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/drv.h
@@ -25,6 +25,7 @@ 

 #include <dspbridge/drvdefs.h>
 #include <linux/idr.h>
+#include <linux/atomic.h>

 #define DRV_ASSIGN     1
 #define DRV_RELEASE    0
@@ -106,6 +107,7 @@  struct dmm_map_object {
 	u32 num_usr_pgs;
 	struct page **pages;
 	struct bridge_dma_map_info dma_info;
+	atomic_t refcnt;
 };

 /* Used for DMM reserved memory accounting */
diff --git a/drivers/staging/tidspbridge/rmgr/proc.c
b/drivers/staging/tidspbridge/rmgr/proc.c
index b47d7aa..4aabfcc 100644
--- a/drivers/staging/tidspbridge/rmgr/proc.c
+++ b/drivers/staging/tidspbridge/rmgr/proc.c
@@ -112,6 +112,26 @@  static s32 get_envp_count(char **envp);
 static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems,
 			   s32 cnew_envp, char *sz_var);

+/*
+ * Grab the dmm_map_object's reference count. This operation is valid only
+ * when map_obj is ALREADY grabbed, e.g., it is still in the dmm_map list
+ * and list's lock is taken
+ */
+static inline void map_obj_get(struct dmm_map_object *map_obj)
+{
+	atomic_inc(&map_obj->refcnt);
+}
+
+/* Ungrab map_obj and destroy it, if it was the last reference */
+static inline void map_obj_put(struct dmm_map_object *map_obj)
+{
+	if (atomic_dec_and_test(&map_obj->refcnt)) {
+		kfree(map_obj->dma_info.sg);
+		kfree(map_obj->pages);
+		kfree(map_obj);
+	}
+}
+
 /* remember mapping information */
 static struct dmm_map_object *add_mapping_info(struct process_context *pr_ctxt,
 				u32 mpu_addr, u32 dsp_addr, u32 size)
@@ -143,6 +163,8 @@  static struct dmm_map_object
*add_mapping_info(struct process_context *pr_ctxt,
 	map_obj->dsp_addr = dsp_addr;
 	map_obj->size = size;
 	map_obj->num_usr_pgs = num_usr_pgs;
+	/* dmm map objects are initially grabbed */
+	atomic_set(&map_obj->refcnt, 1);

 	spin_lock(&pr_ctxt->dmm_map_lock);