Просмотр исходного кода

msm: adsprpc: Support multiple sessions per process

Currently a process is limited to create only 2 sessions, by toggling
the 30th bit of tgid of the process, to create different process IDs on DSP
remote sybsystem. This approach is not scalable to create unique process
IDs to DSP, by using bits within the tgid of the process. Add support to
allow a process to create multiple sessions by choosing and sending unique
dsp process IDs on DSP remote sub system, instead of tgid of HLOS process.

Change-Id: I33f52c68453301bdbb83dfb9a10df16143098a49
Signed-off-by: Himateja Reddy <[email protected]>
Himateja Reddy 2 лет назад
Родитель
Сommit
6e70c954d5
2 измененных файлов с 115 добавлено и 45 удалено
  1. 106 45
      dsp/adsprpc.c
  2. 9 0
      dsp/adsprpc_shared.h

+ 106 - 45
dsp/adsprpc.c

@@ -106,9 +106,6 @@
 #define M_KERNEL_PERF_LIST (PERF_KEY_MAX)
 #define M_DSP_PERF_LIST (12)
 
-#define SESSION_ID_INDEX (30)
-#define SESSION_ID_MASK (1 << SESSION_ID_INDEX)
-#define PROCESS_ID_MASK ((2^SESSION_ID_INDEX) - 1)
 #define FASTRPC_CTX_MAGIC (0xbeeddeed)
 
 /* Process status notifications from DSP will be sent with this unique context */
@@ -203,6 +200,9 @@
 /* Max no. of persistent headers pre-allocated per process */
 #define MAX_PERSISTENT_HEADERS    (25)
 
+/* Max value of unique fastrpc tgid */
+#define MAX_FRPC_TGID 65
+
 #define PERF_CAPABILITY_SUPPORT	(1 << 1)
 #define KERNEL_ERROR_CODE_V1_SUPPORT	1
 #define USERSPACE_ALLOCATION_SUPPORT	1
@@ -229,6 +229,9 @@
 /* Unique index flag used for mini dump */
 static int md_unique_index_flag[MAX_UNIQUE_ID] = { 0, 0, 0, 0, 0 };
 
+/* Array to keep track unique tgid_frpc usage */
+static bool frpc_tgid_usage_array[NUM_CHANNELS][MAX_FRPC_TGID] = {0};
+
 /* Fastrpc remote process attributes */
 enum fastrpc_proc_attr {
 	/* Macro for Debug attr */
@@ -1836,6 +1839,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 	}
 	ctx->retval = -1;
 	ctx->pid = current->pid;
+	/* Store HLOS PID in context, it is not being sent to DSP */
 	ctx->tgid = fl->tgid;
 	init_completion(&ctx->work);
 	ctx->magic = FASTRPC_CTX_MAGIC;
@@ -1854,6 +1858,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 			goto bail;
 		}
 		memset(ctx->perf, 0, sizeof(*(ctx->perf)));
+		/* Use HLOS PID, as perf tid is not being sent to DSP and is used to log in traces */
 		ctx->perf->tid = fl->tgid;
 	}
 	if (invokefd->job) {
@@ -2033,13 +2038,11 @@ static void fastrpc_notif_find_process(int domain, struct smq_notif_rspv3 *notif
 	struct fastrpc_file *fl = NULL;
 	struct hlist_node *n;
 	bool is_process_found = false;
-	int sessionid = 0;
 	unsigned long irq_flags = 0;
 
 	spin_lock_irqsave(&me->hlock, irq_flags);
 	hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
-		if (fl->tgid == notif->pid ||
-				(fl->tgid == (notif->pid & PROCESS_ID_MASK))) {
+		if (fl->tgid_frpc == notif->pid) {
 			is_process_found = true;
 			break;
 		}
@@ -2048,9 +2051,7 @@ static void fastrpc_notif_find_process(int domain, struct smq_notif_rspv3 *notif
 
 	if (!is_process_found)
 		return;
-	if (notif->pid & SESSION_ID_MASK)
-		sessionid = 1;
-	fastrpc_queue_pd_status(fl, domain, notif->status, sessionid);
+	fastrpc_queue_pd_status(fl, domain, notif->status, fl->sessionid);
 }
 
 static void context_notify_user(struct smq_invoke_ctx *ctx,
@@ -2896,10 +2897,9 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
 
 	channel_ctx = &fl->apps->channel[cid];
 	mutex_lock(&channel_ctx->smd_mutex);
-	msg->pid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	msg->pid = fl->tgid_frpc;
 	msg->tid = current->pid;
-	if (fl->sessionid)
-		msg->tid |= SESSION_ID_MASK;
 	if (kernel == KERNEL_MSG_WITH_ZERO_PID)
 		msg->pid = 0;
 	msg->invoke.header.ctx = ctx->ctxid | fl->pd;
@@ -2997,6 +2997,7 @@ static void fastrpc_init(struct fastrpc_apps *me)
 	spin_lock_init(&me->hlock);
 	me->channel = &gcinfo[0];
 	mutex_init(&me->mut_uid);
+	me->max_sess_per_proc = DEFAULT_MAX_SESS_PER_PROC;
 	for (i = 0; i < NUM_CHANNELS; i++) {
 		init_completion(&me->channel[i].work);
 		init_completion(&me->channel[i].workport);
@@ -3576,6 +3577,16 @@ static int fastrpc_set_session_info(
 	// Processes attaching to Sensor Static PD, share context bank.
 	if (sess_info->pd_type == SENSORS_STATICPD)
 		fl->sharedcb = 1;
+	if (sess_info->session_id >= me->max_sess_per_proc) {
+		ADSPRPC_ERR(
+		"Session ID %u cannot be beyond %u\n",
+				sess_info->session_id, me->max_sess_per_proc);
+		err = -EBADR;
+		goto bail;
+	}
+	fl->sessionid = sess_info->session_id;
+	// Set multi_session_support, to disable old way of setting session_id
+	fl->multi_session_support = true;
 	VERIFY(err, 0 == (err = fastrpc_get_info(fl, &(sess_info->domain_id))));
 	if (err)
 		goto bail;
@@ -3826,7 +3837,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl, int locked);
 static int fastrpc_init_attach_process(struct fastrpc_file *fl,
 					struct fastrpc_ioctl_init *init)
 {
-	int err = 0, tgid = fl->tgid;
+	int err = 0, tgid = fl->tgid_frpc;
 	remote_arg_t ra[1];
 	struct fastrpc_ioctl_invoke_async ioctl;
 
@@ -3839,6 +3850,7 @@ static int fastrpc_init_attach_process(struct fastrpc_file *fl,
 	/*
 	 * Prepare remote arguments for creating thread group
 	 * in guestOS/staticPD on the remote subsystem.
+	 * Send unique fastrpc id to dsp
 	 */
 	ra[0].buf.pv = (void *)&tgid;
 	ra[0].buf.len = sizeof(tgid);
@@ -3922,7 +3934,7 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
 
 	spin_unlock(&fl->hlock);
 
-	inbuf.pgid = fl->tgid;
+	inbuf.pgid = fl->tgid_frpc;
 	inbuf.namelen = strlen(current->comm) + 1;
 	inbuf.filelen = init->filelen;
 	fl->pd = FASTRPC_USER_PD;
@@ -4183,7 +4195,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
 	}
 
 	fl->pd = FASTRPC_USER_PD;
-	inbuf.pgid = fl->tgid;
+	inbuf.pgid = fl->tgid_frpc;
 	inbuf.namelen = init->filelen;
 	inbuf.pageslen = 0;
 
@@ -4623,7 +4635,8 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
 		err = -ECONNRESET;
 		goto bail;
 	}
-	tgid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	tgid = fl->tgid_frpc;
 	ra[0].buf.pv = (void *)&tgid;
 	ra[0].buf.len = sizeof(tgid);
 	ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
@@ -4682,7 +4695,8 @@ static int fastrpc_mem_map_to_dsp(struct fastrpc_file *fl, int fd, int offset,
 		uint64_t vaddrout;
 	} routargs;
 
-	inargs.pid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	inargs.pid = fl->tgid_frpc;
 	inargs.fd = fd;
 	inargs.offset = offset;
 	inargs.vaddrin = (uintptr_t)va;
@@ -4733,7 +4747,8 @@ static int fastrpc_mem_unmap_to_dsp(struct fastrpc_file *fl, int fd,
 		uint64_t len;
 	} inargs;
 
-	inargs.pid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	inargs.pid = fl->tgid_frpc;
 	inargs.fd = fd;
 	inargs.vaddrin = (uint64_t)va;
 	inargs.len = (uint64_t)size;
@@ -4769,7 +4784,8 @@ static int fastrpc_unmap_on_dsp(struct fastrpc_file *fl,
 		size_t size;
 	} inargs;
 
-	inargs.pid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	inargs.pid = fl->tgid_frpc;
 	inargs.size = size;
 	inargs.vaddrout = raddr;
 	ra[0].buf.pv = (void *)&inargs;
@@ -4821,7 +4837,8 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
 		goto bail;
 	}
 	cid = fl->cid;
-	inargs.pid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	inargs.pid = fl->tgid_frpc;
 	inargs.vaddrin = (uintptr_t)va;
 	inargs.flags = flags;
 	inargs.num = fl->apps->compat ? num * sizeof(page) : num;
@@ -4926,7 +4943,8 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
 		goto bail;
 	}
 
-	tgid = fl->tgid;
+	/* Send unique fastrpc process ID to dsp */
+	tgid = fl->tgid_frpc;
 	ra[0].buf.pv = (void *)&tgid;
 	ra[0].buf.len = sizeof(tgid);
 	ra[1].buf.pv = (void *)&routargs;
@@ -5566,7 +5584,8 @@ static void handle_remote_signal(uint64_t msg, int cid)
 
 	spin_lock_irqsave(&me->hlock, irq_flags);
 	hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
-		if ((fl->tgid == pid) && (fl->cid == cid)) {
+		/* Response from DSP contains unique fastrpc process id, use unique fastrpc process ID to compare */
+		if ((fl->tgid_frpc == pid) && (fl->cid == cid)) {
 			unsigned long fflags = 0;
 
 			spin_lock_irqsave(&fl->dspsignals_lock, fflags);
@@ -5797,6 +5816,10 @@ skip_dump_wait:
 	fl->is_ramdump_pend = false;
 	fl->is_dma_invoke_pend = false;
 	fl->dsp_process_state = PROCESS_CREATE_DEFAULT;
+	VERIFY(err, VALID_FASTRPC_CID(cid));
+	/* Reset the tgid usage to false */
+	if (!err)
+		frpc_tgid_usage_array[cid][fl->tgid_frpc] = false;
 	is_locked = false;
 	spin_unlock_irqrestore(&fl->apps->hlock, irq_flags);
 
@@ -6247,6 +6270,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
 	fl->apps = me;
 	fl->mode = FASTRPC_MODE_SERIAL;
 	fl->cid = -1;
+	fl->tgid_frpc = -1;
 	fl->tvm_remote_domain = -1;
 	fl->dev_minor = dev_minor;
 	fl->init_mem = NULL;
@@ -6258,6 +6282,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
 	fl->is_compat = false;
 	fl->exit_notif = false;
 	fl->exit_async = false;
+	fl->multi_session_support = false;
 	init_completion(&fl->work);
 	init_completion(&fl->dma_invoke);
 	fl->file_close = FASTRPC_PROCESS_DEFAULT_STATE;
@@ -6306,6 +6331,25 @@ bail:
 	return err;
 }
 
+// Generate a unique process ID to DSP process
+static int get_unique_hlos_process_id(uint32_t cid)
+{
+	int tgid_frpc = -1, tgid_index = 1;
+	struct fastrpc_apps *me = &gfa;
+
+	spin_lock(&me->hlock);
+	for (tgid_index = 1; tgid_index < MAX_FRPC_TGID; tgid_index++) {
+		if (!frpc_tgid_usage_array[cid][tgid_index]) {
+			tgid_frpc = tgid_index;
+			/* Set the tgid usage to false */
+			frpc_tgid_usage_array[cid][tgid_index] = true;
+			break;
+		}
+	}
+	spin_unlock(&me->hlock);
+	return tgid_frpc;
+}
+
 static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
 {
 	int err = 0, buf_size = 0;
@@ -6315,6 +6359,13 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
 	memcpy(cur_comm, current->comm, TASK_COMM_LEN);
 	cur_comm[TASK_COMM_LEN-1] = '\0';
 	fl->tgid = current->tgid;
+	fl->tgid_frpc = get_unique_hlos_process_id(cid);
+	VERIFY(err, fl->tgid_frpc != -1);
+	if (err) {
+		ADSPRPC_ERR("too many fastrpc clients, max %u allowed\n", MAX_FRPC_TGID);
+		err = -EUSERS;
+		goto bail;
+	}
 
 	/*
 	 * Third-party apps don't have permission to open the fastrpc device, so
@@ -6347,8 +6398,11 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
 			err = -ENOMEM;
 			return err;
 		}
-		snprintf(fl->debug_buf, buf_size, "%.10s%s%d%s%d",
-			cur_comm, "_", current->pid, "_", cid);
+		/* Use HLOS PID, unique fastrpc PID, CID in debugfs filename,
+		 * for better ability to debug
+		 */
+		snprintf(fl->debug_buf, buf_size, "%.10s%s%d%s%d%s%d",
+			cur_comm, "_", current->pid, "_", fl->tgid_frpc, "_", cid);
 		fl->debugfs_file = debugfs_create_file(fl->debug_buf, 0644,
 			debugfs_root, fl, &debugfs_fops);
 		if (IS_ERR_OR_NULL(fl->debugfs_file)) {
@@ -6374,6 +6428,11 @@ int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
 		err = -EBADF;
 		goto bail;
 	}
+	VERIFY(err, VALID_FASTRPC_CID(cid));
+	if (err) {
+		err = -ECHRNG;
+		goto bail;
+	}
 
 	fastrpc_get_process_gids(&fl->gidlist);
 	err = fastrpc_set_process_info(fl, cid);
@@ -6383,11 +6442,6 @@ int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
 	if (fl->cid == -1) {
 		struct fastrpc_channel_ctx *chan = NULL;
 
-		VERIFY(err, cid < NUM_CHANNELS);
-		if (err) {
-			err = -ECHRNG;
-			goto bail;
-		}
 		chan = &me->channel[cid];
 		/* Check to see if the device node is non-secure */
 		if (fl->dev_minor == MINOR_NUM_DEV) {
@@ -6468,7 +6522,6 @@ int fastrpc_internal_control(struct fastrpc_file *fl,
 	int err = 0;
 	unsigned int latency;
 	struct fastrpc_apps *me = &gfa;
-	int sessionid = 0;
 	unsigned int cpu;
 	unsigned long flags = 0;
 
@@ -6564,9 +6617,7 @@ int fastrpc_internal_control(struct fastrpc_file *fl,
 		break;
 	case FASTRPC_CONTROL_DSPPROCESS_CLEAN:
 		(void)fastrpc_release_current_dsp_process(fl);
-		if (fl->tgid & SESSION_ID_MASK)
-			sessionid = 1;
-		fastrpc_queue_pd_status(fl, fl->cid, FASTRPC_USER_PD_FORCE_KILL, sessionid);
+		fastrpc_queue_pd_status(fl, fl->cid, FASTRPC_USER_PD_FORCE_KILL, fl->sessionid);
 		break;
 	case FASTRPC_CONTROL_RPC_POLL:
 		err = fastrpc_manage_poll_mode(fl, cp->lp.enable, cp->lp.latency);
@@ -6648,8 +6699,8 @@ int fastrpc_setmode(unsigned long ioctl_param,
 				"multiple sessions not allowed for untrusted apps\n");
 			goto bail;
 		}
-		fl->sessionid = 1;
-		fl->tgid |= SESSION_ID_MASK;
+		if (!fl->multi_session_support)
+			fl->sessionid = 1;
 		break;
 	default:
 		err = -ENOTTY;
@@ -6720,8 +6771,9 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
 	// track outgoing signals in the driver. The userspace library does a
 	// basic sanity check and any security validation needs to be done by
 	// the recipient.
-	DSPSIGNAL_VERBOSE("Send signal PID %u, signal %u\n",
-			  (unsigned int)fl->tgid, (unsigned int)sig->signal_id);
+	DSPSIGNAL_VERBOSE("Send signal PID %u, unique fastrpc pid %u signal %u\n",
+			(unsigned int)fl->tgid, (unsigned int)fl->tgid_frpc,
+			(unsigned int)sig->signal_id);
 	VERIFY(err, sig->signal_id < DSPSIGNAL_NUM_SIGNALS);
 	if (err) {
 		ADSPRPC_ERR("Sending bad signal %u for PID %u",
@@ -6745,7 +6797,8 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
 		goto bail;
 	}
 
-	msg = (((uint64_t)fl->tgid) << 32) | ((uint64_t)sig->signal_id);
+	/* Use unique fastrpc pid, to signal DSP process */
+	msg = (((uint64_t)fl->tgid_frpc) << 32) | ((uint64_t)sig->signal_id);
 	err = fastrpc_transport_send(cid, (void *)&msg, sizeof(msg), fl->tvm_remote_domain);
 	mutex_unlock(&channel_ctx->smd_mutex);
 
@@ -7793,10 +7846,10 @@ static int fastrpc_cb_probe(struct device *dev)
 	if (of_get_property(dev->of_node, "pd-type", NULL) != NULL) {
 		err = of_property_read_u32(dev->of_node, "pd-type",
 				&(sess->smmu.pd_type));
+		/* Set cb_pd_type, if the process type is set for context banks */
+		me->cb_pd_type = true;
 		if (err)
 			goto bail;
-		// Set cb_pd_type, if the process type is configured for context banks
-		me->cb_pd_type = true;
 	}
 	if (of_get_property(dev->of_node, "shared-cb", NULL) != NULL) {
 		sess->smmu.sharedcb = 1;
@@ -8131,6 +8184,8 @@ static int fastrpc_probe(struct platform_device *pdev)
 			me->lowest_capacity_core_count = 1;
 		of_property_read_u32(dev->of_node, "qcom,rpc-latency-us",
 			&me->latency);
+		of_property_read_u32(dev->of_node, "qcom,max-sessions",
+			&me->max_sess_per_proc);
 		if (of_get_property(dev->of_node,
 			"qcom,secure-domains", NULL) != NULL) {
 			VERIFY(err, !of_property_read_u32(dev->of_node,
@@ -8564,17 +8619,23 @@ static int fastrpc_device_create(struct fastrpc_file *fl)
 	frpc_dev->dev.parent = &fastrpc_bus;
 	frpc_dev->dev.bus = &fastrpc_bus_type;
 
-	dev_set_name(&frpc_dev->dev, "%s-%d-%d",
-			dev_name(frpc_dev->dev.parent), fl->tgid, fl->cid);
+	/* Use HLOS PID, unique fastrpc process ID and CID to create device file,
+	 * Else names would conflict for multiple sessions
+	 * And also for better ability to debug
+	 */
+	dev_set_name(&frpc_dev->dev, "%s-%d-%d-%d",
+			dev_name(frpc_dev->dev.parent), fl->tgid, fl->tgid_frpc, fl->cid);
 	frpc_dev->dev.release = fastrpc_dev_release;
 	frpc_dev->fl = fl;
-	frpc_dev->handle = fl->tgid;
+	/* Use unique fastrpc tgid as handle */
+	frpc_dev->handle = fl->tgid_frpc;
 
 	err = device_register(&frpc_dev->dev);
 	if (err) {
 		put_device(&frpc_dev->dev);
-		ADSPRPC_ERR("fastrpc device register failed for process %d with error %d\n",
-			fl->tgid, err);
+		ADSPRPC_ERR(
+		"fastrpc device register failed for process %d unique fastrpc tgid %d session %d with error %d\n",
+			fl->tgid, fl->tgid_frpc, fl->sessionid, err);
 		goto bail;
 	}
 	fl->device = frpc_dev;

+ 9 - 0
dsp/adsprpc_shared.h

@@ -88,6 +88,9 @@
 #define NUM_CHANNELS	4	/* adsp, mdsp, slpi, cdsp*/
 #define NUM_SESSIONS	14	/* max 11 compute, 3 cpz */
 
+/* Default maximum sessions allowed per process */
+#define DEFAULT_MAX_SESS_PER_PROC 4
+
 #define VALID_FASTRPC_CID(cid) \
 	(cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS)
 
@@ -753,6 +756,8 @@ struct fastrpc_apps {
 	unsigned int lowest_capacity_core_count;
 	/* Flag to check if PM QoS vote needs to be done for only one core */
 	bool single_core_latency_vote;
+	/* Maximum sessions allowed to be created per process */
+	uint32_t max_sess_per_proc;
 };
 
 struct fastrpc_mmap {
@@ -846,6 +851,8 @@ struct fastrpc_file {
 	int sessionid;
 	int tgid_open;	/* Process ID during device open */
 	int tgid;		/* Process ID that uses device for RPC calls */
+	/* Unique HLOS process ID created by fastrpc for each client */
+	int tgid_frpc;
 	int cid;
 	int tvm_remote_domain;
 	uint64_t ssrcount;
@@ -914,6 +921,8 @@ struct fastrpc_file {
 	* config paramters.
 	*/
 	struct fastrpc_proc_sharedbuf_info sharedbuf_info;
+	/* Flag to indicate 4 session support available */
+	bool multi_session_support;
 };
 
 int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,