From: Thierry Reding <thierry.reding@gmail.com>
To: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Anand Moon <linux.amoon@gmail.com>,
Guenter Roeck <linux@roeck-us.net>,
Javier Martinez Canillas <javier@osg.samsung.com>,
linux-pwm@vger.kernel.org,
Linux Kernel <linux-kernel@vger.kernel.org>,
"linux-samsung-soc@vger.kernel.org"
<linux-samsung-soc@vger.kernel.org>
Subject: Re: [PATCHv2] pwm: avoid holding mutex in interrupt context
Date: Wed, 20 Jan 2016 15:32:20 +0100 [thread overview]
Message-ID: <20160120143220.GA31427@ulmo> (raw)
In-Reply-To: <569EC6F6.1020505@samsung.com>
[-- Attachment #1: Type: text/plain, Size: 5131 bytes --]
On Wed, Jan 20, 2016 at 08:29:58AM +0900, Krzysztof Kozlowski wrote:
> On 20.01.2016 00:04, Anand Moon wrote:
> > Hi Krzysztof,
> >
> > On 18 January 2016 at 09:58, Krzysztof Kozlowski
> >>> Already within function pwm_samsung_set_invert is protected by
> >>> spin_lock_irqsave(&samsung_pwm_lock, flags);
> >>>
> >>> So no need to introduce another lock to control pwm_samsung_set_polarity.
> >>>
> >>> Best Regards.
> >>> -Anand Moon
> >>
> >> I don't have any clue what is your point here. I don't get what
> >> pwm_samsung_set_polarity has to do with main pwm core...
> >>
> >> Sorry, you need to be more specific.
> >>
> >> Best regards,
> >> Krzysztof
> >>
> >>
> >
> > Below is the mapping of calls from pwm driver.
> > I have tried to map the functionality and I am trying to understand
> > the flow of the driver.
> >
> > Also looking in document
> >
> > https://www.kernel.org/doc/Documentation/pwm.txt
> >
> > pwm-samsung driver controls the LEDS, fans...etc
> >
> > Form the dts modes pwmleds
> >
> > pwmleds {
> > compatible = "pwm-leds";
> >
> > blueled {
> > label = "blue:heartbeat";
> > pwms = <&pwm 2 2000000 0>;
> > pwm-names = "pwm2";
> > max_brightness = <255>;
> > linux,default-trigger = "heartbeat";
> > };
> > };
> >
> > Following is the map out from the device tree.
> >
> > pwms = <&pwm 2 2000000 0>;
> >
> > &pwm -> pwm: pwm@12dd0000 --->samsung,exynos4210-pwm
> > 2 -> period
> > 2000000 -> duty_cycle
> > 0 -> polarity
>
> I do not see any relations between DTS and the problem.
>
> >
> > And here is the mapping of the call of function
> > Note: This function call are as per my understanding of the flow in
> > the driver. I might be wrong.
> >
> > pwm_samsung_set_polarity(struct pwm_chip *chip, struct pwm_device
> > *pwm, enum pwm_polarity polarity)
> > \
> > pwm_samsung_set_invert(our_chip, pwm->hwpwm, invert);
> > \
> > pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
>
> No, pwm_samsung_set_invert does not call pwm_set_polarity(). This would
> result in a circular call - back to pwm_samsung_set_polarity().
>
> > \
> > pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
> > \
> > pwm_enable(struct pwm_device *pwm) or pwm_disable(struct pwm_device *pwm)
> >
> > pwm_enable or pwm_disable will be triggered on change in pwm->flags by
> > the pwm core.
> > before pwm_set_polarity is called form the Samsung driver it hold with
> > following locks
> >
> > Here is the locking
> >
> > pwm_samsung_set_polarity(struct pwm_chip *chip, struct pwm_device
> > *pwm, enum pwm_polarity polarity)
> > \
> > pwm_samsung_set_invert(struct samsung_pwm_chip *chip, unsigned int
> > channel, bool invert)
> > \
> > spin_lock_irqsave(&samsung_pwm_lock, flags);
> > \
> > pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
> > \
> > mutex_lock(&pwm->lock)
> >
> > pwm_enable(struct pwm_device *pwm) or pwm_disable(struct
> > pwm_device *pwm)
> > \
> > mutex_lock(&pwm->lock);
> >
> > Problem I see that we are holding the lock in interrupt context.
> > I don't know how the this triggers this bug.
> >
> > BUG: sleeping function called from invalid context at kernel/locking/mutex.c:97
>
> So leave it. If your flow of calls was correct, you would spot the
> problem. But actually it does not matter - I think the flow is not correct.
The reason for the BUG that you're seeing is that the leds-pwm driver
differentiates between PWMs that can sleep and those that can't. This
used to be limited to some PWMs that were attached to a slow bus like
I2C, or that called functions which might sleep (like clk_prepare()).
With commit d1cd21427747 ("pwm: Set enable state properly on failed
call to enable"), effectively all PWM drivers may sleep. The lock
introduced in that commit must also be a mutex because it protects
sections which may sleep themselves (->enable() and ->set_polarity())
so turning it into a spinlock won't work for the general case.
Given that this is currently broken and we're quite close to -rc1 I
suggest the following fix for now:
--- >8 ---
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index d24ca5f281b4..7831bc6b51dd 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -889,7 +889,7 @@ EXPORT_SYMBOL_GPL(devm_pwm_put);
*/
bool pwm_can_sleep(struct pwm_device *pwm)
{
- return pwm->chip->can_sleep;
+ return true;
}
EXPORT_SYMBOL_GPL(pwm_can_sleep);
--- >8 ---
For v4.6 I can remove all usage of the ->can_sleep and pwm_can_sleep()
because they're effectively useless now.
Does that sound reasonable to everyone?
Anand, the above should fix the issue for you. Can you give it a try
and report if it doesn't?
Thanks,
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2016-01-20 14:32 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-17 21:01 [PATCHv2] pwm: avoid holding mutex in interrupt context Anand Moon
2016-01-17 23:59 ` Krzysztof Kozlowski
2016-01-18 3:09 ` Anand Moon
2016-01-18 4:23 ` Anand Moon
2016-01-18 4:28 ` Krzysztof Kozlowski
2016-01-19 15:04 ` Anand Moon
2016-01-19 23:29 ` Krzysztof Kozlowski
2016-01-20 2:43 ` Anand Moon
2016-01-20 14:32 ` Thierry Reding [this message]
2016-01-20 16:34 ` Anand Moon
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=20160120143220.GA31427@ulmo \
--to=thierry.reding@gmail.com \
--cc=javier@osg.samsung.com \
--cc=k.kozlowski@samsung.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=linux.amoon@gmail.com \
--cc=linux@roeck-us.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox