summaryrefslogtreecommitdiff
path: root/gxp-common-platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxp-common-platform.c')
-rw-r--r--gxp-common-platform.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/gxp-common-platform.c b/gxp-common-platform.c
index 7514b11..6318e98 100644
--- a/gxp-common-platform.c
+++ b/gxp-common-platform.c
@@ -280,8 +280,7 @@ error_destroy:
return ret;
}
-static int gxp_unmap_buffer(struct gxp_client *client,
- struct gxp_map_ioctl __user *argp)
+static int gxp_unmap_buffer(struct gxp_client *client, struct gxp_map_ioctl __user *argp)
{
struct gxp_dev *gxp = client->gxp;
struct gxp_map_ioctl ibuf;
@@ -300,29 +299,32 @@ static int gxp_unmap_buffer(struct gxp_client *client,
goto out;
}
- map = gxp_vd_mapping_search(client->vd,
- (dma_addr_t)ibuf.device_address);
+ down_write(&client->vd->mappings_semaphore);
+
+ map = gxp_vd_mapping_search_locked(client->vd, (dma_addr_t)ibuf.device_address);
if (!map) {
- dev_err(gxp->dev,
- "Mapping not found for provided device address %#llX\n",
+ dev_err(gxp->dev, "Mapping not found for provided device address %#llX\n",
ibuf.device_address);
ret = -EINVAL;
- goto out;
} else if (!map->host_address) {
dev_err(gxp->dev, "dma-bufs must be unmapped via GXP_UNMAP_DMABUF\n");
ret = -EINVAL;
- goto out;
}
- WARN_ON(map->host_address != ibuf.host_address);
+ if (ret) {
+ up_write(&client->vd->mappings_semaphore);
+ goto out_put;
+ }
+
+ gxp_vd_mapping_remove_locked(client->vd, map);
+ up_write(&client->vd->mappings_semaphore);
- gxp_vd_mapping_remove(client->vd, map);
- gxp_mapping_iova_log(client, map,
- GXP_IOVA_LOG_UNMAP | GXP_IOVA_LOG_BUFFER);
+ gxp_mapping_iova_log(client, map, GXP_IOVA_LOG_UNMAP | GXP_IOVA_LOG_BUFFER);
+out_put:
/* Release the reference from gxp_vd_mapping_search() */
- gxp_mapping_put(map);
-
+ if (map)
+ gxp_mapping_put(map);
out:
up_read(&client->semaphore);
@@ -1335,8 +1337,7 @@ out_unlock:
return ret;
}
-static int gxp_unmap_dmabuf(struct gxp_client *client,
- struct gxp_map_dmabuf_ioctl __user *argp)
+static int gxp_unmap_dmabuf(struct gxp_client *client, struct gxp_map_dmabuf_ioctl __user *argp)
{
struct gxp_dev *gxp = client->gxp;
struct gxp_map_dmabuf_ioctl ibuf;
@@ -1355,14 +1356,17 @@ static int gxp_unmap_dmabuf(struct gxp_client *client,
goto out;
}
+ down_write(&client->vd->mappings_semaphore);
+
/*
* Fetch and remove the internal mapping records.
* If host_address is not 0, the provided device_address belongs to a
* non-dma-buf mapping.
*/
- mapping = gxp_vd_mapping_search(client->vd, ibuf.device_address);
+ mapping = gxp_vd_mapping_search_locked(client->vd, ibuf.device_address);
if (IS_ERR_OR_NULL(mapping) || mapping->host_address) {
dev_warn(gxp->dev, "No dma-buf mapped for given IOVA\n");
+ up_write(&client->vd->mappings_semaphore);
/*
* If the device address belongs to a non-dma-buf mapping,
* release the reference to it obtained via the search.
@@ -1374,10 +1378,10 @@ static int gxp_unmap_dmabuf(struct gxp_client *client,
}
/* Remove the mapping from its VD, releasing the VD's reference */
- gxp_vd_mapping_remove(client->vd, mapping);
+ gxp_vd_mapping_remove_locked(client->vd, mapping);
+ up_write(&client->vd->mappings_semaphore);
- gxp_mapping_iova_log(client, mapping,
- GXP_IOVA_LOG_UNMAP | GXP_IOVA_LOG_DMABUF);
+ gxp_mapping_iova_log(client, mapping, GXP_IOVA_LOG_UNMAP | GXP_IOVA_LOG_DMABUF);
/* Release the reference from gxp_vd_mapping_search() */
gxp_mapping_put(mapping);