@@ -312,6 +312,7 @@ struct fastrpc_session_ctx {
int sid;
bool used;
bool valid;
+ bool sharedcb;
};
struct fastrpc_static_pd {
@@ -371,6 +372,7 @@ struct fastrpc_user {
int pd;
bool is_secure_dev;
bool is_unsigned_pd;
+ bool sharedcb;
char *servloc_name;
/* Lock for lists */
spinlock_t lock;
@@ -879,6 +881,37 @@ static const struct dma_buf_ops fastrpc_dma_buf_ops = {
.release = fastrpc_release,
};
+static struct fastrpc_session_ctx *fastrpc_session_alloc(
+ struct fastrpc_channel_ctx *cctx, bool sharedcb)
+{
+ struct fastrpc_session_ctx *session = NULL;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&cctx->lock, flags);
+ for (i = 0; i < cctx->sesscount; i++) {
+ if (!cctx->session[i].used && cctx->session[i].valid &&
+ cctx->session[i].sharedcb == sharedcb) {
+ cctx->session[i].used = true;
+ session = &cctx->session[i];
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cctx->lock, flags);
+
+ return session;
+}
+
+static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
+ struct fastrpc_session_ctx *session)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cctx->lock, flags);
+ session->used = false;
+ spin_unlock_irqrestore(&cctx->lock, flags);
+}
+
static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
@@ -1545,6 +1578,12 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
goto err_name;
}
+ fl->sctx = fastrpc_session_alloc(fl->cctx, fl->sharedcb);
+ if (!fl->sctx) {
+ err = -EBUSY;
+ goto err_name;
+ }
+
if (!fl->cctx->staticpd_status) {
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, &buf);
if (err)
@@ -1674,6 +1713,12 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
goto err;
}
+ fl->sctx = fastrpc_session_alloc(fl->cctx, fl->sharedcb);
+ if (!fl->sctx) {
+ err = -EBUSY;
+ goto err;
+ }
+
inbuf.pgid = fl->tgid;
inbuf.namelen = strlen(current->comm) + 1;
inbuf.filelen = init.filelen;
@@ -1749,36 +1794,6 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
return err;
}
-static struct fastrpc_session_ctx *fastrpc_session_alloc(
- struct fastrpc_channel_ctx *cctx)
-{
- struct fastrpc_session_ctx *session = NULL;
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&cctx->lock, flags);
- for (i = 0; i < cctx->sesscount; i++) {
- if (!cctx->session[i].used && cctx->session[i].valid) {
- cctx->session[i].used = true;
- session = &cctx->session[i];
- break;
- }
- }
- spin_unlock_irqrestore(&cctx->lock, flags);
-
- return session;
-}
-
-static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
- struct fastrpc_session_ctx *session)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cctx->lock, flags);
- session->used = false;
- spin_unlock_irqrestore(&cctx->lock, flags);
-}
-
static void fastrpc_context_list_free(struct fastrpc_user *fl)
{
struct fastrpc_invoke_ctx *ctx, *n;
@@ -1882,15 +1897,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->cctx = cctx;
fl->is_secure_dev = fdevice->secure;
- fl->sctx = fastrpc_session_alloc(cctx);
- if (!fl->sctx) {
- dev_err(&cctx->rpdev->dev, "No session available\n");
- mutex_destroy(&fl->mutex);
- kfree(fl);
-
- return -EBUSY;
- }
-
spin_lock_irqsave(&cctx->lock, flags);
list_add_tail(&fl->user, &cctx->users);
spin_unlock_irqrestore(&cctx->lock, flags);
@@ -1949,6 +1955,10 @@ static int fastrpc_init_attach(struct fastrpc_user *fl, int pd)
struct fastrpc_enhanced_invoke ioctl;
int tgid = fl->tgid;
+ fl->sctx = fastrpc_session_alloc(fl->cctx, fl->sharedcb);
+ if (!fl->sctx)
+ return -EBUSY;
+
args[0].ptr = (u64)(uintptr_t) &tgid;
args[0].length = sizeof(tgid);
args[0].fd = -1;
@@ -2001,11 +2011,33 @@ static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp)
return err;
}
+static int fastrpc_internal_control(struct fastrpc_user *fl,
+ struct fastrpc_internal_control *cp)
+{
+ int err = 0;
+
+ if (!fl)
+ return -EBADF;
+ if (!cp)
+ return -EINVAL;
+
+ switch (cp->req) {
+ case FASTRPC_CONTROL_SMMU:
+ fl->sharedcb = cp->smmu.sharedcb;
+ break;
+ default:
+ err = -EBADRQC;
+ break;
+ }
+ return err;
+}
+
static int fastrpc_multimode_invoke(struct fastrpc_user *fl, char __user *argp)
{
struct fastrpc_enhanced_invoke einv;
struct fastrpc_invoke_args *args = NULL;
struct fastrpc_ioctl_multimode_invoke invoke;
+ struct fastrpc_internal_control cp = {0};
u32 nscalars;
u64 *perf_kernel;
int err, i;
@@ -2049,6 +2081,12 @@ static int fastrpc_multimode_invoke(struct fastrpc_user *fl, char __user *argp)
err = fastrpc_internal_invoke(fl, false, &einv);
kfree(args);
break;
+ case FASTRPC_INVOKE_CONTROL:
+ if (copy_from_user(&cp, (void __user *)(uintptr_t)invoke.invparam, sizeof(cp)))
+ return -EFAULT;
+
+ err = fastrpc_internal_control(fl, &cp);
+ break;
default:
err = -ENOTTY;
break;
@@ -2738,6 +2776,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
if (sessions > 0) {
struct fastrpc_session_ctx *dup_sess;
+ sess->sharedcb = true;
for (i = 1; i < sessions; i++) {
if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
break;
@@ -166,6 +166,27 @@ struct fastrpc_ioctl_capability {
__u32 reserved[4];
};
+enum fastrpc_control_type {
+ FASTRPC_CONTROL_LATENCY = 1,
+ FASTRPC_CONTROL_SMMU = 2,
+ FASTRPC_CONTROL_KALLOC = 3,
+ FASTRPC_CONTROL_WAKELOCK = 4,
+ FASTRPC_CONTROL_PM = 5,
+ FASTRPC_CONTROL_DSPPROCESS_CLEAN = 6,
+ FASTRPC_CONTROL_RPC_POLL = 7,
+ FASTRPC_CONTROL_ASYNC_WAKE = 8,
+ FASTRPC_CONTROL_NOTIF_WAKE = 9,
+};
+
+struct fastrpc_ctrl_smmu {
+ u32 sharedcb; /* Set to SMMU share context bank */
+};
+
+struct fastrpc_internal_control {
+ u32 req;
+ struct fastrpc_ctrl_smmu smmu;
+};
+
enum fastrpc_perfkeys {
PERF_COUNT = 0,
PERF_FLUSH = 1,