* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Takashi Iwai @ 2020-06-03 12:47 UTC (permalink / raw)
To: Macpaul Lin
Cc: alsa-devel, Szabolcs Szőke, Mediatek WSD Upstream,
Greg Kroah-Hartman, linux-usb, Takashi Iwai, stable, linux-kernel,
Hui Wang, Alexander Tsoy, linux-mediatek, Matthias Brugger,
Johan Hovold, Jaroslav Kysela, Macpaul Lin, linux-arm-kernel
In-Reply-To: <1591187964.23525.61.camel@mtkswgap22>
On Wed, 03 Jun 2020 14:39:24 +0200,
Macpaul Lin wrote:
>
> On Wed, 2020-06-03 at 10:45 +0200, Takashi Iwai wrote:
> > On Wed, 03 Jun 2020 08:54:51 +0200,
> > Takashi Iwai wrote:
> > >
> > > On Wed, 03 Jun 2020 08:28:09 +0200,
> > > Takashi Iwai wrote:
> > > >
> > > > And, the most suspicious case is the last one,
> > > > chip->num_suspended-intf. It means that the device has multiple
> > > > USB interfaces and they went to suspend, while the resume isn't
> > > > performed for the all suspended interfaces in return.
> > >
> > > If this is the cause, a patch like below might help.
> > > It gets/puts the all assigned interfaced instead of only the primary
> > > one.
> >
> > ... and considering of the problem again, rather the patch below might
> > be the right answer. Now the driver tries to remember at which state
> > it entered into the system-suspend. Upon resume, in return, when the
> > state reaches back to that point, set the card state to D0.
> >
> > The previous patch can be applied on the top, too, and it might be
> > worth to apply both.
> >
> > Let me know if any of those actually helps.
> >
> >
> > Takashi
>
> Thanks for your response so quickly.
> I've just test this patch since it looks like enough for the issue.
Good to hear!
> This patch worked since the flag system_suspend will be set at the same
> time when power state has been changed. I have 2 interface with the head
> set. But actually the problem happened when primary one is suspended.
Currently the autosuspend is set only to the primary interface; IOW,
the other interfaces will never get autosuspend, and the another
suspend-all-intf patch should improve that situation. But it won't
fix your actual bug, obviously :)
> So I didn't test the earlier patch "suspend all interface instead of
> only the primary one."
Could you try it one on top of the last patch? At least I'd like to
see whether it causes any regression.
> Will you resend this patch officially later? I think this solution is
> required to send to stable, too. It's better to have it for other stable
> kernel versions include android's.
Yes, that's a general bug and worth to be merged quickly.
I'm going to submit a proper patch soon later.
thanks,
Takashi
>
> > ---
> > diff --git a/sound/usb/card.c b/sound/usb/card.c
> > --- a/sound/usb/card.c
> > +++ b/sound/usb/card.c
> > @@ -843,9 +843,6 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
> > if (chip == (void *)-1L)
> > return 0;
> >
> > - chip->autosuspended = !!PMSG_IS_AUTO(message);
> > - if (!chip->autosuspended)
> > - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
> > if (!chip->num_suspended_intf++) {
> > list_for_each_entry(as, &chip->pcm_list, list) {
> > snd_usb_pcm_suspend(as);
> > @@ -858,6 +855,11 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
> > snd_usb_mixer_suspend(mixer);
> > }
> >
> > + if (!PMSG_IS_AUTO(message) && !chip->system_suspend) {
> > + snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
> > + chip->system_suspend = chip->num_suspended_intf;
> > + }
> > +
> > return 0;
> > }
> >
> > @@ -871,10 +873,10 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
> >
> > if (chip == (void *)-1L)
> > return 0;
> > - if (--chip->num_suspended_intf)
> > - return 0;
> >
> > atomic_inc(&chip->active); /* avoid autopm */
> > + if (chip->num_suspended_intf > 1)
> > + goto out;
> >
> > list_for_each_entry(as, &chip->pcm_list, list) {
> > err = snd_usb_pcm_resume(as);
> > @@ -896,9 +898,12 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
> > snd_usbmidi_resume(p);
> > }
> >
> > - if (!chip->autosuspended)
> > + out:
> > + if (chip->num_suspended_intf == chip->system_suspend) {
> > snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
> > - chip->autosuspended = 0;
> > + chip->system_suspend = 0;
> > + }
> > + chip->num_suspended_intf--;
> >
> > err_out:
> > atomic_dec(&chip->active); /* allow autopm after this point */
> > diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
> > index 1c892c7f14d7..e0ebfb25fbd5 100644
> > --- a/sound/usb/usbaudio.h
> > +++ b/sound/usb/usbaudio.h
> > @@ -26,7 +26,7 @@ struct snd_usb_audio {
> > struct usb_interface *pm_intf;
> > u32 usb_id;
> > struct mutex mutex;
> > - unsigned int autosuspended:1;
> > + unsigned int system_suspend;
> > atomic_t active;
> > atomic_t shutdown;
> > atomic_t usage_count;
> >
> > _______________________________________________
>
> Thank you very much!
>
> Best regards,
> Macpaul Lin
>
>
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] usb: host: xhci-mtk: avoid runtime suspend when removing hcd
From: Mathias Nyman @ 2020-06-03 11:47 UTC (permalink / raw)
To: Macpaul Lin, Chunfeng Yun, Mathias Nyman, Greg Kroah-Hartman,
Matthias Brugger
Cc: Mediatek WSD Upstream, linux-usb, linux-kernel, linux-mediatek,
Macpaul Lin, linux-arm-kernel
In-Reply-To: <1590726569-28248-1-git-send-email-macpaul.lin@mediatek.com>
On 29.5.2020 7.29, Macpaul Lin wrote:
> When runtime suspend was enabled, runtime suspend might happened
> when xhci is removing hcd. This might cause kernel panic when hcd
> has been freed but runtime pm suspend related handle need to
> reference it.
>
> Change-Id: I70a5dc8006207caeecbac6955ce8e5345dcc70e6
> Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
> ---
> drivers/usb/host/xhci-mtk.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
> index bfbdb3c..641d24e 100644
> --- a/drivers/usb/host/xhci-mtk.c
> +++ b/drivers/usb/host/xhci-mtk.c
> @@ -587,6 +587,9 @@ static int xhci_mtk_remove(struct platform_device *dev)
> struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> struct usb_hcd *shared_hcd = xhci->shared_hcd;
>
> + pm_runtime_put_sync(&dev->dev);
Might runtime suspend here.
It's a lot better than before, no panic as hcd isn't released, but a bit unnecessary.
how about this sequence instead:
pm_runtime_disable()
pm_runtime_put_noidle()
> + pm_runtime_disable(&dev->dev);
> +
-Mathias
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: Security Random Number Generator support
From: Marc Zyngier @ 2020-06-03 11:12 UTC (permalink / raw)
To: Neal Liu
Cc: mark.rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Julius Werner, Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Jose.Marinho, Sean Wang, lkml, wsd_upstream, Rob Herring,
linux-mediatek, Linux Crypto Mailing List, Matt Mackall,
Matthias Brugger, Crystal Guo (郭晶), Ard Biesheuvel,
Linux ARM
In-Reply-To: <1591170857.19414.5.camel@mtkswgap22>
On 2020-06-03 08:54, Neal Liu wrote:
> On Wed, 2020-06-03 at 08:40 +0100, Marc Zyngier wrote:
>> On 2020-06-03 08:29, Neal Liu wrote:
[...]
>> > Could you give us a hint how to make this SMC interface more generic in
>> > addition to my approach?
>> > There is no (easy) way to get platform-independent SMC function ID,
>> > which is why we encode it into device tree, and provide a generic
>> > driver. In this way, different devices can be mapped and then get
>> > different function ID internally.
>>
>> The idea is simply to have *one* single ID that caters for all
>> implementations, just like we did for PSCI at the time. This
>> requires ARM to edict a standard, which is what I was referring
>> to above.
>>
>> There is zero benefit in having a platform-dependent ID. It just
>> pointlessly increases complexity, and means we cannot use the RNG
>> before the firmware tables are available (yes, we need it that
>> early).
>>
>> M.
>
> Do you know which ARM expert could edict this standard?
> Or is there any chance that we can make one? And be reviewed by
> maintainers?
Sudeep already mentioned Jose's effort to offer a standard.
Hopefully he will *soon* be able to give us something that can be
implemented everywhere (firmware, kernel, but also hypervisors),
as the need exists across the whole stack.
M.
--
Jazz is not dead. It just smells funny...
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: Security Random Number Generator support
From: Sudeep Holla @ 2020-06-03 9:48 UTC (permalink / raw)
To: Neal Liu
Cc: Linux ARM,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Julius Werner, Herbert Xu, Arnd Bergmann, Marc Zyngier,
Matt Mackall, Sean Wang, lkml, wsd_upstream, Sudeep Holla,
Rob Herring, linux-mediatek, Linux Crypto Mailing List,
Greg Kroah-Hartman, Matthias Brugger,
Crystal Guo (郭晶), Ard Biesheuvel, Jose Marinho
In-Reply-To: <1591170857.19414.5.camel@mtkswgap22>
+ Jose
On Wed, Jun 03, 2020 at 03:54:17PM +0800, Neal Liu wrote:
> On Wed, 2020-06-03 at 08:40 +0100, Marc Zyngier wrote:
[...]
> > The idea is simply to have *one* single ID that caters for all
> > implementations, just like we did for PSCI at the time. This
> > requires ARM to edict a standard, which is what I was referring
> > to above.
> >
> > There is zero benefit in having a platform-dependent ID. It just
> > pointlessly increases complexity, and means we cannot use the RNG
> > before the firmware tables are available (yes, we need it that
> > early).
> >
>
> Do you know which ARM expert could edict this standard?
> Or is there any chance that we can make one? And be reviewed by
> maintainers?
>
Jose Marinho is working on the spec, may be he has more updates on the
timeline.
--
Regards,
Sudeep
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: Security Random Number Generator support
From: Russell King - ARM Linux admin @ 2020-06-03 9:34 UTC (permalink / raw)
To: Marc Zyngier
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Julius Werner, Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Sean Wang, lkml, wsd_upstream, Crystal Guo (郭晶),
Rob Herring, Neal Liu, Linux Crypto Mailing List, Matt Mackall,
Matthias Brugger, linux-mediatek, Ard Biesheuvel, Linux ARM
In-Reply-To: <fcbe37f6f9cbcde24f9c28bc504f1f0e@kernel.org>
On Wed, Jun 03, 2020 at 08:40:58AM +0100, Marc Zyngier wrote:
> On 2020-06-03 08:29, Neal Liu wrote:
> > On Tue, 2020-06-02 at 21:02 +0800, Marc Zyngier wrote:
> > > On 2020-06-02 13:14, Ard Biesheuvel wrote:
> > > > On Tue, 2 Jun 2020 at 10:15, Neal Liu <neal.liu@mediatek.com> wrote:
> > > >>
> > > >> These patch series introduce a security random number generator
> > > >> which provides a generic interface to get hardware rnd from Secure
> > > >> state. The Secure state can be Arm Trusted Firmware(ATF), Trusted
> > > >> Execution Environment(TEE), or even EL2 hypervisor.
> > > >>
> > > >> Patch #1..2 adds sec-rng kernel driver for Trustzone based SoCs.
> > > >> For security awareness SoCs on ARMv8 with TrustZone enabled,
> > > >> peripherals like entropy sources is not accessible from normal world
> > > >> (linux) and rather accessible from secure world (HYP/ATF/TEE) only.
> > > >> This driver aims to provide a generic interface to Arm Trusted
> > > >> Firmware or Hypervisor rng service.
> > > >>
> > > >>
> > > >> changes since v1:
> > > >> - rename mt67xx-rng to mtk-sec-rng since all MediaTek ARMv8 SoCs can
> > > >> reuse
> > > >> this driver.
> > > >> - refine coding style and unnecessary check.
> > > >>
> > > >> changes since v2:
> > > >> - remove unused comments.
> > > >> - remove redundant variable.
> > > >>
> > > >> changes since v3:
> > > >> - add dt-bindings for MediaTek rng with TrustZone enabled.
> > > >> - revise HWRNG SMC call fid.
> > > >>
> > > >> changes since v4:
> > > >> - move bindings to the arm/firmware directory.
> > > >> - revise driver init flow to check more property.
> > > >>
> > > >> changes since v5:
> > > >> - refactor to more generic security rng driver which
> > > >> is not platform specific.
> > > >>
> > > >> *** BLURB HERE ***
> > > >>
> > > >> Neal Liu (2):
> > > >> dt-bindings: rng: add bindings for sec-rng
> > > >> hwrng: add sec-rng driver
> > > >>
> > > >
> > > > There is no reason to model a SMC call as a driver, and represent it
> > > > via a DT node like this.
> > >
> > > +1.
> > >
> > > > It would be much better if this SMC interface is made truly generic,
> > > > and wired into the arch_get_random() interface, which can be used much
> > > > earlier.
> > >
> > > Wasn't there a plan to standardize a SMC call to rule them all?
> > >
> > > M.
> >
> > Could you give us a hint how to make this SMC interface more generic in
> > addition to my approach?
> > There is no (easy) way to get platform-independent SMC function ID,
> > which is why we encode it into device tree, and provide a generic
> > driver. In this way, different devices can be mapped and then get
> > different function ID internally.
>
> The idea is simply to have *one* single ID that caters for all
> implementations, just like we did for PSCI at the time. This
> requires ARM to edict a standard, which is what I was referring
> to above.
This sounds all too familiar.
This kind of thing is something that ARM have seems to shy away from
doing - it's a point I brought up many years ago when the whole
trustzone thing first appeared with its SMC call. Those around the
conference table were not interested - ARM seemed to prefer every
vendor to do off and do their own thing with the SMC interface.
Then OMAP came along with its SMC interfaces, and so did the pain of
not having a standardised way to configure the L2C when Linux was
running in the non-secure world, resulting in stuff like l2c_configure
etc, where each and every implementation has to supply a function to
call its platform specific SMC interfaces to configure a piece of
hardware common across many different platforms.
ARM have seemed reluctant to standardise on stuff like this, so
unless someone pushes hard for it from inside ARM, I doubt it will
ever happen.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC for 0.8m (est. 1762m) line in suburbia: sync at 13.1Mbps down 424kbps up
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH v2] usb: host: xhci-mtk: avoid runtime suspend when removing hcd
From: Chunfeng Yun @ 2020-06-03 8:43 UTC (permalink / raw)
To: Macpaul Lin
Cc: Mathias Nyman, Mediatek WSD Upstream, Greg Kroah-Hartman,
linux-usb, linux-kernel, linux-mediatek, Matthias Brugger,
Macpaul Lin, linux-arm-kernel
In-Reply-To: <1590726778-29065-1-git-send-email-macpaul.lin@mediatek.com>
On Fri, 2020-05-29 at 12:32 +0800, Macpaul Lin wrote:
> When runtime suspend was enabled, runtime suspend might happened
> when xhci is removing hcd. This might cause kernel panic when hcd
> has been freed but runtime pm suspend related handle need to
> reference it.
>
> Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
> ---
> drivers/usb/host/xhci-mtk.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
> index bfbdb3c..641d24e 100644
> --- a/drivers/usb/host/xhci-mtk.c
> +++ b/drivers/usb/host/xhci-mtk.c
> @@ -587,6 +587,9 @@ static int xhci_mtk_remove(struct platform_device *dev)
> struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> struct usb_hcd *shared_hcd = xhci->shared_hcd;
>
> + pm_runtime_put_sync(&dev->dev);
> + pm_runtime_disable(&dev->dev);
> +
> usb_remove_hcd(shared_hcd);
> xhci->shared_hcd = NULL;
> device_init_wakeup(&dev->dev, false);
> @@ -597,8 +600,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
> xhci_mtk_sch_exit(mtk);
> xhci_mtk_clks_disable(mtk);
> xhci_mtk_ldos_disable(mtk);
> - pm_runtime_put_sync(&dev->dev);
> - pm_runtime_disable(&dev->dev);
>
> return 0;
> }
Reviewed-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Thanks
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Takashi Iwai @ 2020-06-03 8:45 UTC (permalink / raw)
To: Macpaul Lin
Cc: alsa-devel, Mediatek WSD Upstream, linux-kernel, linux-usb,
Johan Hovold, Takashi Iwai, Hui Wang, Alexander Tsoy,
linux-mediatek, Greg Kroah-Hartman, Matthias Brugger, Macpaul Lin,
Jaroslav Kysela, Szabolcs Szőke, linux-arm-kernel
In-Reply-To: <s5hblm0fxl0.wl-tiwai@suse.de>
On Wed, 03 Jun 2020 08:54:51 +0200,
Takashi Iwai wrote:
>
> On Wed, 03 Jun 2020 08:28:09 +0200,
> Takashi Iwai wrote:
> >
> > And, the most suspicious case is the last one,
> > chip->num_suspended-intf. It means that the device has multiple
> > USB interfaces and they went to suspend, while the resume isn't
> > performed for the all suspended interfaces in return.
>
> If this is the cause, a patch like below might help.
> It gets/puts the all assigned interfaced instead of only the primary
> one.
... and considering of the problem again, rather the patch below might
be the right answer. Now the driver tries to remember at which state
it entered into the system-suspend. Upon resume, in return, when the
state reaches back to that point, set the card state to D0.
The previous patch can be applied on the top, too, and it might be
worth to apply both.
Let me know if any of those actually helps.
Takashi
---
diff --git a/sound/usb/card.c b/sound/usb/card.c
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -843,9 +843,6 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
if (chip == (void *)-1L)
return 0;
- chip->autosuspended = !!PMSG_IS_AUTO(message);
- if (!chip->autosuspended)
- snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
if (!chip->num_suspended_intf++) {
list_for_each_entry(as, &chip->pcm_list, list) {
snd_usb_pcm_suspend(as);
@@ -858,6 +855,11 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
snd_usb_mixer_suspend(mixer);
}
+ if (!PMSG_IS_AUTO(message) && !chip->system_suspend) {
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+ chip->system_suspend = chip->num_suspended_intf;
+ }
+
return 0;
}
@@ -871,10 +873,10 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
if (chip == (void *)-1L)
return 0;
- if (--chip->num_suspended_intf)
- return 0;
atomic_inc(&chip->active); /* avoid autopm */
+ if (chip->num_suspended_intf > 1)
+ goto out;
list_for_each_entry(as, &chip->pcm_list, list) {
err = snd_usb_pcm_resume(as);
@@ -896,9 +898,12 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
snd_usbmidi_resume(p);
}
- if (!chip->autosuspended)
+ out:
+ if (chip->num_suspended_intf == chip->system_suspend) {
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
- chip->autosuspended = 0;
+ chip->system_suspend = 0;
+ }
+ chip->num_suspended_intf--;
err_out:
atomic_dec(&chip->active); /* allow autopm after this point */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1c892c7f14d7..e0ebfb25fbd5 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -26,7 +26,7 @@ struct snd_usb_audio {
struct usb_interface *pm_intf;
u32 usb_id;
struct mutex mutex;
- unsigned int autosuspended:1;
+ unsigned int system_suspend;
atomic_t active;
atomic_t shutdown;
atomic_t usage_count;
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related
* Re: Security Random Number Generator support
From: Neal Liu @ 2020-06-03 7:54 UTC (permalink / raw)
To: Marc Zyngier
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Julius Werner, Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Sean Wang, lkml, wsd_upstream, Crystal Guo (郭晶),
Rob Herring, Neal Liu, Linux Crypto Mailing List, Matt Mackall,
Matthias Brugger, linux-mediatek, Ard Biesheuvel, Linux ARM
In-Reply-To: <fcbe37f6f9cbcde24f9c28bc504f1f0e@kernel.org>
On Wed, 2020-06-03 at 08:40 +0100, Marc Zyngier wrote:
> On 2020-06-03 08:29, Neal Liu wrote:
> > On Tue, 2020-06-02 at 21:02 +0800, Marc Zyngier wrote:
> >> On 2020-06-02 13:14, Ard Biesheuvel wrote:
> >> > On Tue, 2 Jun 2020 at 10:15, Neal Liu <neal.liu@mediatek.com> wrote:
> >> >>
> >> >> These patch series introduce a security random number generator
> >> >> which provides a generic interface to get hardware rnd from Secure
> >> >> state. The Secure state can be Arm Trusted Firmware(ATF), Trusted
> >> >> Execution Environment(TEE), or even EL2 hypervisor.
> >> >>
> >> >> Patch #1..2 adds sec-rng kernel driver for Trustzone based SoCs.
> >> >> For security awareness SoCs on ARMv8 with TrustZone enabled,
> >> >> peripherals like entropy sources is not accessible from normal world
> >> >> (linux) and rather accessible from secure world (HYP/ATF/TEE) only.
> >> >> This driver aims to provide a generic interface to Arm Trusted
> >> >> Firmware or Hypervisor rng service.
> >> >>
> >> >>
> >> >> changes since v1:
> >> >> - rename mt67xx-rng to mtk-sec-rng since all MediaTek ARMv8 SoCs can
> >> >> reuse
> >> >> this driver.
> >> >> - refine coding style and unnecessary check.
> >> >>
> >> >> changes since v2:
> >> >> - remove unused comments.
> >> >> - remove redundant variable.
> >> >>
> >> >> changes since v3:
> >> >> - add dt-bindings for MediaTek rng with TrustZone enabled.
> >> >> - revise HWRNG SMC call fid.
> >> >>
> >> >> changes since v4:
> >> >> - move bindings to the arm/firmware directory.
> >> >> - revise driver init flow to check more property.
> >> >>
> >> >> changes since v5:
> >> >> - refactor to more generic security rng driver which
> >> >> is not platform specific.
> >> >>
> >> >> *** BLURB HERE ***
> >> >>
> >> >> Neal Liu (2):
> >> >> dt-bindings: rng: add bindings for sec-rng
> >> >> hwrng: add sec-rng driver
> >> >>
> >> >
> >> > There is no reason to model a SMC call as a driver, and represent it
> >> > via a DT node like this.
> >>
> >> +1.
> >>
> >> > It would be much better if this SMC interface is made truly generic,
> >> > and wired into the arch_get_random() interface, which can be used much
> >> > earlier.
> >>
> >> Wasn't there a plan to standardize a SMC call to rule them all?
> >>
> >> M.
> >
> > Could you give us a hint how to make this SMC interface more generic in
> > addition to my approach?
> > There is no (easy) way to get platform-independent SMC function ID,
> > which is why we encode it into device tree, and provide a generic
> > driver. In this way, different devices can be mapped and then get
> > different function ID internally.
>
> The idea is simply to have *one* single ID that caters for all
> implementations, just like we did for PSCI at the time. This
> requires ARM to edict a standard, which is what I was referring
> to above.
>
> There is zero benefit in having a platform-dependent ID. It just
> pointlessly increases complexity, and means we cannot use the RNG
> before the firmware tables are available (yes, we need it that
> early).
>
> M.
Do you know which ARM expert could edict this standard?
Or is there any chance that we can make one? And be reviewed by
maintainers?
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: Security Random Number Generator support
From: Marc Zyngier @ 2020-06-03 7:40 UTC (permalink / raw)
To: Neal Liu
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Julius Werner, Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Sean Wang, lkml, wsd_upstream, Rob Herring, linux-mediatek,
Linux Crypto Mailing List, Matt Mackall, Matthias Brugger,
Crystal Guo (郭晶), Ard Biesheuvel, Linux ARM
In-Reply-To: <1591169342.4878.9.camel@mtkswgap22>
On 2020-06-03 08:29, Neal Liu wrote:
> On Tue, 2020-06-02 at 21:02 +0800, Marc Zyngier wrote:
>> On 2020-06-02 13:14, Ard Biesheuvel wrote:
>> > On Tue, 2 Jun 2020 at 10:15, Neal Liu <neal.liu@mediatek.com> wrote:
>> >>
>> >> These patch series introduce a security random number generator
>> >> which provides a generic interface to get hardware rnd from Secure
>> >> state. The Secure state can be Arm Trusted Firmware(ATF), Trusted
>> >> Execution Environment(TEE), or even EL2 hypervisor.
>> >>
>> >> Patch #1..2 adds sec-rng kernel driver for Trustzone based SoCs.
>> >> For security awareness SoCs on ARMv8 with TrustZone enabled,
>> >> peripherals like entropy sources is not accessible from normal world
>> >> (linux) and rather accessible from secure world (HYP/ATF/TEE) only.
>> >> This driver aims to provide a generic interface to Arm Trusted
>> >> Firmware or Hypervisor rng service.
>> >>
>> >>
>> >> changes since v1:
>> >> - rename mt67xx-rng to mtk-sec-rng since all MediaTek ARMv8 SoCs can
>> >> reuse
>> >> this driver.
>> >> - refine coding style and unnecessary check.
>> >>
>> >> changes since v2:
>> >> - remove unused comments.
>> >> - remove redundant variable.
>> >>
>> >> changes since v3:
>> >> - add dt-bindings for MediaTek rng with TrustZone enabled.
>> >> - revise HWRNG SMC call fid.
>> >>
>> >> changes since v4:
>> >> - move bindings to the arm/firmware directory.
>> >> - revise driver init flow to check more property.
>> >>
>> >> changes since v5:
>> >> - refactor to more generic security rng driver which
>> >> is not platform specific.
>> >>
>> >> *** BLURB HERE ***
>> >>
>> >> Neal Liu (2):
>> >> dt-bindings: rng: add bindings for sec-rng
>> >> hwrng: add sec-rng driver
>> >>
>> >
>> > There is no reason to model a SMC call as a driver, and represent it
>> > via a DT node like this.
>>
>> +1.
>>
>> > It would be much better if this SMC interface is made truly generic,
>> > and wired into the arch_get_random() interface, which can be used much
>> > earlier.
>>
>> Wasn't there a plan to standardize a SMC call to rule them all?
>>
>> M.
>
> Could you give us a hint how to make this SMC interface more generic in
> addition to my approach?
> There is no (easy) way to get platform-independent SMC function ID,
> which is why we encode it into device tree, and provide a generic
> driver. In this way, different devices can be mapped and then get
> different function ID internally.
The idea is simply to have *one* single ID that caters for all
implementations, just like we did for PSCI at the time. This
requires ARM to edict a standard, which is what I was referring
to above.
There is zero benefit in having a platform-dependent ID. It just
pointlessly increases complexity, and means we cannot use the RNG
before the firmware tables are available (yes, we need it that
early).
M.
--
Jazz is not dead. It just smells funny...
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: Security Random Number Generator support
From: Neal Liu @ 2020-06-03 7:29 UTC (permalink / raw)
To: Marc Zyngier, Julius Werner, Ard Biesheuvel
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman, Sean Wang,
linux-mediatek@lists.infradead.org, lkml, wsd_upstream,
Rob Herring, Neal Liu, Linux Crypto Mailing List, Matt Mackall,
Matthias Brugger, Crystal Guo (郭晶), Linux ARM
In-Reply-To: <85dfc0142d3879d50c0ba18bcc71e199@misterjones.org>
On Tue, 2020-06-02 at 21:02 +0800, Marc Zyngier wrote:
> On 2020-06-02 13:14, Ard Biesheuvel wrote:
> > On Tue, 2 Jun 2020 at 10:15, Neal Liu <neal.liu@mediatek.com> wrote:
> >>
> >> These patch series introduce a security random number generator
> >> which provides a generic interface to get hardware rnd from Secure
> >> state. The Secure state can be Arm Trusted Firmware(ATF), Trusted
> >> Execution Environment(TEE), or even EL2 hypervisor.
> >>
> >> Patch #1..2 adds sec-rng kernel driver for Trustzone based SoCs.
> >> For security awareness SoCs on ARMv8 with TrustZone enabled,
> >> peripherals like entropy sources is not accessible from normal world
> >> (linux) and rather accessible from secure world (HYP/ATF/TEE) only.
> >> This driver aims to provide a generic interface to Arm Trusted
> >> Firmware or Hypervisor rng service.
> >>
> >>
> >> changes since v1:
> >> - rename mt67xx-rng to mtk-sec-rng since all MediaTek ARMv8 SoCs can
> >> reuse
> >> this driver.
> >> - refine coding style and unnecessary check.
> >>
> >> changes since v2:
> >> - remove unused comments.
> >> - remove redundant variable.
> >>
> >> changes since v3:
> >> - add dt-bindings for MediaTek rng with TrustZone enabled.
> >> - revise HWRNG SMC call fid.
> >>
> >> changes since v4:
> >> - move bindings to the arm/firmware directory.
> >> - revise driver init flow to check more property.
> >>
> >> changes since v5:
> >> - refactor to more generic security rng driver which
> >> is not platform specific.
> >>
> >> *** BLURB HERE ***
> >>
> >> Neal Liu (2):
> >> dt-bindings: rng: add bindings for sec-rng
> >> hwrng: add sec-rng driver
> >>
> >
> > There is no reason to model a SMC call as a driver, and represent it
> > via a DT node like this.
>
> +1.
>
> > It would be much better if this SMC interface is made truly generic,
> > and wired into the arch_get_random() interface, which can be used much
> > earlier.
>
> Wasn't there a plan to standardize a SMC call to rule them all?
>
> M.
Could you give us a hint how to make this SMC interface more generic in
addition to my approach?
There is no (easy) way to get platform-independent SMC function ID,
which is why we encode it into device tree, and provide a generic
driver. In this way, different devices can be mapped and then get
different function ID internally.
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Takashi Iwai @ 2020-06-03 6:54 UTC (permalink / raw)
To: Macpaul Lin
Cc: alsa-devel, Mediatek WSD Upstream, linux-kernel, linux-usb,
Johan Hovold, Takashi Iwai, Hui Wang, Alexander Tsoy,
linux-mediatek, Greg Kroah-Hartman, Matthias Brugger, Macpaul Lin,
Jaroslav Kysela, Szabolcs Szőke, linux-arm-kernel
In-Reply-To: <s5heeqwfyti.wl-tiwai@suse.de>
On Wed, 03 Jun 2020 08:28:09 +0200,
Takashi Iwai wrote:
>
> And, the most suspicious case is the last one,
> chip->num_suspended-intf. It means that the device has multiple
> USB interfaces and they went to suspend, while the resume isn't
> performed for the all suspended interfaces in return.
If this is the cause, a patch like below might help.
It gets/puts the all assigned interfaced instead of only the primary
one.
Takashi
---
diff --git a/sound/usb/card.c b/sound/usb/card.c
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -634,7 +634,6 @@ static int usb_audio_probe(struct usb_interface *intf,
id, &chip);
if (err < 0)
goto __error;
- chip->pm_intf = intf;
break;
} else if (vid[i] != -1 || pid[i] != -1) {
dev_info(&dev->dev,
@@ -651,6 +650,13 @@ static int usb_audio_probe(struct usb_interface *intf,
goto __error;
}
}
+
+ if (chip->num_interfaces >= MAX_CARD_INTERFACES) {
+ dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
+ err = -EINVAL;
+ goto __error;
+ }
+
dev_set_drvdata(&dev->dev, chip);
/*
@@ -703,6 +709,7 @@ static int usb_audio_probe(struct usb_interface *intf,
}
usb_chip[chip->index] = chip;
+ chip->intf[chip->num_interfaces] = intf;
chip->num_interfaces++;
usb_set_intfdata(intf, chip);
atomic_dec(&chip->active);
@@ -818,19 +825,36 @@ void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
int snd_usb_autoresume(struct snd_usb_audio *chip)
{
+ int i, err;
+
if (atomic_read(&chip->shutdown))
return -EIO;
- if (atomic_inc_return(&chip->active) == 1)
- return usb_autopm_get_interface(chip->pm_intf);
+ if (atomic_inc_return(&chip->active) != 1)
+ return 0;
+
+ for (i = 0; i < chip->num_interfaces; i++) {
+ err = usb_autopm_get_interface(chip->intf[i]);
+ if (err < 0) {
+ /* rollback */
+ while (--i >= 0)
+ usb_autopm_put_interface(chip->intf[i]);
+ return err;
+ }
+ }
return 0;
}
void snd_usb_autosuspend(struct snd_usb_audio *chip)
{
+ int i;
+
if (atomic_read(&chip->shutdown))
return;
- if (atomic_dec_and_test(&chip->active))
- usb_autopm_put_interface(chip->pm_intf);
+ if (!atomic_dec_and_test(&chip->active))
+ return;
+
+ for (i = 0; i < chip->num_interfaces; i++)
+ usb_autopm_put_interface(chip->intf[i]);
}
static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -19,11 +19,13 @@
struct media_device;
struct media_intf_devnode;
+#define MAX_CARD_INTERFACES 16
+
struct snd_usb_audio {
int index;
struct usb_device *dev;
struct snd_card *card;
- struct usb_interface *pm_intf;
+ struct usb_interface *intf[MAX_CARD_INTERFACES];
u32 usb_id;
struct mutex mutex;
unsigned int autosuspended:1;
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Takashi Iwai @ 2020-06-03 6:28 UTC (permalink / raw)
To: Macpaul Lin
Cc: alsa-devel, Mediatek WSD Upstream, linux-kernel, linux-usb,
Johan Hovold, Takashi Iwai, Hui Wang, Alexander Tsoy,
linux-mediatek, Greg Kroah-Hartman, Matthias Brugger, Macpaul Lin,
Jaroslav Kysela, Szabolcs Szőke, linux-arm-kernel
In-Reply-To: <1591153515.23525.50.camel@mtkswgap22>
On Wed, 03 Jun 2020 05:05:15 +0200,
Macpaul Lin wrote:
>
> On Tue, 2020-06-02 at 14:46 +0200, Takashi Iwai wrote:
> > On Tue, 02 Jun 2020 13:53:41 +0200,
> > Macpaul Lin wrote:
> > >
> > > This patch fix incorrect power state changed by usb_audio_suspend()
> > > when CONFIG_PM is enabled.
> > >
> > > After receiving suspend PM message with auto flag, usb_audio_suspend()
> > > change card's power state to SNDRV_CTL_POWER_D3hot. Only when the other
> > > resume PM message with auto flag can change power state to
> > > SNDRV_CTL_POWER_D0 in __usb_audio_resume().
> > >
> > > However, when system is not under auto suspend, resume PM message with
> > > auto flag might not be able to receive on time which cause the power
> > > state was incorrect. At this time, if a player starts to play sound,
> > > will cause snd_usb_pcm_open() to access the card and setup_hw_info() will
> > > resume the card.
> > >
> > > But even the card is back to work and all function normal, the power
> > > state is still in SNDRV_CTL_POWER_D3hot.
> >
> > Hm, in exactly which situation does this happen? I still don't get
> > it. Could you elaborate how to trigger this?
>
> I'm not sure if this will happen on laptop or on PC.
> We've found this issue on Android phone (I'm not sure if each Android
> phone can reproduce this.).
>
> After booting the android phone, insert type-c headset without charging
> and play music at any duration, say, 1 second, then stop. Put phone away
> to idle about 17~18 minutes. Wait auto pm happened and the power state
> change to SNDRV_CTL_POWER_D3hot in sound/usb/card.c. Then wake up the
> phone, play music again. Then you'll probably found the music was not
> playing and the progress bar keep at the same position. It only happen
> when power state is SNDRV_CTL_POWER_D3hot. If not (the power state is
> SNDRV_CTL_POWER_D0), repeat the steps for several times, then it will be
> produced at some time.
>
> When it happened, sound_usb_pcm_open() will wake up the sound card by
> setup_hw_info()->__usb_audio_resume(). However, the card and the
> interface is function properly right now, the power state keeps remain
> SNDRV_CTL_POWER_D3hot.
And at this point it's already something wrong. We need to check why
SNDRV_CTL_POWER_D3hot is kept there, instead of working around the
rest behavior.
> The suggestive parameter settings from upper
> sound request will be pending since later snd_power_wait() call will
> still wait the card awaken. Ideally, auto PM should be recovered by
> sound card itself. But once the card is awaken at this circumstance, it
> looks like there are not more auto pm event. And the sound system of
> this interface will stuck here forever until user plug out the headset
> (reset the hardware).
>
> The root cause is that once the card has been resumed, it should inform
> auto pm change the state back into SNDRV_CTL_POWER_D0 and mark the
> device is using by some one.
>
> > > Which cause the infinite loop
> > > happened in snd_power_wait() to check the power state. Thus the
> > > successive setting ioctl cannot be passed to card.
> > >
> > > Hence we suggest to change power state to SNDRV_CTL_POWER_D0 when card
> > > has been resumed successfully.
> >
> > This doesn't look like a right solution for the problem, sorry.
> > The card PM status must be recovered to D0 when the autoresume
> > succeeds. If not, something is broken there, and it must be fixed
> > instead of fiddling the status flag externally.
>
> Yes, I agreed, but after checking the code in sound drivers,
> it looks like there is only chance that auto pm triggered by low-level
> code in sound/usb/card.c. In kernel 4.14, auto pm suspend is triggered
> by snd_pcm_suspend_all(). In later kernel, it is triggered by
> snd_usb_pcm_suspend(). However, it looks like there are no any resume
> trigger to recover auto pm state when the card has been waken by
> sound_usb_pcm_open().
If a running PCM stream has been suspended, the stream needs to be
resumed manually by user-space. There is no automatic resume. You
can forget about it and skip scratching that surface.
Again, the point to be checked is why D3hot is kept after
snd_usb_autoresume() is called.
It's Android, and I wonder whether the system does the system-suspend
(S3), or it's all runtime PM? Basically D3hot is set only for the
former, the system suspend, where the driver's PM callback is called
with PMSG_SUSPEND. Please check this at first. That is,
usb_audio_suspend() receives PMSG_SUSPEND or such, which makes
chip->autosuspended=1. The D3hot flag is set only in this condition.
Then, check the resume patterns. The usb-audio suspend/resume has
multiple refcounts. One is the Linux device PM refcount, and
chip->active refcount, and chip->num_suspended_intf refcount.
The first one (PM refount) is the primary refcount to manage the whole
system, and this is incremented / decremented by the standard PM
calls. The second one, chip->active, is a temporary flag to avoid the
re-entrance of the PM callbacks, and incremented at the probe enter
and __usb_audio_resume(), and decremented at the probe exit and
__usb_audio_resume() exist. The last one, chip->num_suspended_intf is
a refcount for the multiple interfaces assigned to a single card.
And, the most suspicious case is the last one,
chip->num_suspended-intf. It means that the device has multiple
USB interfaces and they went to suspend, while the resume isn't
performed for the all suspended interfaces in return.
If that's the case, you need to check where the suspend gets called to
which USB-interface (and which pm_message_t) and whether the resume
gets called for those.
thanks,
Takashi
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH 06/12] PM / devfreq: Add cpu based scaling support to passive_governor
From: Chanwoo Choi @ 2020-06-03 4:12 UTC (permalink / raw)
To: andrew-sh.cheng
Cc: Mark Rutland, Nishanth Menon, srv_heupstream, devicetree,
Stephen Boyd, Viresh Kumar, Mark Brown, linux-pm,
Rafael J . Wysocki, Liam Girdwood, Rob Herring, linux-kernel,
Kyungmin Park, MyungJoo Ham, linux-mediatek, Sibi Sankar,
Matthias Brugger, linux-arm-kernel
In-Reply-To: <1591100614.1804.1.camel@mtksdaap41>
Hi Andrew-sh.Cheng,
On 6/2/20 9:23 PM, andrew-sh.cheng wrote:
> On Thu, 2020-05-28 at 16:17 +0900, Chanwoo Choi wrote:
>> Hi Andrew-sh.Cheng,
>>
>> The exynos-bus.c used the passive governor.
>> Even if don't make the problem because DEVFREQ_PARENT_DEV is zero,
>> you need to initialize the parent_type with DEVFREQ_PARENT_DEV as following:
>>
>> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
>> index 8fa8eb541373..1c71c47bc2ac 100644
>> --- a/drivers/devfreq/exynos-bus.c
>> +++ b/drivers/devfreq/exynos-bus.c
>> @@ -369,6 +369,7 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>> return -ENOMEM;
>>
>> passive_data->parent = parent_devfreq;
>> + passive_data->parent_type = DEVFREQ_PARENT_DEV;
>>
>> /* Add devfreq device for exynos bus with passive governor */
>> bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
> Hi Chanwoo Choi,
> Do you just remind me to initialize it to DEVFREQ_PARENT_DEV whn use
> this governor?
Yes. This change was not included in this patchset.
> I will do it and thank you for reminding.
Thanks.
(snip)
And, this patchset doesn't include the dt-binding example
and any real example in devicetree. If possible, I recommend
you better to update dt-binding document with example.
--
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH 06/12] PM / devfreq: Add cpu based scaling support to passive_governor
From: Chanwoo Choi @ 2020-06-03 4:07 UTC (permalink / raw)
To: andrew-sh.cheng
Cc: Mark Rutland, Nishanth Menon, srv_heupstream, devicetree,
Stephen Boyd, Viresh Kumar, Mark Brown, linux-pm,
Rafael J . Wysocki, Liam Girdwood, Rob Herring, linux-kernel,
Kyungmin Park, MyungJoo Ham, linux-mediatek, Sibi Sankar,
Matthias Brugger, linux-arm-kernel
In-Reply-To: <1591098190.30729.15.camel@mtksdaap41>
Hi Andrew-sh.Cheng,
Do you know that why cannot show the patches sent from you on mailing list?
Even if you sent them to linux-pm mailing list, I cannot find
your patches on linux-pm's patchwork[1] and others.
[1] https://patchwork.kernel.org/project/linux-pm/list/
Could you find you patch on mailing list?
Do you use git send-email when you send these patches?
I used the thunderbird tool and gmail for reading the patches.
When I tried to read the original source of this patch,
it looks like that the body of patch is encoded.
I cannot read the plain text of patch body.
- When gmail, use 'Show original'
- When thunderbird, use 'More -> View Source'
If I'm missing something to check this patch,
please let me know. I'll fix my environment.
It is strange situation on my case.
On 6/2/20 8:43 PM, andrew-sh.cheng wrote:
> On Thu, 2020-05-28 at 15:14 +0900, Chanwoo Choi wrote:
>> Hi Andrew-sh.Cheng,
>>
>> Thanks for your posting. I like this approach absolutely.
>> I think that it is necessary. When I developed the embedded product,
>> I needed this feature always.
>>
>> I add the comments on below.
>>
>>
>> And the following email is not valid. So, I dropped this email
>> from Cc list.
>> Saravana Kannan <skannan@codeaurora.org>
>>
>>
>> On 5/20/20 12:43 PM, Andrew-sh.Cheng wrote:
>>> From: Saravana Kannan <skannan@codeaurora.org>
>>>
>>> Many CPU architectures have caches that can scale independent of the
>>> CPUs. Frequency scaling of the caches is necessary to make sure that the
>>> cache is not a performance bottleneck that leads to poor performance and
>>> power. The same idea applies for RAM/DDR.
>>>
>>> To achieve this, this patch adds support for cpu based scaling to the
>>> passive governor. This is accomplished by taking the current frequency
>>> of each CPU frequency domain and then adjust the frequency of the cache
>>> (or any devfreq device) based on the frequency of the CPUs. It listens
>>> to CPU frequency transition notifiers to keep itself up to date on the
>>> current CPU frequency.
>>>
>>> To decide the frequency of the device, the governor does one of the
>>> following:
>>> * Derives the optimal devfreq device opp from required-opps property of
>>> the parent cpu opp_table.
>>>
>>> * Scales the device frequency in proportion to the CPU frequency. So, if
>>> the CPUs are running at their max frequency, the device runs at its
>>> max frequency. If the CPUs are running at their min frequency, the
>>> device runs at its min frequency. It is interpolated for frequencies
>>> in between.
>>>
>>> Andrew-sh.Cheng change
>>> dev_pm_opp_xlate_opp to dev_pm_opp_xlate_required_opp devfreq->max_freq
>>> to devfreq->user_min_freq_req.data.freq.qos->min_freq.target_value
>>> for kernel-5.7
>>>
>>> Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
>>> [Sibi: Integrated cpu-freqmap governor into passive_governor]
>>> Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
>>> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
>>> ---
>>> drivers/devfreq/Kconfig | 2 +
>>> drivers/devfreq/governor_passive.c | 278 ++++++++++++++++++++++++++++++++++---
>>> include/linux/devfreq.h | 40 +++++-
>>> 3 files changed, 299 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
>>> index 0b1df12e0f21..d9067950af6a 100644
>>> --- a/drivers/devfreq/Kconfig
>>> +++ b/drivers/devfreq/Kconfig
>>> @@ -73,6 +73,8 @@ config DEVFREQ_GOV_PASSIVE
>>> device. This governor does not change the frequency by itself
>>> through sysfs entries. The passive governor recommends that
>>> devfreq device uses the OPP table to get the frequency/voltage.
>>> + Alternatively the governor can also be chosen to scale based on
>>> + the online CPUs current frequency.
>>>
>>> comment "DEVFREQ Drivers"
>>>
>>> diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
>>> index 2d67d6c12dce..7dcda02a5bb7 100644
>>> --- a/drivers/devfreq/governor_passive.c
>>> +++ b/drivers/devfreq/governor_passive.c
>>> @@ -8,11 +8,89 @@
>>> */
>>>
>>> #include <linux/module.h>
>>> +#include <linux/cpu.h>
>>> +#include <linux/cpufreq.h>
>>> +#include <linux/cpumask.h>
>>> #include <linux/device.h>
>>> #include <linux/devfreq.h>
>>> +#include <linux/slab.h>
>>> #include "governor.h"
>>>
>>> -static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
>>> +static unsigned int xlate_cpufreq_to_devfreq(struct devfreq_passive_data *data,
>>
>> Need to change 'unsigned int' to 'unsigned long'
> Get it.
If you add the blank line before/after of your reply,
it is better to catch your reply. Please add the blank line for me.
>> .
>>
>>> + unsigned int cpu)
>>> +{
>>> + unsigned int cpu_min, cpu_max, dev_min, dev_max, cpu_percent, max_state;
>>
>> Better to define them separately as following and then need to rename
>> the variable. Usually, use the 'min_freq' and 'max_freq' word for
>> the minimum/maximum frequency.
>>
>> unsigned int cpu_min_freq, cpu_max_freq, cpu_curr_freq, cpu_percent;
>> unsigned long dev_min_freq, dev_max_freq, dev_max_state,
>>
>> The devfreq used 'unsigned long'. The cpufreq used 'unsigned long'
>> and 'unsigned int'. You need to handle them properly.
> Get it.
> For cpu_freq, I separate it into "unsigned long cpu_curr_freq" and
> "unsigned int cpu_curr_freq_khz"
>>
>>
>>> + struct devfreq_cpu_state *cpu_state = data->cpu_state[cpu];
>>> + struct devfreq *devfreq = (struct devfreq *)data->this;
>>> + unsigned long *freq_table = devfreq->profile->freq_table;
>>
>> In this function, use 'cpu' work for cpufreq and use 'dev' for devfreq.
>> So, I think 'dev_freq_table' is proper name instead of 'freq_table'
>> for the readability.
>>
>> freq_table -> dev_freq_table
>>
>>> + struct dev_pm_opp *opp = NULL, *cpu_opp = NULL;
>>
>> In the get_target_freq_with_devfreq(), use 'p_opp' indicating
>> the OPP of parent device. For the consistency, I think that
>> use 'p_opp' instead of 'cpu_opp'.
>>
>>> + unsigned long cpu_freq, freq;
>>
>> Define the 'cpu_freq' on above with cpu_min_freq/cpu_max_freq definition.
>> cpu_freq -> cpu_curr_freq.
> Get it.
> Will modify them for readability.
>>
>>> +
>>> + if (!cpu_state || cpu_state->first_cpu != cpu ||
>>> + !cpu_state->opp_table || !devfreq->opp_table)
>>> + return 0;
>>> +
>>> + cpu_freq = cpu_state->freq * 1000;
>>> + cpu_opp = devfreq_recommended_opp(cpu_state->dev, &cpu_freq, 0);
>>> + if (IS_ERR(cpu_opp))
>>> + return 0;
>>> +
>>> + opp = dev_pm_opp_xlate_required_opp(cpu_state->opp_table,
>>> + devfreq->opp_table, cpu_opp);
>>> + dev_pm_opp_put(cpu_opp);
>>> +
>>> + if (!IS_ERR(opp)) {
>>> + freq = dev_pm_opp_get_freq(opp);
>>> + dev_pm_opp_put(opp);
>>
>> Better to add the 'out' goto statement.
>> If you use 'goto out', you can reduce the one indentation
>> without 'else' statement.
> Get it.
>>
>>
>>> + } else {
>>
>> As I commented, when dev_pm_opp_xlate_required_opp() return successfully
>> , use 'goto out'. We can remove 'else' and then reduce the unneeded indentation.
>>
>>
>>> + /* Use Interpolation if required opps is not available */
>>> + cpu_min = cpu_state->min_freq;
>>> + cpu_max = cpu_state->max_freq;
>>> + cpu_freq = cpu_state->freq;
>>> +
>>> + if (freq_table) {
>>> + /* Get minimum frequency according to sorting order */
>>> + max_state = freq_table[devfreq->profile->max_state - 1];
>>> + if (freq_table[0] < max_state) {
>>> + dev_min = freq_table[0];
>>> + dev_max = max_state;
>>> + } else {
>>> + dev_min = max_state;
>>> + dev_max = freq_table[0];
>>> + }
>>> + } else {
>>> + if (devfreq->user_max_freq_req.data.freq.qos->max_freq.target_value
>>> + <= devfreq->user_min_freq_req.data.freq.qos->min_freq.target_value)
>>> + return 0;
>>> + dev_min =
>>> + devfreq->user_min_freq_req.data.freq.qos->min_freq.target_value;
>>> + dev_max =
>>> + devfreq->user_max_freq_req.data.freq.qos->max_freq.target_value;
>>
>> I think it is not proper to access the variable of pm_qos structure directly.
>> Instead of direct access, you have to use the exported PM QoS function such as
>> - pm_qos_read_value(devfreq->dev.parent, DEV_PM_QOS_MIN_FREQUENCY);
>> - pm_qos_read_value(devfreq->dev.parent, DEV_PM_QOS_MAX_FREQUENCY);
> Get it.
>>
>>> + }
>>> + cpu_percent = ((cpu_freq - cpu_min) * 100) / cpu_max - cpu_min;
>>> + freq = dev_min + mult_frac(dev_max - dev_min, cpu_percent, 100);
>>> + }
>>
>>
>> I think that you better to add 'out' jump label as following:
>>
>> out:
>>
>>> +
>>> + return freq;
>>> +}
>>> +
>>> +static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
>>> + unsigned long *freq)
>>> +{
>>> + struct devfreq_passive_data *p_data =
>>> + (struct devfreq_passive_data *)devfreq->data;
>>> + unsigned int cpu, target_freq = 0;
>>
>> Need to define 'target_freq' with 'unsigned long' type.
> Get it.
>>
>>> +
>>> + for_each_online_cpu(cpu)
>>> + target_freq = max(target_freq,
>>> + xlate_cpufreq_to_devfreq(p_data, cpu));
>>> +
>>> + *freq = target_freq;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int get_target_freq_with_devfreq(struct devfreq *devfreq,
>>> unsigned long *freq)
>>> {
>>> struct devfreq_passive_data *p_data
>>> @@ -23,16 +101,6 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
>>> int i, count, ret = 0;
>>>
>>> /*
>>> - * If the devfreq device with passive governor has the specific method
>>> - * to determine the next frequency, should use the get_target_freq()
>>> - * of struct devfreq_passive_data.
>>> - */
>>> - if (p_data->get_target_freq) {
>>> - ret = p_data->get_target_freq(devfreq, freq);
>>> - goto out;
>>> - }
>>> -
>>> - /*
>>> * If the parent and passive devfreq device uses the OPP table,
>>> * get the next frequency by using the OPP table.
>>> */
>>> @@ -102,6 +170,37 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
>>> return ret;
>>> }
>>>
>>> +static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
>>> + unsigned long *freq)
>>> +{
>>> + struct devfreq_passive_data *p_data =
>>> + (struct devfreq_passive_data *)devfreq->data;
>>> + int ret;
>>> +
>>> + /*
>>> + * If the devfreq device with passive governor has the specific method
>>> + * to determine the next frequency, should use the get_target_freq()
>>> + * of struct devfreq_passive_data.
>>> + */
>>> + if (p_data->get_target_freq)
>>> + return p_data->get_target_freq(devfreq, freq);
>>> +
>>> + switch (p_data->parent_type) {
>>> + case DEVFREQ_PARENT_DEV:
>>> + ret = get_target_freq_with_devfreq(devfreq, freq);
>>> + break;
>>> + case CPUFREQ_PARENT_DEV:
>>> + ret = get_target_freq_with_cpufreq(devfreq, freq);
>>> + break;
>>> + default:
>>> + ret = -EINVAL;
>>> + dev_err(&devfreq->dev, "Invalid parent type\n");
>>> + break;
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq)
>>> {
>>> int ret;
>>> @@ -156,6 +255,140 @@ static int devfreq_passive_notifier_call(struct notifier_block *nb,
>>> return NOTIFY_DONE;
>>> }
>>>
>>> +static int cpufreq_passive_notifier_call(struct notifier_block *nb,
>>> + unsigned long event, void *ptr)
>>> +{
>>> + struct devfreq_passive_data *data =
>>> + container_of(nb, struct devfreq_passive_data, nb);
>>> + struct devfreq *devfreq = (struct devfreq *)data->this;
>>> + struct devfreq_cpu_state *cpu_state;
>>> + struct cpufreq_freqs *freq = ptr;
>>
>> How about changing 'freq' to 'cpu_freqs'?
>>
>> In the drivers/cpufreq/cpufreq.c, use 'freqs' name indicating
>> the instance of 'struct cpufreq_freqs'. And in order to
>> identfy, how about adding 'cpu_' prefix for variable name?
>>
>>> + unsigned int current_freq;
>>
>> Need to define curr_freq with 'unsigned long' type
>> and better to use 'curr_freq' variable name.
> It is good to change current_freq to curr_freq, but why should it us
> 'unsigned long'?
> I think it is 'unsigned int'.
I think that 'curr_freq' is proper. Yes, it is 'unsigned int'.
When you changing the cpu frequency to device frequency,
recommend to handle them between unsigned int and unsigned long.
>>
>>> + int ret;
>>> +
>>> + if (event != CPUFREQ_POSTCHANGE || !freq ||
>>> + !data->cpu_state[freq->policy->cpu])
>>> + return 0;
>>> +
>>> + cpu_state = data->cpu_state[freq->policy->cpu];
>>> + if (cpu_state->freq == freq->new)
>>> + return 0;
>>> +
>>> + /* Backup current freq and pre-update cpu state freq*/
>>> + current_freq = cpu_state->freq;
>>> + cpu_state->freq = freq->new;
>>> +
>>> + mutex_lock(&devfreq->lock);
>>> + ret = update_devfreq(devfreq);
>>> + mutex_unlock(&devfreq->lock);
>>> + if (ret) {
>>> + cpu_state->freq = current_freq;
>>> + dev_err(&devfreq->dev, "Couldn't update the frequency.\n");
>>> + return ret;
>>> + }
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int cpufreq_passive_register(struct devfreq_passive_data **p_data)
>>> +{
>>> + struct devfreq_passive_data *data = *p_data;
>>> + struct devfreq *devfreq = (struct devfreq *)data->this;
>>> + struct device *dev = devfreq->dev.parent;
>>> + struct opp_table *opp_table = NULL;
>>> + struct devfreq_cpu_state *state;
>>
>> For the readability, I thinkt 'cpu_state' is proper instead of 'state'.
> Get it.
>>
>>> + struct cpufreq_policy *policy;
>>> + struct device *cpu_dev;
>>> + unsigned int cpu;
>>> + int ret;
>>> +
>>> + get_online_cpus();
>>
>> Add blank line.
> Get it.
>>
>>> + data->nb.notifier_call = cpufreq_passive_notifier_call;
>>> + ret = cpufreq_register_notifier(&data->nb,
>>> + CPUFREQ_TRANSITION_NOTIFIER);
>>> + if (ret) {
>>> + dev_err(dev, "Couldn't register cpufreq notifier.\n");
>>> + data->nb.notifier_call = NULL;
>>> + goto out;
>>> + }
>>> +
>>> + /* Populate devfreq_cpu_state */
>>> + for_each_online_cpu(cpu) {
>>> + if (data->cpu_state[cpu])
>>> + continue;
>>> +
>>> + policy = cpufreq_cpu_get(cpu);
>>
>> cpufreq_cpu_get() might return 'NULL'. I think you need to handle
>> return value as following:
>>
>> if (!policy) {
>> ret = -EINVAL;
>> goto out;
>> } else if (PTR_ERR(policy) == -EPROBE_DEFER) {
>> goto out;
>> } else if (IS_ERR(policy) {
>> ret = PTR_ERR(policy);
>> dev_err(dev, "Couldn't get the cpufreq_poliy.\n");
>> goto out;
>> }
>>
>> If cpufreq_cpu_get() return successfully, to do next.
>> It reduces the one indentaion.
>>
>>
> Get it.
>>
>>> + if (policy) {
>>> + state = kzalloc(sizeof(*state), GFP_KERNEL);
>>> + if (!state) {
>>> + ret = -ENOMEM;
>>> + goto out;
>>> + }
>>> +
>>> + cpu_dev = get_cpu_device(cpu);
>>> + if (!cpu_dev) {
>>> + dev_err(dev, "Couldn't get cpu device.\n");
>>> + ret = -ENODEV;
>>> + goto out;
>>> + }
>>> +
>>> + opp_table = dev_pm_opp_get_opp_table(cpu_dev);
>>> + if (IS_ERR(devfreq->opp_table)) {
>>> + ret = PTR_ERR(opp_table);
>>> + goto out;
>>> + }
>>> +
>>> + state->dev = cpu_dev;
>>> + state->opp_table = opp_table;
>>> + state->first_cpu = cpumask_first(policy->related_cpus);
>>> + state->freq = policy->cur;
>>> + state->min_freq = policy->cpuinfo.min_freq;
>>> + state->max_freq = policy->cpuinfo.max_freq;
>>> + data->cpu_state[cpu] = state;
>>
>> Add blank line.
>>
>>> + cpufreq_cpu_put(policy);
>>> + } else {
>>> + ret = -EPROBE_DEFER;
>>> + goto out;
>>> + }
>>> + }
>>
>> Add blank line.
> Get it.
>>> +out:
>>> + put_online_cpus();
>>> + if (ret)
>>> + return ret;
>>> +
>>> + /* Update devfreq */
>>> + mutex_lock(&devfreq->lock);
>>> + ret = update_devfreq(devfreq);
>>> + mutex_unlock(&devfreq->lock);
>>> + if (ret)
>>> + dev_err(dev, "Couldn't update the frequency.\n");
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static int cpufreq_passive_unregister(struct devfreq_passive_data **p_data)
>>> +{
>>> + struct devfreq_passive_data *data = *p_data;
>>> + struct devfreq_cpu_state *cpu_state;
>>> + int cpu;
>>> +
>>> + if (data->nb.notifier_call)
>>> + cpufreq_unregister_notifier(&data->nb,
>>> + CPUFREQ_TRANSITION_NOTIFIER);
>>> +
>>> + for_each_possible_cpu(cpu) {
>>> + cpu_state = data->cpu_state[cpu];
>>> + if (cpu_state) {
>>> + if (cpu_state->opp_table)
>>> + dev_pm_opp_put_opp_table(cpu_state->opp_table);
>>> + kfree(cpu_state);
>>> + cpu_state = NULL;
>>> + }
>>> + }
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int devfreq_passive_event_handler(struct devfreq *devfreq,
>>> unsigned int event, void *data)
>>> {
>>> @@ -165,7 +398,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
>>> struct notifier_block *nb = &p_data->nb;
>>> int ret = 0;
>>>
>>> - if (!parent)
>>> + if (p_data->parent_type == DEVFREQ_PARENT_DEV && !parent)
>>> return -EPROBE_DEFER;
>>
>> If you modify the devfreq_passive_event_handler() as following,
>> you can move this condition for DEVFREQ_PARENT_DEV into
>> (register|unregister)_parent_dev_notifier.
>>
>> switch (event) {
>> case DEVFREQ_GOV_START:
>> ret = register_parent_dev_notifier(p_data);
>> break;
>> case DEVFREQ_GOV_STOP:
>> ret = unregister_parent_dev_notifier(p_data);
>> break;
>> default:
>> ret = -EINVAL;
>> break;
>> }
>>
>> return ret;
>>
> Get it.
>>>
>>> switch (event) {
>>> @@ -173,13 +406,24 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
>>> if (!p_data->this)
>>> p_data->this = devfreq;
>>>
>>> - nb->notifier_call = devfreq_passive_notifier_call;
>>> - ret = devfreq_register_notifier(parent, nb,
>>> - DEVFREQ_TRANSITION_NOTIFIER);
>>> + if (p_data->parent_type == DEVFREQ_PARENT_DEV) {
>>> + nb->notifier_call = devfreq_passive_notifier_call;
>>> + ret = devfreq_register_notifier(parent, nb,
>>> + DEVFREQ_TRANSITION_NOTIFIER);
>>> + } else if (p_data->parent_type == CPUFREQ_PARENT_DEV) {
>>> + ret = cpufreq_passive_register(&p_data);
>>
>> I think that we better to collect the code related to notifier registration
>> into one function like devfreq_pass_register_notifier() instead of
>> cpufreq_passive_register() as following: I think it is more simple and readable.
>>
>> If you have more proper function name of register_parent_dev_notifier,
>> please give your opinion.
>>
>> int register_parent_dev_notifier(struct devfreq_passive_data **p_data)
>> switch (p_data->parent_type) {
>> case DEVFREQ_PARENT_DEV:
>> nb->notifier_call = devfreq_passive_notifier_call;
>> ret = devfreq_register_notifier(parent, nb,
>> break;
>> case CPUFREQ_PARENT_DEV:
>> cpufreq_register_notifier(...)
>> ...
>> break;
>> }
> Not fully understanding.
> Do you mean expanding cpufreq_passive_register()?
Yes and rename it for both cpufreq and devfreq.
> I think leave it in function will be with clean for this code segment.
I want that one function handle the notifier register
for both cpufreq and devfreq so that we make it more simply as following:
On the step hanling the governor event, don't need to consider
the type of parent device of devfreq deivce with this style.
case DEVFREQ_GOV_START:
ret = register_notifier(...);
break;
case DEVFREQ_GOV_STOP:
ret = unregister_notifier(...);
break;
>
>>
>>
>>> + } else {
>>> + ret = -EINVAL;
>>> + }
>>> break;
>>> case DEVFREQ_GOV_STOP:
>>> - WARN_ON(devfreq_unregister_notifier(parent, nb,
>>> - DEVFREQ_TRANSITION_NOTIFIER));
>>> + if (p_data->parent_type == DEVFREQ_PARENT_DEV)
>>> + WARN_ON(devfreq_unregister_notifier(parent, nb,
>>> + DEVFREQ_TRANSITION_NOTIFIER));
>>> + else if (p_data->parent_type == CPUFREQ_PARENT_DEV)
>>> + cpufreq_passive_unregister(&p_data);
>>> + else
>>> + ret = -EINVAL;
>>
>> ditto. unregister_parent_dev_notifier(struct devfreq_passive_data **p_data)
> Get it.
ditto. As I aboved commented.
>>
>>> break;
>>> default:
>>> break;
>>> diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
>>> index a4b19d593151..04ce576fd6f1 100644
>>> --- a/include/linux/devfreq.h
>>> +++ b/include/linux/devfreq.h
>>> @@ -278,6 +278,32 @@ struct devfreq_simple_ondemand_data {
>>>
>>> #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
>>> /**
>>> + * struct devfreq_cpu_state - holds the per-cpu state
>>> + * @freq: the current frequency of the cpu.
>>> + * @min_freq: the min frequency of the cpu.
>>> + * @max_freq: the max frequency of the cpu.
>>> + * @first_cpu: the cpumask of the first cpu of a policy.
>>> + * @dev: reference to cpu device.
>>> + * @opp_table: reference to cpu opp table.
>>> + *
>>> + * This structure stores the required cpu_state of a cpu.
>>> + * This is auto-populated by the governor.
>>> + */
>>> +struct devfreq_cpu_state {> + unsigned int freq;
>>
>> It is better to change from 'freq' to 'curr_freq'
>> for more correct expression.
> Get it.
>>
>>> + unsigned int min_freq;
>>> + unsigned int max_freq;
>>> + unsigned int first_cpu;
>>> + struct device *dev;
>>
>> How about changing the name 'dev' to 'cpu_dev'?
> Okay.
>>
>>
>>> + struct opp_table *opp_table;
>>> +};
>>
>> devfreq_cpu_state is only handled by within driver/devfreq/governor_passive.c.
>>
>> So, you can move it into drivers/devfreq/governor_passive.c
>> and just add the definition into include/linux/devfreq.h as following:
>> It is able to prevent the access of variable of 'struct devfreq_cpu_state'
>> outside.
>>
>> struct devfreq_cpu_state;
> Get it.
>>
>>> +
>>> +enum devfreq_parent_dev_type {
>>> + DEVFREQ_PARENT_DEV,
>>> + CPUFREQ_PARENT_DEV,
>>> +};
>>> +
>>> +/**
>>> * struct devfreq_passive_data - ``void *data`` fed to struct devfreq
>>> * and devfreq_add_device
>>> * @parent: the devfreq instance of parent device.
>>> @@ -288,13 +314,15 @@ struct devfreq_simple_ondemand_data {
>>> * using governors except for passive governor.
>>> * If the devfreq device has the specific method to decide
>>> * the next frequency, should use this callback.
>>> - * @this: the devfreq instance of own device.
>>> - * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
>>> + * @parent_type parent type of the device
>>
>> Need to add ':' at the end of word. -> "parent_type:".
>>
>>> + * @this: the devfreq instance of own device.
>>> + * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
>>
>> I knew that you make them with same indentation.
>> But, actually, it is not related to this patch like clean-up code.
>> Even if it is not pretty, you better to don't touch 'this' and 'nb' indentaion.
> Get it.
>>
>>> + * @cpu_state: the state min/max/current frequency of all online cpu's
>>> *
>>> * The devfreq_passive_data have to set the devfreq instance of parent
>>> * device with governors except for the passive governor. But, don't need to
>>> - * initialize the 'this' and 'nb' field because the devfreq core will handle
>>> - * them.
>>> + * initialize the 'this', 'nb' and 'cpu_state' field because the devfreq core
>>> + * will handle them.
>>> */
>>> struct devfreq_passive_data {
>>> /* Should set the devfreq instance of parent device */
>>> @@ -303,9 +331,13 @@ struct devfreq_passive_data {
>>> /* Optional callback to decide the next frequency of passvice device */
>>> int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
>>>
>>> + /* Should set the type of parent device */
>>> + enum devfreq_parent_dev_type parent_type;
>>> +
>>> /* For passive governor's internal use. Don't need to set them */
>>> struct devfreq *this;
>>> struct notifier_block nb;
>>> + struct devfreq_cpu_state *cpu_state[NR_CPUS];
>>> };
>>> #endif
>>>
>>>
>>
>>
>
--
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Macpaul Lin @ 2020-06-03 3:05 UTC (permalink / raw)
To: Takashi Iwai
Cc: alsa-devel, Mediatek WSD Upstream, linux-kernel, linux-usb,
Johan Hovold, Takashi Iwai, Hui Wang, Alexander Tsoy,
linux-mediatek, Greg Kroah-Hartman, Matthias Brugger, Macpaul Lin,
Jaroslav Kysela, Szabolcs Szőke, linux-arm-kernel
In-Reply-To: <s5hpnahhbz8.wl-tiwai@suse.de>
On Tue, 2020-06-02 at 14:46 +0200, Takashi Iwai wrote:
> On Tue, 02 Jun 2020 13:53:41 +0200,
> Macpaul Lin wrote:
> >
> > This patch fix incorrect power state changed by usb_audio_suspend()
> > when CONFIG_PM is enabled.
> >
> > After receiving suspend PM message with auto flag, usb_audio_suspend()
> > change card's power state to SNDRV_CTL_POWER_D3hot. Only when the other
> > resume PM message with auto flag can change power state to
> > SNDRV_CTL_POWER_D0 in __usb_audio_resume().
> >
> > However, when system is not under auto suspend, resume PM message with
> > auto flag might not be able to receive on time which cause the power
> > state was incorrect. At this time, if a player starts to play sound,
> > will cause snd_usb_pcm_open() to access the card and setup_hw_info() will
> > resume the card.
> >
> > But even the card is back to work and all function normal, the power
> > state is still in SNDRV_CTL_POWER_D3hot.
>
> Hm, in exactly which situation does this happen? I still don't get
> it. Could you elaborate how to trigger this?
I'm not sure if this will happen on laptop or on PC.
We've found this issue on Android phone (I'm not sure if each Android
phone can reproduce this.).
After booting the android phone, insert type-c headset without charging
and play music at any duration, say, 1 second, then stop. Put phone away
to idle about 17~18 minutes. Wait auto pm happened and the power state
change to SNDRV_CTL_POWER_D3hot in sound/usb/card.c. Then wake up the
phone, play music again. Then you'll probably found the music was not
playing and the progress bar keep at the same position. It only happen
when power state is SNDRV_CTL_POWER_D3hot. If not (the power state is
SNDRV_CTL_POWER_D0), repeat the steps for several times, then it will be
produced at some time.
When it happened, sound_usb_pcm_open() will wake up the sound card by
setup_hw_info()->__usb_audio_resume(). However, the card and the
interface is function properly right now, the power state keeps remain
SNDRV_CTL_POWER_D3hot. The suggestive parameter settings from upper
sound request will be pending since later snd_power_wait() call will
still wait the card awaken. Ideally, auto PM should be recovered by
sound card itself. But once the card is awaken at this circumstance, it
looks like there are not more auto pm event. And the sound system of
this interface will stuck here forever until user plug out the headset
(reset the hardware).
The root cause is that once the card has been resumed, it should inform
auto pm change the state back into SNDRV_CTL_POWER_D0 and mark the
device is using by some one.
> > Which cause the infinite loop
> > happened in snd_power_wait() to check the power state. Thus the
> > successive setting ioctl cannot be passed to card.
> >
> > Hence we suggest to change power state to SNDRV_CTL_POWER_D0 when card
> > has been resumed successfully.
>
> This doesn't look like a right solution for the problem, sorry.
> The card PM status must be recovered to D0 when the autoresume
> succeeds. If not, something is broken there, and it must be fixed
> instead of fiddling the status flag externally.
Yes, I agreed, but after checking the code in sound drivers,
it looks like there is only chance that auto pm triggered by low-level
code in sound/usb/card.c. In kernel 4.14, auto pm suspend is triggered
by snd_pcm_suspend_all(). In later kernel, it is triggered by
snd_usb_pcm_suspend(). However, it looks like there are no any resume
trigger to recover auto pm state when the card has been waken by
sound_usb_pcm_open(). The remain resume trigger in
sound/core/pcm_native.c were all static. I've tried to use these resume
function in sound/usb/card.c but it seems cannot get better result than
changing the power state when sound card is in use.
I've replied another mail earlier includes debug patch and the other
work around to verify this issue. The issue has been found on
kernel-4.14, but check the code logic here in sound/usb/card.c and
sound/usb/pcm.c, I think the same problem still existed in 4.19, 5.4
(used by android), and in current kernel tree.
> thanks,
>
> Takashi
If the above explanation were not clear enough, I'll try my best to
explain it in more detail. Maybe the better way is to send both auto pm
resume and runtime resume when sound_usb_pcm_open() is called. But
according to the current codes in card.c, we might need to call
__usb_audio_resume() twice in setup_hw_info().
Thanks
Macpaul Lin
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] scsi: ufs: Remove redundant urgent_bkop_lvl initialization
From: Martin K. Petersen @ 2020-06-03 2:31 UTC (permalink / raw)
To: avri.altman, linux-scsi, Stanley Chu, alim.akhtar, jejb
Cc: bvanassche, Martin K . Petersen, andy.teng, cc.chou, chun-hung.wu,
kuohong.wang, peter.wang, linux-kernel, cang, linux-mediatek,
chaotian.jing, matthias.bgg, asutoshd, linux-arm-kernel, beanhuo
In-Reply-To: <20200530141200.4616-1-stanley.chu@mediatek.com>
On Sat, 30 May 2020 22:12:00 +0800, Stanley Chu wrote:
> In ufshcd_probe_hba(), all BKOP SW tracking variables can be reset
> together in ufshcd_force_reset_auto_bkops(), thus urgent_bkop_lvl
> initialization in the beginning of ufshcd_probe_hba() can be merged
> into ufshcd_force_reset_auto_bkops().
Applied to 5.8/scsi-queue, thanks!
[1/1] scsi: ufs: Remove redundant urgent_bkop_lvl initialization
https://git.kernel.org/mkp/scsi/c/7b6668d8b806
--
Martin K. Petersen Oracle Linux Engineering
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH v2 00/33] iommu: Move iommu_group setup to IOMMU core code
From: Jerry Snitselaar @ 2020-06-02 21:17 UTC (permalink / raw)
To: Joerg Roedel, Lu Baolu, Will Deacon, Robin Murphy,
Marek Szyprowski, Kukjin Kim, Krzysztof Kozlowski,
David Woodhouse, Andy Gross, Bjorn Andersson, Matthias Brugger,
Rob Clark, Heiko Stuebner, Gerald Schaefer, Thierry Reding,
Jonathan Hunter, Jean-Philippe Brucker, linux-s390,
linux-samsung-soc, linux-arm-msm, linux-kernel, virtualization,
linux-rockchip, iommu, linux-mediatek, linux-tegra
In-Reply-To: <20200602163806.o5dpj2tpemwdzyiw@cantor>
On Tue Jun 02 20, Jerry Snitselaar wrote:
>On Tue Jun 02 20, Joerg Roedel wrote:
>>Hi Jerry,
>>
>>On Mon, Jun 01, 2020 at 05:02:36PM -0700, Jerry Snitselaar wrote:
>>>
>>>Yeah, that will solve the panic.
>>>
>>
>>If you still see the kdump faults, can you please try with the attached
>>diff? I was not able to reproduce them in my setup.
>>
>>Regards,
>>
>> Joerg
>>
>
>I have another hp proliant server now, and reproduced. I will have the
>patch below tested shortly. Minor change, I switched group->domain to
>domain since group isn't an argument, and *data being passed in comes
>from group->domain anyways.
>
Looks like it solves problem for both the epyc system, and the hp proliant
server,
>>diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>>index b5ea203f6c68..5a6d509f72b6 100644
>>--- a/drivers/iommu/iommu.c
>>+++ b/drivers/iommu/iommu.c
>>@@ -1680,8 +1680,12 @@ static void probe_alloc_default_domain(struct bus_type *bus,
>>static int iommu_group_do_dma_attach(struct device *dev, void *data)
>>{
>> struct iommu_domain *domain = data;
>>+ int ret = 0;
>>
>>- return __iommu_attach_device(domain, dev);
>>+ if (!iommu_is_attach_deferred(group->domain, dev))
>>+ ret = __iommu_attach_device(group->domain, dev);
>>+
>>+ return ret;
>>}
>>
>>static int __iommu_group_dma_attach(struct iommu_group *group)
>>_______________________________________________
>>iommu mailing list
>>iommu@lists.linux-foundation.org
>>https://lists.linuxfoundation.org/mailman/listinfo/iommu
>>
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH v2 00/33] iommu: Move iommu_group setup to IOMMU core code
From: Jerry Snitselaar @ 2020-06-02 16:38 UTC (permalink / raw)
To: Joerg Roedel
Cc: Heiko Stuebner, virtualization, linux-tegra, Thierry Reding,
Will Deacon, Marek Szyprowski, Jean-Philippe Brucker,
linux-samsung-soc, iommu, Krzysztof Kozlowski, Jonathan Hunter,
linux-rockchip, Andy Gross, linux-s390, linux-arm-msm,
linux-mediatek, Matthias Brugger, Bjorn Andersson,
Gerald Schaefer, David Woodhouse, linux-kernel, Rob Clark,
Kukjin Kim, Robin Murphy, Lu Baolu
In-Reply-To: <20200602142312.GJ14598@8bytes.org>
On Tue Jun 02 20, Joerg Roedel wrote:
>Hi Jerry,
>
>On Mon, Jun 01, 2020 at 05:02:36PM -0700, Jerry Snitselaar wrote:
>>
>> Yeah, that will solve the panic.
>>
>
>If you still see the kdump faults, can you please try with the attached
>diff? I was not able to reproduce them in my setup.
>
>Regards,
>
> Joerg
>
I have another hp proliant server now, and reproduced. I will have the
patch below tested shortly. Minor change, I switched group->domain to
domain since group isn't an argument, and *data being passed in comes
from group->domain anyways.
>diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>index b5ea203f6c68..5a6d509f72b6 100644
>--- a/drivers/iommu/iommu.c
>+++ b/drivers/iommu/iommu.c
>@@ -1680,8 +1680,12 @@ static void probe_alloc_default_domain(struct bus_type *bus,
> static int iommu_group_do_dma_attach(struct device *dev, void *data)
> {
> struct iommu_domain *domain = data;
>+ int ret = 0;
>
>- return __iommu_attach_device(domain, dev);
>+ if (!iommu_is_attach_deferred(group->domain, dev))
>+ ret = __iommu_attach_device(group->domain, dev);
>+
>+ return ret;
> }
>
> static int __iommu_group_dma_attach(struct iommu_group *group)
>_______________________________________________
>iommu mailing list
>iommu@lists.linux-foundation.org
>https://lists.linuxfoundation.org/mailman/listinfo/iommu
>
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH v2 00/33] iommu: Move iommu_group setup to IOMMU core code
From: Joerg Roedel @ 2020-06-02 14:23 UTC (permalink / raw)
To: Lu Baolu, Will Deacon, Robin Murphy, Marek Szyprowski, Kukjin Kim,
Krzysztof Kozlowski, David Woodhouse, Andy Gross, Bjorn Andersson,
Matthias Brugger, Rob Clark, Heiko Stuebner, Gerald Schaefer,
Thierry Reding, Jonathan Hunter, Jean-Philippe Brucker,
linux-s390, linux-samsung-soc, linux-arm-msm, linux-kernel,
virtualization, linux-rockchip, iommu, linux-mediatek,
linux-tegra
In-Reply-To: <20200602000236.j4m3jvluzdhjngdc@cantor>
Hi Jerry,
On Mon, Jun 01, 2020 at 05:02:36PM -0700, Jerry Snitselaar wrote:
>
> Yeah, that will solve the panic.
>
If you still see the kdump faults, can you please try with the attached
diff? I was not able to reproduce them in my setup.
Regards,
Joerg
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index b5ea203f6c68..5a6d509f72b6 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1680,8 +1680,12 @@ static void probe_alloc_default_domain(struct bus_type *bus,
static int iommu_group_do_dma_attach(struct device *dev, void *data)
{
struct iommu_domain *domain = data;
+ int ret = 0;
- return __iommu_attach_device(domain, dev);
+ if (!iommu_is_attach_deferred(group->domain, dev))
+ ret = __iommu_attach_device(group->domain, dev);
+
+ return ret;
}
static int __iommu_group_dma_attach(struct iommu_group *group)
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related
* Re: Security Random Number Generator support
From: Marc Zyngier @ 2020-06-02 13:02 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman, Sean Wang, lkml,
wsd_upstream, Crystal Guo, Rob Herring, Neal Liu,
Linux Crypto Mailing List, Matt Mackall, Matthias Brugger,
linux-mediatek, Linux ARM
In-Reply-To: <CAMj1kXHjAdk5=-uSh_=S9j5cz42zr3h6t+YYGy+obevuQDp0fg@mail.gmail.com>
On 2020-06-02 13:14, Ard Biesheuvel wrote:
> On Tue, 2 Jun 2020 at 10:15, Neal Liu <neal.liu@mediatek.com> wrote:
>>
>> These patch series introduce a security random number generator
>> which provides a generic interface to get hardware rnd from Secure
>> state. The Secure state can be Arm Trusted Firmware(ATF), Trusted
>> Execution Environment(TEE), or even EL2 hypervisor.
>>
>> Patch #1..2 adds sec-rng kernel driver for Trustzone based SoCs.
>> For security awareness SoCs on ARMv8 with TrustZone enabled,
>> peripherals like entropy sources is not accessible from normal world
>> (linux) and rather accessible from secure world (HYP/ATF/TEE) only.
>> This driver aims to provide a generic interface to Arm Trusted
>> Firmware or Hypervisor rng service.
>>
>>
>> changes since v1:
>> - rename mt67xx-rng to mtk-sec-rng since all MediaTek ARMv8 SoCs can
>> reuse
>> this driver.
>> - refine coding style and unnecessary check.
>>
>> changes since v2:
>> - remove unused comments.
>> - remove redundant variable.
>>
>> changes since v3:
>> - add dt-bindings for MediaTek rng with TrustZone enabled.
>> - revise HWRNG SMC call fid.
>>
>> changes since v4:
>> - move bindings to the arm/firmware directory.
>> - revise driver init flow to check more property.
>>
>> changes since v5:
>> - refactor to more generic security rng driver which
>> is not platform specific.
>>
>> *** BLURB HERE ***
>>
>> Neal Liu (2):
>> dt-bindings: rng: add bindings for sec-rng
>> hwrng: add sec-rng driver
>>
>
> There is no reason to model a SMC call as a driver, and represent it
> via a DT node like this.
+1.
> It would be much better if this SMC interface is made truly generic,
> and wired into the arch_get_random() interface, which can be used much
> earlier.
Wasn't there a plan to standardize a SMC call to rule them all?
M.
--
Who you jivin' with that Cosmik Debris?
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Takashi Iwai @ 2020-06-02 12:46 UTC (permalink / raw)
To: Macpaul Lin
Cc: alsa-devel, Mediatek WSD Upstream, linux-kernel, linux-usb,
Johan Hovold, Takashi Iwai, Hui Wang, Alexander Tsoy,
linux-mediatek, Matthias Brugger, Macpaul Lin, Jaroslav Kysela,
Szabolcs Szőke, linux-arm-kernel
In-Reply-To: <1591098821-17910-1-git-send-email-macpaul.lin@mediatek.com>
On Tue, 02 Jun 2020 13:53:41 +0200,
Macpaul Lin wrote:
>
> This patch fix incorrect power state changed by usb_audio_suspend()
> when CONFIG_PM is enabled.
>
> After receiving suspend PM message with auto flag, usb_audio_suspend()
> change card's power state to SNDRV_CTL_POWER_D3hot. Only when the other
> resume PM message with auto flag can change power state to
> SNDRV_CTL_POWER_D0 in __usb_audio_resume().
>
> However, when system is not under auto suspend, resume PM message with
> auto flag might not be able to receive on time which cause the power
> state was incorrect. At this time, if a player starts to play sound,
> will cause snd_usb_pcm_open() to access the card and setup_hw_info() will
> resume the card.
>
> But even the card is back to work and all function normal, the power
> state is still in SNDRV_CTL_POWER_D3hot.
Hm, in exactly which situation does this happen? I still don't get
it. Could you elaborate how to trigger this?
> Which cause the infinite loop
> happened in snd_power_wait() to check the power state. Thus the
> successive setting ioctl cannot be passed to card.
>
> Hence we suggest to change power state to SNDRV_CTL_POWER_D0 when card
> has been resumed successfully.
This doesn't look like a right solution for the problem, sorry.
The card PM status must be recovered to D0 when the autoresume
succeeds. If not, something is broken there, and it must be fixed
instead of fiddling the status flag externally.
thanks,
Takashi
>
> Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
> ---
> sound/usb/pcm.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index a4e4064..d667ecb 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -1322,6 +1322,17 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
> if (err < 0)
> return err;
>
> + /* fix incorrect power state when resuming by open and later ioctls */
> + if (IS_ENABLED(CONFIG_PM) &&
> + snd_power_get_state(subs->stream->chip->card)
> + == SNDRV_CTL_POWER_D3hot) {
> + /* set these variables for power state correction */
> + subs->stream->chip->autosuspended = 0;
> + subs->stream->chip->num_suspended_intf = 1;
> + dev_info(&subs->dev->dev,
> + "change power state from D3hot to D0\n");
> + }
> +
> return snd_usb_autoresume(subs->stream->chip);
> }
>
> --
> 1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH 06/12] PM / devfreq: Add cpu based scaling support to passive_governor
From: andrew-sh.cheng @ 2020-06-02 12:23 UTC (permalink / raw)
To: Chanwoo Choi
Cc: Mark Rutland, Nishanth Menon, srv_heupstream, devicetree,
Stephen Boyd, Viresh Kumar, Mark Brown, linux-pm,
Rafael J . Wysocki, Liam Girdwood, Rob Herring, linux-kernel,
Kyungmin Park, MyungJoo Ham, linux-mediatek, Sibi Sankar,
Matthias Brugger, linux-arm-kernel
In-Reply-To: <7ad35770-9327-084a-d2ca-1646cabd0a4d@samsung.com>
On Thu, 2020-05-28 at 16:17 +0900, Chanwoo Choi wrote:
> Hi Andrew-sh.Cheng,
>
> The exynos-bus.c used the passive governor.
> Even if don't make the problem because DEVFREQ_PARENT_DEV is zero,
> you need to initialize the parent_type with DEVFREQ_PARENT_DEV as following:
>
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 8fa8eb541373..1c71c47bc2ac 100644
> --- a/drivers/devfreq/exynos-bus.c
> +++ b/drivers/devfreq/exynos-bus.c
> @@ -369,6 +369,7 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> return -ENOMEM;
>
> passive_data->parent = parent_devfreq;
> + passive_data->parent_type = DEVFREQ_PARENT_DEV;
>
> /* Add devfreq device for exynos bus with passive governor */
> bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
Hi Chanwoo Choi,
Do you just remind me to initialize it to DEVFREQ_PARENT_DEV whn use
this governor?
I will do it and thank you for reminding.
>
>
> On 5/28/20 3:14 PM, Chanwoo Choi wrote:
> > Hi Andrew-sh.Cheng,
> >
> > Thanks for your posting. I like this approach absolutely.
> > I think that it is necessary. When I developed the embedded product,
> > I needed this feature always.
> >
> > I add the comments on below.
> >
> >
> > And the following email is not valid. So, I dropped this email
> > from Cc list.
> > Saravana Kannan <skannan@codeaurora.org>
> >
> >
> > On 5/20/20 12:43 PM, Andrew-sh.Cheng wrote:
> >> From: Saravana Kannan <skannan@codeaurora.org>
> >>
> >> Many CPU architectures have caches that can scale independent of the
> >> CPUs. Frequency scaling of the caches is necessary to make sure that the
> >> cache is not a performance bottleneck that leads to poor performance and
> >> power. The same idea applies for RAM/DDR.
> >>
> >> To achieve this, this patch adds support for cpu based scaling to the
> >> passive governor. This is accomplished by taking the current frequency
> >> of each CPU frequency domain and then adjust the frequency of the cache
> >> (or any devfreq device) based on the frequency of the CPUs. It listens
> >> to CPU frequency transition notifiers to keep itself up to date on the
> >> current CPU frequency.
> >>
> >> To decide the frequency of the device, the governor does one of the
> >> following:
> >> * Derives the optimal devfreq device opp from required-opps property of
> >> the parent cpu opp_table.
> >>
> >> * Scales the device frequency in proportion to the CPU frequency. So, if
> >> the CPUs are running at their max frequency, the device runs at its
> >> max frequency. If the CPUs are running at their min frequency, the
> >> device runs at its min frequency. It is interpolated for frequencies
> >> in between.
> >>
> >> Andrew-sh.Cheng change
> >> dev_pm_opp_xlate_opp to dev_pm_opp_xlate_required_opp devfreq->max_freq
> >> to devfreq->user_min_freq_req.data.freq.qos->min_freq.target_value
> >> for kernel-5.7
> >>
> >> Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
> >> [Sibi: Integrated cpu-freqmap governor into passive_governor]
> >> Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
> >> Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
> >> ---
> >> drivers/devfreq/Kconfig | 2 +
> >> drivers/devfreq/governor_passive.c | 278 ++++++++++++++++++++++++++++++++++---
> >> include/linux/devfreq.h | 40 +++++-
> >> 3 files changed, 299 insertions(+), 21 deletions(-)
> >>
> >> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> >> index 0b1df12e0f21..d9067950af6a 100644
> >> --- a/drivers/devfreq/Kconfig
> >> +++ b/drivers/devfreq/Kconfig
> >> @@ -73,6 +73,8 @@ config DEVFREQ_GOV_PASSIVE
> >> device. This governor does not change the frequency by itself
> >> through sysfs entries. The passive governor recommends that
> >> devfreq device uses the OPP table to get the frequency/voltage.
> >> + Alternatively the governor can also be chosen to scale based on
> >> + the online CPUs current frequency.
> >>
> >> comment "DEVFREQ Drivers"
> >>
> >> diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
> >> index 2d67d6c12dce..7dcda02a5bb7 100644
> >> --- a/drivers/devfreq/governor_passive.c
> >> +++ b/drivers/devfreq/governor_passive.c
> >> @@ -8,11 +8,89 @@
> >> */
> >>
> >> #include <linux/module.h>
> >> +#include <linux/cpu.h>
> >> +#include <linux/cpufreq.h>
> >> +#include <linux/cpumask.h>
> >> #include <linux/device.h>
> >> #include <linux/devfreq.h>
> >> +#include <linux/slab.h>
> >> #include "governor.h"
> >>
> >> -static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
> >> +static unsigned int xlate_cpufreq_to_devfreq(struct devfreq_passive_data *data,
> >
> > Need to change 'unsigned int' to 'unsigned long'.
> >
> >> + unsigned int cpu)
> >> +{
> >> + unsigned int cpu_min, cpu_max, dev_min, dev_max, cpu_percent, max_state;
> >
> > Better to define them separately as following and then need to rename
> > the variable. Usually, use the 'min_freq' and 'max_freq' word for
> > the minimum/maximum frequency.
> >
> > unsigned int cpu_min_freq, cpu_max_freq, cpu_curr_freq, cpu_percent;
> > unsigned long dev_min_freq, dev_max_freq, dev_max_state,
> >
> > The devfreq used 'unsigned long'. The cpufreq used 'unsigned long'
> > and 'unsigned int'. You need to handle them properly.
> >
> >
> >> + struct devfreq_cpu_state *cpu_state = data->cpu_state[cpu];
> >> + struct devfreq *devfreq = (struct devfreq *)data->this;
> >> + unsigned long *freq_table = devfreq->profile->freq_table;
> >
> > In this function, use 'cpu' work for cpufreq and use 'dev' for devfreq.
> > So, I think 'dev_freq_table' is proper name instead of 'freq_table'
> > for the readability.
> >
> > freq_table -> dev_freq_table
> >
> >> + struct dev_pm_opp *opp = NULL, *cpu_opp = NULL;
> >
> > In the get_target_freq_with_devfreq(), use 'p_opp' indicating
> > the OPP of parent device. For the consistency, I think that
> > use 'p_opp' instead of 'cpu_opp'.
> >
> >> + unsigned long cpu_freq, freq;
> >
> > Define the 'cpu_freq' on above with cpu_min_freq/cpu_max_freq definition.
> > cpu_freq -> cpu_curr_freq.
> >
> >> +
> >> + if (!cpu_state || cpu_state->first_cpu != cpu ||
> >> + !cpu_state->opp_table || !devfreq->opp_table)
> >> + return 0;
> >> +
> >> + cpu_freq = cpu_state->freq * 1000;
> >> + cpu_opp = devfreq_recommended_opp(cpu_state->dev, &cpu_freq, 0);
> >> + if (IS_ERR(cpu_opp))
> >> + return 0;
> >> +
> >> + opp = dev_pm_opp_xlate_required_opp(cpu_state->opp_table,
> >> + devfreq->opp_table, cpu_opp);
> >> + dev_pm_opp_put(cpu_opp);
> >> +
> >> + if (!IS_ERR(opp)) {
> >> + freq = dev_pm_opp_get_freq(opp);
> >> + dev_pm_opp_put(opp);
> >
> > Better to add the 'out' goto statement.
> > If you use 'goto out', you can reduce the one indentation
> > without 'else' statement.
> >
> >
> >> + } else {
> >
> > As I commented, when dev_pm_opp_xlate_required_opp() return successfully
> > , use 'goto out'. We can remove 'else' and then reduce the unneeded indentation.
> >
> >
> >> + /* Use Interpolation if required opps is not available */
> >> + cpu_min = cpu_state->min_freq;
> >> + cpu_max = cpu_state->max_freq;
> >> + cpu_freq = cpu_state->freq;
> >> +
> >> + if (freq_table) {
> >> + /* Get minimum frequency according to sorting order */
> >> + max_state = freq_table[devfreq->profile->max_state - 1];
> >> + if (freq_table[0] < max_state) {
> >> + dev_min = freq_table[0];
> >> + dev_max = max_state;
> >> + } else {
> >> + dev_min = max_state;
> >> + dev_max = freq_table[0];
> >> + }
> >> + } else {
> >> + if (devfreq->user_max_freq_req.data.freq.qos->max_freq.target_value
> >> + <= devfreq->user_min_freq_req.data.freq.qos->min_freq.target_value)
> >> + return 0;
> >> + dev_min =
> >> + devfreq->user_min_freq_req.data.freq.qos->min_freq.target_value;
> >> + dev_max =
> >> + devfreq->user_max_freq_req.data.freq.qos->max_freq.target_value;
> >
> > I think it is not proper to access the variable of pm_qos structure directly.
> > Instead of direct access, you have to use the exported PM QoS function such as
> > - pm_qos_read_value(devfreq->dev.parent, DEV_PM_QOS_MIN_FREQUENCY);
> > - pm_qos_read_value(devfreq->dev.parent, DEV_PM_QOS_MAX_FREQUENCY);
> >
> >> + }
> >> + cpu_percent = ((cpu_freq - cpu_min) * 100) / cpu_max - cpu_min;
> >> + freq = dev_min + mult_frac(dev_max - dev_min, cpu_percent, 100);
> >> + }
> >
> >
> > I think that you better to add 'out' jump label as following:
> >
> > out:
> >
> >> +
> >> + return freq;
> >> +}
> >> +
> >> +static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
> >> + unsigned long *freq)
> >> +{
> >> + struct devfreq_passive_data *p_data =
> >> + (struct devfreq_passive_data *)devfreq->data;
> >> + unsigned int cpu, target_freq = 0;
> >
> > Need to define 'target_freq' with 'unsigned long' type.
> >
> >> +
> >> + for_each_online_cpu(cpu)
> >> + target_freq = max(target_freq,
> >> + xlate_cpufreq_to_devfreq(p_data, cpu));
> >> +
> >> + *freq = target_freq;
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int get_target_freq_with_devfreq(struct devfreq *devfreq,
> >> unsigned long *freq)
> >> {
> >> struct devfreq_passive_data *p_data
> >> @@ -23,16 +101,6 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
> >> int i, count, ret = 0;
> >>
> >> /*
> >> - * If the devfreq device with passive governor has the specific method
> >> - * to determine the next frequency, should use the get_target_freq()
> >> - * of struct devfreq_passive_data.
> >> - */
> >> - if (p_data->get_target_freq) {
> >> - ret = p_data->get_target_freq(devfreq, freq);
> >> - goto out;
> >> - }
> >> -
> >> - /*
> >> * If the parent and passive devfreq device uses the OPP table,
> >> * get the next frequency by using the OPP table.
> >> */
> >> @@ -102,6 +170,37 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
> >> return ret;
> >> }
> >>
> >> +static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
> >> + unsigned long *freq)
> >> +{
> >> + struct devfreq_passive_data *p_data =
> >> + (struct devfreq_passive_data *)devfreq->data;
> >> + int ret;
> >> +
> >> + /*
> >> + * If the devfreq device with passive governor has the specific method
> >> + * to determine the next frequency, should use the get_target_freq()
> >> + * of struct devfreq_passive_data.
> >> + */
> >> + if (p_data->get_target_freq)
> >> + return p_data->get_target_freq(devfreq, freq);
> >> +
> >> + switch (p_data->parent_type) {
> >> + case DEVFREQ_PARENT_DEV:
> >> + ret = get_target_freq_with_devfreq(devfreq, freq);
> >> + break;
> >> + case CPUFREQ_PARENT_DEV:
> >> + ret = get_target_freq_with_cpufreq(devfreq, freq);
> >> + break;
> >> + default:
> >> + ret = -EINVAL;
> >> + dev_err(&devfreq->dev, "Invalid parent type\n");
> >> + break;
> >> + }
> >> +
> >> + return ret;
> >> +}
> >> +
> >> static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq)
> >> {
> >> int ret;
> >> @@ -156,6 +255,140 @@ static int devfreq_passive_notifier_call(struct notifier_block *nb,
> >> return NOTIFY_DONE;
> >> }
> >>
> >> +static int cpufreq_passive_notifier_call(struct notifier_block *nb,
> >> + unsigned long event, void *ptr)
> >> +{
> >> + struct devfreq_passive_data *data =
> >> + container_of(nb, struct devfreq_passive_data, nb);
> >> + struct devfreq *devfreq = (struct devfreq *)data->this;
> >> + struct devfreq_cpu_state *cpu_state;
> >> + struct cpufreq_freqs *freq = ptr;
> >
> > How about changing 'freq' to 'cpu_freqs'?
> >
> > In the drivers/cpufreq/cpufreq.c, use 'freqs' name indicating
> > the instance of 'struct cpufreq_freqs'. And in order to
> > identfy, how about adding 'cpu_' prefix for variable name?
> >
> >> + unsigned int current_freq;
> >
> > Need to define curr_freq with 'unsigned long' type
> > and better to use 'curr_freq' variable name.
> >
> >> + int ret;
> >> +
> >> + if (event != CPUFREQ_POSTCHANGE || !freq ||
> >> + !data->cpu_state[freq->policy->cpu])
> >> + return 0;
> >> +
> >> + cpu_state = data->cpu_state[freq->policy->cpu];
> >> + if (cpu_state->freq == freq->new)
> >> + return 0;
> >> +
> >> + /* Backup current freq and pre-update cpu state freq*/
> >> + current_freq = cpu_state->freq;
> >> + cpu_state->freq = freq->new;
> >> +
> >> + mutex_lock(&devfreq->lock);
> >> + ret = update_devfreq(devfreq);
> >> + mutex_unlock(&devfreq->lock);
> >> + if (ret) {
> >> + cpu_state->freq = current_freq;
> >> + dev_err(&devfreq->dev, "Couldn't update the frequency.\n");
> >> + return ret;
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int cpufreq_passive_register(struct devfreq_passive_data **p_data)
> >> +{
> >> + struct devfreq_passive_data *data = *p_data;
> >> + struct devfreq *devfreq = (struct devfreq *)data->this;
> >> + struct device *dev = devfreq->dev.parent;
> >> + struct opp_table *opp_table = NULL;
> >> + struct devfreq_cpu_state *state;
> >
> > For the readability, I thinkt 'cpu_state' is proper instead of 'state'.
> >
> >> + struct cpufreq_policy *policy;
> >> + struct device *cpu_dev;
> >> + unsigned int cpu;
> >> + int ret;
> >> +
> >> + get_online_cpus();
> >
> > Add blank line.
> >
> >> + data->nb.notifier_call = cpufreq_passive_notifier_call;
> >> + ret = cpufreq_register_notifier(&data->nb,
> >> + CPUFREQ_TRANSITION_NOTIFIER);
> >> + if (ret) {
> >> + dev_err(dev, "Couldn't register cpufreq notifier.\n");
> >> + data->nb.notifier_call = NULL;
> >> + goto out;
> >> + }
> >> +
> >> + /* Populate devfreq_cpu_state */
> >> + for_each_online_cpu(cpu) {
> >> + if (data->cpu_state[cpu])
> >> + continue;
> >> +
> >> + policy = cpufreq_cpu_get(cpu);
> >
> > cpufreq_cpu_get() might return 'NULL'. I think you need to handle
> > return value as following:
> >
> > if (!policy) {
> > ret = -EINVAL;
> > goto out;
> > } else if (PTR_ERR(policy) == -EPROBE_DEFER) {
> > goto out;
> > } else if (IS_ERR(policy) {
> > ret = PTR_ERR(policy);
> > dev_err(dev, "Couldn't get the cpufreq_poliy.\n");
> > goto out;
> > }
> >
> > If cpufreq_cpu_get() return successfully, to do next.
> > It reduces the one indentaion.
> >
> >
> >
> >> + if (policy) {
> >> + state = kzalloc(sizeof(*state), GFP_KERNEL);
> >> + if (!state) {
> >> + ret = -ENOMEM;
> >> + goto out;
> >> + }
> >> +
> >> + cpu_dev = get_cpu_device(cpu);
> >> + if (!cpu_dev) {
> >> + dev_err(dev, "Couldn't get cpu device.\n");
> >> + ret = -ENODEV;
> >> + goto out;
> >> + }
> >> +
> >> + opp_table = dev_pm_opp_get_opp_table(cpu_dev);
> >> + if (IS_ERR(devfreq->opp_table)) {
> >> + ret = PTR_ERR(opp_table);
> >> + goto out;
> >> + }
> >> +
> >> + state->dev = cpu_dev;
> >> + state->opp_table = opp_table;
> >> + state->first_cpu = cpumask_first(policy->related_cpus);
> >> + state->freq = policy->cur;
> >> + state->min_freq = policy->cpuinfo.min_freq;
> >> + state->max_freq = policy->cpuinfo.max_freq;
> >> + data->cpu_state[cpu] = state;
> >
> > Add blank line.
> >
> >> + cpufreq_cpu_put(policy);
> >> + } else {
> >> + ret = -EPROBE_DEFER;
> >> + goto out;
> >> + }
> >> + }
> >
> > Add blank line.
> >
> >> +out:
> >> + put_online_cpus();
> >> + if (ret)
> >> + return ret;
> >> +
> >> + /* Update devfreq */
> >> + mutex_lock(&devfreq->lock);
> >> + ret = update_devfreq(devfreq);
> >> + mutex_unlock(&devfreq->lock);
> >> + if (ret)
> >> + dev_err(dev, "Couldn't update the frequency.\n");
> >> +
> >> + return ret;
> >> +}
> >> +
> >> +static int cpufreq_passive_unregister(struct devfreq_passive_data **p_data)
> >> +{
> >> + struct devfreq_passive_data *data = *p_data;
> >> + struct devfreq_cpu_state *cpu_state;
> >> + int cpu;
> >> +
> >> + if (data->nb.notifier_call)
> >> + cpufreq_unregister_notifier(&data->nb,
> >> + CPUFREQ_TRANSITION_NOTIFIER);
> >> +
> >> + for_each_possible_cpu(cpu) {
> >> + cpu_state = data->cpu_state[cpu];
> >> + if (cpu_state) {
> >> + if (cpu_state->opp_table)
> >> + dev_pm_opp_put_opp_table(cpu_state->opp_table);
> >> + kfree(cpu_state);
> >> + cpu_state = NULL;
> >> + }
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> static int devfreq_passive_event_handler(struct devfreq *devfreq,
> >> unsigned int event, void *data)
> >> {
> >> @@ -165,7 +398,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
> >> struct notifier_block *nb = &p_data->nb;
> >> int ret = 0;
> >>
> >> - if (!parent)
> >> + if (p_data->parent_type == DEVFREQ_PARENT_DEV && !parent)
> >> return -EPROBE_DEFER;
> >
> > If you modify the devfreq_passive_event_handler() as following,
> > you can move this condition for DEVFREQ_PARENT_DEV into
> > (register|unregister)_parent_dev_notifier.
> >
> > switch (event) {
> > case DEVFREQ_GOV_START:
> > ret = register_parent_dev_notifier(p_data);
> > break;
> > case DEVFREQ_GOV_STOP:
> > ret = unregister_parent_dev_notifier(p_data);
> > break;
> > default:
> > ret = -EINVAL;
> > break;
> > }
> >
> > return ret;
> >
> >>
> >> switch (event) {
> >> @@ -173,13 +406,24 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
> >> if (!p_data->this)
> >> p_data->this = devfreq;
> >>
> >> - nb->notifier_call = devfreq_passive_notifier_call;
> >> - ret = devfreq_register_notifier(parent, nb,
> >> - DEVFREQ_TRANSITION_NOTIFIER);
> >> + if (p_data->parent_type == DEVFREQ_PARENT_DEV) {
> >> + nb->notifier_call = devfreq_passive_notifier_call;
> >> + ret = devfreq_register_notifier(parent, nb,
> >> + DEVFREQ_TRANSITION_NOTIFIER);
> >> + } else if (p_data->parent_type == CPUFREQ_PARENT_DEV) {
> >> + ret = cpufreq_passive_register(&p_data);
> >
> > I think that we better to collect the code related to notifier registration
> > into one function like devfreq_pass_register_notifier() instead of
> > cpufreq_passive_register() as following: I think it is more simple and readable.
> >
> > If you have more proper function name of register_parent_dev_notifier,
> > please give your opinion.
> >
> >
> > int register_parent_dev_notifier(struct devfreq_passive_data **p_data)
> > switch (p_data->parent_type) {
> > case DEVFREQ_PARENT_DEV:
> > nb->notifier_call = devfreq_passive_notifier_call;
> > ret = devfreq_register_notifier(parent, nb,
> > break;
> > case CPUFREQ_PARENT_DEV:
> > cpufreq_register_notifier(...)
> > ...
> > break;
> > }
> >
> >
> >> + } else {
> >> + ret = -EINVAL;
> >> + }
> >> break;
> >> case DEVFREQ_GOV_STOP:
> >> - WARN_ON(devfreq_unregister_notifier(parent, nb,
> >> - DEVFREQ_TRANSITION_NOTIFIER));
> >> + if (p_data->parent_type == DEVFREQ_PARENT_DEV)
> >> + WARN_ON(devfreq_unregister_notifier(parent, nb,
> >> + DEVFREQ_TRANSITION_NOTIFIER));
> >> + else if (p_data->parent_type == CPUFREQ_PARENT_DEV)
> >> + cpufreq_passive_unregister(&p_data);
> >> + else
> >> + ret = -EINVAL;
> >
> > ditto. unregister_parent_dev_notifier(struct devfreq_passive_data **p_data)
> >
> >> break;
> >> default:
> >> break;
> >> diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
> >> index a4b19d593151..04ce576fd6f1 100644
> >> --- a/include/linux/devfreq.h
> >> +++ b/include/linux/devfreq.h
> >> @@ -278,6 +278,32 @@ struct devfreq_simple_ondemand_data {
> >>
> >> #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
> >> /**
> >> + * struct devfreq_cpu_state - holds the per-cpu state
> >> + * @freq: the current frequency of the cpu.
> >> + * @min_freq: the min frequency of the cpu.
> >> + * @max_freq: the max frequency of the cpu.
> >> + * @first_cpu: the cpumask of the first cpu of a policy.
> >> + * @dev: reference to cpu device.
> >> + * @opp_table: reference to cpu opp table.
> >> + *
> >> + * This structure stores the required cpu_state of a cpu.
> >> + * This is auto-populated by the governor.
> >> + */
> >> +struct devfreq_cpu_state {> + unsigned int freq;
> >
> > It is better to change from 'freq' to 'curr_freq'
> > for more correct expression.
> >
> >> + unsigned int min_freq;
> >> + unsigned int max_freq;
> >> + unsigned int first_cpu;
> >> + struct device *dev;
> >
> > How about changing the name 'dev' to 'cpu_dev'?
> >
> >
> >> + struct opp_table *opp_table;
> >> +};
> >
> > devfreq_cpu_state is only handled by within driver/devfreq/governor_passive.c.
> >
> > So, you can move it into drivers/devfreq/governor_passive.c
> > and just add the definition into include/linux/devfreq.h as following:
> > It is able to prevent the access of variable of 'struct devfreq_cpu_state'
> > outside.
> >
> > struct devfreq_cpu_state;
> >
> >> +
> >> +enum devfreq_parent_dev_type {
> >> + DEVFREQ_PARENT_DEV,
> >> + CPUFREQ_PARENT_DEV,
> >> +};
> >> +
> >> +/**
> >> * struct devfreq_passive_data - ``void *data`` fed to struct devfreq
> >> * and devfreq_add_device
> >> * @parent: the devfreq instance of parent device.
> >> @@ -288,13 +314,15 @@ struct devfreq_simple_ondemand_data {
> >> * using governors except for passive governor.
> >> * If the devfreq device has the specific method to decide
> >> * the next frequency, should use this callback.
> >> - * @this: the devfreq instance of own device.
> >> - * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
> >> + * @parent_type parent type of the device
> >
> > Need to add ':' at the end of word. -> "parent_type:".
> >
> >> + * @this: the devfreq instance of own device.
> >> + * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
> >
> > I knew that you make them with same indentation.
> > But, actually, it is not related to this patch like clean-up code.
> > Even if it is not pretty, you better to don't touch 'this' and 'nb' indentaion.
> >
> >> + * @cpu_state: the state min/max/current frequency of all online cpu's
> >> *
> >> * The devfreq_passive_data have to set the devfreq instance of parent
> >> * device with governors except for the passive governor. But, don't need to
> >> - * initialize the 'this' and 'nb' field because the devfreq core will handle
> >> - * them.
> >> + * initialize the 'this', 'nb' and 'cpu_state' field because the devfreq core
> >> + * will handle them.
> >> */
> >> struct devfreq_passive_data {
> >> /* Should set the devfreq instance of parent device */
> >> @@ -303,9 +331,13 @@ struct devfreq_passive_data {
> >> /* Optional callback to decide the next frequency of passvice device */
> >> int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
> >>
> >> + /* Should set the type of parent device */
> >> + enum devfreq_parent_dev_type parent_type;
> >> +
> >> /* For passive governor's internal use. Don't need to set them */
> >> struct devfreq *this;
> >> struct notifier_block nb;
> >> + struct devfreq_cpu_state *cpu_state[NR_CPUS];
> >> };
> >> #endif
> >>
> >>
> >
> >
>
>
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Macpaul Lin @ 2020-06-02 12:19 UTC (permalink / raw)
To: Jaroslav Kysela, Alexander Tsoy, Johan Hovold, Hui Wang,
Szabolcs Szőke, alsa-devel, linux-usb, Mediatek WSD Upstream,
Macpaul Lin, linux-kernel, linux-arm-kernel, linux-mediatek,
Matthias Brugger, Takashi Iwai
In-Reply-To: <1591098821-17910-1-git-send-email-macpaul.lin@mediatek.com>
On Tue, 2020-06-02 at 19:53 +0800, Macpaul Lin wrote:
> This patch fix incorrect power state changed by usb_audio_suspend()
> when CONFIG_PM is enabled.
>
> After receiving suspend PM message with auto flag, usb_audio_suspend()
> change card's power state to SNDRV_CTL_POWER_D3hot. Only when the other
> resume PM message with auto flag can change power state to
> SNDRV_CTL_POWER_D0 in __usb_audio_resume().
>
> However, when system is not under auto suspend, resume PM message with
> auto flag might not be able to receive on time which cause the power
> state was incorrect. At this time, if a player starts to play sound,
> will cause snd_usb_pcm_open() to access the card and setup_hw_info() will
> resume the card.
>
> But even the card is back to work and all function normal, the power
> state is still in SNDRV_CTL_POWER_D3hot. Which cause the infinite loop
> happened in snd_power_wait() to check the power state. Thus the
> successive setting ioctl cannot be passed to card.
>
> Hence we suggest to change power state to SNDRV_CTL_POWER_D0 when card
> has been resumed successfully.
>
> Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
> ---
> sound/usb/pcm.c | 11 +++++++++++linux-usb@vger.kernel.org,
> 1 file changed, 11 insertions(+)
>
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index a4e4064..d667ecb 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -1322,6 +1322,17 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
> if (err < 0)
> return err;
>
> + /* fix incorrect power state when resuming by open and later ioctls */
> + if (IS_ENABLED(CONFIG_PM) &&
> + snd_power_get_state(subs->stream->chip->card)
> + == SNDRV_CTL_POWER_D3hot) {
> + /* set these variables for power state correction */
> + subs->stream->chip->autosuspended = 0;
> + subs->stream->chip->num_suspended_intf = 1;
> + dev_info(&subs->dev->dev,
> + "change power state from D3hot to D0\n");
> + }
> +
> return snd_usb_autoresume(subs->stream->chip);
> }
>
The issue was found on kernel 4.14 (android tree). The test is to add
debug log in sound/core/init.c to check if the power state is
SNDRV_CTL_POWER_D3hot.
diff --git a/sound/core/init.c b/sound/core/init.c
index b02a997..a0bee76 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -1011,6 +1011,8 @@ int snd_power_wait(struct snd_card *card, unsigned
int power_state)
if (snd_power_get_state(card) == power_state)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
+ pr_info("%s snd_power_get_state[%x]\n", __func__,
+ snd_power_get_state(card));
schedule_timeout(30 * HZ);
}
remove_wait_queue(&card->power_sleep, &wait);
After applied a work around by forcing the power state, pcm related
ioctl and parameter settings can be set to usb sound card correctly.
Otherwise a infinite loop will happened in snd_power_wait().
Here is the origin work around for verifying this power state issue on
kernel 4.14.
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 933adcd7af81..9acd50dd7155 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1274,6 +1274,16 @@ static int setup_hw_info(struct snd_pcm_runtime
*runtime, struct snd_usb_substre
if (err < 0)
return err;
+ /* avoid incorrect power state when executing IOCTL */
+ if (IS_ENABLED(CONFIG_PM) &&
+ snd_power_get_state(subs->stream->chip->card)
+ == SNDRV_CTL_POWER_D3hot) {
+ dev_info(&subs->dev->dev,
+ "change power state from D3hot to D0\n");
+ snd_power_change_state(subs->stream->chip->card,
+ SNDRV_CTL_POWER_D0);
+ }
+
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
if (subs->speed == USB_SPEED_FULL)
/* full speed devices have fixed data packet interval */
However, the patch I've send is meant to make sure the power state will
be corrected before snd_usb_autoresume(), It should be adapt to kernel
4.14 and later.
Thanks.
Macpaul Lin
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related
* Re: Security Random Number Generator support
From: Ard Biesheuvel @ 2020-06-02 12:14 UTC (permalink / raw)
To: Neal Liu
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman, Sean Wang, lkml,
wsd_upstream, Rob Herring, linux-mediatek,
Linux Crypto Mailing List, Matt Mackall, Matthias Brugger,
Crystal Guo, Linux ARM
In-Reply-To: <1591085678-22764-1-git-send-email-neal.liu@mediatek.com>
On Tue, 2 Jun 2020 at 10:15, Neal Liu <neal.liu@mediatek.com> wrote:
>
> These patch series introduce a security random number generator
> which provides a generic interface to get hardware rnd from Secure
> state. The Secure state can be Arm Trusted Firmware(ATF), Trusted
> Execution Environment(TEE), or even EL2 hypervisor.
>
> Patch #1..2 adds sec-rng kernel driver for Trustzone based SoCs.
> For security awareness SoCs on ARMv8 with TrustZone enabled,
> peripherals like entropy sources is not accessible from normal world
> (linux) and rather accessible from secure world (HYP/ATF/TEE) only.
> This driver aims to provide a generic interface to Arm Trusted
> Firmware or Hypervisor rng service.
>
>
> changes since v1:
> - rename mt67xx-rng to mtk-sec-rng since all MediaTek ARMv8 SoCs can reuse
> this driver.
> - refine coding style and unnecessary check.
>
> changes since v2:
> - remove unused comments.
> - remove redundant variable.
>
> changes since v3:
> - add dt-bindings for MediaTek rng with TrustZone enabled.
> - revise HWRNG SMC call fid.
>
> changes since v4:
> - move bindings to the arm/firmware directory.
> - revise driver init flow to check more property.
>
> changes since v5:
> - refactor to more generic security rng driver which
> is not platform specific.
>
> *** BLURB HERE ***
>
> Neal Liu (2):
> dt-bindings: rng: add bindings for sec-rng
> hwrng: add sec-rng driver
>
There is no reason to model a SMC call as a driver, and represent it
via a DT node like this.
It would be much better if this SMC interface is made truly generic,
and wired into the arch_get_random() interface, which can be used much
earlier.
> .../devicetree/bindings/rng/sec-rng.yaml | 53 ++++++
> drivers/char/hw_random/Kconfig | 13 ++
> drivers/char/hw_random/Makefile | 1 +
> drivers/char/hw_random/sec-rng.c | 155 ++++++++++++++++++
> 4 files changed, 222 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/rng/sec-rng.yaml
> create mode 100644 drivers/char/hw_random/sec-rng.c
>
> --
> 2.18.0
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* [PATCH] sound: usb: pcm: fix incorrect power state when playing sound after PM_AUTO suspend
From: Macpaul Lin @ 2020-06-02 11:53 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Matthias Brugger, Alexander Tsoy,
Johan Hovold, Hui Wang, Szabolcs Szőke, Macpaul Lin,
alsa-devel, linux-usb
Cc: linux-arm-kernel, Macpaul Lin, linux-mediatek, linux-kernel,
Mediatek WSD Upstream
In-Reply-To: <linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org>
This patch fix incorrect power state changed by usb_audio_suspend()
when CONFIG_PM is enabled.
After receiving suspend PM message with auto flag, usb_audio_suspend()
change card's power state to SNDRV_CTL_POWER_D3hot. Only when the other
resume PM message with auto flag can change power state to
SNDRV_CTL_POWER_D0 in __usb_audio_resume().
However, when system is not under auto suspend, resume PM message with
auto flag might not be able to receive on time which cause the power
state was incorrect. At this time, if a player starts to play sound,
will cause snd_usb_pcm_open() to access the card and setup_hw_info() will
resume the card.
But even the card is back to work and all function normal, the power
state is still in SNDRV_CTL_POWER_D3hot. Which cause the infinite loop
happened in snd_power_wait() to check the power state. Thus the
successive setting ioctl cannot be passed to card.
Hence we suggest to change power state to SNDRV_CTL_POWER_D0 when card
has been resumed successfully.
Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
---
sound/usb/pcm.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index a4e4064..d667ecb 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1322,6 +1322,17 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
if (err < 0)
return err;
+ /* fix incorrect power state when resuming by open and later ioctls */
+ if (IS_ENABLED(CONFIG_PM) &&
+ snd_power_get_state(subs->stream->chip->card)
+ == SNDRV_CTL_POWER_D3hot) {
+ /* set these variables for power state correction */
+ subs->stream->chip->autosuspended = 0;
+ subs->stream->chip->num_suspended_intf = 1;
+ dev_info(&subs->dev->dev,
+ "change power state from D3hot to D0\n");
+ }
+
return snd_usb_autoresume(subs->stream->chip);
}
--
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox