[PATCH v2] pinctrl: pinctrl-imx8mq: Add suspend/resume ops

2019-04-08 Thread Abel Vesa
To support pinctl hog restore after LPSR resume back,
add the generic suspend/resume in pinctrl-imx along with the
generic pm opsto be used by platform specific drivers. Then
make use of the newly added ops in i.MX8MQ platform specific
driver.

Signed-off-by: Robin Gong 
Signed-off-by: Abel Vesa 
---

Changes since v1:
 - Replaced the imx8mq specific ops with generic ones.

 drivers/pinctrl/freescale/pinctrl-imx.c| 25 +
 drivers/pinctrl/freescale/pinctrl-imx.h|  4 
 drivers/pinctrl/freescale/pinctrl-imx8mq.c |  1 +
 3 files changed, 30 insertions(+)

diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c 
b/drivers/pinctrl/freescale/pinctrl-imx.c
index 188001b..ee120ee 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -887,3 +887,28 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 
return ret;
 }
+
+int imx_pinctrl_suspend(struct device *dev)
+{
+   struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+   if (!ipctl)
+   return -EINVAL;
+
+   return pinctrl_force_sleep(ipctl->pctl);
+}
+
+int imx_pinctrl_resume(struct device *dev)
+{
+   struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+   if (!ipctl)
+   return -EINVAL;
+
+   return pinctrl_force_default(ipctl->pctl);
+}
+
+const struct dev_pm_ops imx_pinctrl_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(imx_pinctrl_suspend,
+   imx_pinctrl_resume)
+};
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h 
b/drivers/pinctrl/freescale/pinctrl-imx.h
index 98a4889..ae78314 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -17,6 +17,7 @@
 struct platform_device;
 
 extern struct pinmux_ops imx_pmx_ops;
+extern const struct dev_pm_ops imx_pinctrl_pm_ops;
 
 /**
  * struct imx_pin_mmio - MMIO pin configurations
@@ -136,6 +137,9 @@ struct imx_pinctrl {
 int imx_pinctrl_probe(struct platform_device *pdev,
const struct imx_pinctrl_soc_info *info);
 
+int imx_pinctrl_suspend(struct device *dev);
+int imx_pinctrl_resume(struct device *dev);
+
 #ifdef CONFIG_PINCTRL_IMX_SCU
 #define BM_PAD_CTL_GP_ENABLE   BIT(30)
 #define BM_PAD_CTL_IFMUX_ENABLEBIT(31)
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mq.c 
b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
index 8d39af5..50aa1c0 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx8mq.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
@@ -339,6 +339,7 @@ static struct platform_driver imx8mq_pinctrl_driver = {
.driver = {
.name = "imx8mq-pinctrl",
.of_match_table = of_match_ptr(imx8mq_pinctrl_of_match),
+   .pm = &imx_pinctrl_pm_ops,
.suppress_bind_attrs = true,
},
.probe = imx8mq_pinctrl_probe,
-- 
2.7.4



Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-04 Thread Andy Shevchenko
On Thu, Apr 04, 2019 at 09:06:04PM +0800, Chris Chiu wrote:
> On Wed, Apr 3, 2019 at 9:06 PM Andy Shevchenko
>  wrote:
> > On Wed, Apr 03, 2019 at 03:06:43PM +0800, Chris Chiu wrote:
> > > On Tue, Apr 2, 2019 at 7:58 PM Andy Shevchenko
> > >  wrote:

> > This better to make as a separate helper function
> >
> > static u32 intel_gpio_is_requested(chip, base, size)
> > {
> > u32 requested = 0;
> > unsigned int i;
> >
> > for () {
> > if ()
> > requested |= BIT();
> > }
> > return requested;
> > }
> >
> > (Note u32 as a type)
> >
> 
> Thanks. I made a minor modification for the check function. I think to
> pass a padgroup
> as the argument would be better instead of base, size which I may need
> to check if
> the size > 32 (of course it shouldn't happen) or not.

Group size is never bigger than 32 pins.

The helper should be pure GPIO, that's why I still would like to see base
there. Otherwise it would be layering violation.

> +intel_padgroup_has_gpio_requested(struct gpio_chip *chip,  const
> struct intel_padgroup *gpp)

Namespace is intel_gpio_ here.

> +{
> +   u32 requested = 0;
> +   int i;
> +
> +   if (gpp == NULL)
> +   return 0;
> +
> +   if (gpp->gpio_base < 0)
> +   return 0;
> +
> +   for (i = 0; i < gpp->size; i++)
> +   if (gpiochip_is_requested(chip, gpp->gpio_base + i))
> +   requested |= BIT(i);
> +
> +   return requested;
> +}

> > > +   if (requested) {
> > > +   if (communities[i].hostown[gpp] !=
> > > readl(base + gpp * 4)) {
> > > +
> > > writel(communities[i].hostown[gpp], base + gpp * 4);
> >
> > The idea here not to check this at all, but rather apply a mask.
> >
> > u32 value;
> >
> > ...
> > value = readl();
> > value = (value & ~requested) | (hostown[gpp] & requested);
> > writel(value);
> >
> 
> I made the following per your suggestion. So basically I don't need to show a
> warning for the abnormal HOSTSW_OWN value change? I will submit a formal
> patch for review if there's no big problem for these code logic. Please advise
> if any. Thanks.

You still have all data to produce a warning if it's needed.

((value ^ hostown[gpp]) & requested) will return the changed bits.


> +   base = community->regs + community->hostown_offset;
> +   for (gpp = 0; gpp < community->ngpps; gpp++) {
> +   const struct intel_padgroup *padgrp =
> &community->gpps[i];
> +   u32 requested =
> intel_padgroup_has_gpio_requested(&pctrl->chip, padgrp);
> +

> +   if (requested) {

You may not need this check at all.

> +   u32 value = readl(base + gpp * 4);
> +   u32 saved = communities[i].hostown[gpp];
> +
> +   value = (value & ~requested) | (saved
> & requested);
> +   writel(value, base + gpp * 4);

It's possible to split this as well to another helper function.

static void intel_gpio_update_pad_mode(void __iomem *hostown, u32 mask, u32 
value)
{
...
}

> +   dev_dbg(dev, "restored hostown %d/%u
> %#08x\n", i, gpp,
> +   readl(base + gpp * 4));
> +   }
> +   }

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-04 Thread Chris Chiu
On Wed, Apr 3, 2019 at 9:06 PM Andy Shevchenko
 wrote:
>
> On Wed, Apr 03, 2019 at 03:06:43PM +0800, Chris Chiu wrote:
> > On Tue, Apr 2, 2019 at 7:58 PM Andy Shevchenko
> >  wrote:
>
> > > Instead you may need to loop over each pin in the part of the group 
> > > related to
> > > one 32-bit HOSTSW_OWN register (i.e. 8, see PADOWN_*() macros in the 
> > > driver),
> > > check if it's requested and break a loop. If loop index is off-by-one a 
> > > limit,
> > > nothing to do, otherwise restore hostown register.
> > >
> > > More pedantic approach is to collect the mask inside the loop and apply 
> > > it.
> > >
> > > The check function name is gpiochip_is_requested().
> > >
> > > (One of Intel's drivers which is using that at ->resume() is
> > >  drivers/gpio/gpio-lynxpoint.c)
> > >
> > > P.S. I prefer pedantic approach. The simplification one is showed in 
> > > order to
> > > give you an idea.
>
> > Thanks for your great comment. I remove the useless hostown save function
> > and make the following change in ->resume() to detect and restore the 
> > abnormal
> > HOSTSW_OWN. Please help comment if there're still problems. Thanks.
>
>
> This better to make as a separate helper function
>
> static u32 intel_gpio_is_requested(chip, base, size)
> {
> u32 requested = 0;
> unsigned int i;
>
> for () {
> if ()
> requested |= BIT();
> }
> return requested;
> }
>
> (Note u32 as a type)
>

Thanks. I made a minor modification for the check function. I think to
pass a padgroup
as the argument would be better instead of base, size which I may need
to check if
the size > 32 (of course it shouldn't happen) or not.

+intel_padgroup_has_gpio_requested(struct gpio_chip *chip,  const
struct intel_padgroup *gpp)
+{
+   u32 requested = 0;
+   int i;
+
+   if (gpp == NULL)
+   return 0;
+
+   if (gpp->gpio_base < 0)
+   return 0;
+
+   for (i = 0; i < gpp->size; i++)
+   if (gpiochip_is_requested(chip, gpp->gpio_base + i))
+   requested |= BIT(i);
+
+   return requested;
+}
+
 int intel_pinctrl_resume(struct device *dev)
 {
struct platform_device *pdev = to_platform_device(dev);

> > +   if (requested) {
> > +   if (communities[i].hostown[gpp] !=
> > readl(base + gpp * 4)) {
> > +
> > writel(communities[i].hostown[gpp], base + gpp * 4);
>
> The idea here not to check this at all, but rather apply a mask.
>
> u32 value;
>
> ...
> value = readl();
> value = (value & ~requested) | (hostown[gpp] & requested);
> writel(value);
>

I made the following per your suggestion. So basically I don't need to show a
warning for the abnormal HOSTSW_OWN value change? I will submit a formal
patch for review if there's no big problem for these code logic. Please advise
if any. Thanks.

@@ -1588,6 +1619,22 @@ int intel_pinctrl_resume(struct device *dev)
dev_dbg(dev, "restored mask %d/%u %#08x\n", i, gpp,
readl(base + gpp * 4));
}
+
+   base = community->regs + community->hostown_offset;
+   for (gpp = 0; gpp < community->ngpps; gpp++) {
+   const struct intel_padgroup *padgrp =
&community->gpps[i];
+   u32 requested =
intel_padgroup_has_gpio_requested(&pctrl->chip, padgrp);
+
+   if (requested) {
+   u32 value = readl(base + gpp * 4);
+   u32 saved = communities[i].hostown[gpp];
+
+   value = (value & ~requested) | (saved
& requested);
+   writel(value, base + gpp * 4);
+   dev_dbg(dev, "restored hostown %d/%u
%#08x\n", i, gpp,
+   readl(base + gpp * 4));
+   }
+   }


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-03 Thread Andy Shevchenko
On Wed, Apr 03, 2019 at 03:06:43PM +0800, Chris Chiu wrote:
> On Tue, Apr 2, 2019 at 7:58 PM Andy Shevchenko
>  wrote:

> > Instead you may need to loop over each pin in the part of the group related 
> > to
> > one 32-bit HOSTSW_OWN register (i.e. 8, see PADOWN_*() macros in the 
> > driver),
> > check if it's requested and break a loop. If loop index is off-by-one a 
> > limit,
> > nothing to do, otherwise restore hostown register.
> >
> > More pedantic approach is to collect the mask inside the loop and apply it.
> >
> > The check function name is gpiochip_is_requested().
> >
> > (One of Intel's drivers which is using that at ->resume() is
> >  drivers/gpio/gpio-lynxpoint.c)
> >
> > P.S. I prefer pedantic approach. The simplification one is showed in order 
> > to
> > give you an idea.

> Thanks for your great comment. I remove the useless hostown save function
> and make the following change in ->resume() to detect and restore the abnormal
> HOSTSW_OWN. Please help comment if there're still problems. Thanks.

> +   base = community->regs + community->hostown_offset;
> +   for (gpp = 0; gpp < community->ngpps; gpp++) {
> +   const struct intel_padgroup *padgrp =
> &community->gpps[i];
> +   unsigned int requested = 0;
> +   int j;
> +
> +   if (padgrp->gpio_base < 0)
> +   continue;

> +
> +   for (j = 0; j < padgrp->size; j++)
> +   if
> (gpiochip_is_requested(&pctrl->chip, padgrp->gpio_base + j))
> +   requested |= BIT(j);
> +

This better to make as a separate helper function

static u32 intel_gpio_is_requested(chip, base, size)
{
u32 requested = 0;
unsigned int i;

for () {
if ()
requested |= BIT();
}
return requested;
}

(Note u32 as a type)

> +   if (requested) {
> +   if (communities[i].hostown[gpp] !=
> readl(base + gpp * 4)) {
> +
> writel(communities[i].hostown[gpp], base + gpp * 4);

The idea here not to check this at all, but rather apply a mask.

u32 value;

...
value = readl();
value = (value & ~requested) | (hostown[gpp] & requested);
writel(value);

> +   dev_warn(dev, "hostown been
> changed during resume\n");
> +   dev_dbg(dev, "restored hostown
> %d/%u %#08x\n", i, gpp,
> +   readl(base + gpp * 4));
> +   }
> +   }
> +   }

-- 
With Best Regards,
Andy Shevchenko




Re: [RFC PATCH 4/4] bus: ti-sysc: Ensure PRU-ICSS doesn't break suspend/resume

2019-04-03 Thread Roger Quadros
On 02/04/2019 19:57, Tony Lindgren wrote:
> * Roger Quadros  [190402 13:38]:
>> The PRU-ICSS subsystem's SYSCONFIG register is similar to
>> omap4-simple but has 2 special bits STANDBY_INIT and SUB_MWAIT.
>>
>> The STANDBY_INIT bit initiates a Standby sequence (when set) and
>> triggers a MStandby request to the SoC's PRCM module. This same
>> bit is also used to enable the OCP master ports (when cleared).
>>
>> Some PRU applications require the OCP master port access to be
>> enabled thus keeping it out of standby.
> 
> So do we need to configure this depending on the application?

Yes.
> 
>> During sustem suspend/resume we must ensure that the PRUSS is in
>> standby else it will break resume.
>>
>> NOTE:
>> 1. This patch only adds the PM callbacks with code to fix the System
>> Suspend/Resume hang issue on AM33xx/AM437x SoCs, but does not
>> implement the full context save and restore required for the PRUSS
>> drivers to work across system suspend/resume when the power domain
>> is switched off (L4PER domain is switched OFF on AM335x/AM437x
>> during system suspend/resume, so PRUSS modules do lose context).
> 
> I think we already restore the interconnect target module access
> properly on resume. If not we should fix that.
> 
> Saving and restoring the child device state is up to the device
> drivers managing the child device(s), and there's not much ti-sysc.c
> can do about it, right?

Agreed. In that case this handling should be done by pruss.c
and uio_pruss.c in their suspend/resume handlers.

Suman, do you agree?

> 
>> @@ -92,6 +93,7 @@ struct sysc {
>>  bool enabled;
>>  bool needs_resume;
>>  bool child_needs_resume;
>> +bool in_standby;
>>  struct delayed_work idle_work;
>>  };
> 
> We should start using bitfields for the bool here, might as well
> already do it now:
> 
> unsigned long in_standby:1;
> 
> See "17) Using bool" in Documentation/process/coding-style.rst.
> 
>> @@ -1023,6 +1025,21 @@ static int __maybe_unused sysc_noirq_suspend(struct 
>> device *dev)
>>  if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
>>  return 0;
>>  
>> +if (ddata->cap->type == TI_SYSC_PRUSS) {
> 
> Should this test be made more generic based on the mstandby
> bit being configured?

No other module uses this bit. It is specific to PRUSS.
> 
> And can you please make these into separate functions to
> avoid cluttering the suspend and resume functions. Something
> like sysc_handle_mstandby() maybe?
> 
>> +u32 reg, mask;
>> +const struct sysc_regbits *regbits = ddata->cap->regbits;
>> +
>> +mask = BIT(regbits->standby_init_shift);
>> +reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
>> +ddata->in_standby = reg & mask;
> 
> Hmm so could we just assume that the device drivers for child device(s)
> configure the MSTANDBY bit? Or do we need to manage it in ti-sysc?
> 

I'm in favor of managing it in the child device driver.
Let's see if Suman has any concerns.

> See for example drivers/usb/musb/omap2430.c omap2430_low_level_init()
> and omap2430_low_level_exit(). That's a separate register though.
> 

--
cheers,
-roger 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-03 Thread Chris Chiu
On Tue, Apr 2, 2019 at 7:58 PM Andy Shevchenko
 wrote:
> > +   base = community->regs + community->hostown_offset;
> > +   for (gpp = 0; gpp < community->ngpps; gpp++) {
> > +   if (communities[i].hostown[gpp] &&
> > +   communities[i].hostown[gpp] != readl(base
> > + gpp * 4)) {
> > +   writel(communities[i].hostown[gpp],
> > base + gpp * 4);
> > +   dev_warn(dev, "hostown changed after 
> > resume\n");
> > +   dev_dbg(dev, "restored hostown %d/%u
> > %#08x\n", i, gpp,
> > +   readl(base + gpp * 4));
> > +   }
> > +   }
>
> Instead you may need to loop over each pin in the part of the group related to
> one 32-bit HOSTSW_OWN register (i.e. 8, see PADOWN_*() macros in the driver),
> check if it's requested and break a loop. If loop index is off-by-one a limit,
> nothing to do, otherwise restore hostown register.
>
> More pedantic approach is to collect the mask inside the loop and apply it.
>
> The check function name is gpiochip_is_requested().
>
> (One of Intel's drivers which is using that at ->resume() is
>  drivers/gpio/gpio-lynxpoint.c)
>
> P.S. I prefer pedantic approach. The simplification one is showed in order to
> give you an idea.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>

Thanks for your great comment. I remove the useless hostown save function
and make the following change in ->resume() to detect and restore the abnormal
HOSTSW_OWN. Please help comment if there're still problems. Thanks.

@@ -1588,6 +1600,29 @@ int intel_pinctrl_resume(struct device *dev)
dev_dbg(dev, "restored mask %d/%u %#08x\n", i, gpp,
readl(base + gpp * 4));
}
+
+   base = community->regs + community->hostown_offset;
+   for (gpp = 0; gpp < community->ngpps; gpp++) {
+   const struct intel_padgroup *padgrp =
&community->gpps[i];
+   unsigned int requested = 0;
+   int j;
+
+   if (padgrp->gpio_base < 0)
+   continue;
+
+   for (j = 0; j < padgrp->size; j++)
+   if
(gpiochip_is_requested(&pctrl->chip, padgrp->gpio_base + j))
+   requested |= BIT(j);
+
+   if (requested) {
+   if (communities[i].hostown[gpp] !=
readl(base + gpp * 4)) {
+
writel(communities[i].hostown[gpp], base + gpp * 4);
+   dev_warn(dev, "hostown been
changed during resume\n");
+   dev_dbg(dev, "restored hostown
%d/%u %#08x\n", i, gpp,
+   readl(base + gpp * 4));
+   }
+   }
+   }
}

return 0;


Re: [RFC PATCH 4/4] bus: ti-sysc: Ensure PRU-ICSS doesn't break suspend/resume

2019-04-02 Thread Tony Lindgren
* Roger Quadros  [190402 13:38]:
> The PRU-ICSS subsystem's SYSCONFIG register is similar to
> omap4-simple but has 2 special bits STANDBY_INIT and SUB_MWAIT.
> 
> The STANDBY_INIT bit initiates a Standby sequence (when set) and
> triggers a MStandby request to the SoC's PRCM module. This same
> bit is also used to enable the OCP master ports (when cleared).
> 
> Some PRU applications require the OCP master port access to be
> enabled thus keeping it out of standby.

So do we need to configure this depending on the application?

> During sustem suspend/resume we must ensure that the PRUSS is in
> standby else it will break resume.
> 
> NOTE:
> 1. This patch only adds the PM callbacks with code to fix the System
> Suspend/Resume hang issue on AM33xx/AM437x SoCs, but does not
> implement the full context save and restore required for the PRUSS
> drivers to work across system suspend/resume when the power domain
> is switched off (L4PER domain is switched OFF on AM335x/AM437x
> during system suspend/resume, so PRUSS modules do lose context).

I think we already restore the interconnect target module access
properly on resume. If not we should fix that.

Saving and restoring the child device state is up to the device
drivers managing the child device(s), and there's not much ti-sysc.c
can do about it, right?

> @@ -92,6 +93,7 @@ struct sysc {
>   bool enabled;
>   bool needs_resume;
>   bool child_needs_resume;
> + bool in_standby;
>   struct delayed_work idle_work;
>  };

We should start using bitfields for the bool here, might as well
already do it now:

unsigned long in_standby:1;

See "17) Using bool" in Documentation/process/coding-style.rst.

> @@ -1023,6 +1025,21 @@ static int __maybe_unused sysc_noirq_suspend(struct 
> device *dev)
>   if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
>   return 0;
>  
> + if (ddata->cap->type == TI_SYSC_PRUSS) {

Should this test be made more generic based on the mstandby
bit being configured?

And can you please make these into separate functions to
avoid cluttering the suspend and resume functions. Something
like sysc_handle_mstandby() maybe?

> + u32 reg, mask;
> + const struct sysc_regbits *regbits = ddata->cap->regbits;
> +
> + mask = BIT(regbits->standby_init_shift);
> + reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
> + ddata->in_standby = reg & mask;

Hmm so could we just assume that the device drivers for child device(s)
configure the MSTANDBY bit? Or do we need to manage it in ti-sysc?

See for example drivers/usb/musb/omap2430.c omap2430_low_level_init()
and omap2430_low_level_exit(). That's a separate register though.

Regards,

Tony


[RFC PATCH 4/4] bus: ti-sysc: Ensure PRU-ICSS doesn't break suspend/resume

2019-04-02 Thread Roger Quadros
The PRU-ICSS subsystem's SYSCONFIG register is similar to
omap4-simple but has 2 special bits STANDBY_INIT and SUB_MWAIT.

The STANDBY_INIT bit initiates a Standby sequence (when set) and
triggers a MStandby request to the SoC's PRCM module. This same
bit is also used to enable the OCP master ports (when cleared).

Some PRU applications require the OCP master port access to be
enabled thus keeping it out of standby.
During sustem suspend/resume we must ensure that the PRUSS is in
standby else it will break resume.

NOTE:
1. This patch only adds the PM callbacks with code to fix the System
Suspend/Resume hang issue on AM33xx/AM437x SoCs, but does not
implement the full context save and restore required for the PRUSS
drivers to work across system suspend/resume when the power domain
is switched off (L4PER domain is switched OFF on AM335x/AM437x
during system suspend/resume, so PRUSS modules do lose context).
2. The PRUSS driver functionality on AM57xx SoCs is not affected that
much because the PER power domain to which the PRUSS IPs belong is
not switched OFF during suspend/resume.

Based on work by Suman Anna.

Cc: Suman Anna 
Signed-off-by: Roger Quadros 
---
 drivers/bus/ti-sysc.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index e4ab4d422ea5..9c94ce08dd36 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -71,6 +71,7 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = {
  * @name: name if available
  * @revision: interconnect target module revision
  * @needs_resume: runtime resume needed on resume from suspend
+ * @in_standby: flag used by PRUSS type during suspend/resume
  */
 struct sysc {
struct device *dev;
@@ -92,6 +93,7 @@ struct sysc {
bool enabled;
bool needs_resume;
bool child_needs_resume;
+   bool in_standby;
struct delayed_work idle_work;
 };
 
@@ -1023,6 +1025,21 @@ static int __maybe_unused sysc_noirq_suspend(struct 
device *dev)
if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
return 0;
 
+   if (ddata->cap->type == TI_SYSC_PRUSS) {
+   u32 reg, mask;
+   const struct sysc_regbits *regbits = ddata->cap->regbits;
+
+   mask = BIT(regbits->standby_init_shift);
+   reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+   ddata->in_standby = reg & mask;
+
+   /* initiate MStandby */
+   if (!ddata->in_standby) {
+   reg |= mask;
+   sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+   }
+   }
+
return pm_runtime_force_suspend(dev);
 }
 
@@ -1035,6 +1052,25 @@ static int __maybe_unused sysc_noirq_resume(struct 
device *dev)
if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
return 0;
 
+   if (ddata->cap->type == TI_SYSC_PRUSS && !ddata->in_standby) {
+   u32 reg;
+   const struct sysc_regbits *regbits = ddata->cap->regbits;
+
+   /* re-enable OCP master ports/disable MStandby */
+   reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+   reg &= ~BIT(regbits->standby_init_shift);
+   sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+   ddata->in_standby = 0;
+
+   /* wait till ready for transactions - delay is arbitrary */
+   usleep_range(50, 100);
+   reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+   if (reg & BIT(regbits->sub_mwait_shift)) {
+   dev_err(dev, "timeout waiting for SUB_MWAIT_READY\n");
+   return -ETIMEDOUT;
+   }
+   }
+
return pm_runtime_force_resume(dev);
 }
 
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki



Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-02 Thread Andy Shevchenko
On Tue, Apr 02, 2019 at 02:16:19PM +0800, Chris Chiu wrote:
> On Mon, Apr 1, 2019 at 8:23 PM Andy Shevchenko
>  wrote:
> > On Mon, Apr 01, 2019 at 06:41:57PM +0800, Chris Chiu wrote:

> Thanks for the comment. My first version did mimic the logic of the interrupt
> mask restore but it was based on the DMI quirk. It saves HOSTSW_OWN
> for each padgroup and restores them all after resume if DMI info matched.
> 
> What really confused me is how to do this specifically for a requested GPIO
> pin. So here's my new proposed patch. Please suggests if there's any better
> idea. Thanks.

>  struct intel_community_context {
> u32 *intmask;
> +   u32 *hostown;

This is okay.

>  };

> +#ifdef CONFIG_PM_SLEEP
> +static void intel_save_hostown(struct intel_pinctrl *pctrl, unsigned int 
> pin);
> +#endif
> +

No need for this...

> /* Disable TX buffer and enable RX (this will be input) */
> __intel_gpio_set_direction(padcfg0, true);
> +#ifdef CONFIG_PM_SLEEP
> +   intel_save_hostown(pctrl, pin);
> +#endif

...and for this.
Just save all of them at ->suspend()

> for (i = 0; i < pctrl->ncommunities; i++) {
> struct intel_community *community = &pctrl->communities[i];
> -   u32 *intmask;
> +   u32 *intmask, *hostown;
> 
> intmask = devm_kcalloc(pctrl->dev, community->ngpps,
>sizeof(*intmask), GFP_KERNEL);
> @@ -1292,6 +1299,13 @@ static int intel_pinctrl_pm_init(struct
> intel_pinctrl *pctrl)
> return -ENOMEM;
> 
> communities[i].intmask = intmask;
> +
> +   hostown = devm_kcalloc(pctrl->dev, community->ngpps,
> +  sizeof(*hostown), GFP_KERNEL);
> +   if (!hostown)
> +   return -ENOMEM;
> +
> +   communities[i].hostown= hostown;

This is good.

> }

> +static void intel_save_hostown(struct intel_pinctrl *pctrl, unsigned int pin)
> +{
> +   const struct intel_community *community;
> +   const struct intel_padgroup *padgrp;
> +   int i;
> +
> +   community = intel_get_community(pctrl, pin);
> +   if (!community)
> +   return;
> +   if (!community->hostown_offset)
> +   return;
> +
> +   padgrp = intel_community_get_padgroup(community, pin);
> +   if (!padgrp)
> +   return;
> +
> +   for (i = 0; i < pctrl->ncommunities; i++) {
> +   const struct intel_community *comm = &pctrl->communities[i];
> +   int j;
> +
> +   for (j = 0; j < comm->ngpps; j++) {
> +   const struct intel_padgroup *pgrp = &comm->gpps[j];
> +
> +   if (padgrp == pgrp) {
> +   struct intel_community_context *communities;
> +   void __iomem *base;
> +
> +   communities = pctrl->context.communities;
> +   base = community->regs +
> community->hostown_offset;
> +   communities[i].hostown[j] = readl(base + j * 
> 4);
> +   break;
> +   }
> +   }
> +   }

> +   return;

Useless.

> +}

This is too complicated. Just add

base = community->regs + community->hostown_offset;
for (gpp = 0; gpp < community->ngpps; gpp++)
communities[i].hostown[gpp] = readl(base + gpp * 4);

into ->suspend() loop.

> +   base = community->regs + community->hostown_offset;
> +   for (gpp = 0; gpp < community->ngpps; gpp++) {
> +   if (communities[i].hostown[gpp] &&
> +   communities[i].hostown[gpp] != readl(base
> + gpp * 4)) {
> +   writel(communities[i].hostown[gpp],
> base + gpp * 4);
> +   dev_warn(dev, "hostown changed after 
> resume\n");
> +   dev_dbg(dev, "restored hostown %d/%u
> %#08x\n", i, gpp,
> +   readl(base + gpp * 4));
> +   }
> +   }

Instead you may need to loop over each pin in the part of the group related to
one 32-bit HOSTSW_OWN register (i.e. 8, see PADOWN_*() macros in the driver),
check if it's requested and break a loop. If loop index is off-by-one a limit,
nothing to do, otherwise restore hostown register.

More pedantic approach is to collect the mask inside the loop and apply it.

The check function name is gpiochip_is_requested().

(One of Intel's drivers which is using that at ->resume() is
 drivers/gpio/gpio-lynxpoint.c)

P.S. I prefer pedantic approach. The simplification one is showed in order to
give you an idea.

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-01 Thread Chris Chiu
On Mon, Apr 1, 2019 at 8:23 PM Andy Shevchenko
 wrote:
>
> On Mon, Apr 01, 2019 at 06:41:57PM +0800, Chris Chiu wrote:
>
> Thanks for the patch.
> My comments below.
>
> > diff --git a/drivers/pinctrl/intel/pinctrl-intel.c
> > b/drivers/pinctrl/intel/pinctrl-intel.c
> > index 8cda7b535b02..d1cfa5adef9b 100644
> > --- a/drivers/pinctrl/intel/pinctrl-intel.c
> > +++ b/drivers/pinctrl/intel/pinctrl-intel.c
> > @@ -77,6 +77,7 @@ struct intel_pad_context {
> > u32 padcfg0;
> > u32 padcfg1;
> > u32 padcfg2;
>
> > +   u32 hostown;
>
> This is wrong. We have one register per entire (*) group of pins to keep host
> ownership. Basically it's a mask.
>
> *) if it's <= 32, otherwise there are more registers. But in any case it's 1
> bit per pin, and not 32 bits.
>
> > for (i = 0; i < pctrl->soc->npins; i++)
>
> Thus, the actual actions should mimic what we do for interrupt mask.
>
> --
> With Best Regards,
> Andy Shevchenko
>

Thanks for the comment. My first version did mimic the logic of the interrupt
mask restore but it was based on the DMI quirk. It saves HOSTSW_OWN
for each padgroup and restores them all after resume if DMI info matched.

What really confused me is how to do this specifically for a requested GPIO
pin. So here's my new proposed patch. Please suggests if there's any better
idea. Thanks.

--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -81,6 +81,7 @@ struct intel_pad_context {

 struct intel_community_context {
u32 *intmask;
+   u32 *hostown;
 };

 struct intel_pinctrl_context {
@@ -117,6 +118,10 @@ struct intel_pinctrl {
 #define pin_to_padno(c, p) ((p) - (c)->pin_base)
 #define padgroup_offset(g, p)  ((p) - (g)->base)

+#ifdef CONFIG_PM_SLEEP
+static void intel_save_hostown(struct intel_pinctrl *pctrl, unsigned int pin);
+#endif
+
 static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
   unsigned int pin)
 {
@@ -456,7 +461,9 @@ static int intel_gpio_request_enable(struct
pinctrl_dev *pctldev,
intel_gpio_set_gpio_mode(padcfg0);
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(padcfg0, true);
+#ifdef CONFIG_PM_SLEEP
+   intel_save_hostown(pctrl, pin);
+#endif
raw_spin_unlock_irqrestore(&pctrl->lock, flags);

return 0;
@@ -1284,7 +1291,7 @@ static int intel_pinctrl_pm_init(struct
intel_pinctrl *pctrl)

for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
-   u32 *intmask;
+   u32 *intmask, *hostown;

intmask = devm_kcalloc(pctrl->dev, community->ngpps,
   sizeof(*intmask), GFP_KERNEL);
@@ -1292,6 +1299,13 @@ static int intel_pinctrl_pm_init(struct
intel_pinctrl *pctrl)
return -ENOMEM;

communities[i].intmask = intmask;
+
+   hostown = devm_kcalloc(pctrl->dev, community->ngpps,
+  sizeof(*hostown), GFP_KERNEL);
+   if (!hostown)
+   return -ENOMEM;
+
+   communities[i].hostown= hostown;
}

pctrl->context.pads = pads;
@@ -1447,6 +1461,43 @@ int intel_pinctrl_probe_by_uid(struct
platform_device *pdev)
 EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_uid);

 #ifdef CONFIG_PM_SLEEP
+static void intel_save_hostown(struct intel_pinctrl *pctrl, unsigned int pin)
+{
+   const struct intel_community *community;
+   const struct intel_padgroup *padgrp;
+   int i;
+
+   community = intel_get_community(pctrl, pin);
+   if (!community)
+   return;
+   if (!community->hostown_offset)
+   return;
+
+   padgrp = intel_community_get_padgroup(community, pin);
+   if (!padgrp)
+   return;
+
+   for (i = 0; i < pctrl->ncommunities; i++) {
+   const struct intel_community *comm = &pctrl->communities[i];
+   int j;
+
+   for (j = 0; j < comm->ngpps; j++) {
+   const struct intel_padgroup *pgrp = &comm->gpps[j];
+
+   if (padgrp == pgrp) {
+   struct intel_community_context *communities;
+   void __iomem *base;
+
+   communities = pctrl->context.communities;
+   base = community->regs +
community->hostown_offset;
+   communities[i].hostown[j] = readl(base + j * 4);
+   break;
+   }
+   }
+   }
+   return;
+}
+
 static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl,
unsigned int pin)
 {
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
@@ -1588,6 +1639,17 @@ int intel_pinctrl_resume(struct device *dev)
 

[PATCH 4.4 024/131] extcon: usb-gpio: Dont miss event during suspend/resume

2019-04-01 Thread Greg Kroah-Hartman
4.4-stable review patch.  If anyone has any objections, please let me know.

--

From: Roger Quadros 

commit 04c080080855ce84dcd490a2e04805608a21085d upstream.

Pin state might have changed during suspend/resume while
our interrupts were disabled and if device doesn't support wakeup.

Scan for change during resume for such case.

Signed-off-by: Roger Quadros 
Signed-off-by: Chanwoo Choi 
Signed-off-by: Arnd Bergmann 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/extcon/extcon-usb-gpio.c |3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -192,6 +192,9 @@ static int usb_extcon_resume(struct devi
}
 
enable_irq(info->id_irq);
+   if (!device_may_wakeup(dev))
+   queue_delayed_work(system_power_efficient_wq,
+  &info->wq_detcable, 0);
 
return ret;
 }




[PATCH 4.4 020/131] usb: dwc3: gadget: Fix suspend/resume during device mode

2019-04-01 Thread Greg Kroah-Hartman
4.4-stable review patch.  If anyone has any objections, please let me know.

--

From: Roger Quadros 

commit 9772b47a4c2916d645c551228b6085ea24acbe5d upstream.

Gadget controller might not be always active during system
suspend/resume as gadget driver might not have yet been loaded or
might have been unloaded prior to system suspend.

Check if we're active and only then perform
necessary actions during suspend/resume.

Signed-off-by: Roger Quadros 
Signed-off-by: Felipe Balbi 
Signed-off-by: Arnd Bergmann 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/usb/dwc3/gadget.c |6 ++
 1 file changed, 6 insertions(+)

--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2894,6 +2894,9 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 int dwc3_gadget_suspend(struct dwc3 *dwc)
 {
+   if (!dwc->gadget_driver)
+   return 0;
+
if (dwc->pullups_connected) {
dwc3_gadget_disable_irq(dwc);
dwc3_gadget_run_stop(dwc, true, true);
@@ -2912,6 +2915,9 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
struct dwc3_ep  *dep;
int ret;
 
+   if (!dwc->gadget_driver)
+   return 0;
+
/* Start with SuperSpeed Default */
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 




[PATCH 4.4 013/131] ALSA: hda - Record the current power state before suspend/resume calls

2019-04-01 Thread Greg Kroah-Hartman
4.4-stable review patch.  If anyone has any objections, please let me know.

--

From: Takashi Iwai 

commit 98081ca62cbac31fb0f7efaf90b2e7384ce22257 upstream.

Currently we deal with single codec and suspend codec callbacks for
all S3, S4 and runtime PM handling.  But it turned out that we want
distinguish the call patterns sometimes, e.g. for applying some init
sequence only at probing and restoring from hibernate.

This patch slightly modifies the common PM callbacks for HD-audio
codec and stores the currently processed PM event in power_state of
the codec's device.power field, which is currently unused.  The codec
callback can take a look at this event value and judges which purpose
it's being called.

Signed-off-by: Takashi Iwai 
Signed-off-by: Greg Kroah-Hartman 

---
 sound/pci/hda/hda_codec.c |   43 +--
 1 file changed, 41 insertions(+), 2 deletions(-)

--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3004,6 +3004,7 @@ static void hda_call_codec_resume(struct
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
+   codec->core.dev.power.power_state = PMSG_ON;
atomic_dec(&codec->core.in_pm);
 }
 
@@ -3036,10 +3037,48 @@ static int hda_codec_runtime_resume(stru
 }
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_SLEEP
+static int hda_codec_pm_suspend(struct device *dev)
+{
+   dev->power.power_state = PMSG_SUSPEND;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_resume(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESUME;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_freeze(struct device *dev)
+{
+   dev->power.power_state = PMSG_FREEZE;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_thaw(struct device *dev)
+{
+   dev->power.power_state = PMSG_THAW;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_restore(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESTORE;
+   return pm_runtime_force_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
 /* referred in hda_bind.c */
 const struct dev_pm_ops hda_codec_driver_pm = {
-   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-   pm_runtime_force_resume)
+#ifdef CONFIG_PM_SLEEP
+   .suspend = hda_codec_pm_suspend,
+   .resume = hda_codec_pm_resume,
+   .freeze = hda_codec_pm_freeze,
+   .thaw = hda_codec_pm_thaw,
+   .poweroff = hda_codec_pm_suspend,
+   .restore = hda_codec_pm_restore,
+#endif /* CONFIG_PM_SLEEP */
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
   NULL)
 };




Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-01 Thread Andy Shevchenko
On Mon, Apr 01, 2019 at 06:41:57PM +0800, Chris Chiu wrote:
> On Mon, Apr 1, 2019 at 3:49 PM Mika Westerberg
>  wrote:
> > On Fri, Mar 29, 2019 at 04:38:20PM +0800, Chris Chiu wrote:

> > Sure I can but it probably does not happen until end of the week because
> > I'm currently busy with something else.
> 
> Thanks for your attention. I don't want to distract you so I'll try to
> refine the
> patch. It would be a great help if you can help review and give comments.
> 
> Don't know whether if the following patch still get the wrong idea about
> your thought.  It saves the hostsw_own when GPIO requested, check
> if the value differs in resume() and restore if necessary. Please kindly
> correct me if any. Thanks

Thanks for the patch.
My comments below.

> diff --git a/drivers/pinctrl/intel/pinctrl-intel.c
> b/drivers/pinctrl/intel/pinctrl-intel.c
> index 8cda7b535b02..d1cfa5adef9b 100644
> --- a/drivers/pinctrl/intel/pinctrl-intel.c
> +++ b/drivers/pinctrl/intel/pinctrl-intel.c
> @@ -77,6 +77,7 @@ struct intel_pad_context {
> u32 padcfg0;
> u32 padcfg1;
> u32 padcfg2;

> +   u32 hostown;

This is wrong. We have one register per entire (*) group of pins to keep host
ownership. Basically it's a mask.

*) if it's <= 32, otherwise there are more registers. But in any case it's 1
bit per pin, and not 32 bits.

> for (i = 0; i < pctrl->soc->npins; i++)

Thus, the actual actions should mimic what we do for interrupt mask.

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-01 Thread Chris Chiu
On Mon, Apr 1, 2019 at 3:49 PM Mika Westerberg
 wrote:
>
> On Fri, Mar 29, 2019 at 04:38:20PM +0800, Chris Chiu wrote:
> > On Thu, Mar 28, 2019 at 8:34 PM Mika Westerberg
> >  wrote:
> > >
> > > On Thu, Mar 28, 2019 at 08:19:59PM +0800, Chris Chiu wrote:
> > > > On Thu, Mar 28, 2019 at 5:38 PM Daniel Drake  wrote:
> > > > >
> > > > > On Thu, Mar 28, 2019 at 5:17 PM Andy Shevchenko
> > > > >  wrote:
> > > > > > Hmm... Can you confirm that laptop you declared as a fixed case and 
> > > > > > the
> > > > > > mentioned here is the same one?
> > > > >
> > > > > They are definitely not the same exact unit - originally we had a
> > > > > pre-production sample, and now we briefly diagnosed a real production
> > > > > unit that was sold to a customer. There could be subtle motherboard
> > > > > variations as you mention.
> > > > >
> > > > > > If it's the case, I recommend to ping Asus again and make them 
> > > > > > check and fix.
> > > > >
> > > > > We'll keep an eye open for any opportunities to go deeper here.
> > > > > However further investigation on both our side and theirs is blocked
> > > > > by not having any of the affected hardware (since the models are now
> > > > > so old), so I'm not very optimistic that we'll be able to make
> > > > > progress there.
> > > > >
> > > > > > Meanwhile, Mika's proposal sounds feasible and not so intrusive. We 
> > > > > > may
> > > > > > implement this later on.
> > > > >
> > > > > Chris will work on implementing this for your consideration.
> > > > >
> > > > > Thanks for the quick feedback!
> > > > > Daniel
> > > >
> > > > What if I modify the patch as follows? It doesn't save HOSTSW_OWN 
> > > > register.
> > > > It just toggles the bit specifically for the IRQ GPIO pin after resume 
> > > > when DMI
> > > > matches.
> > >
> > > I don't really like having quirks like this if we can avoid it and in
> > > this case I think we can. Just always save HOSTSW_OWN and then restore
> > > it if there is a GPIO requested and the value differs (and log a warning
> > > or something like that).
> >
> > You mean save the content of hostsw_own register on padgroup based ex.
> > communities[i].hostown[gpp] = readl(base + gpp * 4);
> >
> > And then check the hostown bit for the GPIO requested pin in
> > intel_pinctrl_resume(),
> > differs the hostsw_own bit on pin base (like padcfg), then restore the
> > hostsw_own
> > value of the padgroug which the GPIO pin is belonging to?
>
> Yes.
>
> > I think what you mean should be a much more straightforward solution
> > for this. Could
> > you implement this in your way and we can try to help verification. Thanks.
>
> Sure I can but it probably does not happen until end of the week because
> I'm currently busy with something else.

Thanks for your attention. I don't want to distract you so I'll try to
refine the
patch. It would be a great help if you can help review and give comments.

Don't know whether if the following patch still get the wrong idea about
your thought.  It saves the hostsw_own when GPIO requested, check
if the value differs in resume() and restore if necessary. Please kindly
correct me if any. Thanks

diff --git a/drivers/pinctrl/intel/pinctrl-intel.c
b/drivers/pinctrl/intel/pinctrl-intel.c
index 8cda7b535b02..d1cfa5adef9b 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -77,6 +77,7 @@ struct intel_pad_context {
u32 padcfg0;
u32 padcfg1;
u32 padcfg2;
+   u32 hostown;
 };

 struct intel_community_context {
@@ -219,6 +220,24 @@ static bool intel_pad_acpi_mode(struct
intel_pinctrl *pctrl, unsigned int pin)
return !(readl(hostown) & BIT(gpp_offset));
 }

+static void __iomem *intel_get_hostown(struct intel_pinctrl *pctrl,
unsigned int pin)
+{
+   const struct intel_community *community;
+   const struct intel_padgroup *padgrp;
+
+   community = intel_get_community(pctrl, pin);
+   if (!community)
+   return NULL;
+   if (!community->hostown_offset)
+   return NULL;
+
+   padgrp = intel_community_get_padgroup(community, pin);
+   if (!padgrp)
+   return NULL;
+
+   return community->regs + community->hostown_offset +
padgrp->reg_num * 4;
+}
+
 static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
 {
struct intel_community *community;
@@ -442,7 +461,7 @@ static int intel_gpio_request_enable(struct
pinctrl_dev *pctldev,
 unsigned int pin)
 {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-   void __iomem *padcfg0;
+   void __iomem *padcfg0, *hostown;
unsigned long flags;

raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -457,6 +476,10 @@ static int intel_gpio_request_enable(struct
pinctrl_dev *pctldev,
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(padcfg0, true);

+   /* Save HOSTSW_OWN */
+   hostown = 

Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-04-01 Thread Mika Westerberg
On Fri, Mar 29, 2019 at 04:38:20PM +0800, Chris Chiu wrote:
> On Thu, Mar 28, 2019 at 8:34 PM Mika Westerberg
>  wrote:
> >
> > On Thu, Mar 28, 2019 at 08:19:59PM +0800, Chris Chiu wrote:
> > > On Thu, Mar 28, 2019 at 5:38 PM Daniel Drake  wrote:
> > > >
> > > > On Thu, Mar 28, 2019 at 5:17 PM Andy Shevchenko
> > > >  wrote:
> > > > > Hmm... Can you confirm that laptop you declared as a fixed case and 
> > > > > the
> > > > > mentioned here is the same one?
> > > >
> > > > They are definitely not the same exact unit - originally we had a
> > > > pre-production sample, and now we briefly diagnosed a real production
> > > > unit that was sold to a customer. There could be subtle motherboard
> > > > variations as you mention.
> > > >
> > > > > If it's the case, I recommend to ping Asus again and make them check 
> > > > > and fix.
> > > >
> > > > We'll keep an eye open for any opportunities to go deeper here.
> > > > However further investigation on both our side and theirs is blocked
> > > > by not having any of the affected hardware (since the models are now
> > > > so old), so I'm not very optimistic that we'll be able to make
> > > > progress there.
> > > >
> > > > > Meanwhile, Mika's proposal sounds feasible and not so intrusive. We 
> > > > > may
> > > > > implement this later on.
> > > >
> > > > Chris will work on implementing this for your consideration.
> > > >
> > > > Thanks for the quick feedback!
> > > > Daniel
> > >
> > > What if I modify the patch as follows? It doesn't save HOSTSW_OWN 
> > > register.
> > > It just toggles the bit specifically for the IRQ GPIO pin after resume 
> > > when DMI
> > > matches.
> >
> > I don't really like having quirks like this if we can avoid it and in
> > this case I think we can. Just always save HOSTSW_OWN and then restore
> > it if there is a GPIO requested and the value differs (and log a warning
> > or something like that).
> 
> You mean save the content of hostsw_own register on padgroup based ex.
> communities[i].hostown[gpp] = readl(base + gpp * 4);
> 
> And then check the hostown bit for the GPIO requested pin in
> intel_pinctrl_resume(),
> differs the hostsw_own bit on pin base (like padcfg), then restore the
> hostsw_own
> value of the padgroug which the GPIO pin is belonging to?

Yes.

> I think what you mean should be a much more straightforward solution
> for this. Could
> you implement this in your way and we can try to help verification. Thanks.

Sure I can but it probably does not happen until end of the week because
I'm currently busy with something else.


Re: [PATCH net-next v3 0/2] net: phy: marvell10g: implement suspend/resume callbacks

2019-03-29 Thread David Miller
From: Antoine Tenart 
Date: Tue, 26 Mar 2019 15:53:00 +0100

> This series implements the suspend/resume callbacks in the
> marvell10g PHY driver.

Heiner gave you feedback, you have not responded.

Therefore I am removing your patches from my queue.


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-29 Thread Chris Chiu
On Thu, Mar 28, 2019 at 8:34 PM Mika Westerberg
 wrote:
>
> On Thu, Mar 28, 2019 at 08:19:59PM +0800, Chris Chiu wrote:
> > On Thu, Mar 28, 2019 at 5:38 PM Daniel Drake  wrote:
> > >
> > > On Thu, Mar 28, 2019 at 5:17 PM Andy Shevchenko
> > >  wrote:
> > > > Hmm... Can you confirm that laptop you declared as a fixed case and the
> > > > mentioned here is the same one?
> > >
> > > They are definitely not the same exact unit - originally we had a
> > > pre-production sample, and now we briefly diagnosed a real production
> > > unit that was sold to a customer. There could be subtle motherboard
> > > variations as you mention.
> > >
> > > > If it's the case, I recommend to ping Asus again and make them check 
> > > > and fix.
> > >
> > > We'll keep an eye open for any opportunities to go deeper here.
> > > However further investigation on both our side and theirs is blocked
> > > by not having any of the affected hardware (since the models are now
> > > so old), so I'm not very optimistic that we'll be able to make
> > > progress there.
> > >
> > > > Meanwhile, Mika's proposal sounds feasible and not so intrusive. We may
> > > > implement this later on.
> > >
> > > Chris will work on implementing this for your consideration.
> > >
> > > Thanks for the quick feedback!
> > > Daniel
> >
> > What if I modify the patch as follows? It doesn't save HOSTSW_OWN register.
> > It just toggles the bit specifically for the IRQ GPIO pin after resume when 
> > DMI
> > matches.
>
> I don't really like having quirks like this if we can avoid it and in
> this case I think we can. Just always save HOSTSW_OWN and then restore
> it if there is a GPIO requested and the value differs (and log a warning
> or something like that).

You mean save the content of hostsw_own register on padgroup based ex.
communities[i].hostown[gpp] = readl(base + gpp * 4);

And then check the hostown bit for the GPIO requested pin in
intel_pinctrl_resume(),
differs the hostsw_own bit on pin base (like padcfg), then restore the
hostsw_own
value of the padgroug which the GPIO pin is belonging to?

I think what you mean should be a much more straightforward solution
for this. Could
you implement this in your way and we can try to help verification. Thanks.


Chris


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-28 Thread Mika Westerberg
On Thu, Mar 28, 2019 at 08:19:59PM +0800, Chris Chiu wrote:
> On Thu, Mar 28, 2019 at 5:38 PM Daniel Drake  wrote:
> >
> > On Thu, Mar 28, 2019 at 5:17 PM Andy Shevchenko
> >  wrote:
> > > Hmm... Can you confirm that laptop you declared as a fixed case and the
> > > mentioned here is the same one?
> >
> > They are definitely not the same exact unit - originally we had a
> > pre-production sample, and now we briefly diagnosed a real production
> > unit that was sold to a customer. There could be subtle motherboard
> > variations as you mention.
> >
> > > If it's the case, I recommend to ping Asus again and make them check and 
> > > fix.
> >
> > We'll keep an eye open for any opportunities to go deeper here.
> > However further investigation on both our side and theirs is blocked
> > by not having any of the affected hardware (since the models are now
> > so old), so I'm not very optimistic that we'll be able to make
> > progress there.
> >
> > > Meanwhile, Mika's proposal sounds feasible and not so intrusive. We may
> > > implement this later on.
> >
> > Chris will work on implementing this for your consideration.
> >
> > Thanks for the quick feedback!
> > Daniel
> 
> What if I modify the patch as follows? It doesn't save HOSTSW_OWN register.
> It just toggles the bit specifically for the IRQ GPIO pin after resume when 
> DMI
> matches.

I don't really like having quirks like this if we can avoid it and in
this case I think we can. Just always save HOSTSW_OWN and then restore
it if there is a GPIO requested and the value differs (and log a warning
or something like that).


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-28 Thread Chris Chiu
On Thu, Mar 28, 2019 at 5:38 PM Daniel Drake  wrote:
>
> On Thu, Mar 28, 2019 at 5:17 PM Andy Shevchenko
>  wrote:
> > Hmm... Can you confirm that laptop you declared as a fixed case and the
> > mentioned here is the same one?
>
> They are definitely not the same exact unit - originally we had a
> pre-production sample, and now we briefly diagnosed a real production
> unit that was sold to a customer. There could be subtle motherboard
> variations as you mention.
>
> > If it's the case, I recommend to ping Asus again and make them check and 
> > fix.
>
> We'll keep an eye open for any opportunities to go deeper here.
> However further investigation on both our side and theirs is blocked
> by not having any of the affected hardware (since the models are now
> so old), so I'm not very optimistic that we'll be able to make
> progress there.
>
> > Meanwhile, Mika's proposal sounds feasible and not so intrusive. We may
> > implement this later on.
>
> Chris will work on implementing this for your consideration.
>
> Thanks for the quick feedback!
> Daniel

What if I modify the patch as follows? It doesn't save HOSTSW_OWN register.
It just toggles the bit specifically for the IRQ GPIO pin after resume when DMI
matches.

---
 drivers/pinctrl/intel/pinctrl-intel.c | 67 +++
 1 file changed, 67 insertions(+)

diff --git a/drivers/pinctrl/intel/pinctrl-intel.c
b/drivers/pinctrl/intel/pinctrl-intel.c
index 8cda7b535b02..994abc5ecd32 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 

 #include "../core.h"
 #include "pinctrl-intel.h"
@@ -73,6 +74,8 @@

 #define DEBOUNCE_PERIOD31250 /* ns */

+#define PINCTRL_QUIRK_KEEP_HOSTOWN BIT(0)
+
 struct intel_pad_context {
u32 padcfg0;
u32 padcfg1;
@@ -112,11 +115,37 @@ struct intel_pinctrl {
size_t ncommunities;
struct intel_pinctrl_context context;
int irq;
+   u32 quirks;
 };

 #define pin_to_padno(c, p) ((p) - (c)->pin_base)
 #define padgroup_offset(g, p)  ((p) - (g)->base)

+static const struct dmi_system_id dmi_retain_hostown_table[] = {
+   {
+   .ident = "ASUSTeK COMPUTER INC. ASUS E403NA",
+   .matches = {
+   DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+   DMI_MATCH(DMI_BOARD_NAME, "E403NA"),
+   },
+   },
+   {
+   .ident = "ASUSTeK COMPUTER INC. ASUS X540NA",
+   .matches = {
+   DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+   DMI_MATCH(DMI_BOARD_NAME, "X540NA"),
+   },
+   },
+   {
+   .ident = "ASUSTeK COMPUTER INC. ASUS X541NA",
+   .matches = {
+   DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+   DMI_MATCH(DMI_BOARD_NAME, "X541NA"),
+   },
+   },
+   { }
+};
+
 static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
   unsigned int pin)
 {
@@ -219,6 +248,32 @@ static bool intel_pad_acpi_mode(struct
intel_pinctrl *pctrl, unsigned int pin)
return !(readl(hostown) & BIT(gpp_offset));
 }

+static void intel_pad_force_hostown(struct intel_pinctrl *pctrl,
unsigned int pin)
+{
+   const struct intel_community *community;
+   const struct intel_padgroup *padgrp;
+   unsigned int offset, gpp_offset;
+   void __iomem *hostown;
+
+   community = intel_get_community(pctrl, pin);
+   if (!community)
+   return;
+   if (!community->hostown_offset)
+   return;
+
+   padgrp = intel_community_get_padgroup(community, pin);
+   if (!padgrp)
+   return;
+
+   gpp_offset = padgroup_offset(padgrp, pin);
+   offset = community->hostown_offset + padgrp->reg_num * 4;
+   hostown = community->regs + offset;
+
+   writel(readl(hostown) | BIT(gpp_offset), hostown);
+
+   return;
+}
+
 static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
 {
struct intel_community *community;
@@ -1318,6 +1373,11 @@ int intel_pinctrl_probe(struct platform_device *pdev,
pctrl->soc = soc_data;
raw_spin_lock_init(&pctrl->lock);

+   if (dmi_first_match(dmi_retain_hostown_table)) {
+   pctrl->quirks |= PINCTRL_QUIRK_KEEP_HOSTOWN;
+   dev_info(&pdev->dev, "enabling KEEP_HOSTOWN quirk on
this hw\n");
+   }
+
/*
 * Make a copy of the communities which we can use to hold pointers
 * to the registers.
@@ -1549,6 +1609,13 @@ int intel_pinctrl_resume(struct device *dev)
if (!intel_pinctrl_should_save(pctrl, desc->number))
continue;

+   if ((pctrl->quirks & PINCTRL_QUIRK_KEEP_HOSTOWN) &&
+   intel_pad_ac

Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-28 Thread Daniel Drake
On Thu, Mar 28, 2019 at 5:17 PM Andy Shevchenko
 wrote:
> Hmm... Can you confirm that laptop you declared as a fixed case and the
> mentioned here is the same one?

They are definitely not the same exact unit - originally we had a
pre-production sample, and now we briefly diagnosed a real production
unit that was sold to a customer. There could be subtle motherboard
variations as you mention.

> If it's the case, I recommend to ping Asus again and make them check and fix.

We'll keep an eye open for any opportunities to go deeper here.
However further investigation on both our side and theirs is blocked
by not having any of the affected hardware (since the models are now
so old), so I'm not very optimistic that we'll be able to make
progress there.

> Meanwhile, Mika's proposal sounds feasible and not so intrusive. We may
> implement this later on.

Chris will work on implementing this for your consideration.

Thanks for the quick feedback!
Daniel


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-28 Thread Andy Shevchenko
On Wed, Mar 27, 2019 at 07:29:40PM +0200, Mika Westerberg wrote:
> On Wed, Mar 27, 2019 at 04:22:04PM +0800, Daniel Drake wrote:
> > On Tue, Nov 21, 2017 at 8:13 PM Mika Westerberg
> >  wrote:
> > > On Tue, Nov 21, 2017 at 07:54:26PM +0800, Chris Chiu wrote:
> > > > Yup, I checked the value of the corresponded pin. It shows following 
> > > > before
> > > > suspend
> > > > pin 18 (GPIO_18) GPIO 0x40800102 0x00024075
> > > >
> > > > Then after resume
> > > > pin 18 (GPIO_18) GPIO 0x40800102 0x00024075 [ACPI]
> > >
> > > OK, so ownership is changed to ACPI.
> > >
> > > > What else register do you suggest me to compare? The PADCFG2 is invalid
> > >
> > > It's fine APL does not have PADCFG2.
> > >
> > > Hmm, I don't understand how this can work in Windows either. The Windows
> > > people told me that they don't save and restore anything else than
> > > padcfg registers + ie. If the ownership is changed to ACPI it means you
> > > don't get interrupts anymore (only GPEs) and that applies to Windows as
> > > well.
> > 
> > In the mails after the one quoted above, we reported back to you that
> > the new BIOS from Asus solved the issue.
> > 
> > However, during the time that has followed, we have had numerous user
> > reports from Asus E403NA, X540NA, and X541NA laptops (basically the
> > same models that we originally discussed) where the touchpad stops
> > working after suspend/resume, even with the latest BIOS. We managed to
> > get an affected E403NA unit in-hands again, and confirmed that
> > HOSTSW_OWN was being lost like we had observed before.

Hmm... Can you confirm that laptop you declared as a fixed case and the
mentioned here is the same one?

If they are different, I have a theory that PCBs of those two are not the same
and used GPIO pin can be also not the same, therefore the BIOS fixes only one
revision of the model, but didn't consider the rest.

If it's the case, I recommend to ping Asus again and make them check and fix.

Meanwhile, Mika's proposal sounds feasible and not so intrusive. We may
implement this later on.

> > 
> > Unfortunately as this was a customer laptop we had to return it
> > immediately, before we could investigate further. We don't have access
> > to any more units since they are old models now.
> > 
> > However I'm wondering if you have any other ideas or if you think
> > something like our workaround patch might be acceptable under these
> > circumstances:
> > https://github.com/endlessm/linux/commit/f391452299f62a3d0cbe5333be90f69e9895d8ff
> 
> I wonder if it would be simpler to save it always and then upon resume
> compare them and if changed, log this in dmesg and restore the saved
> one.

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-28 Thread Mika Westerberg
On Wed, Mar 27, 2019 at 07:29:40PM +0200, Mika Westerberg wrote:
> I wonder if it would be simpler to save it always and then upon resume
> compare them and if changed, log this in dmesg and restore the saved
> one.

Actually I think better is to restore hostsw_own only for GPIOs that are
already requested by us. The BIOS should have no business messing those
anyway once they are owned by the GPIO driver.


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-27 Thread Mika Westerberg
+Andy

On Wed, Mar 27, 2019 at 04:22:04PM +0800, Daniel Drake wrote:
> Hi Mika,
> 
> Digging up this old thread again...
> 
> On Tue, Nov 21, 2017 at 8:13 PM Mika Westerberg
>  wrote:
> >
> > On Tue, Nov 21, 2017 at 07:54:26PM +0800, Chris Chiu wrote:
> > > Yup, I checked the value of the corresponded pin. It shows following 
> > > before
> > > suspend
> > > pin 18 (GPIO_18) GPIO 0x40800102 0x00024075
> > >
> > > Then after resume
> > > pin 18 (GPIO_18) GPIO 0x40800102 0x00024075 [ACPI]
> >
> > OK, so ownership is changed to ACPI.
> >
> > > What else register do you suggest me to compare? The PADCFG2 is invalid
> >
> > It's fine APL does not have PADCFG2.
> >
> > Hmm, I don't understand how this can work in Windows either. The Windows
> > people told me that they don't save and restore anything else than
> > padcfg registers + ie. If the ownership is changed to ACPI it means you
> > don't get interrupts anymore (only GPEs) and that applies to Windows as
> > well.
> 
> In the mails after the one quoted above, we reported back to you that
> the new BIOS from Asus solved the issue.
> 
> However, during the time that has followed, we have had numerous user
> reports from Asus E403NA, X540NA, and X541NA laptops (basically the
> same models that we originally discussed) where the touchpad stops
> working after suspend/resume, even with the latest BIOS. We managed to
> get an affected E403NA unit in-hands again, and confirmed that
> HOSTSW_OWN was being lost like we had observed before.
> 
> Unfortunately as this was a customer laptop we had to return it
> immediately, before we could investigate further. We don't have access
> to any more units since they are old models now.
> 
> However I'm wondering if you have any other ideas or if you think
> something like our workaround patch might be acceptable under these
> circumstances:
> https://github.com/endlessm/linux/commit/f391452299f62a3d0cbe5333be90f69e9895d8ff

I wonder if it would be simpler to save it always and then upon resume
compare them and if changed, log this in dmesg and restore the saved
one.


Re: [PATCH] pinctrl: intel: save HOSTSW_OWN register over suspend/resume

2019-03-27 Thread Daniel Drake
Hi Mika,

Digging up this old thread again...

On Tue, Nov 21, 2017 at 8:13 PM Mika Westerberg
 wrote:
>
> On Tue, Nov 21, 2017 at 07:54:26PM +0800, Chris Chiu wrote:
> > Yup, I checked the value of the corresponded pin. It shows following before
> > suspend
> > pin 18 (GPIO_18) GPIO 0x40800102 0x00024075
> >
> > Then after resume
> > pin 18 (GPIO_18) GPIO 0x40800102 0x00024075 [ACPI]
>
> OK, so ownership is changed to ACPI.
>
> > What else register do you suggest me to compare? The PADCFG2 is invalid
>
> It's fine APL does not have PADCFG2.
>
> Hmm, I don't understand how this can work in Windows either. The Windows
> people told me that they don't save and restore anything else than
> padcfg registers + ie. If the ownership is changed to ACPI it means you
> don't get interrupts anymore (only GPEs) and that applies to Windows as
> well.

In the mails after the one quoted above, we reported back to you that
the new BIOS from Asus solved the issue.

However, during the time that has followed, we have had numerous user
reports from Asus E403NA, X540NA, and X541NA laptops (basically the
same models that we originally discussed) where the touchpad stops
working after suspend/resume, even with the latest BIOS. We managed to
get an affected E403NA unit in-hands again, and confirmed that
HOSTSW_OWN was being lost like we had observed before.

Unfortunately as this was a customer laptop we had to return it
immediately, before we could investigate further. We don't have access
to any more units since they are old models now.

However I'm wondering if you have any other ideas or if you think
something like our workaround patch might be acceptable under these
circumstances:
https://github.com/endlessm/linux/commit/f391452299f62a3d0cbe5333be90f69e9895d8ff

Thanks
Daniel


[PATCH net-next v3 1/2] net: phy: marvell10g: implement suspend/resume callbacks

2019-03-26 Thread Antoine Tenart
This patch adds the suspend/resume callbacks for Marvell 10G PHYs. The
three PCS (base-t, base-r and 1000base-x) are set in low power (the PCS
are powered down) when the PHY isn't used.

Signed-off-by: Antoine Tenart 
Reviewed-by: Andrew Lunn 
---
 drivers/net/phy/marvell10g.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 100b401b1f4a..b56cd35182d5 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -226,11 +226,25 @@ static int mv3310_probe(struct phy_device *phydev)
 
 static int mv3310_suspend(struct phy_device *phydev)
 {
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+
return 0;
 }
 
 static int mv3310_resume(struct phy_device *phydev)
 {
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+
return mv3310_hwmon_config(phydev, true);
 }
 
-- 
2.20.1



[PATCH net-next v3 2/2] net: phy: marvell10g: add the suspend/resume callbacks for the 88x2210

2019-03-26 Thread Antoine Tenart
When the 88x2110 PHY support was added, the suspend and resume callbacks
were forgotten. This patch adds them to the 88x2110 PHY callback
definition.

Signed-off-by: Antoine Tenart 
Reviewed-by: Andrew Lunn 
---
 drivers/net/phy/marvell10g.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index b56cd35182d5..08dd2ea08236 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -488,6 +488,8 @@ static struct phy_driver mv3310_drivers[] = {
.name   = "mv88x2110",
.get_features   = genphy_c45_pma_read_abilities,
.probe  = mv3310_probe,
+   .suspend= mv3310_suspend,
+   .resume = mv3310_resume,
.soft_reset = genphy_no_soft_reset,
.config_init= mv3310_config_init,
.config_aneg= mv3310_config_aneg,
-- 
2.20.1



[PATCH 4.14 29/41] ALSA: hda - Record the current power state before suspend/resume calls

2019-03-25 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Takashi Iwai 

commit 98081ca62cbac31fb0f7efaf90b2e7384ce22257 upstream.

Currently we deal with single codec and suspend codec callbacks for
all S3, S4 and runtime PM handling.  But it turned out that we want
distinguish the call patterns sometimes, e.g. for applying some init
sequence only at probing and restoring from hibernate.

This patch slightly modifies the common PM callbacks for HD-audio
codec and stores the currently processed PM event in power_state of
the codec's device.power field, which is currently unused.  The codec
callback can take a look at this event value and judges which purpose
it's being called.

Signed-off-by: Takashi Iwai 
Signed-off-by: Greg Kroah-Hartman 

---
 sound/pci/hda/hda_codec.c |   43 +--
 1 file changed, 41 insertions(+), 2 deletions(-)

--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2900,6 +2900,7 @@ static void hda_call_codec_resume(struct
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
+   codec->core.dev.power.power_state = PMSG_ON;
atomic_dec(&codec->core.in_pm);
 }
 
@@ -2932,10 +2933,48 @@ static int hda_codec_runtime_resume(stru
 }
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_SLEEP
+static int hda_codec_pm_suspend(struct device *dev)
+{
+   dev->power.power_state = PMSG_SUSPEND;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_resume(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESUME;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_freeze(struct device *dev)
+{
+   dev->power.power_state = PMSG_FREEZE;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_thaw(struct device *dev)
+{
+   dev->power.power_state = PMSG_THAW;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_restore(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESTORE;
+   return pm_runtime_force_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
 /* referred in hda_bind.c */
 const struct dev_pm_ops hda_codec_driver_pm = {
-   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-   pm_runtime_force_resume)
+#ifdef CONFIG_PM_SLEEP
+   .suspend = hda_codec_pm_suspend,
+   .resume = hda_codec_pm_resume,
+   .freeze = hda_codec_pm_freeze,
+   .thaw = hda_codec_pm_thaw,
+   .poweroff = hda_codec_pm_suspend,
+   .restore = hda_codec_pm_restore,
+#endif /* CONFIG_PM_SLEEP */
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
   NULL)
 };




[PATCH 5.0 51/52] ALSA: hda - Record the current power state before suspend/resume calls

2019-03-25 Thread Greg Kroah-Hartman
5.0-stable review patch.  If anyone has any objections, please let me know.

--

From: Takashi Iwai 

commit 98081ca62cbac31fb0f7efaf90b2e7384ce22257 upstream.

Currently we deal with single codec and suspend codec callbacks for
all S3, S4 and runtime PM handling.  But it turned out that we want
distinguish the call patterns sometimes, e.g. for applying some init
sequence only at probing and restoring from hibernate.

This patch slightly modifies the common PM callbacks for HD-audio
codec and stores the currently processed PM event in power_state of
the codec's device.power field, which is currently unused.  The codec
callback can take a look at this event value and judges which purpose
it's being called.

Signed-off-by: Takashi Iwai 
Signed-off-by: Greg Kroah-Hartman 

---
 sound/pci/hda/hda_codec.c |   43 +--
 1 file changed, 41 insertions(+), 2 deletions(-)

--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2917,6 +2917,7 @@ static void hda_call_codec_resume(struct
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
+   codec->core.dev.power.power_state = PMSG_ON;
snd_hdac_leave_pm(&codec->core);
 }
 
@@ -2950,10 +2951,48 @@ static int hda_codec_runtime_resume(stru
 }
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_SLEEP
+static int hda_codec_pm_suspend(struct device *dev)
+{
+   dev->power.power_state = PMSG_SUSPEND;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_resume(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESUME;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_freeze(struct device *dev)
+{
+   dev->power.power_state = PMSG_FREEZE;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_thaw(struct device *dev)
+{
+   dev->power.power_state = PMSG_THAW;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_restore(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESTORE;
+   return pm_runtime_force_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
 /* referred in hda_bind.c */
 const struct dev_pm_ops hda_codec_driver_pm = {
-   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-   pm_runtime_force_resume)
+#ifdef CONFIG_PM_SLEEP
+   .suspend = hda_codec_pm_suspend,
+   .resume = hda_codec_pm_resume,
+   .freeze = hda_codec_pm_freeze,
+   .thaw = hda_codec_pm_thaw,
+   .poweroff = hda_codec_pm_suspend,
+   .restore = hda_codec_pm_restore,
+#endif /* CONFIG_PM_SLEEP */
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
   NULL)
 };




[PATCH 4.19 43/45] ALSA: hda - Record the current power state before suspend/resume calls

2019-03-25 Thread Greg Kroah-Hartman
4.19-stable review patch.  If anyone has any objections, please let me know.

--

From: Takashi Iwai 

commit 98081ca62cbac31fb0f7efaf90b2e7384ce22257 upstream.

Currently we deal with single codec and suspend codec callbacks for
all S3, S4 and runtime PM handling.  But it turned out that we want
distinguish the call patterns sometimes, e.g. for applying some init
sequence only at probing and restoring from hibernate.

This patch slightly modifies the common PM callbacks for HD-audio
codec and stores the currently processed PM event in power_state of
the codec's device.power field, which is currently unused.  The codec
callback can take a look at this event value and judges which purpose
it's being called.

Signed-off-by: Takashi Iwai 
Signed-off-by: Greg Kroah-Hartman 

---
 sound/pci/hda/hda_codec.c |   43 +--
 1 file changed, 41 insertions(+), 2 deletions(-)

--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2909,6 +2909,7 @@ static void hda_call_codec_resume(struct
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
+   codec->core.dev.power.power_state = PMSG_ON;
snd_hdac_leave_pm(&codec->core);
 }
 
@@ -2942,10 +2943,48 @@ static int hda_codec_runtime_resume(stru
 }
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_SLEEP
+static int hda_codec_pm_suspend(struct device *dev)
+{
+   dev->power.power_state = PMSG_SUSPEND;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_resume(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESUME;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_freeze(struct device *dev)
+{
+   dev->power.power_state = PMSG_FREEZE;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_thaw(struct device *dev)
+{
+   dev->power.power_state = PMSG_THAW;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_restore(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESTORE;
+   return pm_runtime_force_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
 /* referred in hda_bind.c */
 const struct dev_pm_ops hda_codec_driver_pm = {
-   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-   pm_runtime_force_resume)
+#ifdef CONFIG_PM_SLEEP
+   .suspend = hda_codec_pm_suspend,
+   .resume = hda_codec_pm_resume,
+   .freeze = hda_codec_pm_freeze,
+   .thaw = hda_codec_pm_thaw,
+   .poweroff = hda_codec_pm_suspend,
+   .restore = hda_codec_pm_restore,
+#endif /* CONFIG_PM_SLEEP */
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
   NULL)
 };




[PATCH 4.9 17/30] ALSA: hda - Record the current power state before suspend/resume calls

2019-03-25 Thread Greg Kroah-Hartman
4.9-stable review patch.  If anyone has any objections, please let me know.

--

From: Takashi Iwai 

commit 98081ca62cbac31fb0f7efaf90b2e7384ce22257 upstream.

Currently we deal with single codec and suspend codec callbacks for
all S3, S4 and runtime PM handling.  But it turned out that we want
distinguish the call patterns sometimes, e.g. for applying some init
sequence only at probing and restoring from hibernate.

This patch slightly modifies the common PM callbacks for HD-audio
codec and stores the currently processed PM event in power_state of
the codec's device.power field, which is currently unused.  The codec
callback can take a look at this event value and judges which purpose
it's being called.

Signed-off-by: Takashi Iwai 
Signed-off-by: Greg Kroah-Hartman 

---
 sound/pci/hda/hda_codec.c |   43 +--
 1 file changed, 41 insertions(+), 2 deletions(-)

--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3004,6 +3004,7 @@ static void hda_call_codec_resume(struct
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
+   codec->core.dev.power.power_state = PMSG_ON;
atomic_dec(&codec->core.in_pm);
 }
 
@@ -3036,10 +3037,48 @@ static int hda_codec_runtime_resume(stru
 }
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_SLEEP
+static int hda_codec_pm_suspend(struct device *dev)
+{
+   dev->power.power_state = PMSG_SUSPEND;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_resume(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESUME;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_freeze(struct device *dev)
+{
+   dev->power.power_state = PMSG_FREEZE;
+   return pm_runtime_force_suspend(dev);
+}
+
+static int hda_codec_pm_thaw(struct device *dev)
+{
+   dev->power.power_state = PMSG_THAW;
+   return pm_runtime_force_resume(dev);
+}
+
+static int hda_codec_pm_restore(struct device *dev)
+{
+   dev->power.power_state = PMSG_RESTORE;
+   return pm_runtime_force_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
 /* referred in hda_bind.c */
 const struct dev_pm_ops hda_codec_driver_pm = {
-   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-   pm_runtime_force_resume)
+#ifdef CONFIG_PM_SLEEP
+   .suspend = hda_codec_pm_suspend,
+   .resume = hda_codec_pm_resume,
+   .freeze = hda_codec_pm_freeze,
+   .thaw = hda_codec_pm_thaw,
+   .poweroff = hda_codec_pm_suspend,
+   .restore = hda_codec_pm_restore,
+#endif /* CONFIG_PM_SLEEP */
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
   NULL)
 };




Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Guenter Roeck
On Mon, Mar 25, 2019 at 03:05:33PM +, Mark Brown wrote:
> On Mon, Mar 25, 2019 at 07:21:00AM -0700, Guenter Roeck wrote:
> 
> > It is actually a bit more complicated than that. The stored pointer 
> > (drv->soc_card)
> > isn't released. The problem is that dev_get_drvdata(drv->soc_card->dev) is 
> > NULL,
> > which causes the crash. I don't think there is a UAF involved - I built the
> > test image with KASAN enabled and it did not barf at me.
> 
> What is a "UAF"?
> 

use-after-free. Sorry, I saw that term used so often recently that I somehow
thought it was common and started using it myself.

Guenter

> > Overall the implementation does seem a bit suspicious to me. I don't really
> > understand why the platform driver handles suspend/resume for the cards.
> > But that may just be my lack of understanding. However, either case, I 
> > think the
> > Haswell driver (sst-haswell-pcm.c) has a similar problem. I am also not 
> > sure if
> 
> It's certainly a bit unusual, usually the platform driver would just
> deal with suspending itself and the card driver would handle overall
> card suspension together with the core.




Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Mark Brown
On Mon, Mar 25, 2019 at 07:21:00AM -0700, Guenter Roeck wrote:

> It is actually a bit more complicated than that. The stored pointer 
> (drv->soc_card)
> isn't released. The problem is that dev_get_drvdata(drv->soc_card->dev) is 
> NULL,
> which causes the crash. I don't think there is a UAF involved - I built the
> test image with KASAN enabled and it did not barf at me.

What is a "UAF"?

> Overall the implementation does seem a bit suspicious to me. I don't really
> understand why the platform driver handles suspend/resume for the cards.
> But that may just be my lack of understanding. However, either case, I think 
> the
> Haswell driver (sst-haswell-pcm.c) has a similar problem. I am also not sure 
> if

It's certainly a bit unusual, usually the platform driver would just
deal with suspending itself and the card driver would handle overall
card suspension together with the core.


signature.asc
Description: PGP signature


Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Mark Brown
On Mon, Mar 25, 2019 at 09:18:04AM -0400, Pierre-Louis Bossart wrote:
> On 3/25/19 8:12 AM, Mark Brown wrote:

> > These are driver specific issues not device model issues as far as I can
> > see?  The issue fixed by this as is that you're storing a pointer in the
> > ASoC level (not device model level) probe that you don't free when the
> > component is unbound, causing you to dereference it later during
> > suspend.  There is absolutely no problem with the machine driver not
> > being guaranteed to bind at the time it's initially registered, that's
> > perfectly normal and should cause no problems.

> Agree, what I was referring is that if the machine probe and card
> registration fails (not just deferred), the parent acpi/pci driver isn't
> notified - there is just no means to provide that information and that leads
> to all kinds of configuration issues.

If there are issues here they could happen via means other than a probe
failing so there's a problem whatever is going on - someone manually
unbinding a device for example.


signature.asc
Description: PGP signature


Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Guenter Roeck

On 3/25/19 5:12 AM, Mark Brown wrote:

On Sat, Mar 23, 2019 at 09:55:46AM -0400, Pierre-Louis Bossart wrote:


I'd like to highlight that there is a fundamental flaw in the way the
machine drivers are handled. Since we don't have a hook for the machine
driver in the BIOS, the DSP driver creates a platform_device which will
instantiate the machine driver. When errors happen in the machine driver
probe, they are suppressed due to a 'feature' of the device model, so you
can end-up with a broken configuration that is still reported as a
successful strobe.


These are driver specific issues not device model issues as far as I can
see?  The issue fixed by this as is that you're storing a pointer in the
ASoC level (not device model level) probe that you don't free when the
component is unbound, causing you to dereference it later during
suspend.  There is absolutely no problem with the machine driver not
being guaranteed to bind at the time it's initially registered, that's
perfectly normal and should cause no problems.


It is actually a bit more complicated than that. The stored pointer 
(drv->soc_card)
isn't released. The problem is that dev_get_drvdata(drv->soc_card->dev) is NULL,
which causes the crash. I don't think there is a UAF involved - I built the
test image with KASAN enabled and it did not barf at me.

It may of course well be that there _should_ be a UAF but it doesn't happen
because some pointer that should be released isn't released due to some memory
or reference count leak. But that would be a different problem.

Overall the implementation does seem a bit suspicious to me. I don't really
understand why the platform driver handles suspend/resume for the cards.
But that may just be my lack of understanding. However, either case, I think the
Haswell driver (sst-haswell-pcm.c) has a similar problem. I am also not sure if
there are more problems lurking - I see a similar but different crash in v4.4.y
but have not been able to track it down. Actually, I found the problem fixed 
here
while trying to reproduce that crash with the latest kernel.

Guenter


[PATCH v2 1/2] pinctrl: pinctrl-imx: Add suspend/resume for LPSR

2019-03-25 Thread Abel Vesa
From: Robin Gong 

To support pinctl hog restore after LPSR resume back,
add suspend/resume in pinctrl driver.

Signed-off-by: Robin Gong 
Signed-off-by: Abel Vesa 
---

Changes since v1:
 * fixed Robin's email

 drivers/pinctrl/freescale/pinctrl-imx.c | 20 
 drivers/pinctrl/freescale/pinctrl-imx.h |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c 
b/drivers/pinctrl/freescale/pinctrl-imx.c
index 188001b..93c0253 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -887,3 +887,23 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 
return ret;
 }
+
+int imx_pinctrl_suspend(struct device *dev)
+{
+   struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+   if (!ipctl)
+   return -EINVAL;
+
+   return pinctrl_force_sleep(ipctl->pctl);
+}
+
+int imx_pinctrl_resume(struct device *dev)
+{
+   struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+   if (!ipctl)
+   return -EINVAL;
+
+   return pinctrl_force_default(ipctl->pctl);
+}
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h 
b/drivers/pinctrl/freescale/pinctrl-imx.h
index 98a4889..795669c 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -136,6 +136,9 @@ struct imx_pinctrl {
 int imx_pinctrl_probe(struct platform_device *pdev,
const struct imx_pinctrl_soc_info *info);
 
+int imx_pinctrl_suspend(struct device *dev);
+int imx_pinctrl_resume(struct device *dev);
+
 #ifdef CONFIG_PINCTRL_IMX_SCU
 #define BM_PAD_CTL_GP_ENABLE   BIT(30)
 #define BM_PAD_CTL_IFMUX_ENABLEBIT(31)
-- 
2.7.4



Re: [PATCH 1/2] pinctrl: pinctrl-imx: Add suspend/resume for LPSR

2019-03-25 Thread Daniel Baluta
On Mon, Mar 25, 2019 at 3:49 PM Abel Vesa  wrote:
>
> From: Robin Gong 

Please fix Robin's email.


[PATCH 1/2] pinctrl: pinctrl-imx: Add suspend/resume for LPSR

2019-03-25 Thread Abel Vesa
From: Robin Gong 

To support pinctl hog restore after LPSR resume back,
add suspend/resume in pinctrl driver.

Signed-off-by: Robin Gong 
Signed-off-by: Abel Vesa 
---
 drivers/pinctrl/freescale/pinctrl-imx.c | 20 
 drivers/pinctrl/freescale/pinctrl-imx.h |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c 
b/drivers/pinctrl/freescale/pinctrl-imx.c
index 188001b..93c0253 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -887,3 +887,23 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 
return ret;
 }
+
+int imx_pinctrl_suspend(struct device *dev)
+{
+   struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+   if (!ipctl)
+   return -EINVAL;
+
+   return pinctrl_force_sleep(ipctl->pctl);
+}
+
+int imx_pinctrl_resume(struct device *dev)
+{
+   struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+   if (!ipctl)
+   return -EINVAL;
+
+   return pinctrl_force_default(ipctl->pctl);
+}
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h 
b/drivers/pinctrl/freescale/pinctrl-imx.h
index 98a4889..795669c 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -136,6 +136,9 @@ struct imx_pinctrl {
 int imx_pinctrl_probe(struct platform_device *pdev,
const struct imx_pinctrl_soc_info *info);
 
+int imx_pinctrl_suspend(struct device *dev);
+int imx_pinctrl_resume(struct device *dev);
+
 #ifdef CONFIG_PINCTRL_IMX_SCU
 #define BM_PAD_CTL_GP_ENABLE   BIT(30)
 #define BM_PAD_CTL_IFMUX_ENABLEBIT(31)
-- 
2.7.4



Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Pierre-Louis Bossart

On 3/25/19 8:12 AM, Mark Brown wrote:

On Sat, Mar 23, 2019 at 09:55:46AM -0400, Pierre-Louis Bossart wrote:


I'd like to highlight that there is a fundamental flaw in the way the
machine drivers are handled. Since we don't have a hook for the machine
driver in the BIOS, the DSP driver creates a platform_device which will
instantiate the machine driver. When errors happen in the machine driver
probe, they are suppressed due to a 'feature' of the device model, so you
can end-up with a broken configuration that is still reported as a
successful strobe.


These are driver specific issues not device model issues as far as I can
see?  The issue fixed by this as is that you're storing a pointer in the
ASoC level (not device model level) probe that you don't free when the
component is unbound, causing you to dereference it later during
suspend.  There is absolutely no problem with the machine driver not
being guaranteed to bind at the time it's initially registered, that's
perfectly normal and should cause no problems.


Agree, what I was referring is that if the machine probe and card 
registration fails (not just deferred), the parent acpi/pci driver isn't 
notified - there is just no means to provide that information and that 
leads to all kinds of configuration issues.


Applied "ASoC: intel: Fix crash at suspend/resume after failed codec registration" to the asoc tree

2019-03-25 Thread Mark Brown
The patch

   ASoC: intel: Fix crash at suspend/resume after failed codec registration

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 8f71370f4b02730e8c27faf460af7a3586e24e1f Mon Sep 17 00:00:00 2001
From: Guenter Roeck 
Date: Fri, 22 Mar 2019 15:39:48 -0700
Subject: [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec
 registration

If codec registration fails after the ASoC Intel SST driver has been probed,
the kernel will Oops and crash at suspend/resume.

general protection fault:  [#1] PREEMPT SMP KASAN PTI
CPU: 1 PID: 2811 Comm: cat Tainted: GW 4.19.30 #15
Hardware name: GOOGLE Clapper, BIOS Google_Clapper.5216.199.7 08/22/2014
RIP: 0010:snd_soc_suspend+0x5a/0xd21
Code: 03 80 3c 10 00 49 89 d7 74 0b 48 89 df e8 71 72 c4 fe 4c 89
fa 48 8b 03 48 89 45 d0 48 8d 98 a0 01 00 00 48 89 d8 48 c1 e8 03
<8a> 04 10 84 c0 0f 85 85 0c 00 00 80 3b 00 0f 84 6b 0c 00 00 48 8b
RSP: 0018:888035407750 EFLAGS: 00010202
RAX: 0034 RBX: 01a0 RCX: 
RDX: dc00 RSI: 0008 RDI: 88805c417098
RBP: 8880354077b0 R08: dc00 R09: ed100b975718
R10: 0001 R11: 949ea4a3 R12: 11100b975746
R13: dc00 R14: 88805cba4588 R15: dc00
FS:  794a78e91b80() GS:888068d0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 7bd5283ccf58 CR3: 4b7aa000 CR4: 001006e0
Call Trace:
? dpm_complete+0x67b/0x67b
? i915_gem_suspend+0x14d/0x1ad
sst_soc_prepare+0x91/0x1dd
? sst_be_hw_params+0x7e/0x7e
dpm_prepare+0x39a/0x88b
dpm_suspend_start+0x13/0x9d
suspend_devices_and_enter+0x18f/0xbd7
? arch_suspend_enable_irqs+0x11/0x11
? printk+0xd9/0x12d
? lock_release+0x95f/0x95f
? log_buf_vmcoreinfo_setup+0x131/0x131
? rcu_read_lock_sched_held+0x140/0x22a
? __bpf_trace_rcu_utilization+0xa/0xa
? __pm_pr_dbg+0x186/0x190
? pm_notifier_call_chain+0x39/0x39
? suspend_test+0x9d/0x9d
pm_suspend+0x2f4/0x728
? trace_suspend_resume+0x3da/0x3da
? lock_release+0x95f/0x95f
? kernfs_fop_write+0x19f/0x32d
state_store+0xd8/0x147
? sysfs_kf_read+0x155/0x155
kernfs_fop_write+0x23e/0x32d
__vfs_write+0x108/0x608
? vfs_read+0x2e9/0x2e9
? rcu_read_lock_sched_held+0x140/0x22a
? __bpf_trace_rcu_utilization+0xa/0xa
? debug_smp_processor_id+0x10/0x10
? selinux_file_permission+0x1c5/0x3c8
? rcu_sync_lockdep_assert+0x6a/0xad
? __sb_start_write+0x129/0x2ac
vfs_write+0x1aa/0x434
ksys_write+0xfe/0x1be
? __ia32_sys_read+0x82/0x82
do_syscall_64+0xcd/0x120
entry_SYSCALL_64_after_hwframe+0x49/0xbe

In the observed situation, the problem is seen because the codec driver
failed to probe due to a hardware problem.

max98090 i2c-193C9890:00: Failed to read device revision: -1
max98090 i2c-193C9890:00: ASoC: failed to probe component -1
cht-bsw-max98090 cht-bsw-max98090: ASoC: failed to instantiate card -1
cht-bsw-max98090 cht-bsw-max98090: snd_soc_register_card failed -1
cht-bsw-max98090: probe of cht-bsw-max98090 failed with error -1

The problem is similar to the problem solved with commit 2fc995a87f2e
("ASoC: intel: Fix crash at suspend/resume without card registration"),
but codec registration fails at a later point. At that time, the pointer
checked with the above mentioned commit is already set, but it is not
cleared if the device is subsequently removed. Adding a remove function
to clear the pointer fixes the problem.

Cc: sta...@vger.kernel.org
Cc: Jarkko Nikula 
Cc: Curtis Malainey 
Signed-off-by: Guenter Roeck 
Acked-by: Pierre-Louis Bossart 
Signed-off-by: Mark Brown 
---
 sound/soc/intel/atom/sst-mfld-platform-pcm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c 
b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 08cea5b5cda9..0e8b1c5eec88 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -706,9 +706,17 @@ static int sst_soc_probe(struct snd_soc_component 
*component)
return sst_dsp_init_v2_dpcm(component);
 }
 
+static void sst_soc_remove(struct snd_soc_component *component)
+{
+   s

Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Mark Brown
On Sat, Mar 23, 2019 at 09:55:46AM -0400, Pierre-Louis Bossart wrote:

> I'd like to highlight that there is a fundamental flaw in the way the
> machine drivers are handled. Since we don't have a hook for the machine
> driver in the BIOS, the DSP driver creates a platform_device which will
> instantiate the machine driver. When errors happen in the machine driver
> probe, they are suppressed due to a 'feature' of the device model, so you
> can end-up with a broken configuration that is still reported as a
> successful strobe.

These are driver specific issues not device model issues as far as I can
see?  The issue fixed by this as is that you're storing a pointer in the
ASoC level (not device model level) probe that you don't free when the
component is unbound, causing you to dereference it later during
suspend.  There is absolutely no problem with the machine driver not
being guaranteed to bind at the time it's initially registered, that's
perfectly normal and should cause no problems.


signature.asc
Description: PGP signature


Re: [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-25 Thread Mark Brown
On Fri, Mar 22, 2019 at 03:39:48PM -0700, Guenter Roeck wrote:

> general protection fault:  [#1] PREEMPT SMP KASAN PTI
> CPU: 1 PID: 2811 Comm: cat Tainted: GW 4.19.30 #15
> Hardware name: GOOGLE Clapper, BIOS Google_Clapper.5216.199.7 08/22/2014
> RIP: 0010:snd_soc_suspend+0x5a/0xd21
> Code: 03 80 3c 10 00 49 89 d7 74 0b 48 89 df e8 71 72 c4 fe 4c 89
> fa 48 8b 03 48 89 45 d0 48 8d 98 a0 01 00 00 48 89 d8 48 c1 e8 03
> <8a> 04 10 84 c0 0f 85 85 0c 00 00 80 3b 00 0f 84 6b 0c 00 00 48 8b

Please think hard before including complete backtraces in upstream
reports, they are very large and contain almost no useful information
relative to their size so often obscure the relevant content in your
message. If part of the backtrace is usefully illustrative then it's
usually better to pull out the relevant sections.


signature.asc
Description: PGP signature


Re: [alsa-devel] [PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-23 Thread Pierre-Louis Bossart

On 3/22/19 6:39 PM, Guenter Roeck wrote:

If codec registration fails after the ASoC Intel SST driver has been probed,
the kernel will Oops and crash at suspend/resume.

general protection fault:  [#1] PREEMPT SMP KASAN PTI
CPU: 1 PID: 2811 Comm: cat Tainted: GW 4.19.30 #15
Hardware name: GOOGLE Clapper, BIOS Google_Clapper.5216.199.7 08/22/2014
RIP: 0010:snd_soc_suspend+0x5a/0xd21
Code: 03 80 3c 10 00 49 89 d7 74 0b 48 89 df e8 71 72 c4 fe 4c 89
fa 48 8b 03 48 89 45 d0 48 8d 98 a0 01 00 00 48 89 d8 48 c1 e8 03
<8a> 04 10 84 c0 0f 85 85 0c 00 00 80 3b 00 0f 84 6b 0c 00 00 48 8b
RSP: 0018:888035407750 EFLAGS: 00010202
RAX: 0034 RBX: 01a0 RCX: 
RDX: dc00 RSI: 0008 RDI: 88805c417098
RBP: 8880354077b0 R08: dc00 R09: ed100b975718
R10: 0001 R11: 949ea4a3 R12: 11100b975746
R13: dc00 R14: 88805cba4588 R15: dc00
FS:  794a78e91b80() GS:888068d0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 7bd5283ccf58 CR3: 4b7aa000 CR4: 001006e0
Call Trace:
? dpm_complete+0x67b/0x67b
? i915_gem_suspend+0x14d/0x1ad
sst_soc_prepare+0x91/0x1dd
? sst_be_hw_params+0x7e/0x7e
dpm_prepare+0x39a/0x88b
dpm_suspend_start+0x13/0x9d
suspend_devices_and_enter+0x18f/0xbd7
? arch_suspend_enable_irqs+0x11/0x11
? printk+0xd9/0x12d
? lock_release+0x95f/0x95f
? log_buf_vmcoreinfo_setup+0x131/0x131
? rcu_read_lock_sched_held+0x140/0x22a
? __bpf_trace_rcu_utilization+0xa/0xa
? __pm_pr_dbg+0x186/0x190
? pm_notifier_call_chain+0x39/0x39
? suspend_test+0x9d/0x9d
pm_suspend+0x2f4/0x728
? trace_suspend_resume+0x3da/0x3da
? lock_release+0x95f/0x95f
? kernfs_fop_write+0x19f/0x32d
state_store+0xd8/0x147
? sysfs_kf_read+0x155/0x155
kernfs_fop_write+0x23e/0x32d
__vfs_write+0x108/0x608
? vfs_read+0x2e9/0x2e9
? rcu_read_lock_sched_held+0x140/0x22a
? __bpf_trace_rcu_utilization+0xa/0xa
? debug_smp_processor_id+0x10/0x10
? selinux_file_permission+0x1c5/0x3c8
? rcu_sync_lockdep_assert+0x6a/0xad
? __sb_start_write+0x129/0x2ac
vfs_write+0x1aa/0x434
ksys_write+0xfe/0x1be
? __ia32_sys_read+0x82/0x82
do_syscall_64+0xcd/0x120
entry_SYSCALL_64_after_hwframe+0x49/0xbe

In the observed situation, the problem is seen because the codec driver
failed to probe due to a hardware problem.

max98090 i2c-193C9890:00: Failed to read device revision: -1
max98090 i2c-193C9890:00: ASoC: failed to probe component -1
cht-bsw-max98090 cht-bsw-max98090: ASoC: failed to instantiate card -1
cht-bsw-max98090 cht-bsw-max98090: snd_soc_register_card failed -1
cht-bsw-max98090: probe of cht-bsw-max98090 failed with error -1

The problem is similar to the problem solved with commit 2fc995a87f2e
("ASoC: intel: Fix crash at suspend/resume without card registration"),
but codec registration fails at a later point. At that time, the pointer
checked with the above mentioned commit is already set, but it is not
cleared if the device is subsequently removed. Adding a remove function
to clear the pointer fixes the problem.


Makes sense

Acked-by: Pierre-Louis Bossart 

I'd like to highlight that there is a fundamental flaw in the way the 
machine drivers are handled. Since we don't have a hook for the machine 
driver in the BIOS, the DSP driver creates a platform_device which will 
instantiate the machine driver. When errors happen in the machine driver 
probe, they are suppressed due to a 'feature' of the device model, so 
you can end-up with a broken configuration that is still reported as a 
successful strobe.




Cc: sta...@vger.kernel.org
Cc: Jarkko Nikula 
Cc: Curtis Malainey 
Signed-off-by: Guenter Roeck 
---
  sound/soc/intel/atom/sst-mfld-platform-pcm.c | 8 
  1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c 
b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 08cea5b5cda9..0e8b1c5eec88 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -706,9 +706,17 @@ static int sst_soc_probe(struct snd_soc_component 
*component)
return sst_dsp_init_v2_dpcm(component);
  }
  
+static void sst_soc_remove(struct snd_soc_component *component)

+{
+   struct sst_data *drv = dev_get_drvdata(component->dev);
+
+   drv->soc_card = NULL;
+}
+
  static const struct snd_soc_component_driver sst_soc_platform_drv  = {
.name   = DRV_NAME,
.probe  = sst_soc_probe,
+   .remove = sst_soc_remove,
.ops= &sst_platform_ops,
.compr_ops  = &sst_platform_compr_ops,
.pcm_new= sst_pcm_new,





[PATCH] ASoC: intel: Fix crash at suspend/resume after failed codec registration

2019-03-22 Thread Guenter Roeck
If codec registration fails after the ASoC Intel SST driver has been probed,
the kernel will Oops and crash at suspend/resume.

general protection fault:  [#1] PREEMPT SMP KASAN PTI
CPU: 1 PID: 2811 Comm: cat Tainted: GW 4.19.30 #15
Hardware name: GOOGLE Clapper, BIOS Google_Clapper.5216.199.7 08/22/2014
RIP: 0010:snd_soc_suspend+0x5a/0xd21
Code: 03 80 3c 10 00 49 89 d7 74 0b 48 89 df e8 71 72 c4 fe 4c 89
fa 48 8b 03 48 89 45 d0 48 8d 98 a0 01 00 00 48 89 d8 48 c1 e8 03
<8a> 04 10 84 c0 0f 85 85 0c 00 00 80 3b 00 0f 84 6b 0c 00 00 48 8b
RSP: 0018:888035407750 EFLAGS: 00010202
RAX: 0034 RBX: 01a0 RCX: 
RDX: dc00 RSI: 0008 RDI: 88805c417098
RBP: 8880354077b0 R08: dc00 R09: ed100b975718
R10: 0001 R11: 949ea4a3 R12: 11100b975746
R13: dc00 R14: 88805cba4588 R15: dc00
FS:  794a78e91b80() GS:888068d0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 7bd5283ccf58 CR3: 4b7aa000 CR4: 001006e0
Call Trace:
? dpm_complete+0x67b/0x67b
? i915_gem_suspend+0x14d/0x1ad
sst_soc_prepare+0x91/0x1dd
? sst_be_hw_params+0x7e/0x7e
dpm_prepare+0x39a/0x88b
dpm_suspend_start+0x13/0x9d
suspend_devices_and_enter+0x18f/0xbd7
? arch_suspend_enable_irqs+0x11/0x11
? printk+0xd9/0x12d
? lock_release+0x95f/0x95f
? log_buf_vmcoreinfo_setup+0x131/0x131
? rcu_read_lock_sched_held+0x140/0x22a
? __bpf_trace_rcu_utilization+0xa/0xa
? __pm_pr_dbg+0x186/0x190
? pm_notifier_call_chain+0x39/0x39
? suspend_test+0x9d/0x9d
pm_suspend+0x2f4/0x728
? trace_suspend_resume+0x3da/0x3da
? lock_release+0x95f/0x95f
? kernfs_fop_write+0x19f/0x32d
state_store+0xd8/0x147
? sysfs_kf_read+0x155/0x155
kernfs_fop_write+0x23e/0x32d
__vfs_write+0x108/0x608
? vfs_read+0x2e9/0x2e9
? rcu_read_lock_sched_held+0x140/0x22a
? __bpf_trace_rcu_utilization+0xa/0xa
? debug_smp_processor_id+0x10/0x10
? selinux_file_permission+0x1c5/0x3c8
? rcu_sync_lockdep_assert+0x6a/0xad
? __sb_start_write+0x129/0x2ac
vfs_write+0x1aa/0x434
ksys_write+0xfe/0x1be
? __ia32_sys_read+0x82/0x82
do_syscall_64+0xcd/0x120
entry_SYSCALL_64_after_hwframe+0x49/0xbe

In the observed situation, the problem is seen because the codec driver
failed to probe due to a hardware problem.

max98090 i2c-193C9890:00: Failed to read device revision: -1
max98090 i2c-193C9890:00: ASoC: failed to probe component -1
cht-bsw-max98090 cht-bsw-max98090: ASoC: failed to instantiate card -1
cht-bsw-max98090 cht-bsw-max98090: snd_soc_register_card failed -1
cht-bsw-max98090: probe of cht-bsw-max98090 failed with error -1

The problem is similar to the problem solved with commit 2fc995a87f2e
("ASoC: intel: Fix crash at suspend/resume without card registration"),
but codec registration fails at a later point. At that time, the pointer
checked with the above mentioned commit is already set, but it is not
cleared if the device is subsequently removed. Adding a remove function
to clear the pointer fixes the problem.

Cc: sta...@vger.kernel.org
Cc: Jarkko Nikula 
Cc: Curtis Malainey 
Signed-off-by: Guenter Roeck 
---
 sound/soc/intel/atom/sst-mfld-platform-pcm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c 
b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 08cea5b5cda9..0e8b1c5eec88 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -706,9 +706,17 @@ static int sst_soc_probe(struct snd_soc_component 
*component)
return sst_dsp_init_v2_dpcm(component);
 }
 
+static void sst_soc_remove(struct snd_soc_component *component)
+{
+   struct sst_data *drv = dev_get_drvdata(component->dev);
+
+   drv->soc_card = NULL;
+}
+
 static const struct snd_soc_component_driver sst_soc_platform_drv  = {
.name   = DRV_NAME,
.probe  = sst_soc_probe,
+   .remove = sst_soc_remove,
.ops= &sst_platform_ops,
.compr_ops  = &sst_platform_compr_ops,
.pcm_new= sst_pcm_new,
-- 
2.7.4



[BACKPORT 4.4.y 13/25] extcon: usb-gpio: Don't miss event during suspend/resume

2019-03-22 Thread Arnd Bergmann
From: Roger Quadros 

Pin state might have changed during suspend/resume while
our interrupts were disabled and if device doesn't support wakeup.

Scan for change during resume for such case.

Signed-off-by: Roger Quadros 
Signed-off-by: Chanwoo Choi 
(cherry picked from commit 04c080080855ce84dcd490a2e04805608a21085d)
Signed-off-by: Arnd Bergmann 
---
 drivers/extcon/extcon-usb-gpio.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index 2b2fecffb1ad..c6a7c9ddf0ac 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -192,6 +192,9 @@ static int usb_extcon_resume(struct device *dev)
}
 
enable_irq(info->id_irq);
+   if (!device_may_wakeup(dev))
+   queue_delayed_work(system_power_efficient_wq,
+  &info->wq_detcable, 0);
 
return ret;
 }
-- 
2.20.0



Re: [PATCH] rtc: cros-ec: Fail suspend/resume if wake IRQ can't be configured

2019-03-20 Thread Alexandre Belloni
On 15/03/2019 11:51:12-0700, Stephen Boyd wrote:
> If we encounter a failure during suspend where this RTC was programmed
> to wakeup the system from suspend, but that wakeup couldn't be
> configured because the system didn't support wakeup interrupts, we'll
> run into the following warning:
> 
>   Unbalanced IRQ 166 wake disable
>   WARNING: CPU: 7 PID: 3071 at kernel/irq/manage.c:669 
> irq_set_irq_wake+0x108/0x278
> 
> This happens because the suspend process isn't aborted when the RTC
> fails to configure the wakeup IRQ. Instead, we continue suspending the
> system and then another suspend callback fails the suspend process and
> "unwinds" the previously suspended drivers by calling their resume
> callbacks. When we get back to resuming this RTC driver, we'll call
> disable_irq_wake() on an IRQ that hasn't been configured for wake.
> 
> Let's just fail suspend/resume here if we can't configure the system to
> wake and the user has chosen to wakeup with this device. This fixes this
> warning and makes the code more robust in case there are systems out
> there that can't wakeup from suspend on this line but the user has
> chosen to do so.
> 
> Cc: Enric Balletbo i Serra 
> Cc: Evan Green 
> Cc: Benson Leung 
> Cc: Guenter Roeck 
> Signed-off-by: Stephen Boyd 
> ---
>  drivers/rtc/rtc-cros-ec.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
Applied, thanks.

-- 
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


[PATCH v10 7/7] ARM: tegra: Add firmware calls required for suspend-resume on Tegra30

2019-03-17 Thread Dmitry Osipenko
In order to suspend-resume CPU with Trusted Foundations firmware being
present on Tegra30, the LP1/LP2 boot vectors and CPU caches need to be
set up using the firmware calls and then suspend code shall avoid
re-disabling parts that were disabled by the firmware.

Tested-by: Robert Yang 
Tested-by: Michał Mirosław 
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 49 +
 arch/arm/mach-tegra/reset-handler.S | 26 +++
 arch/arm/mach-tegra/sleep.S | 14 ++---
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..abf5f88778f4 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,11 +33,13 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "iomap.h"
 #include "pm.h"
@@ -159,6 +161,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+   /*
+* L2 cache disabling using kernel API only allowed when all
+* secondary CPU's are offline. Cache have to be disabled with
+* MMU-on if cache maintenance is done via Trusted Foundations
+* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+* if any of secondary CPU's is online and this is the LP2-idle
+* code-path only for Tegra20/30.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   /*
+* Note that besides of setting up CPU reset vector this firmware
+* call may also do the following, depending on the FW version:
+*  1) Disable L2. But this doesn't matter since we already
+* disabled the L2.
+*  2) Disable D-cache. This need to be taken into account in
+* particular by the tegra_disable_clean_inv_dcache() which
+* shall avoid the re-disable.
+*/
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
setup_mm_for_reboot();
tegra_sleep_cpu_finish(v2p);
 
@@ -197,6 +221,14 @@ void tegra_idle_lp2_last(void)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
+*/
+   outer_resume();
+
restore_cpu_complex();
cpu_cluster_pm_exit();
 }
@@ -215,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+   /*
+* Cache have to be disabled with MMU-on if cache maintenance is done
+* via Trusted Foundations firmware. This is a no-op on Tegra114+.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
setup_mm_for_reboot();
tegra_sleep_core_finish(v2p);
 
@@ -342,6 +383,14 @@ static int tegra_suspend_enter(suspend_state_t state)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op.
+*/
+   outer_resume();
+
switch (mode) {
case TEGRA_SUSPEND_LP1:
tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index 31fb53f9ce13..cd94d7c41fc0 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   RESET_DATA(TF_PRESENT)
+   ldr r1, [r2, r1]
+   cmp r1, #0
+   reteq   lr
+
+ .arch_extension sec
+   /*

[PATCH 2/3] habanalabs: prevent host crash during suspend/resume

2019-03-16 Thread Oded Gabbay
This patch fixes the implementation of suspend/resume of the device so that
upon resume of the device, the host won't crash due to PCI completion
timeout.

Upon suspend, the device is being reset due to PERST. Therefore, upon
resume, the driver must initialize the PCI controller as if the driver was
loaded. If the controller is not initialized and the device tries to
access the device through the PCI bars, the host will crash with PCI
completion timeout error.

Signed-off-by: Oded Gabbay 
---
 drivers/misc/habanalabs/device.c| 46 +++--
 drivers/misc/habanalabs/goya/goya.c | 63 +
 2 files changed, 43 insertions(+), 66 deletions(-)

diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c
index 470d8005b50e..77d51be66c7e 100644
--- a/drivers/misc/habanalabs/device.c
+++ b/drivers/misc/habanalabs/device.c
@@ -416,6 +416,27 @@ int hl_device_suspend(struct hl_device *hdev)
 
pci_save_state(hdev->pdev);
 
+   /* Block future CS/VM/JOB completion operations */
+   rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
+   if (rc) {
+   dev_err(hdev->dev, "Can't suspend while in reset\n");
+   return -EIO;
+   }
+
+   /* This blocks all other stuff that is not blocked by in_reset */
+   hdev->disabled = true;
+
+   /*
+* Flush anyone that is inside the critical section of enqueue
+* jobs to the H/W
+*/
+   hdev->asic_funcs->hw_queues_lock(hdev);
+   hdev->asic_funcs->hw_queues_unlock(hdev);
+
+   /* Flush processes that are sending message to CPU */
+   mutex_lock(&hdev->send_cpu_message_lock);
+   mutex_unlock(&hdev->send_cpu_message_lock);
+
rc = hdev->asic_funcs->suspend(hdev);
if (rc)
dev_err(hdev->dev,
@@ -443,21 +464,38 @@ int hl_device_resume(struct hl_device *hdev)
 
pci_set_power_state(hdev->pdev, PCI_D0);
pci_restore_state(hdev->pdev);
-   rc = pci_enable_device(hdev->pdev);
+   rc = pci_enable_device_mem(hdev->pdev);
if (rc) {
dev_err(hdev->dev,
"Failed to enable PCI device in resume\n");
return rc;
}
 
+   pci_set_master(hdev->pdev);
+
rc = hdev->asic_funcs->resume(hdev);
if (rc) {
-   dev_err(hdev->dev,
-   "Failed to enable PCI access from device CPU\n");
-   return rc;
+   dev_err(hdev->dev, "Failed to resume device after suspend\n");
+   goto disable_device;
+   }
+
+
+   hdev->disabled = false;
+   atomic_set(&hdev->in_reset, 0);
+
+   rc = hl_device_reset(hdev, true, false);
+   if (rc) {
+   dev_err(hdev->dev, "Failed to reset device during resume\n");
+   goto disable_device;
}
 
return 0;
+
+disable_device:
+   pci_clear_master(hdev->pdev);
+   pci_disable_device(hdev->pdev);
+
+   return rc;
 }
 
 static void hl_device_hard_reset_pending(struct work_struct *work)
diff --git a/drivers/misc/habanalabs/goya/goya.c 
b/drivers/misc/habanalabs/goya/goya.c
index 238dd57c541b..538d8d59d9dc 100644
--- a/drivers/misc/habanalabs/goya/goya.c
+++ b/drivers/misc/habanalabs/goya/goya.c
@@ -1201,15 +1201,6 @@ static int goya_stop_external_queues(struct hl_device 
*hdev)
return retval;
 }
 
-static void goya_resume_external_queues(struct hl_device *hdev)
-{
-   WREG32(mmDMA_QM_0_GLBL_CFG1, 0);
-   WREG32(mmDMA_QM_1_GLBL_CFG1, 0);
-   WREG32(mmDMA_QM_2_GLBL_CFG1, 0);
-   WREG32(mmDMA_QM_3_GLBL_CFG1, 0);
-   WREG32(mmDMA_QM_4_GLBL_CFG1, 0);
-}
-
 /*
  * goya_init_cpu_queues - Initialize PQ/CQ/EQ of CPU
  *
@@ -2178,36 +2169,6 @@ static int goya_stop_internal_queues(struct hl_device 
*hdev)
return retval;
 }
 
-static void goya_resume_internal_queues(struct hl_device *hdev)
-{
-   WREG32(mmMME_QM_GLBL_CFG1, 0);
-   WREG32(mmMME_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC0_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC0_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC1_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC1_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC2_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC2_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC3_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC3_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC4_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC4_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC5_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC5_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC6_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC6_CMDQ_GLBL_CFG1, 0);
-
-   WREG32(mmTPC7_QM_GLBL_CFG1, 0);
-   WREG32(mmTPC7_CMDQ_GLBL_CFG1, 0);
-}
-
 static void goya_dma_stall(struct hl_device *hdev)
 {
WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT);
@@ -2905,20 +2866,

Re: [PATCH] rtc: cros-ec: Fail suspend/resume if wake IRQ can't be configured

2019-03-15 Thread Benson Leung
Hi Stephen,

On Fri, Mar 15, 2019 at 11:51:12AM -0700, Stephen Boyd wrote:
> If we encounter a failure during suspend where this RTC was programmed
> to wakeup the system from suspend, but that wakeup couldn't be
> configured because the system didn't support wakeup interrupts, we'll
> run into the following warning:
> 
>   Unbalanced IRQ 166 wake disable
>   WARNING: CPU: 7 PID: 3071 at kernel/irq/manage.c:669 
> irq_set_irq_wake+0x108/0x278
> 
> This happens because the suspend process isn't aborted when the RTC
> fails to configure the wakeup IRQ. Instead, we continue suspending the
> system and then another suspend callback fails the suspend process and
> "unwinds" the previously suspended drivers by calling their resume
> callbacks. When we get back to resuming this RTC driver, we'll call
> disable_irq_wake() on an IRQ that hasn't been configured for wake.
> 
> Let's just fail suspend/resume here if we can't configure the system to
> wake and the user has chosen to wakeup with this device. This fixes this
> warning and makes the code more robust in case there are systems out
> there that can't wakeup from suspend on this line but the user has
> chosen to do so.
> 
> Cc: Enric Balletbo i Serra 
> Cc: Evan Green 
> Cc: Benson Leung 
> Cc: Guenter Roeck 
> Signed-off-by: Stephen Boyd 

Acked-By: Benson Leung 


-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
ble...@google.com
Chromium OS Project
ble...@chromium.org


signature.asc
Description: PGP signature


[PATCH] rtc: cros-ec: Fail suspend/resume if wake IRQ can't be configured

2019-03-15 Thread Stephen Boyd
If we encounter a failure during suspend where this RTC was programmed
to wakeup the system from suspend, but that wakeup couldn't be
configured because the system didn't support wakeup interrupts, we'll
run into the following warning:

Unbalanced IRQ 166 wake disable
WARNING: CPU: 7 PID: 3071 at kernel/irq/manage.c:669 
irq_set_irq_wake+0x108/0x278

This happens because the suspend process isn't aborted when the RTC
fails to configure the wakeup IRQ. Instead, we continue suspending the
system and then another suspend callback fails the suspend process and
"unwinds" the previously suspended drivers by calling their resume
callbacks. When we get back to resuming this RTC driver, we'll call
disable_irq_wake() on an IRQ that hasn't been configured for wake.

Let's just fail suspend/resume here if we can't configure the system to
wake and the user has chosen to wakeup with this device. This fixes this
warning and makes the code more robust in case there are systems out
there that can't wakeup from suspend on this line but the user has
chosen to do so.

Cc: Enric Balletbo i Serra 
Cc: Evan Green 
Cc: Benson Leung 
Cc: Guenter Roeck 
Signed-off-by: Stephen Boyd 
---
 drivers/rtc/rtc-cros-ec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
index e5444296075e..4d6bf9304ceb 100644
--- a/drivers/rtc/rtc-cros-ec.c
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -298,7 +298,7 @@ static int cros_ec_rtc_suspend(struct device *dev)
struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
 
if (device_may_wakeup(dev))
-   enable_irq_wake(cros_ec_rtc->cros_ec->irq);
+   return enable_irq_wake(cros_ec_rtc->cros_ec->irq);
 
return 0;
 }
@@ -309,7 +309,7 @@ static int cros_ec_rtc_resume(struct device *dev)
struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
 
if (device_may_wakeup(dev))
-   disable_irq_wake(cros_ec_rtc->cros_ec->irq);
+   return disable_irq_wake(cros_ec_rtc->cros_ec->irq);
 
return 0;
 }
-- 
Sent by a computer through tubes



Applied "spi: spi-mem: stm32-qspi: add suspend/resume support" to the spi tree

2019-03-15 Thread Mark Brown
The patch

   spi: spi-mem: stm32-qspi: add suspend/resume support

has been applied to the spi tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 2e541b64ee5269278fde5c87953a9963a8219ed4 Mon Sep 17 00:00:00 2001
From: Ludovic Barre 
Date: Fri, 8 Mar 2019 14:12:21 +0100
Subject: [PATCH] spi: spi-mem: stm32-qspi: add suspend/resume support

This patch adds suspend and resume support for spi-stm32-qspi
drivers.

Signed-off-by: Ludovic Barre 
Signed-off-by: Mark Brown 
---
 drivers/spi/spi-stm32-qspi.c | 39 
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
index 7354f9d68dba..3e8ca10011cc 100644
--- a/drivers/spi/spi-stm32-qspi.c
+++ b/drivers/spi/spi-stm32-qspi.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -101,6 +102,9 @@ struct stm32_qspi {
struct completion data_completion;
u32 fmode;
 
+   u32 cr_reg;
+   u32 dcr_reg;
+
/*
 * to protect device configuration, could be different between
 * 2 flash access (bk1, bk2)
@@ -355,7 +359,7 @@ static int stm32_qspi_setup(struct spi_device *spi)
struct spi_controller *ctrl = spi->master;
struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
struct stm32_qspi_flash *flash;
-   u32 cr, presc;
+   u32 presc;
 
if (ctrl->busy)
return -EBUSY;
@@ -371,11 +375,12 @@ static int stm32_qspi_setup(struct spi_device *spi)
flash->presc = presc;
 
mutex_lock(&qspi->lock);
-   cr = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
-   writel_relaxed(cr, qspi->io_base + QSPI_CR);
+   qspi->cr_reg = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
+   writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
 
/* set dcr fsize to max address */
-   writel_relaxed(DCR_FSIZE_MASK, qspi->io_base + QSPI_DCR);
+   qspi->dcr_reg = DCR_FSIZE_MASK;
+   writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
mutex_unlock(&qspi->lock);
 
return 0;
@@ -489,6 +494,31 @@ static int stm32_qspi_remove(struct platform_device *pdev)
return 0;
 }
 
+static int __maybe_unused stm32_qspi_suspend(struct device *dev)
+{
+   struct stm32_qspi *qspi = dev_get_drvdata(dev);
+
+   clk_disable_unprepare(qspi->clk);
+   pinctrl_pm_select_sleep_state(dev);
+
+   return 0;
+}
+
+static int __maybe_unused stm32_qspi_resume(struct device *dev)
+{
+   struct stm32_qspi *qspi = dev_get_drvdata(dev);
+
+   pinctrl_pm_select_default_state(dev);
+   clk_prepare_enable(qspi->clk);
+
+   writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
+   writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
+
+   return 0;
+}
+
+SIMPLE_DEV_PM_OPS(stm32_qspi_pm_ops, stm32_qspi_suspend, stm32_qspi_resume);
+
 static const struct of_device_id stm32_qspi_match[] = {
{.compatible = "st,stm32f469-qspi"},
{}
@@ -501,6 +531,7 @@ static struct platform_driver stm32_qspi_driver = {
.driver = {
.name = "stm32-qspi",
.of_match_table = stm32_qspi_match,
+   .pm = &stm32_qspi_pm_ops,
},
 };
 module_platform_driver(stm32_qspi_driver);
-- 
2.20.1



Re: [Patch 1/1] drm/atomic: integrate private objects with suspend/resume helpers

2019-03-14 Thread Benoit Parrot
Ville Syrjälä  wrote on Thu [2019-Mar-14 
17:31:29 +0200]:
> On Thu, Mar 14, 2019 at 08:44:45AM -0500, Benoit Parrot wrote:
> > During a suspend cycle the atomic state is saved to be used during the
> > restore cycle.
> > 
> > However the current state duplication logic does not duplicate private
> > objects. This leads to state inconsistencies at resume time.
> > 
> > With private objects modeset lock now integrated, we can make sure that
> > private object state are properly saved and restored.
> > 
> > Signed-off-by: Benoit Parrot 
> > ---
> >  drivers/gpu/drm/drm_atomic_helper.c | 16 
> >  1 file changed, 16 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> > b/drivers/gpu/drm/drm_atomic_helper.c
> > index 540a77a2ade9..b108021cc092 100644
> > --- a/drivers/gpu/drm/drm_atomic_helper.c
> > +++ b/drivers/gpu/drm/drm_atomic_helper.c
> > @@ -3189,6 +3189,7 @@ drm_atomic_helper_duplicate_state(struct drm_device 
> > *dev,
> > struct drm_connector_list_iter conn_iter;
> > struct drm_plane *plane;
> > struct drm_crtc *crtc;
> > +   struct drm_private_obj *privobj;
> > int err = 0;
> >  
> > state = drm_atomic_state_alloc(dev);
> > @@ -3218,6 +3219,16 @@ drm_atomic_helper_duplicate_state(struct drm_device 
> > *dev,
> > }
> > }
> >  
> > +   drm_for_each_privobj(privobj, dev) {
> > +   struct drm_private_state *priv_state;
> > +
> > +   priv_state = drm_atomic_get_private_obj_state(state, privobj);
> > +   if (IS_ERR(priv_state)) {
> > +   err = PTR_ERR(priv_state);
> > +   goto free;
> > +   }
> > +   }
> > +
> > drm_connector_list_iter_begin(dev, &conn_iter);
> > drm_for_each_connector_iter(conn, &conn_iter) {
> > struct drm_connector_state *conn_state;
> > @@ -3325,12 +3336,17 @@ int 
> > drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
> > struct drm_connector_state *new_conn_state;
> > struct drm_crtc *crtc;
> > struct drm_crtc_state *new_crtc_state;
> > +   struct drm_private_obj *privobj;
> > +   struct drm_private_state *new_priv_state;
> >  
> > state->acquire_ctx = ctx;
> >  
> > for_each_new_plane_in_state(state, plane, new_plane_state, i)
> > state->planes[i].old_state = plane->state;
> >  
> > +   for_each_new_private_obj_in_state(state, privobj, new_priv_state, i)
> > +   state->private_objs[i].old_state = privobj->state;
> > +
> > for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
> > state->crtcs[i].old_state = crtc->state;
> 
> Random order between crtc vs. plane vs. connector vs. priv is tickling
> my ocd nerve a bit.

These loops are independent from each other.
And even without this patch the order is different between
drm_atomic_helper_duplicate_state() and
drm_atomic_helper_commit_duplicated_state(). :)

Benoit

> 
> Otherwise looks sensible to me.
> Reviewed-by: Ville Syrjälä 
> 
> >  
> > -- 
> > 2.17.1
> > 
> > ___
> > dri-devel mailing list
> > dri-de...@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> -- 
> Ville Syrjälä
> Intel


RE: [PATCH] mailbox: imx: keep MU irq working during suspend/resume

2019-03-11 Thread Anson Huang
Ping...

Best Regards!
Anson Huang

> -Original Message-
> From: Anson Huang [mailto:anson.hu...@nxp.com]
> Sent: 2019年2月12日 20:40
> To: jassisinghb...@gmail.com; shawn...@kernel.org;
> s.ha...@pengutronix.de; ker...@pengutronix.de; feste...@gmail.com;
> linux-kernel@vger.kernel.org; linux-arm-ker...@lists.infradead.org
> Cc: dl-linux-imx 
> Subject: [PATCH] mailbox: imx: keep MU irq working during suspend/resume
> 
> During noirq suspend phase, mailbox MU irq will be masked but many
> drivers still need to communicate with system controller firmware via
> mailbox, if MU irq is masked, it will cause RPC timeout as below:
> 
> [   23.372103] imx-scu scu: RPC send msg timeout
> 
> Setting MU irq to be wakeup source is NOT working as GIC driver does NOT
> have .irq_set_wake implemented, so to support suspend/resume, just make
> imx mailbox driver NOT suspend, since MU is always a wakeup source on
> i.MX platforms with system controller inside, and its power/clock is
> maintained by system controller, mailbox driver no need to manage them.
> 
> Signed-off-by: Anson Huang 
> ---
>  drivers/mailbox/imx-mailbox.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> index 774362a..85fc5b5 100644
> --- a/drivers/mailbox/imx-mailbox.c
> +++ b/drivers/mailbox/imx-mailbox.c
> @@ -187,8 +187,8 @@ static int imx_mu_startup(struct mbox_chan *chan)
>   return 0;
>   }
> 
> - ret = request_irq(priv->irq, imx_mu_isr, IRQF_SHARED, cp->irq_desc,
> -   chan);
> + ret = request_irq(priv->irq, imx_mu_isr, IRQF_SHARED |
> +   IRQF_NO_SUSPEND, cp->irq_desc, chan);
>   if (ret) {
>   dev_err(priv->dev,
>   "Unable to acquire IRQ %d\n", priv->irq);
> --
> 2.7.4



[PATCH 2/2] spi: spi-mem: stm32-qspi: add suspend/resume support

2019-03-08 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds suspend and resume support for spi-stm32-qspi
drivers.

Signed-off-by: Ludovic Barre 
---
 drivers/spi/spi-stm32-qspi.c | 39 +++
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
index 7354f9d..3e8ca10 100644
--- a/drivers/spi/spi-stm32-qspi.c
+++ b/drivers/spi/spi-stm32-qspi.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -101,6 +102,9 @@ struct stm32_qspi {
struct completion data_completion;
u32 fmode;
 
+   u32 cr_reg;
+   u32 dcr_reg;
+
/*
 * to protect device configuration, could be different between
 * 2 flash access (bk1, bk2)
@@ -355,7 +359,7 @@ static int stm32_qspi_setup(struct spi_device *spi)
struct spi_controller *ctrl = spi->master;
struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
struct stm32_qspi_flash *flash;
-   u32 cr, presc;
+   u32 presc;
 
if (ctrl->busy)
return -EBUSY;
@@ -371,11 +375,12 @@ static int stm32_qspi_setup(struct spi_device *spi)
flash->presc = presc;
 
mutex_lock(&qspi->lock);
-   cr = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
-   writel_relaxed(cr, qspi->io_base + QSPI_CR);
+   qspi->cr_reg = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
+   writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
 
/* set dcr fsize to max address */
-   writel_relaxed(DCR_FSIZE_MASK, qspi->io_base + QSPI_DCR);
+   qspi->dcr_reg = DCR_FSIZE_MASK;
+   writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
mutex_unlock(&qspi->lock);
 
return 0;
@@ -489,6 +494,31 @@ static int stm32_qspi_remove(struct platform_device *pdev)
return 0;
 }
 
+static int __maybe_unused stm32_qspi_suspend(struct device *dev)
+{
+   struct stm32_qspi *qspi = dev_get_drvdata(dev);
+
+   clk_disable_unprepare(qspi->clk);
+   pinctrl_pm_select_sleep_state(dev);
+
+   return 0;
+}
+
+static int __maybe_unused stm32_qspi_resume(struct device *dev)
+{
+   struct stm32_qspi *qspi = dev_get_drvdata(dev);
+
+   pinctrl_pm_select_default_state(dev);
+   clk_prepare_enable(qspi->clk);
+
+   writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
+   writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR);
+
+   return 0;
+}
+
+SIMPLE_DEV_PM_OPS(stm32_qspi_pm_ops, stm32_qspi_suspend, stm32_qspi_resume);
+
 static const struct of_device_id stm32_qspi_match[] = {
{.compatible = "st,stm32f469-qspi"},
{}
@@ -501,6 +531,7 @@ static struct platform_driver stm32_qspi_driver = {
.driver = {
.name = "stm32-qspi",
.of_match_table = stm32_qspi_match,
+   .pm = &stm32_qspi_pm_ops,
},
 };
 module_platform_driver(stm32_qspi_driver);
-- 
2.7.4



Re: [PATCH net-next v2 0/3] net: phy: marvell10g: implement suspend/resume callbacks

2019-03-04 Thread David Miller
From: Antoine Tenart 
Date: Fri,  1 Mar 2019 12:00:44 +0100

> This series implements the suspend/resume callbacks in the marvell10g
> PHY driver:
> 
> - When the PHY isn't used, it is set in low power mode.
> - At boot time we might now know the PHY status (as it's depending on
>   the hardware configuration, or on what the previous stages
>   configured), it is forced in low power.
> 
> Doing this prevents a PHY which was initialized in a previous stage from
> negotiating with the link partner when a local port is down. If the PHY
> isn't shutdown when a port is not used, the link partner's PHY may
> report the link being up while it's not.

Looks like this needs some more discussion and Russell has some
concerns still.

So deferring to the next merge window, sorry.


[PATCH v9 7/7] ARM: tegra: Add firmware calls required for suspend-resume on Tegra30

2019-03-03 Thread Dmitry Osipenko
In order to suspend-resume CPU with Trusted Foundations firmware being
present on Tegra30, the LP1/LP2 boot vectors and CPU caches need to be
set up using the firmware calls and then suspend code shall avoid
re-disabling parts that were disabled by the firmware.

Tested-by: Robert Yang 
Tested-by: Michał Mirosław 
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 49 +
 arch/arm/mach-tegra/reset-handler.S | 26 +++
 arch/arm/mach-tegra/sleep.S | 14 ++---
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..abf5f88778f4 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,11 +33,13 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "iomap.h"
 #include "pm.h"
@@ -159,6 +161,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+   /*
+* L2 cache disabling using kernel API only allowed when all
+* secondary CPU's are offline. Cache have to be disabled with
+* MMU-on if cache maintenance is done via Trusted Foundations
+* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+* if any of secondary CPU's is online and this is the LP2-idle
+* code-path only for Tegra20/30.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   /*
+* Note that besides of setting up CPU reset vector this firmware
+* call may also do the following, depending on the FW version:
+*  1) Disable L2. But this doesn't matter since we already
+* disabled the L2.
+*  2) Disable D-cache. This need to be taken into account in
+* particular by the tegra_disable_clean_inv_dcache() which
+* shall avoid the re-disable.
+*/
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
setup_mm_for_reboot();
tegra_sleep_cpu_finish(v2p);
 
@@ -197,6 +221,14 @@ void tegra_idle_lp2_last(void)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
+*/
+   outer_resume();
+
restore_cpu_complex();
cpu_cluster_pm_exit();
 }
@@ -215,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+   /*
+* Cache have to be disabled with MMU-on if cache maintenance is done
+* via Trusted Foundations firmware. This is a no-op on Tegra114+.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
setup_mm_for_reboot();
tegra_sleep_core_finish(v2p);
 
@@ -342,6 +383,14 @@ static int tegra_suspend_enter(suspend_state_t state)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op.
+*/
+   outer_resume();
+
switch (mode) {
case TEGRA_SUSPEND_LP1:
tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index 31fb53f9ce13..cd94d7c41fc0 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   RESET_DATA(TF_PRESENT)
+   ldr r1, [r2, r1]
+   cmp r1, #0
+   reteq   lr
+
+ .arch_extension sec
+   /*

Re: [PATCH net-next v2 1/3] net: phy: marvell10g: implement suspend/resume callbacks

2019-03-01 Thread Andrew Lunn
On Fri, Mar 01, 2019 at 12:00:45PM +0100, Antoine Tenart wrote:
> This patch adds the suspend/resume callbacks for Marvell 10G PHYs. The
> three PCS (base-t, base-r and 1000base-x) are set in low power (the PCS
> are powered down) when the PHY isn't used.
> 
> Signed-off-by: Antoine Tenart 

Reviewed-by: Andrew Lunn 

Andrew


Re: [PATCH net-next v2 2/3] net: phy: marvell10g: add the suspend/resume callbacks for the 88x2210

2019-03-01 Thread Andrew Lunn
On Fri, Mar 01, 2019 at 12:00:46PM +0100, Antoine Tenart wrote:
> When the 88x2110 PHY support was added, the suspend and resume callbacks
> were forgotten. This patch adds them to the 88x2110 PHY callback
> definition.
> 
> Signed-off-by: Antoine Tenart 

Reviewed-by: Andrew Lunn 

Andrew


[PATCH net-next v2 1/3] net: phy: marvell10g: implement suspend/resume callbacks

2019-03-01 Thread Antoine Tenart
This patch adds the suspend/resume callbacks for Marvell 10G PHYs. The
three PCS (base-t, base-r and 1000base-x) are set in low power (the PCS
are powered down) when the PHY isn't used.

Signed-off-by: Antoine Tenart 
---
 drivers/net/phy/marvell10g.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 79106e70010f..92462344c5ad 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -226,11 +226,25 @@ static int mv3310_probe(struct phy_device *phydev)
 
 static int mv3310_suspend(struct phy_device *phydev)
 {
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+
return 0;
 }
 
 static int mv3310_resume(struct phy_device *phydev)
 {
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+
return mv3310_hwmon_config(phydev, true);
 }
 
-- 
2.20.1



[PATCH net-next v2 2/3] net: phy: marvell10g: add the suspend/resume callbacks for the 88x2210

2019-03-01 Thread Antoine Tenart
When the 88x2110 PHY support was added, the suspend and resume callbacks
were forgotten. This patch adds them to the 88x2110 PHY callback
definition.

Signed-off-by: Antoine Tenart 
---
 drivers/net/phy/marvell10g.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 92462344c5ad..4f6f96080182 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -488,6 +488,8 @@ static struct phy_driver mv3310_drivers[] = {
.name   = "mv88x2110",
.get_features   = genphy_c45_pma_read_abilities,
.probe  = mv3310_probe,
+   .suspend= mv3310_suspend,
+   .resume = mv3310_resume,
.soft_reset = gen10g_no_soft_reset,
.config_init= mv3310_config_init,
.config_aneg= mv3310_config_aneg,
-- 
2.20.1



[PATCH net-next v2 0/3] net: phy: marvell10g: implement suspend/resume callbacks

2019-03-01 Thread Antoine Tenart
Hello,

This series implements the suspend/resume callbacks in the marvell10g
PHY driver:

- When the PHY isn't used, it is set in low power mode.
- At boot time we might now know the PHY status (as it's depending on
  the hardware configuration, or on what the previous stages
  configured), it is forced in low power.

Doing this prevents a PHY which was initialized in a previous stage from
negotiating with the link partner when a local port is down. If the PHY
isn't shutdown when a port is not used, the link partner's PHY may
report the link being up while it's not.

Thanks,
Antoine

Since v1:
  - Fixed a mix up in the patches where two implementations of the
suspend/resume callbacks were kept in the driver.
  - Rebased on the latest net-next.

Antoine Tenart (3):
  net: phy: marvell10g: implement suspend/resume callbacks
  net: phy: marvell10g: add the suspend/resume callbacks for the 88x2210
  net: phy: marvell10g: set the PHY in low power by default

 drivers/net/phy/marvell10g.c | 39 ++--
 1 file changed, 28 insertions(+), 11 deletions(-)

-- 
2.20.1



[PATCH v3 4/4] net: macb: Add support for suspend/resume with full power down

2019-03-01 Thread Harini Katakam
When macb device is suspended and system is powered down, the clocks
are removed and hence macb should be closed gracefully and restored
upon resume. This patch does the same by switching off the net device,
suspending phy and performing necessary cleanup of interrupts and BDs.
Upon resume, all these are reinitialized again.

Reset of macb device is done only when GEM is not a wake device.
Even when gem is a wake device, tx queues can be stopped and ptp device
can be closed (tsu clock will be disabled in pm_runtime_suspend) as
wake event detection has no dependency on this.

Signed-off-by: Kedareswara rao Appana 
Signed-off-by: Harini Katakam 
---
v3:
Fix >80 char lines

v2 changes:
Fixed parameter passed to phy calls.

 drivers/net/ethernet/cadence/macb_main.c | 40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 5173c02..ad099fd 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4283,16 +4283,34 @@ static int __maybe_unused macb_suspend(struct device 
*dev)
 {
struct net_device *netdev = dev_get_drvdata(dev);
struct macb *bp = netdev_priv(netdev);
+   struct macb_queue *queue = bp->queues;
+   unsigned long flags;
+   unsigned int q;
+
+   if (!netif_running(netdev))
+   return 0;
 
-   netif_carrier_off(netdev);
-   netif_device_detach(netdev);
 
if (bp->wol & MACB_WOL_ENABLED) {
macb_writel(bp, IER, MACB_BIT(WOL));
macb_writel(bp, WOL, MACB_BIT(MAG));
enable_irq_wake(bp->queues[0].irq);
+   netif_device_detach(netdev);
+   } else {
+   netif_device_detach(netdev);
+   for (q = 0, queue = bp->queues; q < bp->num_queues;
+++q, ++queue)
+   napi_disable(&queue->napi);
+   phy_stop(netdev->phydev);
+   phy_suspend(netdev->phydev);
+   spin_lock_irqsave(&bp->lock, flags);
+   macb_reset_hw(bp);
+   spin_unlock_irqrestore(&bp->lock, flags);
}
 
+   netif_carrier_off(netdev);
+   if (bp->ptp_info)
+   bp->ptp_info->ptp_remove(netdev);
pm_runtime_force_suspend(dev);
 
return 0;
@@ -4302,6 +4320,11 @@ static int __maybe_unused macb_resume(struct device *dev)
 {
struct net_device *netdev = dev_get_drvdata(dev);
struct macb *bp = netdev_priv(netdev);
+   struct macb_queue *queue = bp->queues;
+   unsigned int q;
+
+   if (!netif_running(netdev))
+   return 0;
 
pm_runtime_force_resume(dev);
 
@@ -4309,9 +4332,22 @@ static int __maybe_unused macb_resume(struct device *dev)
macb_writel(bp, IDR, MACB_BIT(WOL));
macb_writel(bp, WOL, 0);
disable_irq_wake(bp->queues[0].irq);
+   } else {
+   macb_writel(bp, NCR, MACB_BIT(MPE));
+   for (q = 0, queue = bp->queues; q < bp->num_queues;
+++q, ++queue)
+   napi_enable(&queue->napi);
+   phy_resume(netdev->phydev);
+   phy_init_hw(netdev->phydev);
+   phy_start(netdev->phydev);
}
 
+   bp->macbgem_ops.mog_init_rings(bp);
+   macb_init_hw(bp);
+   macb_set_rx_mode(netdev);
netif_device_attach(netdev);
+   if (bp->ptp_info)
+   bp->ptp_info->ptp_init(netdev);
 
return 0;
 }
-- 
2.7.4



[PATCH v8 7/7] ARM: tegra: Add firmware calls required for suspend-resume on Tegra30

2019-02-28 Thread Dmitry Osipenko
In order to suspend-resume CPU with Trusted Foundations firmware being
present on Tegra30, the LP1/LP2 boot vectors and CPU caches need to be
set up using the firmware calls and then suspend code shall avoid
re-disabling parts that were disabled by the firmware.

Tested-by: Robert Yang 
Tested-by: Michał Mirosław 
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 49 +
 arch/arm/mach-tegra/reset-handler.S | 26 +++
 arch/arm/mach-tegra/sleep.S | 14 ++---
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..abf5f88778f4 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,11 +33,13 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "iomap.h"
 #include "pm.h"
@@ -159,6 +161,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+   /*
+* L2 cache disabling using kernel API only allowed when all
+* secondary CPU's are offline. Cache have to be disabled with
+* MMU-on if cache maintenance is done via Trusted Foundations
+* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+* if any of secondary CPU's is online and this is the LP2-idle
+* code-path only for Tegra20/30.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   /*
+* Note that besides of setting up CPU reset vector this firmware
+* call may also do the following, depending on the FW version:
+*  1) Disable L2. But this doesn't matter since we already
+* disabled the L2.
+*  2) Disable D-cache. This need to be taken into account in
+* particular by the tegra_disable_clean_inv_dcache() which
+* shall avoid the re-disable.
+*/
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
setup_mm_for_reboot();
tegra_sleep_cpu_finish(v2p);
 
@@ -197,6 +221,14 @@ void tegra_idle_lp2_last(void)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
+*/
+   outer_resume();
+
restore_cpu_complex();
cpu_cluster_pm_exit();
 }
@@ -215,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+   /*
+* Cache have to be disabled with MMU-on if cache maintenance is done
+* via Trusted Foundations firmware. This is a no-op on Tegra114+.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
setup_mm_for_reboot();
tegra_sleep_core_finish(v2p);
 
@@ -342,6 +383,14 @@ static int tegra_suspend_enter(suspend_state_t state)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op.
+*/
+   outer_resume();
+
switch (mode) {
case TEGRA_SUSPEND_LP1:
tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index 3bf202819534..19a609046547 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   RESET_DATA(TF_PRESENT)
+   ldr r1, [r2, r1]
+   cmp r1, #0
+   reteq   lr
+
+ .arch_extension sec
+   /*

[PATCH net-next 0/3] net: phy: marvell10g: implement suspend/resume callbacks

2019-02-28 Thread Antoine Tenart
Hello,

This series implements the suspend/resume callbacks in the marvell10g
PHY driver:

- When the PHY isn't used, it is set in low power mode.
- At boot time we might now know the PHY status (as it's depending on
  the hardware configuration, or on what the previous stages
  configured), it is forced in low power.

Doing this prevents a PHY which was initialized in a previous stage from
negotiating with the link partner when a local port is down. If the PHY
isn't shutdown when a port is not used, the link partner's PHY may
report the link being up while it's not.

Thanks,
Antoine

Antoine Tenart (3):
  net: phy: marvell10g: implement suspend/resume callbacks
  net: phy: marvell10g: add the suspend/resume callbacks for the 88x2210
  net: phy: marvell10g: set the PHY in low power by default

 drivers/net/phy/marvell10g.c | 39 ++--
 1 file changed, 28 insertions(+), 11 deletions(-)

-- 
2.20.1



[PATCH net-next 1/3] net: phy: marvell10g: implement suspend/resume callbacks

2019-02-28 Thread Antoine Tenart
This patch adds the suspend/resume callbacks for Marvell 10G PHYs. The
three PCS (base-t, base-r and 1000base-x) are set in low power (the PCS
are powered down) when the PHY isn't used.

Signed-off-by: Antoine Tenart 
---
 drivers/net/phy/marvell10g.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 79106e70010f..95aeeda0eb16 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -201,6 +201,30 @@ static int mv3310_hwmon_probe(struct phy_device *phydev)
 }
 #endif
 
+static int mv3310_suspend(struct phy_device *phydev)
+{
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, MDIO_CTRL1_LPOWER);
+
+   return 0;
+}
+
+static int mv3310_resume(struct phy_device *phydev)
+{
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+   phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1,
+  MDIO_CTRL1_LPOWER, 0);
+
+   return mv3310_hwmon_config(phydev, true);
+}
+
 static int mv3310_probe(struct phy_device *phydev)
 {
struct mv3310_priv *priv;
-- 
2.20.1



[PATCH net-next 2/3] net: phy: marvell10g: add the suspend/resume callbacks for the 88x2210

2019-02-28 Thread Antoine Tenart
When the 88x2110 PHY support was added, the suspend and resume callbacks
were forgotten. This patch adds them to the 88x2110 PHY callback
definition.

Signed-off-by: Antoine Tenart 
---
 drivers/net/phy/marvell10g.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 95aeeda0eb16..e5d098bd33a6 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -498,6 +498,8 @@ static struct phy_driver mv3310_drivers[] = {
.name   = "mv88x2110",
.get_features   = genphy_c45_pma_read_abilities,
.probe  = mv3310_probe,
+   .suspend= mv3310_suspend,
+   .resume = mv3310_resume,
.soft_reset = gen10g_no_soft_reset,
.config_init= mv3310_config_init,
.config_aneg= mv3310_config_aneg,
-- 
2.20.1



[PATCH v7 7/7] ARM: tegra: Add firmware calls required for suspend-resume on Tegra30

2019-02-28 Thread Dmitry Osipenko
In order to suspend-resume CPU with Trusted Foundations firmware being
present on Tegra30, the LP1/LP2 boot vectors and CPU caches need to be
set up using the firmware calls and then suspend code shall avoid
re-disabling parts that were disabled by the firmware.

Tested-by: Robert Yang 
Tested-by: Michał Mirosław 
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 49 +
 arch/arm/mach-tegra/reset-handler.S | 26 +++
 arch/arm/mach-tegra/sleep.S | 14 ++---
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..abf5f88778f4 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,11 +33,13 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "iomap.h"
 #include "pm.h"
@@ -159,6 +161,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+   /*
+* L2 cache disabling using kernel API only allowed when all
+* secondary CPU's are offline. Cache have to be disabled with
+* MMU-on if cache maintenance is done via Trusted Foundations
+* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+* if any of secondary CPU's is online and this is the LP2-idle
+* code-path only for Tegra20/30.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   /*
+* Note that besides of setting up CPU reset vector this firmware
+* call may also do the following, depending on the FW version:
+*  1) Disable L2. But this doesn't matter since we already
+* disabled the L2.
+*  2) Disable D-cache. This need to be taken into account in
+* particular by the tegra_disable_clean_inv_dcache() which
+* shall avoid the re-disable.
+*/
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
setup_mm_for_reboot();
tegra_sleep_cpu_finish(v2p);
 
@@ -197,6 +221,14 @@ void tegra_idle_lp2_last(void)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
+*/
+   outer_resume();
+
restore_cpu_complex();
cpu_cluster_pm_exit();
 }
@@ -215,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+   /*
+* Cache have to be disabled with MMU-on if cache maintenance is done
+* via Trusted Foundations firmware. This is a no-op on Tegra114+.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
setup_mm_for_reboot();
tegra_sleep_core_finish(v2p);
 
@@ -342,6 +383,14 @@ static int tegra_suspend_enter(suspend_state_t state)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op.
+*/
+   outer_resume();
+
switch (mode) {
case TEGRA_SUSPEND_LP1:
tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index 3bf202819534..19a609046547 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   RESET_DATA(TF_PRESENT)
+   ldr r1, [r2, r1]
+   cmp r1, #0
+   reteq   lr
+
+ .arch_extension sec
+   /*

[PATCH 4.20 005/183] mt76x0u: fix suspend/resume

2019-02-25 Thread Greg Kroah-Hartman
4.20-stable review patch.  If anyone has any objections, please let me know.

--

From: Stanislaw Gruszka 

commit d04ca383860bef90a0dab4eb397907f7f05e839e upstream.

We need to reset MCU and do other initializations on resume otherwise
MT7610U device will fail to initialize, what cause system hung due to
USB requests timeouts.

Patch fixes 4.19 -> 4.20 regression.

Cc: sta...@vger.kernel.org # 4.20+
Signed-off-by: Stanislaw Gruszka 
Acked-by: Lorenzo Bianconi 
Signed-off-by: Kalle Valo 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c |   46 +++-
 1 file changed, 29 insertions(+), 17 deletions(-)

--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -159,39 +159,49 @@ static const struct ieee80211_ops mt76x0
.wake_tx_queue = mt76_wake_tx_queue,
 };
 
-static int mt76x0u_register_device(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
 {
-   struct ieee80211_hw *hw = dev->mt76.hw;
int err;
 
-   err = mt76u_alloc_queues(&dev->mt76);
-   if (err < 0)
-   goto out_err;
-
-   err = mt76u_mcu_init_rx(&dev->mt76);
-   if (err < 0)
-   goto out_err;
-
mt76x0_chip_onoff(dev, true, true);
-   if (!mt76x02_wait_for_mac(&dev->mt76)) {
-   err = -ETIMEDOUT;
-   goto out_err;
-   }
+
+   if (!mt76x02_wait_for_mac(&dev->mt76))
+   return -ETIMEDOUT;
 
err = mt76x0u_mcu_init(dev);
if (err < 0)
-   goto out_err;
+   return err;
 
mt76x0_init_usb_dma(dev);
err = mt76x0_init_hardware(dev);
if (err < 0)
-   goto out_err;
+   return err;
 
mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
mt76_wr(dev, MT_TXOP_CTRL_CFG,
FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
 
+   return 0;
+}
+
+static int mt76x0u_register_device(struct mt76x02_dev *dev)
+{
+   struct ieee80211_hw *hw = dev->mt76.hw;
+   int err;
+
+   err = mt76u_alloc_queues(&dev->mt76);
+   if (err < 0)
+   goto out_err;
+
+   err = mt76u_mcu_init_rx(&dev->mt76);
+   if (err < 0)
+   goto out_err;
+
+   err = mt76x0u_init_hardware(dev);
+   if (err < 0)
+   goto out_err;
+
err = mt76x0_register_device(dev);
if (err < 0)
goto out_err;
@@ -300,6 +310,8 @@ static int __maybe_unused mt76x0_suspend
 
mt76u_stop_queues(&dev->mt76);
mt76x0u_mac_stop(dev);
+   clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
+   mt76x0_chip_onoff(dev, false, false);
usb_kill_urb(usb->mcu.res.urb);
 
return 0;
@@ -327,7 +339,7 @@ static int __maybe_unused mt76x0_resume(
tasklet_enable(&usb->rx_tasklet);
tasklet_enable(&usb->tx_tasklet);
 
-   ret = mt76x0_init_hardware(dev);
+   ret = mt76x0u_init_hardware(dev);
if (ret)
goto err;
 




[PATCH v6 7/7] ARM: tegra: Add firmware calls required for suspend-resume on Tegra30

2019-02-22 Thread Dmitry Osipenko
In order to suspend-resume CPU with Trusted Foundations firmware being
present on Tegra30, the LP1/LP2 boot vectors and CPU caches need to be
set up using the firmware calls and then suspend code shall avoid
re-disabling parts that were disabled by the firmware.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 49 +
 arch/arm/mach-tegra/reset-handler.S | 26 +++
 arch/arm/mach-tegra/sleep.S | 14 ++---
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..f209f59e0daf 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,11 +33,13 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "iomap.h"
 #include "pm.h"
@@ -159,6 +161,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+   /*
+* L2 cache disabling using kernel API only allowed when all
+* secondary CPU's are offline. Cache have to be disabled with
+* MMU-on if cache maintenance is done via Trusted Foundations
+* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+* if any of secondary CPU's is online and this is the LP2-idle
+* code-path only for Tegra20/30.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   /*
+* Note that besides of setting up CPU reset vector this firmware
+* call may also do the following, depending on the FW version:
+*  1) Disable L2. But this doesn't matter since we already
+* disabled the L2.
+*  2) Disable D-cache. This need to be taken into account in
+* particular by the tegra_disable_clean_inv_dcache() which
+* shall avoid the re-disable.
+*/
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
setup_mm_for_reboot();
tegra_sleep_cpu_finish(v2p);
 
@@ -197,6 +221,14 @@ void tegra_idle_lp2_last(void)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
+*/
+   outer_resume();
+
restore_cpu_complex();
cpu_cluster_pm_exit();
 }
@@ -215,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+   /*
+* Cache have to be disabled with MMU-on if cache maintenance is done
+* via Trusted Foundations firmware. This is a no-op on Tegra114+.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
setup_mm_for_reboot();
tegra_sleep_core_finish(v2p);
 
@@ -342,6 +383,14 @@ static int tegra_suspend_enter(suspend_state_t state)
 
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
+   /*
+* Resume L2 cache if it wasn't re-enabled early during resume,
+* which is the case for Tegra30 that has to re-enable the cache
+* via firmware call. In other cases cache is already enabled and
+* hence re-enabling is a no-op.
+*/
+   outer_resume();
+
switch (mode) {
case TEGRA_SUSPEND_LP1:
tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index 3bf202819534..19a609046547 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   RESET_DATA(TF_PRESENT)
+   ldr r1, [r2, r1]
+   cmp r1, #0
+   reteq   lr
+
+ .arch_extension sec
+   /* First call after suspend wakes fir

Re: [PATCH v5 8/8] ARM: tegra: Add firmware calls required for suspend-resume

2019-02-22 Thread Dmitry Osipenko
22.02.2019 20:59, Dmitry Osipenko пишет:
> In order to resume CPU from suspend via trusted Foundations firmware,
> the LP1/LP2 boot vectors and CPU caches need to be set up using the
> firmware calls.
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  arch/arm/mach-tegra/pm.c| 53 ++---
>  arch/arm/mach-tegra/reset-handler.S | 26 ++
>  arch/arm/mach-tegra/sleep.S |  3 +-
>  3 files changed, 61 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
> index 66c8cd63dd86..f209f59e0daf 100644
> --- a/arch/arm/mach-tegra/pm.c
> +++ b/arch/arm/mach-tegra/pm.c
> @@ -33,6 +33,7 @@
>  #include 
>  
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -160,6 +161,28 @@ int tegra_cpu_do_idle(void)
>  
>  static int tegra_sleep_cpu(unsigned long v2p)
>  {
> + /*
> +  * L2 cache disabling using kernel API only allowed when all
> +  * secondary CPU's are offline. Cache have to be disabled with
> +  * MMU-on if cache maintenance is done via Trusted Foundations
> +  * firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
> +  * if any of secondary CPU's is online and this is the LP2-idle
> +  * code-path only for Tegra20/30.
> +  */
> + if (trusted_foundations_registered())
> + outer_disable();
> +
> + /*
> +  * Note that besides of setting up CPU reset vector this firmware
> +  * call may also do the following, depending on the FW version:
> +  *  1) Disable L2. But this doesn't matter since we already
> +  * disabled the L2.
> +  *  2) Disable D-cache. This need to be taken into account in
> +  * particular by the tegra_disable_clean_inv_dcache() which
> +  * shall avoid the re-disable.
> +  */
> + call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
> +
>   setup_mm_for_reboot();
>   tegra_sleep_cpu_finish(v2p);
>  
> @@ -196,24 +219,13 @@ void tegra_idle_lp2_last(void)
>   cpu_cluster_pm_enter();
>   suspend_cpu_complex();
>  
> - /*
> -  * L2 cache disabling using kernel API only allowed when all
> -  * secondary CPU's are offline. Cache have to be disabled early
> -  * if cache maintenance is done via Trusted Foundations firmware.
> -  * Note that CPUIDLE won't ever enter powergate on Tegra30 if any
> -  * of secondary CPU's is online and this is the LP2 codepath only
> -  * for Tegra20/30.
> -  */
> - if (trusted_foundations_registered())
> - outer_disable();
> -
>   cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
>  
>   /*
>* Resume L2 cache if it wasn't re-enabled early during resume,
>* which is the case for Tegra30 that has to re-enable the cache
>* via firmware call. In other cases cache is already enabled and
> -  * hence re-enabling is a no-op.
> +  * hence re-enabling is a no-op. This is always a no-op on Tegra114+.
>*/
>   outer_resume();
>  
> @@ -235,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
>  
>  static int tegra_sleep_core(unsigned long v2p)
>  {
> + /*
> +  * Cache have to be disabled with MMU-on if cache maintenance is done
> +  * via Trusted Foundations firmware. This is a no-op on Tegra114+.
> +  */
> + if (trusted_foundations_registered())
> + outer_disable();
> +
> + call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
> +
>   setup_mm_for_reboot();
>   tegra_sleep_core_finish(v2p);
>  
> @@ -360,14 +381,6 @@ static int tegra_suspend_enter(suspend_state_t state)
>   break;
>   }
>  
> - /*
> -  * Cache have to be disabled early if cache maintenance is done
> -  * via Trusted Foundations firmware. Otherwise this is a no-op,
> -  * like on Tegra114+.
> -  */
> - if (trusted_foundations_registered())
> - outer_disable();
> -
>   cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);

Seems I messed up the rebasing a tad. Will send another version.


[PATCH v5 8/8] ARM: tegra: Add firmware calls required for suspend-resume

2019-02-22 Thread Dmitry Osipenko
In order to resume CPU from suspend via trusted Foundations firmware,
the LP1/LP2 boot vectors and CPU caches need to be set up using the
firmware calls.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 53 ++---
 arch/arm/mach-tegra/reset-handler.S | 26 ++
 arch/arm/mach-tegra/sleep.S |  3 +-
 3 files changed, 61 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 66c8cd63dd86..f209f59e0daf 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,6 +33,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -160,6 +161,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+   /*
+* L2 cache disabling using kernel API only allowed when all
+* secondary CPU's are offline. Cache have to be disabled with
+* MMU-on if cache maintenance is done via Trusted Foundations
+* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+* if any of secondary CPU's is online and this is the LP2-idle
+* code-path only for Tegra20/30.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   /*
+* Note that besides of setting up CPU reset vector this firmware
+* call may also do the following, depending on the FW version:
+*  1) Disable L2. But this doesn't matter since we already
+* disabled the L2.
+*  2) Disable D-cache. This need to be taken into account in
+* particular by the tegra_disable_clean_inv_dcache() which
+* shall avoid the re-disable.
+*/
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
setup_mm_for_reboot();
tegra_sleep_cpu_finish(v2p);
 
@@ -196,24 +219,13 @@ void tegra_idle_lp2_last(void)
cpu_cluster_pm_enter();
suspend_cpu_complex();
 
-   /*
-* L2 cache disabling using kernel API only allowed when all
-* secondary CPU's are offline. Cache have to be disabled early
-* if cache maintenance is done via Trusted Foundations firmware.
-* Note that CPUIDLE won't ever enter powergate on Tegra30 if any
-* of secondary CPU's is online and this is the LP2 codepath only
-* for Tegra20/30.
-*/
-   if (trusted_foundations_registered())
-   outer_disable();
-
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
/*
 * Resume L2 cache if it wasn't re-enabled early during resume,
 * which is the case for Tegra30 that has to re-enable the cache
 * via firmware call. In other cases cache is already enabled and
-* hence re-enabling is a no-op.
+* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
 */
outer_resume();
 
@@ -235,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+   /*
+* Cache have to be disabled with MMU-on if cache maintenance is done
+* via Trusted Foundations firmware. This is a no-op on Tegra114+.
+*/
+   if (trusted_foundations_registered())
+   outer_disable();
+
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
setup_mm_for_reboot();
tegra_sleep_core_finish(v2p);
 
@@ -360,14 +381,6 @@ static int tegra_suspend_enter(suspend_state_t state)
break;
}
 
-   /*
-* Cache have to be disabled early if cache maintenance is done
-* via Trusted Foundations firmware. Otherwise this is a no-op,
-* like on Tegra114+.
-*/
-   if (trusted_foundations_registered())
-   outer_disable();
-
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
/*
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index 3bf202819534..19a609046547 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   

Re: recalibrating x86 TSC during suspend/resume

2019-02-22 Thread Olaf Hering
On Fri, Feb 22, Paolo Bonzini wrote:

> On 22/02/19 12:44, Thomas Gleixner wrote:
> >> The specific usecase I have is a workload within VMs that makes heavy
> >> use of TSC. The kernel is booted with 'clocksource=tsc highres=off 
> >> nohz=off'
> >> because only this clocksource gives enough granularity. The default
> >> paravirtualized clock will return the same values via
> >> clock_gettime(CLOCK_MONOTONIC) if the timespan between two calls is too
> >> short. This does not happen with 'clocksource=tsc'.
> 
> This shouldn't happen.  clock_gettime(CLOCK_MONOTONIC) should be
> monotonic increasing.  Do you have a testcase?

Two years ago I tweaked sysbench to track the execution time of the
'memory' test:

https://github.com/olafhering/sysbench
https://github.com/olafhering/sysbench/blame/pv/src/tests/memory/sb_memory.c

The checks in diff_timespec() triggered with clocksource=xen, but I can
not reproduce it right now with 5.0 and 4.4 based kernels. I have no
data how KVM behaves. In the end the hypervisor was tweaked to tolerate
a certain jitter in expected TSC speed before emulation kicks in. Up to
~1MHz would be ok to stay within the 500PPM limit that ntpd can handle.

But now there is that "island" issue that needs to be resolved in one
way or another.

Olaf


signature.asc
Description: PGP signature


Re: [PATCH 7/7] iommu/ipmmu-vmsa: Add suspend/resume support

2019-02-22 Thread Robin Murphy

Hi Geert,

On 20/02/2019 15:05, Geert Uytterhoeven wrote:

During PSCI system suspend, R-Car Gen3 SoCs are powered down, and all
IPMMU state is lost.  Hence after s2ram, devices wired behind an IPMMU,
and configured to use it, will see their DMA operations hang.

To fix this, restore all IPMMU contexts, and re-enable all active
micro-TLBs during system resume.

To avoid overhead on platforms not needing it, the resume code has a
build time dependency on sleep and PSCI support, and a runtime
dependency on PSCI.


Frankly, that aspect looks horribly hacky. It's not overly reasonable 
for random device drivers to be poking at PSCI internals, and while it 
might happen to correlate on some known set of current SoCs with current 
firmware, in general it's really too fragile to be accurate:


- Firmware is free to implement suspend callbacks in a way which doesn't 
actually lose power.
- Support for CPU_SUSPEND does not imply that SYSTEM_SUSPEND is even 
implemented, let alone how it might behave.
- The dev_pm_ops callbacks can also be used for hibernate, wherein it 
doesn't really matter what the firmware may or may not do if the user 
has pulled the plug and resumed us a week later.


Furthermore, I think any attempt to detect whether you need to resume or 
not is inherently fraught with danger - from testing the arm-smmu 
runtime PM ops, I've seen register state take a surprisingly long time 
to decay in a switched-off power domain, to the point where unless you 
check every bit of every register you can't necessarily be certain that 
they're really all still valid, and by that point you're doing far more 
work than just unconditionally reinitialising the whole state anyway. 
Upon resuming from hibernate, the state left by the cold-boot stage 
almost certainly *will* be valid, but it probably won't be the state you 
actually want.


Really, the whole idea smells of the premature optimisation demons 
anyway - is the resume overhead measurably significant?



Signed-off-by: Geert Uytterhoeven 
---
This patch takes a different approach than the BSP, which implements a
bulk save/restore of all registers during system suspend/resume.

  drivers/iommu/ipmmu-vmsa.c | 52 +-
  1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 92a766dd8b459f0c..5d22139914e8f033 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -22,6 +22,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -36,7 +37,10 @@
  #define arm_iommu_detach_device(...)  do {} while (0)
  #endif
  
-#define IPMMU_CTX_MAX 8U

+#define IPMMU_CTX_MAX  8U
+#define IPMMU_CTX_INVALID  -1
+
+#define IPMMU_UTLB_MAX 48U
  
  struct ipmmu_features {

bool use_ns_alias_offset;
@@ -58,6 +62,7 @@ struct ipmmu_vmsa_device {
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
+   s8 utlb_ctx[IPMMU_UTLB_MAX];
  
  	struct iommu_group *group;

struct dma_iommu_mapping *mapping;
@@ -335,6 +340,7 @@ static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain 
*domain,
ipmmu_write(mmu, IMUCTR(utlb),
IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
IMUCTR_MMUEN);
+   mmu->utlb_ctx[utlb] = domain->context_id;
  }
  
  /*

@@ -346,6 +352,7 @@ static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain 
*domain,
struct ipmmu_vmsa_device *mmu = domain->mmu;
  
  	ipmmu_write(mmu, IMUCTR(utlb), 0);

+   mmu->utlb_ctx[utlb] = IPMMU_CTX_INVALID;
  }
  
  static void ipmmu_tlb_flush_all(void *cookie)

@@ -1043,6 +1050,7 @@ static int ipmmu_probe(struct platform_device *pdev)
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(&pdev->dev);
+   memset(mmu->utlb_ctx, IPMMU_CTX_INVALID, mmu->features->num_utlbs);
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
  
  	/* Map I/O memory and request IRQ. */

@@ -1158,10 +1166,52 @@ static int ipmmu_remove(struct platform_device *pdev)
return 0;
  }
  
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)

+static int ipmmu_resume_noirq(struct device *dev)
+{
+   struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
+   unsigned int i;
+
+   /* This is the best we can do to check for the presence of PSCI */
+   if (!psci_ops.cpu_suspend)
+   return 0;
+
+   /* Reset root MMU and restore contexts */
+   if (ipmmu_is_root(mmu)) {
+   ipmmu_device_reset(mmu);
+
+   for (i = 0; i < mmu->num_ctx; i++) {
+   if (!mmu->domains[i])
+ 

Re: recalibrating x86 TSC during suspend/resume

2019-02-22 Thread Paolo Bonzini
On 22/02/19 12:44, Thomas Gleixner wrote:
>> The specific usecase I have is a workload within VMs that makes heavy
>> use of TSC. The kernel is booted with 'clocksource=tsc highres=off nohz=off'
>> because only this clocksource gives enough granularity. The default
>> paravirtualized clock will return the same values via
>> clock_gettime(CLOCK_MONOTONIC) if the timespan between two calls is too
>> short. This does not happen with 'clocksource=tsc'.

This shouldn't happen.  clock_gettime(CLOCK_MONOTONIC) should be
monotonic increasing.  Do you have a testcase?

The KVM clocksource is high-resolution and also TSC-based, the
difference is that it performs two multiplications instead of one.  The
first uses TSC parameters from the host.  The second, which is the one
in arch/x86/entry/vdso/vclock_gettime.c's do_hres function, will have a
1:1 multiplier (excluding adjtime shearing) because kvmclock already
returns nanoseconds.

> Newer Intels support TSC scaling for VMX, which could solve the problem. It
> affects TSC readout by:
> 
>   TSC = (read(HWTSC) * multiplier) >> 48
> 
> So you can standarize on a TSC frequency accross a fleet. Not sure when
> that was introduced and no idea whether it's available on AMD.

It's Skylake (server parts only) or newer.  AMD instead has had it
(almost) forever.  QEMU 2.6 or newer will use it automatically across
live migration, if available.

> For a software solution we could try the following:
> 
>  1) Provide the raw TSC frequency of the host to the guest in some magic
> software defined MSR or CPUID. If there is an existing mechanism, use
> that.

This shouldn't be needed for two reasons:

1) you could also use kvmclock's provided mult/shift

2) I am not convinced that kvmclock has the behavior that Olaf mentions,
and if it does it would be a bug.

Paolo


Re: recalibrating x86 TSC during suspend/resume

2019-02-22 Thread Olaf Hering
Am Fri, 22 Feb 2019 12:44:39 +0100 (CET)
schrieb Thomas Gleixner :

> Whether that is accurate enough or not to make NTP happy, I can't tell, but
> it's definitely worth a try.

Thanks Thomas, I will look into the suggestions.


Olaf


pgpKvKEGb9vSF.pgp
Description: Digitale Signatur von OpenPGP


Re: recalibrating x86 TSC during suspend/resume

2019-02-22 Thread Thomas Gleixner
On Fri, 22 Feb 2019, Olaf Hering wrote:
> Is there a way to recalibrate the x86 TSC during a suspend/resume cycle?

No.

> While the frequency will remain the same on a Laptop, it may (or rather:
> it definitly will) differ if a VM is migrated from one host to another.
> The hypervisor may choose to emulate the expected TSC frequency on the
> destination host, but this emulation comes with a significant
> performance cost. Therefore it would be good if the kernel evaluates the
> environment during resume.
> 
> The specific usecase I have is a workload within VMs that makes heavy
> use of TSC. The kernel is booted with 'clocksource=tsc highres=off nohz=off'
> because only this clocksource gives enough granularity. The default
> paravirtualized clock will return the same values via
> clock_gettime(CLOCK_MONOTONIC) if the timespan between two calls is too
> short. This does not happen with 'clocksource=tsc'.
> 
> Right now it is not possible to migrate VMs to hosts with different CPU
> speeds. This leads to "islands" of identical hardware, and makes
> maintenance of hosts harder than it needs to be. If the VM kernel would
> be able to cope with CPU/TSC frequency changes, the pool of potential
> destination hosts will become significant larger.

The problem with recalibrating TSC on resume is that it would have to be

1) quick

2) accurate, so NTP does not get utterly unhappy.

Newer Intels support TSC scaling for VMX, which could solve the problem. It
affects TSC readout by:

TSC = (read(HWTSC) * multiplier) >> 48

So you can standarize on a TSC frequency accross a fleet. Not sure when
that was introduced and no idea whether it's available on AMD.

For a software solution we could try the following:

 1) Provide the raw TSC frequency of the host to the guest in some magic
software defined MSR or CPUID. If there is an existing mechanism, use
that.

 2) On resume check whether the MSR/CPUID is available and if so readout
that information and check whether the frequency is the same as
before. If not it is trivial enough to adjust the guest mult/shift
values for both raw and NTP adjusted clocks before they are used again,
i.e. before timekeeping_resume(). Need to look what's the best place,
but probably the clocksource resume callback. Plus if TSC deadline
timer is used, we'd need the same adjustment there.

That's backward compatible, because if the MSR/CPUID is not there, then
the recalibration is not tried.

Whether that is accurate enough or not to make NTP happy, I can't tell, but
it's definitely worth a try.

Thanks,

tglx



recalibrating x86 TSC during suspend/resume

2019-02-22 Thread Olaf Hering
Is there a way to recalibrate the x86 TSC during a suspend/resume cycle?

While the frequency will remain the same on a Laptop, it may (or rather:
it definitly will) differ if a VM is migrated from one host to another.
The hypervisor may choose to emulate the expected TSC frequency on the
destination host, but this emulation comes with a significant
performance cost. Therefore it would be good if the kernel evaluates the
environment during resume.

The specific usecase I have is a workload within VMs that makes heavy
use of TSC. The kernel is booted with 'clocksource=tsc highres=off nohz=off'
because only this clocksource gives enough granularity. The default
paravirtualized clock will return the same values via
clock_gettime(CLOCK_MONOTONIC) if the timespan between two calls is too
short. This does not happen with 'clocksource=tsc'.

Right now it is not possible to migrate VMs to hosts with different CPU
speeds. This leads to "islands" of identical hardware, and makes
maintenance of hosts harder than it needs to be. If the VM kernel would
be able to cope with CPU/TSC frequency changes, the pool of potential
destination hosts will become significant larger.

The current result of a migration with non-emulated TSC between hosts of
different speed is:

[   42.452258] clocksource: timekeeping watchdog on CPU1: Marking clocksource 
'tsc' as unstable because the skew is too large:
[   42.452270] clocksource:   'xen' wd_now: 6d34a86adb 
wd_last: 6d1dc51793 mask: 
[   42.452272] clocksource:   'tsc' cs_now: 1fd2ce46bb 
cs_last: 1f95c4ca75 mask: 
[   42.452273] tsc: Marking TSC unstable due to clocksource watchdog

Thanks,
Olaf


signature.asc
Description: PGP signature


Re: [PATCH 7/7] iommu/ipmmu-vmsa: Add suspend/resume support

2019-02-20 Thread Geert Uytterhoeven
Hi Laurent,

On Wed, Feb 20, 2019 at 5:11 PM Laurent Pinchart
 wrote:
> On Wed, Feb 20, 2019 at 05:05:49PM +0100, Geert Uytterhoeven wrote:
> > On Wed, Feb 20, 2019 at 4:42 PM Laurent Pinchart wrote:
> > > On Wed, Feb 20, 2019 at 04:05:31PM +0100, Geert Uytterhoeven wrote:
> > >> During PSCI system suspend, R-Car Gen3 SoCs are powered down, and all
> > >> IPMMU state is lost.  Hence after s2ram, devices wired behind an IPMMU,
> > >> and configured to use it, will see their DMA operations hang.
> > >>
> > >> To fix this, restore all IPMMU contexts, and re-enable all active
> > >> micro-TLBs during system resume.
> > >>
> > >> To avoid overhead on platforms not needing it, the resume code has a
> > >> build time dependency on sleep and PSCI support, and a runtime
> > >> dependency on PSCI.

> > >> --- a/drivers/iommu/ipmmu-vmsa.c
> > >> +++ b/drivers/iommu/ipmmu-vmsa.c

> > >> @@ -1158,10 +1166,52 @@ static int ipmmu_remove(struct platform_device 
> > >> *pdev)
> > >>   return 0;
> > >>  }
> > >>
> > >> +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
> > >> +static int ipmmu_resume_noirq(struct device *dev)
> > >> +{
> > >> + struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
> > >> + unsigned int i;
> > >> +
> > >> + /* This is the best we can do to check for the presence of PSCI */
> > >> + if (!psci_ops.cpu_suspend)
> > >> + return 0;
> > >
> > > PSCI suspend disabling power to the SoC completely may be a common
> > > behaviour on our development boards, but isn't mandated by the PSCI
> > > specification if I'm not mistaken. Is there a way to instead detect that
> > > power has been lost, perhaps by checking whether a register has been
> > > reset to its default value ?
> >
> > The approach here is the same as in the clk and pinctrl drivers.
> >
> > I think we could check if the IMCTR registers for allocated domains in root
> > IPMMUs are non-zero.  But that's about as expensive as doing the full
> > restore, I think.
>
> Would reading just one register be more expensive that full
> reconfiguration ? Or is there no single register that could serve this
> purpose ?
>
> > And it may have to be done for each and every IPMMU instance, or do
> > you trust caching for this?
>
> If we can find a single register I think that reading it for every IPMMU
> instance wouldn't be an issue.

Upon more thought, probably it can be done by reading the IMCTR
for the first non-zero domain. Will look into it...

> > >> +static const struct dev_pm_ops ipmmu_pm  = {
> > >> + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, ipmmu_resume_noirq)
> > >> +};
> > >> +#define DEV_PM_OPS   &ipmmu_pm
> > >> +#else
> > >> +#define DEV_PM_OPS   NULL
> > >> +#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
> > >> +
> > >>  static struct platform_driver ipmmu_driver = {
> > >>   .driver = {
> > >>   .name = "ipmmu-vmsa",
> > >>   .of_match_table = of_match_ptr(ipmmu_of_ids),
> > >> + .pm = DEV_PM_OPS,
> > >
> > > I would have used conditional compilation here instead of using a
> > > DEV_PM_OPS macro, as I think the macro decreases readability (and also
> > > given how its generic name could later conflict with something else).
> >
> > You mean
> >
> > #ifdef ...
> > .pm = &ipmmu_pm,
> > #endif
> >
> > and marking ipmmu_pm __maybe_unused__?
>
> Yes. Up to you.

I'm not such a big fan of __maybe_unused. It's easy to add, and too
easy to forget to remove it when it's no longer needed (casts have the
same problem).

Usually people just annotate the actual suspend/resume methods with
__maybe_unused, which still leaves the (large) struct dev_pm_ops in
memory.

So I started preferring the DEV_PM_OPS approach...

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH 7/7] iommu/ipmmu-vmsa: Add suspend/resume support

2019-02-20 Thread Laurent Pinchart
Hi Geert,

On Wed, Feb 20, 2019 at 05:05:49PM +0100, Geert Uytterhoeven wrote:
> On Wed, Feb 20, 2019 at 4:42 PM Laurent Pinchart wrote:
> > On Wed, Feb 20, 2019 at 04:05:31PM +0100, Geert Uytterhoeven wrote:
> >> During PSCI system suspend, R-Car Gen3 SoCs are powered down, and all
> >> IPMMU state is lost.  Hence after s2ram, devices wired behind an IPMMU,
> >> and configured to use it, will see their DMA operations hang.
> >>
> >> To fix this, restore all IPMMU contexts, and re-enable all active
> >> micro-TLBs during system resume.
> >>
> >> To avoid overhead on platforms not needing it, the resume code has a
> >> build time dependency on sleep and PSCI support, and a runtime
> >> dependency on PSCI.
> >>
> >> Signed-off-by: Geert Uytterhoeven 
> >> ---
> >> This patch takes a different approach than the BSP, which implements a
> >> bulk save/restore of all registers during system suspend/resume.
> >
> > I like this approach better too.
> 
> Thanks ;-)
> 
> >> --- a/drivers/iommu/ipmmu-vmsa.c
> >> +++ b/drivers/iommu/ipmmu-vmsa.c
> 
> >> @@ -58,6 +62,7 @@ struct ipmmu_vmsa_device {
> >>   spinlock_t lock;/* Protects ctx and 
> >> domains[] */
> >>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
> >>   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
> >> + s8 utlb_ctx[IPMMU_UTLB_MAX];
> >
> > How about making this a bitmask instead to save memory ? I would also
> > rename it as utlb_ctx doesn't really carry the meaning of the field,
> > whose purpose is to store whether the µTLB is enabled or disabled.
> 
> This field isn't just a binary flag, but stores the context used for the
> uTLB, so we can map from micro-TLB to context.
> Given there can be 8 contexts, plus the need to indicate unused contexts,
> that means 4 bits/micro-TLB.  So the overhead is just 24 bytes per IPMMU
> instance.

My bad, I've overlooked that.

> I considered allocating the array dynamically (by having s8 utlb_ctx[]
> at the end of the structure), but didn't go that route, as the domains[]
> array already uses more memory.
> 
> >> @@ -1158,10 +1166,52 @@ static int ipmmu_remove(struct platform_device 
> >> *pdev)
> >>   return 0;
> >>  }
> >>
> >> +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
> >> +static int ipmmu_resume_noirq(struct device *dev)
> >> +{
> >> + struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
> >> + unsigned int i;
> >> +
> >> + /* This is the best we can do to check for the presence of PSCI */
> >> + if (!psci_ops.cpu_suspend)
> >> + return 0;
> >
> > PSCI suspend disabling power to the SoC completely may be a common
> > behaviour on our development boards, but isn't mandated by the PSCI
> > specification if I'm not mistaken. Is there a way to instead detect that
> > power has been lost, perhaps by checking whether a register has been
> > reset to its default value ?
> 
> The approach here is the same as in the clk and pinctrl drivers.
> 
> I think we could check if the IMCTR registers for allocated domains in root
> IPMMUs are non-zero.  But that's about as expensive as doing the full
> restore, I think.

Would reading just one register be more expensive that full
reconfiguration ? Or is there no single register that could serve this
purpose ?

> And it may have to be done for each and every IPMMU instance, or do
> you trust caching for this?

If we can find a single register I think that reading it for every IPMMU
instance wouldn't be an issue.

> >> +
> >> + /* Reset root MMU and restore contexts */
> >
> > I think the rest of the code adds a period at the end of sentences in
> > comments.
> 
> The balance seems to be just under 50% ;-)
> 
> >> + if (ipmmu_is_root(mmu)) {
> >> + ipmmu_device_reset(mmu);
> >> +
> >> + for (i = 0; i < mmu->num_ctx; i++) {
> >> + if (!mmu->domains[i])
> >> + continue;
> >> +
> >> + ipmmu_context_init(mmu->domains[i]);
> >> + }
> >> + }
> >> +
> >> + /* Re-enable active micro-TLBs */
> >> + for (i = 0; i < mmu->features->num_utlbs; i++) {
> >> + if (mmu->utlb_ctx[i] == IPMMU_CTX_INVALID)
> >> + continue;
> >> +
&

Re: [PATCH 7/7] iommu/ipmmu-vmsa: Add suspend/resume support

2019-02-20 Thread Geert Uytterhoeven
Hi Laurent,

On Wed, Feb 20, 2019 at 4:42 PM Laurent Pinchart
 wrote:
> On Wed, Feb 20, 2019 at 04:05:31PM +0100, Geert Uytterhoeven wrote:
> > During PSCI system suspend, R-Car Gen3 SoCs are powered down, and all
> > IPMMU state is lost.  Hence after s2ram, devices wired behind an IPMMU,
> > and configured to use it, will see their DMA operations hang.
> >
> > To fix this, restore all IPMMU contexts, and re-enable all active
> > micro-TLBs during system resume.
> >
> > To avoid overhead on platforms not needing it, the resume code has a
> > build time dependency on sleep and PSCI support, and a runtime
> > dependency on PSCI.
> >
> > Signed-off-by: Geert Uytterhoeven 
> > ---
> > This patch takes a different approach than the BSP, which implements a
> > bulk save/restore of all registers during system suspend/resume.
>
> I like this approach better too.

Thanks ;-)

> > --- a/drivers/iommu/ipmmu-vmsa.c
> > +++ b/drivers/iommu/ipmmu-vmsa.c

> > @@ -58,6 +62,7 @@ struct ipmmu_vmsa_device {
> >   spinlock_t lock;/* Protects ctx and domains[] 
> > */
> >   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
> >   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
> > + s8 utlb_ctx[IPMMU_UTLB_MAX];
>
> How about making this a bitmask instead to save memory ? I would also
> rename it as utlb_ctx doesn't really carry the meaning of the field,
> whose purpose is to store whether the µTLB is enabled or disabled.

This field isn't just a binary flag, but stores the context used for the
uTLB, so we can map from micro-TLB to context.
Given there can be 8 contexts, plus the need to indicate unused contexts,
that means 4 bits/micro-TLB.  So the overhead is just 24 bytes per IPMMU
instance.

I considered allocating the array dynamically (by having s8 utlb_ctx[]
at the end of the structure), but didn't go that route, as the domains[]
array already uses more memory.

> > @@ -1158,10 +1166,52 @@ static int ipmmu_remove(struct platform_device 
> > *pdev)
> >   return 0;
> >  }
> >
> > +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
> > +static int ipmmu_resume_noirq(struct device *dev)
> > +{
> > + struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
> > + unsigned int i;
> > +
> > + /* This is the best we can do to check for the presence of PSCI */
> > + if (!psci_ops.cpu_suspend)
> > + return 0;
>
> PSCI suspend disabling power to the SoC completely may be a common
> behaviour on our development boards, but isn't mandated by the PSCI
> specification if I'm not mistaken. Is there a way to instead detect that
> power has been lost, perhaps by checking whether a register has been
> reset to its default value ?

The approach here is the same as in the clk and pinctrl drivers.

I think we could check if the IMCTR registers for allocated domains in root
IPMMUs are non-zero.  But that's about as expensive as doing the full
restore, I think.  And it may have to be done for each and every IPMMU
instance, or do you trust caching for this?

> > +
> > + /* Reset root MMU and restore contexts */
>
> I think the rest of the code adds a period at the end of sentences in
> comments.

The balance seems to be just under 50% ;-)

> > + if (ipmmu_is_root(mmu)) {
> > + ipmmu_device_reset(mmu);
> > +
> > + for (i = 0; i < mmu->num_ctx; i++) {
> > + if (!mmu->domains[i])
> > + continue;
> > +
> > + ipmmu_context_init(mmu->domains[i]);
> > + }
> > + }
> > +
> > + /* Re-enable active micro-TLBs */
> > + for (i = 0; i < mmu->features->num_utlbs; i++) {
> > + if (mmu->utlb_ctx[i] == IPMMU_CTX_INVALID)
> > + continue;
> > +
> > + ipmmu_utlb_enable(mmu->root->domains[mmu->utlb_ctx[i]], i);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static const struct dev_pm_ops ipmmu_pm  = {
> > + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, ipmmu_resume_noirq)
> > +};
> > +#define DEV_PM_OPS   &ipmmu_pm
> > +#else
> > +#define DEV_PM_OPS   NULL
> > +#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
> > +
> >  static struct platform_driver ipmmu_driver = {
> >   .driver = {
> >   .name = "ipmmu-vmsa",
> >   .of_match_table = of_match_ptr(ipmmu_of_ids),
> > + .pm = DEV_PM_OPS,
>
> I would ha

Re: [PATCH 7/7] iommu/ipmmu-vmsa: Add suspend/resume support

2019-02-20 Thread Laurent Pinchart
Hi Geert,

Thank you for the patch.

On Wed, Feb 20, 2019 at 04:05:31PM +0100, Geert Uytterhoeven wrote:
> During PSCI system suspend, R-Car Gen3 SoCs are powered down, and all
> IPMMU state is lost.  Hence after s2ram, devices wired behind an IPMMU,
> and configured to use it, will see their DMA operations hang.
> 
> To fix this, restore all IPMMU contexts, and re-enable all active
> micro-TLBs during system resume.
> 
> To avoid overhead on platforms not needing it, the resume code has a
> build time dependency on sleep and PSCI support, and a runtime
> dependency on PSCI.
> 
> Signed-off-by: Geert Uytterhoeven 
> ---
> This patch takes a different approach than the BSP, which implements a
> bulk save/restore of all registers during system suspend/resume.

I like this approach better too.

>  drivers/iommu/ipmmu-vmsa.c | 52 +-
>  1 file changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 92a766dd8b459f0c..5d22139914e8f033 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -22,6 +22,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -36,7 +37,10 @@
>  #define arm_iommu_detach_device(...) do {} while (0)
>  #endif
>  
> -#define IPMMU_CTX_MAX 8U
> +#define IPMMU_CTX_MAX8U
> +#define IPMMU_CTX_INVALID-1
> +
> +#define IPMMU_UTLB_MAX   48U
>  
>  struct ipmmu_features {
>   bool use_ns_alias_offset;
> @@ -58,6 +62,7 @@ struct ipmmu_vmsa_device {
>   spinlock_t lock;/* Protects ctx and domains[] */
>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
> + s8 utlb_ctx[IPMMU_UTLB_MAX];

How about making this a bitmask instead to save memory ? I would also
rename it as utlb_ctx doesn't really carry the meaning of the field,
whose purpose is to store whether the µTLB is enabled or disabled.

>  
>   struct iommu_group *group;
>   struct dma_iommu_mapping *mapping;
> @@ -335,6 +340,7 @@ static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain 
> *domain,
>   ipmmu_write(mmu, IMUCTR(utlb),
>   IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
>   IMUCTR_MMUEN);
> + mmu->utlb_ctx[utlb] = domain->context_id;
>  }
>  
>  /*
> @@ -346,6 +352,7 @@ static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain 
> *domain,
>   struct ipmmu_vmsa_device *mmu = domain->mmu;
>  
>   ipmmu_write(mmu, IMUCTR(utlb), 0);
> + mmu->utlb_ctx[utlb] = IPMMU_CTX_INVALID;
>  }
>  
>  static void ipmmu_tlb_flush_all(void *cookie)
> @@ -1043,6 +1050,7 @@ static int ipmmu_probe(struct platform_device *pdev)
>   spin_lock_init(&mmu->lock);
>   bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
>   mmu->features = of_device_get_match_data(&pdev->dev);
> + memset(mmu->utlb_ctx, IPMMU_CTX_INVALID, mmu->features->num_utlbs);
>   dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
>  
>   /* Map I/O memory and request IRQ. */
> @@ -1158,10 +1166,52 @@ static int ipmmu_remove(struct platform_device *pdev)
>   return 0;
>  }
>  
> +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
> +static int ipmmu_resume_noirq(struct device *dev)
> +{
> + struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
> + unsigned int i;
> +
> + /* This is the best we can do to check for the presence of PSCI */
> + if (!psci_ops.cpu_suspend)
> + return 0;

PSCI suspend disabling power to the SoC completely may be a common
behaviour on our development boards, but isn't mandated by the PSCI
specification if I'm not mistaken. Is there a way to instead detect that
power has been lost, perhaps by checking whether a register has been
reset to its default value ?

> +
> + /* Reset root MMU and restore contexts */

I think the rest of the code adds a period at the end of sentences in
comments.

> + if (ipmmu_is_root(mmu)) {
> + ipmmu_device_reset(mmu);
> +
> + for (i = 0; i < mmu->num_ctx; i++) {
> + if (!mmu->domains[i])
> + continue;
> +
> + ipmmu_context_init(mmu->domains[i]);
> + }
> + }
> +
> + /* Re-enable active micro-TLBs */
> + for (i = 0; i < mmu->features->num_utlbs; i++) {
> + if (mmu->utlb_ctx[i] == IPMMU_CTX_INVALID)
> + continue;
> +
> + ipmmu_utlb_enable(mmu->root-&

[PATCH 7/7] iommu/ipmmu-vmsa: Add suspend/resume support

2019-02-20 Thread Geert Uytterhoeven
During PSCI system suspend, R-Car Gen3 SoCs are powered down, and all
IPMMU state is lost.  Hence after s2ram, devices wired behind an IPMMU,
and configured to use it, will see their DMA operations hang.

To fix this, restore all IPMMU contexts, and re-enable all active
micro-TLBs during system resume.

To avoid overhead on platforms not needing it, the resume code has a
build time dependency on sleep and PSCI support, and a runtime
dependency on PSCI.

Signed-off-by: Geert Uytterhoeven 
---
This patch takes a different approach than the BSP, which implements a
bulk save/restore of all registers during system suspend/resume.

 drivers/iommu/ipmmu-vmsa.c | 52 +-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 92a766dd8b459f0c..5d22139914e8f033 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -36,7 +37,10 @@
 #define arm_iommu_detach_device(...)   do {} while (0)
 #endif
 
-#define IPMMU_CTX_MAX 8U
+#define IPMMU_CTX_MAX  8U
+#define IPMMU_CTX_INVALID  -1
+
+#define IPMMU_UTLB_MAX 48U
 
 struct ipmmu_features {
bool use_ns_alias_offset;
@@ -58,6 +62,7 @@ struct ipmmu_vmsa_device {
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
+   s8 utlb_ctx[IPMMU_UTLB_MAX];
 
struct iommu_group *group;
struct dma_iommu_mapping *mapping;
@@ -335,6 +340,7 @@ static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain 
*domain,
ipmmu_write(mmu, IMUCTR(utlb),
IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
IMUCTR_MMUEN);
+   mmu->utlb_ctx[utlb] = domain->context_id;
 }
 
 /*
@@ -346,6 +352,7 @@ static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain 
*domain,
struct ipmmu_vmsa_device *mmu = domain->mmu;
 
ipmmu_write(mmu, IMUCTR(utlb), 0);
+   mmu->utlb_ctx[utlb] = IPMMU_CTX_INVALID;
 }
 
 static void ipmmu_tlb_flush_all(void *cookie)
@@ -1043,6 +1050,7 @@ static int ipmmu_probe(struct platform_device *pdev)
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(&pdev->dev);
+   memset(mmu->utlb_ctx, IPMMU_CTX_INVALID, mmu->features->num_utlbs);
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
 
/* Map I/O memory and request IRQ. */
@@ -1158,10 +1166,52 @@ static int ipmmu_remove(struct platform_device *pdev)
return 0;
 }
 
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
+static int ipmmu_resume_noirq(struct device *dev)
+{
+   struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
+   unsigned int i;
+
+   /* This is the best we can do to check for the presence of PSCI */
+   if (!psci_ops.cpu_suspend)
+   return 0;
+
+   /* Reset root MMU and restore contexts */
+   if (ipmmu_is_root(mmu)) {
+   ipmmu_device_reset(mmu);
+
+   for (i = 0; i < mmu->num_ctx; i++) {
+   if (!mmu->domains[i])
+   continue;
+
+   ipmmu_context_init(mmu->domains[i]);
+   }
+   }
+
+   /* Re-enable active micro-TLBs */
+   for (i = 0; i < mmu->features->num_utlbs; i++) {
+   if (mmu->utlb_ctx[i] == IPMMU_CTX_INVALID)
+   continue;
+
+   ipmmu_utlb_enable(mmu->root->domains[mmu->utlb_ctx[i]], i);
+   }
+
+   return 0;
+}
+
+static const struct dev_pm_ops ipmmu_pm  = {
+   SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, ipmmu_resume_noirq)
+};
+#define DEV_PM_OPS &ipmmu_pm
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
+
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",
.of_match_table = of_match_ptr(ipmmu_of_ids),
+   .pm = DEV_PM_OPS,
},
.probe = ipmmu_probe,
.remove = ipmmu_remove,
-- 
2.17.1



[PATCH 0/7] iommu/ipmmu-vmsa: Suspend/resume support and assorted cleanups

2019-02-20 Thread Geert Uytterhoeven
Hi Jörg, Magnus,

On R-Car Gen3 systems with PSCI, PSCI may power down the SoC during
system suspend, thus losing all IOMMU state.  Hence after s2ram, devices
behind an IPMMU (e.g. SATA), and configured to use it, will fail to
complete their I/O operations.

This patch series adds suspend/resume support to the Renesas IPMMU-VMSA
IOMMU driver, and performs some smaller cleanups and fixes during the
process.  Most patches are fairly independent, except for patch 7/7,
which depends on patches 5/7 and 6/7.

This has been tested on Salvator-XS with R-Car H3 ES2.0, with IPMMU
suport for SATA enabled.  To play safe, the resume operation has also
been tested on R-Car M2-W, where it is currently not enabled due to the
absence of PSCI in the firmware.

Thanks for your comments!

Geert Uytterhoeven (7):
  iommu/ipmmu-vmsa: Link IOMMUs and devices in sysfs
  iommu/ipmmu-vmsa: Call ipmmu_ctx_write_root() instead of open coding
  iommu/ipmmu-vmsa: Prepare to handle 40-bit error addresses
  iommu/ipmmu-vmsa: Make IPMMU_CTX_MAX unsigned
  iommu/ipmmu-vmsa: Move num_utlbs to SoC-specific features
  iommu/ipmmu-vmsa: Extract hardware context initialization
  iommu/ipmmu-vmsa: Add suspend/resume support

 drivers/iommu/ipmmu-vmsa.c | 194 +
 1 file changed, 131 insertions(+), 63 deletions(-)

-- 
2.17.1

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH 0/3] usb: gadget: atmel: support USB suspend/resume

2019-02-20 Thread Jonas Bonn
This patch series hooks up proper support for USB suspend and resume to the
Atmel UDC.

Jonas Bonn (3):
  usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled
mask
  usb: gadget: atmel: support USB suspend
  usb: gadget: atmel: tie wake lock to running clock

 drivers/usb/gadget/udc/atmel_usba_udc.c | 84 -
 drivers/usb/gadget/udc/atmel_usba_udc.h |  1 +
 2 files changed, 71 insertions(+), 14 deletions(-)

-- 
2.19.1



[PATCH 4.19 50/85] gpio: mxc: move gpio noirq suspend/resume to syscore phase

2019-02-18 Thread Greg Kroah-Hartman
4.19-stable review patch.  If anyone has any objections, please let me know.

--

commit 1a5287a3dbc34cd0c02c8f64c9131bd23cdfe2bb upstream.

During noirq suspend/resume phase, GPIO irq could arrive
and its registers like IMR will be changed by irq handle
process, to make the GPIO registers exactly when it is
powered ON after resume, move the GPIO noirq suspend/resume
callback to syscore suspend/resume phase, local irq is
disabled at this phase so GPIO registers are atomic.

Fixes: c19fdaeea0aa ("gpio: mxc: add power management support")
Signed-off-by: Anson Huang 
Signed-off-by: Linus Walleij 
Signed-off-by: Martin Hundebøll 
Cc:  # 4.19.x+
Signed-off-by: Sasha Levin 
---
 drivers/gpio/gpio-mxc.c | 41 -
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 995cf0b9e0b1..2d1dfa1e0745 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -550,33 +551,38 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port 
*port)
writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
 }
 
-static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
+static int mxc_gpio_syscore_suspend(void)
 {
-   struct platform_device *pdev = to_platform_device(dev);
-   struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+   struct mxc_gpio_port *port;
 
-   mxc_gpio_save_regs(port);
-   clk_disable_unprepare(port->clk);
+   /* walk through all ports */
+   list_for_each_entry(port, &mxc_gpio_ports, node) {
+   mxc_gpio_save_regs(port);
+   clk_disable_unprepare(port->clk);
+   }
 
return 0;
 }
 
-static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
+static void mxc_gpio_syscore_resume(void)
 {
-   struct platform_device *pdev = to_platform_device(dev);
-   struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+   struct mxc_gpio_port *port;
int ret;
 
-   ret = clk_prepare_enable(port->clk);
-   if (ret)
-   return ret;
-   mxc_gpio_restore_regs(port);
-
-   return 0;
+   /* walk through all ports */
+   list_for_each_entry(port, &mxc_gpio_ports, node) {
+   ret = clk_prepare_enable(port->clk);
+   if (ret) {
+   pr_err("mxc: failed to enable gpio clock %d\n", ret);
+   return;
+   }
+   mxc_gpio_restore_regs(port);
+   }
 }
 
-static const struct dev_pm_ops mxc_gpio_dev_pm_ops = {
-   SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, 
mxc_gpio_noirq_resume)
+static struct syscore_ops mxc_gpio_syscore_ops = {
+   .suspend = mxc_gpio_syscore_suspend,
+   .resume = mxc_gpio_syscore_resume,
 };
 
 static struct platform_driver mxc_gpio_driver = {
@@ -584,7 +590,6 @@ static struct platform_driver mxc_gpio_driver = {
.name   = "gpio-mxc",
.of_match_table = mxc_gpio_dt_ids,
.suppress_bind_attrs = true,
-   .pm = &mxc_gpio_dev_pm_ops,
},
.probe  = mxc_gpio_probe,
.id_table   = mxc_gpio_devtype,
@@ -592,6 +597,8 @@ static struct platform_driver mxc_gpio_driver = {
 
 static int __init gpio_mxc_init(void)
 {
+   register_syscore_ops(&mxc_gpio_syscore_ops);
+
return platform_driver_register(&mxc_gpio_driver);
 }
 subsys_initcall(gpio_mxc_init);
-- 
2.19.1





[PATCH 4.20 49/92] gpio: mxc: move gpio noirq suspend/resume to syscore phase

2019-02-18 Thread Greg Kroah-Hartman
4.20-stable review patch.  If anyone has any objections, please let me know.

--

commit 1a5287a3dbc34cd0c02c8f64c9131bd23cdfe2bb upstream.

During noirq suspend/resume phase, GPIO irq could arrive
and its registers like IMR will be changed by irq handle
process, to make the GPIO registers exactly when it is
powered ON after resume, move the GPIO noirq suspend/resume
callback to syscore suspend/resume phase, local irq is
disabled at this phase so GPIO registers are atomic.

Fixes: c19fdaeea0aa ("gpio: mxc: add power management support")
Signed-off-by: Anson Huang 
Signed-off-by: Linus Walleij 
Signed-off-by: Martin Hundebøll 
Cc:  # 4.19.x+
Signed-off-by: Sasha Levin 
---
 drivers/gpio/gpio-mxc.c | 41 -
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 995cf0b9e0b1..2d1dfa1e0745 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -550,33 +551,38 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port 
*port)
writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
 }
 
-static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
+static int mxc_gpio_syscore_suspend(void)
 {
-   struct platform_device *pdev = to_platform_device(dev);
-   struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+   struct mxc_gpio_port *port;
 
-   mxc_gpio_save_regs(port);
-   clk_disable_unprepare(port->clk);
+   /* walk through all ports */
+   list_for_each_entry(port, &mxc_gpio_ports, node) {
+   mxc_gpio_save_regs(port);
+   clk_disable_unprepare(port->clk);
+   }
 
return 0;
 }
 
-static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
+static void mxc_gpio_syscore_resume(void)
 {
-   struct platform_device *pdev = to_platform_device(dev);
-   struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+   struct mxc_gpio_port *port;
int ret;
 
-   ret = clk_prepare_enable(port->clk);
-   if (ret)
-   return ret;
-   mxc_gpio_restore_regs(port);
-
-   return 0;
+   /* walk through all ports */
+   list_for_each_entry(port, &mxc_gpio_ports, node) {
+   ret = clk_prepare_enable(port->clk);
+   if (ret) {
+   pr_err("mxc: failed to enable gpio clock %d\n", ret);
+   return;
+   }
+   mxc_gpio_restore_regs(port);
+   }
 }
 
-static const struct dev_pm_ops mxc_gpio_dev_pm_ops = {
-   SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, 
mxc_gpio_noirq_resume)
+static struct syscore_ops mxc_gpio_syscore_ops = {
+   .suspend = mxc_gpio_syscore_suspend,
+   .resume = mxc_gpio_syscore_resume,
 };
 
 static struct platform_driver mxc_gpio_driver = {
@@ -584,7 +590,6 @@ static struct platform_driver mxc_gpio_driver = {
.name   = "gpio-mxc",
.of_match_table = mxc_gpio_dt_ids,
.suppress_bind_attrs = true,
-   .pm = &mxc_gpio_dev_pm_ops,
},
.probe  = mxc_gpio_probe,
.id_table   = mxc_gpio_devtype,
@@ -592,6 +597,8 @@ static struct platform_driver mxc_gpio_driver = {
 
 static int __init gpio_mxc_init(void)
 {
+   register_syscore_ops(&mxc_gpio_syscore_ops);
+
return platform_driver_register(&mxc_gpio_driver);
 }
 subsys_initcall(gpio_mxc_init);
-- 
2.19.1





[PATCH v4 8/8] ARM: tegra: Add firmware calls required for suspend-resume

2019-02-17 Thread Dmitry Osipenko
In order to resume CPU from suspend via trusted Foundations firmware,
the LP1/LP2 boot vectors shall be specified using the firmware calls.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/mach-tegra/pm.c| 14 ++
 arch/arm/mach-tegra/reset-handler.S | 26 ++
 2 files changed, 40 insertions(+)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 66c8cd63dd86..97bdfffc244e 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,6 +33,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -207,6 +208,8 @@ void tegra_idle_lp2_last(void)
if (trusted_foundations_registered())
outer_disable();
 
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
/*
@@ -368,6 +371,17 @@ static int tegra_suspend_enter(suspend_state_t state)
if (trusted_foundations_registered())
outer_disable();
 
+   switch (mode) {
+   case TEGRA_SUSPEND_LP1:
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+   break;
+   case TEGRA_SUSPEND_LP2:
+   call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+   break;
+   default:
+   break;
+   }
+
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
/*
diff --git a/arch/arm/mach-tegra/reset-handler.S 
b/arch/arm/mach-tegra/reset-handler.S
index c827b185d281..24fb375e11a9 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
orr r1, r1, #1
str r1, [r0]
 #endif
+   bl  tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
/* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
 
b   cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ * tegra_resume_trusted_foundations
+ *
+ *   Trusted Foundations firmware initialization.
+ *
+ * Doesn't return if firmware presents.
+ * Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+   /* Check whether Trusted Foundations firmware presents. */
+   mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+   ldr r1, =__tegra_cpu_reset_handler_data_offset + \
+   RESET_DATA(TF_PRESENT)
+   ldr r1, [r2, r1]
+   cmp r1, #0
+   reteq   lr
+
+ .arch_extension sec
+   /* First call after suspend wakes firmware. No arguments required. */
+   smc #0
+
+   b   cpu_resume
+ENDPROC(tegra_resume_trusted_foundations)
 #endif
 
.align L1_CACHE_SHIFT
-- 
2.20.1



Re: [PATCH 2/4] PM / devfreq: Handle monitor suspend/resume in the devfreq core

2019-02-14 Thread Matthias Kaehlcke
Hi Chanwoo,

On Thu, Feb 14, 2019 at 11:10:00PM +0900, Chanwoo Choi wrote:
> Hi Matthias,
> 
> 2019년 2월 14일 (목) 오후 7:16, Matthias Kaehlcke 님이 작성:
> >
> > devfreq expects governors to call devfreq_monitor_suspend/resume()
> > in response to DEVFREQ_GOV_SUSPEND/RESUME events. Since the devfreq
> > core itself generates these events and invokes the governor's event
> > handler the suspend/resume of the load monitoring can be done in the
> > common code.
> >
> > Call devfreq_monitor_suspend/resume() when the governor reports a
> > successful handling of DEVFREQ_GOV_SUSPEND/RESUME and remove these
> > calls from the simpleondemand and tegra governors. Make
> > devfreq_monitor_suspend/resume() static since these functions are now
> > only used by the devfreq core.
> 
> The devfreq core generates the all events including
> DEVFREQ_GOV_START/STOP/INTERVAL.
> It is possible to make 'devfreq_monitor_*()' function as the static
> instead of exported function.
> And call them in devfreq.c as this patch as following:
> 
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -728,6 +728,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
> goto err_init;
> }
> 
> +   devfreq_monitor_start(devfreq);
> +
> list_add(&devfreq->node, &devfreq_list);
> 
> mutex_unlock(&devfreq_list_lock);
> @@ -760,6 +762,7 @@ int devfreq_remove_device(struct devfreq *devfreq)
> if (devfreq->governor)
> devfreq->governor->event_handler(devfreq,
>  DEVFREQ_GOV_STOP, NULL);
> +   devfreq_monitor_stop(devfreq);
> device_unregister(&devfreq->dev);
> 
> return 0;
> @@ -1259,6 +1262,9 @@ static ssize_t polling_interval_store(struct device 
> *dev,
> df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value);
> ret = count;
> 
> +   if (!ret)
> +   devfreq_interval_update(devfreq, (unsigned int *)data);
> +
> return ret;
>  }
>  static DEVICE_ATTR_RW(polling_interval);
> diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c
> index 79efa1e..515fb85 100644
> --- a/drivers/devfreq/tegra-devfreq.c
> +++ b/drivers/devfreq/tegra-devfreq.c
> @@ -580,13 +580,11 @@ static int tegra_governor_event_handler(struct
> devfreq *devfreq,
> 
> switch (event) {
> case DEVFREQ_GOV_START:
> -   devfreq_monitor_start(devfreq);
> tegra_actmon_enable_interrupts(tegra);
> break;
> 
> case DEVFREQ_GOV_STOP:
> tegra_actmon_disable_interrupts(tegra);
> -   devfreq_monitor_stop(devfreq);
> break;

indeed, that's similar to "[4/4] PM / devfreq: Handle monitor
start/stop in the devfreq core" of this series.

> Instead,
> 
> If the governor should execute some codes before and after of
> DEVFREQ_GOV_SUSPEND, DEVFREQ_GOV_RESUME,
> it is impossible to change the order between devfreq_monitor_*() function
> and the specific governor in the event_handler callback function of
> each governor.
> 
> For example, if some govenor requires the following sequencue,
> after this patch, it is not possible.
> 
> case DEVFREQ_GOV_SUSPEND:
> /* execute some code before devfreq_monitor_suspend() */
> devfreq_monitor_suspend()
> /* execute some code after devfreq_monitor_suspend() */

I agree that the patch introduces this limitation, however I'm not
convinced it is a problem in practice.

For suspend we'd essentially end up with:

governor_suspend
  governor->suspend

  monitor_suspend
update_status

stop polling

What would a governor want to do after polling is stopped? Is there
any real world or halfway reasonable hypothetical example?


And for resume:

governor_resume
  governor->resume

  monitor_resume
start polling

Same question here, what would the governor realistically want to do
after polling has started that it couldn't have done before?

Cheers

Matthias


Re: [PATCH 2/4] PM / devfreq: Handle monitor suspend/resume in the devfreq core

2019-02-14 Thread Chanwoo Choi
Hi Matthias,

2019년 2월 14일 (목) 오후 7:16, Matthias Kaehlcke 님이 작성:
>
> devfreq expects governors to call devfreq_monitor_suspend/resume()
> in response to DEVFREQ_GOV_SUSPEND/RESUME events. Since the devfreq
> core itself generates these events and invokes the governor's event
> handler the suspend/resume of the load monitoring can be done in the
> common code.
>
> Call devfreq_monitor_suspend/resume() when the governor reports a
> successful handling of DEVFREQ_GOV_SUSPEND/RESUME and remove these
> calls from the simpleondemand and tegra governors. Make
> devfreq_monitor_suspend/resume() static since these functions are now
> only used by the devfreq core.

The devfreq core generates the all events including
DEVFREQ_GOV_START/STOP/INTERVAL.
It is possible to make 'devfreq_monitor_*()' function as the static
instead of exported function.
And call them in devfreq.c as this patch as following:

--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -728,6 +728,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
goto err_init;
}

+   devfreq_monitor_start(devfreq);
+
list_add(&devfreq->node, &devfreq_list);

mutex_unlock(&devfreq_list_lock);
@@ -760,6 +762,7 @@ int devfreq_remove_device(struct devfreq *devfreq)
if (devfreq->governor)
devfreq->governor->event_handler(devfreq,
 DEVFREQ_GOV_STOP, NULL);
+   devfreq_monitor_stop(devfreq);
device_unregister(&devfreq->dev);

return 0;
@@ -1259,6 +1262,9 @@ static ssize_t polling_interval_store(struct device *dev,
df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value);
ret = count;

+   if (!ret)
+   devfreq_interval_update(devfreq, (unsigned int *)data);
+
return ret;
 }
 static DEVICE_ATTR_RW(polling_interval);
diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c
index 79efa1e..515fb85 100644
--- a/drivers/devfreq/tegra-devfreq.c
+++ b/drivers/devfreq/tegra-devfreq.c
@@ -580,13 +580,11 @@ static int tegra_governor_event_handler(struct
devfreq *devfreq,

switch (event) {
case DEVFREQ_GOV_START:
-   devfreq_monitor_start(devfreq);
tegra_actmon_enable_interrupts(tegra);
break;

case DEVFREQ_GOV_STOP:
tegra_actmon_disable_interrupts(tegra);
-   devfreq_monitor_stop(devfreq);
break;

Instead,

If the governor should execute some codes before and after of
DEVFREQ_GOV_SUSPEND, DEVFREQ_GOV_RESUME,
it is impossible to change the order between devfreq_monitor_*() function
and the specific governor in the event_handler callback function of
each governor.

For example, if some govenor requires the following sequencue,
after this patch, it is not possible.

case DEVFREQ_GOV_SUSPEND:
/* execute some code before devfreq_monitor_suspend() */
devfreq_monitor_suspend()
/* execute some code after devfreq_monitor_suspend() */

>
> Signed-off-by: Matthias Kaehlcke 
> ---
>  drivers/devfreq/devfreq.c | 18 --
>  drivers/devfreq/governor.h|  2 --
>  drivers/devfreq/governor_simpleondemand.c |  8 
>  drivers/devfreq/tegra-devfreq.c   |  2 --
>  4 files changed, 8 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> index 1d3a43f8b3a10..7fab6c4cf719b 100644
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -447,15 +447,13 @@ EXPORT_SYMBOL(devfreq_monitor_stop);
>   * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
>   * @devfreq:   the devfreq instance.
>   *
> - * Helper function to suspend devfreq device load monitoing. Function
> - * to be called from governor in response to DEVFREQ_GOV_SUSPEND
> - * event or when polling interval is set to zero.
> + * Helper function to suspend devfreq device load monitoring.
>   *
>   * Note: Though this function is same as devfreq_monitor_stop(),
>   * intentionally kept separate to provide hooks for collecting
>   * transition statistics.
>   */
> -void devfreq_monitor_suspend(struct devfreq *devfreq)
> +static void devfreq_monitor_suspend(struct devfreq *devfreq)
>  {
> mutex_lock(&devfreq->lock);
> if (devfreq->monitor_state != DEVFREQ_MONITOR_RUNNING) {
> @@ -468,17 +466,14 @@ void devfreq_monitor_suspend(struct devfreq *devfreq)
> mutex_unlock(&devfreq->lock);
> cancel_delayed_work_sync(&devfreq->work);
>  }
> -EXPORT_SYMBOL(devfreq_monitor_suspend);
>
>  /**
>   * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
>   * @devfreq:the devfr

[PATCH 2/4] PM / devfreq: Handle monitor suspend/resume in the devfreq core

2019-02-13 Thread Matthias Kaehlcke
devfreq expects governors to call devfreq_monitor_suspend/resume()
in response to DEVFREQ_GOV_SUSPEND/RESUME events. Since the devfreq
core itself generates these events and invokes the governor's event
handler the suspend/resume of the load monitoring can be done in the
common code.

Call devfreq_monitor_suspend/resume() when the governor reports a
successful handling of DEVFREQ_GOV_SUSPEND/RESUME and remove these
calls from the simpleondemand and tegra governors. Make
devfreq_monitor_suspend/resume() static since these functions are now
only used by the devfreq core.

Signed-off-by: Matthias Kaehlcke 
---
 drivers/devfreq/devfreq.c | 18 --
 drivers/devfreq/governor.h|  2 --
 drivers/devfreq/governor_simpleondemand.c |  8 
 drivers/devfreq/tegra-devfreq.c   |  2 --
 4 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 1d3a43f8b3a10..7fab6c4cf719b 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -447,15 +447,13 @@ EXPORT_SYMBOL(devfreq_monitor_stop);
  * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
  * @devfreq:   the devfreq instance.
  *
- * Helper function to suspend devfreq device load monitoing. Function
- * to be called from governor in response to DEVFREQ_GOV_SUSPEND
- * event or when polling interval is set to zero.
+ * Helper function to suspend devfreq device load monitoring.
  *
  * Note: Though this function is same as devfreq_monitor_stop(),
  * intentionally kept separate to provide hooks for collecting
  * transition statistics.
  */
-void devfreq_monitor_suspend(struct devfreq *devfreq)
+static void devfreq_monitor_suspend(struct devfreq *devfreq)
 {
mutex_lock(&devfreq->lock);
if (devfreq->monitor_state != DEVFREQ_MONITOR_RUNNING) {
@@ -468,17 +466,14 @@ void devfreq_monitor_suspend(struct devfreq *devfreq)
mutex_unlock(&devfreq->lock);
cancel_delayed_work_sync(&devfreq->work);
 }
-EXPORT_SYMBOL(devfreq_monitor_suspend);
 
 /**
  * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
  * @devfreq:the devfreq instance.
  *
- * Helper function to resume devfreq device load monitoing. Function
- * to be called from governor in response to DEVFREQ_GOV_RESUME
- * event or when polling interval is set to non-zero.
+ * Helper function to resume devfreq device load monitoring.
  */
-void devfreq_monitor_resume(struct devfreq *devfreq)
+static void devfreq_monitor_resume(struct devfreq *devfreq)
 {
unsigned long freq;
 
@@ -501,7 +496,6 @@ void devfreq_monitor_resume(struct devfreq *devfreq)
 out:
mutex_unlock(&devfreq->lock);
 }
-EXPORT_SYMBOL(devfreq_monitor_resume);
 
 /**
  * devfreq_interval_update() - Update device devfreq monitoring interval
@@ -903,6 +897,8 @@ int devfreq_suspend_device(struct devfreq *devfreq)
DEVFREQ_GOV_SUSPEND, NULL);
if (ret)
return ret;
+
+   devfreq_monitor_suspend(devfreq);
}
 
if (devfreq->suspend_freq) {
@@ -944,6 +940,8 @@ int devfreq_resume_device(struct devfreq *devfreq)
DEVFREQ_GOV_RESUME, NULL);
if (ret)
return ret;
+
+   devfreq_monitor_resume(devfreq);
}
 
return 0;
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
index f53339ca610fc..d136792c0cc91 100644
--- a/drivers/devfreq/governor.h
+++ b/drivers/devfreq/governor.h
@@ -59,8 +59,6 @@ struct devfreq_governor {
 
 extern void devfreq_monitor_start(struct devfreq *devfreq);
 extern void devfreq_monitor_stop(struct devfreq *devfreq);
-extern void devfreq_monitor_suspend(struct devfreq *devfreq);
-extern void devfreq_monitor_resume(struct devfreq *devfreq);
 extern void devfreq_interval_update(struct devfreq *devfreq,
unsigned int *delay);
 
diff --git a/drivers/devfreq/governor_simpleondemand.c 
b/drivers/devfreq/governor_simpleondemand.c
index c0417f0e081e0..52eb0c734b312 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -103,14 +103,6 @@ static int devfreq_simple_ondemand_handler(struct devfreq 
*devfreq,
devfreq_interval_update(devfreq, (unsigned int *)data);
break;
 
-   case DEVFREQ_GOV_SUSPEND:
-   devfreq_monitor_suspend(devfreq);
-   break;
-
-   case DEVFREQ_GOV_RESUME:
-   devfreq_monitor_resume(devfreq);
-   break;
-
default:
break;
}
diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c
index c59d2eee5d309..79efa1e51bd06 100644
--- a/drivers/devfreq/tegra-devfreq.c
+++ b/drivers/devfreq/tegra-devfreq.c
@@ -591,11 +591,9 @@ static 

Re: [PATCH v1 2/2] PCI/ASPM: Save LTR Capability for suspend/resume

2019-02-13 Thread Bjorn Helgaas
On Wed, Feb 13, 2019 at 10:53:01AM +0530, Vidya Sagar wrote:
> On 2/12/2019 4:25 AM, Bjorn Helgaas wrote:
> > From: Bjorn Helgaas 
> > 
> > Latency Tolerance Reporting (LTR) allows Endpoints and Switch Upstream
> > Ports to report their latency requirements to upstream components.  If ASPM
> > L1 PM substates are enabled, the LTR information helps determine when a
> > Link enters L1.2 [1].
> > 
> > Software must set the maximum latency values in the LTR Capability based on
> > characteristics of the platform, then set LTR Mechanism Enable in the
> > Device Control 2 register in the PCIe Capability.  The device can then use
> > LTR to report its latency tolerance.
> > 
> > If the device reports a maximum latency value of zero, that means the
> > device requires the highest possible performance and the ASPM L1.2 substate
> > is effectively disabled.
> > 
> > We put devices in D3 for suspend, and we assume their internal state is
> > lost.  On resume, previously we did not restore the LTR Capability, but we
> > did restore the LTR Mechanism Enable bit, so devices would request the
> > highest possible performance and ASPM L1.2 wouldn't be used.
> > 
> > [1] PCIe r4.0, sec 5.5.1
> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=201469
> > Signed-off-by: Bjorn Helgaas 
> > ---
> >   drivers/pci/pci.c |   53 
> > +++--
> >   1 file changed, 51 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index c9d8e3c837de..13d65991c77b 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -1233,7 +1233,6 @@ static void pci_restore_pcie_state(struct pci_dev 
> > *dev)
> > pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]);
> >   }
> > -
> >   static int pci_save_pcix_state(struct pci_dev *dev)
> >   {
> > int pos;
> > @@ -1270,6 +1269,45 @@ static void pci_restore_pcix_state(struct pci_dev 
> > *dev)
> > pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
> >   }
> > +static void pci_save_ltr_state(struct pci_dev *dev)
> > +{
> > +   int ltr;
> > +   struct pci_cap_saved_state *save_state;
> > +   u16 *cap;
> > +
> > +   if (!pci_is_pcie(dev))
> > +   return;
> > +
> > +   ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
> > +   if (!ltr)
> > +   return;
> > +
> > +   save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
> > +   if (!save_state) {
> > +   pci_err(dev, "no suspend buffer for LTR; ASPM issues possible 
> > after resume\n");
> > +   return;
> > +   }
> > +
> > +   cap = (u16 *)&save_state->cap.data[0];
> > +   pci_read_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap++);
> > +   pci_read_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, cap++);
> > +}
> > +
> > +static void pci_restore_ltr_state(struct pci_dev *dev)
> > +{
> > +   struct pci_cap_saved_state *save_state;
> > +   int ltr;
> > +   u16 *cap;
> > +
> > +   save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
> > +   ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
> > +   if (!save_state || !ltr)
> > +   return;
> > +
> > +   cap = (u16 *)&save_state->cap.data[0];
> > +   pci_write_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap++);
> > +   pci_write_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, *cap++);
> > +}
> >   /**
> >* pci_save_state - save the PCI configuration space of a device before 
> > suspending
> > @@ -1291,6 +1329,7 @@ int pci_save_state(struct pci_dev *dev)
> > if (i != 0)
> > return i;
> > +   pci_save_ltr_state(dev);
> > pci_save_dpc_state(dev);
> > return pci_save_vc_state(dev);
> >   }
> > @@ -1390,7 +1429,12 @@ void pci_restore_state(struct pci_dev *dev)
> > if (!dev->state_saved)
> > return;
> > -   /* PCI Express register must be restored first */
> > +   /*
> > +* Restore max latencies (in the LTR capability) before enabling
> > +* LTR itself (in the PCIe capability).
> > +*/
> > +   pci_restore_ltr_state(dev);
> > +
> > pci_restore_pcie_state(dev);
> > pci_restore_pasid_state(dev);
> > pci_restore_pri_state(dev);
> > @@ -2998,6 +3042,11 @@ void pci_allocate_cap_save_buffers(struct pci_dev 
> > *dev)
> > if (error)
> > pci_err(dev, "unable to preallocate PCI-X save buffer\n");
> > +   error = pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_LTR,
> > +   2 * sizeof(u16));
> > +   if (error)
> > +   pci_err(dev, "unable to allocate suspend buffer for LTR\n");
> > +
> > pci_allocate_vc_save_buffers(dev);
> >   }

> Don't we have to save and restore L1SS control registers (PCI_L1SS_CTL1 &
> PCI_L1SS_CTL2) as well?

I think you're right!  It's getting embarrassing how much stuff we
missed.  I'll work on this, and look for other capabilities where we
might be missing save/restore.

Bjorn


Re: [PATCH v1 2/2] PCI/ASPM: Save LTR Capability for suspend/resume

2019-02-12 Thread Vidya Sagar



On 2/12/2019 4:25 AM, Bjorn Helgaas wrote:

From: Bjorn Helgaas 

Latency Tolerance Reporting (LTR) allows Endpoints and Switch Upstream
Ports to report their latency requirements to upstream components.  If ASPM
L1 PM substates are enabled, the LTR information helps determine when a
Link enters L1.2 [1].

Software must set the maximum latency values in the LTR Capability based on
characteristics of the platform, then set LTR Mechanism Enable in the
Device Control 2 register in the PCIe Capability.  The device can then use
LTR to report its latency tolerance.

If the device reports a maximum latency value of zero, that means the
device requires the highest possible performance and the ASPM L1.2 substate
is effectively disabled.

We put devices in D3 for suspend, and we assume their internal state is
lost.  On resume, previously we did not restore the LTR Capability, but we
did restore the LTR Mechanism Enable bit, so devices would request the
highest possible performance and ASPM L1.2 wouldn't be used.

[1] PCIe r4.0, sec 5.5.1
Link: https://bugzilla.kernel.org/show_bug.cgi?id=201469
Signed-off-by: Bjorn Helgaas 
---
  drivers/pci/pci.c |   53 +++--
  1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c9d8e3c837de..13d65991c77b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1233,7 +1233,6 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]);
  }
  
-

  static int pci_save_pcix_state(struct pci_dev *dev)
  {
int pos;
@@ -1270,6 +1269,45 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
  }
  
+static void pci_save_ltr_state(struct pci_dev *dev)

+{
+   int ltr;
+   struct pci_cap_saved_state *save_state;
+   u16 *cap;
+
+   if (!pci_is_pcie(dev))
+   return;
+
+   ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+   if (!ltr)
+   return;
+
+   save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
+   if (!save_state) {
+   pci_err(dev, "no suspend buffer for LTR; ASPM issues possible after 
resume\n");
+   return;
+   }
+
+   cap = (u16 *)&save_state->cap.data[0];
+   pci_read_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap++);
+   pci_read_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, cap++);
+}
+
+static void pci_restore_ltr_state(struct pci_dev *dev)
+{
+   struct pci_cap_saved_state *save_state;
+   int ltr;
+   u16 *cap;
+
+   save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
+   ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+   if (!save_state || !ltr)
+   return;
+
+   cap = (u16 *)&save_state->cap.data[0];
+   pci_write_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap++);
+   pci_write_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, *cap++);
+}
  
  /**

   * pci_save_state - save the PCI configuration space of a device before 
suspending
@@ -1291,6 +1329,7 @@ int pci_save_state(struct pci_dev *dev)
if (i != 0)
return i;
  
+	pci_save_ltr_state(dev);

pci_save_dpc_state(dev);
return pci_save_vc_state(dev);
  }
@@ -1390,7 +1429,12 @@ void pci_restore_state(struct pci_dev *dev)
if (!dev->state_saved)
return;
  
-	/* PCI Express register must be restored first */

+   /*
+* Restore max latencies (in the LTR capability) before enabling
+* LTR itself (in the PCIe capability).
+*/
+   pci_restore_ltr_state(dev);
+
pci_restore_pcie_state(dev);
pci_restore_pasid_state(dev);
pci_restore_pri_state(dev);
@@ -2998,6 +3042,11 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
if (error)
pci_err(dev, "unable to preallocate PCI-X save buffer\n");
  
+	error = pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_LTR,

+   2 * sizeof(u16));
+   if (error)
+   pci_err(dev, "unable to allocate suspend buffer for LTR\n");
+
pci_allocate_vc_save_buffers(dev);
  }
Don't we have to save and restore L1SS control registers (PCI_L1SS_CTL1 
& PCI_L1SS_CTL2) as well?
  



[PATCH] mailbox: imx: keep MU irq working during suspend/resume

2019-02-12 Thread Anson Huang
During noirq suspend phase, mailbox MU irq will be masked
but many drivers still need to communicate with system
controller firmware via mailbox, if MU irq is masked, it
will cause RPC timeout as below:

[   23.372103] imx-scu scu: RPC send msg timeout

Setting MU irq to be wakeup source is NOT working as GIC
driver does NOT have .irq_set_wake implemented, so to
support suspend/resume, just make imx mailbox driver NOT
suspend, since MU is always a wakeup source on i.MX platforms
with system controller inside, and its power/clock is
maintained by system controller, mailbox driver no need
to manage them.

Signed-off-by: Anson Huang 
---
 drivers/mailbox/imx-mailbox.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
index 774362a..85fc5b5 100644
--- a/drivers/mailbox/imx-mailbox.c
+++ b/drivers/mailbox/imx-mailbox.c
@@ -187,8 +187,8 @@ static int imx_mu_startup(struct mbox_chan *chan)
return 0;
}
 
-   ret = request_irq(priv->irq, imx_mu_isr, IRQF_SHARED, cp->irq_desc,
- chan);
+   ret = request_irq(priv->irq, imx_mu_isr, IRQF_SHARED |
+ IRQF_NO_SUSPEND, cp->irq_desc, chan);
if (ret) {
dev_err(priv->dev,
"Unable to acquire IRQ %d\n", priv->irq);
-- 
2.7.4



[PATCH v1 2/2] PCI/ASPM: Save LTR Capability for suspend/resume

2019-02-11 Thread Bjorn Helgaas
From: Bjorn Helgaas 

Latency Tolerance Reporting (LTR) allows Endpoints and Switch Upstream
Ports to report their latency requirements to upstream components.  If ASPM
L1 PM substates are enabled, the LTR information helps determine when a
Link enters L1.2 [1].

Software must set the maximum latency values in the LTR Capability based on
characteristics of the platform, then set LTR Mechanism Enable in the
Device Control 2 register in the PCIe Capability.  The device can then use
LTR to report its latency tolerance.

If the device reports a maximum latency value of zero, that means the
device requires the highest possible performance and the ASPM L1.2 substate
is effectively disabled.

We put devices in D3 for suspend, and we assume their internal state is
lost.  On resume, previously we did not restore the LTR Capability, but we
did restore the LTR Mechanism Enable bit, so devices would request the
highest possible performance and ASPM L1.2 wouldn't be used.

[1] PCIe r4.0, sec 5.5.1
Link: https://bugzilla.kernel.org/show_bug.cgi?id=201469
Signed-off-by: Bjorn Helgaas 
---
 drivers/pci/pci.c |   53 +++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c9d8e3c837de..13d65991c77b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1233,7 +1233,6 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]);
 }
 
-
 static int pci_save_pcix_state(struct pci_dev *dev)
 {
int pos;
@@ -1270,6 +1269,45 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
 }
 
+static void pci_save_ltr_state(struct pci_dev *dev)
+{
+   int ltr;
+   struct pci_cap_saved_state *save_state;
+   u16 *cap;
+
+   if (!pci_is_pcie(dev))
+   return;
+
+   ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+   if (!ltr)
+   return;
+
+   save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
+   if (!save_state) {
+   pci_err(dev, "no suspend buffer for LTR; ASPM issues possible 
after resume\n");
+   return;
+   }
+
+   cap = (u16 *)&save_state->cap.data[0];
+   pci_read_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap++);
+   pci_read_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, cap++);
+}
+
+static void pci_restore_ltr_state(struct pci_dev *dev)
+{
+   struct pci_cap_saved_state *save_state;
+   int ltr;
+   u16 *cap;
+
+   save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
+   ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+   if (!save_state || !ltr)
+   return;
+
+   cap = (u16 *)&save_state->cap.data[0];
+   pci_write_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap++);
+   pci_write_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, *cap++);
+}
 
 /**
  * pci_save_state - save the PCI configuration space of a device before 
suspending
@@ -1291,6 +1329,7 @@ int pci_save_state(struct pci_dev *dev)
if (i != 0)
return i;
 
+   pci_save_ltr_state(dev);
pci_save_dpc_state(dev);
return pci_save_vc_state(dev);
 }
@@ -1390,7 +1429,12 @@ void pci_restore_state(struct pci_dev *dev)
if (!dev->state_saved)
return;
 
-   /* PCI Express register must be restored first */
+   /*
+* Restore max latencies (in the LTR capability) before enabling
+* LTR itself (in the PCIe capability).
+*/
+   pci_restore_ltr_state(dev);
+
pci_restore_pcie_state(dev);
pci_restore_pasid_state(dev);
pci_restore_pri_state(dev);
@@ -2998,6 +3042,11 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
if (error)
pci_err(dev, "unable to preallocate PCI-X save buffer\n");
 
+   error = pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_LTR,
+   2 * sizeof(u16));
+   if (error)
+   pci_err(dev, "unable to allocate suspend buffer for LTR\n");
+
pci_allocate_vc_save_buffers(dev);
 }
 



PCI LTR - ASPM handling upon suspend / resume cycle. Regression since 4.18

2019-01-28 Thread Grumbach, Emmanuel
Hi,

Lately we (Intel) have got a few bugs on suspend / resume. The
complaint is that our device becomes unavailable after suspend / resume
cycle. The bug on which we have most data is [1].

The original submitter reported a regression since commit
9ab105deb60fa76d66cae5548819b4e8703d2056:

   PCI/ASPM: Disable ASPM L1.2 Substate if we don't have LTR

   When in the ASPM L1.0 state (but not the PCI-PM L1.0 state), the
   most
   recent LTR value and the LTR_L1.2_THRESHOLD determines whether the
   link
   enters the L1.2 substate.

   If we don't have LTR enabled, prevent the use of ASPM L1.2.

   PCI-PM L1.2 may still be used because it doesn't depend on
   LTR_L1.2_THRESHOLD (see PCIe r4.0, sec 5.5.1).


After this commit, L1.2 is disabled upon resume:
L1SubCtl1: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2- ASPM_L1.1+

   T_CommonMode=0us LTR1.2_Threshold=163840ns

Whereas it wasn't before this commit:
L1SubCtl1: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2+ ASPM_L1.1+
   T_CommonMode=0us LTR1.2_Threshold=163840ns

I am copying here an initial analysis by Bjorn (from [2]):

1) Linux has no support for saving/restoring the Max Latency values in
the LTR Capability.  This results in the latencies being zero after you
resume, as you see in the lspci output.  The device still *works* after
resume, but power consumption should increase because the device is
effectively requesting the best possible service, so we probably don't
use the L1.2 state at all.

2) Linux has no support for programming the Max Latency values for hot-
added devices.  When using ACPI hotplug, firmware may do this, but for
native PCIe hotplug (pciehp), the new device should again be requesting
the best possible service, resulting in more power consumption than
necessary.  The platform is supposed to supply a _DSM method with
information required to program these values


Another user found another commit impacting his device after suspend /
resume:
commit 6f9db69ad93cd6ab77d5571cf748ff7cdcfb0285

ACPI / PM: Default to s2idle in all machines supporting LP S0

The Dell Venue Pro 7140 supports the Low Power S0 Idle state, but
does not support any of the _DSM functions that the current
heuristic
checks for.

Since suspend-to-mem can not be safely performed on this machine,
and since the bitfield check can't cover this case, it is safer
to enable s2idle by default by checking for the presence of the
_DSM alone and removing the bitfield check.

This user confirmed that using suspend-to-mem instead of suspend-to-
idle works for him.

A user contacted my privately to let me know that he has issues with
devices from other vendors although I can't tell if the problem is the
same or not.

Note that this problem started from kernel 4.18.

Thank you.

[1] - https://bugzilla.kernel.org/show_bug.cgi?id=201469
[2] - https://bugzilla.kernel.org/show_bug.cgi?id=201469#c26


Re: [PATCH v2 0/3] scsi: arcmsr: Fix suspend/resume of ACB_ADAPTER_TYPE_B part 2

2019-01-22 Thread Ching Huang
On Tue, 2019-01-22 at 21:41 -0500, Martin K. Petersen wrote:
> Ching,
> 
> > This patch series are against to mkp's 5.1/scsi-queue.
> 
> Applied to 5.1/scsi-queue. Thank you.
> 
> PS. Your file permissions are odd. I always have to change your diffs
> from 755 to 644 before applying.
> 
Thanks Martin and Dan's help.

The file permission problem also confused to me.
I used Evolution mail of CentOS 6.x to submit the patches.
The mail context format is Plain text, preformatted.
I inserted the diff text file to the mail, and diff file listing as below.

-rw-r--r--. 1 root root 1663 Jan 16 04:11 p1.txt

Don't know why and when it's permission changed from 644 to 755.



Re: [PATCH v2 0/3] scsi: arcmsr: Fix suspend/resume of ACB_ADAPTER_TYPE_B part 2

2019-01-22 Thread Martin K. Petersen


Ching,

> This patch series are against to mkp's 5.1/scsi-queue.

Applied to 5.1/scsi-queue. Thank you.

PS. Your file permissions are odd. I always have to change your diffs
from 755 to 644 before applying.

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH net-next] net: dsa: mv88e6xxx: Add suspend/resume callbacks

2019-01-22 Thread Miquel Raynal
Hi Andrew,

Andrew Lunn  wrote on Tue, 22 Jan 2019 14:20:05 +0100:

> > I am not sure to understand what is lost. On my setup ethtool shows
> > that everything is fine after resume but maybe I fall into a "default"
> > working case.  
> 
> Hi Miquèl
> 
> Is the power removed from the switch? If so, you need to restore the
> full switch configuration. The current code might be sufficient for
> runtime suspend, where the switch is put into a low power mode, but it
> is kept powered. It is not sufficient for a full power cycle.
> 
> > When I compare with the two drivers pointed out by Andrew:
> > * qca8k resume callback:
> > * enable ports,
> > * call dsa_switch_resume().
> > * bcm_sf2 resume callback:
> > * call dsa_switch_resume(),
> > * reset the switch,
> > * refresh rules (Not applicable?),
> > * enable the PHYs,
> > * setup the ports,
> > * configure vlan (Not applicable?),
> > * mv88e6xxx resume callback:
> > * reset the switch,
> > * enable the PHYs,
> > * setup the ports,
> > * enable IRQs,
> > * call dsa_switch_resume().  
>  
> Here are some commands to try before you suspend:
> 
> ip link add name br0 type bridge
> ip link set br0 up
> ip link set lan1 up
> ip link set lan1 master br0
> ip link set lan2 up
> ip link set lan2 master br0
> 
> At this point, you should be able to pass traffic between lan1 and
> lan2.
> 
> bridge fdb add 00:42:42:42:42:42 lan1
> bridge fdb add 00:24:24:24:24:24 lan2
> 
> That adds two static forwarding database entries. You can show these using
> 
> bridge fdb show
> 
> There are likely to be additional dynamic FDB entries. It is O.K. to
> loose the dynamic entries over a suspend/resume cycle, but the static
> ones must remain.

Thank you very much for this, it is really helpful.

> 
> > This looks pretty similar. Maybe the ports setup are set to default
> > values while I should save some parameters at suspend? I changed a
> > few parameters (like the MTU or the queue length) but they seem to be
> > correct across suspend cycles.  
> 
> MTU and queue length have nothing to do with the actual switch. Your
> tests need to actually program the hardware.

I didn't checked the hw was programmed indeed. Well, I'll try with the
test described above and will propose something.

Thanks,
Miquèl


Re: [PATCH net-next] net: dsa: mv88e6xxx: Add suspend/resume callbacks

2019-01-22 Thread Andrew Lunn
> I am not sure to understand what is lost. On my setup ethtool shows
> that everything is fine after resume but maybe I fall into a "default"
> working case.

Hi Miquèl

Is the power removed from the switch? If so, you need to restore the
full switch configuration. The current code might be sufficient for
runtime suspend, where the switch is put into a low power mode, but it
is kept powered. It is not sufficient for a full power cycle.

> When I compare with the two drivers pointed out by Andrew:
> * qca8k resume callback:
>   * enable ports,
>   * call dsa_switch_resume().
> * bcm_sf2 resume callback:
>   * call dsa_switch_resume(),
>   * reset the switch,
>   * refresh rules (Not applicable?),
>   * enable the PHYs,
>   * setup the ports,
>   * configure vlan (Not applicable?),
> * mv88e6xxx resume callback:
>   * reset the switch,
>   * enable the PHYs,
>   * setup the ports,
>   * enable IRQs,
>   * call dsa_switch_resume().
 
Here are some commands to try before you suspend:

ip link add name br0 type bridge
ip link set br0 up
ip link set lan1 up
ip link set lan1 master br0
ip link set lan2 up
ip link set lan2 master br0

At this point, you should be able to pass traffic between lan1 and
lan2.

bridge fdb add 00:42:42:42:42:42 lan1
bridge fdb add 00:24:24:24:24:24 lan2

That adds two static forwarding database entries. You can show these using

bridge fdb show

There are likely to be additional dynamic FDB entries. It is O.K. to
loose the dynamic entries over a suspend/resume cycle, but the static
ones must remain.

> This looks pretty similar. Maybe the ports setup are set to default
> values while I should save some parameters at suspend? I changed a
> few parameters (like the MTU or the queue length) but they seem to be
> correct across suspend cycles.

MTU and queue length have nothing to do with the actual switch. Your
tests need to actually program the hardware.

Andrew


Re: [PATCH net-next] net: dsa: mv88e6xxx: Add suspend/resume callbacks

2019-01-22 Thread Miquel Raynal
Hi Florian,

Florian Fainelli  wrote on Thu, 17 Jan 2019
10:00:46 -0800:

> On 1/17/19 7:50 AM, Miquel Raynal wrote:
> > Hi Andrew, Vivien,
> > 
> > Vivien Didelot  wrote on Thu, 17 Jan 2019
> > 10:46:41 -0500:
> >   
> >> Hi,
> >>
> >> On Wed, 16 Jan 2019 23:23:29 +0100, Andrew Lunn  wrote:  
> >>> Hi Florian
> >>> 
> >>>> A possible approach could be to call the port_disable, port_enable
> >>>> callbacks from dsa_slave_suspend() and dsa_slave_resume(), I might have
> >>>> some patches doing that already somewhere.
> >>>
> >>> I expect it is also on Viviens TODO list, since this really could be
> >>> in the core.
> >>
> >> Indeed that is!  
> > 
> > So, shall I wait for Vivien's patches (adding port_disable/enable()
> > in dsa_slave_suspend/resume()) and keep the driver as-is or do you want
> > me to manually call port_disable/enable() from the mv88e6xxx driver?  
> 
> Up to you guys, the only thing that I an tell you is that my platform
> loses its register contents during suspend/resume, therefore you must
> make sure the driver re-applies the entire switch configuration,
> identical to how it was prior to suspend. If you need me to test
> something, please holler.

I am not sure to understand what is lost. On my setup ethtool shows
that everything is fine after resume but maybe I fall into a "default"
working case.

When I compare with the two drivers pointed out by Andrew:
* qca8k resume callback:
* enable ports,
* call dsa_switch_resume().
* bcm_sf2 resume callback:
* call dsa_switch_resume(),
* reset the switch,
* refresh rules (Not applicable?),
* enable the PHYs,
* setup the ports,
* configure vlan (Not applicable?),
* mv88e6xxx resume callback:
* reset the switch,
* enable the PHYs,
* setup the ports,
* enable IRQs,
* call dsa_switch_resume().

This looks pretty similar. Maybe the ports setup are set to default
values while I should save some parameters at suspend? I changed a
few parameters (like the MTU or the queue length) but they seem to be
correct across suspend cycles. Can you show a diff of what part of the
configuration is lost?

Anyway, I have little background working with switches, so I might miss
something big.


Thanks,
Miquèl


<    3   4   5   6   7   8   9   10   11   12   >