Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 51 additions & 5 deletions drivers/misc/fastrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ struct fastrpc_session_ctx {
int sid;
bool used;
bool valid;
bool allocated;
struct mutex mutex;
};

struct fastrpc_soc_data {
Expand Down Expand Up @@ -353,9 +355,14 @@ static inline u64 fastrpc_sid_offset(struct fastrpc_channel_ctx *cctx,
static void fastrpc_free_map(struct kref *ref)
{
struct fastrpc_map *map;
struct fastrpc_user *fl;

map = container_of(ref, struct fastrpc_map, refcount);

fl = map->fl;
if (!fl)
return;

if (map->table) {
if (map->attr & FASTRPC_ATTR_SECUREMAP) {
struct qcom_scm_vmperm perm;
Expand All @@ -374,10 +381,16 @@ static void fastrpc_free_map(struct kref *ref)
return;
}
}
mutex_lock(&fl->sctx->mutex);
if (!fl->sctx->dev) {
mutex_unlock(&fl->sctx->mutex);
return;
}
dma_buf_unmap_attachment_unlocked(map->attach, map->table,
DMA_BIDIRECTIONAL);
dma_buf_detach(map->buf, map->attach);
dma_buf_put(map->buf);
mutex_unlock(&fl->sctx->mutex);
}

if (map->fl) {
Expand Down Expand Up @@ -434,9 +447,17 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,

static void fastrpc_buf_free(struct fastrpc_buf *buf)
{
dma_free_coherent(buf->dev, buf->size, buf->virt,
fastrpc_ipa_to_dma_addr(buf->fl->cctx, buf->dma_addr));
kfree(buf);
struct fastrpc_user *fl = buf->fl;

if (!fl)
return;
mutex_lock(&fl->sctx->mutex);
if (fl->sctx->dev) {
dma_free_coherent(buf->dev, buf->size, buf->virt,
FASTRPC_PHYS(buf->phys));
kfree(buf);
}
mutex_unlock(&fl->sctx->mutex);
}

static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
Expand All @@ -459,8 +480,10 @@ static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
buf->dev = dev;
buf->raddr = 0;

buf->virt = dma_alloc_coherent(dev, buf->size, &buf->dma_addr,
GFP_KERNEL);
mutex_lock(&fl->sctx->mutex);
if (fl->sctx->dev)
buf->virt = dma_alloc_coherent(dev, buf->size, (dma_addr_t *)&buf->phys, GFP_KERNEL);
mutex_unlock(&fl->sctx->mutex);
if (!buf->virt) {
mutex_destroy(&buf->lock);
kfree(buf);
Expand Down Expand Up @@ -503,6 +526,10 @@ static void fastrpc_channel_ctx_free(struct kref *ref)
struct fastrpc_channel_ctx *cctx;

cctx = container_of(ref, struct fastrpc_channel_ctx, refcount);
for (int i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
if (cctx->session[i].allocated)
mutex_destroy(&cctx->session[i].mutex);
}

kfree(cctx);
}
Expand Down Expand Up @@ -846,19 +873,29 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
goto get_err;
}

mutex_lock(&fl->sctx->mutex);
if (!fl->sctx->dev) {
err = -ENODEV;
mutex_unlock(&fl->sctx->mutex);
goto attach_err;
}

map->attach = dma_buf_attach(map->buf, sess->dev);
if (IS_ERR(map->attach)) {
dev_err(sess->dev, "Failed to attach dmabuf\n");
err = PTR_ERR(map->attach);
mutex_unlock(&fl->sctx->mutex);
goto attach_err;
}

table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL);
if (IS_ERR(table)) {
err = PTR_ERR(table);
mutex_unlock(&fl->sctx->mutex);
goto map_err;
}
map->table = table;
mutex_unlock(&fl->sctx->mutex);

if (attr & FASTRPC_ATTR_SECUREMAP)
map->dma_addr = sg_phys(map->table->sgl);
Expand Down Expand Up @@ -2364,6 +2401,8 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
sess->used = false;
sess->valid = true;
sess->dev = dev;
mutex_init(&sess->mutex);
sess->allocated = true;
dev_set_drvdata(dev, sess);

if (cctx->domain_id == CDSP_DOMAIN_ID)
Expand All @@ -2380,6 +2419,8 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
break;
dup_sess = &cctx->session[cctx->sesscount++];
memcpy(dup_sess, sess, sizeof(*dup_sess));
mutex_init(&dup_sess->mutex);
dup_sess->allocated = true;
}
}
spin_unlock_irqrestore(&cctx->lock, flags);
Expand All @@ -2402,6 +2443,11 @@ static void fastrpc_cb_remove(struct platform_device *pdev)
spin_lock_irqsave(&cctx->lock, flags);
for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
if (cctx->session[i].sid == sess->sid) {
spin_unlock_irqrestore(&cctx->lock, flags);
mutex_lock(&cctx->session[i].mutex);
cctx->session[i].dev = NULL;
mutex_unlock(&cctx->session[i].mutex);
spin_lock_irqsave(&cctx->lock, flags);
cctx->session[i].valid = false;
cctx->sesscount--;
}
Expand Down