Browse Source

Merge c0787f28468755ee714eb9c30e0295c3be79b5a3 on remote branch

Change-Id: I41f52549b780e504201d970cd659501e08f2313a
Linux Build Service Account 2 years ago
parent
commit
c711637df6
6 changed files with 459 additions and 227 deletions
  1. 10 0
      Android.mk
  2. 170 104
      dsp/adsprpc.c
  3. 8 2
      dsp/adsprpc_rpmsg.c
  4. 11 5
      dsp/adsprpc_shared.h
  5. 257 115
      dsp/adsprpc_socket.c
  6. 3 1
      dsp/cdsp-loader.c

+ 10 - 0
Android.mk

@@ -1,3 +1,12 @@
+FASTRPC_DLKM_ENABLED := true
+
+ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
+	ifeq ($(TARGET_KERNEL_DLKM_FASTRPC_OVERRIDE), false)
+		FASTRPC_DLKM_ENABLED := false
+	endif
+endif
+
+ifeq ($(FASTRPC_DLKM_ENABLED), true)
 DLKM_DIR   := device/qcom/common/dlkm
 
 LOCAL_PATH := $(call my-dir)
@@ -39,3 +48,4 @@ $(info KBUILD_OPTIONS = $(KBUILD_OPTIONS))
 $(info intermediates dsp symvers path = $(call intermediates-dir-for,DLKM,dsp-module-symvers))
 $(info DLKM_DIR = $(DLKM_DIR))
 
+endif

+ 170 - 104
dsp/adsprpc.c

@@ -1870,6 +1870,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 		err = -ENOKEY;
 		goto bail;
 	}
+	ctx->xo_time_in_us_created = CONVERT_CNT_TO_US(__arch_counter_get_cntvct());
 	spin_lock(&fl->hlock);
 	hlist_add_head(&ctx->hn, &clst->pending);
 	clst->num_active_ctxs++;
@@ -2860,7 +2861,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
 		memcpy(&msg_temp, msg, sizeof(struct smq_msg));
 		msg = &msg_temp;
 	}
-	err = fastrpc_transport_send(cid, (void *)msg, sizeof(*msg), fl->trusted_vm);
+	err = fastrpc_transport_send(cid, (void *)msg, sizeof(*msg), fl->tvm_remote_domain);
 	trace_fastrpc_transport_send(cid, (uint64_t)ctx, msg->invoke.header.ctx,
 		handle, sc, msg->invoke.page.addr, msg->invoke.page.size);
 	ns = get_timestamp_in_ns();
@@ -3114,6 +3115,8 @@ static void fastrpc_update_invoke_count(uint32_t handle, uint64_t *perf_counter,
 	}
 }
 
+static int fastrpc_check_pd_status(struct fastrpc_file *fl, char *sloc_name);
+
 int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
 				   uint32_t kernel,
 				   struct fastrpc_ioctl_invoke_async *inv)
@@ -3174,6 +3177,18 @@ int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
 	trace_fastrpc_msg("context_alloc: end");
 	if (err)
 		goto bail;
+
+	if (fl->servloc_name) {
+		err = fastrpc_check_pd_status(fl,
+			AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME);
+		err |= fastrpc_check_pd_status(fl,
+			SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME);
+		err |= fastrpc_check_pd_status(fl,
+			SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME);
+		if (err)
+			goto bail;
+	}
+
 	isasyncinvoke = (ctx->asyncjob.isasyncjob ? true : false);
 	if (fl->profile)
 		perf_counter = (uint64_t *)ctx->perf + PERF_COUNT;
@@ -3990,8 +4005,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
 		err = fastrpc_mmap_remove_pdr(fl);
 		if (err)
 			goto bail;
-	} else if (!strcmp(proc_name, "securepd")) {
-		fl->trusted_vm = true;
 	} else {
 		ADSPRPC_ERR(
 			"Create static process is failed for proc_name %s",
@@ -3999,7 +4012,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
 		goto bail;
 	}
 
-	if (!fl->trusted_vm && (!me->staticpd_flags && !me->legacy_remote_heap)) {
+	if ((!me->staticpd_flags && !me->legacy_remote_heap)) {
 		inbuf.pageslen = 1;
 		if (!fastrpc_get_persistent_map(init->memlen, &mem)) {
 			mutex_lock(&fl->map_mutex);
@@ -4025,6 +4038,8 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
 
 			VERIFY(err, NULL != (dst_perms = kcalloc(rhvm->vmcount,
 						sizeof(struct qcom_scm_vmperm), GFP_KERNEL)));
+			if (err)
+				goto bail;
 			for (i = 0; i < rhvm->vmcount; i++) {
 				dst_perms[i].vmid = rhvm->vmid[i];
 				dst_perms[i].perm = rhvm->vmperm[i];
@@ -4193,6 +4208,10 @@ int fastrpc_init_process(struct fastrpc_file *fl,
 	}
 
 	fastrpc_set_servloc(fl, init);
+	err = fastrpc_set_tvm_remote_domain(fl, init);
+	if (err)
+		goto bail;
+
 	err = fastrpc_channel_open(fl, init->flags);
 	if (err)
 		goto bail;
@@ -4401,7 +4420,7 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
 		err = -EBADR;
 		goto bail;
 	}
-	err = verify_transport_device(cid, fl->trusted_vm);
+	err = verify_transport_device(cid, fl->tvm_remote_domain);
 	if (err)
 		goto bail;
 
@@ -4659,7 +4678,8 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
 
 		VERIFY(err, NULL != (dst_perms = kcalloc(rhvm->vmcount,
 					sizeof(struct qcom_scm_vmperm), GFP_KERNEL)));
-
+		if (err)
+			goto bail;
 		for (i = 0; i < rhvm->vmcount; i++) {
 			dst_perms[i].vmid = rhvm->vmid[i];
 			dst_perms[i].perm = rhvm->vmperm[i];
@@ -5539,9 +5559,10 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
 
 	spin_lock_irqsave(&fl->apps->hlock, irq_flags);
 	is_locked = true;
-	if (!fl->is_ramdump_pend) {
+	if (fl->is_dma_invoke_pend)
+		wait_for_completion(&fl->dma_invoke);
+	if (!fl->is_ramdump_pend)
 		goto skip_dump_wait;
-	}
 	is_locked = false;
 	spin_unlock_irqrestore(&fl->apps->hlock, irq_flags);
 	wait_for_completion(&fl->work);
@@ -5553,6 +5574,7 @@ skip_dump_wait:
 	}
 	hlist_del_init(&fl->hn);
 	fl->is_ramdump_pend = false;
+	fl->is_dma_invoke_pend = false;
 	fl->dsp_process_state = PROCESS_CREATE_DEFAULT;
 	is_locked = false;
 	spin_unlock_irqrestore(&fl->apps->hlock, irq_flags);
@@ -5582,6 +5604,7 @@ skip_dump_wait:
 		kfree(fl->hdr_bufs);
 	if (!IS_ERR_OR_NULL(fl->pers_hdr_buf))
 		fastrpc_buf_free(fl->pers_hdr_buf, 0);
+	mutex_lock(&fl->internal_map_mutex);
 	mutex_lock(&fl->map_mutex);
 	do {
 		lmap = NULL;
@@ -5593,6 +5616,7 @@ skip_dump_wait:
 		fastrpc_mmap_free(lmap, 1);
 	} while (lmap);
 	mutex_unlock(&fl->map_mutex);
+	mutex_unlock(&fl->internal_map_mutex);
 
 	if (fl->device && is_driver_closed)
 		device_unregister(&fl->device->dev);
@@ -5768,7 +5792,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
 			"\n=======%s %s %s======\n", title,
 			" LIST OF MAPS ", title);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-			"%-20s|%-20s|%-20s\n", "va", "phys", "size");
+			"%-20s|%-20s|%-20s|%-20s\n", "va", "phys", "size", "flags");
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
 			"%s%s%s%s%s\n",
 			single_line, single_line, single_line,
@@ -5776,9 +5800,9 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
 		mutex_lock(&fl->map_mutex);
 		hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
 			len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-				"0x%-20lX|0x%-20llX|0x%-20zu\n\n",
+				"0x%-20lX|0x%-20llX|0x%-20zu|0x%-17llX\n\n",
 				map->va, map->phys,
-				map->size);
+				map->size, map->flags);
 		}
 		mutex_unlock(&fl->map_mutex);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
@@ -5814,16 +5838,16 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
 			" LIST OF BUFS ", title);
 		spin_lock(&fl->hlock);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-			"%-19s|%-19s|%-19s\n",
-			"virt", "phys", "size");
+			"%-19s|%-19s|%-19s|%-19s\n",
+			"virt", "phys", "size", "flags");
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
 			"%s%s%s%s%s\n", single_line, single_line,
 			single_line, single_line, single_line);
 		hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) {
 			len += scnprintf(fileinfo + len,
 				DEBUGFS_SIZE - len,
-				"0x%-17p|0x%-17llX|%-19zu\n",
-				buf->virt, (uint64_t)buf->phys, buf->size);
+				"0x%-17p|0x%-17llX|%-19zu|0x%-17llX\n",
+				buf->virt, (uint64_t)buf->phys, buf->size, buf->flags);
 		}
 
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
@@ -5906,7 +5930,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl, uint32_t flags)
 	if (err)
 		goto bail;
 
-	err = verify_transport_device(cid, fl->trusted_vm);
+	err = verify_transport_device(cid, fl->tvm_remote_domain);
 	if (err)
 		goto bail;
 
@@ -6000,6 +6024,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
 	fl->apps = me;
 	fl->mode = FASTRPC_MODE_SERIAL;
 	fl->cid = -1;
+	fl->tvm_remote_domain = -1;
 	fl->dev_minor = dev_minor;
 	fl->init_mem = NULL;
 	fl->qos_request = 0;
@@ -6011,6 +6036,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
 	fl->exit_notif = false;
 	fl->exit_async = false;
 	init_completion(&fl->work);
+	init_completion(&fl->dma_invoke);
 	fl->file_close = FASTRPC_PROCESS_DEFAULT_STATE;
 	filp->private_data = fl;
 	mutex_init(&fl->internal_map_mutex);
@@ -6490,7 +6516,7 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
 	}
 
 	msg = (((uint64_t)fl->tgid) << 32) | ((uint64_t)sig->signal_id);
-	err = fastrpc_transport_send(cid, (void *)&msg, sizeof(msg), fl->trusted_vm);
+	err = fastrpc_transport_send(cid, (void *)&msg, sizeof(msg), fl->tvm_remote_domain);
 	mutex_unlock(&channel_ctx->smd_mutex);
 
 bail:
@@ -6889,17 +6915,6 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
 	p.inv.perf_dsp = NULL;
 	p.inv.job = NULL;
 
-	if (fl->servloc_name) {
-		err = fastrpc_check_pd_status(fl,
-			AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME);
-		err |= fastrpc_check_pd_status(fl,
-			SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME);
-		err |= fastrpc_check_pd_status(fl,
-			SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME);
-		if (err)
-			goto bail;
-	}
-
 	spin_lock(&fl->hlock);
 	if (fl->file_close >= FASTRPC_PROCESS_EXIT_START) {
 		err = -ESHUTDOWN;
@@ -8074,8 +8089,7 @@ union fastrpc_dev_param {
 	struct fastrpc_dev_unmap_dma *unmap;
 };
 
-long fastrpc_driver_invoke(struct fastrpc_device *dev, unsigned int invoke_num,
-								unsigned long invoke_param)
+long fastrpc_dev_map_dma(struct fastrpc_device *dev, unsigned long invoke_param)
 {
 	int err = 0;
 	union fastrpc_dev_param p;
@@ -8085,86 +8099,138 @@ long fastrpc_driver_invoke(struct fastrpc_device *dev, unsigned int invoke_num,
 	uintptr_t raddr = 0;
 	unsigned long irq_flags = 0;
 
-	switch (invoke_num) {
-	case FASTRPC_DEV_MAP_DMA:
-		p.map = (struct fastrpc_dev_map_dma *)invoke_param;
-		spin_lock_irqsave(&me->hlock, irq_flags);
-		/* Verify if fastrpc device is closed*/
-		VERIFY(err, dev && !dev->dev_close);
-		if (err) {
-			err = -ESRCH;
-			spin_unlock_irqrestore(&me->hlock, irq_flags);
-			break;
-		}
-		fl = dev->fl;
-		spin_lock(&fl->hlock);
-		/* Verify if fastrpc file is being closed, holding device lock*/
-		if (fl->file_close) {
-			err = -ESRCH;
-			spin_unlock(&fl->hlock);
-			spin_unlock_irqrestore(&me->hlock, irq_flags);
-			break;
-		}
-		spin_unlock(&fl->hlock);
+	p.map = (struct fastrpc_dev_map_dma *)invoke_param;
+	spin_lock_irqsave(&me->hlock, irq_flags);
+	/* Verify if fastrpc device is closed*/
+	VERIFY(err, dev && !dev->dev_close);
+	if (err) {
+		err = -ESRCH;
+		spin_unlock_irqrestore(&me->hlock, irq_flags);
+		return err;
+	}
+	fl = dev->fl;
+	/* Verify if fastrpc file is not NULL*/
+	if (!fl) {
+		err = -EBADF;
+		spin_unlock_irqrestore(&me->hlock, irq_flags);
+		return err;
+	}
+	spin_unlock_irqrestore(&me->hlock, irq_flags);
+	mutex_lock(&fl->internal_map_mutex);
+	spin_lock_irqsave(&me->hlock, irq_flags);
+	/* Verify if fastrpc file is being closed, holding device lock*/
+	if (fl->file_close) {
+		err = -ESRCH;
 		spin_unlock_irqrestore(&me->hlock, irq_flags);
-		mutex_lock(&fl->internal_map_mutex);
+		goto bail;
+	}
+	fl->is_dma_invoke_pend = true;
+	spin_unlock_irqrestore(&me->hlock, irq_flags);
+	mutex_lock(&fl->map_mutex);
+	/* Map DMA buffer on SMMU device*/
+	err = fastrpc_mmap_create(fl, -1, p.map->buf,
+				p.map->attrs, 0, p.map->size,
+				ADSP_MMAP_DMA_BUFFER, &map);
+	mutex_unlock(&fl->map_mutex);
+	if (err)
+		goto bail;
+	/* Map DMA buffer on DSP*/
+	VERIFY(err, 0 == (err = fastrpc_mmap_on_dsp(fl,
+		map->flags, 0, map->phys, map->size, map->refs, &raddr)));
+	if (err)
+		goto bail;
+	map->raddr = raddr;
+	p.map->v_dsp_addr = raddr;
+bail:
+	if (err && map) {
 		mutex_lock(&fl->map_mutex);
-		/* Map DMA buffer on SMMU device*/
-		err = fastrpc_mmap_create(fl, -1, p.map->buf,
-					p.map->attrs, 0, p.map->size,
-					ADSP_MMAP_DMA_BUFFER, &map);
+		fastrpc_mmap_free(map, 0);
 		mutex_unlock(&fl->map_mutex);
-		if (err) {
-			mutex_unlock(&fl->internal_map_mutex);
-			break;
-		}
-		/* Map DMA buffer on DSP*/
-		VERIFY(err, 0 == (err = fastrpc_mmap_on_dsp(fl,
-			map->flags, 0, map->phys, map->size, map->refs, &raddr)));
-		if (err) {
-			mutex_unlock(&fl->internal_map_mutex);
-			break;
-		}
-		map->raddr = raddr;
-		mutex_unlock(&fl->internal_map_mutex);
-		p.map->v_dsp_addr = raddr;
-		break;
-	case FASTRPC_DEV_UNMAP_DMA:
-		p.unmap = (struct fastrpc_dev_unmap_dma *)invoke_param;
+	}
+	if (fl) {
 		spin_lock_irqsave(&me->hlock, irq_flags);
-		/* Verify if fastrpc device is closed*/
-		VERIFY(err, dev && !dev->dev_close);
-		if (err) {
-			err = -ESRCH;
-			spin_unlock_irqrestore(&me->hlock, irq_flags);
-			break;
-		}
-		fl = dev->fl;
-		spin_lock(&fl->hlock);
-		/* Verify if fastrpc file is being closed, holding device lock*/
-		if (fl->file_close) {
-			err = -ESRCH;
-			spin_unlock(&fl->hlock);
-			spin_unlock_irqrestore(&me->hlock, irq_flags);
-			break;
-		}
-		spin_unlock(&fl->hlock);
+		if (fl->file_close && fl->is_dma_invoke_pend)
+			complete(&fl->dma_invoke);
+		fl->is_dma_invoke_pend = false;
 		spin_unlock_irqrestore(&me->hlock, irq_flags);
-		mutex_lock(&fl->internal_map_mutex);
-		mutex_lock(&fl->map_mutex);
-		if (!fastrpc_mmap_find(fl, -1, p.unmap->buf, 0, 0, ADSP_MMAP_DMA_BUFFER, 0, &map)) {
-			/* Un-map DMA buffer on DSP*/
-			mutex_unlock(&fl->map_mutex);
-			VERIFY(err, !(err = fastrpc_munmap_on_dsp(fl, map->raddr,
-				map->phys, map->size, map->flags)));
-			if (err) {
-				mutex_unlock(&fl->internal_map_mutex);
-				break;
-			}
-			fastrpc_mmap_free(map, 0);
-		}
+	}
+	mutex_unlock(&fl->internal_map_mutex);
+	return err;
+}
+
+long fastrpc_dev_unmap_dma(struct fastrpc_device *dev, unsigned long invoke_param)
+{
+	int err = 0;
+	union fastrpc_dev_param p;
+	struct fastrpc_file *fl = NULL;
+	struct fastrpc_mmap *map = NULL;
+	struct fastrpc_apps *me = &gfa;
+	unsigned long irq_flags = 0;
+
+	p.unmap = (struct fastrpc_dev_unmap_dma *)invoke_param;
+	spin_lock_irqsave(&me->hlock, irq_flags);
+	/* Verify if fastrpc device is closed*/
+	VERIFY(err, dev && !dev->dev_close);
+	if (err) {
+		err = -ESRCH;
+		spin_unlock_irqrestore(&me->hlock, irq_flags);
+		return err;
+	}
+	fl = dev->fl;
+	/* Verify if fastrpc file is not NULL*/
+	if (!fl) {
+		err = -EBADF;
+		spin_unlock_irqrestore(&me->hlock, irq_flags);
+		return err;
+	}
+	spin_unlock_irqrestore(&me->hlock, irq_flags);
+	mutex_lock(&fl->internal_map_mutex);
+	spin_lock_irqsave(&me->hlock, irq_flags);
+	/* Verify if fastrpc file is being closed, holding device lock*/
+	if (fl->file_close) {
+		err = -ESRCH;
+		spin_unlock_irqrestore(&me->hlock, irq_flags);
+		goto bail;
+	}
+	fl->is_dma_invoke_pend = true;
+	spin_unlock_irqrestore(&me->hlock, irq_flags);
+	mutex_lock(&fl->map_mutex);
+	if (!fastrpc_mmap_find(fl, -1, p.unmap->buf, 0, 0, ADSP_MMAP_DMA_BUFFER, 0, &map)) {
 		mutex_unlock(&fl->map_mutex);
-		mutex_unlock(&fl->internal_map_mutex);
+		if (err)
+			goto bail;
+		/* Un-map DMA buffer on DSP*/
+		VERIFY(err, !(err = fastrpc_munmap_on_dsp(fl, map->raddr,
+			map->phys, map->size, map->flags)));
+		if (err)
+			goto bail;
+		mutex_lock(&fl->map_mutex);
+		fastrpc_mmap_free(map, 0);
+	}
+	mutex_unlock(&fl->map_mutex);
+bail:
+	if (fl) {
+		spin_lock_irqsave(&me->hlock, irq_flags);
+		if (fl->file_close && fl->is_dma_invoke_pend)
+			complete(&fl->dma_invoke);
+		fl->is_dma_invoke_pend = false;
+		spin_unlock_irqrestore(&me->hlock, irq_flags);
+	}
+	mutex_unlock(&fl->internal_map_mutex);
+	return err;
+}
+
+long fastrpc_driver_invoke(struct fastrpc_device *dev, unsigned int invoke_num,
+								unsigned long invoke_param)
+{
+	int err = 0;
+
+	switch (invoke_num) {
+	case FASTRPC_DEV_MAP_DMA:
+		err = fastrpc_dev_map_dma(dev, invoke_param);
+		break;
+	case FASTRPC_DEV_UNMAP_DMA:
+		err = fastrpc_dev_unmap_dma(dev, invoke_param);
 		break;
 	default:
 		err = -ENOTTY;

+ 8 - 2
dsp/adsprpc_rpmsg.c

@@ -21,7 +21,7 @@ struct frpc_transport_session_control {
 
 static struct frpc_transport_session_control rpmsg_session_control[NUM_CHANNELS];
 
-inline int verify_transport_device(int cid, bool trusted_vm)
+inline int verify_transport_device(int cid, int tvm_remote_domain)
 {
 	int err = 0;
 	struct frpc_transport_session_control *rpmsg_session = &rpmsg_session_control[cid];
@@ -197,7 +197,7 @@ int fastrpc_wait_for_transport_interrupt(int cid,
 	return err;
 }
 
-int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, bool trusted_vm)
+int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, int tvm_remote_domain)
 {
 	int err = 0;
 	struct frpc_transport_session_control *rpmsg_session = &rpmsg_session_control[cid];
@@ -256,6 +256,12 @@ inline void fastrpc_transport_session_deinit(int cid)
 	mutex_destroy(&rpmsg_session_control[cid].rpmsg_mutex);
 }
 
+int fastrpc_set_tvm_remote_domain(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init)
+{
+	fl->tvm_remote_domain = -1;
+	return 0;
+}
+
 int fastrpc_transport_init(void)
 {
 	int err = 0;

+ 11 - 5
dsp/adsprpc_shared.h

@@ -624,14 +624,17 @@ enum fastrpc_process_exit_states {
 	FASTRPC_PROCESS_DSP_EXIT_ERROR				= 4,
 };
 
-inline int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, bool trusted_vm);
+struct fastrpc_file;
+
+int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, int tvm_remote_domain);
 inline int fastrpc_handle_rpc_response(void *data, int len, int cid);
-inline int verify_transport_device(int cid, bool trusted_vm);
+inline int verify_transport_device(int cid, int tvm_remote_domain);
 int fastrpc_transport_init(void);
 void fastrpc_transport_deinit(void);
 void fastrpc_transport_session_init(int cid, char *subsys);
 void fastrpc_transport_session_deinit(int cid);
 int fastrpc_wait_for_transport_interrupt(int cid, unsigned int flags);
+int fastrpc_set_tvm_remote_domain(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init);
 
 static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg64_t *pra,
 							uint32_t sc)
@@ -711,8 +714,6 @@ struct qos_cores {
 	int corecount;
 };
 
-struct fastrpc_file;
-
 struct fastrpc_buf {
 	struct hlist_node hn;
 	struct hlist_node hn_rem;
@@ -831,6 +832,7 @@ struct smq_invoke_ctx {
 	uint32_t sc_interrupted;
 	struct fastrpc_file *fl_interrupted;
 	uint32_t handle_interrupted;
+	uint64_t xo_time_in_us_created; /* XO Timestamp (in us) of ctx creation */
 	uint64_t xo_time_in_us_interrupted; /* XO Timestamp (in us) of interrupted ctx */
 	uint64_t xo_time_in_us_restored; /* XO Timestamp (in us) of restored ctx */
 	int tx_index; /* index of current ctx in channel gmsg_log array */
@@ -1053,7 +1055,7 @@ struct fastrpc_file {
 	int tgid_open;	/* Process ID during device open */
 	int tgid;		/* Process ID that uses device for RPC calls */
 	int cid;
-	bool trusted_vm;
+	int tvm_remote_domain;
 	uint64_t ssrcount;
 	int pd;
 	char *servloc_name;
@@ -1089,6 +1091,10 @@ struct fastrpc_file {
 	struct completion work;
 	/* Flag to indicate ram dump collection status*/
 	bool is_ramdump_pend;
+	/* Process kill will wait on bus driver invoke thread to complete its process */
+	struct completion dma_invoke;
+	/* Flag to indicate invoke pending */
+	bool is_dma_invoke_pend;
 	/* Flag to indicate type of process (static, dynamic) */
 	uint32_t proc_flags;
 	/* If set, threads will poll for DSP response instead of glink wait */

+ 257 - 115
dsp/adsprpc_socket.c

@@ -1,6 +1,21 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* For debug only. Uncomment these blocks to log on every VERIFY statement */
+
+/*
+ * #ifndef VERIFY_PRINT_ERROR
+ * #define VERIFY_PRINT_ERROR
+ * #endif
+ */
+
+/*
+ * #ifndef VERIFY_PRINT_INFO
+ * #define VERIFY_PRINT_INFO
+ * #endif
+ * #define VERIFY_IPRINTF(format, ...) pr_info(format, ##__VA_ARGS__)
  */
 
 #include <linux/uaccess.h>
@@ -8,14 +23,12 @@
 #include <linux/mutex.h>
 #include <net/sock.h>
 #include "fastrpc_trace.h"
+#include <linux/workqueue.h>
 #include "adsprpc_shared.h"
 
 // Registered QRTR service ID
 #define FASTRPC_REMOTE_SERVER_SERVICE_ID 5012
 
-// Number of remote domains
-#define REMOTE_DOMAINS (2)
-
 /*
  * Fastrpc remote server instance ID bit-map:
  *
@@ -42,6 +55,7 @@ union rsp {
 enum fastrpc_remote_domains_id {
 	SECURE_PD = 0,
 	GUEST_OS = 1,
+	MAX_REMOTE_ID = SECURE_PD + 1,
 };
 
 struct fastrpc_socket {
@@ -55,44 +69,84 @@ struct fastrpc_socket {
 struct frpc_transport_session_control {
 	struct fastrpc_socket frpc_socket;     // Fastrpc socket data structure
 	uint32_t remote_server_instance;       // Unique remote server instance ID
-	bool remote_domain_available;          // Flag to indicate if remote domain is enabled
 	bool remote_server_online;             // Flag to indicate remote server status
+	struct work_struct work;               // work for handling incoming messages
+	struct workqueue_struct *wq;           // workqueue to post @work on
+};
+
+struct remote_domain_configuration {
+	int channel_id;
+	int remote_domain;
 };
 
 /**
  * glist_session_ctrl
  * Static list containing socket session information for all remote domains.
- * Update session flag remote_domain_available whenever a remote domain will be using
- * kernel sockets.
  */
-static struct frpc_transport_session_control glist_session_ctrl[NUM_CHANNELS][REMOTE_DOMAINS] = {
-	[CDSP_DOMAIN_ID][SECURE_PD].remote_domain_available = true
+static struct frpc_transport_session_control *glist_session_ctrl[MAX_DOMAIN_ID][MAX_REMOTE_ID];
+
+
+static const struct remote_domain_configuration configurations[] = {
+	{
+		.channel_id = CDSP_DOMAIN_ID,
+		.remote_domain = SECURE_PD,
+	},
 };
 
+int fastrpc_set_tvm_remote_domain(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init)
+{
+	int err = 0;
+	char *proc_name = NULL;
+
+	fl->tvm_remote_domain = GUEST_OS;
+	if (init->file) {
+		if (!init->filelen)
+			goto bail;
+
+		proc_name = kzalloc(init->filelen + 1, GFP_KERNEL);
+		VERIFY(err, !IS_ERR_OR_NULL(proc_name));
+		if (err) {
+			err = -ENOMEM;
+			goto bail;
+		}
+		err = copy_from_user((void *)proc_name,
+			(void __user *)init->file, init->filelen);
+		if (err) {
+			err = -EFAULT;
+			goto bail;
+		}
+		if (!strcmp(proc_name, "securepd"))
+			fl->tvm_remote_domain = SECURE_PD;
+	}
+bail:
+	kfree(proc_name);
+	return err;
+}
+
 /**
  * verify_transport_device()
  * @cid: Channel ID.
- * @trusted_vm: Flag to indicate whether session is for secure PD or guest OS.
+ * @tvm_remote_domain: Remote domain on TVM.
  *
- * Obtain remote session information given channel ID and trusted_vm
+ * Obtain remote session information given channel ID and tvm_remote_domain
  * and verify that socket has been created and remote server is up.
  *
  * Return: 0 on success or negative errno value on failure.
  */
-inline int verify_transport_device(int cid, bool trusted_vm)
+inline int verify_transport_device(int cid, int tvm_remote_domain)
 {
 	int remote_domain, err = 0;
 	struct frpc_transport_session_control *session_control = NULL;
 
-	remote_domain = (trusted_vm) ? SECURE_PD : GUEST_OS;
-	VERIFY(err, remote_domain < REMOTE_DOMAINS);
+	remote_domain = tvm_remote_domain;
+	VERIFY(err, remote_domain < MAX_REMOTE_ID);
 	if (err) {
 		err = -ECHRNG;
 		goto bail;
 	}
 
-	session_control = &glist_session_ctrl[cid][remote_domain];
-	VERIFY(err, session_control->remote_domain_available);
+	session_control = glist_session_ctrl[cid][remote_domain];
+	VERIFY(err, session_control);
 	if (err) {
 		err = -ECHRNG;
 		goto bail;
@@ -117,14 +171,19 @@ static void fastrpc_recv_new_server(struct frpc_transport_session_control *sessi
 				unsigned int node, unsigned int port)
 {
 	uint32_t remote_server_instance = session_control->remote_server_instance;
+	int32_t err = 0;
 
 	/* Ignore EOF marker */
-	if (!node && !port)
-		return;
+	if (!node && !port) {
+		err = -EINVAL;
+		goto bail;
+	}
 
 	if (service != FASTRPC_REMOTE_SERVER_SERVICE_ID ||
-		instance != remote_server_instance)
-		return;
+		instance != remote_server_instance) {
+		err = -ENOMSG;
+		goto bail;
+	}
 
 	mutex_lock(&session_control->frpc_socket.socket_mutex);
 	session_control->frpc_socket.remote_sock_addr.sq_family = AF_QIPCRTR;
@@ -132,28 +191,42 @@ static void fastrpc_recv_new_server(struct frpc_transport_session_control *sessi
 	session_control->frpc_socket.remote_sock_addr.sq_port = port;
 	session_control->remote_server_online = true;
 	mutex_unlock(&session_control->frpc_socket.socket_mutex);
-	ADSPRPC_INFO("Remote server is up: remote ID (0x%x)", remote_server_instance);
+	ADSPRPC_INFO("Remote server is up: remote ID (0x%x), node %u, port %u",
+				remote_server_instance, node, port);
+bail:
+	if (err != -EINVAL && err) {
+		ADSPRPC_WARN("Ignoring ctrl packet: service id %u, instance id %u, err %d",
+					service, instance, err);
+	}
 }
 
 static void fastrpc_recv_del_server(struct frpc_transport_session_control *session_control,
 				unsigned int node, unsigned int port)
 {
 	uint32_t remote_server_instance = session_control->remote_server_instance;
+	int32_t err = 0;
 
 	/* Ignore EOF marker */
-	if (!node && !port)
-		return;
+	if (!node && !port) {
+		err = -EINVAL;
+		goto bail;
+	}
 
 	if (node != session_control->frpc_socket.remote_sock_addr.sq_node ||
-		port != session_control->frpc_socket.remote_sock_addr.sq_port)
-		return;
+		port != session_control->frpc_socket.remote_sock_addr.sq_port) {
+		err = -ENOMSG;
+		goto bail;
+	}
 
 	mutex_lock(&session_control->frpc_socket.socket_mutex);
 	session_control->frpc_socket.remote_sock_addr.sq_node = 0;
 	session_control->frpc_socket.remote_sock_addr.sq_port = 0;
 	session_control->remote_server_online = false;
 	mutex_unlock(&session_control->frpc_socket.socket_mutex);
-	ADSPRPC_WARN("Remote server is down: remote ID (0x%x)", remote_server_instance);
+	ADSPRPC_INFO("Remote server is down: remote ID (0x%x)", remote_server_instance);
+bail:
+	if (err != -EINVAL && err)
+		ADSPRPC_WARN("Ignoring ctrl packet: node %u, port %u, err %d", node, port, err);
 }
 
 /**
@@ -188,70 +261,109 @@ static void fastrpc_recv_ctrl_pkt(struct frpc_transport_session_control *session
 				    le32_to_cpu(pkt->server.node),
 				    le32_to_cpu(pkt->server.port));
 		break;
+	default:
+		ADSPRPC_WARN("Ignoring unknown ctrl packet with size %zu", len);
 	}
 }
 
 /**
- * fastrpc_socket_callback()
- * @sk: Sock data structure with information related to the callback response.
+ * fastrpc_socket_callback_wq()
+ * @work: workqueue structure for incoming socket packets
  *
- * Callback function to receive responses from socket layer.
+ * Callback function to receive responses that were posted on workqueue.
  * We expect to receive control packets with remote domain status notifications or
  * RPC data packets from remote domain.
  */
-static void fastrpc_socket_callback(struct sock *sk)
+static void fastrpc_socket_callback_wq(struct work_struct *work)
 {
-	int err = 0, cid = 0;
+	int32_t err = 0, cid = -1, bytes_rx = 0;
+	uint32_t remote_server_instance = (uint32_t)-1;
+	bool ignore_err = false;
 	struct kvec msg = {0};
 	struct sockaddr_qrtr remote_sock_addr = {0};
 	struct msghdr remote_server = {0};
 	struct frpc_transport_session_control *session_control = NULL;
+	__u32 sq_node = 0, sq_port = 0;
 
-	remote_server.msg_name = &remote_sock_addr;
-	remote_server.msg_namelen = sizeof(remote_sock_addr);
-	trace_fastrpc_msg("socket_callback: begin");
-	VERIFY(err, sk);
-	if (err) {
-		err = -EFAULT;
-		goto bail;
-	}
-
-	rcu_read_lock();
-	session_control = rcu_dereference_sk_user_data(sk);
-	rcu_read_unlock();
+	session_control = container_of(work, struct frpc_transport_session_control, work);
 	VERIFY(err, session_control);
 	if (err) {
 		err = -EFAULT;
 		goto bail;
 	}
 
+	remote_server.msg_name = &remote_sock_addr;
+	remote_server.msg_namelen = sizeof(remote_sock_addr);
 	msg.iov_base = session_control->frpc_socket.recv_buf;
 	msg.iov_len = FASTRPC_SOCKET_RECV_SIZE;
-	err = kernel_recvmsg(session_control->frpc_socket.sock, &remote_server, &msg, 1,
-				msg.iov_len, MSG_DONTWAIT);
-	if (err < 0)
-		goto bail;
-
-	if (remote_sock_addr.sq_node == session_control->frpc_socket.local_sock_addr.sq_node &&
-		remote_sock_addr.sq_port == QRTR_PORT_CTRL) {
-		fastrpc_recv_ctrl_pkt(session_control, session_control->frpc_socket.recv_buf,
-					FASTRPC_SOCKET_RECV_SIZE);
-	} else {
-		cid = GET_CID_FROM_SERVER_INSTANCE(session_control->remote_server_instance);
-		VERIFY(err, VALID_FASTRPC_CID(cid));
-		if (err) {
-			err = -ECHRNG;
+	remote_server_instance = session_control->remote_server_instance;
+	for (;;) {
+		trace_fastrpc_msg("socket_callback_ready: begin");
+		err = kernel_recvmsg(session_control->frpc_socket.sock, &remote_server, &msg, 1,
+					msg.iov_len, MSG_DONTWAIT);
+		if (err == -EAGAIN) {
+			ignore_err = true;
+			goto bail;
+		}
+		if (err < 0)
 			goto bail;
+
+		bytes_rx = err;
+		err = 0;
+
+		sq_node = remote_sock_addr.sq_node;
+		sq_port = remote_sock_addr.sq_port;
+		if (sq_node == session_control->frpc_socket.local_sock_addr.sq_node &&
+			sq_port == QRTR_PORT_CTRL) {
+			fastrpc_recv_ctrl_pkt(session_control,
+							session_control->frpc_socket.recv_buf,
+							bytes_rx);
+		} else {
+			cid = GET_CID_FROM_SERVER_INSTANCE(remote_server_instance);
+			VERIFY(err, VALID_FASTRPC_CID(cid));
+			if (err) {
+				err = -ECHRNG;
+				goto bail;
+			}
+			fastrpc_handle_rpc_response(msg.iov_base, msg.iov_len, cid);
 		}
-		fastrpc_handle_rpc_response(msg.iov_base, msg.iov_len, cid);
+		trace_fastrpc_msg("socket_callback_ready: end");
 	}
 bail:
-	if (err < 0) {
+	if (!ignore_err && err < 0) {
 		ADSPRPC_ERR(
-			"invalid response data %pK, len %d from remote ID (0x%x) err %d\n",
-			msg.iov_base, msg.iov_len, session_control->remote_server_instance, err);
+			"invalid response data %pK (rx %d bytes), buffer len %d from remote ID (0x%x) err %d\n",
+			msg.iov_base, bytes_rx, msg.iov_len, remote_server_instance, err);
+	}
+}
+
+/**
+ * fastrpc_socket_callback()
+ * @sk: Sock data structure with information related to the callback response.
+ *
+ * Callback function to receive responses from socket layer.
+ * Responses are posted on workqueue to be process.
+ */
+static void fastrpc_socket_callback(struct sock *sk)
+{
+	int32_t err = 0;
+	struct frpc_transport_session_control *session_control = NULL;
+
+	trace_fastrpc_msg("socket_callback: begin");
+	VERIFY(err, sk);
+	if (err) {
+		err = -EFAULT;
+		goto bail;
 	}
 
+	rcu_read_lock();
+	session_control = rcu_dereference_sk_user_data(sk);
+	if (session_control)
+		queue_work(session_control->wq, &session_control->work);
+	rcu_read_unlock();
+bail:
+	if (err < 0)
+		ADSPRPC_ERR("invalid sock received, err %d", err);
 	trace_fastrpc_msg("socket_callback: end");
 }
 
@@ -260,16 +372,16 @@ bail:
  * @cid: Channel ID.
  * @rpc_msg: RPC message to send to remote domain.
  * @rpc_msg_size: RPC message size.
- * @trusted_vm: Flag to indicate whether to send message to secure PD or guest OS.
+ * @tvm_remote_domain: Remote domain on TVM.
  *
- * Send RPC message to remote domain. Depending on trusted_vm flag message will be
- * sent to secure PD or guest OS on remote subsystem.
+ * Send RPC message to remote domain. Depending on tvm_remote_domain flag message will be
+ * sent to one of the remote domains on remote subsystem.
  * Depending on the channel ID and remote domain, a corresponding socket is retrieved
  * from glist_session_ctrl and is use to send RPC message.
  *
  * Return: 0 on success or negative errno value on failure.
  */
-int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, bool trusted_vm)
+int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, int tvm_remote_domain)
 {
 	int err = 0, remote_domain;
 	struct fastrpc_socket *frpc_socket = NULL;
@@ -277,14 +389,14 @@ int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, bool t
 	struct msghdr remote_server = {0};
 	struct kvec msg = {0};
 
-	remote_domain = (trusted_vm) ? SECURE_PD : GUEST_OS;
-	VERIFY(err, remote_domain < REMOTE_DOMAINS);
+	remote_domain = tvm_remote_domain;
+	VERIFY(err, remote_domain < MAX_REMOTE_ID);
 	if (err) {
 		err = -ECHRNG;
 		goto bail;
 	}
-	session_control = &glist_session_ctrl[cid][remote_domain];
-	VERIFY(err, session_control->remote_domain_available);
+	session_control = glist_session_ctrl[cid][remote_domain];
+	VERIFY(err, session_control);
 	if (err) {
 		err = -ECHRNG;
 		goto bail;
@@ -304,7 +416,11 @@ int fastrpc_transport_send(int cid, void *rpc_msg, uint32_t rpc_msg_size, bool t
 		mutex_unlock(&frpc_socket->socket_mutex);
 		goto bail;
 	}
+
 	err = kernel_sendmsg(frpc_socket->sock, &remote_server, &msg, 1, msg.iov_len);
+	if (err > 0)
+		err = 0;
+
 	mutex_unlock(&frpc_socket->socket_mutex);
 bail:
 	return err;
@@ -338,6 +454,7 @@ static struct socket *create_socket(struct frpc_transport_session_control *sessi
 		ADSPRPC_ERR("kernel_getsockname failed with err %d\n", err);
 		goto bail;
 	}
+
 	rcu_assign_sk_user_data(sock->sk, session_control);
 	sock->sk->sk_data_ready = fastrpc_socket_callback;
 	sock->sk->sk_error_report = fastrpc_socket_callback;
@@ -413,47 +530,66 @@ void fastrpc_rproc_trace_events(const char *name, const char *event,
  *
  * Initialize and create all sockets that are enabled from all channels
  * and remote domains.
- * Traverse array glist_session_ctrl and initialize session if remote
+ * Traverse array configurations and initialize session on glist_session_ctrl if remote
  * domain is enabled.
  *
  * Return: 0 on success or negative errno value on failure.
  */
 int fastrpc_transport_init(void)
 {
-	int err = 0, cid = 0, ii = 0;
+	int err = 0, cid = -1, ii = 0, remote_domain = -1;
 	struct socket *sock = NULL;
 	struct fastrpc_socket *frpc_socket = NULL;
 	struct frpc_transport_session_control *session_control = NULL;
+	struct workqueue_struct *wq = NULL;
 
-	for (cid = 0; cid < NUM_CHANNELS; cid++) {
-		for (ii = 0; ii < REMOTE_DOMAINS; ii++) {
-			session_control = &glist_session_ctrl[cid][ii];
-			if (!session_control->remote_domain_available)
-				continue;
+	for (ii = 0; ii < ARRAY_SIZE(configurations); ii++) {
+		session_control = kzalloc(sizeof(*session_control), GFP_KERNEL);
+		VERIFY(err, NULL != session_control);
+		if (err) {
+			err = -ENOMEM;
+			goto bail;
+		}
+		cid = configurations[ii].channel_id;
+		remote_domain = configurations[ii].remote_domain;
 
-			session_control->remote_server_online = false;
-			frpc_socket = &session_control->frpc_socket;
-			mutex_init(&frpc_socket->socket_mutex);
+		session_control->remote_server_online = false;
+		frpc_socket = &session_control->frpc_socket;
+		mutex_init(&frpc_socket->socket_mutex);
 
-			sock = create_socket(session_control);
-			if (IS_ERR_OR_NULL(sock)) {
-				err = PTR_ERR(sock);
-				goto bail;
-			}
+		sock = create_socket(session_control);
+		if (IS_ERR_OR_NULL(sock)) {
+			err = PTR_ERR(sock);
+			goto bail;
+		}
 
-			frpc_socket->sock = sock;
-			frpc_socket->recv_buf = kzalloc(FASTRPC_SOCKET_RECV_SIZE, GFP_KERNEL);
-			if (!frpc_socket->recv_buf) {
-				err = -ENOMEM;
-				goto bail;
-			}
-			session_control->remote_server_instance = GET_SERVER_INSTANCE(ii, cid);
-			err = register_remote_server_notifications(frpc_socket,
-							session_control->remote_server_instance);
-			if (err < 0)
-				goto bail;
+		frpc_socket->sock = sock;
+		frpc_socket->recv_buf = kzalloc(FASTRPC_SOCKET_RECV_SIZE, GFP_KERNEL);
+		if (!frpc_socket->recv_buf) {
+			err = -ENOMEM;
+			goto bail;
 		}
+
+		INIT_WORK(&session_control->work, fastrpc_socket_callback_wq);
+		wq = alloc_workqueue("fastrpc_msg_handler", WQ_UNBOUND|WQ_HIGHPRI, 0);
+		if (!wq) {
+			err = -ENOMEM;
+			goto bail;
+		}
+		session_control->wq = wq;
+
+		session_control->remote_server_instance = GET_SERVER_INSTANCE(remote_domain, cid);
+		err = register_remote_server_notifications(frpc_socket,
+						session_control->remote_server_instance);
+		if (err < 0)
+			goto bail;
+
+		glist_session_ctrl[cid][remote_domain] = session_control;
+		ADSPRPC_INFO("Created and registered socket for remote server (service ID %u, instance ID 0x%x)\n",
+			FASTRPC_REMOTE_SERVER_SERVICE_ID, session_control->remote_server_instance);
+
 	}
+
 	err = 0;
 bail:
 	if (err)
@@ -466,30 +602,36 @@ bail:
  *
  * Deinitialize and release all sockets that are enabled from all channels
  * and remote domains.
- * Traverse array glist_session_ctrl and deinitialize session if remote
- * domain is enabled.
+ * Traverse array configurations and deinitialize corresponding session from
+ * glist_session_ctrl.
  */
 void fastrpc_transport_deinit(void)
 {
-	int ii = 0;
+	int ii = 0, cid = -1, remote_domain = -1;
 	struct fastrpc_socket *frpc_socket = NULL;
 	struct frpc_transport_session_control *session_control = NULL;
-	int cid = -1;
-
-	for (cid = 0; cid < NUM_CHANNELS; cid++) {
-		for (ii = 0; ii < REMOTE_DOMAINS; ii++) {
-			session_control = &glist_session_ctrl[cid][ii];
-			frpc_socket = &session_control->frpc_socket;
-			if (!session_control->remote_domain_available)
-				continue;
-
-			if (frpc_socket->sock)
-				sock_release(frpc_socket->sock);
-
-			kfree(frpc_socket->recv_buf);
-			frpc_socket->recv_buf = NULL;
-			frpc_socket->sock = NULL;
-			mutex_destroy(&frpc_socket->socket_mutex);
-		}
+
+	for (ii = 0; ii < ARRAY_SIZE(configurations); ii++) {
+		cid = configurations[ii].channel_id;
+		remote_domain = configurations[ii].remote_domain;
+
+		session_control = glist_session_ctrl[cid][remote_domain];
+		if (!session_control)
+			continue;
+
+		frpc_socket = &session_control->frpc_socket;
+
+		if (frpc_socket->sock)
+			sock_release(frpc_socket->sock);
+
+		if (session_control->wq)
+			destroy_workqueue(session_control->wq);
+
+		kfree(frpc_socket->recv_buf);
+		frpc_socket->recv_buf = NULL;
+		frpc_socket->sock = NULL;
+		mutex_destroy(&frpc_socket->socket_mutex);
+		kfree(session_control);
+		glist_session_ctrl[cid][remote_domain] = NULL;
 	}
 }

+ 3 - 1
dsp/cdsp-loader.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2012-2014, 2017-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -156,6 +156,7 @@ static void cdsp_loader_unload(struct platform_device *pdev)
 		dev_dbg(&pdev->dev, "%s: calling subsystem_put\n", __func__);
 		rproc_shutdown(priv->pil_h);
 		priv->pil_h = NULL;
+		cdsp_state = CDSP_SUBSYS_DOWN;
 	}
 }
 
@@ -229,6 +230,7 @@ static int cdsp_loader_remove(struct platform_device *pdev)
 	if (priv->pil_h) {
 		rproc_shutdown(priv->pil_h);
 		priv->pil_h = NULL;
+		cdsp_state = CDSP_SUBSYS_DOWN;
 	}
 
 	if (priv->boot_cdsp_obj) {