Linux Power Management development
 help / color / mirror / Atom feed
* Re: [linux-pm] [PATCH 1/4] thermal: Add a new trip type to use cooling device instance number
From: Amit Kachhap @ 2012-04-04  4:23 UTC (permalink / raw)
  To: eduardo.valentin
  Cc: R, Durgadoss, linaro-dev@lists.linaro.org, patches@linaro.org,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	linux-pm@lists.linux-foundation.org, rob.lee@linaro.org
In-Reply-To: <20120403141545.GA27497@besouro>

Hi Eduardo,

On 3 April 2012 19:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
> Hello,
>
> On Thu, Feb 23, 2012 at 04:50:14PM +0530, Amit Kachhap wrote:
>> On 23 February 2012 12:16, R, Durgadoss <durgadoss.r@intel.com> wrote:
>> > Hi Amit,
>> >
>> >> -----Original Message-----
>> >> From: amit kachhap [mailto:amitdanielk@gmail.com] On Behalf Of Amit Daniel
>> >> Kachhap
>> >> Sent: Wednesday, February 22, 2012 3:44 PM
>> >> To: linux-pm@lists.linux-foundation.org
>> >> Cc: linux-kernel@vger.kernel.org; mjg59@srcf.ucam.org; linux-
>> >> acpi@vger.kernel.org; lenb@kernel.org; linaro-dev@lists.linaro.org;
>> >> amit.kachhap@linaro.org; R, Durgadoss; rob.lee@linaro.org; patches@linaro.org
>> >> Subject: [PATCH 1/4] thermal: Add a new trip type to use cooling device
>> >> instance number
>> >>
>> >> This patch adds a new trip type THERMAL_TRIP_STATE_ACTIVE. This
>> >> trip behaves same as THERMAL_TRIP_ACTIVE but also passes the cooling
>> >> device instance number. This helps the cooling device registered as
>> >> different instances to perform appropriate cooling action decision in
>> >> the set_cur_state call back function.
>> >>
>> >> Also since the trip temperature's are in ascending order so some logic
>> >> is put in place to skip the un-necessary checks.
>> >>
>> >> Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
>> >> ---
>> >>  Documentation/thermal/sysfs-api.txt |    4 +-
>> >>  drivers/thermal/thermal_sys.c       |   45 ++++++++++++++++++++++++++++++++--
>> >>  include/linux/thermal.h             |    1 +
>> >>  3 files changed, 45 insertions(+), 5 deletions(-)
>> >>
>> >> diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-
>> >> api.txt
>> >> index 1733ab9..7a0c080 100644
>> >> --- a/Documentation/thermal/sysfs-api.txt
>> >> +++ b/Documentation/thermal/sysfs-api.txt
>> >> @@ -184,8 +184,8 @@ trip_point_[0-*]_temp
>> >>
>> >>  trip_point_[0-*]_type
>> >>       Strings which indicate the type of the trip point.
>> >> -     E.g. it can be one of critical, hot, passive, active[0-*] for ACPI
>> >> -     thermal zone.
>> >> +     E.g. it can be one of critical, hot, passive, active[0-1],
>> >> +     state-active[0-*] for ACPI thermal zone.
>> >>       RO, Optional
>> >>
>> >>  cdev[0-*]
>> >> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
>> >> index 220ce7e..d4c9b20 100644
>> >> --- a/drivers/thermal/thermal_sys.c
>> >> +++ b/drivers/thermal/thermal_sys.c
>> >> @@ -192,6 +192,8 @@ trip_point_type_show(struct device *dev, struct
>> >> device_attribute *attr,
>> >>               return sprintf(buf, "passive\n");
>> >>       case THERMAL_TRIP_ACTIVE:
>> >>               return sprintf(buf, "active\n");
>> >> +     case THERMAL_TRIP_STATE_ACTIVE:
>> >> +             return sprintf(buf, "state-active\n");
>> >>       default:
>> >>               return sprintf(buf, "unknown\n");
>> >>       }
>> >> @@ -1034,10 +1036,10 @@ EXPORT_SYMBOL(thermal_cooling_device_unregister);
>> >>
>> >>  void thermal_zone_device_update(struct thermal_zone_device *tz)
>> >>  {
>> >> -     int count, ret = 0;
>> >> -     long temp, trip_temp;
>> >> +     int count, ret = 0, inst_id;
>> >> +     long temp, trip_temp, max_state, last_trip_change = 0;
>> >>       enum thermal_trip_type trip_type;
>> >> -     struct thermal_cooling_device_instance *instance;
>> >> +     struct thermal_cooling_device_instance *instance, *state_instance;
>> >>       struct thermal_cooling_device *cdev;
>> >>
>> >>       mutex_lock(&tz->lock);
>> >> @@ -1086,6 +1088,43 @@ void thermal_zone_device_update(struct
>> >> thermal_zone_device *tz)
>> >>                                       cdev->ops->set_cur_state(cdev, 0);
>> >>                       }
>> >>                       break;
>> >> +             case THERMAL_TRIP_STATE_ACTIVE:
>> >> +                     list_for_each_entry(instance, &tz->cooling_devices,
>> >> +                                         node) {
>> >> +                             if (instance->trip != count)
>> >> +                                     continue;
>> >> +
>> >> +                             if (temp <= last_trip_change)
>> >> +                                     continue;
>> >> +
>> >> +                             inst_id = 0;
>> >> +                             /*
>> >> +                             *For this instance how many instance of same
>> >> +                             *cooling device occured before
>> >> +                             */
>> >> +
>> >> +                             list_for_each_entry(state_instance,
>> >> +                                             &tz->cooling_devices, node) {
>> >> +                                     if (instance->cdev ==
>> >> +                                                     state_instance->cdev)
>> >> +                                             inst_id++;
>> >> +                                     if (state_instance->trip == count)
>> >> +                                             break;
>> >> +                             }
>> >
>> > Can you explain a bit more on this loop and the set_cur_state below ?
>> > Sorry, I don't get the logic behind this..
>>
>> This loop is basically finding the instance id of the same cooling device.
>> Say we have done like this,
>> thermal_zone_bind_cooling_device(thermal, 2, cdev);
>> thermal_zone_bind_cooling_device(thermal, 3, cdev);
>> thermal_zone_bind_cooling_device(thermal, 4, cdev);
>>
>> In above same cooling device cdev is binded to trip no 2,3 and 4 with
>> inst_id generated as 1,2,3 respectively. so set_cur_state for those
>> trip reached will be called as,
>> set_cur_state(cdev, 1);
>> set_cur_state(cdev, 2);
>> set_cur_state(cdev, 3);
>
> In this case, why a simple state = get_cur_state() followed by a
> set_cur_state(++state) / set_cur_state(--state) is not enough?

Thanks for looking into the patch. Well actually what you are
suggesting is exactly happening in PASSIVE trip types where the states
are incremented or decremented based on thermal trend. On the contrary
what this part of code is doing is to jump to a fixed state as and
when a trip point is reached.  The cooling effect of a frequency level
is known beforehand and hence jumping into that is safe and also this
does not cause performance degradation by going into a much lower
frequency state just for temperature stablization.

>
> Another thing is if we want to do jumps in the sequence?
>
>  set_cur_state(cdev, 1);
>  set_cur_state(cdev, 3);
>  set_cur_state(cdev, 6);
>
> But for that we need a table mapping, trip vs. state.
>
>
> What do you think?
In the current thermal_zone_device_update implementation all the
checks are currently based on increase in temperature. So even though
we want to go to  set_cur_state(cdev, 6) we have to follow
set_cur_state(cdev, 1), set_cur_state(cdev, 2) ,..... and finally
set_cur_state(cdev, 6). So mapping table may not be needed as state
transition is one by one. This a type of limitation but I think there
can be some kind of modification in the way the
thermal_zone_device_update calls all the lower temperature cooling
devices instead of jumping directly to the final trip point cooling
devices.
>
>>
>> Thanks,
>> Amit D
>>
>> >
>> > Thanks,
>> > Durga
>> >
>> >> +
>> >> +                             cdev = instance->cdev;
>> >> +                             cdev->ops->get_max_state(cdev, &max_state);
>> >> +
>> >> +                             if ((temp >= trip_temp) &&
>> >> +                                             (inst_id <= max_state))
>> >> +                                     cdev->ops->set_cur_state(cdev, inst_id);
>> >> +                             else if ((temp < trip_temp) &&
>> >> +                                             (--inst_id <= max_state))
>> >> +                                     cdev->ops->set_cur_state(cdev, inst_id);
>> >> +
>> >> +                             last_trip_change = trip_temp;
>> >> +                     }
>> >> +                     break;
>> >>               case THERMAL_TRIP_PASSIVE:
>> >>                       if (temp >= trip_temp || tz->passive)
>> >>                               thermal_zone_device_passive(tz, temp,
>> >> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
>> >> index 796f1ff..8df901f 100644
>> >> --- a/include/linux/thermal.h
>> >> +++ b/include/linux/thermal.h
>> >> @@ -42,6 +42,7 @@ enum thermal_trip_type {
>> >>       THERMAL_TRIP_PASSIVE,
>> >>       THERMAL_TRIP_HOT,
>> >>       THERMAL_TRIP_CRITICAL,
>> >> +     THERMAL_TRIP_STATE_ACTIVE,
>> >>  };
>> >>
>> >>  struct thermal_zone_device_ops {
>> >> --
>> >> 1.7.1
>> >
>> _______________________________________________
>> linux-pm mailing list
>> linux-pm@lists.linux-foundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH V2 0/6] thermal: exynos: Add kernel thermal support for exynos platform
From: Amit Kachhap @ 2012-04-04  4:32 UTC (permalink / raw)
  To: lenb, rui.zhang
  Cc: linux-samsung-soc, linaro-dev, patches, linux-kernel, lm-sensors,
	linux-acpi, linux-pm
In-Reply-To: <1332137864-12943-1-git-send-email-amit.kachhap@linaro.org>

Hi Len/Rui,

Any comment or feedback from your side about the status of this patch?
Is it merge-able or major re-work is needed? I have fixed most of the
comments in this patchset and currently working on some of the minor
comments received and will submit them shortly.

Regards,
Amit Daniel

On 19 March 2012 11:47, Amit Daniel Kachhap <amit.kachhap@linaro.org> wrote:
> Changes since V1:
> *Moved the sensor driver to driver/thermal folder from driver/hwmon folder
>  as suggested by Mark Brown and Guenter Roeck
> *Added notifier support to notify the registered drivers of any cpu cooling
>  action. The driver can modify the default cooling behaviour(eg set different
>  max clip frequency).
> *The percentage based frequency replaced with absolute clipped frequency.
> *Some more conditional checks when setting max frequency.
> *Renamed the new trip type THERMAL_TRIP_STATE_ACTIVE to
>  THERMAL_TRIP_STATE_INSTANCE
> *Many review comments from R, Durgadoss <durgadoss.r@intel.com> and
>  eduardo.valentin@ti.com implemented.
> *Removed cooling stats through debugfs patch
> *The V1 based can be found here,
>  https://lkml.org/lkml/2012/2/22/123
>  http://lkml.org/lkml/2012/3/3/32
>
> Changes since RFC:
> *Changed the cpu cooling registration/unregistration API's to instance based
> *Changed the STATE_ACTIVE trip type to pass correct instance id
> *Adding support to restore back the policy->max_freq after doing frequency
>  clipping.
> *Moved the trip cooling stats from sysfs node to debugfs node as suggested
>  by Greg KH greg@kroah.com
> *Incorporated several review comments from eduardo.valentin@ti.com
> *Moved the Temperature sensor driver from driver/hwmon/ to driver/mfd
>  as discussed with Guenter Roeck <guenter.roeck@ericsson.com> and
>  Donggeun Kim <dg77.kim@samsung.com> (https://lkml.org/lkml/2012/1/5/7)
> *Some changes according to the changes in common cpu cooling APIs
> *The RFC based patches can be found here,
>  https://lkml.org/lkml/2011/12/13/186
>  https://lkml.org/lkml/2011/12/21/169
>
>
> Brief Description:
>
> 1) The generic cooling devices code is placed inside driver/thermal/* as
> placing inside acpi folder will need un-necessary enabling of acpi code. This
> codes is architecture independent.
>
> 2) This patchset adds a new trip type THERMAL_TRIP_STATE_INSTANCE which passes
> cooling device instance number and may be helpful for cpufreq cooling devices
> to take the correct cooling action. This trip type avoids the temperature
> comparision check again inside the cooling handler.
>
> 3) This patchset adds generic cpu cooling low level implementation through
> frequency clipping and cpu hotplug. In future, other cpu related cooling
> devices may be added here. An ACPI version of this already exists
> (drivers/acpi/processor_thermal.c). But this will be useful for platforms
> like ARM using the generic thermal interface along with the generic cpu
> cooling devices. The cooling device registration API's return cooling device
> pointers which can be easily binded with the thermal zone trip points.
> The important APIs exposed are,
>   a)struct thermal_cooling_device *cpufreq_cooling_register(
>        struct freq_clip_table *tab_ptr, unsigned int tab_size,
>        const struct cpumask *mask_val)
>   b)void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
>
> 4) Samsung exynos platform thermal implementation is done using the generic
> cpu cooling APIs and the new trip type. The temperature sensor driver present
> in the hwmon folder(registered as hwmon driver) is moved to thermal folder
> and registered as a thermal driver.
>
> All this patchset is based on Kernel version 3.3-rc7
>
> A simple data/control flow diagrams is shown below,
>
> Core Linux thermal <----->  Exynos thermal interface <----- Temperature Sensor
>          |                             |
>         \|/                            |
>  Cpufreq cooling device <---------------
>
>
> Amit Daniel Kachhap (6):
>  thermal: Add a new trip type to use cooling device instance number
>  thermal: Add generic cpufreq cooling implementation
>  thermal: Add generic cpuhotplug cooling implementation
>  hwmon: exynos4: Move thermal sensor driver to driver/thermal
>    directory
>  thermal: exynos4: Register the tmu sensor with the kernel thermal
>    layer
>  ARM: exynos4: Add thermal sensor driver platform device support
>
>  Documentation/hwmon/exynos4_tmu           |   81 ---
>  Documentation/thermal/cpu-cooling-api.txt |   76 +++
>  Documentation/thermal/exynos4_tmu         |   52 ++
>  Documentation/thermal/sysfs-api.txt       |    4 +-
>  arch/arm/mach-exynos/Kconfig              |   11 +
>  arch/arm/mach-exynos/Makefile             |    1 +
>  arch/arm/mach-exynos/clock.c              |    4 +
>  arch/arm/mach-exynos/dev-tmu.c            |   39 ++
>  arch/arm/mach-exynos/include/mach/irqs.h  |    2 +
>  arch/arm/mach-exynos/include/mach/map.h   |    1 +
>  arch/arm/mach-exynos/mach-origen.c        |    1 +
>  arch/arm/plat-samsung/include/plat/devs.h |    1 +
>  drivers/hwmon/Kconfig                     |   10 -
>  drivers/hwmon/Makefile                    |    1 -
>  drivers/hwmon/exynos4_tmu.c               |  514 -------------------
>  drivers/thermal/Kconfig                   |   21 +
>  drivers/thermal/Makefile                  |    2 +
>  drivers/thermal/cpu_cooling.c             |  529 +++++++++++++++++++
>  drivers/thermal/exynos4_thermal.c         |  790 +++++++++++++++++++++++++++++
>  drivers/thermal/thermal_sys.c             |   45 ++-
>  include/linux/cpu_cooling.h               |   78 +++
>  include/linux/platform_data/exynos4_tmu.h |    7 +
>  include/linux/thermal.h                   |    1 +
>  23 files changed, 1660 insertions(+), 611 deletions(-)
>  delete mode 100644 Documentation/hwmon/exynos4_tmu
>  create mode 100644 Documentation/thermal/cpu-cooling-api.txt
>  create mode 100644 Documentation/thermal/exynos4_tmu
>  create mode 100644 arch/arm/mach-exynos/dev-tmu.c
>  delete mode 100644 drivers/hwmon/exynos4_tmu.c
>  create mode 100644 drivers/thermal/cpu_cooling.c
>  create mode 100644 drivers/thermal/exynos4_thermal.c
>  create mode 100644 include/linux/cpu_cooling.h
>

^ permalink raw reply

* Re: [PATCH 1/4] thermal: Add a new trip type to use cooling device instance number
From: Eduardo Valentin @ 2012-04-04  6:27 UTC (permalink / raw)
  To: Amit Kachhap
  Cc: linaro-dev@lists.linaro.org, patches@linaro.org,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	linux-pm@lists.linux-foundation.org, rob.lee@linaro.org
In-Reply-To: <CAK44p20MOu+6qFpwwta+ttbKXgHxsDKyG06EFZBSNFO0aLMDag@mail.gmail.com>

Hello,

On Wed, Apr 04, 2012 at 09:53:15AM +0530, Amit Kachhap wrote:
> Hi Eduardo,
> 
> On 3 April 2012 19:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
> > Hello,
> >
> > On Thu, Feb 23, 2012 at 04:50:14PM +0530, Amit Kachhap wrote:
> >> On 23 February 2012 12:16, R, Durgadoss <durgadoss.r@intel.com> wrote:
> >> > Hi Amit,
> >> >
> >> >> -----Original Message-----
> >> >> From: amit kachhap [mailto:amitdanielk@gmail.com] On Behalf Of Amit Daniel
> >> >> Kachhap
> >> >> Sent: Wednesday, February 22, 2012 3:44 PM
> >> >> To: linux-pm@lists.linux-foundation.org
> >> >> Cc: linux-kernel@vger.kernel.org; mjg59@srcf.ucam.org; linux-
> >> >> acpi@vger.kernel.org; lenb@kernel.org; linaro-dev@lists.linaro.org;
> >> >> amit.kachhap@linaro.org; R, Durgadoss; rob.lee@linaro.org; patches@linaro.org
> >> >> Subject: [PATCH 1/4] thermal: Add a new trip type to use cooling device
> >> >> instance number
> >> >>
> >> >> This patch adds a new trip type THERMAL_TRIP_STATE_ACTIVE. This
> >> >> trip behaves same as THERMAL_TRIP_ACTIVE but also passes the cooling
> >> >> device instance number. This helps the cooling device registered as
> >> >> different instances to perform appropriate cooling action decision in
> >> >> the set_cur_state call back function.
> >> >>
> >> >> Also since the trip temperature's are in ascending order so some logic
> >> >> is put in place to skip the un-necessary checks.
> >> >>
> >> >> Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
> >> >> ---
> >> >>  Documentation/thermal/sysfs-api.txt |    4 +-
> >> >>  drivers/thermal/thermal_sys.c       |   45 ++++++++++++++++++++++++++++++++--
> >> >>  include/linux/thermal.h             |    1 +
> >> >>  3 files changed, 45 insertions(+), 5 deletions(-)
> >> >>
> >> >> diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-
> >> >> api.txt
> >> >> index 1733ab9..7a0c080 100644
> >> >> --- a/Documentation/thermal/sysfs-api.txt
> >> >> +++ b/Documentation/thermal/sysfs-api.txt
> >> >> @@ -184,8 +184,8 @@ trip_point_[0-*]_temp
> >> >>
> >> >>  trip_point_[0-*]_type
> >> >>       Strings which indicate the type of the trip point.
> >> >> -     E.g. it can be one of critical, hot, passive, active[0-*] for ACPI
> >> >> -     thermal zone.
> >> >> +     E.g. it can be one of critical, hot, passive, active[0-1],
> >> >> +     state-active[0-*] for ACPI thermal zone.
> >> >>       RO, Optional
> >> >>
> >> >>  cdev[0-*]
> >> >> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> >> >> index 220ce7e..d4c9b20 100644
> >> >> --- a/drivers/thermal/thermal_sys.c
> >> >> +++ b/drivers/thermal/thermal_sys.c
> >> >> @@ -192,6 +192,8 @@ trip_point_type_show(struct device *dev, struct
> >> >> device_attribute *attr,
> >> >>               return sprintf(buf, "passive\n");
> >> >>       case THERMAL_TRIP_ACTIVE:
> >> >>               return sprintf(buf, "active\n");
> >> >> +     case THERMAL_TRIP_STATE_ACTIVE:
> >> >> +             return sprintf(buf, "state-active\n");
> >> >>       default:
> >> >>               return sprintf(buf, "unknown\n");
> >> >>       }
> >> >> @@ -1034,10 +1036,10 @@ EXPORT_SYMBOL(thermal_cooling_device_unregister);
> >> >>
> >> >>  void thermal_zone_device_update(struct thermal_zone_device *tz)
> >> >>  {
> >> >> -     int count, ret = 0;
> >> >> -     long temp, trip_temp;
> >> >> +     int count, ret = 0, inst_id;
> >> >> +     long temp, trip_temp, max_state, last_trip_change = 0;
> >> >>       enum thermal_trip_type trip_type;
> >> >> -     struct thermal_cooling_device_instance *instance;
> >> >> +     struct thermal_cooling_device_instance *instance, *state_instance;
> >> >>       struct thermal_cooling_device *cdev;
> >> >>
> >> >>       mutex_lock(&tz->lock);
> >> >> @@ -1086,6 +1088,43 @@ void thermal_zone_device_update(struct
> >> >> thermal_zone_device *tz)
> >> >>                                       cdev->ops->set_cur_state(cdev, 0);
> >> >>                       }
> >> >>                       break;
> >> >> +             case THERMAL_TRIP_STATE_ACTIVE:
> >> >> +                     list_for_each_entry(instance, &tz->cooling_devices,
> >> >> +                                         node) {
> >> >> +                             if (instance->trip != count)
> >> >> +                                     continue;
> >> >> +
> >> >> +                             if (temp <= last_trip_change)
> >> >> +                                     continue;
> >> >> +
> >> >> +                             inst_id = 0;
> >> >> +                             /*
> >> >> +                             *For this instance how many instance of same
> >> >> +                             *cooling device occured before
> >> >> +                             */
> >> >> +
> >> >> +                             list_for_each_entry(state_instance,
> >> >> +                                             &tz->cooling_devices, node) {
> >> >> +                                     if (instance->cdev ==
> >> >> +                                                     state_instance->cdev)
> >> >> +                                             inst_id++;
> >> >> +                                     if (state_instance->trip == count)
> >> >> +                                             break;
> >> >> +                             }
> >> >
> >> > Can you explain a bit more on this loop and the set_cur_state below ?
> >> > Sorry, I don't get the logic behind this..
> >>
> >> This loop is basically finding the instance id of the same cooling device.
> >> Say we have done like this,
> >> thermal_zone_bind_cooling_device(thermal, 2, cdev);
> >> thermal_zone_bind_cooling_device(thermal, 3, cdev);
> >> thermal_zone_bind_cooling_device(thermal, 4, cdev);
> >>
> >> In above same cooling device cdev is binded to trip no 2,3 and 4 with
> >> inst_id generated as 1,2,3 respectively. so set_cur_state for those
> >> trip reached will be called as,
> >> set_cur_state(cdev, 1);
> >> set_cur_state(cdev, 2);
> >> set_cur_state(cdev, 3);
> >
> > In this case, why a simple state = get_cur_state() followed by a
> > set_cur_state(++state) / set_cur_state(--state) is not enough?
> 
> Thanks for looking into the patch. Well actually what you are
> suggesting is exactly happening in PASSIVE trip types where the states
> are incremented or decremented based on thermal trend. On the contrary
> what this part of code is doing is to jump to a fixed state as and
> when a trip point is reached.  The cooling effect of a frequency level
> is known beforehand and hence jumping into that is safe and also this
> does not cause performance degradation by going into a much lower
> frequency state just for temperature stablization.

Yeah, I see that you want to match an instance of the cooling device with
a cooling state for that cooling device.

> 
> >
> > Another thing is if we want to do jumps in the sequence?
> >
> >  set_cur_state(cdev, 1);
> >  set_cur_state(cdev, 3);
> >  set_cur_state(cdev, 6);
> >
> > But for that we need a table mapping, trip vs. state.
> >
> >
> > What do you think?
> In the current thermal_zone_device_update implementation all the
> checks are currently based on increase in temperature. So even though
> we want to go to  set_cur_state(cdev, 6) we have to follow
> set_cur_state(cdev, 1), set_cur_state(cdev, 2) ,..... and finally
> set_cur_state(cdev, 6). So mapping table may not be needed as state
> transition is one by one. This a type of limitation but I think there
> can be some kind of modification in the way the
> thermal_zone_device_update calls all the lower temperature cooling
> devices instead of jumping directly to the final trip point cooling
> devices.


But, because you also force the thing to be increasing / decreasing 1 by 1,
I don't understand why you don't have a similar implementation of the
PASSIVE type. Just get its cur state and set the next state based on the curr.
How that would be different than what you are currently doing?

If you want to have a 1 to 1 relation between cooling device instance and cooling
device state, then you could do the jumps I mentioned, but only if you would
have the cooling state reference stored somewhere.

What bugs me is the fact that you have to be iterating in the cooling device list to determine
the next cooling state.

> >
> >>
> >> Thanks,
> >> Amit D
> >>
> >> >
> >> > Thanks,
> >> > Durga
> >> >
> >> >> +
> >> >> +                             cdev = instance->cdev;
> >> >> +                             cdev->ops->get_max_state(cdev, &max_state);
> >> >> +
> >> >> +                             if ((temp >= trip_temp) &&
> >> >> +                                             (inst_id <= max_state))
> >> >> +                                     cdev->ops->set_cur_state(cdev, inst_id);
> >> >> +                             else if ((temp < trip_temp) &&
> >> >> +                                             (--inst_id <= max_state))
> >> >> +                                     cdev->ops->set_cur_state(cdev, inst_id);
> >> >> +
> >> >> +                             last_trip_change = trip_temp;
> >> >> +                     }
> >> >> +                     break;
> >> >>               case THERMAL_TRIP_PASSIVE:
> >> >>                       if (temp >= trip_temp || tz->passive)
> >> >>                               thermal_zone_device_passive(tz, temp,
> >> >> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> >> >> index 796f1ff..8df901f 100644
> >> >> --- a/include/linux/thermal.h
> >> >> +++ b/include/linux/thermal.h
> >> >> @@ -42,6 +42,7 @@ enum thermal_trip_type {
> >> >>       THERMAL_TRIP_PASSIVE,
> >> >>       THERMAL_TRIP_HOT,
> >> >>       THERMAL_TRIP_CRITICAL,
> >> >> +     THERMAL_TRIP_STATE_ACTIVE,
> >> >>  };
> >> >>
> >> >>  struct thermal_zone_device_ops {
> >> >> --
> >> >> 1.7.1
> >> >
> >> _______________________________________________
> >> linux-pm mailing list
> >> linux-pm@lists.linux-foundation.org
> >> https://lists.linuxfoundation.org/mailman/listinfo/linux-pm

^ permalink raw reply

* Re: [3.0.y, 3.2.y, 3.3.y] Re: [PATCH 04/76] ACPICA: Fix regression in FADT revision checks
From: Greg Kroah-Hartman @ 2012-04-04 18:58 UTC (permalink / raw)
  To: Josh Boyer
  Cc: Len Brown, linux-kernel, stable, Jonathan Nieder, linux-acpi,
	Julian Anastasov, linux-pm, wzab
In-Reply-To: <CA+5PVA58jN8S9efACB==o5Z9frEOxVN__wo9yYU6ErQcsKyj8w@mail.gmail.com>

On Tue, Apr 03, 2012 at 04:15:32PM -0400, Josh Boyer wrote:
> On Tue, Apr 3, 2012 at 3:58 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> > Hi Greg,
> >
> > Josh Boyer wrote:
> >> On Fri, Mar 30, 2012 at 6:13 AM, Len Brown <lenb@kernel.org> wrote:
> >
> >>> From: Julian Anastasov <ja@ssi.bg>
> >>>
> >>>        commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39),
> >>> "Remove use of unreliable FADT revision field" causes regression
> >>> for old P4 systems because now cst_control and other fields are
> >>> not reset to 0.
> > [...]
> >>>        The fix is to update acpi_gbl_FADT.header.length after
> >>> the original value is used to check for old revisions.
> >>>
> >>> https://bugzilla.kernel.org/show_bug.cgi?id=42700
> >>> https://bugzilla.redhat.com/show_bug.cgi?id=727865
> >>>
> >>> Signed-off-by: Julian Anastasov <ja@ssi.bg>
> >>> Acked-by: Bob Moore <robert.moore@intel.com>
> >>> Signed-off-by: Len Brown <len.brown@intel.com>
> >>
> >> This one should go into the stable trees.
> >
> > Please apply
> >
> >  3e80acd1af40 "ACPICA: Fix regression in FADT revision checks"
> >
> > which is in linus's master to the 3.0.y, 3.2.y, and 3.3.y series to
> > fix this old boot problem.  (Many affected people disabled HT in the
> > BIOS to work around it in the meantime.)
> >
> > WZab (cc-ed) has tested that the patch addresses the problem when
> > applied to the 3.2.y and 3.3.y branches.  [1] has details.
> 
> We've had this applied in Fedora on 3.2 and 3.3 for a while now as
> well.

Wonderful, now queued up, thanks for letting me know.

greg k-h

^ permalink raw reply

* [PATCH V2]mmc: remove MMC bus legacy suspend/resume method
From: Chuanxiao Dong @ 2012-04-05  7:51 UTC (permalink / raw)
  To: linux-mmc, linux-pm; +Cc: rjw

MMC bus is using legacy suspend/resume method, which is not compatible if
runtime pm callbacks are used. In this scenario, MMC bus suspend/resume
callbacks cannot be called when system entering S3. So change to use the new
defined dev_pm_ops for system sleeping mode

Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
---
Changes in v2:
	use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
	suggested

 drivers/mmc/card/block.c |    2 +-
 drivers/mmc/core/bus.c   |   26 ++++++++++++--------------
 include/linux/mmc/card.h |    2 +-
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f2020d3..3582c03 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1826,7 +1826,7 @@ static void mmc_blk_remove(struct mmc_card *card)
 }
 
 #ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+static int mmc_blk_suspend(struct mmc_card *card)
 {
 	struct mmc_blk_data *part_md;
 	struct mmc_blk_data *md = mmc_get_drvdata(card);
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 5d011a3..d44f0d9 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev)
 	return 0;
 }
 
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+static int mmc_bus_suspend(struct device *dev)
 {
 	struct mmc_driver *drv = to_mmc_driver(dev->driver);
 	struct mmc_card *card = mmc_dev_to_card(dev);
 	int ret = 0;
 
 	if (dev->driver && drv->suspend)
-		ret = drv->suspend(card, state);
+		ret = drv->suspend(card);
 	return ret;
 }
 
@@ -165,20 +165,20 @@ static int mmc_runtime_idle(struct device *dev)
 	return pm_runtime_suspend(dev);
 }
 
-static const struct dev_pm_ops mmc_bus_pm_ops = {
-	.runtime_suspend	= mmc_runtime_suspend,
-	.runtime_resume		= mmc_runtime_resume,
-	.runtime_idle		= mmc_runtime_idle,
-};
-
-#define MMC_PM_OPS_PTR	(&mmc_bus_pm_ops)
-
 #else /* !CONFIG_PM_RUNTIME */
 
-#define MMC_PM_OPS_PTR	NULL
+#define mmc_runtime_suspend	NULL
+#define mmc_runtime_resume	NULL
+#define mmc_runtime_idle	NULL
 
 #endif /* !CONFIG_PM_RUNTIME */
 
+static const struct dev_pm_ops mmc_bus_pm_ops = {
+	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
+			mmc_runtime_idle)
+	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
+};
+
 static struct bus_type mmc_bus_type = {
 	.name		= "mmc",
 	.dev_attrs	= mmc_dev_attrs,
@@ -186,9 +186,7 @@ static struct bus_type mmc_bus_type = {
 	.uevent		= mmc_bus_uevent,
 	.probe		= mmc_bus_probe,
 	.remove		= mmc_bus_remove,
-	.suspend	= mmc_bus_suspend,
-	.resume		= mmc_bus_resume,
-	.pm		= MMC_PM_OPS_PTR,
+	.pm		= &mmc_bus_pm_ops,
 };
 
 int mmc_register_bus(void)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 1a1ca71..c984c9a 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -480,7 +480,7 @@ struct mmc_driver {
 	struct device_driver drv;
 	int (*probe)(struct mmc_card *);
 	void (*remove)(struct mmc_card *);
-	int (*suspend)(struct mmc_card *, pm_message_t);
+	int (*suspend)(struct mmc_card *);
 	int (*resume)(struct mmc_card *);
 };
 
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH] Use safe_halt() rather than halt() in acpi_idle_play_deay()
From: Len Brown @ 2012-04-05 17:43 UTC (permalink / raw)
  To: Boris Ostrovsky; +Cc: Tony Luck, linux-acpi, linux-pm, linux-kernel, Len Brown
In-Reply-To: <4F7B2AC3.3060706@amd.com>

applied.

thanks,
Len Brown, Intel Open Source Technology Center

^ permalink raw reply

* [PATCH 1/1] Remove "mrst_pmu: driver for Intel Moorestown Power Management Unit"
From: Len Brown @ 2012-04-06 17:18 UTC (permalink / raw)
  To: x86, linux-pm, linux-kernel; +Cc: Len Brown

From: Len Brown <len.brown@intel.com>

This reverts commit 22f4521d664030e417f41953e922f61c65f2e189.
and
This reverts commit 6dccf9c508d5d773859df1cc2dce75c5b19e35a0.

All customers of this product line are using a different driver,
currently out-of-tree, so there is no purpose in supporting
this version upstream.

Signed-off-by: Len Brown <len.brown@intel.com>
---
 MAINTAINERS                     |    6 -
 arch/x86/platform/mrst/Makefile |    1 -
 arch/x86/platform/mrst/pmu.c    |  817 ---------------------------------------
 arch/x86/platform/mrst/pmu.h    |  234 -----------
 4 files changed, 1058 deletions(-)
 delete mode 100644 arch/x86/platform/mrst/pmu.c
 delete mode 100644 arch/x86/platform/mrst/pmu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c63a43..b741c2f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3513,12 +3513,6 @@ F:	Documentation/networking/ixgbe.txt
 F:	Documentation/networking/ixgbevf.txt
 F:	drivers/net/ethernet/intel/
 
-INTEL MRST PMU DRIVER
-M:	Len Brown <len.brown@intel.com>
-L:	linux-pm@vger.kernel.org
-S:	Supported
-F:	arch/x86/platform/mrst/pmu.*
-
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
 L:	linux-wireless@vger.kernel.org
 S:	Orphan
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile
index 7baed51..af1da7e 100644
--- a/arch/x86/platform/mrst/Makefile
+++ b/arch/x86/platform/mrst/Makefile
@@ -1,4 +1,3 @@
 obj-$(CONFIG_X86_INTEL_MID)	+= mrst.o
 obj-$(CONFIG_X86_INTEL_MID)	+= vrtc.o
 obj-$(CONFIG_EARLY_PRINTK_INTEL_MID)	+= early_printk_mrst.o
-obj-$(CONFIG_X86_MRST)		+= pmu.o
diff --git a/arch/x86/platform/mrst/pmu.c b/arch/x86/platform/mrst/pmu.c
deleted file mode 100644
index c0ac06d..0000000
--- a/arch/x86/platform/mrst/pmu.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * mrst/pmu.c - driver for MRST Power Management Unit
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/cpuidle.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/seq_file.h>
-#include <linux/sfi.h>
-#include <asm/intel_scu_ipc.h>
-#include "pmu.h"
-
-#define IPCMSG_FW_REVISION	0xF4
-
-struct mrst_device {
-	u16 pci_dev_num;	/* DEBUG only */
-	u16 lss;
-	u16 latest_request;
-	unsigned int pci_state_counts[PCI_D3cold + 1]; /* DEBUG only */
-};
-
-/*
- * comlete list of MRST PCI devices
- */
-static struct mrst_device mrst_devs[] = {
-/*  0 */ { 0x0800, LSS_SPI0 },		/* Moorestown SPI Ctrl 0 */
-/*  1 */ { 0x0801, LSS_SPI1 },		/* Moorestown SPI Ctrl 1 */
-/*  2 */ { 0x0802, LSS_I2C0 },		/* Moorestown I2C 0 */
-/*  3 */ { 0x0803, LSS_I2C1 },		/* Moorestown I2C 1 */
-/*  4 */ { 0x0804, LSS_I2C2 },		/* Moorestown I2C 2 */
-/*  5 */ { 0x0805, LSS_KBD },		/* Moorestown Keyboard Ctrl */
-/*  6 */ { 0x0806, LSS_USB_HC },	/* Moorestown USB Ctrl */
-/*  7 */ { 0x0807, LSS_SD_HC0 },	/* Moorestown SD Host Ctrl 0 */
-/*  8 */ { 0x0808, LSS_SD_HC1 },	/* Moorestown SD Host Ctrl 1 */
-/*  9 */ { 0x0809, LSS_NAND },		/* Moorestown NAND Ctrl */
-/* 10 */ { 0x080a, LSS_AUDIO },		/* Moorestown Audio Ctrl */
-/* 11 */ { 0x080b, LSS_IMAGING },	/* Moorestown ISP */
-/* 12 */ { 0x080c, LSS_SECURITY },	/* Moorestown Security Controller */
-/* 13 */ { 0x080d, LSS_DISPLAY },	/* Moorestown External Displays */
-/* 14 */ { 0x080e, 0 },			/* Moorestown SCU IPC */
-/* 15 */ { 0x080f, LSS_GPIO },		/* Moorestown GPIO Controller */
-/* 16 */ { 0x0810, 0 },			/* Moorestown Power Management Unit */
-/* 17 */ { 0x0811, LSS_USB_OTG },	/* Moorestown OTG Ctrl */
-/* 18 */ { 0x0812, LSS_SPI2 },		/* Moorestown SPI Ctrl 2 */
-/* 19 */ { 0x0813, 0 },			/* Moorestown SC DMA */
-/* 20 */ { 0x0814, LSS_AUDIO_LPE },	/* Moorestown LPE DMA */
-/* 21 */ { 0x0815, LSS_AUDIO_SSP },	/* Moorestown SSP0 */
-
-/* 22 */ { 0x084F, LSS_SD_HC2 },	/* Moorestown SD Host Ctrl 2 */
-
-/* 23 */ { 0x4102, 0 },			/* Lincroft */
-/* 24 */ { 0x4110, 0 },			/* Lincroft */
-};
-
-/* n.b. We ignore PCI-id 0x815 in LSS9 b/c Linux has no driver for it */
-static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0};
-static u16 mrst_lss10_pci_ids[] = {0x0800, 0x0801, 0x0802, 0x0803,
-					0x0804, 0x0805, 0x080f, 0};
-
-/* handle concurrent SMP invokations of pmu_pci_set_power_state() */
-static spinlock_t mrst_pmu_power_state_lock;
-
-static unsigned int wake_counters[MRST_NUM_LSS];	/* DEBUG only */
-static unsigned int pmu_irq_stats[INT_INVALID + 1];	/* DEBUG only */
-
-static int graphics_is_off;
-static int lss_s0i3_enabled;
-static bool mrst_pmu_s0i3_enable;
-
-/*  debug counters */
-static u32 pmu_wait_ready_calls;
-static u32 pmu_wait_ready_udelays;
-static u32 pmu_wait_ready_udelays_max;
-static u32 pmu_wait_done_calls;
-static u32 pmu_wait_done_udelays;
-static u32 pmu_wait_done_udelays_max;
-static u32 pmu_set_power_state_entry;
-static u32 pmu_set_power_state_send_cmd;
-
-static struct mrst_device *pci_id_2_mrst_dev(u16 pci_dev_num)
-{
-	int index = 0;
-
-	if ((pci_dev_num >= 0x0800) && (pci_dev_num <= 0x815))
-		index = pci_dev_num - 0x800;
-	else if (pci_dev_num == 0x084F)
-		index = 22;
-	else if (pci_dev_num == 0x4102)
-		index = 23;
-	else if (pci_dev_num == 0x4110)
-		index = 24;
-
-	if (pci_dev_num != mrst_devs[index].pci_dev_num) {
-		WARN_ONCE(1, FW_BUG "Unknown PCI device 0x%04X\n", pci_dev_num);
-		return 0;
-	}
-
-	return &mrst_devs[index];
-}
-
-/**
- * mrst_pmu_validate_cstates
- * @dev: cpuidle_device
- *
- * Certain states are not appropriate for governor to pick in some cases.
- * This function will be called as cpuidle_device's prepare callback and
- * thus tells governor to ignore such states when selecting the next state
- * to enter.
- */
-
-#define IDLE_STATE4_IS_C6	4
-#define IDLE_STATE5_IS_S0I3	5
-
-int mrst_pmu_invalid_cstates(void)
-{
-	int cpu = smp_processor_id();
-
-	/*
-	 * Demote to C4 if the PMU is busy.
-	 * Since LSS changes leave the busy bit clear...
-	 * busy means either the PMU is waiting for an ACK-C6 that
-	 * isn't coming due to an MWAIT that returned immediately;
-	 * or we returned from S0i3 successfully, and the PMU
-	 * is not done sending us interrupts.
-	 */
-	if (pmu_read_busy_status())
-		return 1 << IDLE_STATE4_IS_C6 | 1 << IDLE_STATE5_IS_S0I3;
-
-	/*
-	 * Disallow S0i3 if: PMU is not initialized, or CPU1 is active,
-	 * or if device LSS is insufficient, or the GPU is active,
-	 * or if it has been explicitly disabled.
-	 */
-	if (!pmu_reg || !cpumask_equal(cpu_online_mask, cpumask_of(cpu)) ||
-	    !lss_s0i3_enabled || !graphics_is_off || !mrst_pmu_s0i3_enable)
-		return 1 << IDLE_STATE5_IS_S0I3;
-	else
-		return 0;
-}
-
-/*
- * pmu_update_wake_counters(): read PM_WKS, update wake_counters[]
- * DEBUG only.
- */
-static void pmu_update_wake_counters(void)
-{
-	int lss;
-	u32 wake_status;
-
-	wake_status = pmu_read_wks();
-
-	for (lss = 0; lss < MRST_NUM_LSS; ++lss) {
-		if (wake_status & (1 << lss))
-			wake_counters[lss]++;
-	}
-}
-
-int mrst_pmu_s0i3_entry(void)
-{
-	int status;
-
-	/* Clear any possible error conditions */
-	pmu_write_ics(0x300);
-
-	/* set wake control to current D-states */
-	pmu_write_wssc(S0I3_SSS_TARGET);
-
-	status = mrst_s0i3_entry(PM_S0I3_COMMAND, &pmu_reg->pm_cmd);
-	pmu_update_wake_counters();
-	return status;
-}
-
-/* poll for maximum of 5ms for busy bit to clear */
-static int pmu_wait_ready(void)
-{
-	int udelays;
-
-	pmu_wait_ready_calls++;
-
-	for (udelays = 0; udelays < 500; ++udelays) {
-		if (udelays > pmu_wait_ready_udelays_max)
-			pmu_wait_ready_udelays_max = udelays;
-
-		if (pmu_read_busy_status() == 0)
-			return 0;
-
-		udelay(10);
-		pmu_wait_ready_udelays++;
-	}
-
-	/*
-	 * if this fires, observe
-	 * /sys/kernel/debug/mrst_pmu_wait_ready_calls
-	 * /sys/kernel/debug/mrst_pmu_wait_ready_udelays
-	 */
-	WARN_ONCE(1, "SCU not ready for 5ms");
-	return -EBUSY;
-}
-/* poll for maximum of 50ms us for busy bit to clear */
-static int pmu_wait_done(void)
-{
-	int udelays;
-
-	pmu_wait_done_calls++;
-
-	for (udelays = 0; udelays < 500; ++udelays) {
-		if (udelays > pmu_wait_done_udelays_max)
-			pmu_wait_done_udelays_max = udelays;
-
-		if (pmu_read_busy_status() == 0)
-			return 0;
-
-		udelay(100);
-		pmu_wait_done_udelays++;
-	}
-
-	/*
-	 * if this fires, observe
-	 * /sys/kernel/debug/mrst_pmu_wait_done_calls
-	 * /sys/kernel/debug/mrst_pmu_wait_done_udelays
-	 */
-	WARN_ONCE(1, "SCU not done for 50ms");
-	return -EBUSY;
-}
-
-u32 mrst_pmu_msi_is_disabled(void)
-{
-	return pmu_msi_is_disabled();
-}
-
-void mrst_pmu_enable_msi(void)
-{
-	pmu_msi_enable();
-}
-
-/**
- * pmu_irq - pmu driver interrupt handler
- * Context: interrupt context
- */
-static irqreturn_t pmu_irq(int irq, void *dummy)
-{
-	union pmu_pm_ics pmu_ics;
-
-	pmu_ics.value = pmu_read_ics();
-
-	if (!pmu_ics.bits.pending)
-		return IRQ_NONE;
-
-	switch (pmu_ics.bits.cause) {
-	case INT_SPURIOUS:
-	case INT_CMD_DONE:
-	case INT_CMD_ERR:
-	case INT_WAKE_RX:
-	case INT_SS_ERROR:
-	case INT_S0IX_MISS:
-	case INT_NO_ACKC6:
-		pmu_irq_stats[pmu_ics.bits.cause]++;
-		break;
-	default:
-		pmu_irq_stats[INT_INVALID]++;
-	}
-
-	pmu_write_ics(pmu_ics.value); /* Clear pending interrupt */
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Translate PCI power management to MRST LSS D-states
- */
-static int pci_2_mrst_state(int lss, pci_power_t pci_state)
-{
-	switch (pci_state) {
-	case PCI_D0:
-		if (SSMSK(D0i1, lss) & D0I1_ACG_SSS_TARGET)
-			return D0i1;
-		else
-			return D0;
-	case PCI_D1:
-		return D0i1;
-	case PCI_D2:
-		return D0i2;
-	case PCI_D3hot:
-	case PCI_D3cold:
-		return D0i3;
-	default:
-		WARN(1, "pci_state %d\n", pci_state);
-		return 0;
-	}
-}
-
-static int pmu_issue_command(u32 pm_ssc)
-{
-	union pmu_pm_set_cfg_cmd_t command;
-
-	if (pmu_read_busy_status()) {
-		pr_debug("pmu is busy, Operation not permitted\n");
-		return -1;
-	}
-
-	/*
-	 * enable interrupts in PMU so that interrupts are
-	 * propagated when ioc bit for a particular set
-	 * command is set
-	 */
-
-	pmu_irq_enable();
-
-	/* Configure the sub systems for pmu2 */
-
-	pmu_write_ssc(pm_ssc);
-
-	/*
-	 * Send the set config command for pmu its configured
-	 * for mode CM_IMMEDIATE & hence with No Trigger
-	 */
-
-	command.pmu2_params.d_param.cfg_mode = CM_IMMEDIATE;
-	command.pmu2_params.d_param.cfg_delay = 0;
-	command.pmu2_params.d_param.rsvd = 0;
-
-	/* construct the command to send SET_CFG to particular PMU */
-	command.pmu2_params.d_param.cmd = SET_CFG_CMD;
-	command.pmu2_params.d_param.ioc = 0;
-	command.pmu2_params.d_param.mode_id = 0;
-	command.pmu2_params.d_param.sys_state = SYS_STATE_S0I0;
-
-	/* write the value of PM_CMD into particular PMU */
-	pr_debug("pmu command being written %x\n",
-			command.pmu_pm_set_cfg_cmd_value);
-
-	pmu_write_cmd(command.pmu_pm_set_cfg_cmd_value);
-
-	return 0;
-}
-
-static u16 pmu_min_lss_pci_req(u16 *ids, u16 pci_state)
-{
-	u16 existing_request;
-	int i;
-
-	for (i = 0; ids[i]; ++i) {
-		struct mrst_device *mrst_dev;
-
-		mrst_dev = pci_id_2_mrst_dev(ids[i]);
-		if (unlikely(!mrst_dev))
-			continue;
-
-		existing_request = mrst_dev->latest_request;
-		if (existing_request < pci_state)
-			pci_state = existing_request;
-	}
-	return pci_state;
-}
-
-/**
- * pmu_pci_set_power_state - Callback function is used by all the PCI devices
- *			for a platform  specific device power on/shutdown.
- */
-
-int pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t pci_state)
-{
-	u32 old_sss, new_sss;
-	int status = 0;
-	struct mrst_device *mrst_dev;
-
-	pmu_set_power_state_entry++;
-
-	BUG_ON(pdev->vendor != PCI_VENDOR_ID_INTEL);
-	BUG_ON(pci_state < PCI_D0 || pci_state > PCI_D3cold);
-
-	mrst_dev = pci_id_2_mrst_dev(pdev->device);
-	if (unlikely(!mrst_dev))
-		return -ENODEV;
-
-	mrst_dev->pci_state_counts[pci_state]++;	/* count invocations */
-
-	/* PMU driver calls self as part of PCI initialization, ignore */
-	if (pdev->device == PCI_DEV_ID_MRST_PMU)
-		return 0;
-
-	BUG_ON(!pmu_reg); /* SW bug if called before initialized */
-
-	spin_lock(&mrst_pmu_power_state_lock);
-
-	if (pdev->d3_delay) {
-		dev_dbg(&pdev->dev, "d3_delay %d, should be 0\n",
-			pdev->d3_delay);
-		pdev->d3_delay = 0;
-	}
-	/*
-	 * If Lincroft graphics, simply remember state
-	 */
-	if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY
-		&& !((pdev->class & PCI_SUB_CLASS_MASK) >> 8)) {
-		if (pci_state == PCI_D0)
-			graphics_is_off = 0;
-		else
-			graphics_is_off = 1;
-		goto ret;
-	}
-
-	if (!mrst_dev->lss)
-		goto ret;	/* device with no LSS */
-
-	if (mrst_dev->latest_request == pci_state)
-		goto ret;	/* no change */
-
-	mrst_dev->latest_request = pci_state;	/* record latest request */
-
-	/*
-	 * LSS9 and LSS10 contain multiple PCI devices.
-	 * Use the lowest numbered (highest power) state in the LSS
-	 */
-	if (mrst_dev->lss == 9)
-		pci_state = pmu_min_lss_pci_req(mrst_lss9_pci_ids, pci_state);
-	else if (mrst_dev->lss == 10)
-		pci_state = pmu_min_lss_pci_req(mrst_lss10_pci_ids, pci_state);
-
-	status = pmu_wait_ready();
-	if (status)
-		goto ret;
-
-	old_sss = pmu_read_sss();
-	new_sss = old_sss & ~SSMSK(3, mrst_dev->lss);
-	new_sss |= SSMSK(pci_2_mrst_state(mrst_dev->lss, pci_state),
-			mrst_dev->lss);
-
-	if (new_sss == old_sss)
-		goto ret;	/* nothing to do */
-
-	pmu_set_power_state_send_cmd++;
-
-	status = pmu_issue_command(new_sss);
-
-	if (unlikely(status != 0)) {
-		dev_err(&pdev->dev, "Failed to Issue a PM command\n");
-		goto ret;
-	}
-
-	if (pmu_wait_done())
-		goto ret;
-
-	lss_s0i3_enabled =
-	((pmu_read_sss() & S0I3_SSS_TARGET) == S0I3_SSS_TARGET);
-ret:
-	spin_unlock(&mrst_pmu_power_state_lock);
-	return status;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static char *d0ix_names[] = {"D0", "D0i1", "D0i2", "D0i3"};
-
-static inline const char *d0ix_name(int state)
-{
-	return d0ix_names[(int) state];
-}
-
-static int debug_mrst_pmu_show(struct seq_file *s, void *unused)
-{
-	struct pci_dev *pdev = NULL;
-	u32 cur_pmsss;
-	int lss;
-
-	seq_printf(s, "0x%08X D0I1_ACG_SSS_TARGET\n", D0I1_ACG_SSS_TARGET);
-
-	cur_pmsss = pmu_read_sss();
-
-	seq_printf(s, "0x%08X S0I3_SSS_TARGET\n", S0I3_SSS_TARGET);
-
-	seq_printf(s, "0x%08X Current SSS ", cur_pmsss);
-	seq_printf(s, lss_s0i3_enabled ? "\n" : "[BLOCKS s0i3]\n");
-
-	if (cpumask_equal(cpu_online_mask, cpumask_of(0)))
-		seq_printf(s, "cpu0 is only cpu online\n");
-	else
-		seq_printf(s, "cpu0 is NOT only cpu online [BLOCKS S0i3]\n");
-
-	seq_printf(s, "GFX: %s\n", graphics_is_off ? "" : "[BLOCKS s0i3]");
-
-
-	for_each_pci_dev(pdev) {
-		int pos;
-		u16 pmcsr;
-		struct mrst_device *mrst_dev;
-		int i;
-
-		mrst_dev = pci_id_2_mrst_dev(pdev->device);
-
-		seq_printf(s, "%s %04x/%04X %-16.16s ",
-			dev_name(&pdev->dev),
-			pdev->vendor, pdev->device,
-			dev_driver_string(&pdev->dev));
-
-		if (unlikely (!mrst_dev)) {
-			seq_printf(s, " UNKNOWN\n");
-			continue;
-		}
-
-		if (mrst_dev->lss)
-			seq_printf(s, "LSS %2d %-4s ", mrst_dev->lss,
-				d0ix_name(((cur_pmsss >>
-					(mrst_dev->lss * 2)) & 0x3)));
-		else
-			seq_printf(s, "            ");
-
-		/* PCI PM config space setting */
-		pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
-		if (pos != 0) {
-			pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
-		seq_printf(s, "PCI-%-4s",
-			pci_power_name(pmcsr & PCI_PM_CTRL_STATE_MASK));
-		} else {
-			seq_printf(s, "        ");
-		}
-
-		seq_printf(s, " %s ", pci_power_name(mrst_dev->latest_request));
-		for (i = 0; i <= PCI_D3cold; ++i)
-			seq_printf(s, "%d ", mrst_dev->pci_state_counts[i]);
-
-		if (mrst_dev->lss) {
-			unsigned int lssmask;
-
-			lssmask = SSMSK(D0i3, mrst_dev->lss);
-
-			if ((lssmask & S0I3_SSS_TARGET) &&
-				((lssmask & cur_pmsss) !=
-					(lssmask & S0I3_SSS_TARGET)))
-						seq_printf(s , "[BLOCKS s0i3]");
-		}
-
-		seq_printf(s, "\n");
-	}
-	seq_printf(s, "Wake Counters:\n");
-	for (lss = 0; lss < MRST_NUM_LSS; ++lss)
-		seq_printf(s, "LSS%d %d\n", lss, wake_counters[lss]);
-
-	seq_printf(s, "Interrupt Counters:\n");
-	seq_printf(s,
-		"INT_SPURIOUS \t%8u\n" "INT_CMD_DONE \t%8u\n"
-		"INT_CMD_ERR  \t%8u\n" "INT_WAKE_RX  \t%8u\n"
-		"INT_SS_ERROR \t%8u\n" "INT_S0IX_MISS\t%8u\n"
-		"INT_NO_ACKC6 \t%8u\n" "INT_INVALID  \t%8u\n",
-		pmu_irq_stats[INT_SPURIOUS], pmu_irq_stats[INT_CMD_DONE],
-		pmu_irq_stats[INT_CMD_ERR], pmu_irq_stats[INT_WAKE_RX],
-		pmu_irq_stats[INT_SS_ERROR], pmu_irq_stats[INT_S0IX_MISS],
-		pmu_irq_stats[INT_NO_ACKC6], pmu_irq_stats[INT_INVALID]);
-
-	seq_printf(s, "mrst_pmu_wait_ready_calls          %8d\n",
-			pmu_wait_ready_calls);
-	seq_printf(s, "mrst_pmu_wait_ready_udelays        %8d\n",
-			pmu_wait_ready_udelays);
-	seq_printf(s, "mrst_pmu_wait_ready_udelays_max    %8d\n",
-			pmu_wait_ready_udelays_max);
-	seq_printf(s, "mrst_pmu_wait_done_calls           %8d\n",
-			pmu_wait_done_calls);
-	seq_printf(s, "mrst_pmu_wait_done_udelays         %8d\n",
-			pmu_wait_done_udelays);
-	seq_printf(s, "mrst_pmu_wait_done_udelays_max     %8d\n",
-			pmu_wait_done_udelays_max);
-	seq_printf(s, "mrst_pmu_set_power_state_entry     %8d\n",
-			pmu_set_power_state_entry);
-	seq_printf(s, "mrst_pmu_set_power_state_send_cmd  %8d\n",
-			pmu_set_power_state_send_cmd);
-	seq_printf(s, "SCU busy: %d\n", pmu_read_busy_status());
-
-	return 0;
-}
-
-static int debug_mrst_pmu_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, debug_mrst_pmu_show, NULL);
-}
-
-static const struct file_operations devices_state_operations = {
-	.open		= debug_mrst_pmu_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-#endif	/* DEBUG_FS */
-
-/*
- * Validate SCU PCI shim PCI vendor capability byte
- * against LSS hard-coded in mrst_devs[] above.
- * DEBUG only.
- */
-static void pmu_scu_firmware_debug(void)
-{
-	struct pci_dev *pdev = NULL;
-
-	for_each_pci_dev(pdev) {
-		struct mrst_device *mrst_dev;
-		u8 pci_config_lss;
-		int pos;
-
-		mrst_dev = pci_id_2_mrst_dev(pdev->device);
-		if (unlikely(!mrst_dev)) {
-			printk(KERN_ERR FW_BUG "pmu: Unknown "
-				"PCI device 0x%04X\n", pdev->device);
-			continue;
-		}
-
-		if (mrst_dev->lss == 0)
-			continue;	 /* no LSS in our table */
-
-		pos = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
-		if (!pos != 0) {
-			printk(KERN_ERR FW_BUG "pmu: 0x%04X "
-				"missing PCI Vendor Capability\n",
-				pdev->device);
-			continue;
-		}
-		pci_read_config_byte(pdev, pos + 4, &pci_config_lss);
-		if (!(pci_config_lss & PCI_VENDOR_CAP_LOG_SS_MASK)) {
-			printk(KERN_ERR FW_BUG "pmu: 0x%04X "
-				"invalid PCI Vendor Capability 0x%x "
-				" expected LSS 0x%X\n",
-				pdev->device, pci_config_lss, mrst_dev->lss);
-			continue;
-		}
-		pci_config_lss &= PCI_VENDOR_CAP_LOG_ID_MASK;
-
-		if (mrst_dev->lss == pci_config_lss)
-			continue;
-
-		printk(KERN_ERR FW_BUG "pmu: 0x%04X LSS = %d, expected %d\n",
-			pdev->device, pci_config_lss, mrst_dev->lss);
-	}
-}
-
-/**
- * pmu_probe
- */
-static int __devinit pmu_probe(struct pci_dev *pdev,
-				   const struct pci_device_id *pci_id)
-{
-	int ret;
-	struct mrst_pmu_reg *pmu;
-
-	/* Init the device */
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "Unable to Enable PCI device\n");
-		return ret;
-	}
-
-	ret = pci_request_regions(pdev, MRST_PMU_DRV_NAME);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
-		goto out_err1;
-	}
-
-	/* Map the memory of PMU reg base */
-	pmu = pci_iomap(pdev, 0, 0);
-	if (!pmu) {
-		dev_err(&pdev->dev, "Unable to map the PMU address space\n");
-		ret = -ENOMEM;
-		goto out_err2;
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	/* /sys/kernel/debug/mrst_pmu */
-	(void) debugfs_create_file("mrst_pmu", S_IFREG | S_IRUGO,
-				NULL, NULL, &devices_state_operations);
-#endif
-	pmu_reg = pmu;	/* success */
-
-	if (request_irq(pdev->irq, pmu_irq, 0, MRST_PMU_DRV_NAME, NULL)) {
-		dev_err(&pdev->dev, "Registering isr has failed\n");
-		ret = -1;
-		goto out_err3;
-	}
-
-	pmu_scu_firmware_debug();
-
-	pmu_write_wkc(S0I3_WAKE_SOURCES);	/* Enable S0i3 wakeup sources */
-
-	pmu_wait_ready();
-
-	pmu_write_ssc(D0I1_ACG_SSS_TARGET);	/* Enable Auto-Clock_Gating */
-	pmu_write_cmd(0x201);
-
-	spin_lock_init(&mrst_pmu_power_state_lock);
-
-	/* Enable the hardware interrupt */
-	pmu_irq_enable();
-	return 0;
-
-out_err3:
-	free_irq(pdev->irq, NULL);
-	pci_iounmap(pdev, pmu_reg);
-	pmu_reg = NULL;
-out_err2:
-	pci_release_region(pdev, 0);
-out_err1:
-	pci_disable_device(pdev);
-	return ret;
-}
-
-static void __devexit pmu_remove(struct pci_dev *pdev)
-{
-	dev_err(&pdev->dev, "Mid PM pmu_remove called\n");
-
-	/* Freeing up the irq */
-	free_irq(pdev->irq, NULL);
-
-	pci_iounmap(pdev, pmu_reg);
-	pmu_reg = NULL;
-
-	/* disable the current PCI device */
-	pci_release_region(pdev, 0);
-	pci_disable_device(pdev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(pmu_pci_ids) = {
-	{ PCI_VDEVICE(INTEL, PCI_DEV_ID_MRST_PMU), 0 },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, pmu_pci_ids);
-
-static struct pci_driver driver = {
-	.name = MRST_PMU_DRV_NAME,
-	.id_table = pmu_pci_ids,
-	.probe = pmu_probe,
-	.remove = __devexit_p(pmu_remove),
-};
-
-/**
- * pmu_pci_register - register the PMU driver as PCI device
- */
-static int __init pmu_pci_register(void)
-{
-	return pci_register_driver(&driver);
-}
-
-/* Register and probe via fs_initcall() to preceed device_initcall() */
-fs_initcall(pmu_pci_register);
-
-static void __exit mid_pci_cleanup(void)
-{
-	pci_unregister_driver(&driver);
-}
-
-static int ia_major;
-static int ia_minor;
-
-static int pmu_sfi_parse_oem(struct sfi_table_header *table)
-{
-	struct sfi_table_simple *sb;
-
-	sb = (struct sfi_table_simple *)table;
-	ia_major = (sb->pentry[1] >> 0) & 0xFFFF;
-	ia_minor = (sb->pentry[1] >> 16) & 0xFFFF;
-	printk(KERN_INFO "mrst_pmu: IA FW version v%x.%x\n",
-		ia_major, ia_minor);
-
-	return 0;
-}
-
-static int __init scu_fw_check(void)
-{
-	int ret;
-	u32 fw_version;
-
-	if (!pmu_reg)
-		return 0;	/* this driver didn't probe-out */
-
-	sfi_table_parse("OEMB", NULL, NULL, pmu_sfi_parse_oem);
-
-	if (ia_major < 0x6005 || ia_minor < 0x1525) {
-		WARN(1, "mrst_pmu: IA FW version too old\n");
-		return -1;
-	}
-
-	ret = intel_scu_ipc_command(IPCMSG_FW_REVISION, 0, NULL, 0,
-					&fw_version, 1);
-
-	if (ret) {
-		WARN(1, "mrst_pmu: IPC FW version? %d\n", ret);
-	} else {
-		int scu_major = (fw_version >> 8) & 0xFF;
-		int scu_minor = (fw_version >> 0) & 0xFF;
-
-		printk(KERN_INFO "mrst_pmu: firmware v%x\n", fw_version);
-
-		if ((scu_major >= 0xC0) && (scu_minor >= 0x49)) {
-			printk(KERN_INFO "mrst_pmu: enabling S0i3\n");
-			mrst_pmu_s0i3_enable = true;
-		} else {
-			WARN(1, "mrst_pmu: S0i3 disabled, old firmware %X.%X",
-					scu_major, scu_minor);
-		}
-	}
-	return 0;
-}
-late_initcall(scu_fw_check);
-module_exit(mid_pci_cleanup);
diff --git a/arch/x86/platform/mrst/pmu.h b/arch/x86/platform/mrst/pmu.h
deleted file mode 100644
index bfbfe64..0000000
--- a/arch/x86/platform/mrst/pmu.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * mrst/pmu.h - private definitions for MRST Power Management Unit mrst/pmu.c
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef _MRST_PMU_H_
-#define _MRST_PMU_H_
-
-#define PCI_DEV_ID_MRST_PMU		0x0810
-#define MRST_PMU_DRV_NAME		"mrst_pmu"
-#define	PCI_SUB_CLASS_MASK		0xFF00
-
-#define	PCI_VENDOR_CAP_LOG_ID_MASK	0x7F
-#define PCI_VENDOR_CAP_LOG_SS_MASK	0x80
-
-#define SUB_SYS_ALL_D0I1	0x01155555
-#define S0I3_WAKE_SOURCES	0x00001FFF
-
-#define PM_S0I3_COMMAND					\
-	((0 << 31) |	/* Reserved */			\
-	(0 << 30) |	/* Core must be idle */		\
-	(0xc2 << 22) |	/* ACK C6 trigger */		\
-	(3 << 19) |	/* Trigger on DMI message */	\
-	(3 << 16) |	/* Enter S0i3 */		\
-	(0 << 13) |	/* Numeric mode ID (sw) */	\
-	(3 << 9) |	/* Trigger mode */		\
-	(0 << 8) |	/* Do not interrupt */		\
-	(1 << 0))	/* Set configuration */
-
-#define	LSS_DMI		0
-#define	LSS_SD_HC0	1
-#define	LSS_SD_HC1	2
-#define	LSS_NAND	3
-#define	LSS_IMAGING	4
-#define	LSS_SECURITY	5
-#define	LSS_DISPLAY	6
-#define	LSS_USB_HC	7
-#define	LSS_USB_OTG	8
-#define	LSS_AUDIO	9
-#define	LSS_AUDIO_LPE	9
-#define	LSS_AUDIO_SSP	9
-#define	LSS_I2C0	10
-#define	LSS_I2C1	10
-#define	LSS_I2C2	10
-#define	LSS_KBD		10
-#define	LSS_SPI0	10
-#define	LSS_SPI1	10
-#define	LSS_SPI2	10
-#define	LSS_GPIO	10
-#define	LSS_SRAM	11	/* used by SCU, do not touch */
-#define	LSS_SD_HC2	12
-/* LSS hardware bits 15,14,13 are hardwired to 0, thus unusable */
-#define MRST_NUM_LSS	13
-
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
-#define	SSMSK(mask, lss) ((mask) << ((lss) * 2))
-#define	D0	0
-#define	D0i1	1
-#define	D0i2	2
-#define	D0i3	3
-
-#define S0I3_SSS_TARGET	(		\
-	SSMSK(D0i1, LSS_DMI) |		\
-	SSMSK(D0i3, LSS_SD_HC0) |	\
-	SSMSK(D0i3, LSS_SD_HC1) |	\
-	SSMSK(D0i3, LSS_NAND) |		\
-	SSMSK(D0i3, LSS_SD_HC2) |	\
-	SSMSK(D0i3, LSS_IMAGING) |	\
-	SSMSK(D0i3, LSS_SECURITY) |	\
-	SSMSK(D0i3, LSS_DISPLAY) |	\
-	SSMSK(D0i3, LSS_USB_HC) |	\
-	SSMSK(D0i3, LSS_USB_OTG) |	\
-	SSMSK(D0i3, LSS_AUDIO) |	\
-	SSMSK(D0i1, LSS_I2C0))
-
-/*
- * D0i1 on Langwell is Autonomous Clock Gating (ACG).
- * Enable ACG on every LSS except camera and audio
- */
-#define D0I1_ACG_SSS_TARGET	 \
-	(SUB_SYS_ALL_D0I1 & ~SSMSK(D0i1, LSS_IMAGING) & ~SSMSK(D0i1, LSS_AUDIO))
-
-enum cm_mode {
-	CM_NOP,			/* ignore the config mode value */
-	CM_IMMEDIATE,
-	CM_DELAY,
-	CM_TRIGGER,
-	CM_INVALID
-};
-
-enum sys_state {
-	SYS_STATE_S0I0,
-	SYS_STATE_S0I1,
-	SYS_STATE_S0I2,
-	SYS_STATE_S0I3,
-	SYS_STATE_S3,
-	SYS_STATE_S5
-};
-
-#define SET_CFG_CMD	1
-
-enum int_status {
-	INT_SPURIOUS = 0,
-	INT_CMD_DONE = 1,
-	INT_CMD_ERR = 2,
-	INT_WAKE_RX = 3,
-	INT_SS_ERROR = 4,
-	INT_S0IX_MISS = 5,
-	INT_NO_ACKC6 = 6,
-	INT_INVALID = 7,
-};
-
-/* PMU register interface */
-static struct mrst_pmu_reg {
-	u32 pm_sts;		/* 0x00 */
-	u32 pm_cmd;		/* 0x04 */
-	u32 pm_ics;		/* 0x08 */
-	u32 _resv1;		/* 0x0C */
-	u32 pm_wkc[2];		/* 0x10 */
-	u32 pm_wks[2];		/* 0x18 */
-	u32 pm_ssc[4];		/* 0x20 */
-	u32 pm_sss[4];		/* 0x30 */
-	u32 pm_wssc[4];		/* 0x40 */
-	u32 pm_c3c4;		/* 0x50 */
-	u32 pm_c5c6;		/* 0x54 */
-	u32 pm_msi_disable;	/* 0x58 */
-} *pmu_reg;
-
-static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); }
-static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); }
-static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); }
-static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); }
-
-static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); }
-static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); }
-static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); }
-static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); }
-static inline void pmu_write_wssc(u32 arg)
-					{ writel(arg, &pmu_reg->pm_wssc[0]); }
-
-static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); }
-static inline u32 pmu_msi_is_disabled(void)
-				{ return readl(&pmu_reg->pm_msi_disable); }
-
-union pmu_pm_ics {
-	struct {
-		u32 cause:8;
-		u32 enable:1;
-		u32 pending:1;
-		u32 reserved:22;
-	} bits;
-	u32 value;
-};
-
-static inline void pmu_irq_enable(void)
-{
-	union pmu_pm_ics pmu_ics;
-
-	pmu_ics.value = pmu_read_ics();
-	pmu_ics.bits.enable = 1;
-	pmu_write_ics(pmu_ics.value);
-}
-
-union pmu_pm_status {
-	struct {
-		u32 pmu_rev:8;
-		u32 pmu_busy:1;
-		u32 mode_id:4;
-		u32 Reserved:19;
-	} pmu_status_parts;
-	u32 pmu_status_value;
-};
-
-static inline int pmu_read_busy_status(void)
-{
-	union pmu_pm_status result;
-
-	result.pmu_status_value = pmu_read_sts();
-
-	return result.pmu_status_parts.pmu_busy;
-}
-
-/* pmu set config parameters */
-struct cfg_delay_param_t {
-	u32 cmd:8;
-	u32 ioc:1;
-	u32 cfg_mode:4;
-	u32 mode_id:3;
-	u32 sys_state:3;
-	u32 cfg_delay:8;
-	u32 rsvd:5;
-};
-
-struct cfg_trig_param_t {
-	u32 cmd:8;
-	u32 ioc:1;
-	u32 cfg_mode:4;
-	u32 mode_id:3;
-	u32 sys_state:3;
-	u32 cfg_trig_type:3;
-	u32 cfg_trig_val:8;
-	u32 cmbi:1;
-	u32 rsvd1:1;
-};
-
-union pmu_pm_set_cfg_cmd_t {
-	union {
-		struct cfg_delay_param_t d_param;
-		struct cfg_trig_param_t t_param;
-	} pmu2_params;
-	u32 pmu_pm_set_cfg_cmd_value;
-};
-
-#ifdef FUTURE_PATCH
-extern int mrst_s0i3_entry(u32 regval, u32 *regaddr);
-#else
-static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; }
-#endif
-#endif
-- 
1.7.10.rc4

^ permalink raw reply related

* [RFC] Runtime PM for host controllers
From: Kevin Cernekee @ 2012-04-08 22:08 UTC (permalink / raw)
  To: Rafael J. Wysocki, Alan Stern, linux-pm

In embedded applications, there are a number of situations in which it
is useful to completely disable a host controller in order to conserve
power.  Some typical scenarios include:

1) A SATA controller is present, but there are no disks attached.
Clock-gating the SATA PHY saves a great deal of power, with the
tradeoff that the controller will no longer be able to detect
hotplugging on the (e)SATA connector.  The user/application is willing
to forego the possibility that a disk will be hotplugged, in order to
realize the power savings.

2) Similar to #1, except there IS a disk attached.  Maybe even
mounted.  But the user/application knows that it will not need to
access the disk any time soon, so it would like to put that part of
the system to sleep.

One such case occurs on PVRs: the user presses the "power off" button
to put the PVR into a non-interactive standby mode.  The TV screen
goes black, yet the OS needs to be kept running for various reasons:
program guide downloads, network bridging/routing, general
housekeeping, etc.  But the HDD can be safely spun down, and the SATA
interface can be put into power save mode until such time that it is
needed again.

It is possible that the various Linux-based NAS devices may also want
to implement this sort of feature, to conserve power after several
hours/days of inactivity.  For many home users, it might make sense
for a NAS appliance to enter a low power state during periods of
limited usage (nighttime), but remain active on the LAN (replying to
ARPs and sending NetBIOS advertisements) so that new requests could be
serviced with a few seconds' notice.

For both NAS and PVR, the root filesystem is typically on flash, not on the HDD.

PVRs in particular are subject to increasingly strict Energy Star /
European CoC rules, so saving even a few hundred milliwatts in standby
mode is critical.

3) Cases #1 and #2, applied to other hotpluggable interfaces like USB,
MMC/SD, or (less commonly) PCIe.

The USB scenario could include situations where the USB *HCI host
controllers can be safely disabled because the physical interface has
been switched to USB device (gadget/OTG) mode.  Or disabled through a
configuration menu to conserve power - especially on a mobile phone.

It could also occur in the case of NAS devices that use external USB
drives instead of SATA drives.

4) A network interface is present, but the user/application knows that
networking will not be needed in the host's current state.  So it can
run "ifconfig eth0 down" and then put the controller and PHY into a
low-power state.


FWIW, these "extra" power save features are usually implemented in
proprietary ways by each SoC manufacturer.  They are not always part
of the general AHCI/EHCI/SDHCI/... specification.  In some cases the
official specification does provide for certain power save modes, but
more extensive savings can be achieved by clock-gating or power-gating
the entire hardware block.  It is probably best to assume they will
always need to be handled by the clk_* functions, or something
similar.


Looking through Linus' head of tree, I see:

USB runtime PM seems to focus on the individual USB devices, and does
not allow for dynamically suspending the entire host controller
AFAICT.

USB used to allow writing "suspend" to the power/control file, but
that no longer seems to be the case as of 2.6.32.  In general I don't
see any facility where the application can explicitly tell the PM core
to suspend a device (incurring a potential loss of functionality, such
as hot plug/unplug detection).

libata has some limited support for runtime PM on a per-port basis,
but on my ahci_platform controller, both ports show up as "active" and
do not seem to want to autosuspend.  One has a HDD attached; the other
is unconnected.  I do not see a way to tell libata to suspend the
whole controller, or even freeze a single port, from userland.

MMC/SD seems to be in better shape with respect to "opportunistically"
suspending the controller if it is idle for 50ms, except the design
still assumes that the hardware is able to detect card
insertion/removal through some other mechanism.  From commit
66fd8ad51:

"For Medfield, the host controller's card detect mechanism is
supplanted by an always-on GPIO which provides for card detect
wake-up."

This is not feasible on all systems, so for systems that lack this
"side channel," it would be necessary to provide a way for userland to
indicate whether it is really OK to suspend the controller and
potentially lose the ability to detect card plug/unplug events.

Several ethernet drivers (such as e1000e) allow autosuspend via
runtime PM if the interface is down.  This is probably about the best
we could hope for on a network adapter.  Although it may be worth
thinking about what to do for cases like ethtool ioctls, which could
cause problems if they result in register accesses to a clock-gated
device.  Is it better to let each driver handle the problem in its own
way, or should the net/core/ code be made aware of runtime PM?


So, my questions are:

a) Is SATA/USB/MMC host controller suspension something that can be
accomplished within the existing runtime PM framework?

b) If not, what is the best way to modify the runtime PM framework so
that it can support these use cases?

c) Is this something you would even want in mainline?

d) Or should I just go back to using "rmmod"?


Thanks in advance for your input.

^ permalink raw reply

* RE: [PATCH V2]mmc: remove MMC bus legacy suspend/resume method
From: Hebbar, Gururaja @ 2012-04-09  5:22 UTC (permalink / raw)
  To: Chuanxiao Dong, linux-mmc@vger.kernel.org,
	linux-pm@lists.linux-foundation.org
  Cc: rjw@sisk.pl
In-Reply-To: <20120405075118.GA29395@intel.com>

On Thu, Apr 05, 2012 at 13:21:18, Chuanxiao Dong wrote:
> MMC bus is using legacy suspend/resume method, which is not compatible if
> runtime pm callbacks are used. In this scenario, MMC bus suspend/resume
> callbacks cannot be called when system entering S3. So change to use the new
> defined dev_pm_ops for system sleeping mode
> 
> Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
> ---
> Changes in v2:
> 	use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
> 	suggested
> 
>  drivers/mmc/card/block.c |    2 +-
>  drivers/mmc/core/bus.c   |   26 ++++++++++++--------------
>  include/linux/mmc/card.h |    2 +-
>  3 files changed, 14 insertions(+), 16 deletions(-)
> 

Tested on AM335x Platform. Solves major issue/crash reported at 
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg65425.html

Tested-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>

..snip..


Regards, 
Gururaja

^ permalink raw reply

* Re: [PATCHv2 5/5] cpuidle: coupled: add trace events
From: Santosh Shilimkar @ 2012-04-09  6:59 UTC (permalink / raw)
  To: Colin Cross
  Cc: Kevin Hilman, Len Brown, Kay Sievers, Greg Kroah-Hartman,
	linux-kernel, Amit Kucheria, linux-pm, Arjan van de Ven,
	linux-arm-kernel
In-Reply-To: <1331749794-8056-6-git-send-email-ccross@android.com>

On Wednesday 14 March 2012 11:59 PM, Colin Cross wrote:
> Adds trace events to allow debugging of coupled cpuidle.
> Can be used to verify cpuidle performance, including time spent
> spinning and time spent in safe states.  Not intended for merging.
> 
> Signed-off-by: Colin Cross <ccross@android.com>
> ---
I found the trace events quite useful for debug and also to monitor
the cpuidle performance.

I guess we should add these trace events to the core code unless
and until there is a strong reason not to do so.

Regards
Santosh

^ permalink raw reply

* Re: [PATCHv2 0/5] coupled cpuidle state support
From: Santosh Shilimkar @ 2012-04-09  7:11 UTC (permalink / raw)
  To: Colin Cross
  Cc: Kevin Hilman, Len Brown, Kay Sievers, Greg Kroah-Hartman,
	linux-kernel, Amit Kucheria, linux-pm, Arjan van de Ven, Rob Lee,
	linux-arm-kernel
In-Reply-To: <4F75ACCA.4090009@ti.com>

On Friday 30 March 2012 06:23 PM, Santosh Shilimkar wrote:
> Colin,
> 
> On Friday 16 March 2012 05:07 AM, Colin Cross wrote:
>> On Wed, Mar 14, 2012 at 11:29 AM, Colin Cross <ccross@android.com> wrote:
> 
> [...]
> 
>>>
>>> v2:
>>>   * removed the coupled lock, replacing it with atomic counters
>>>   * added a check for outstanding pokes before beginning the
>>>     final transition to avoid extra wakeups
>>>   * made the cpuidle_coupled struct completely private
>>>   * fixed kerneldoc comment formatting
>>>   * added a patch with a helper function for resynchronizing
>>>     cpus after aborting idle
>>>   * added a patch (not for merging) to add trace events for
>>>     verification and performance testing
>>
>> I forgot to mention, this patch series is on v3.3-rc7, and will
>> conflict with the cpuidle timekeeping patches.  If those go in first
>> (which is likely), I will rework this series on top of it.  I left it
>> on v3.3-rc7 now to make testing easier.
> 
> I have re-based your series against Len Browns
> next branch [1] which has time keeping and other cpuidle patches.
> Have also folded the CPU hotplug fix which I posted in the
> original coupled idle patch.
> 
As you know, we have been playing around this series for OMAP
for last few weeks. This version series seems to work as intended
and found it pretty stable in my testing. Apart from the cpu
hotplug fix and the trace event comment, series looks fine
to me.

FWIW,
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>	

An updated version of this series along with OMAP cpuidle
driver updates against 3.4-rc2 is available here [1] in
case some body is interested looking at it.

Regards
Santosh

[1] git://gitorious.org/omap-sw-develoment/linux-omap-dev.git
for_3.5/coupled_cpuidle-rebase

^ permalink raw reply

* Re: [RFC] Runtime PM for host controllers
From: Alan Stern @ 2012-04-09 14:14 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: linux-pm
In-Reply-To: <CAJiQ=7D8QbV45euE1VN0ENpCMUESMMgeUr6gKwK3g+8-PUyTcQ@mail.gmail.com>

On Sun, 8 Apr 2012, Kevin Cernekee wrote:

> In embedded applications, there are a number of situations in which it
> is useful to completely disable a host controller in order to conserve
> power.  Some typical scenarios include:

<SNIP>

> Looking through Linus' head of tree, I see:
> 
> USB runtime PM seems to focus on the individual USB devices, and does
> not allow for dynamically suspending the entire host controller
> AFAICT.

That is not correct.  USB host controllers _can_ be suspended.  (Not 
all of them; many of the platform drivers don't implement controller 
suspend.  But some of them do, and almost all of the PCI-based drivers 
do.)

> USB used to allow writing "suspend" to the power/control file, but
> that no longer seems to be the case as of 2.6.32.

Correct.

>  In general I don't
> see any facility where the application can explicitly tell the PM core
> to suspend a device (incurring a potential loss of functionality, such
> as hot plug/unplug detection).

Right; there is no way to do this.  The OS will suspend a device only 
when it believes it is safe to do so.

<SNIP>

> So, my questions are:
> 
> a) Is SATA/USB/MMC host controller suspension something that can be
> accomplished within the existing runtime PM framework?

Not only _can_ it be accomplished, it already _has_ been accomplished 
(for USB at least, I'm not familiar with the others).

> b) If not, what is the best way to modify the runtime PM framework so
> that it can support these use cases?

No changes to the framework are needed.  If a subsystem or driver
doesn't support runtime suspend then support has to be added at the 
subsystem or driver level.

> c) Is this something you would even want in mainline?

Yes.  People are already working on this stuff.

> d) Or should I just go back to using "rmmod"?

I don't see how rmmod will save any power.

Alan Stern

^ permalink raw reply

* Re: [PATCH V2]mmc: remove MMC bus legacy suspend/resume method
From: Linus Walleij @ 2012-04-09 21:07 UTC (permalink / raw)
  To: Chuanxiao Dong; +Cc: linux-mmc, linux-pm, rjw
In-Reply-To: <20120405075118.GA29395@intel.com>

On Thu, Apr 5, 2012 at 9:51 AM, Chuanxiao Dong <chuanxiao.dong@intel.com> wrote:

> MMC bus is using legacy suspend/resume method, which is not compatible if
> runtime pm callbacks are used. In this scenario, MMC bus suspend/resume
> callbacks cannot be called when system entering S3. So change to use the new
> defined dev_pm_ops for system sleeping mode
>
> Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
> ---
> Changes in v2:
>        use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
>        suggested

This looks so much more sane.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* Re: [RFC] Runtime PM for host controllers
From: Kevin Cernekee @ 2012-04-09 21:14 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-pm
In-Reply-To: <Pine.LNX.4.44L0.1204091007350.1429-100000@iolanthe.rowland.org>

On Mon, Apr 9, 2012 at 7:14 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> USB runtime PM seems to focus on the individual USB devices, and does
>> not allow for dynamically suspending the entire host controller
>> AFAICT.
>
> That is not correct.  USB host controllers _can_ be suspended.  (Not
> all of them; many of the platform drivers don't implement controller
> suspend.  But some of them do, and almost all of the PCI-based drivers
> do.)

I am not clear on what is actually happening at the chip level in these cases?

i.e. is the entire USB core getting clock gated or power gated, such
that it is completely non-responsive to register accesses or device
hotplug?  Or is the driver just shutting down a few tiny pieces of the
hardware?

Is there a way to initiate USB runtime suspend on the host controller
even if there are devices plugged into the downstream ports?

>>  In general I don't
>> see any facility where the application can explicitly tell the PM core
>> to suspend a device (incurring a potential loss of functionality, such
>> as hot plug/unplug detection).
>
> Right; there is no way to do this.  The OS will suspend a device only
> when it believes it is safe to do so.

Assuming that somebody is able to come up with a satisfactory
implementation, are you open to allowing a "user-initiated suspend"
mode, in addition to "opportunistic suspend"?

>> d) Or should I just go back to using "rmmod"?
>
> I don't see how rmmod will save any power.

rmmod allows me to forcibly shut down the controller, cleanly (in
theory) disconnecting any active devices and preventing the kernel
from touching the registers.

After rmmod, I can then tell the SoC to put the whole core into an
unresponsive, low power state.

This is not a very clean way of doing things, so I would prefer to use
runtime PM if at all possible.  But I don't think my hardware is
designed in a way that is compatible with "opportunistic suspend."


Thanks.

^ permalink raw reply

* Re: [linux-pm] [PATCHv2 0/5] coupled cpuidle state support
From: Kevin Hilman @ 2012-04-09 23:35 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Len Brown, Greg Kroah-Hartman, Kay Sievers, linux-kernel,
	Amit Kucheria, Colin Cross, linux-pm, Arjan van de Ven, Rob Lee,
	linux-arm-kernel
In-Reply-To: <4F828BAB.5010302@ti.com>

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Friday 30 March 2012 06:23 PM, Santosh Shilimkar wrote:
>> Colin,
>> 
>> On Friday 16 March 2012 05:07 AM, Colin Cross wrote:
>>> On Wed, Mar 14, 2012 at 11:29 AM, Colin Cross <ccross@android.com> wrote:
>> 
>> [...]
>> 
>>>>
>>>> v2:
>>>>   * removed the coupled lock, replacing it with atomic counters
>>>>   * added a check for outstanding pokes before beginning the
>>>>     final transition to avoid extra wakeups
>>>>   * made the cpuidle_coupled struct completely private
>>>>   * fixed kerneldoc comment formatting
>>>>   * added a patch with a helper function for resynchronizing
>>>>     cpus after aborting idle
>>>>   * added a patch (not for merging) to add trace events for
>>>>     verification and performance testing
>>>
>>> I forgot to mention, this patch series is on v3.3-rc7, and will
>>> conflict with the cpuidle timekeeping patches.  If those go in first
>>> (which is likely), I will rework this series on top of it.  I left it
>>> on v3.3-rc7 now to make testing easier.
>> 
>> I have re-based your series against Len Browns
>> next branch [1] which has time keeping and other cpuidle patches.
>> Have also folded the CPU hotplug fix which I posted in the
>> original coupled idle patch.
>> 
> As you know, we have been playing around this series for OMAP
> for last few weeks. This version series seems to work as intended
> and found it pretty stable in my testing. Apart from the cpu
> hotplug fix and the trace event comment, series looks fine
> to me.
>
> FWIW,
> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>	

Also

Reviewed-by: Kevin Hilman <khilman@ti.com>
Tested-by: Kevin Hilman <khilman@ti.com>

as I've been working with Santosh on getting this stabilized on OMAP and
we are very keen to see this functionality merged.

Thanks,

Kevin

^ permalink raw reply

* Re: [PATCH V2 0/6] thermal: exynos: Add kernel thermal support for exynos platform
From: Zhang Rui @ 2012-04-10  0:58 UTC (permalink / raw)
  To: Amit Kachhap
  Cc: linux-samsung-soc, linaro-dev, patches, linux-kernel, lm-sensors,
	linux-acpi, linux-pm
In-Reply-To: <CAK44p23jiXn6mn-VsdXr3h9J5FfKztXMiqu=XjaF6nqLnRQAmA@mail.gmail.com>

Hi, Amit,

On 三, 2012-04-04 at 10:02 +0530, Amit Kachhap wrote:
> Hi Len/Rui,
> 
> Any comment or feedback from your side about the status of this patch?
> Is it merge-able or major re-work is needed? I have fixed most of the
> comments in this patchset and currently working on some of the minor
> comments received and will submit them shortly.
> 
Sorry for the late response.

First of all, it makes sense to me to introduce the generic cpufrq
cooling implementation.
But I still have some questions.
I think the key reason why THERMAL_TRIP_STATE_INSTANCE is introduced is
that the MONIROR_ZONE and WARN_ZONE on exynos4 can not fit into the
current passive handling in the generic thermal layer well, right?
e.g. there is no tc1/tc2 on exynos4.

If yes, is it possible that we can enhance the passive cooling to
support the generic processor cooling?
say, introduce another way to throttle the processor in
thermal_zone_device_passive when tc1 and tc2 are not available?

thanks,
rui

> Regards,
> Amit Daniel
> 
> On 19 March 2012 11:47, Amit Daniel Kachhap <amit.kachhap@linaro.org> wrote:
> > Changes since V1:
> > *Moved the sensor driver to driver/thermal folder from driver/hwmon folder
> >  as suggested by Mark Brown and Guenter Roeck
> > *Added notifier support to notify the registered drivers of any cpu cooling
> >  action. The driver can modify the default cooling behaviour(eg set different
> >  max clip frequency).
> > *The percentage based frequency replaced with absolute clipped frequency.
> > *Some more conditional checks when setting max frequency.
> > *Renamed the new trip type THERMAL_TRIP_STATE_ACTIVE to
> >  THERMAL_TRIP_STATE_INSTANCE
> > *Many review comments from R, Durgadoss <durgadoss.r@intel.com> and
> >  eduardo.valentin@ti.com implemented.
> > *Removed cooling stats through debugfs patch
> > *The V1 based can be found here,
> >  https://lkml.org/lkml/2012/2/22/123
> >  http://lkml.org/lkml/2012/3/3/32
> >
> > Changes since RFC:
> > *Changed the cpu cooling registration/unregistration API's to instance based
> > *Changed the STATE_ACTIVE trip type to pass correct instance id
> > *Adding support to restore back the policy->max_freq after doing frequency
> >  clipping.
> > *Moved the trip cooling stats from sysfs node to debugfs node as suggested
> >  by Greg KH greg@kroah.com
> > *Incorporated several review comments from eduardo.valentin@ti.com
> > *Moved the Temperature sensor driver from driver/hwmon/ to driver/mfd
> >  as discussed with Guenter Roeck <guenter.roeck@ericsson.com> and
> >  Donggeun Kim <dg77.kim@samsung.com> (https://lkml.org/lkml/2012/1/5/7)
> > *Some changes according to the changes in common cpu cooling APIs
> > *The RFC based patches can be found here,
> >  https://lkml.org/lkml/2011/12/13/186
> >  https://lkml.org/lkml/2011/12/21/169
> >
> >
> > Brief Description:
> >
> > 1) The generic cooling devices code is placed inside driver/thermal/* as
> > placing inside acpi folder will need un-necessary enabling of acpi code. This
> > codes is architecture independent.
> >
> > 2) This patchset adds a new trip type THERMAL_TRIP_STATE_INSTANCE which passes
> > cooling device instance number and may be helpful for cpufreq cooling devices
> > to take the correct cooling action. This trip type avoids the temperature
> > comparision check again inside the cooling handler.
> >
> > 3) This patchset adds generic cpu cooling low level implementation through
> > frequency clipping and cpu hotplug. In future, other cpu related cooling
> > devices may be added here. An ACPI version of this already exists
> > (drivers/acpi/processor_thermal.c). But this will be useful for platforms
> > like ARM using the generic thermal interface along with the generic cpu
> > cooling devices. The cooling device registration API's return cooling device
> > pointers which can be easily binded with the thermal zone trip points.
> > The important APIs exposed are,
> >   a)struct thermal_cooling_device *cpufreq_cooling_register(
> >        struct freq_clip_table *tab_ptr, unsigned int tab_size,
> >        const struct cpumask *mask_val)
> >   b)void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
> >
> > 4) Samsung exynos platform thermal implementation is done using the generic
> > cpu cooling APIs and the new trip type. The temperature sensor driver present
> > in the hwmon folder(registered as hwmon driver) is moved to thermal folder
> > and registered as a thermal driver.
> >
> > All this patchset is based on Kernel version 3.3-rc7
> >
> > A simple data/control flow diagrams is shown below,
> >
> > Core Linux thermal <----->  Exynos thermal interface <----- Temperature Sensor
> >          |                             |
> >         \|/                            |
> >  Cpufreq cooling device <---------------
> >
> >
> > Amit Daniel Kachhap (6):
> >  thermal: Add a new trip type to use cooling device instance number
> >  thermal: Add generic cpufreq cooling implementation
> >  thermal: Add generic cpuhotplug cooling implementation
> >  hwmon: exynos4: Move thermal sensor driver to driver/thermal
> >    directory
> >  thermal: exynos4: Register the tmu sensor with the kernel thermal
> >    layer
> >  ARM: exynos4: Add thermal sensor driver platform device support
> >
> >  Documentation/hwmon/exynos4_tmu           |   81 ---
> >  Documentation/thermal/cpu-cooling-api.txt |   76 +++
> >  Documentation/thermal/exynos4_tmu         |   52 ++
> >  Documentation/thermal/sysfs-api.txt       |    4 +-
> >  arch/arm/mach-exynos/Kconfig              |   11 +
> >  arch/arm/mach-exynos/Makefile             |    1 +
> >  arch/arm/mach-exynos/clock.c              |    4 +
> >  arch/arm/mach-exynos/dev-tmu.c            |   39 ++
> >  arch/arm/mach-exynos/include/mach/irqs.h  |    2 +
> >  arch/arm/mach-exynos/include/mach/map.h   |    1 +
> >  arch/arm/mach-exynos/mach-origen.c        |    1 +
> >  arch/arm/plat-samsung/include/plat/devs.h |    1 +
> >  drivers/hwmon/Kconfig                     |   10 -
> >  drivers/hwmon/Makefile                    |    1 -
> >  drivers/hwmon/exynos4_tmu.c               |  514 -------------------
> >  drivers/thermal/Kconfig                   |   21 +
> >  drivers/thermal/Makefile                  |    2 +
> >  drivers/thermal/cpu_cooling.c             |  529 +++++++++++++++++++
> >  drivers/thermal/exynos4_thermal.c         |  790 +++++++++++++++++++++++++++++
> >  drivers/thermal/thermal_sys.c             |   45 ++-
> >  include/linux/cpu_cooling.h               |   78 +++
> >  include/linux/platform_data/exynos4_tmu.h |    7 +
> >  include/linux/thermal.h                   |    1 +
> >  23 files changed, 1660 insertions(+), 611 deletions(-)
> >  delete mode 100644 Documentation/hwmon/exynos4_tmu
> >  create mode 100644 Documentation/thermal/cpu-cooling-api.txt
> >  create mode 100644 Documentation/thermal/exynos4_tmu
> >  create mode 100644 arch/arm/mach-exynos/dev-tmu.c
> >  delete mode 100644 drivers/hwmon/exynos4_tmu.c
> >  create mode 100644 drivers/thermal/cpu_cooling.c
> >  create mode 100644 drivers/thermal/exynos4_thermal.c
> >  create mode 100644 include/linux/cpu_cooling.h
> >


_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-pm

^ permalink raw reply

* Re: [RFC] Runtime PM for host controllers
From: Mark Brown @ 2012-04-10  9:25 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-pm
In-Reply-To: <Pine.LNX.4.44L0.1204091007350.1429-100000@iolanthe.rowland.org>

On Mon, Apr 09, 2012 at 10:14:06AM -0400, Alan Stern wrote:
> On Sun, 8 Apr 2012, Kevin Cernekee wrote:

> > a) Is SATA/USB/MMC host controller suspension something that can be
> > accomplished within the existing runtime PM framework?

> Not only _can_ it be accomplished, it already _has_ been accomplished 
> (for USB at least, I'm not familiar with the others).

MMC does this quite happily too, controller and device suspends are
largely orthogonal.

^ permalink raw reply

* Re: [PATCH V2]mmc: remove MMC bus legacy suspend/resume method
From: Ulf Hansson @ 2012-04-10 13:19 UTC (permalink / raw)
  To: Chuanxiao Dong
  Cc: linux-mmc@vger.kernel.org, linux-pm@lists.linux-foundation.org,
	rjw@sisk.pl
In-Reply-To: <20120405075118.GA29395@intel.com>


On 04/05/2012 09:51 AM, Chuanxiao Dong wrote:
> MMC bus is using legacy suspend/resume method, which is not compatible if
> runtime pm callbacks are used. In this scenario, MMC bus suspend/resume
> callbacks cannot be called when system entering S3. So change to use the new
> defined dev_pm_ops for system sleeping mode
>
> Signed-off-by: Chuanxiao Dong<chuanxiao.dong@intel.com>
> ---
> Changes in v2:
> 	use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
> 	suggested
>
>   drivers/mmc/card/block.c |    2 +-
>   drivers/mmc/core/bus.c   |   26 ++++++++++++--------------
>   include/linux/mmc/card.h |    2 +-
>   3 files changed, 14 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index f2020d3..3582c03 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -1826,7 +1826,7 @@ static void mmc_blk_remove(struct mmc_card *card)
>   }
>
>   #ifdef CONFIG_PM
> -static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
> +static int mmc_blk_suspend(struct mmc_card *card)
>   {
>   	struct mmc_blk_data *part_md;
>   	struct mmc_blk_data *md = mmc_get_drvdata(card);
> diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
> index 5d011a3..d44f0d9 100644
> --- a/drivers/mmc/core/bus.c
> +++ b/drivers/mmc/core/bus.c
> @@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev)
>   	return 0;
>   }
>
> -static int mmc_bus_suspend(struct device *dev, pm_message_t state)
> +static int mmc_bus_suspend(struct device *dev)
>   {
>   	struct mmc_driver *drv = to_mmc_driver(dev->driver);
>   	struct mmc_card *card = mmc_dev_to_card(dev);
>   	int ret = 0;
>
>   	if (dev->driver&&  drv->suspend)
> -		ret = drv->suspend(card, state);
> +		ret = drv->suspend(card);
>   	return ret;
>   }
>
> @@ -165,20 +165,20 @@ static int mmc_runtime_idle(struct device *dev)
>   	return pm_runtime_suspend(dev);
>   }
>
> -static const struct dev_pm_ops mmc_bus_pm_ops = {
> -	.runtime_suspend	= mmc_runtime_suspend,
> -	.runtime_resume		= mmc_runtime_resume,
> -	.runtime_idle		= mmc_runtime_idle,
> -};
> -
> -#define MMC_PM_OPS_PTR	(&mmc_bus_pm_ops)
> -
>   #else /* !CONFIG_PM_RUNTIME */
>
> -#define MMC_PM_OPS_PTR	NULL
> +#define mmc_runtime_suspend	NULL
> +#define mmc_runtime_resume	NULL
> +#define mmc_runtime_idle	NULL

You do not have to set these functions to NULL, the use of 
SET_RUNTIME_PM_OPS will fix that when !CONFIG_PM_RUNTIME

>
>   #endif /* !CONFIG_PM_RUNTIME */
>
> +static const struct dev_pm_ops mmc_bus_pm_ops = {
> +	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
> +			mmc_runtime_idle)
> +	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
> +};
> +
>   static struct bus_type mmc_bus_type = {
>   	.name		= "mmc",
>   	.dev_attrs	= mmc_dev_attrs,
> @@ -186,9 +186,7 @@ static struct bus_type mmc_bus_type = {
>   	.uevent		= mmc_bus_uevent,
>   	.probe		= mmc_bus_probe,
>   	.remove		= mmc_bus_remove,
> -	.suspend	= mmc_bus_suspend,
> -	.resume		= mmc_bus_resume,
> -	.pm		= MMC_PM_OPS_PTR,
> +	.pm		=&mmc_bus_pm_ops,
>   };
>
>   int mmc_register_bus(void)
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index 1a1ca71..c984c9a 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -480,7 +480,7 @@ struct mmc_driver {
>   	struct device_driver drv;
>   	int (*probe)(struct mmc_card *);
>   	void (*remove)(struct mmc_card *);
> -	int (*suspend)(struct mmc_card *, pm_message_t);
> +	int (*suspend)(struct mmc_card *);
>   	int (*resume)(struct mmc_card *);
>   };
>

Otherwise looks good!

Kind regards
Ulf Hansson

^ permalink raw reply

* RE: [PATCH V2]mmc: remove MMC bus legacy suspend/resume method
From: Dong, Chuanxiao @ 2012-04-10 14:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: linux-mmc@vger.kernel.org, linux-pm@lists.linux-foundation.org,
	rjw@sisk.pl
In-Reply-To: <4F84336A.8070903@stericsson.com>



> -----Original Message-----
> From: Ulf Hansson [mailto:ulf.hansson@stericsson.com]
> Sent: Tuesday, April 10, 2012 9:20 PM
> To: Dong, Chuanxiao
> Cc: linux-mmc@vger.kernel.org; linux-pm@lists.linux-foundation.org; rjw@sisk.pl
> Subject: Re: [PATCH V2]mmc: remove MMC bus legacy suspend/resume method
> 
> 
> On 04/05/2012 09:51 AM, Chuanxiao Dong wrote:
> > MMC bus is using legacy suspend/resume method, which is not compatible
> > if runtime pm callbacks are used. In this scenario, MMC bus
> > suspend/resume callbacks cannot be called when system entering S3. So
> > change to use the new defined dev_pm_ops for system sleeping mode
> >
> > Signed-off-by: Chuanxiao Dong<chuanxiao.dong@intel.com>
> > ---
> > Changes in v2:
> > 	use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
> > 	suggested
> >
> >   drivers/mmc/card/block.c |    2 +-
> >   drivers/mmc/core/bus.c   |   26 ++++++++++++--------------
> >   include/linux/mmc/card.h |    2 +-
> >   3 files changed, 14 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index
> > f2020d3..3582c03 100644
> > --- a/drivers/mmc/card/block.c
> > +++ b/drivers/mmc/card/block.c
> > @@ -1826,7 +1826,7 @@ static void mmc_blk_remove(struct mmc_card *card)
> >   }
> >
> >   #ifdef CONFIG_PM
> > -static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
> > +static int mmc_blk_suspend(struct mmc_card *card)
> >   {
> >   	struct mmc_blk_data *part_md;
> >   	struct mmc_blk_data *md = mmc_get_drvdata(card); diff --git
> > a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index
> > 5d011a3..d44f0d9 100644
> > --- a/drivers/mmc/core/bus.c
> > +++ b/drivers/mmc/core/bus.c
> > @@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev)
> >   	return 0;
> >   }
> >
> > -static int mmc_bus_suspend(struct device *dev, pm_message_t state)
> > +static int mmc_bus_suspend(struct device *dev)
> >   {
> >   	struct mmc_driver *drv = to_mmc_driver(dev->driver);
> >   	struct mmc_card *card = mmc_dev_to_card(dev);
> >   	int ret = 0;
> >
> >   	if (dev->driver&&  drv->suspend)
> > -		ret = drv->suspend(card, state);
> > +		ret = drv->suspend(card);
> >   	return ret;
> >   }
> >
> > @@ -165,20 +165,20 @@ static int mmc_runtime_idle(struct device *dev)
> >   	return pm_runtime_suspend(dev);
> >   }
> >
> > -static const struct dev_pm_ops mmc_bus_pm_ops = {
> > -	.runtime_suspend	= mmc_runtime_suspend,
> > -	.runtime_resume		= mmc_runtime_resume,
> > -	.runtime_idle		= mmc_runtime_idle,
> > -};
> > -
> > -#define MMC_PM_OPS_PTR	(&mmc_bus_pm_ops)
> > -
> >   #else /* !CONFIG_PM_RUNTIME */
> >
> > -#define MMC_PM_OPS_PTR	NULL
> > +#define mmc_runtime_suspend	NULL
> > +#define mmc_runtime_resume	NULL
> > +#define mmc_runtime_idle	NULL
> 
> You do not have to set these functions to NULL, the use of SET_RUNTIME_PM_OPS
> will fix that when !CONFIG_PM_RUNTIME
Okay, will remove this in v3.

Thanks
Chuanxiao

> 
> >
> >   #endif /* !CONFIG_PM_RUNTIME */
> >
> > +static const struct dev_pm_ops mmc_bus_pm_ops = {
> > +	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
> > +			mmc_runtime_idle)
> > +	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) };
> > +
> >   static struct bus_type mmc_bus_type = {
> >   	.name		= "mmc",
> >   	.dev_attrs	= mmc_dev_attrs,
> > @@ -186,9 +186,7 @@ static struct bus_type mmc_bus_type = {
> >   	.uevent		= mmc_bus_uevent,
> >   	.probe		= mmc_bus_probe,
> >   	.remove		= mmc_bus_remove,
> > -	.suspend	= mmc_bus_suspend,
> > -	.resume		= mmc_bus_resume,
> > -	.pm		= MMC_PM_OPS_PTR,
> > +	.pm		=&mmc_bus_pm_ops,
> >   };
> >
> >   int mmc_register_bus(void)
> > diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index
> > 1a1ca71..c984c9a 100644
> > --- a/include/linux/mmc/card.h
> > +++ b/include/linux/mmc/card.h
> > @@ -480,7 +480,7 @@ struct mmc_driver {
> >   	struct device_driver drv;
> >   	int (*probe)(struct mmc_card *);
> >   	void (*remove)(struct mmc_card *);
> > -	int (*suspend)(struct mmc_card *, pm_message_t);
> > +	int (*suspend)(struct mmc_card *);
> >   	int (*resume)(struct mmc_card *);
> >   };
> >
> 
> Otherwise looks good!
> 
> Kind regards
> Ulf Hansson

^ permalink raw reply

* [PATCH V3]mmc: remove MMC bus legacy suspend/resume method
From: Chuanxiao Dong @ 2012-04-10 14:07 UTC (permalink / raw)
  To: linux-mmc, linux-pm; +Cc: cjb, linus.walleij, ulf.hansson, rjw

MMC bus is using legacy suspend/resume method, which is not compatible if
runtime pm callbacks are used. In this scenario, MMC bus suspend/resume
callbacks cannot be called when system entering S3. So change to use the new
defined dev_pm_ops for system sleeping mode

Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
---
Changes in v2:
	use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
	suggested

Changes in v3:
	remove NULL pointer define for runtime callbacks when PM_RUNTIME is not
	selected, as Ulf Hansson suggested

 drivers/mmc/card/block.c |    2 +-
 drivers/mmc/core/bus.c   |   24 ++++++------------------
 include/linux/mmc/card.h |    2 +-
 3 files changed, 8 insertions(+), 20 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f2020d3..3582c03 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1826,7 +1826,7 @@ static void mmc_blk_remove(struct mmc_card *card)
 }
 
 #ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+static int mmc_blk_suspend(struct mmc_card *card)
 {
 	struct mmc_blk_data *part_md;
 	struct mmc_blk_data *md = mmc_get_drvdata(card);
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 5d011a3..1996c9b 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev)
 	return 0;
 }
 
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+static int mmc_bus_suspend(struct device *dev)
 {
 	struct mmc_driver *drv = to_mmc_driver(dev->driver);
 	struct mmc_card *card = mmc_dev_to_card(dev);
 	int ret = 0;
 
 	if (dev->driver && drv->suspend)
-		ret = drv->suspend(card, state);
+		ret = drv->suspend(card);
 	return ret;
 }
 
@@ -144,8 +144,6 @@ static int mmc_bus_resume(struct device *dev)
 	return ret;
 }
 
-#ifdef CONFIG_PM_RUNTIME
-
 static int mmc_runtime_suspend(struct device *dev)
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
@@ -166,19 +164,11 @@ static int mmc_runtime_idle(struct device *dev)
 }
 
 static const struct dev_pm_ops mmc_bus_pm_ops = {
-	.runtime_suspend	= mmc_runtime_suspend,
-	.runtime_resume		= mmc_runtime_resume,
-	.runtime_idle		= mmc_runtime_idle,
+	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
+			mmc_runtime_idle)
+	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
 };
 
-#define MMC_PM_OPS_PTR	(&mmc_bus_pm_ops)
-
-#else /* !CONFIG_PM_RUNTIME */
-
-#define MMC_PM_OPS_PTR	NULL
-
-#endif /* !CONFIG_PM_RUNTIME */
-
 static struct bus_type mmc_bus_type = {
 	.name		= "mmc",
 	.dev_attrs	= mmc_dev_attrs,
@@ -186,9 +176,7 @@ static struct bus_type mmc_bus_type = {
 	.uevent		= mmc_bus_uevent,
 	.probe		= mmc_bus_probe,
 	.remove		= mmc_bus_remove,
-	.suspend	= mmc_bus_suspend,
-	.resume		= mmc_bus_resume,
-	.pm		= MMC_PM_OPS_PTR,
+	.pm		= &mmc_bus_pm_ops,
 };
 
 int mmc_register_bus(void)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 1a1ca71..c984c9a 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -480,7 +480,7 @@ struct mmc_driver {
 	struct device_driver drv;
 	int (*probe)(struct mmc_card *);
 	void (*remove)(struct mmc_card *);
-	int (*suspend)(struct mmc_card *, pm_message_t);
+	int (*suspend)(struct mmc_card *);
 	int (*resume)(struct mmc_card *);
 };
 
-- 
1.7.1


^ permalink raw reply related

* Re: [RFC] Runtime PM for host controllers
From: Alan Stern @ 2012-04-10 14:15 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: linux-pm
In-Reply-To: <CAJiQ=7CVzOpRdKWMzLwtYznjOno-GQjOZ8Jm7EiEzs9icWwnHw@mail.gmail.com>

On Mon, 9 Apr 2012, Kevin Cernekee wrote:

> On Mon, Apr 9, 2012 at 7:14 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> >> USB runtime PM seems to focus on the individual USB devices, and does
> >> not allow for dynamically suspending the entire host controller
> >> AFAICT.
> >
> > That is not correct.  USB host controllers _can_ be suspended.  (Not
> > all of them; many of the platform drivers don't implement controller
> > suspend.  But some of them do, and almost all of the PCI-based drivers
> > do.)
> 
> I am not clear on what is actually happening at the chip level in these cases?
> 
> i.e. is the entire USB core getting clock gated or power gated, such
> that it is completely non-responsive to register accesses or device
> hotplug?  Or is the driver just shutting down a few tiny pieces of the
> hardware?

The entire controller goes into a low-power mode.  For example, a PCI 
controller would go into D3hot.  The hardware is no longer responsive 
to register accesses, but it can generate a wakeup signal in response 
to device hotplug.

> Is there a way to initiate USB runtime suspend on the host controller
> even if there are devices plugged into the downstream ports?

Yes, provided all those devices are themselves already suspended.

> >>  In general I don't
> >> see any facility where the application can explicitly tell the PM core
> >> to suspend a device (incurring a potential loss of functionality, such
> >> as hot plug/unplug detection).
> >
> > Right; there is no way to do this.  The OS will suspend a device only
> > when it believes it is safe to do so.
> 
> Assuming that somebody is able to come up with a satisfactory
> implementation, are you open to allowing a "user-initiated suspend"
> mode, in addition to "opportunistic suspend"?

I'm not sure what you are asking.  If "use-initiated suspend"  
involves loss of functionality (such as loss of hotplug/unplug
detection) then no, it is generally not acceptable -- although the
final decision rests with the subsystem's maintainer.  If it does not
involve any such loss then no "user-initiated suspend" should be
needed, because the existing runtime suspend methods will do the job.

On the other hand, if you really want to suspend a device and don't
care about using it, then unbinding it from its driver is a good start.  
For USB devices, that alone will cause the device to be suspended.  
For PCI devices (such as host controllers), unfortunately, it isn't
sufficient -- the PCI subsystem doesn't allow driverless devices to be
suspended.  Perhaps the same is true of the platform subsystem; I'm not
sure.

If you'd like to work on a method of allowing driverless PCI or
platform devices to be runtime-suspended, that would be okay.  It 
probably wouldn't be very hard to do.

> >> d) Or should I just go back to using "rmmod"?
> >
> > I don't see how rmmod will save any power.
> 
> rmmod allows me to forcibly shut down the controller, cleanly (in
> theory) disconnecting any active devices and preventing the kernel
> from touching the registers.
> 
> After rmmod, I can then tell the SoC to put the whole core into an
> unresponsive, low power state.
> 
> This is not a very clean way of doing things, so I would prefer to use
> runtime PM if at all possible.  But I don't think my hardware is
> designed in a way that is compatible with "opportunistic suspend."

In what way is it incompatible?

Alan Stern

^ permalink raw reply

* Re: [PATCH V3]mmc: remove MMC bus legacy suspend/resume method
From: Ulf Hansson @ 2012-04-10 14:32 UTC (permalink / raw)
  To: Chuanxiao Dong
  Cc: linux-mmc@vger.kernel.org, linux-pm@lists.linux-foundation.org,
	cjb@laptop.org, linus.walleij@linaro.org, rjw@sisk.pl
In-Reply-To: <20120410140721.GA15362@intel.com>

On 04/10/2012 04:07 PM, Chuanxiao Dong wrote:
> MMC bus is using legacy suspend/resume method, which is not compatible if
> runtime pm callbacks are used. In this scenario, MMC bus suspend/resume
> callbacks cannot be called when system entering S3. So change to use the new
> defined dev_pm_ops for system sleeping mode
>
> Signed-off-by: Chuanxiao Dong<chuanxiao.dong@intel.com>
> ---
> Changes in v2:
> 	use SET_SYSTEM_SLEEP_PM_OPS to define sleep callbacks as Rafael
> 	suggested
>
> Changes in v3:
> 	remove NULL pointer define for runtime callbacks when PM_RUNTIME is not
> 	selected, as Ulf Hansson suggested
>
>   drivers/mmc/card/block.c |    2 +-
>   drivers/mmc/core/bus.c   |   24 ++++++------------------
>   include/linux/mmc/card.h |    2 +-
>   3 files changed, 8 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index f2020d3..3582c03 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -1826,7 +1826,7 @@ static void mmc_blk_remove(struct mmc_card *card)
>   }
>
>   #ifdef CONFIG_PM
> -static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
> +static int mmc_blk_suspend(struct mmc_card *card)
>   {
>   	struct mmc_blk_data *part_md;
>   	struct mmc_blk_data *md = mmc_get_drvdata(card);
> diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
> index 5d011a3..1996c9b 100644
> --- a/drivers/mmc/core/bus.c
> +++ b/drivers/mmc/core/bus.c
> @@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev)
>   	return 0;
>   }
>
> -static int mmc_bus_suspend(struct device *dev, pm_message_t state)
> +static int mmc_bus_suspend(struct device *dev)
>   {
>   	struct mmc_driver *drv = to_mmc_driver(dev->driver);
>   	struct mmc_card *card = mmc_dev_to_card(dev);
>   	int ret = 0;
>
>   	if (dev->driver&&  drv->suspend)
> -		ret = drv->suspend(card, state);
> +		ret = drv->suspend(card);
>   	return ret;
>   }
>
> @@ -144,8 +144,6 @@ static int mmc_bus_resume(struct device *dev)
>   	return ret;
>   }
>
> -#ifdef CONFIG_PM_RUNTIME

I don't think this "idfef" shall removed. Won't that trigger compiler 
warnings when !CONFIG_PM_RUNTIME?

Just remove these three lines from patch v2...

+#define mmc_runtime_suspend	NULL
+#define mmc_runtime_resume	NULL
+#define mmc_runtime_idle	NULL

...and thus the "else" to the CONFIG_PM_RUNTIME, as done below.

> -
>   static int mmc_runtime_suspend(struct device *dev)
>   {
>   	struct mmc_card *card = mmc_dev_to_card(dev);
> @@ -166,19 +164,11 @@ static int mmc_runtime_idle(struct device *dev)
>   }
>
>   static const struct dev_pm_ops mmc_bus_pm_ops = {
> -	.runtime_suspend	= mmc_runtime_suspend,
> -	.runtime_resume		= mmc_runtime_resume,
> -	.runtime_idle		= mmc_runtime_idle,
> +	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
> +			mmc_runtime_idle)
> +	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
>   };
>
> -#define MMC_PM_OPS_PTR	(&mmc_bus_pm_ops)
> -
> -#else /* !CONFIG_PM_RUNTIME */
> -
> -#define MMC_PM_OPS_PTR	NULL
> -
> -#endif /* !CONFIG_PM_RUNTIME */
> -
>   static struct bus_type mmc_bus_type = {
>   	.name		= "mmc",
>   	.dev_attrs	= mmc_dev_attrs,
> @@ -186,9 +176,7 @@ static struct bus_type mmc_bus_type = {
>   	.uevent		= mmc_bus_uevent,
>   	.probe		= mmc_bus_probe,
>   	.remove		= mmc_bus_remove,
> -	.suspend	= mmc_bus_suspend,
> -	.resume		= mmc_bus_resume,
> -	.pm		= MMC_PM_OPS_PTR,
> +	.pm		=&mmc_bus_pm_ops,
>   };
>
>   int mmc_register_bus(void)
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index 1a1ca71..c984c9a 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -480,7 +480,7 @@ struct mmc_driver {
>   	struct device_driver drv;
>   	int (*probe)(struct mmc_card *);
>   	void (*remove)(struct mmc_card *);
> -	int (*suspend)(struct mmc_card *, pm_message_t);
> +	int (*suspend)(struct mmc_card *);
>   	int (*resume)(struct mmc_card *);
>   };
>

Kind regards
Ulf Hansson

^ permalink raw reply

* Re: [RFC] Runtime PM for host controllers
From: Kevin Cernekee @ 2012-04-10 19:21 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-pm
In-Reply-To: <Pine.LNX.4.44L0.1204100949390.1605-100000@iolanthe.rowland.org>

On Tue, Apr 10, 2012 at 7:15 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> I am not clear on what is actually happening at the chip level in these cases?
>>
>> i.e. is the entire USB core getting clock gated or power gated, such
>> that it is completely non-responsive to register accesses or device
>> hotplug?  Or is the driver just shutting down a few tiny pieces of the
>> hardware?
>
> The entire controller goes into a low-power mode.  For example, a PCI
> controller would go into D3hot.  The hardware is no longer responsive
> to register accesses, but it can generate a wakeup signal in response
> to device hotplug.

Do you have any estimates of power savings on the host controller side?

On my systems, it would take a lot of extra power to maintain the
ability to detect device hotplug.  I am wondering if the PCI based
controller has a better way of handling it in the hardware than we do,
or if the power savings from D3hot are just very small.

>> Is there a way to initiate USB runtime suspend on the host controller
>> even if there are devices plugged into the downstream ports?
>
> Yes, provided all those devices are themselves already suspended.

But a lot of the drivers for USB devices do not even support suspend,
correct?  And many of them become unreliable if you turn it on?

What if I just want to forcibly suspend the entire USB subsystem?

>> >>  In general I don't
>> >> see any facility where the application can explicitly tell the PM core
>> >> to suspend a device (incurring a potential loss of functionality, such
>> >> as hot plug/unplug detection).
>> >
>> > Right; there is no way to do this.  The OS will suspend a device only
>> > when it believes it is safe to do so.
>>
>> Assuming that somebody is able to come up with a satisfactory
>> implementation, are you open to allowing a "user-initiated suspend"
>> mode, in addition to "opportunistic suspend"?
>
> I'm not sure what you are asking.  If "use-initiated suspend"
> involves loss of functionality (such as loss of hotplug/unplug
> detection) then no, it is generally not acceptable -- although the
> final decision rests with the subsystem's maintainer.

Who is the right person to make the call?  Rafael?

> If it does not
> involve any such loss then no "user-initiated suspend" should be
> needed, because the existing runtime suspend methods will do the job.

Right.  Unfortunately I don't really have any devices that work this
way.  Most are "all or nothing."

>> rmmod allows me to forcibly shut down the controller, cleanly (in
>> theory) disconnecting any active devices and preventing the kernel
>> from touching the registers.
>>
>> After rmmod, I can then tell the SoC to put the whole core into an
>> unresponsive, low power state.
>>
>> This is not a very clean way of doing things, so I would prefer to use
>> runtime PM if at all possible.  But I don't think my hardware is
>> designed in a way that is compatible with "opportunistic suspend."
>
> In what way is it incompatible?

My devices lose functionality when they are put into low-power modes.

^ permalink raw reply

* Re: [RFC] Runtime PM for host controllers
From: Alan Stern @ 2012-04-10 19:48 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: linux-pm
In-Reply-To: <CAJiQ=7AL24L2-KJ405jOkFutti5QcGfMEzp2rKbcrMY=5TuJzg@mail.gmail.com>

On Tue, 10 Apr 2012, Kevin Cernekee wrote:

> > The entire controller goes into a low-power mode.  For example, a PCI
> > controller would go into D3hot.  The hardware is no longer responsive
> > to register accesses, but it can generate a wakeup signal in response
> > to device hotplug.
> 
> Do you have any estimates of power savings on the host controller side?

No.  Other people may have measured it, though.

> On my systems, it would take a lot of extra power to maintain the
> ability to detect device hotplug.  I am wondering if the PCI based
> controller has a better way of handling it in the hardware than we do,
> or if the power savings from D3hot are just very small.

PCI devices have two different power wells, one for normal use and one 
for use during suspend.  As far as I know, there is no way to turn off 
power to the auxiliary well short of turning off the entire computer.  
Rafael may have a more complete picture.

> >> Is there a way to initiate USB runtime suspend on the host controller
> >> even if there are devices plugged into the downstream ports?
> >
> > Yes, provided all those devices are themselves already suspended.
> 
> But a lot of the drivers for USB devices do not even support suspend,
> correct?  And many of them become unreliable if you turn it on?

I haven't counted, but I think most of the commonly used drivers do
support it.  And most of the devices can be suspended and resumed
reliably, although there certainly are exceptions.

> What if I just want to forcibly suspend the entire USB subsystem?

Your rmmod approach will always work, but that isn't really a suspend.  
The USB subsystem doesn't provide any way to "force" a device to be
suspended against the kernel's will.

> >> Assuming that somebody is able to come up with a satisfactory
> >> implementation, are you open to allowing a "user-initiated suspend"
> >> mode, in addition to "opportunistic suspend"?
> >
> > I'm not sure what you are asking.  If "use-initiated suspend"
> > involves loss of functionality (such as loss of hotplug/unplug
> > detection) then no, it is generally not acceptable -- although the
> > final decision rests with the subsystem's maintainer.
> 
> Who is the right person to make the call?  Rafael?

The maintainer for whatever subsystem you're working on.  However,
general policy is set by Rafael and overall consensus on the linux-pm
list.

> > If it does not
> > involve any such loss then no "user-initiated suspend" should be
> > needed, because the existing runtime suspend methods will do the job.
> 
> Right.  Unfortunately I don't really have any devices that work this
> way.  Most are "all or nothing."

Is the loss of functionality you're talking about essentially the same
as removing the driver?  I don't think anybody would object to a
driverless device being put into a non-functional low-power mode, since
without a driver, it's pretty non-functional anyway.  It's easy for
userspace to unbind a device from its driver; would that then do what
you want?

> >> This is not a very clean way of doing things, so I would prefer to use
> >> runtime PM if at all possible.  But I don't think my hardware is
> >> designed in a way that is compatible with "opportunistic suspend."
> >
> > In what way is it incompatible?
> 
> My devices lose functionality when they are put into low-power modes.

What functionality do they lose?

Alan Stern

^ permalink raw reply

* Re: [RFC] Runtime PM for host controllers
From: Kevin Cernekee @ 2012-04-10 22:42 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-pm
In-Reply-To: <Pine.LNX.4.44L0.1204101535090.1605-100000@iolanthe.rowland.org>

On Tue, Apr 10, 2012 at 12:48 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> On my systems, it would take a lot of extra power to maintain the
>> ability to detect device hotplug.  I am wondering if the PCI based
>> controller has a better way of handling it in the hardware than we do,
>> or if the power savings from D3hot are just very small.
>
> PCI devices have two different power wells, one for normal use and one
> for use during suspend.  As far as I know, there is no way to turn off
> power to the auxiliary well short of turning off the entire computer.
> Rafael may have a more complete picture.

That may be the case on PCs, but on many embedded systems (mine
included), entire hardware blocks can be clock-gated or power-gated
without shutting off the rest of the system.

>> > If it does not
>> > involve any such loss then no "user-initiated suspend" should be
>> > needed, because the existing runtime suspend methods will do the job.
>>
>> Right.  Unfortunately I don't really have any devices that work this
>> way.  Most are "all or nothing."
>
> Is the loss of functionality you're talking about essentially the same
> as removing the driver?

>From a hardware perspective, yes.

> I don't think anybody would object to a
> driverless device being put into a non-functional low-power mode, since
> without a driver, it's pretty non-functional anyway.  It's easy for
> userspace to unbind a device from its driver; would that then do what
> you want?

Probably, but it seems a little clunky when we have a "runtime
suspend" framework already in place...

Unbinding/binding the device is slower than suspending it, and might
be a problem if there are mounted filesystems involved.

Going back to the NAS example I mentioned earlier - I would imagine
that merely resuming the USB/SATA controller + HDD when a new request
arrives is going to provide a much faster recovery time than rebinding
+ redetecting + remounting.

(Of course that raises issues like: what if somebody unplugs the
current HDD, then plugs in a different HDD, while the USB/SATA core is
asleep?)

>> >> This is not a very clean way of doing things, so I would prefer to use
>> >> runtime PM if at all possible.  But I don't think my hardware is
>> >> designed in a way that is compatible with "opportunistic suspend."
>> >
>> > In what way is it incompatible?
>>
>> My devices lose functionality when they are put into low-power modes.
>
> What functionality do they lose?

Everything, including register access, PHY links, and hotplug detection.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox