map a bo only when it is locked for CPU access

To match the doc a little better.
diff --git a/gralloc.c b/gralloc.c
index fd4f848..e134e81 100644
--- a/gralloc.c
+++ b/gralloc.c
@@ -149,7 +149,7 @@
 	if (!bo)
 		return -EINVAL;
 
-	return gralloc_drm_bo_map(bo, x, y, w, h, 1, ptr);
+	return gralloc_drm_bo_lock(bo, usage, x, y, w, h, ptr);
 }
 
 static int drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle)
@@ -161,7 +161,7 @@
 	if (!bo)
 		return -EINVAL;
 
-	gralloc_drm_bo_unmap(bo);
+	gralloc_drm_bo_unlock(bo);
 
 	return 0;
 }
diff --git a/gralloc_drm.c b/gralloc_drm.c
index e220ebe..2ec11ef 100644
--- a/gralloc_drm.c
+++ b/gralloc_drm.c
@@ -294,22 +294,57 @@
 }
 
 /*
- * Map a bo for CPU access.
+ * Lock a bo.  XXX thread-safety?
  */
-int gralloc_drm_bo_map(struct gralloc_drm_bo_t *bo,
-		int x, int y, int w, int h,
-		int enable_write, void **addr)
+int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo,
+		int usage, int x, int y, int w, int h,
+		void **addr)
 {
-	return bo->drm->drv->map(bo->drm->drv, bo,
-			x, y, w, h, enable_write, addr);
+	if ((bo->handle->usage & usage) != usage)
+		return -EINVAL;
+
+	/* allow multiple locks with compatible usages */
+	if (bo->lock_count && (bo->locked_for & usage) != usage)
+		return -EINVAL;
+
+	usage |= bo->locked_for;
+
+	if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
+		     GRALLOC_USAGE_SW_READ_MASK)) {
+		/* the driver is supposed to wait for the bo */
+		int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
+		int err = bo->drm->drv->map(bo->drm->drv, bo,
+				x, y, w, h, write, addr);
+		if (err)
+			return err;
+	}
+	else {
+		/* kernel handles the synchronization here */
+	}
+
+	bo->lock_count++;
+	bo->locked_for |= usage;
+
+	return 0;
 }
 
 /*
- * Unmap a bo.
+ * Unlock a bo.
  */
-void gralloc_drm_bo_unmap(struct gralloc_drm_bo_t *bo)
+void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo)
 {
-	bo->drm->drv->unmap(bo->drm->drv, bo);
+	int mapped = bo->locked_for &
+		(GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
+
+	if (!bo->lock_count)
+		return;
+
+	if (mapped)
+		bo->drm->drv->unmap(bo->drm->drv, bo);
+
+	bo->lock_count--;
+	if (!bo->lock_count)
+		bo->locked_for = 0;
 }
 
 /*
diff --git a/gralloc_drm.h b/gralloc_drm.h
index 3907dfd..794abf3 100644
--- a/gralloc_drm.h
+++ b/gralloc_drm.h
@@ -79,8 +79,8 @@
 	return gralloc_drm_bo_register(drm, handle, 0);
 }
 
-int gralloc_drm_bo_map(struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, int enable_write, void **addr);
-void gralloc_drm_bo_unmap(struct gralloc_drm_bo_t *bo);
+int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, int enable_write, void **addr);
+void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo);
 buffer_handle_t gralloc_drm_bo_get_handle(struct gralloc_drm_bo_t *bo, int *stride);
 
 int gralloc_drm_bo_need_fb(const struct gralloc_drm_bo_t *bo);
diff --git a/gralloc_drm_priv.h b/gralloc_drm_priv.h
index 0838db7..ada152d 100644
--- a/gralloc_drm_priv.h
+++ b/gralloc_drm_priv.h
@@ -107,6 +107,9 @@
 	int imported;  /* the handle is from a remote proces when true */
 	int fb_handle; /* the GEM handle of the bo */
 	int fb_id;     /* the fb id */
+
+	int lock_count;
+	int locked_for;
 };
 
 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_pipe(int fd, const char *name);