diff mbox series

[v15,6/7] soc: qcom: rpmh-rsc: Clear active mode configuration for wake TCS

Message ID 1585660782-23416-7-git-send-email-mkshah@codeaurora.org
State New
Headers show
Series None | expand

Commit Message

Maulik Shah March 31, 2020, 1:19 p.m. UTC
From: "Raju P.L.S.S.S.N" <rplsssn@codeaurora.org>

For RSCs that have sleep & wake TCS but no dedicated active TCS, wake
TCS can be re-purposed to send active requests. Once the active requests
are sent and response is received, the active mode configuration needs
to be cleared so that controller can use wake TCS for sending wake
requests.

Introduce enable_tcs_irq() to enable completion IRQ for repurposed TCSes.

Fixes: 2de4b8d33eab (drivers: qcom: rpmh-rsc: allow active requests from wake TCS)
Signed-off-by: Raju P.L.S.S.S.N <rplsssn@codeaurora.org>
[mkshah: call enable_tcs_irq() within drv->lock, update commit message]
Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
---
 drivers/soc/qcom/rpmh-rsc.c | 77 +++++++++++++++++++++++++++++++--------------
 1 file changed, 54 insertions(+), 23 deletions(-)

Comments

Doug Anderson April 2, 2020, 8:14 p.m. UTC | #1
Hi,

On Tue, Mar 31, 2020 at 6:21 AM Maulik Shah <mkshah@codeaurora.org> wrote:
>
> @@ -243,6 +279,14 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
>                 }
>
>                 trace_rpmh_tx_done(drv, i, req, err);
> +
> +               /*
> +                * If wake tcs was re-purposed for sending active
> +                * votes, clear AMC trigger & enable modes and
> +                * disable interrupt for this TCS
> +                */
> +               if (!drv->tcs[ACTIVE_TCS].num_tcs)
> +                       __tcs_set_trigger(drv, i, false);

Still seems weird that we have to do the untrigger in the IRQ routine
here and also weird that we _don't_ do it in the IRQ routine for
non-borrowed TCSes.  I guess it's not the end of the world, though.

Reviewed-by: Douglas Anderson <dianders@chromium.org>
Maulik Shah April 6, 2020, 5:08 a.m. UTC | #2
Hi,

On 4/3/2020 1:44 AM, Doug Anderson wrote:
> Hi,
>
> On Tue, Mar 31, 2020 at 6:21 AM Maulik Shah <mkshah@codeaurora.org> wrote:
>> @@ -243,6 +279,14 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
>>                  }
>>
>>                  trace_rpmh_tx_done(drv, i, req, err);
>> +
>> +               /*
>> +                * If wake tcs was re-purposed for sending active
>> +                * votes, clear AMC trigger & enable modes and
>> +                * disable interrupt for this TCS
>> +                */
>> +               if (!drv->tcs[ACTIVE_TCS].num_tcs)
>> +                       __tcs_set_trigger(drv, i, false);
> Still seems weird that we have to do the untrigger in the IRQ routine
> here and also weird that we _don't_ do it in the IRQ routine for
> non-borrowed TCSes.  I guess it's not the end of the world, though.
>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

Thanks Doug for the review.

IRQ is only needed to be enabled for TCSes used as ACTIVE_TCS.

When we have dedicated ACTIVE_TCS, we leave IRQ always enabled from 
probe (one time configuration), since the TCS won't be used for anything 
other than to send ACTIVE transaction.

When we don't have dedicated ACTIVE_TCS, we enable it when borrowed TCS 
is used for ACTIVE transaction and then once its done using it, we 
disable it again to leave it in its original configuration.

Thanks,
Maulik
Doug Anderson April 6, 2020, 3:33 p.m. UTC | #3
Hi,

On Sun, Apr 5, 2020 at 10:08 PM Maulik Shah <mkshah@codeaurora.org> wrote:
>
> Hi,
>
> On 4/3/2020 1:44 AM, Doug Anderson wrote:
> > Hi,
> >
> > On Tue, Mar 31, 2020 at 6:21 AM Maulik Shah <mkshah@codeaurora.org> wrote:
> >> @@ -243,6 +279,14 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
> >>                  }
> >>
> >>                  trace_rpmh_tx_done(drv, i, req, err);
> >> +
> >> +               /*
> >> +                * If wake tcs was re-purposed for sending active
> >> +                * votes, clear AMC trigger & enable modes and
> >> +                * disable interrupt for this TCS
> >> +                */
> >> +               if (!drv->tcs[ACTIVE_TCS].num_tcs)
> >> +                       __tcs_set_trigger(drv, i, false);
> > Still seems weird that we have to do the untrigger in the IRQ routine
> > here and also weird that we _don't_ do it in the IRQ routine for
> > non-borrowed TCSes.  I guess it's not the end of the world, though.
> >
> > Reviewed-by: Douglas Anderson <dianders@chromium.org>
>
> Thanks Doug for the review.
>
> IRQ is only needed to be enabled for TCSes used as ACTIVE_TCS.
>
> When we have dedicated ACTIVE_TCS, we leave IRQ always enabled from
> probe (one time configuration), since the TCS won't be used for anything
> other than to send ACTIVE transaction.
>
> When we don't have dedicated ACTIVE_TCS, we enable it when borrowed TCS
> is used for ACTIVE transaction and then once its done using it, we
> disable it again to leave it in its original configuration.

Sure, I get the concept.  ...but:

* It seems like it would be ideal to not call __tcs_set_trigger() from
the IRQ handler.  It uses write_tcs_reg_sync() which has a wait loop
in it.  That's not something you normally want in an IRQ handler.

* It seems like it would be a common case for the WAKE_TCS to be
borrowed several times in-between actually using it as a WAKE_TCS.

To make both of the above things better, it seems like you could just
leave the WAKE_TCS configured for active-mode transfers and just
switch all that stuff off when you actually need it as a WAKE_TCS.  To
some extent we could conceptually re-envision this and think of this
as being the ACTIVE_TCS that is occasionally borrowed to make up for
not having a WAKE_TCS.


In any case, I think the patch you have right now is good enough and
it feels like it's overdue to land this series.  I'd suggest against
spinning at this point.  Maybe we can try to improve this in a future
patch after your series lands.

-Doug
diff mbox series

Patch

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 9e4512e..d5b6dff 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -207,6 +207,42 @@  static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv,
 	return NULL;
 }
 
+static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger)
+{
+	u32 enable;
+
+	/*
+	 * HW req: Clear the DRV_CONTROL and enable TCS again
+	 * While clearing ensure that the AMC mode trigger is cleared
+	 * and then the mode enable is cleared.
+	 */
+	enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0);
+	enable &= ~TCS_AMC_MODE_TRIGGER;
+	write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
+	enable &= ~TCS_AMC_MODE_ENABLE;
+	write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
+
+	if (trigger) {
+		/* Enable the AMC mode on the TCS and then trigger the TCS */
+		enable = TCS_AMC_MODE_ENABLE;
+		write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
+		enable |= TCS_AMC_MODE_TRIGGER;
+		write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
+	}
+}
+
+static void enable_tcs_irq(struct rsc_drv *drv, int tcs_id, bool enable)
+{
+	u32 data;
+
+	data = read_tcs_reg(drv, RSC_DRV_IRQ_ENABLE, 0, 0);
+	if (enable)
+		data |= BIT(tcs_id);
+	else
+		data &= ~BIT(tcs_id);
+	write_tcs_reg(drv, RSC_DRV_IRQ_ENABLE, 0, data);
+}
+
 /**
  * tcs_tx_done: TX Done interrupt handler
  */
@@ -243,6 +279,14 @@  static irqreturn_t tcs_tx_done(int irq, void *p)
 		}
 
 		trace_rpmh_tx_done(drv, i, req, err);
+
+		/*
+		 * If wake tcs was re-purposed for sending active
+		 * votes, clear AMC trigger & enable modes and
+		 * disable interrupt for this TCS
+		 */
+		if (!drv->tcs[ACTIVE_TCS].num_tcs)
+			__tcs_set_trigger(drv, i, false);
 skip:
 		/* Reclaim the TCS */
 		write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0);
@@ -250,6 +294,13 @@  static irqreturn_t tcs_tx_done(int irq, void *p)
 		write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i));
 		spin_lock(&drv->lock);
 		clear_bit(i, drv->tcs_in_use);
+		/*
+		 * Disable interrupt for WAKE TCS to avoid being
+		 * spammed with interrupts coming when the solver
+		 * sends its wake votes.
+		 */
+		if (!drv->tcs[ACTIVE_TCS].num_tcs)
+			enable_tcs_irq(drv, i, false);
 		spin_unlock(&drv->lock);
 		if (req)
 			rpmh_tx_done(req, err);
@@ -291,28 +342,6 @@  static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
 	write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable);
 }
 
-static void __tcs_trigger(struct rsc_drv *drv, int tcs_id)
-{
-	u32 enable;
-
-	/*
-	 * HW req: Clear the DRV_CONTROL and enable TCS again
-	 * While clearing ensure that the AMC mode trigger is cleared
-	 * and then the mode enable is cleared.
-	 */
-	enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0);
-	enable &= ~TCS_AMC_MODE_TRIGGER;
-	write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
-	enable &= ~TCS_AMC_MODE_ENABLE;
-	write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
-
-	/* Enable the AMC mode on the TCS and then trigger the TCS */
-	enable = TCS_AMC_MODE_ENABLE;
-	write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
-	enable |= TCS_AMC_MODE_TRIGGER;
-	write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
-}
-
 static int check_for_req_inflight(struct rsc_drv *drv, struct tcs_group *tcs,
 				  const struct tcs_request *msg)
 {
@@ -383,10 +412,12 @@  static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
 
 	tcs->req[tcs_id - tcs->offset] = msg;
 	set_bit(tcs_id, drv->tcs_in_use);
+	if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS)
+		enable_tcs_irq(drv, tcs_id, true);
 	spin_unlock(&drv->lock);
 
 	__tcs_buffer_write(drv, tcs_id, 0, msg);
-	__tcs_trigger(drv, tcs_id);
+	__tcs_set_trigger(drv, tcs_id, true);
 
 done_write:
 	spin_unlock_irqrestore(&tcs->lock, flags);