mbox series

[0/6] hwspinlock: allow sharing of hwspinlocks

Message ID 1552492237-28810-1-git-send-email-fabien.dessenne@st.com (mailing list archive)
Headers show
Series hwspinlock: allow sharing of hwspinlocks | expand

Message

Fabien DESSENNE March 13, 2019, 3:50 p.m. UTC
The current implementation does not allow two different devices to use
a common hwspinlock. This patch set proposes to have, as an option, some
hwspinlocks shared between several users.

Below is an example that explain the need for this:
	exti: interrupt-controller@5000d000 {
		compatible = "st,stm32mp1-exti", "syscon";
		interrupt-controller;
		#interrupt-cells = <2>;
		reg = <0x5000d000 0x400>;
		hwlocks = <&hsem 1>;
	};
The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
With the current hwspinlock implementation, only the first driver succeeds
in requesting (hwspin_lock_request_specific) the hwlock. The second request
fails.


The proposed approach does not modify the API, but extends the DT 'hwlocks'
property with a second optional parameter (the first one identifies an
hwlock) that specifies whether an hwlock is requested for exclusive usage
(current behavior) or can be shared between several users.
Examples:
	hwlocks = <&hsem 8>;	Ref to hwlock #8 for exclusive usage
	hwlocks = <&hsem 8 0>;	Ref to hwlock #8 for exclusive (0) usage
	hwlocks = <&hsem 8 1>;	Ref to hwlock #8 for shared (1) usage

As a constraint, the #hwlock-cells value must be 1 or 2.
In the current implementation, this can have theorically any value but:
- all of the exisiting drivers use the same value : 1.
- the framework supports only one value : 1 (see implementation of
  of_hwspin_lock_simple_xlate())
Hence, it shall not be a problem to restrict this value to 1 or 2 since
it won't break any driver.

Fabien Dessenne (6):
  dt-bindings: hwlock: add support of shared locks
  hwspinlock: allow sharing of hwspinlocks
  dt-bindings: hwlock: update STM32 #hwlock-cells value
  ARM: dts: stm32: Add hwspinlock node for stm32mp157 SoC
  ARM: dts: stm32: Add hwlock for irqchip on stm32mp157
  ARM: dts: stm32: hwlocks for GPIO for stm32mp157

 .../devicetree/bindings/hwlock/hwlock.txt          | 27 +++++--
 .../bindings/hwlock/st,stm32-hwspinlock.txt        |  6 +-
 Documentation/hwspinlock.txt                       | 10 ++-
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi          |  2 +
 arch/arm/boot/dts/stm32mp157c.dtsi                 | 10 +++
 drivers/hwspinlock/hwspinlock_core.c               | 82 +++++++++++++++++-----
 drivers/hwspinlock/hwspinlock_internal.h           |  2 +
 7 files changed, 108 insertions(+), 31 deletions(-)

Comments

Bjorn Andersson Aug. 1, 2019, 7:14 p.m. UTC | #1
On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:

> The current implementation does not allow two different devices to use
> a common hwspinlock. This patch set proposes to have, as an option, some
> hwspinlocks shared between several users.
> 
> Below is an example that explain the need for this:
> 	exti: interrupt-controller@5000d000 {
> 		compatible = "st,stm32mp1-exti", "syscon";
> 		interrupt-controller;
> 		#interrupt-cells = <2>;
> 		reg = <0x5000d000 0x400>;
> 		hwlocks = <&hsem 1>;
> 	};
> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
> With the current hwspinlock implementation, only the first driver succeeds
> in requesting (hwspin_lock_request_specific) the hwlock. The second request
> fails.
> 
> 
> The proposed approach does not modify the API, but extends the DT 'hwlocks'
> property with a second optional parameter (the first one identifies an
> hwlock) that specifies whether an hwlock is requested for exclusive usage
> (current behavior) or can be shared between several users.
> Examples:
> 	hwlocks = <&hsem 8>;	Ref to hwlock #8 for exclusive usage
> 	hwlocks = <&hsem 8 0>;	Ref to hwlock #8 for exclusive (0) usage
> 	hwlocks = <&hsem 8 1>;	Ref to hwlock #8 for shared (1) usage
> 
> As a constraint, the #hwlock-cells value must be 1 or 2.
> In the current implementation, this can have theorically any value but:
> - all of the exisiting drivers use the same value : 1.
> - the framework supports only one value : 1 (see implementation of
>   of_hwspin_lock_simple_xlate())
> Hence, it shall not be a problem to restrict this value to 1 or 2 since
> it won't break any driver.
> 

Hi Fabien,

Your series looks good, but it makes me wonder why the hardware locks
should be an exclusive resource.

How about just making all (specific) locks shared?

Regards,
Bjorn

> Fabien Dessenne (6):
>   dt-bindings: hwlock: add support of shared locks
>   hwspinlock: allow sharing of hwspinlocks
>   dt-bindings: hwlock: update STM32 #hwlock-cells value
>   ARM: dts: stm32: Add hwspinlock node for stm32mp157 SoC
>   ARM: dts: stm32: Add hwlock for irqchip on stm32mp157
>   ARM: dts: stm32: hwlocks for GPIO for stm32mp157
> 
>  .../devicetree/bindings/hwlock/hwlock.txt          | 27 +++++--
>  .../bindings/hwlock/st,stm32-hwspinlock.txt        |  6 +-
>  Documentation/hwspinlock.txt                       | 10 ++-
>  arch/arm/boot/dts/stm32mp157-pinctrl.dtsi          |  2 +
>  arch/arm/boot/dts/stm32mp157c.dtsi                 | 10 +++
>  drivers/hwspinlock/hwspinlock_core.c               | 82 +++++++++++++++++-----
>  drivers/hwspinlock/hwspinlock_internal.h           |  2 +
>  7 files changed, 108 insertions(+), 31 deletions(-)
> 
> -- 
> 2.7.4
>
Fabien DESSENNE Aug. 5, 2019, 8:48 a.m. UTC | #2
On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
>
>> The current implementation does not allow two different devices to use
>> a common hwspinlock. This patch set proposes to have, as an option, some
>> hwspinlocks shared between several users.
>>
>> Below is an example that explain the need for this:
>> 	exti: interrupt-controller@5000d000 {
>> 		compatible = "st,stm32mp1-exti", "syscon";
>> 		interrupt-controller;
>> 		#interrupt-cells = <2>;
>> 		reg = <0x5000d000 0x400>;
>> 		hwlocks = <&hsem 1>;
>> 	};
>> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
>> With the current hwspinlock implementation, only the first driver succeeds
>> in requesting (hwspin_lock_request_specific) the hwlock. The second request
>> fails.
>>
>>
>> The proposed approach does not modify the API, but extends the DT 'hwlocks'
>> property with a second optional parameter (the first one identifies an
>> hwlock) that specifies whether an hwlock is requested for exclusive usage
>> (current behavior) or can be shared between several users.
>> Examples:
>> 	hwlocks = <&hsem 8>;	Ref to hwlock #8 for exclusive usage
>> 	hwlocks = <&hsem 8 0>;	Ref to hwlock #8 for exclusive (0) usage
>> 	hwlocks = <&hsem 8 1>;	Ref to hwlock #8 for shared (1) usage
>>
>> As a constraint, the #hwlock-cells value must be 1 or 2.
>> In the current implementation, this can have theorically any value but:
>> - all of the exisiting drivers use the same value : 1.
>> - the framework supports only one value : 1 (see implementation of
>>    of_hwspin_lock_simple_xlate())
>> Hence, it shall not be a problem to restrict this value to 1 or 2 since
>> it won't break any driver.
>>
> Hi Fabien,
>
> Your series looks good, but it makes me wonder why the hardware locks
> should be an exclusive resource.
>
> How about just making all (specific) locks shared?

Hi Bjorn,

Making all locks shared is a possible implementation (my first 
implementation
was going this way) but there are some drawbacks we must be aware of:

A/ This theoretically break the legacy behavior (the legacy works with
exclusive (UNUSED radix tag) usage). As a consequence, an existing driver
that is currently failing to request a lock (already claimed by another
user) would now work fine. Not sure that there are such drivers, so this
point is probably not a real issue.

B/ This would introduce some inconsistency between the two 'request' API
which are hwspin_lock_request() and hwspin_lock_request_specific().
hwspin_lock_request() looks for an unused lock, so requests for an exclusive
usage. On the other side, request_specific() would request shared locks.
Worst the following sequence can transform an exclusive usage into a shared

one:
   -hwspin_lock_request() -> returns Id#0 (exclusive)
   -hwspin_lock_request() -> returns Id#1 (exclusive)
   -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
Honestly I am not sure that this is a real issue, but it's better to have it
in mind before we take ay decision
I could not find any driver using the hwspin_lock_request() API, we may 
decide
to remove (or to make deprecated) this API, having everything 'shared 
without
any conditions'.


I can see three options:
1- Keep my initial proposition
2- Have hwspin_lock_request_specific() using shared locks and
    hwspin_lock_request() using unused (so 'initially' exclusive) locks.
3- Have hwspin_lock_request_specific() using shared locks and
    remove/make deprecated hwspin_lock_request().

Just let me know what is your preference.

BR

Fabien

>
> Regards,
> Bjorn
>
>> Fabien Dessenne (6):
>>    dt-bindings: hwlock: add support of shared locks
>>    hwspinlock: allow sharing of hwspinlocks
>>    dt-bindings: hwlock: update STM32 #hwlock-cells value
>>    ARM: dts: stm32: Add hwspinlock node for stm32mp157 SoC
>>    ARM: dts: stm32: Add hwlock for irqchip on stm32mp157
>>    ARM: dts: stm32: hwlocks for GPIO for stm32mp157
>>
>>   .../devicetree/bindings/hwlock/hwlock.txt          | 27 +++++--
>>   .../bindings/hwlock/st,stm32-hwspinlock.txt        |  6 +-
>>   Documentation/hwspinlock.txt                       | 10 ++-
>>   arch/arm/boot/dts/stm32mp157-pinctrl.dtsi          |  2 +
>>   arch/arm/boot/dts/stm32mp157c.dtsi                 | 10 +++
>>   drivers/hwspinlock/hwspinlock_core.c               | 82 +++++++++++++++++-----
>>   drivers/hwspinlock/hwspinlock_internal.h           |  2 +
>>   7 files changed, 108 insertions(+), 31 deletions(-)
>>
>> -- 
>> 2.7.4
>>
Bjorn Andersson Aug. 5, 2019, 5:46 p.m. UTC | #3
On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:

> 
> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
> > On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
> >
> >> The current implementation does not allow two different devices to use
> >> a common hwspinlock. This patch set proposes to have, as an option, some
> >> hwspinlocks shared between several users.
> >>
> >> Below is an example that explain the need for this:
> >> 	exti: interrupt-controller@5000d000 {
> >> 		compatible = "st,stm32mp1-exti", "syscon";
> >> 		interrupt-controller;
> >> 		#interrupt-cells = <2>;
> >> 		reg = <0x5000d000 0x400>;
> >> 		hwlocks = <&hsem 1>;
> >> 	};
> >> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
> >> With the current hwspinlock implementation, only the first driver succeeds
> >> in requesting (hwspin_lock_request_specific) the hwlock. The second request
> >> fails.
> >>
> >>
> >> The proposed approach does not modify the API, but extends the DT 'hwlocks'
> >> property with a second optional parameter (the first one identifies an
> >> hwlock) that specifies whether an hwlock is requested for exclusive usage
> >> (current behavior) or can be shared between several users.
> >> Examples:
> >> 	hwlocks = <&hsem 8>;	Ref to hwlock #8 for exclusive usage
> >> 	hwlocks = <&hsem 8 0>;	Ref to hwlock #8 for exclusive (0) usage
> >> 	hwlocks = <&hsem 8 1>;	Ref to hwlock #8 for shared (1) usage
> >>
> >> As a constraint, the #hwlock-cells value must be 1 or 2.
> >> In the current implementation, this can have theorically any value but:
> >> - all of the exisiting drivers use the same value : 1.
> >> - the framework supports only one value : 1 (see implementation of
> >>    of_hwspin_lock_simple_xlate())
> >> Hence, it shall not be a problem to restrict this value to 1 or 2 since
> >> it won't break any driver.
> >>
> > Hi Fabien,
> >
> > Your series looks good, but it makes me wonder why the hardware locks
> > should be an exclusive resource.
> >
> > How about just making all (specific) locks shared?
> 
> Hi Bjorn,
> 
> Making all locks shared is a possible implementation (my first 
> implementation
> was going this way) but there are some drawbacks we must be aware of:
> 
> A/ This theoretically break the legacy behavior (the legacy works with
> exclusive (UNUSED radix tag) usage). As a consequence, an existing driver
> that is currently failing to request a lock (already claimed by another
> user) would now work fine. Not sure that there are such drivers, so this
> point is probably not a real issue.
> 

Right, it's possible that a previously misconfigured system now
successfully probes more than one device that uses a particular
spinlock. But such system would be suffering from issues related to e.g.
probe ordering.

So I think we should ignore this issue.

> B/ This would introduce some inconsistency between the two 'request' API
> which are hwspin_lock_request() and hwspin_lock_request_specific().
> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
> usage. On the other side, request_specific() would request shared locks.
> Worst the following sequence can transform an exclusive usage into a shared
> 

There is already an inconsistency in between these; as with above any
system that uses both request() and request_specific() will be suffering
from intermittent failures due to probe ordering.

> one:
>    -hwspin_lock_request() -> returns Id#0 (exclusive)
>    -hwspin_lock_request() -> returns Id#1 (exclusive)
>    -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
> Honestly I am not sure that this is a real issue, but it's better to have it
> in mind before we take ay decision

The case where I can see a
problem with this would be if the two clients somehow would nest their
locking regions.

But generally I think this could consider this an improvement, because
the request_specific() would now be able to acquire its hwlock, with
some additional contention due to the multiple use.

> I could not find any driver using the hwspin_lock_request() API, we
> may decide to remove (or to make deprecated) this API, having
> everything 'shared without any conditions'.
> 

It would be nice to have an upstream user of this API.

> 
> I can see three options:
> 1- Keep my initial proposition
> 2- Have hwspin_lock_request_specific() using shared locks and
>     hwspin_lock_request() using unused (so 'initially' exclusive) locks.
> 3- Have hwspin_lock_request_specific() using shared locks and
>     remove/make deprecated hwspin_lock_request().
> 
> Just let me know what is your preference.
> 

I think we should start with #2 and would like input from e.g. Suman
regarding #3.

Regards,
Bjorn

> BR
> 
> Fabien
> 
> >
> > Regards,
> > Bjorn
> >
> >> Fabien Dessenne (6):
> >>    dt-bindings: hwlock: add support of shared locks
> >>    hwspinlock: allow sharing of hwspinlocks
> >>    dt-bindings: hwlock: update STM32 #hwlock-cells value
> >>    ARM: dts: stm32: Add hwspinlock node for stm32mp157 SoC
> >>    ARM: dts: stm32: Add hwlock for irqchip on stm32mp157
> >>    ARM: dts: stm32: hwlocks for GPIO for stm32mp157
> >>
> >>   .../devicetree/bindings/hwlock/hwlock.txt          | 27 +++++--
> >>   .../bindings/hwlock/st,stm32-hwspinlock.txt        |  6 +-
> >>   Documentation/hwspinlock.txt                       | 10 ++-
> >>   arch/arm/boot/dts/stm32mp157-pinctrl.dtsi          |  2 +
> >>   arch/arm/boot/dts/stm32mp157c.dtsi                 | 10 +++
> >>   drivers/hwspinlock/hwspinlock_core.c               | 82 +++++++++++++++++-----
> >>   drivers/hwspinlock/hwspinlock_internal.h           |  2 +
> >>   7 files changed, 108 insertions(+), 31 deletions(-)
> >>
> >> -- 
> >> 2.7.4
> >>
Fabien DESSENNE Aug. 6, 2019, 7:43 a.m. UTC | #4
Hi Suman,

Could you please let us know your thoughts or comments?

BR

Fabien


> -----Original Message-----
> From: Bjorn Andersson <bjorn.andersson@linaro.org>
> Sent: lundi 5 août 2019 19:47
> To: Fabien DESSENNE <fabien.dessenne@st.com>
> Cc: Ohad Ben-Cohen <ohad@wizery.com>; Rob Herring <robh+dt@kernel.org>;
> Mark Rutland <mark.rutland@arm.com>; Maxime Coquelin
> <mcoquelin.stm32@gmail.com>; Alexandre TORGUE
> <alexandre.torgue@st.com>; Jonathan Corbet <corbet@lwn.net>; linux-
> remoteproc@vger.kernel.org; devicetree@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-stm32@st-md-mailman.stormreply.com; linux-arm-
> kernel@lists.infradead.org; linux-doc@vger.kernel.org; Benjamin GAIGNARD
> <benjamin.gaignard@st.com>
> Subject: Re: [PATCH 0/6] hwspinlock: allow sharing of hwspinlocks
> 
> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
> 
> >
> > On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
> > > On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
> > >
> > >> The current implementation does not allow two different devices to
> > >> use a common hwspinlock. This patch set proposes to have, as an
> > >> option, some hwspinlocks shared between several users.
> > >>
> > >> Below is an example that explain the need for this:
> > >> 	exti: interrupt-controller@5000d000 {
> > >> 		compatible = "st,stm32mp1-exti", "syscon";
> > >> 		interrupt-controller;
> > >> 		#interrupt-cells = <2>;
> > >> 		reg = <0x5000d000 0x400>;
> > >> 		hwlocks = <&hsem 1>;
> > >> 	};
> > >> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
> > >> With the current hwspinlock implementation, only the first driver
> > >> succeeds in requesting (hwspin_lock_request_specific) the hwlock.
> > >> The second request fails.
> > >>
> > >>
> > >> The proposed approach does not modify the API, but extends the DT
> 'hwlocks'
> > >> property with a second optional parameter (the first one identifies
> > >> an
> > >> hwlock) that specifies whether an hwlock is requested for exclusive
> > >> usage (current behavior) or can be shared between several users.
> > >> Examples:
> > >> 	hwlocks = <&hsem 8>;	Ref to hwlock #8 for exclusive usage
> > >> 	hwlocks = <&hsem 8 0>;	Ref to hwlock #8 for exclusive (0) usage
> > >> 	hwlocks = <&hsem 8 1>;	Ref to hwlock #8 for shared (1) usage
> > >>
> > >> As a constraint, the #hwlock-cells value must be 1 or 2.
> > >> In the current implementation, this can have theorically any value but:
> > >> - all of the exisiting drivers use the same value : 1.
> > >> - the framework supports only one value : 1 (see implementation of
> > >>    of_hwspin_lock_simple_xlate())
> > >> Hence, it shall not be a problem to restrict this value to 1 or 2
> > >> since it won't break any driver.
> > >>
> > > Hi Fabien,
> > >
> > > Your series looks good, but it makes me wonder why the hardware
> > > locks should be an exclusive resource.
> > >
> > > How about just making all (specific) locks shared?
> >
> > Hi Bjorn,
> >
> > Making all locks shared is a possible implementation (my first
> > implementation was going this way) but there are some drawbacks we
> > must be aware of:
> >
> > A/ This theoretically break the legacy behavior (the legacy works with
> > exclusive (UNUSED radix tag) usage). As a consequence, an existing
> > driver that is currently failing to request a lock (already claimed by
> > another
> > user) would now work fine. Not sure that there are such drivers, so
> > this point is probably not a real issue.
> >
> 
> Right, it's possible that a previously misconfigured system now successfully
> probes more than one device that uses a particular spinlock. But such system
> would be suffering from issues related to e.g.
> probe ordering.
> 
> So I think we should ignore this issue.
> 
> > B/ This would introduce some inconsistency between the two 'request'
> > API which are hwspin_lock_request() and hwspin_lock_request_specific().
> > hwspin_lock_request() looks for an unused lock, so requests for an
> > exclusive usage. On the other side, request_specific() would request shared
> locks.
> > Worst the following sequence can transform an exclusive usage into a
> > shared
> >
> 
> There is already an inconsistency in between these; as with above any system
> that uses both request() and request_specific() will be suffering from intermittent
> failures due to probe ordering.
> 
> > one:
> >    -hwspin_lock_request() -> returns Id#0 (exclusive)
> >    -hwspin_lock_request() -> returns Id#1 (exclusive)
> >    -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0
> > shared Honestly I am not sure that this is a real issue, but it's
> > better to have it in mind before we take ay decision
> 
> The case where I can see a
> problem with this would be if the two clients somehow would nest their locking
> regions.
> 
> But generally I think this could consider this an improvement, because the
> request_specific() would now be able to acquire its hwlock, with some additional
> contention due to the multiple use.
> 
> > I could not find any driver using the hwspin_lock_request() API, we
> > may decide to remove (or to make deprecated) this API, having
> > everything 'shared without any conditions'.
> >
> 
> It would be nice to have an upstream user of this API.
> 
> >
> > I can see three options:
> > 1- Keep my initial proposition
> > 2- Have hwspin_lock_request_specific() using shared locks and
> >     hwspin_lock_request() using unused (so 'initially' exclusive) locks.
> > 3- Have hwspin_lock_request_specific() using shared locks and
> >     remove/make deprecated hwspin_lock_request().
> >
> > Just let me know what is your preference.
> >
> 
> I think we should start with #2 and would like input from e.g. Suman regarding #3.
> 
> Regards,
> Bjorn
> 
> > BR
> >
> > Fabien
> >
> > >
> > > Regards,
> > > Bjorn
> > >
> > >> Fabien Dessenne (6):
> > >>    dt-bindings: hwlock: add support of shared locks
> > >>    hwspinlock: allow sharing of hwspinlocks
> > >>    dt-bindings: hwlock: update STM32 #hwlock-cells value
> > >>    ARM: dts: stm32: Add hwspinlock node for stm32mp157 SoC
> > >>    ARM: dts: stm32: Add hwlock for irqchip on stm32mp157
> > >>    ARM: dts: stm32: hwlocks for GPIO for stm32mp157
> > >>
> > >>   .../devicetree/bindings/hwlock/hwlock.txt          | 27 +++++--
> > >>   .../bindings/hwlock/st,stm32-hwspinlock.txt        |  6 +-
> > >>   Documentation/hwspinlock.txt                       | 10 ++-
> > >>   arch/arm/boot/dts/stm32mp157-pinctrl.dtsi          |  2 +
> > >>   arch/arm/boot/dts/stm32mp157c.dtsi                 | 10 +++
> > >>   drivers/hwspinlock/hwspinlock_core.c               | 82 +++++++++++++++++-
> ----
> > >>   drivers/hwspinlock/hwspinlock_internal.h           |  2 +
> > >>   7 files changed, 108 insertions(+), 31 deletions(-)
> > >>
> > >> --
> > >> 2.7.4
> > >>
Suman Anna Aug. 6, 2019, 5:38 p.m. UTC | #5
Hi Fabien,

On 8/5/19 12:46 PM, Bjorn Andersson wrote:
> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
> 
>>
>> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
>>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
>>>
>>>> The current implementation does not allow two different devices to use
>>>> a common hwspinlock. This patch set proposes to have, as an option, some
>>>> hwspinlocks shared between several users.
>>>>
>>>> Below is an example that explain the need for this:
>>>> 	exti: interrupt-controller@5000d000 {
>>>> 		compatible = "st,stm32mp1-exti", "syscon";
>>>> 		interrupt-controller;
>>>> 		#interrupt-cells = <2>;
>>>> 		reg = <0x5000d000 0x400>;
>>>> 		hwlocks = <&hsem 1>;
>>>> 	};
>>>> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
>>>> With the current hwspinlock implementation, only the first driver succeeds
>>>> in requesting (hwspin_lock_request_specific) the hwlock. The second request
>>>> fails.

Help me understand the problem that you are trying to solve here. Is
this a case of you having two clients on Linux-side needing to use the
same lock but still requiring the arbitration with software running on
some other remote processor? Are they talking to the same entity on the
remote-side or different peers.

I see the series is all about getting a handle so that they can use the
API, and is the expected usage that the same entity will lock and unlock
before the other driver can lock it.

>>>>
>>>>
>>>> The proposed approach does not modify the API, but extends the DT 'hwlocks'
>>>> property with a second optional parameter (the first one identifies an
>>>> hwlock) that specifies whether an hwlock is requested for exclusive usage
>>>> (current behavior) or can be shared between several users.
>>>> Examples:
>>>> 	hwlocks = <&hsem 8>;	Ref to hwlock #8 for exclusive usage
>>>> 	hwlocks = <&hsem 8 0>;	Ref to hwlock #8 for exclusive (0) usage
>>>> 	hwlocks = <&hsem 8 1>;	Ref to hwlock #8 for shared (1) usage
>>>>
>>>> As a constraint, the #hwlock-cells value must be 1 or 2.
>>>> In the current implementation, this can have theorically any value but:
>>>> - all of the exisiting drivers use the same value : 1.
>>>> - the framework supports only one value : 1 (see implementation of
>>>>    of_hwspin_lock_simple_xlate())
>>>> Hence, it shall not be a problem to restrict this value to 1 or 2 since
>>>> it won't break any driver.
>>>>
>>> Hi Fabien,
>>>
>>> Your series looks good, but it makes me wonder why the hardware locks
>>> should be an exclusive resource.
>>>
>>> How about just making all (specific) locks shared?
>>
>> Hi Bjorn,
>>
>> Making all locks shared is a possible implementation (my first 
>> implementation
>> was going this way) but there are some drawbacks we must be aware of:
>>
>> A/ This theoretically break the legacy behavior (the legacy works with
>> exclusive (UNUSED radix tag) usage). As a consequence, an existing driver
>> that is currently failing to request a lock (already claimed by another
>> user) would now work fine. Not sure that there are such drivers, so this
>> point is probably not a real issue.
>>
> 
> Right, it's possible that a previously misconfigured system now
> successfully probes more than one device that uses a particular
> spinlock. But such system would be suffering from issues related to e.g.
> probe ordering.
> 
> So I think we should ignore this issue.
> 
>> B/ This would introduce some inconsistency between the two 'request' API
>> which are hwspin_lock_request() and hwspin_lock_request_specific().
>> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
>> usage. On the other side, request_specific() would request shared locks.
>> Worst the following sequence can transform an exclusive usage into a shared
>>
> 
> There is already an inconsistency in between these; as with above any
> system that uses both request() and request_specific() will be suffering
> from intermittent failures due to probe ordering.
> 
>> one:
>>    -hwspin_lock_request() -> returns Id#0 (exclusive)
>>    -hwspin_lock_request() -> returns Id#1 (exclusive)
>>    -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
>> Honestly I am not sure that this is a real issue, but it's better to have it
>> in mind before we take ay decision

Wouldn't it be actually simpler to just introduce a new specific API
variant for this, similar to the reset core for example (it uses a
separate exclusive API), without having to modify the bindings at all.
It is just a case of your driver using the right API, and the core can
be modified to use the additional tag semantics based on the API. It
should avoid any confusion with say using a different second cell value
for the same lock in two different nodes.

If you are sharing a hwlock on the Linux side, surely your driver should
be aware that it is a shared lock. The tag can be set during the first
request API, and you look through both tags when giving out a handle.

Obviously, the hwspin_lock_request() API usage semantics always had the
implied additional need for communicating the lock id to the other peer
entity, so a realistic usage is most always the specific API variant. I
doubt this API would be of much use for the shared driver usage. This
also implies that the client user does not care about specifying a lock
in DT.

regards
Suman

> 
> The case where I can see a
> problem with this would be if the two clients somehow would nest their
> locking regions.
> 
> But generally I think this could consider this an improvement, because
> the request_specific() would now be able to acquire its hwlock, with
> some additional contention due to the multiple use.
> 
>> I could not find any driver using the hwspin_lock_request() API, we
>> may decide to remove (or to make deprecated) this API, having
>> everything 'shared without any conditions'.
>>
> 
> It would be nice to have an upstream user of this API.
> 
>>
>> I can see three options:
>> 1- Keep my initial proposition
>> 2- Have hwspin_lock_request_specific() using shared locks and
>>     hwspin_lock_request() using unused (so 'initially' exclusive) locks.
>> 3- Have hwspin_lock_request_specific() using shared locks and
>>     remove/make deprecated hwspin_lock_request().
>>
>> Just let me know what is your preference.
>>
> 
> I think we should start with #2 and would like input from e.g. Suman
> regarding #3.
> 
> Regards,
> Bjorn
> 
>> BR
>>
>> Fabien
>>
>>>
>>> Regards,
>>> Bjorn
>>>
>>>> Fabien Dessenne (6):
>>>>    dt-bindings: hwlock: add support of shared locks
>>>>    hwspinlock: allow sharing of hwspinlocks
>>>>    dt-bindings: hwlock: update STM32 #hwlock-cells value
>>>>    ARM: dts: stm32: Add hwspinlock node for stm32mp157 SoC
>>>>    ARM: dts: stm32: Add hwlock for irqchip on stm32mp157
>>>>    ARM: dts: stm32: hwlocks for GPIO for stm32mp157
>>>>
>>>>   .../devicetree/bindings/hwlock/hwlock.txt          | 27 +++++--
>>>>   .../bindings/hwlock/st,stm32-hwspinlock.txt        |  6 +-
>>>>   Documentation/hwspinlock.txt                       | 10 ++-
>>>>   arch/arm/boot/dts/stm32mp157-pinctrl.dtsi          |  2 +
>>>>   arch/arm/boot/dts/stm32mp157c.dtsi                 | 10 +++
>>>>   drivers/hwspinlock/hwspinlock_core.c               | 82 +++++++++++++++++-----
>>>>   drivers/hwspinlock/hwspinlock_internal.h           |  2 +
>>>>   7 files changed, 108 insertions(+), 31 deletions(-)
>>>>
>>>> -- 
>>>> 2.7.4
>>>>
Bjorn Andersson Aug. 6, 2019, 6:21 p.m. UTC | #6
On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:

> Hi Fabien,
> 
> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
> > On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
> > 
> >>
> >> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
> >>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
[..]
> >> B/ This would introduce some inconsistency between the two 'request' API
> >> which are hwspin_lock_request() and hwspin_lock_request_specific().
> >> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
> >> usage. On the other side, request_specific() would request shared locks.
> >> Worst the following sequence can transform an exclusive usage into a shared
> >>
> > 
> > There is already an inconsistency in between these; as with above any
> > system that uses both request() and request_specific() will be suffering
> > from intermittent failures due to probe ordering.
> > 
> >> one:
> >>    -hwspin_lock_request() -> returns Id#0 (exclusive)
> >>    -hwspin_lock_request() -> returns Id#1 (exclusive)
> >>    -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
> >> Honestly I am not sure that this is a real issue, but it's better to have it
> >> in mind before we take ay decision
> 
> Wouldn't it be actually simpler to just introduce a new specific API
> variant for this, similar to the reset core for example (it uses a
> separate exclusive API), without having to modify the bindings at all.
> It is just a case of your driver using the right API, and the core can
> be modified to use the additional tag semantics based on the API. It
> should avoid any confusion with say using a different second cell value
> for the same lock in two different nodes.
> 

But this implies that there is an actual need to hold these locks
exclusively. Given that they are (except for the raw case) all wrapped
by Linux locking primitives there shouldn't be a problem sharing a lock
(except possibly for the raw case).


I agree that we shouldn't specify this property in DT - if anything it
should be a variant of the API.

> If you are sharing a hwlock on the Linux side, surely your driver should
> be aware that it is a shared lock. The tag can be set during the first
> request API, and you look through both tags when giving out a handle.
> 

Why would the driver need to know about it?

> Obviously, the hwspin_lock_request() API usage semantics always had the
> implied additional need for communicating the lock id to the other peer
> entity, so a realistic usage is most always the specific API variant. I
> doubt this API would be of much use for the shared driver usage. This
> also implies that the client user does not care about specifying a lock
> in DT.
> 

Afaict if the lock are shared then there shouldn't be a problem with
some clients using the request API and others request_specific(). As any
collisions would simply mean that there are more contention on the lock.

With the current exclusive model that is not possible and the success of
the request_specific will depend on probe order.

But perhaps it should be explicitly prohibited to use both APIs on the
same hwspinlock instance?

Regards,
Bjorn
Suman Anna Aug. 6, 2019, 9:30 p.m. UTC | #7
On 8/6/19 1:21 PM, Bjorn Andersson wrote:
> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
> 
>> Hi Fabien,
>>
>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
>>> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
>>>
>>>>
>>>> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
>>>>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
> [..]
>>>> B/ This would introduce some inconsistency between the two 'request' API
>>>> which are hwspin_lock_request() and hwspin_lock_request_specific().
>>>> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
>>>> usage. On the other side, request_specific() would request shared locks.
>>>> Worst the following sequence can transform an exclusive usage into a shared
>>>>
>>>
>>> There is already an inconsistency in between these; as with above any
>>> system that uses both request() and request_specific() will be suffering
>>> from intermittent failures due to probe ordering.
>>>
>>>> one:
>>>>    -hwspin_lock_request() -> returns Id#0 (exclusive)
>>>>    -hwspin_lock_request() -> returns Id#1 (exclusive)
>>>>    -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
>>>> Honestly I am not sure that this is a real issue, but it's better to have it
>>>> in mind before we take ay decision
>>
>> Wouldn't it be actually simpler to just introduce a new specific API
>> variant for this, similar to the reset core for example (it uses a
>> separate exclusive API), without having to modify the bindings at all.
>> It is just a case of your driver using the right API, and the core can
>> be modified to use the additional tag semantics based on the API. It
>> should avoid any confusion with say using a different second cell value
>> for the same lock in two different nodes.
>>
> 
> But this implies that there is an actual need to hold these locks
> exclusively. Given that they are (except for the raw case) all wrapped
> by Linux locking primitives there shouldn't be a problem sharing a lock
> (except possibly for the raw case).

Yes agreed, the HWLOCK_RAW and HWLOCK_IN_ATOMIC cases are unprotected. I
am still trying to understand better the usecase to see if the same lock
is being multiplexed for different protection contexts, or if all of
them are protecting the same context.

> 
> I agree that we shouldn't specify this property in DT - if anything it
> should be a variant of the API.
> 
>> If you are sharing a hwlock on the Linux side, surely your driver should
>> be aware that it is a shared lock. The tag can be set during the first
>> request API, and you look through both tags when giving out a handle.
>>
> 
> Why would the driver need to know about it?

Just the semantics if we were to support single user vs multiple users
on Linux-side to even get a handle. Your point is that this may be moot
since we have protection anyway other than the raw cases. But we need to
be able to have the same API work across all cases.

So far, it had mostly been that there would be one user on Linux
competing with other equivalent peer entities on different processors.
It is not common to have multiple users since these protection schemes
are usually needed only at the lowest levels of a stack, so the
exclusive handle stuff had been sufficient.

> 
>> Obviously, the hwspin_lock_request() API usage semantics always had the
>> implied additional need for communicating the lock id to the other peer
>> entity, so a realistic usage is most always the specific API variant. I
>> doubt this API would be of much use for the shared driver usage. This
>> also implies that the client user does not care about specifying a lock
>> in DT.
>>
> 
> Afaict if the lock are shared then there shouldn't be a problem with
> some clients using the request API and others request_specific(). As any
> collisions would simply mean that there are more contention on the lock.
> 
> With the current exclusive model that is not possible and the success of
> the request_specific will depend on probe order.
> 
> But perhaps it should be explicitly prohibited to use both APIs on the
> same hwspinlock instance?

Yeah, they are meant to be complimentary usage, though I doubt we will
ever have any realistic users for the generic API if we haven't had a
usage so far. I had posted a concept of reserved locks long back [1] to
keep away certain locks from the generic requestor, but dropped it since
we did not have an actual use-case needing it.

regards
Suman

[1] https://lwn.net/Articles/611944/
Fabien DESSENNE Aug. 7, 2019, 8:39 a.m. UTC | #8
Hi


On 06/08/2019 11:30 PM, Suman Anna wrote:
> On 8/6/19 1:21 PM, Bjorn Andersson wrote:
>> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
>>
>>> Hi Fabien,
>>>
>>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
>>>> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
>>>>
>>>>> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
>>>>>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
>> [..]
>>>>> B/ This would introduce some inconsistency between the two 'request' API
>>>>> which are hwspin_lock_request() and hwspin_lock_request_specific().
>>>>> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
>>>>> usage. On the other side, request_specific() would request shared locks.
>>>>> Worst the following sequence can transform an exclusive usage into a shared
>>>>>
>>>> There is already an inconsistency in between these; as with above any
>>>> system that uses both request() and request_specific() will be suffering
>>>> from intermittent failures due to probe ordering.
>>>>
>>>>> one:
>>>>>     -hwspin_lock_request() -> returns Id#0 (exclusive)
>>>>>     -hwspin_lock_request() -> returns Id#1 (exclusive)
>>>>>     -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
>>>>> Honestly I am not sure that this is a real issue, but it's better to have it
>>>>> in mind before we take ay decision
>>> Wouldn't it be actually simpler to just introduce a new specific API
>>> variant for this, similar to the reset core for example (it uses a
>>> separate exclusive API), without having to modify the bindings at all.
>>> It is just a case of your driver using the right API, and the core can
>>> be modified to use the additional tag semantics based on the API. It
>>> should avoid any confusion with say using a different second cell value
>>> for the same lock in two different nodes.
>>>
>> But this implies that there is an actual need to hold these locks
>> exclusively. Given that they are (except for the raw case) all wrapped
>> by Linux locking primitives there shouldn't be a problem sharing a lock
>> (except possibly for the raw case).
> Yes agreed, the HWLOCK_RAW and HWLOCK_IN_ATOMIC cases are unprotected. I
> am still trying to understand better the usecase to see if the same lock
> is being multiplexed for different protection contexts, or if all of
> them are protecting the same context.


Here are two different examples that explain the need for changes.
In both cases the Linux clients are talking to a single entity on the
remote-side.

Example 1:
     exti: interrupt-controller@5000d000 {
         compatible = "st,stm32mp1-exti", "syscon";
         interrupt-controller;
         #interrupt-cells = <2>;
         reg = <0x5000d000 0x400>;
         hwlocks = <&hsem 1>;
     };
The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
With the current hwspinlock implementation, only the first driver succeeds
in requesting (hwspin_lock_request_specific) the hwlock. The second request
fails.
Here, we really need to share the hwlock between the two drivers.
Note: hardware spinlock support for regmap was 'recently' introduced in 4.15
see https://lore.kernel.org/patchwork/patch/845941/



Example 2:
Here it is more a question of optimization : we want to save the number of
hwlocks used to protect resources, using an unique hwlock to protect all
pinctrl resources:
         pinctrl: pin-controller@50002000 {
             compatible = "st,stm32mp157-pinctrl";
             ranges = <0 0x50002000 0xa400>;
             hwlocks = <&hsem 0 1>;

         pinctrl_z: pin-controller-z@54004000 {
             compatible = "st,stm32mp157-z-pinctrl";
             ranges = <0 0x54004000 0x400>;
             pins-are-numbered;
             hwlocks = <&hsem 0 1>;

>
>> I agree that we shouldn't specify this property in DT - if anything it
>> should be a variant of the API.


If we decide to add a 'shared' API, then, what about the generic regmap 
driver?

In the context of above example1, this would require to update the 
regmap driver.

But would this be acceptable for any driver using syscon/regmap?


I think it is better to keep the existing API (modifying it so it always 
allows

hwlocks sharing, so no need for bindings update) than adding another API.



>>
>>> If you are sharing a hwlock on the Linux side, surely your driver should
>>> be aware that it is a shared lock. The tag can be set during the first
>>> request API, and you look through both tags when giving out a handle.
>>>
>> Why would the driver need to know about it?
> Just the semantics if we were to support single user vs multiple users
> on Linux-side to even get a handle. Your point is that this may be moot
> since we have protection anyway other than the raw cases. But we need to
> be able to have the same API work across all cases.
>
> So far, it had mostly been that there would be one user on Linux
> competing with other equivalent peer entities on different processors.
> It is not common to have multiple users since these protection schemes
> are usually needed only at the lowest levels of a stack, so the
> exclusive handle stuff had been sufficient.
>
>>> Obviously, the hwspin_lock_request() API usage semantics always had the
>>> implied additional need for communicating the lock id to the other peer
>>> entity, so a realistic usage is most always the specific API variant. I
>>> doubt this API would be of much use for the shared driver usage. This
>>> also implies that the client user does not care about specifying a lock
>>> in DT.
>>>
>> Afaict if the lock are shared then there shouldn't be a problem with
>> some clients using the request API and others request_specific(). As any
>> collisions would simply mean that there are more contention on the lock.
>>
>> With the current exclusive model that is not possible and the success of
>> the request_specific will depend on probe order.
>>
>> But perhaps it should be explicitly prohibited to use both APIs on the
>> same hwspinlock instance?
> Yeah, they are meant to be complimentary usage, though I doubt we will
> ever have any realistic users for the generic API if we haven't had a
> usage so far. I had posted a concept of reserved locks long back [1] to
> keep away certain locks from the generic requestor, but dropped it since
> we did not have an actual use-case needing it.
>
> regards
> Suman
>
> [1] https://lwn.net/Articles/611944/
Suman Anna Aug. 7, 2019, 4:19 p.m. UTC | #9
Hi Fabien,

On 8/7/19 3:39 AM, Fabien DESSENNE wrote:
> Hi
> 
> On 06/08/2019 11:30 PM, Suman Anna wrote:
>> On 8/6/19 1:21 PM, Bjorn Andersson wrote:
>>> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
>>>
>>>> Hi Fabien,
>>>>
>>>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
>>>>> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
>>>>>
>>>>>> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
>>>>>>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
>>> [..]
>>>>>> B/ This would introduce some inconsistency between the two 'request' API
>>>>>> which are hwspin_lock_request() and hwspin_lock_request_specific().
>>>>>> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
>>>>>> usage. On the other side, request_specific() would request shared locks.
>>>>>> Worst the following sequence can transform an exclusive usage into a shared
>>>>>>
>>>>> There is already an inconsistency in between these; as with above any
>>>>> system that uses both request() and request_specific() will be suffering
>>>>> from intermittent failures due to probe ordering.
>>>>>
>>>>>> one:
>>>>>>     -hwspin_lock_request() -> returns Id#0 (exclusive)
>>>>>>     -hwspin_lock_request() -> returns Id#1 (exclusive)
>>>>>>     -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
>>>>>> Honestly I am not sure that this is a real issue, but it's better to have it
>>>>>> in mind before we take ay decision
>>>> Wouldn't it be actually simpler to just introduce a new specific API
>>>> variant for this, similar to the reset core for example (it uses a
>>>> separate exclusive API), without having to modify the bindings at all.
>>>> It is just a case of your driver using the right API, and the core can
>>>> be modified to use the additional tag semantics based on the API. It
>>>> should avoid any confusion with say using a different second cell value
>>>> for the same lock in two different nodes.
>>>>
>>> But this implies that there is an actual need to hold these locks
>>> exclusively. Given that they are (except for the raw case) all wrapped
>>> by Linux locking primitives there shouldn't be a problem sharing a lock
>>> (except possibly for the raw case).
>> Yes agreed, the HWLOCK_RAW and HWLOCK_IN_ATOMIC cases are unprotected. I
>> am still trying to understand better the usecase to see if the same lock
>> is being multiplexed for different protection contexts, or if all of
>> them are protecting the same context.
> 
> 
> Here are two different examples that explain the need for changes.
> In both cases the Linux clients are talking to a single entity on the
> remote-side.
> 
> Example 1:
>      exti: interrupt-controller@5000d000 {
>          compatible = "st,stm32mp1-exti", "syscon";
>          interrupt-controller;
>          #interrupt-cells = <2>;
>          reg = <0x5000d000 0x400>;
>          hwlocks = <&hsem 1>;
>      };
> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
> With the current hwspinlock implementation, only the first driver succeeds
> in requesting (hwspin_lock_request_specific) the hwlock. The second request
> fails.
> Here, we really need to share the hwlock between the two drivers.
> Note: hardware spinlock support for regmap was 'recently' introduced in 4.15
> see https://lore.kernel.org/patchwork/patch/845941/
> 
> 
> 
> Example 2:
> Here it is more a question of optimization : we want to save the number of
> hwlocks used to protect resources, using an unique hwlock to protect all
> pinctrl resources:
>          pinctrl: pin-controller@50002000 {
>              compatible = "st,stm32mp157-pinctrl";
>              ranges = <0 0x50002000 0xa400>;
>              hwlocks = <&hsem 0 1>;
> 
>          pinctrl_z: pin-controller-z@54004000 {
>              compatible = "st,stm32mp157-z-pinctrl";
>              ranges = <0 0x54004000 0x400>;
>              pins-are-numbered;
>              hwlocks = <&hsem 0 1>;

Thanks for the examples.

> 
>>
>>> I agree that we shouldn't specify this property in DT - if anything it
>>> should be a variant of the API.
> 
> 
> If we decide to add a 'shared' API, then, what about the generic regmap 
> driver?
> 
> In the context of above example1, this would require to update the 
> regmap driver.
> 
> But would this be acceptable for any driver using syscon/regmap?
> 
> 
> I think it is better to keep the existing API (modifying it so it always 
> allows
> 
> hwlocks sharing, so no need for bindings update) than adding another API.

For your usecases, you would definitely need the syscon/regmap behavior
to be shared right. Whether we introduce a 'shared' API or an
'exclusive' API and change the current API behavior to shared, it is
definitely a case-by-case usage scenario for the existing drivers and
usage right. The main contention point is what to do with the
unprotected usecases like Bjorn originally pointed out.

regards
Suman

> 
> 
> 
>>>
>>>> If you are sharing a hwlock on the Linux side, surely your driver should
>>>> be aware that it is a shared lock. The tag can be set during the first
>>>> request API, and you look through both tags when giving out a handle.
>>>>
>>> Why would the driver need to know about it?
>> Just the semantics if we were to support single user vs multiple users
>> on Linux-side to even get a handle. Your point is that this may be moot
>> since we have protection anyway other than the raw cases. But we need to
>> be able to have the same API work across all cases.
>>
>> So far, it had mostly been that there would be one user on Linux
>> competing with other equivalent peer entities on different processors.
>> It is not common to have multiple users since these protection schemes
>> are usually needed only at the lowest levels of a stack, so the
>> exclusive handle stuff had been sufficient.
>>
>>>> Obviously, the hwspin_lock_request() API usage semantics always had the
>>>> implied additional need for communicating the lock id to the other peer
>>>> entity, so a realistic usage is most always the specific API variant. I
>>>> doubt this API would be of much use for the shared driver usage. This
>>>> also implies that the client user does not care about specifying a lock
>>>> in DT.
>>>>
>>> Afaict if the lock are shared then there shouldn't be a problem with
>>> some clients using the request API and others request_specific(). As any
>>> collisions would simply mean that there are more contention on the lock.
>>>
>>> With the current exclusive model that is not possible and the success of
>>> the request_specific will depend on probe order.
>>>
>>> But perhaps it should be explicitly prohibited to use both APIs on the
>>> same hwspinlock instance?
>> Yeah, they are meant to be complimentary usage, though I doubt we will
>> ever have any realistic users for the generic API if we haven't had a
>> usage so far. I had posted a concept of reserved locks long back [1] to
>> keep away certain locks from the generic requestor, but dropped it since
>> we did not have an actual use-case needing it.
>>
>> regards
>> Suman
>>
>> [1] https://lwn.net/Articles/611944/
Fabien DESSENNE Aug. 8, 2019, 12:52 p.m. UTC | #10
On 07/08/2019 6:19 PM, Suman Anna wrote:
> Hi Fabien,
>
> On 8/7/19 3:39 AM, Fabien DESSENNE wrote:
>> Hi
>>
>> On 06/08/2019 11:30 PM, Suman Anna wrote:
>>> On 8/6/19 1:21 PM, Bjorn Andersson wrote:
>>>> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
>>>>
>>>>> Hi Fabien,
>>>>>
>>>>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
>>>>>> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
>>>>>>
>>>>>>> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
>>>>>>>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
>>>> [..]
>>>>>>> B/ This would introduce some inconsistency between the two 'request' API
>>>>>>> which are hwspin_lock_request() and hwspin_lock_request_specific().
>>>>>>> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
>>>>>>> usage. On the other side, request_specific() would request shared locks.
>>>>>>> Worst the following sequence can transform an exclusive usage into a shared
>>>>>>>
>>>>>> There is already an inconsistency in between these; as with above any
>>>>>> system that uses both request() and request_specific() will be suffering
>>>>>> from intermittent failures due to probe ordering.
>>>>>>
>>>>>>> one:
>>>>>>>      -hwspin_lock_request() -> returns Id#0 (exclusive)
>>>>>>>      -hwspin_lock_request() -> returns Id#1 (exclusive)
>>>>>>>      -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
>>>>>>> Honestly I am not sure that this is a real issue, but it's better to have it
>>>>>>> in mind before we take ay decision
>>>>> Wouldn't it be actually simpler to just introduce a new specific API
>>>>> variant for this, similar to the reset core for example (it uses a
>>>>> separate exclusive API), without having to modify the bindings at all.
>>>>> It is just a case of your driver using the right API, and the core can
>>>>> be modified to use the additional tag semantics based on the API. It
>>>>> should avoid any confusion with say using a different second cell value
>>>>> for the same lock in two different nodes.
>>>>>
>>>> But this implies that there is an actual need to hold these locks
>>>> exclusively. Given that they are (except for the raw case) all wrapped
>>>> by Linux locking primitives there shouldn't be a problem sharing a lock
>>>> (except possibly for the raw case).
>>> Yes agreed, the HWLOCK_RAW and HWLOCK_IN_ATOMIC cases are unprotected. I
>>> am still trying to understand better the usecase to see if the same lock
>>> is being multiplexed for different protection contexts, or if all of
>>> them are protecting the same context.
>>
>> Here are two different examples that explain the need for changes.
>> In both cases the Linux clients are talking to a single entity on the
>> remote-side.
>>
>> Example 1:
>>       exti: interrupt-controller@5000d000 {
>>           compatible = "st,stm32mp1-exti", "syscon";
>>           interrupt-controller;
>>           #interrupt-cells = <2>;
>>           reg = <0x5000d000 0x400>;
>>           hwlocks = <&hsem 1>;
>>       };
>> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
>> With the current hwspinlock implementation, only the first driver succeeds
>> in requesting (hwspin_lock_request_specific) the hwlock. The second request
>> fails.
>> Here, we really need to share the hwlock between the two drivers.
>> Note: hardware spinlock support for regmap was 'recently' introduced in 4.15
>> see https://lore.kernel.org/patchwork/patch/845941/
>>
>>
>>
>> Example 2:
>> Here it is more a question of optimization : we want to save the number of
>> hwlocks used to protect resources, using an unique hwlock to protect all
>> pinctrl resources:
>>           pinctrl: pin-controller@50002000 {
>>               compatible = "st,stm32mp157-pinctrl";
>>               ranges = <0 0x50002000 0xa400>;
>>               hwlocks = <&hsem 0 1>;
>>
>>           pinctrl_z: pin-controller-z@54004000 {
>>               compatible = "st,stm32mp157-z-pinctrl";
>>               ranges = <0 0x54004000 0x400>;
>>               pins-are-numbered;
>>               hwlocks = <&hsem 0 1>;
> Thanks for the examples.
>
>>>> I agree that we shouldn't specify this property in DT - if anything it
>>>> should be a variant of the API.
>>
>> If we decide to add a 'shared' API, then, what about the generic regmap
>> driver?
>>
>> In the context of above example1, this would require to update the
>> regmap driver.
>>
>> But would this be acceptable for any driver using syscon/regmap?
>>
>>
>> I think it is better to keep the existing API (modifying it so it always
>> allows
>>
>> hwlocks sharing, so no need for bindings update) than adding another API.
> For your usecases, you would definitely need the syscon/regmap behavior
> to be shared right. Whether we introduce a 'shared' API or an
> 'exclusive' API and change the current API behavior to shared, it is
> definitely a case-by-case usage scenario for the existing drivers and
> usage right. The main contention point is what to do with the
> unprotected usecases like Bjorn originally pointed out.

OK, I see : the hwspinlock framework does not offer any lock protection 
with the RAW/IN_ATOMIC modes.
This is an issue if several different 'local' drivers try to get a 
shared lock in the same time.
And this is a personal problem since I need to use shared locks in 
...atomic mode.

I have tried to see how it is possible to put a constraint on the 
callers, just like this is documented for the RAW mode which is:
    "Caution: If the mode is HWLOCK_RAW, that means user must protect 
the routine
     of getting hardware lock with mutex or spinlock.."
I do not think that it is acceptable to ask several drivers to share a 
common mutex/spinlock for shared locks.
But I think about another option: the driver implementing the trylock 
ops may offer such protection. This is the case if the driver returns 
"busy" if the lock is already taken, not only by the remote processor, 
but also by the local host.

So what do you think about adding such a documentation note :
"Caution : the HWLOCK_RAW / HWLOCK_IN_ATOMIC modes shall not be used 
with shared locks unless the hwspinlock driver supports local lock 
protection"

Optionally, we may add a "local_lock_protection" flag in the 
hwspinlock_device struct, set by the driver before it calls 
hwspin_lock_register().
This flag can then be checked by hwspinlock core to allow/deny use of 
shared locks in the raw/atomic modes.

Let me know what you think about it.

BR

Fabien

>
> regards
> Suman
>
>>
>>
>>>>> If you are sharing a hwlock on the Linux side, surely your driver should
>>>>> be aware that it is a shared lock. The tag can be set during the first
>>>>> request API, and you look through both tags when giving out a handle.
>>>>>
>>>> Why would the driver need to know about it?
>>> Just the semantics if we were to support single user vs multiple users
>>> on Linux-side to even get a handle. Your point is that this may be moot
>>> since we have protection anyway other than the raw cases. But we need to
>>> be able to have the same API work across all cases.
>>>
>>> So far, it had mostly been that there would be one user on Linux
>>> competing with other equivalent peer entities on different processors.
>>> It is not common to have multiple users since these protection schemes
>>> are usually needed only at the lowest levels of a stack, so the
>>> exclusive handle stuff had been sufficient.
>>>
>>>>> Obviously, the hwspin_lock_request() API usage semantics always had the
>>>>> implied additional need for communicating the lock id to the other peer
>>>>> entity, so a realistic usage is most always the specific API variant. I
>>>>> doubt this API would be of much use for the shared driver usage. This
>>>>> also implies that the client user does not care about specifying a lock
>>>>> in DT.
>>>>>
>>>> Afaict if the lock are shared then there shouldn't be a problem with
>>>> some clients using the request API and others request_specific(). As any
>>>> collisions would simply mean that there are more contention on the lock.
>>>>
>>>> With the current exclusive model that is not possible and the success of
>>>> the request_specific will depend on probe order.
>>>>
>>>> But perhaps it should be explicitly prohibited to use both APIs on the
>>>> same hwspinlock instance?
>>> Yeah, they are meant to be complimentary usage, though I doubt we will
>>> ever have any realistic users for the generic API if we haven't had a
>>> usage so far. I had posted a concept of reserved locks long back [1] to
>>> keep away certain locks from the generic requestor, but dropped it since
>>> we did not have an actual use-case needing it.
>>>
>>> regards
>>> Suman
>>>
>>> [1] https://lwn.net/Articles/611944/
Bjorn Andersson Aug. 8, 2019, 3:37 p.m. UTC | #11
On Thu 08 Aug 05:52 PDT 2019, Fabien DESSENNE wrote:

> 
> On 07/08/2019 6:19 PM, Suman Anna wrote:
> > Hi Fabien,
> >
> > On 8/7/19 3:39 AM, Fabien DESSENNE wrote:
> >> Hi
> >>
> >> On 06/08/2019 11:30 PM, Suman Anna wrote:
> >>> On 8/6/19 1:21 PM, Bjorn Andersson wrote:
> >>>> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
> >>>>
> >>>>> Hi Fabien,
> >>>>>
> >>>>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
> >>>> I agree that we shouldn't specify this property in DT - if anything it
> >>>> should be a variant of the API.
> >>
> >> If we decide to add a 'shared' API, then, what about the generic regmap
> >> driver?
> >>
> >> In the context of above example1, this would require to update the
> >> regmap driver.
> >>
> >> But would this be acceptable for any driver using syscon/regmap?
> >>
> >>
> >> I think it is better to keep the existing API (modifying it so it always
> >> allows
> >>
> >> hwlocks sharing, so no need for bindings update) than adding another API.
> > For your usecases, you would definitely need the syscon/regmap behavior
> > to be shared right. Whether we introduce a 'shared' API or an
> > 'exclusive' API and change the current API behavior to shared, it is
> > definitely a case-by-case usage scenario for the existing drivers and
> > usage right. The main contention point is what to do with the
> > unprotected usecases like Bjorn originally pointed out.
> 
> OK, I see : the hwspinlock framework does not offer any lock protection 
> with the RAW/IN_ATOMIC modes.
> This is an issue if several different 'local' drivers try to get a 
> shared lock in the same time.
> And this is a personal problem since I need to use shared locks in 
> ...atomic mode.
> 

Why can't you use HWLOCK_IRQSTATE in this mode?

> I have tried to see how it is possible to put a constraint on the 
> callers, just like this is documented for the RAW mode which is:
>     "Caution: If the mode is HWLOCK_RAW, that means user must protect 
> the routine
>      of getting hardware lock with mutex or spinlock.."
> I do not think that it is acceptable to ask several drivers to share a 
> common mutex/spinlock for shared locks.

No it's not.

> But I think about another option: the driver implementing the trylock 
> ops may offer such protection. This is the case if the driver returns 
> "busy" if the lock is already taken, not only by the remote processor, 
> but also by the local host.
> 

I think it's typical for hwspinlock hardware to not be able to
distinguish between different clients within Linux, so we would need to
wrap the usage in some construct that ensures mutual exclusion in Linux
- like a spinlock...

> So what do you think about adding such a documentation note :
> "Caution : the HWLOCK_RAW / HWLOCK_IN_ATOMIC modes shall not be used 
> with shared locks unless the hwspinlock driver supports local lock 
> protection"
> 

But having local lock protection in the hwspinlock driver would defeat
the purpose of HWLOCK_RAW.

Also this kind of warning will at best be consumed by the client driver
authors, it will not be read by the dts authors.

Regards,
Bjorn

> Optionally, we may add a "local_lock_protection" flag in the 
> hwspinlock_device struct, set by the driver before it calls 
> hwspin_lock_register().
> This flag can then be checked by hwspinlock core to allow/deny use of 
> shared locks in the raw/atomic modes.
> 
> Let me know what you think about it.
> 
> BR
> 
> Fabien
> 
> >
> > regards
> > Suman
> >
> >>
> >>
> >>>>> If you are sharing a hwlock on the Linux side, surely your driver should
> >>>>> be aware that it is a shared lock. The tag can be set during the first
> >>>>> request API, and you look through both tags when giving out a handle.
> >>>>>
> >>>> Why would the driver need to know about it?
> >>> Just the semantics if we were to support single user vs multiple users
> >>> on Linux-side to even get a handle. Your point is that this may be moot
> >>> since we have protection anyway other than the raw cases. But we need to
> >>> be able to have the same API work across all cases.
> >>>
> >>> So far, it had mostly been that there would be one user on Linux
> >>> competing with other equivalent peer entities on different processors.
> >>> It is not common to have multiple users since these protection schemes
> >>> are usually needed only at the lowest levels of a stack, so the
> >>> exclusive handle stuff had been sufficient.
> >>>
> >>>>> Obviously, the hwspin_lock_request() API usage semantics always had the
> >>>>> implied additional need for communicating the lock id to the other peer
> >>>>> entity, so a realistic usage is most always the specific API variant. I
> >>>>> doubt this API would be of much use for the shared driver usage. This
> >>>>> also implies that the client user does not care about specifying a lock
> >>>>> in DT.
> >>>>>
> >>>> Afaict if the lock are shared then there shouldn't be a problem with
> >>>> some clients using the request API and others request_specific(). As any
> >>>> collisions would simply mean that there are more contention on the lock.
> >>>>
> >>>> With the current exclusive model that is not possible and the success of
> >>>> the request_specific will depend on probe order.
> >>>>
> >>>> But perhaps it should be explicitly prohibited to use both APIs on the
> >>>> same hwspinlock instance?
> >>> Yeah, they are meant to be complimentary usage, though I doubt we will
> >>> ever have any realistic users for the generic API if we haven't had a
> >>> usage so far. I had posted a concept of reserved locks long back [1] to
> >>> keep away certain locks from the generic requestor, but dropped it since
> >>> we did not have an actual use-case needing it.
> >>>
> >>> regards
> >>> Suman
> >>>
> >>> [1] https://lwn.net/Articles/611944/
Fabien DESSENNE Aug. 26, 2019, 1:30 p.m. UTC | #12
Hi Bjorn,


On 08/08/2019 5:37 PM, Bjorn Andersson wrote:
> On Thu 08 Aug 05:52 PDT 2019, Fabien DESSENNE wrote:
>
>> On 07/08/2019 6:19 PM, Suman Anna wrote:
>>> Hi Fabien,
>>>
>>> On 8/7/19 3:39 AM, Fabien DESSENNE wrote:
>>>> Hi
>>>>
>>>> On 06/08/2019 11:30 PM, Suman Anna wrote:
>>>>> On 8/6/19 1:21 PM, Bjorn Andersson wrote:
>>>>>> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
>>>>>>
>>>>>>> Hi Fabien,
>>>>>>>
>>>>>>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
>>>>>> I agree that we shouldn't specify this property in DT - if anything it
>>>>>> should be a variant of the API.
>>>> If we decide to add a 'shared' API, then, what about the generic regmap
>>>> driver?
>>>>
>>>> In the context of above example1, this would require to update the
>>>> regmap driver.
>>>>
>>>> But would this be acceptable for any driver using syscon/regmap?
>>>>
>>>>
>>>> I think it is better to keep the existing API (modifying it so it always
>>>> allows
>>>>
>>>> hwlocks sharing, so no need for bindings update) than adding another API.
>>> For your usecases, you would definitely need the syscon/regmap behavior
>>> to be shared right. Whether we introduce a 'shared' API or an
>>> 'exclusive' API and change the current API behavior to shared, it is
>>> definitely a case-by-case usage scenario for the existing drivers and
>>> usage right. The main contention point is what to do with the
>>> unprotected usecases like Bjorn originally pointed out.
>> OK, I see : the hwspinlock framework does not offer any lock protection
>> with the RAW/IN_ATOMIC modes.
>> This is an issue if several different 'local' drivers try to get a
>> shared lock in the same time.
>> And this is a personal problem since I need to use shared locks in
>> ...atomic mode.
>>
> Why can't you use HWLOCK_IRQSTATE in this mode?
>
>> I have tried to see how it is possible to put a constraint on the
>> callers, just like this is documented for the RAW mode which is:
>>      "Caution: If the mode is HWLOCK_RAW, that means user must protect
>> the routine
>>       of getting hardware lock with mutex or spinlock.."
>> I do not think that it is acceptable to ask several drivers to share a
>> common mutex/spinlock for shared locks.
> No it's not.
>
>> But I think about another option: the driver implementing the trylock
>> ops may offer such protection. This is the case if the driver returns
>> "busy" if the lock is already taken, not only by the remote processor,
>> but also by the local host.
>>
> I think it's typical for hwspinlock hardware to not be able to
> distinguish between different clients within Linux, so we would need to


Agree with that, let's forget this idea.


> wrap the usage in some construct that ensures mutual exclusion in Linux
> - like a spinlock...
>
>> So what do you think about adding such a documentation note :
>> "Caution : the HWLOCK_RAW / HWLOCK_IN_ATOMIC modes shall not be used
>> with shared locks unless the hwspinlock driver supports local lock
>> protection"
>>
> But having local lock protection in the hwspinlock driver would defeat
> the purpose of HWLOCK_RAW.


My understanding is that the purpose of the RAW mode is to allow the 
user to do some time-consuming or sleepable operations under the 
hardware spinlock protection.

This is probably the reason why the RAW mode does not uses any spinlock 
is used in RAW mode.

But I do not think that this is a requirement to not use any local 
protection.

So, in this mode, instead of using a spinlock, what about calling the 
atomic bitop test_and_set_bit()  ?

This would ensure safe concurrency between the hwspinlock linux users, 
and will respect the purpose of the RAW mode.

Let me know if this is acceptable.


BR

Fabien


>
> Also this kind of warning will at best be consumed by the client driver
> authors, it will not be read by the dts authors.
>
> Regards,
> Bjorn
>
>> Optionally, we may add a "local_lock_protection" flag in the
>> hwspinlock_device struct, set by the driver before it calls
>> hwspin_lock_register().
>> This flag can then be checked by hwspinlock core to allow/deny use of
>> shared locks in the raw/atomic modes.
>>
>> Let me know what you think about it.
>>
>> BR
>>
>> Fabien
>>
>>> regards
>>> Suman
>>>
>>>>
>>>>>>> If you are sharing a hwlock on the Linux side, surely your driver should
>>>>>>> be aware that it is a shared lock. The tag can be set during the first
>>>>>>> request API, and you look through both tags when giving out a handle.
>>>>>>>
>>>>>> Why would the driver need to know about it?
>>>>> Just the semantics if we were to support single user vs multiple users
>>>>> on Linux-side to even get a handle. Your point is that this may be moot
>>>>> since we have protection anyway other than the raw cases. But we need to
>>>>> be able to have the same API work across all cases.
>>>>>
>>>>> So far, it had mostly been that there would be one user on Linux
>>>>> competing with other equivalent peer entities on different processors.
>>>>> It is not common to have multiple users since these protection schemes
>>>>> are usually needed only at the lowest levels of a stack, so the
>>>>> exclusive handle stuff had been sufficient.
>>>>>
>>>>>>> Obviously, the hwspin_lock_request() API usage semantics always had the
>>>>>>> implied additional need for communicating the lock id to the other peer
>>>>>>> entity, so a realistic usage is most always the specific API variant. I
>>>>>>> doubt this API would be of much use for the shared driver usage. This
>>>>>>> also implies that the client user does not care about specifying a lock
>>>>>>> in DT.
>>>>>>>
>>>>>> Afaict if the lock are shared then there shouldn't be a problem with
>>>>>> some clients using the request API and others request_specific(). As any
>>>>>> collisions would simply mean that there are more contention on the lock.
>>>>>>
>>>>>> With the current exclusive model that is not possible and the success of
>>>>>> the request_specific will depend on probe order.
>>>>>>
>>>>>> But perhaps it should be explicitly prohibited to use both APIs on the
>>>>>> same hwspinlock instance?
>>>>> Yeah, they are meant to be complimentary usage, though I doubt we will
>>>>> ever have any realistic users for the generic API if we haven't had a
>>>>> usage so far. I had posted a concept of reserved locks long back [1] to
>>>>> keep away certain locks from the generic requestor, but dropped it since
>>>>> we did not have an actual use-case needing it.
>>>>>
>>>>> regards
>>>>> Suman
>>>>>
>>>>> [1] https://lwn.net/Articles/611944/