#include <linux/device.h>
#include <linux/dma-buf.h>
#include <linux/fdtable.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/tee_drv.h>
{
struct tee_device *teedev = shm->teedev;
- mutex_lock(&teedev->mutex);
- idr_remove(&teedev->idr, shm->id);
- if (shm->ctx)
- list_del(&shm->link);
- mutex_unlock(&teedev->mutex);
+ xa_erase(&teedev->shms, shm->id);
if (shm->flags & TEE_SHM_POOL) {
struct tee_shm_pool_mgr *poolm;
goto err_kfree;
}
- mutex_lock(&teedev->mutex);
- shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
- mutex_unlock(&teedev->mutex);
- if (shm->id < 0) {
- ret = ERR_PTR(shm->id);
+ rc = xa_alloc(&teedev->shms, &shm->id, shm, xa_limit_32b, GFP_KERNEL);
+ if (rc < 0) {
+ ret = ERR_PTR(rc);
goto err_pool_free;
}
}
}
- if (ctx) {
+ if (ctx)
teedev_ctx_get(ctx);
- mutex_lock(&teedev->mutex);
- list_add_tail(&shm->link, &ctx->list_shm);
- mutex_unlock(&teedev->mutex);
- }
return shm;
err_rem:
- mutex_lock(&teedev->mutex);
- idr_remove(&teedev->idr, shm->id);
- mutex_unlock(&teedev->mutex);
+ xa_erase(&teedev->shms, shm->id);
err_pool_free:
poolm->ops->free(poolm, shm);
err_kfree:
shm = kzalloc(sizeof(*shm), GFP_KERNEL);
if (!shm) {
ret = ERR_PTR(-ENOMEM);
- goto err;
+ goto err_free;
}
shm->flags = flags | TEE_SHM_REGISTER;
shm->teedev = teedev;
shm->ctx = ctx;
- shm->id = -1;
start = rounddown(addr, PAGE_SIZE);
shm->offset = addr - start;
shm->size = length;
shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL);
if (!shm->pages) {
ret = ERR_PTR(-ENOMEM);
- goto err;
+ goto err_free;
}
rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages);
if (rc >= 0)
rc = -ENOMEM;
ret = ERR_PTR(rc);
- goto err;
+ goto err_pages;
}
- mutex_lock(&teedev->mutex);
- shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
- mutex_unlock(&teedev->mutex);
-
- if (shm->id < 0) {
- ret = ERR_PTR(shm->id);
- goto err;
+ rc = xa_alloc(&teedev->shms, &shm->id, shm, xa_limit_32b, GFP_KERNEL);
+ if (rc < 0) {
+ ret = ERR_PTR(rc);
+ goto err_pages;
}
rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
shm->num_pages, start);
if (rc) {
ret = ERR_PTR(rc);
- goto err;
+ goto err_erase;
}
if (flags & TEE_SHM_DMA_BUF) {
if (IS_ERR(shm->dmabuf)) {
ret = ERR_CAST(shm->dmabuf);
teedev->desc->ops->shm_unregister(ctx, shm);
- goto err;
+ goto err_erase;
}
}
- mutex_lock(&teedev->mutex);
- list_add_tail(&shm->link, &ctx->list_shm);
- mutex_unlock(&teedev->mutex);
-
return shm;
-err:
- if (shm) {
- size_t n;
- if (shm->id >= 0) {
- mutex_lock(&teedev->mutex);
- idr_remove(&teedev->idr, shm->id);
- mutex_unlock(&teedev->mutex);
- }
- if (shm->pages) {
- for (n = 0; n < shm->num_pages; n++)
- put_page(shm->pages[n]);
- kfree(shm->pages);
- }
+err_erase:
+ xa_erase(&teedev->shms, shm->id);
+err_pages:
+ if (shm->pages) {
+ size_t n;
+ for (n = 0; n < shm->num_pages; n++)
+ put_page(shm->pages[n]);
+ kfree(shm->pages);
}
+err_free:
kfree(shm);
teedev_ctx_put(ctx);
tee_device_put(teedev);
return ERR_PTR(-EINVAL);
teedev = ctx->teedev;
- mutex_lock(&teedev->mutex);
- shm = idr_find(&teedev->idr, id);
+ xa_lock(&teedev->shms);
+ shm = xa_load(&teedev->shms, id);
if (!shm || shm->ctx != ctx)
shm = ERR_PTR(-EINVAL);
else if (shm->flags & TEE_SHM_DMA_BUF)
get_dma_buf(shm->dmabuf);
- mutex_unlock(&teedev->mutex);
+ xa_unlock(&teedev->shms);
return shm;
}
EXPORT_SYMBOL_GPL(tee_shm_get_from_id);