From: lee.jones@linaro.org (Lee Jones)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
Date: Fri, 31 Jul 2015 09:48:30 +0100 [thread overview]
Message-ID: <20150731084830.GC3208@x1> (raw)
In-Reply-To: <20150731070350.GT2564@lukather>
On Fri, 31 Jul 2015, Maxime Ripard wrote:
> On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > >
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> >
> > What should it be replaced with?
>
> clk->critical_count++
> clk_prepare_enable
>
> ?
Ah, so not replace it then. Just add a reference counter.
I'm with you, that's fine.
> > > > Cast your mind back to the reasons for this critical clock API. One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > >
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for. Take a look at clk_enable_critical().
> > >
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > >
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> >
> > That's the idea. See my point above, the one you replied "Indeed"
> > to. So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".
>
> We do agree on the semantic of clk_disable_critical :)
>
> > So then if it's not the last user to call clk_disable(), the last
> > one out the door will be allowed to finally gate the clock,
> > regardless whether it's critical aware or not.
>
> That's right, but what I mean would be a case where you have two users
> that are aware that it is a critical clock (A and B), and one which is
> not (C).
>
> If I understood correctly your code, if A calls clk_disable_critical,
> leave_on is set to false. That means that now, if C calls clk_disable
> on that clock, it will actually be shut down, while B still considers
> it a critical clock.
Hmm... I'd have to think about this.
How would you mark a clock as critical twice?
> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> >
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> >
> > That's not what happens (at least it shouldn't if I've coded it up
> > right). The API _still_ requires all of the users to give-up their
> > reference.
>
> Ah, right. So I guess it all boils down to the discussion you're
> having with Mike regarding whether critical users should expect to
> already have a reference taken or calling clk_prepare / clk_enable
> themselves.
Then we'd need a clk_prepare_enable_critical() :)
... which would be aware of the original reference (taken by
__set_critical_clocks). However, if a second knowledgeable driver
were to call it, then how would it know that whether the original
reference was still present or not? I guess that's where your
critical clock reference comes in. If it's the first critical user,
it would decrement the original reference, it it's a subsequent user,
then it won't
> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> >
> > If I understand you correctly, we already have a count. We use the
> > original reference count. No need for one of our own.
> >
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> >
> > Early start-up:
> > Clock 4 is marked as critical and a reference is taken (ref == 1)
> >
> > Driver probe:
> > SPI enables Clock 4 (ref == 2)
> > I2C enables Clock 4 (ref == 3)
> >
> > Suspend (without RAM driver's permission):
> > SPI disables Clock 4 (ref == 2)
> > I2C disables Clock 4 (ref == 1)
> > /*
> > * Clock won't be gated because:
> > * .leave_on is True - can't dec final reference
> > */
> >
> > Suspend (with RAM driver's permission):
> > /* Order is unimportant */
> > SPI disables Clock 4 (ref == 2)
> > RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> > I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> > /*
> > * Clock will be gated because:
> > * .leave_on is False, so (ref == 0)
> > */
> >
> > Resume:
> > /* Order is unimportant */
> > SPI enables Clock 4 (ref == 1)
> > RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > I2C enables Clock 4 (ref == 3)
> >
> > Hopefully that clears things up.
>
> It does indeed. I simply forgot to take into account the fact that it
> would still need the reference to be set to 0. My bad.
>
> Still, If we take the same kind of scenario:
>
> Early start-up:
> Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)
>
> Driver probe:
> SPI enables Clock 4 (ref == 2)
> I2C enables Clock 4 (ref == 3)
> RAM enables Clock 4 (ref == 4, leave_on = true )
> CPUIdle enables Clock 4 (ref == 5, leave_on = true )
>
> Suspend (with CPUIdle and RAM permissions):
> /* Order is unimportant */
> SPI disables Clock 4 (ref == 4)
> CPUIdle disables Clock 4 (ref == 3, leave_on = false )
> RAM disables Clock 4 (ref == 2, leave_on = false )
> I2C disables Clock 4 (ref == 1)
>
> And even though the clock will still be running when CPUIdle calls
> clk_disable_critical because of the enable_count, the status of
> leave_on is off, as the RAM driver still considers it to be left on
> (ie, hasn't called clk_disable_critical yet).
>
> Or at least, that's what I understood of it.
Right, I understood this problem when you suggested that two critical
clock users could be using the same clock. Other than having them
call clock_prepare_enable[_critical](), I'm not sure if that's
possible.
As I mentioned above, we can handle this with reference counting and
I'm happy to code that up.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
WARNING: multiple messages have this Message-ID (diff)
From: Lee Jones <lee.jones@linaro.org>
To: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, kernel@stlinux.com,
mturquette@linaro.org, sboyd@codeaurora.org,
devicetree@vger.kernel.org, geert@linux-m68k.org,
s.hauer@pengutronix.de
Subject: Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
Date: Fri, 31 Jul 2015 09:48:30 +0100 [thread overview]
Message-ID: <20150731084830.GC3208@x1> (raw)
In-Reply-To: <20150731070350.GT2564@lukather>
On Fri, 31 Jul 2015, Maxime Ripard wrote:
> On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > >
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> >
> > What should it be replaced with?
>
> clk->critical_count++
> clk_prepare_enable
>
> ?
Ah, so not replace it then. Just add a reference counter.
I'm with you, that's fine.
> > > > Cast your mind back to the reasons for this critical clock API. One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > >
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for. Take a look at clk_enable_critical().
> > >
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > >
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> >
> > That's the idea. See my point above, the one you replied "Indeed"
> > to. So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".
>
> We do agree on the semantic of clk_disable_critical :)
>
> > So then if it's not the last user to call clk_disable(), the last
> > one out the door will be allowed to finally gate the clock,
> > regardless whether it's critical aware or not.
>
> That's right, but what I mean would be a case where you have two users
> that are aware that it is a critical clock (A and B), and one which is
> not (C).
>
> If I understood correctly your code, if A calls clk_disable_critical,
> leave_on is set to false. That means that now, if C calls clk_disable
> on that clock, it will actually be shut down, while B still considers
> it a critical clock.
Hmm... I'd have to think about this.
How would you mark a clock as critical twice?
> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> >
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> >
> > That's not what happens (at least it shouldn't if I've coded it up
> > right). The API _still_ requires all of the users to give-up their
> > reference.
>
> Ah, right. So I guess it all boils down to the discussion you're
> having with Mike regarding whether critical users should expect to
> already have a reference taken or calling clk_prepare / clk_enable
> themselves.
Then we'd need a clk_prepare_enable_critical() :)
... which would be aware of the original reference (taken by
__set_critical_clocks). However, if a second knowledgeable driver
were to call it, then how would it know that whether the original
reference was still present or not? I guess that's where your
critical clock reference comes in. If it's the first critical user,
it would decrement the original reference, it it's a subsequent user,
then it won't
> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> >
> > If I understand you correctly, we already have a count. We use the
> > original reference count. No need for one of our own.
> >
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> >
> > Early start-up:
> > Clock 4 is marked as critical and a reference is taken (ref == 1)
> >
> > Driver probe:
> > SPI enables Clock 4 (ref == 2)
> > I2C enables Clock 4 (ref == 3)
> >
> > Suspend (without RAM driver's permission):
> > SPI disables Clock 4 (ref == 2)
> > I2C disables Clock 4 (ref == 1)
> > /*
> > * Clock won't be gated because:
> > * .leave_on is True - can't dec final reference
> > */
> >
> > Suspend (with RAM driver's permission):
> > /* Order is unimportant */
> > SPI disables Clock 4 (ref == 2)
> > RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> > I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> > /*
> > * Clock will be gated because:
> > * .leave_on is False, so (ref == 0)
> > */
> >
> > Resume:
> > /* Order is unimportant */
> > SPI enables Clock 4 (ref == 1)
> > RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > I2C enables Clock 4 (ref == 3)
> >
> > Hopefully that clears things up.
>
> It does indeed. I simply forgot to take into account the fact that it
> would still need the reference to be set to 0. My bad.
>
> Still, If we take the same kind of scenario:
>
> Early start-up:
> Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)
>
> Driver probe:
> SPI enables Clock 4 (ref == 2)
> I2C enables Clock 4 (ref == 3)
> RAM enables Clock 4 (ref == 4, leave_on = true )
> CPUIdle enables Clock 4 (ref == 5, leave_on = true )
>
> Suspend (with CPUIdle and RAM permissions):
> /* Order is unimportant */
> SPI disables Clock 4 (ref == 4)
> CPUIdle disables Clock 4 (ref == 3, leave_on = false )
> RAM disables Clock 4 (ref == 2, leave_on = false )
> I2C disables Clock 4 (ref == 1)
>
> And even though the clock will still be running when CPUIdle calls
> clk_disable_critical because of the enable_count, the status of
> leave_on is off, as the RAM driver still considers it to be left on
> (ie, hasn't called clk_disable_critical yet).
>
> Or at least, that's what I understood of it.
Right, I understood this problem when you suggested that two critical
clock users could be using the same clock. Other than having them
call clock_prepare_enable[_critical](), I'm not sure if that's
possible.
As I mentioned above, we can handle this with reference counting and
I'm happy to code that up.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
next prev parent reply other threads:[~2015-07-31 8:48 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-22 13:04 [PATCH v7 0/5] clk: Provide support for always-on clocks Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` [PATCH v7 1/5] ARM: sti: stih407-family: Supply defines for CLOCKGEN A0 Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` [PATCH v7 2/5] ARM: sti: stih410-clocks: Identify critical clocks Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-27 7:25 ` Maxime Ripard
2015-07-27 7:25 ` Maxime Ripard
2015-07-27 7:25 ` Maxime Ripard
2015-07-27 8:53 ` Lee Jones
2015-07-27 8:53 ` Lee Jones
2015-07-27 8:53 ` Lee Jones
2015-07-28 11:40 ` Maxime Ripard
2015-07-28 11:40 ` Maxime Ripard
2015-07-28 13:00 ` Lee Jones
2015-07-28 13:00 ` Lee Jones
2015-07-28 13:00 ` Lee Jones
2015-07-30 1:19 ` Michael Turquette
2015-07-30 1:19 ` Michael Turquette
2015-07-30 1:19 ` Michael Turquette
2015-07-30 9:50 ` Lee Jones
2015-07-30 9:50 ` Lee Jones
2015-07-30 9:50 ` Lee Jones
2015-07-30 22:47 ` Michael Turquette
2015-07-30 22:47 ` Michael Turquette
2015-07-31 7:30 ` Maxime Ripard
2015-07-31 7:30 ` Maxime Ripard
2015-07-31 7:30 ` Maxime Ripard
2015-07-31 8:32 ` Lee Jones
2015-07-31 8:32 ` Lee Jones
2015-07-31 8:32 ` Lee Jones
2015-07-31 7:03 ` Maxime Ripard
2015-07-31 7:03 ` Maxime Ripard
2015-07-31 7:03 ` Maxime Ripard
2015-07-31 8:48 ` Lee Jones [this message]
2015-07-31 8:48 ` Lee Jones
2015-07-30 1:21 ` Michael Turquette
2015-07-30 1:21 ` Michael Turquette
2015-07-30 1:21 ` Michael Turquette
2015-07-30 9:21 ` Lee Jones
2015-07-30 9:21 ` Lee Jones
2015-07-30 9:21 ` Lee Jones
2015-07-30 22:57 ` Michael Turquette
2015-07-30 22:57 ` Michael Turquette
2015-07-31 8:56 ` Lee Jones
2015-07-31 8:56 ` Lee Jones
2015-07-31 8:56 ` Lee Jones
2015-07-30 1:02 ` Michael Turquette
2015-07-30 1:02 ` Michael Turquette
2015-07-30 1:02 ` Michael Turquette
2015-07-30 11:17 ` Lee Jones
2015-07-30 11:17 ` Lee Jones
2015-07-30 23:35 ` Michael Turquette
2015-07-30 23:35 ` Michael Turquette
2015-07-30 23:35 ` Michael Turquette
2015-07-31 9:02 ` Lee Jones
2015-07-31 9:02 ` Lee Jones
2015-08-01 0:59 ` Michael Turquette
2015-08-01 0:59 ` Michael Turquette
2015-08-01 0:59 ` Michael Turquette
2015-07-22 13:04 ` [PATCH v7 4/5] clk: Provide critical clock support Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-08-17 5:43 ` Barry Song
2015-08-17 5:43 ` Barry Song
2015-08-17 5:43 ` Barry Song
2015-08-17 7:42 ` Lee Jones
2015-08-17 7:42 ` Lee Jones
2015-08-20 13:23 ` Barry Song
2015-08-20 13:23 ` Barry Song
2015-08-20 13:23 ` Barry Song
2015-07-22 13:04 ` [PATCH v7 5/5] clk: dt: Introduce binding for " Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-27 7:10 ` Maxime Ripard
2015-07-27 7:10 ` Maxime Ripard
2015-07-27 7:31 ` Lee Jones
2015-07-27 7:31 ` Lee Jones
2015-07-28 9:32 ` Maxime Ripard
2015-07-28 9:32 ` Maxime Ripard
2015-07-30 9:23 ` Lee Jones
2015-07-30 9:23 ` Lee Jones
2015-07-30 0:27 ` [PATCH v7 0/5] clk: Provide support for always-on clocks Michael Turquette
2015-07-30 0:27 ` Michael Turquette
2015-07-30 0:27 ` Michael Turquette
2015-07-30 9:09 ` Lee Jones
2015-07-30 9:09 ` Lee Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150731084830.GC3208@x1 \
--to=lee.jones@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.