@@ -359,6 +359,7 @@ struct fastrpc_user {
struct list_head user;
struct list_head maps;
struct list_head pending;
+ struct list_head interrupted;
struct list_head mmaps;
struct fastrpc_channel_ctx *cctx;
@@ -740,6 +741,40 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
return ERR_PTR(ret);
}
+static struct fastrpc_invoke_ctx *fastrpc_context_restore_interrupted(
+ struct fastrpc_user *fl, struct fastrpc_invoke *inv)
+{
+ struct fastrpc_invoke_ctx *ctx = NULL, *ictx = NULL, *n;
+
+ spin_lock(&fl->lock);
+ list_for_each_entry_safe(ictx, n, &fl->interrupted, node) {
+ if (ictx->pid == current->pid) {
+ if (inv->sc != ictx->sc || ictx->fl != fl) {
+ dev_err(ictx->fl->sctx->dev,
+ "interrupted sc (0x%x) or fl (%pK) does not match with invoke sc (0x%x) or fl (%pK)\n",
+ ictx->sc, ictx->fl, inv->sc, fl);
+ spin_unlock(&fl->lock);
+ return ERR_PTR(-EINVAL);
+ }
+ ctx = ictx;
+ list_del(&ctx->node);
+ list_add_tail(&ctx->node, &fl->pending);
+ break;
+ }
+ }
+ spin_unlock(&fl->lock);
+ return ctx;
+}
+
+static void fastrpc_context_save_interrupted(
+ struct fastrpc_invoke_ctx *ctx)
+{
+ spin_lock(&ctx->fl->lock);
+ list_del(&ctx->node);
+ list_add_tail(&ctx->node, &ctx->fl->interrupted);
+ spin_unlock(&ctx->fl->lock);
+}
+
static struct sg_table *
fastrpc_map_dma_buf(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
@@ -1292,6 +1327,14 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
return -EPERM;
}
+ if (!kernel) {
+ ctx = fastrpc_context_restore_interrupted(fl, inv);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+ if (ctx)
+ goto wait;
+ }
+
ctx = fastrpc_context_alloc(fl, kernel, sc, invoke);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -1313,6 +1356,7 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
goto bail;
PERF_END);
+wait:
if (kernel) {
if (!wait_for_completion_timeout(&ctx->work, 10 * HZ))
err = -ETIMEDOUT;
@@ -1338,12 +1382,9 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
goto bail;
bail:
- if (err != -ERESTARTSYS && err != -ETIMEDOUT) {
- /* We are done with this compute context */
- spin_lock(&fl->lock);
- list_del(&ctx->node);
- spin_unlock(&fl->lock);
- fastrpc_context_put(ctx);
+ if (err == -ERESTARTSYS) {
+ if (ctx)
+ fastrpc_context_save_interrupted(ctx);
} else if (ctx) {
if (fl->profile && !err)
fastrpc_update_invoke_count(handle, perf_counter, &invoket);
@@ -1353,6 +1394,10 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
if (perferr)
dev_info(fl->sctx->dev, "Warning: failed to copy perf data %d\n", perferr);
}
+ spin_lock(&fl->lock);
+ list_del(&ctx->node);
+ spin_unlock(&fl->lock);
+ fastrpc_context_put(ctx);
}
if (err)
@@ -1734,6 +1779,25 @@ static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
spin_unlock_irqrestore(&cctx->lock, flags);
}
+static void fastrpc_context_list_free(struct fastrpc_user *fl)
+{
+ struct fastrpc_invoke_ctx *ctx, *n;
+
+ list_for_each_entry_safe(ctx, n, &fl->interrupted, node) {
+ spin_lock(&fl->lock);
+ list_del(&ctx->node);
+ spin_unlock(&fl->lock);
+ fastrpc_context_put(ctx);
+ }
+
+ list_for_each_entry_safe(ctx, n, &fl->pending, node) {
+ spin_lock(&fl->lock);
+ list_del(&ctx->node);
+ spin_unlock(&fl->lock);
+ fastrpc_context_put(ctx);
+ }
+}
+
static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl)
{
struct fastrpc_invoke_args args[1];
@@ -1756,7 +1820,6 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
{
struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data;
struct fastrpc_channel_ctx *cctx = fl->cctx;
- struct fastrpc_invoke_ctx *ctx, *n;
struct fastrpc_map *map, *m;
struct fastrpc_buf *buf, *b;
unsigned long flags;
@@ -1770,10 +1833,7 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
if (fl->init_mem)
fastrpc_buf_free(fl->init_mem);
- list_for_each_entry_safe(ctx, n, &fl->pending, node) {
- list_del(&ctx->node);
- fastrpc_context_put(ctx);
- }
+ fastrpc_context_list_free(fl);
list_for_each_entry_safe(map, m, &fl->maps, node)
fastrpc_map_put(map);
@@ -1814,6 +1874,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
spin_lock_init(&fl->lock);
mutex_init(&fl->mutex);
INIT_LIST_HEAD(&fl->pending);
+ INIT_LIST_HEAD(&fl->interrupted);
INIT_LIST_HEAD(&fl->maps);
INIT_LIST_HEAD(&fl->mmaps);
INIT_LIST_HEAD(&fl->user);