remoteproc: Proxy unvote clk/regs in handover context
Subsystems (2)
PATCH 1/1 remoteproc: Proxy unvote clk/regs in handover context
Introduce interrupt handler for smp2p ready interrupt and handle start completion. Remove the proxy votes for clocks and regulators in the handover interrupt context. Disable wdog and fatal interrupts on remoteproc device stop and re-enable them on remoteproc device start.
--- drivers/remoteproc/qcom_q6v5_pil.c | 71 +++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 11 deletions(-)
drivers/remoteproc/qcom_q6v5_pil.c +60 -11
@@ -143,6 +143,10 @@ struct q6v5 {struct qcom_smem_state *state;unsigned stop_bit; +unsigned int handover_interrupt; +unsigned int wdog_interrupt; +unsigned int fatal_interrupt; +struct clk *active_clks[8 ];struct clk *proxy_clks[4 ];int active_clk_count;
@@ -170,6 +174,7 @@ struct q6v5 {struct qcom_rproc_ssr ssr_subdev;struct qcom_sysmon *sysmon;bool need_mem_protection; +bool unvoted_flag;int mpss_perm;int mba_perm;int version;
@@ -727,6 +732,7 @@ static int q6v5_start(struct rproc *rproc)int xfermemop_ret;int ret; + qproc->unvoted_flag = false; ret =q6v5_regulator_enable (qproc, qproc->proxy_regs, qproc->proxy_reg_count);if (ret) {
@@ -793,9 +799,16 @@ static int q6v5_start(struct rproc *rproc)if (ret) goto reclaim_mpss; +enable_irq (qproc->handover_interrupt); +enable_irq (qproc->wdog_interrupt); +enable_irq (qproc->fatal_interrupt); + ret =wait_for_completion_timeout (&qproc->start_done,msecs_to_jiffies (5000 ));if (ret ==0 ) { +disable_irq (qproc->handover_interrupt); +disable_irq (qproc->wdog_interrupt); +disable_irq (qproc->fatal_interrupt);dev_err (qproc->dev,"start timed out\n" ); ret = -ETIMEDOUT ; goto reclaim_mpss;
@@ -809,11 +822,6 @@ static int q6v5_start(struct rproc *rproc) "Failed to reclaim mba buffer system may become unstable\n"); qproc->running = true; -q6v5_clk_disable (qproc->dev, qproc->proxy_clks, - qproc->proxy_clk_count); -q6v5_regulator_disable (qproc, qproc->proxy_regs, - qproc->proxy_reg_count); -return 0 ; reclaim_mpss:
@@ -892,6 +900,16 @@ static int q6v5_stop(struct rproc *rproc)WARN_ON (ret);reset_control_assert (qproc->mss_restart); +disable_irq (qproc->handover_interrupt); +if (!qproc->unvoted_flag) { +q6v5_clk_disable (qproc->dev, qproc->proxy_clks, + qproc->proxy_clk_count); +q6v5_regulator_disable (qproc, qproc->proxy_regs, + qproc->proxy_reg_count); + } +disable_irq (qproc->wdog_interrupt); +disable_irq (qproc->fatal_interrupt); +q6v5_clk_disable (qproc->dev, qproc->active_clks, qproc->active_clk_count); q6v5_regulator_disable(qproc, qproc->active_regs,
@@ -959,7 +977,7 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)return IRQ_HANDLED ; } -static irqreturn_t q6v5_handover_interrupt (int irq,void *dev) +static irqreturn_t q6v5_ready_interrupt (int irq,void *dev) {struct q6v5 *qproc = dev;
@@ -967,6 +985,21 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)return IRQ_HANDLED ; } +static irqreturn_t q6v5_handover_interrupt (int irq,void *dev) +{ +struct q6v5 *qproc = dev; + +if (!qproc->unvoted_flag) { + qproc->unvoted_flag = true; +q6v5_clk_disable (qproc->dev, qproc->proxy_clks, + qproc->proxy_clk_count); +q6v5_regulator_disable (qproc, qproc->proxy_regs, + qproc->proxy_reg_count); + } + +return IRQ_HANDLED ; +} +static irqreturn_t q6v5_stop_ack_interrupt (int irq,void *dev) {struct q6v5 *qproc = dev;
@@ -1048,7 +1081,8 @@ static int q6v5_init_reset(struct q6v5 *qproc)static int q6v5_request_irq (struct q6v5 *qproc,struct platform_device *pdev,const char *name, -irq_handler_t thread_fn) +irq_handler_t thread_fn, +unsigned int *irq_num) {int ret;
@@ -1058,6 +1092,9 @@ static int q6v5_request_irq(struct q6v5 *qproc,return ret; } +if (irq_num) + *irq_num = ret; + ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, thread_fn, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -1184,19 +1221,31 @@ static int q6v5_probe(struct platform_device *pdev) qproc->version = desc->version; qproc->need_mem_protection = desc->need_mem_protection; - ret =q6v5_request_irq (qproc, pdev,"wdog" , q6v5_wdog_interrupt); + ret =q6v5_request_irq (qproc, pdev,"wdog" , q6v5_wdog_interrupt, + &qproc->wdog_interrupt); +if (ret <0 ) + goto free_rproc; +disable_irq (qproc->wdog_interrupt); + + ret =q6v5_request_irq (qproc, pdev,"fatal" , q6v5_fatal_interrupt, + &qproc->fatal_interrupt);if (ret <0 ) goto free_rproc; +disable_irq (qproc->fatal_interrupt); - ret =q6v5_request_irq (qproc, pdev,"fatal" , q6v5_fatal_interrupt); + ret =q6v5_request_irq (qproc, pdev,"ready" , q6v5_ready_interrupt, +NULL );if (ret <0 ) goto free_rproc; - ret =q6v5_request_irq (qproc, pdev,"handover" , q6v5_handover_interrupt); + ret =q6v5_request_irq (qproc, pdev,"handover" , q6v5_handover_interrupt, + &qproc->handover_interrupt);if (ret <0 ) goto free_rproc; +disable_irq (qproc->handover_interrupt); - ret =q6v5_request_irq (qproc, pdev,"stop-ack" , q6v5_stop_ack_interrupt); + ret =q6v5_request_irq (qproc, pdev,"stop-ack" , q6v5_stop_ack_interrupt, +NULL );if (ret <0 ) goto free_rproc;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 5 lines · Sibi Sankar
Introduce interrupt handler for smp2p ready interrupt and handle start completion. Remove the proxy votes for clocks and regulators in the handover interrupt context. Disable wdog and fatal interrupts on remoteproc device stop and re-enable them on remoteproc device start.
Can't the enable/disable dance be split out into a separate commit? Making the introduction of them cleaner in the git history?
Quoted 11 lines
Signed-off-by Sibi Sankar <[email protected]>--- drivers/remoteproc/qcom_q6v5_pil.c | 71 +++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 11 deletions(-)drivers/remoteproc/qcom_q6v5_pil.c +0
-0
drivers/remoteproc/qcom_q6v5_pil.c struct q6v5 { · line 148
Quoted 6 lines
drivers/remoteproc/qcom_q6v5_pil.c +3
-0@@ -143,6 +143,10 @@ struct q6v5 {struct qcom_smem_state *state;unsigned stop_bit; +unsigned int handover_interrupt; +unsigned int wdog_interrupt; +unsigned int fatal_interrupt;
Make these "int", and write "irq" instead of "interrupt".
Quoted 50 lines
drivers/remoteproc/qcom_q6v5_pil.c +10
-5+struct clk *active_clks[8 ];struct clk *proxy_clks[4 ];int active_clk_count;@@ -170,6 +174,7 @@ struct q6v5 {struct qcom_rproc_ssr ssr_subdev;struct qcom_sysmon *sysmon;bool need_mem_protection; +bool unvoted_flag;int mpss_perm;int mba_perm;int version;@@ -727,6 +732,7 @@ static int q6v5_start(struct rproc *rproc)int xfermemop_ret;int ret; + qproc->unvoted_flag = false; ret =q6v5_regulator_enable (qproc, qproc->proxy_regs, qproc->proxy_reg_count);if (ret) {@@ -793,9 +799,16 @@ static int q6v5_start(struct rproc *rproc)if (ret) goto reclaim_mpss; +enable_irq (qproc->handover_interrupt); +enable_irq (qproc->wdog_interrupt); +enable_irq (qproc->fatal_interrupt); + ret =wait_for_completion_timeout (&qproc->start_done,msecs_to_jiffies (5000 ));if (ret ==0 ) { +disable_irq (qproc->handover_interrupt); +disable_irq (qproc->wdog_interrupt); +disable_irq (qproc->fatal_interrupt);dev_err (qproc->dev,"start timed out\n" ); ret = -ETIMEDOUT ; goto reclaim_mpss;@@ -809,11 +822,6 @@ static int q6v5_start(struct rproc *rproc) "Failed to reclaim mba buffer system may become unstable\n"); qproc->running = true; -q6v5_clk_disable (qproc->dev, qproc->proxy_clks, - qproc->proxy_clk_count); -q6v5_regulator_disable (qproc, qproc->proxy_regs, - qproc->proxy_reg_count); -return 0 ; reclaim_mpss:
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_stop(struct rproc *rproc) · line 909
Quoted 10 lines
drivers/remoteproc/qcom_q6v5_pil.c +7
-0@@ -892,6 +900,16 @@ static int q6v5_stop(struct rproc *rproc)WARN_ON (ret);reset_control_assert (qproc->mss_restart); +disable_irq (qproc->handover_interrupt); +if (!qproc->unvoted_flag) { +q6v5_clk_disable (qproc->dev, qproc->proxy_clks, + qproc->proxy_clk_count); +q6v5_regulator_disable (qproc, qproc->proxy_regs, + qproc->proxy_reg_count); + }
Perhaps break this out into a separate function and call it from the two places?
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_stop(struct rproc *rproc) · line 911
Quoted 2 lines
drivers/remoteproc/qcom_q6v5_pil.c +2
-0+disable_irq (qproc->wdog_interrupt); +disable_irq (qproc->fatal_interrupt);
Any particular reason why you didn't group the disable_irq() calls together? Would look prettier than spreading them on each side of the resource disable.
Quoted 4 lines
drivers/remoteproc/qcom_q6v5_pil.c +1
-0+q6v5_clk_disable (qproc->dev, qproc->active_clks, qproc->active_clk_count); q6v5_regulator_disable(qproc, qproc->active_regs,
[..]
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_probe(struct platform_device *pdev) · line 1225
Quoted 7 lines
drivers/remoteproc/qcom_q6v5_pil.c +2
-1@@ -1184,19 +1221,31 @@ static int q6v5_probe(struct platform_device *pdev) qproc->version = desc->version; qproc->need_mem_protection = desc->need_mem_protection; - ret =q6v5_request_irq (qproc, pdev,"wdog" , q6v5_wdog_interrupt); + ret =q6v5_request_irq (qproc, pdev,"wdog" , q6v5_wdog_interrupt, + &qproc->wdog_interrupt);
I think it's time to inline this function instead. You can omit the first error handling and rely on request_irq to fail if you pass it an invalid irq number.
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_probe(struct platform_device *pdev) · line 1228
Quoted 3 lines
drivers/remoteproc/qcom_q6v5_pil.c +3
-0+if (ret <0 ) + goto free_rproc; +disable_irq (qproc->wdog_interrupt);
I presume this is to balance the IRQ enable/disable later?
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_probe(struct platform_device *pdev) · line 1229
Quoted 1 line
drivers/remoteproc/qcom_q6v5_pil.c +1
-0+
Regards,
Bjorn
Hi Bjorn,
Thanks for the review. Will make all the suggested changes.
Quoted 11 lines · Bjorn Andersson
Quoted 5 lines · Sibi Sankar
Introduce interrupt handler for smp2p ready interrupt and handle start completion. Remove the proxy votes for clocks and regulators in the handover interrupt context. Disable wdog and fatal interrupts on remoteproc device stop and re-enable them on remoteproc device start.
Can't the enable/disable dance be split out into a separate commit? Making the introduction of them cleaner in the git history?
will split it into separate commits
Quoted 14 lines
Quoted 14 lines
Signed-off-by Sibi Sankar <[email protected]>--- drivers/remoteproc/qcom_q6v5_pil.c | 71 +++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 11 deletions(-)drivers/remoteproc/qcom_q6v5_pil.c +0
-0@@ -143,6 +143,10 @@ struct q6v5 {struct qcom_smem_state *state;unsigned stop_bit;
Quoted 6 lines
drivers/remoteproc/qcom_q6v5_pil.c struct q6v5 { · line 148
Quoted 3 lines
drivers/remoteproc/qcom_q6v5_pil.c +3
-0+unsigned int handover_interrupt; +unsigned int wdog_interrupt; +unsigned int fatal_interrupt;Make these "int", and write "irq" instead of "interrupt".
ok
Quoted 52 lines
Quoted 52 lines
drivers/remoteproc/qcom_q6v5_pil.c +10
-5+struct clk *active_clks[8 ];struct clk *proxy_clks[4 ];int active_clk_count;@@ -170,6 +174,7 @@ struct q6v5 {struct qcom_rproc_ssr ssr_subdev;struct qcom_sysmon *sysmon;bool need_mem_protection; +bool unvoted_flag;int mpss_perm;int mba_perm;int version;@@ -727,6 +732,7 @@ static int q6v5_start(struct rproc *rproc)int xfermemop_ret;int ret; + qproc->unvoted_flag = false; ret =q6v5_regulator_enable (qproc, qproc->proxy_regs, qproc->proxy_reg_count);if (ret) {@@ -793,9 +799,16 @@ static int q6v5_start(struct rproc *rproc)if (ret) goto reclaim_mpss; +enable_irq (qproc->handover_interrupt); +enable_irq (qproc->wdog_interrupt); +enable_irq (qproc->fatal_interrupt); + ret =wait_for_completion_timeout (&qproc->start_done,msecs_to_jiffies (5000 ));if (ret ==0 ) { +disable_irq (qproc->handover_interrupt); +disable_irq (qproc->wdog_interrupt); +disable_irq (qproc->fatal_interrupt);dev_err (qproc->dev,"start timed out\n" ); ret = -ETIMEDOUT ; goto reclaim_mpss;@@ -809,11 +822,6 @@ static int q6v5_start(struct rproc *rproc) "Failed to reclaim mba buffer system may become unstable\n"); qproc->running = true; -q6v5_clk_disable (qproc->dev, qproc->proxy_clks, - qproc->proxy_clk_count); -q6v5_regulator_disable (qproc, qproc->proxy_regs, - qproc->proxy_reg_count); -return 0 ; reclaim_mpss:@@ -892,6 +900,16 @@ static int q6v5_stop(struct rproc *rproc)WARN_ON (ret);
Quoted 11 lines
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_stop(struct rproc *rproc) · line 909
Quoted 8 lines
drivers/remoteproc/qcom_q6v5_pil.c +7
-0reset_control_assert (qproc->mss_restart); +disable_irq (qproc->handover_interrupt); +if (!qproc->unvoted_flag) { +q6v5_clk_disable (qproc->dev, qproc->proxy_clks, + qproc->proxy_clk_count); +q6v5_regulator_disable (qproc, qproc->proxy_regs, + qproc->proxy_reg_count); + }Perhaps break this out into a separate function and call it from the two places?
Will create two separate functions for enable/disable
Quoted 7 lines
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_stop(struct rproc *rproc) · line 911
Quoted 3 lines
drivers/remoteproc/qcom_q6v5_pil.c +2
-0+disable_irq (qproc->wdog_interrupt); +disable_irq (qproc->fatal_interrupt);Any particular reason why you didn't group the
disable_irq()calls together? Would look prettier than spreading them on each side of the resource disable.
Nope they can be grouped together.
Quoted 8 lines
Quoted 5 lines
drivers/remoteproc/qcom_q6v5_pil.c +1
-0+q6v5_clk_disable (qproc->dev, qproc->active_clks, qproc->active_clk_count); q6v5_regulator_disable(qproc, qproc->active_regs,[..]
Quoted 2 lines
drivers/remoteproc/qcom_q6v5_pil.c +0
-0@@ -1184,19 +1221,31 @@ static int q6v5_probe(struct platform_device *pdev)
Quoted 9 lines
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_probe(struct platform_device *pdev) · line 1225
Quoted 5 lines
drivers/remoteproc/qcom_q6v5_pil.c +2
-1qproc->version = desc->version; qproc->need_mem_protection = desc->need_mem_protection; - ret =q6v5_request_irq (qproc, pdev,"wdog" , q6v5_wdog_interrupt); + ret =q6v5_request_irq (qproc, pdev,"wdog" , q6v5_wdog_interrupt, + &qproc->wdog_interrupt);I think it's time to inline this function instead. You can omit the first error handling and rely on
request_irqto fail if you pass it an invalid irq number.
I'll inline the function.
Quoted 7 lines
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_probe(struct platform_device *pdev) · line 1228
Quoted 4 lines
drivers/remoteproc/qcom_q6v5_pil.c +3
-0+if (ret <0 ) + goto free_rproc; +disable_irq (qproc->wdog_interrupt);I presume this is to balance the IRQ enable/disable later?
yes just to keep things symmetric.
Quoted 5 lines
drivers/remoteproc/qcom_q6v5_pil.c static int q6v5_probe(struct platform_device *pdev) · line 1229
Quoted 1 line
drivers/remoteproc/qcom_q6v5_pil.c +1
-0+Regards,
Bjorn
Signature · 3 lines
Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc, is a member of Code Aurora Forum, a Linux Foundation Collaborative Project