Loading drivers/soc/qcom/cdsprm.c +109 −100 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/kthread.h> #include <linux/workqueue.h> #include <linux/pm_qos.h> #include <linux/delay.h> Loading Loading @@ -152,9 +153,8 @@ struct cdsprm { struct completion msg_avail; struct cdsprm_request msg_queue[CDSPRM_MSG_QUEUE_DEPTH]; unsigned int msg_queue_idx; struct workqueue_struct *work_queue; struct task_struct *cdsprm_wq_task; struct workqueue_struct *delay_work_queue; struct work_struct cdsprm_work; struct work_struct cdsprm_delay_work; struct mutex rm_lock; spinlock_t l3_lock; Loading @@ -162,7 +162,6 @@ struct cdsprm { struct mutex rpmsg_lock; struct rpmsg_device *rpmsgdev; enum delay_state dt_state; enum delay_state work_state; unsigned long long timestamp; struct pm_qos_request pm_qos_req; unsigned int qos_latency_us; Loading Loading @@ -200,6 +199,7 @@ struct cdsprm { static struct cdsprm gcdsprm; static LIST_HEAD(cdsprm_list); DECLARE_WAIT_QUEUE_HEAD(cdsprm_wq); /** * cdsprm_register_cdspl3gov() - Register a method to set L3 clock Loading Loading @@ -620,57 +620,66 @@ static void cdsprm_rpmsg_send_details(void) } } static void process_cdsp_request(struct work_struct *work) static struct cdsprm_request *get_next_request(void) { struct cdsprm_request *req = NULL; struct sysmon_msg *msg = NULL; unsigned int l3_clock_khz; unsigned long flags; int result = 0; struct sysmon_msg_tx rpmsg_msg_tx; while (gcdsprm.work_state == CDSP_DELAY_THREAD_STARTED) { spin_lock_irqsave(&gcdsprm.list_lock, flags); req = list_first_entry_or_null(&cdsprm_list, struct cdsprm_request, node); if (req) { msg = &req->msg; if (!msg) { spin_lock_irqsave(&gcdsprm.list_lock, flags); list_del(&req->node); req->busy = false; spin_unlock_irqrestore(&gcdsprm.list_lock, flags); continue; return req; } static int process_cdsp_request_thread(void *data) { struct cdsprm_request *req = NULL; struct sysmon_msg *msg = NULL; unsigned int l3_clock_khz; unsigned long flags; int result = 0; struct sysmon_msg_tx rpmsg_msg_tx; while (!kthread_should_stop()) { result = wait_event_interruptible(cdsprm_wq, (req = get_next_request())); if (result) continue; msg = &req->msg; if ((msg->feature_id == SYSMON_CDSP_FEATURE_RM_RX) && gcdsprm.b_qosinitdone) { process_rm_request(msg); } else if (msg->feature_id == SYSMON_CDSP_FEATURE_L3_RX) { l3_clock_khz = msg->fs.l3_struct.l3_clock_khz; l3_clock_khz = msg->fs.l3_struct.l3_clock_khz; spin_lock_irqsave(&gcdsprm.l3_lock, flags); gcdsprm.set_l3_freq_cached = gcdsprm.set_l3_freq; gcdsprm.set_l3_freq_cached = gcdsprm.set_l3_freq; spin_unlock_irqrestore(&gcdsprm.l3_lock, flags); if (gcdsprm.set_l3_freq_cached) { gcdsprm.set_l3_freq_cached( l3_clock_khz); gcdsprm.set_l3_freq_cached(l3_clock_khz); pr_debug("Set L3 clock %d done\n", l3_clock_khz); } } else if (msg->feature_id == SYSMON_CDSP_FEATURE_NPU_LIMIT_RX) { mutex_lock(&gcdsprm.npu_activity_lock); gcdsprm.set_corner_limit_cached = gcdsprm.set_corner_limit; if (gcdsprm.set_corner_limit_cached) { gcdsprm.npu_corner_limit = msg->fs.npu_limit.corner; gcdsprm.b_applyingNpuLimit = true; result = gcdsprm.set_corner_limit_cached( result = gcdsprm.set_corner_limit_cached( gcdsprm.npu_corner_limit); gcdsprm.b_applyingNpuLimit = false; pr_debug("Set NPU limit to %d\n", Loading @@ -679,12 +688,14 @@ static void process_cdsp_request(struct work_struct *work) result = -ENOMSG; pr_debug("NPU limit not registered\n"); } mutex_unlock(&gcdsprm.npu_activity_lock); /* * Send Limit ack back to DSP */ rpmsg_msg_tx.feature_id = SYSMON_CDSP_FEATURE_NPU_LIMIT_TX; if (result == 0) { rpmsg_msg_tx.fs.npu_limit_ack.corner = msg->fs.npu_limit.corner; Loading @@ -692,13 +703,14 @@ static void process_cdsp_request(struct work_struct *work) rpmsg_msg_tx.fs.npu_limit_ack.corner = CDSPRM_NPU_CLK_OFF; } rpmsg_msg_tx.size = sizeof(rpmsg_msg_tx); result = rpmsg_send(gcdsprm.rpmsgdev->ept, &rpmsg_msg_tx, sizeof(rpmsg_msg_tx)); if (result) pr_err("rpmsg send failed %d\n", result); pr_err("rpmsg send failed %d\n", result); else pr_debug("NPU limit ack sent\n"); } else if (msg->feature_id == Loading @@ -706,14 +718,14 @@ static void process_cdsp_request(struct work_struct *work) cdsprm_rpmsg_send_details(); pr_debug("Sent preserved data to DSP\n"); } spin_lock_irqsave(&gcdsprm.list_lock, flags); list_del(&req->node); req->busy = false; spin_unlock_irqrestore(&gcdsprm.list_lock, flags); } else { wait_for_completion(&gcdsprm.msg_avail); } } do_exit(0); } static int cdsprm_rpmsg_probe(struct rpmsg_device *dev) Loading Loading @@ -801,6 +813,7 @@ static int cdsprm_rpmsg_callback(struct rpmsg_device *dev, void *data, if (b_valid) { spin_lock_irqsave(&gcdsprm.list_lock, flags); if (!gcdsprm.msg_queue[gcdsprm.msg_queue_idx].busy) { req = &gcdsprm.msg_queue[gcdsprm.msg_queue_idx]; req->busy = true; Loading @@ -816,17 +829,10 @@ static int cdsprm_rpmsg_callback(struct rpmsg_device *dev, void *data, "Unable to queue cdsp request, no memory\n"); return -ENOMEM; } list_add_tail(&req->node, &cdsprm_list); spin_unlock_irqrestore(&gcdsprm.list_lock, flags); if (gcdsprm.work_state == CDSP_DELAY_THREAD_NOT_STARTED) { gcdsprm.work_state = CDSP_DELAY_THREAD_STARTED; queue_work(gcdsprm.work_queue, &gcdsprm.cdsprm_work); } else { complete(&gcdsprm.msg_avail); } wake_up_interruptible(&cdsprm_wq); } return 0; Loading Loading @@ -1063,10 +1069,12 @@ static int __init cdsprm_init(void) init_completion(&gcdsprm.msg_avail); init_completion(&gcdsprm.npu_activity_complete); init_completion(&gcdsprm.npu_corner_complete); gcdsprm.work_queue = create_singlethread_workqueue("cdsprm-wq"); if (!gcdsprm.work_queue) { pr_err("Failed to create rm work queue\n"); gcdsprm.cdsprm_wq_task = kthread_run(process_cdsp_request_thread, NULL, "cdsprm-wq"); if (!gcdsprm.cdsprm_wq_task) { pr_err("Failed to create kernel thread\n"); return -ENOMEM; } Loading @@ -1080,7 +1088,6 @@ static int __init cdsprm_init(void) } INIT_WORK(&gcdsprm.cdsprm_delay_work, process_delayed_rm_request); INIT_WORK(&gcdsprm.cdsprm_work, process_cdsp_request); err = platform_driver_register(&cdsp_rm); if (err) { Loading Loading @@ -1113,7 +1120,7 @@ static int __init cdsprm_init(void) bail: destroy_workqueue(gcdsprm.delay_work_queue); err_wq: destroy_workqueue(gcdsprm.work_queue); kthread_stop(gcdsprm.cdsprm_wq_task); return err; } Loading @@ -1126,9 +1133,11 @@ static void __exit cdsprm_exit(void) gcdsprm.b_rpmsg_register = false; platform_driver_unregister(&cdsp_rm); platform_driver_unregister(&hvx_rm); gcdsprm.work_state = CDSP_DELAY_THREAD_NOT_STARTED; complete(&gcdsprm.msg_avail); destroy_workqueue(gcdsprm.work_queue); if (gcdsprm.cdsprm_wq_task) kthread_stop(gcdsprm.cdsprm_wq_task); destroy_workqueue(gcdsprm.delay_work_queue); debugfs_remove_recursive(gcdsprm.debugfs_dir); } Loading Loading
drivers/soc/qcom/cdsprm.c +109 −100 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/kthread.h> #include <linux/workqueue.h> #include <linux/pm_qos.h> #include <linux/delay.h> Loading Loading @@ -152,9 +153,8 @@ struct cdsprm { struct completion msg_avail; struct cdsprm_request msg_queue[CDSPRM_MSG_QUEUE_DEPTH]; unsigned int msg_queue_idx; struct workqueue_struct *work_queue; struct task_struct *cdsprm_wq_task; struct workqueue_struct *delay_work_queue; struct work_struct cdsprm_work; struct work_struct cdsprm_delay_work; struct mutex rm_lock; spinlock_t l3_lock; Loading @@ -162,7 +162,6 @@ struct cdsprm { struct mutex rpmsg_lock; struct rpmsg_device *rpmsgdev; enum delay_state dt_state; enum delay_state work_state; unsigned long long timestamp; struct pm_qos_request pm_qos_req; unsigned int qos_latency_us; Loading Loading @@ -200,6 +199,7 @@ struct cdsprm { static struct cdsprm gcdsprm; static LIST_HEAD(cdsprm_list); DECLARE_WAIT_QUEUE_HEAD(cdsprm_wq); /** * cdsprm_register_cdspl3gov() - Register a method to set L3 clock Loading Loading @@ -620,57 +620,66 @@ static void cdsprm_rpmsg_send_details(void) } } static void process_cdsp_request(struct work_struct *work) static struct cdsprm_request *get_next_request(void) { struct cdsprm_request *req = NULL; struct sysmon_msg *msg = NULL; unsigned int l3_clock_khz; unsigned long flags; int result = 0; struct sysmon_msg_tx rpmsg_msg_tx; while (gcdsprm.work_state == CDSP_DELAY_THREAD_STARTED) { spin_lock_irqsave(&gcdsprm.list_lock, flags); req = list_first_entry_or_null(&cdsprm_list, struct cdsprm_request, node); if (req) { msg = &req->msg; if (!msg) { spin_lock_irqsave(&gcdsprm.list_lock, flags); list_del(&req->node); req->busy = false; spin_unlock_irqrestore(&gcdsprm.list_lock, flags); continue; return req; } static int process_cdsp_request_thread(void *data) { struct cdsprm_request *req = NULL; struct sysmon_msg *msg = NULL; unsigned int l3_clock_khz; unsigned long flags; int result = 0; struct sysmon_msg_tx rpmsg_msg_tx; while (!kthread_should_stop()) { result = wait_event_interruptible(cdsprm_wq, (req = get_next_request())); if (result) continue; msg = &req->msg; if ((msg->feature_id == SYSMON_CDSP_FEATURE_RM_RX) && gcdsprm.b_qosinitdone) { process_rm_request(msg); } else if (msg->feature_id == SYSMON_CDSP_FEATURE_L3_RX) { l3_clock_khz = msg->fs.l3_struct.l3_clock_khz; l3_clock_khz = msg->fs.l3_struct.l3_clock_khz; spin_lock_irqsave(&gcdsprm.l3_lock, flags); gcdsprm.set_l3_freq_cached = gcdsprm.set_l3_freq; gcdsprm.set_l3_freq_cached = gcdsprm.set_l3_freq; spin_unlock_irqrestore(&gcdsprm.l3_lock, flags); if (gcdsprm.set_l3_freq_cached) { gcdsprm.set_l3_freq_cached( l3_clock_khz); gcdsprm.set_l3_freq_cached(l3_clock_khz); pr_debug("Set L3 clock %d done\n", l3_clock_khz); } } else if (msg->feature_id == SYSMON_CDSP_FEATURE_NPU_LIMIT_RX) { mutex_lock(&gcdsprm.npu_activity_lock); gcdsprm.set_corner_limit_cached = gcdsprm.set_corner_limit; if (gcdsprm.set_corner_limit_cached) { gcdsprm.npu_corner_limit = msg->fs.npu_limit.corner; gcdsprm.b_applyingNpuLimit = true; result = gcdsprm.set_corner_limit_cached( result = gcdsprm.set_corner_limit_cached( gcdsprm.npu_corner_limit); gcdsprm.b_applyingNpuLimit = false; pr_debug("Set NPU limit to %d\n", Loading @@ -679,12 +688,14 @@ static void process_cdsp_request(struct work_struct *work) result = -ENOMSG; pr_debug("NPU limit not registered\n"); } mutex_unlock(&gcdsprm.npu_activity_lock); /* * Send Limit ack back to DSP */ rpmsg_msg_tx.feature_id = SYSMON_CDSP_FEATURE_NPU_LIMIT_TX; if (result == 0) { rpmsg_msg_tx.fs.npu_limit_ack.corner = msg->fs.npu_limit.corner; Loading @@ -692,13 +703,14 @@ static void process_cdsp_request(struct work_struct *work) rpmsg_msg_tx.fs.npu_limit_ack.corner = CDSPRM_NPU_CLK_OFF; } rpmsg_msg_tx.size = sizeof(rpmsg_msg_tx); result = rpmsg_send(gcdsprm.rpmsgdev->ept, &rpmsg_msg_tx, sizeof(rpmsg_msg_tx)); if (result) pr_err("rpmsg send failed %d\n", result); pr_err("rpmsg send failed %d\n", result); else pr_debug("NPU limit ack sent\n"); } else if (msg->feature_id == Loading @@ -706,14 +718,14 @@ static void process_cdsp_request(struct work_struct *work) cdsprm_rpmsg_send_details(); pr_debug("Sent preserved data to DSP\n"); } spin_lock_irqsave(&gcdsprm.list_lock, flags); list_del(&req->node); req->busy = false; spin_unlock_irqrestore(&gcdsprm.list_lock, flags); } else { wait_for_completion(&gcdsprm.msg_avail); } } do_exit(0); } static int cdsprm_rpmsg_probe(struct rpmsg_device *dev) Loading Loading @@ -801,6 +813,7 @@ static int cdsprm_rpmsg_callback(struct rpmsg_device *dev, void *data, if (b_valid) { spin_lock_irqsave(&gcdsprm.list_lock, flags); if (!gcdsprm.msg_queue[gcdsprm.msg_queue_idx].busy) { req = &gcdsprm.msg_queue[gcdsprm.msg_queue_idx]; req->busy = true; Loading @@ -816,17 +829,10 @@ static int cdsprm_rpmsg_callback(struct rpmsg_device *dev, void *data, "Unable to queue cdsp request, no memory\n"); return -ENOMEM; } list_add_tail(&req->node, &cdsprm_list); spin_unlock_irqrestore(&gcdsprm.list_lock, flags); if (gcdsprm.work_state == CDSP_DELAY_THREAD_NOT_STARTED) { gcdsprm.work_state = CDSP_DELAY_THREAD_STARTED; queue_work(gcdsprm.work_queue, &gcdsprm.cdsprm_work); } else { complete(&gcdsprm.msg_avail); } wake_up_interruptible(&cdsprm_wq); } return 0; Loading Loading @@ -1063,10 +1069,12 @@ static int __init cdsprm_init(void) init_completion(&gcdsprm.msg_avail); init_completion(&gcdsprm.npu_activity_complete); init_completion(&gcdsprm.npu_corner_complete); gcdsprm.work_queue = create_singlethread_workqueue("cdsprm-wq"); if (!gcdsprm.work_queue) { pr_err("Failed to create rm work queue\n"); gcdsprm.cdsprm_wq_task = kthread_run(process_cdsp_request_thread, NULL, "cdsprm-wq"); if (!gcdsprm.cdsprm_wq_task) { pr_err("Failed to create kernel thread\n"); return -ENOMEM; } Loading @@ -1080,7 +1088,6 @@ static int __init cdsprm_init(void) } INIT_WORK(&gcdsprm.cdsprm_delay_work, process_delayed_rm_request); INIT_WORK(&gcdsprm.cdsprm_work, process_cdsp_request); err = platform_driver_register(&cdsp_rm); if (err) { Loading Loading @@ -1113,7 +1120,7 @@ static int __init cdsprm_init(void) bail: destroy_workqueue(gcdsprm.delay_work_queue); err_wq: destroy_workqueue(gcdsprm.work_queue); kthread_stop(gcdsprm.cdsprm_wq_task); return err; } Loading @@ -1126,9 +1133,11 @@ static void __exit cdsprm_exit(void) gcdsprm.b_rpmsg_register = false; platform_driver_unregister(&cdsp_rm); platform_driver_unregister(&hvx_rm); gcdsprm.work_state = CDSP_DELAY_THREAD_NOT_STARTED; complete(&gcdsprm.msg_avail); destroy_workqueue(gcdsprm.work_queue); if (gcdsprm.cdsprm_wq_task) kthread_stop(gcdsprm.cdsprm_wq_task); destroy_workqueue(gcdsprm.delay_work_queue); debugfs_remove_recursive(gcdsprm.debugfs_dir); } Loading