code:
.. SPDX-License-Identifier: GPL-2.0+

.. |u8| replace:: :c:type:`u8 <u8>`
.. |u16| replace:: :c:type:`u16 <u16>`
.. |TYPE| replace:: ``TYPE``
.. |LEN| replace:: ``LEN``
.. |SEQ| replace:: ``SEQ``
.. |SYN| replace:: ``SYN``
.. |NAK| replace:: ``NAK``
.. |ACK| replace:: ``ACK``
.. |DATA| replace:: ``DATA``
.. |DATA_SEQ| replace:: ``DATA_SEQ``
.. |DATA_NSQ| replace:: ``DATA_NSQ``
.. |TC| replace:: ``TC``
.. |TID| replace:: ``TID``
.. |IID| replace:: ``IID``
.. |RQID| replace:: ``RQID``
.. |CID| replace:: ``CID``

===========================
Surface Serial Hub Protocol
===========================

The Surface Serial Hub (SSH) is the central communication interface for the
embedded Surface Aggregator Module controller (SAM or EC), found on newer
Surface generations. We will refer to this protocol and interface as
SAM-over-SSH, as opposed to SAM-over-HID for the older generations.

On Surface devices with SAM-over-SSH, SAM is connected to the host via UART
and defined in ACPI as device with ID ``MSHW0084``. On these devices,
significant functionality is provided via SAM, including access to battery
and power information and events, thermal read-outs and events, and many
more. For Surface Laptops, keyboard input is handled via HID directed
through SAM, on the Surface Laptop 3 and Surface Book 3 this also includes
touchpad input.

Note that the standard disclaimer for this subsystem also applies to this
document: All of this has been reverse-engineered and may thus be erroneous
and/or incomplete.

All CRCs used in the following are two-byte ``crc_ccitt_false(0xffff, ...)``.
All multi-byte values are little-endian, there is no implicit padding between
values.

SSH Packet Protocol: Definitions
================================

The fundamental communication unit of the SSH protocol is a frame
(:c:type:`struct ssh_frame <ssh_frame>`). A frame consists of the following
fields, packed together and in order:

.. flat-table:: SSH Frame
   :widths: 1 1 4
   :header-rows: 1

   * - Field
     - Type
     - Description

   * - |TYPE|
     - |u8|
     - Type identifier of the frame.

   * - |LEN|
     - |u16|
     - Length of the payload associated with the frame.

   * - |SEQ|
     - |u8|
     - Sequence ID (see explanation below).

Each frame structure is followed by a CRC over this structure. The CRC over
the frame structure (|TYPE|, |LEN|, and |SEQ| fields) is placed directly
after the frame structure and before the payload. The payload is followed by
its own CRC (over all payload bytes). If the payload is not present (i.e.
the frame has ``LEN=0``), the CRC of the payload is still present and will
evaluate to ``0xffff``. The |LEN| field does not include any of the CRCs, it
equals the number of bytes inbetween the CRC of the frame and the CRC of the
payload.

Additionally, the following fixed two-byte sequences are used:

.. flat-table:: SSH Byte Sequences
   :widths: 1 1 4
   :header-rows: 1

   * - Name
     - Value
     - Description

   * - |SYN|
     - ``[0xAA, 0x55]``
     - Synchronization bytes.

A message consists of |SYN|, followed by the frame (|TYPE|, |LEN|, |SEQ| and
CRC) and, if specified in the frame (i.e. ``LEN > 0``), payload bytes,
followed finally, regardless if the payload is present, the payload CRC. The
messages corresponding to an exchange are, in part, identified by having the
same sequence ID (|SEQ|), stored inside the frame (more on this in the next
section). The sequence ID is a wrapping counter.

A frame can have the following types
(:c:type:`enum ssh_frame_type <ssh_frame_type>`):

.. flat-table:: SSH Frame Types
   :widths: 1 1 4
   :header-rows: 1

   * - Name
     - Value
     - Short Description

   * - |NAK|
     - ``0x04``
     - Sent on error in previously received message.

   * - |ACK|
     - ``0x40``
     - Sent to acknowledge receival of |DATA| frame.

   * - |DATA_SEQ|
     - ``0x80``
     - Sent to transfer data. Sequenced.

   * - |DATA_NSQ|
     - ``0x00``
     - Same as |DATA_SEQ|, but does not need to be ACKed.

Both |NAK|- and |ACK|-type frames are used to control flow of messages and
thus do not carry a payload. |DATA_SEQ|- and |DATA_NSQ|-type frames on the
other hand must carry a payload. The flow sequence and interaction of
different frame types will be described in more depth in the next section.

SSH Packet Protocol: Flow Sequence
==================================

Each exchange begins with |SYN|, followed by a |DATA_SEQ|- or
|DATA_NSQ|-type frame, followed by its CRC, payload, and payload CRC. In
case of a |DATA_NSQ|-type frame, the exchange is then finished. In case of a
|DATA_SEQ|-type frame, the receiving party has to acknowledge receival of
the frame by responding with a message containing an |ACK|-type frame with
the same sequence ID of the |DATA| frame. In other words, the sequence ID of
the |ACK| frame specifies the |DATA| frame to be acknowledged. In case of an
error, e.g. an invalid CRC, the receiving party responds with a message
containing an |NAK|-type frame. As the sequence ID of the previous data
frame, for which an error is indicated via the |NAK| frame, cannot be relied
upon, the sequence ID of the |NAK| frame should not be used and is set to
zero. After receival of an |NAK| frame, the sending party should re-send all
outstanding (non-ACKed) messages.

Sequence IDs are not synchronized between the two parties, meaning that they
are managed independently for each party. Identifying the messages
corresponding to a single exchange thus relies on the sequence ID as well as
the type of the message, and the context. Specifically, the sequence ID is
used to associate an ``ACK`` with its ``DATA_SEQ``-type frame, but not
``DATA_SEQ``- or ``DATA_NSQ``-type frames with other ``DATA``- type frames.

An example exchange might look like this:

::

    tx: -- SYN FRAME(D) CRC(F) PAYLOAD CRC(P) -----------------------------
    rx: ------------------------------------- SYN FRAME(A) CRC(F) CRC(P) --

where both frames have the same sequence ID (``SEQ``). Here, ``FRAME(D)``
indicates a |DATA_SEQ|-type frame, ``FRAME(A)`` an ``ACK``-type frame,
``CRC(F)`` the CRC over the previous frame, ``CRC(P)`` the CRC over the
previous payload. In case of an error, the exchange would look like this:

::

    tx: -- SYN FRAME(D) CRC(F) PAYLOAD CRC(P) -----------------------------
    rx: ------------------------------------- SYN FRAME(N) CRC(F) CRC(P) --

upon which the sender should re-send the message. ``FRAME(N)`` indicates an
|NAK|-type frame. Note that the sequence ID of the |NAK|-type frame is fixed
to zero. For |DATA_NSQ|-type frames, both exchanges are the same:

::

    tx: -- SYN FRAME(DATA_NSQ) CRC(F) PAYLOAD CRC(P) ----------------------
    rx: -------------------------------------------------------------------

Here, an error can be detected, but not corrected or indicated to the
sending party. These exchanges are symmetric, i.e. switching ``rx`` and
``tx`` results again in a valid exchange. Currently, no longer exchanges are
known.

Commands: Requests, Responses, and Events
=========================================

Commands are sent as payload inside a data frame. Currently, this is the
only known payload type of |DATA| frames, with a payload-type value of
``0x80`` (:c:type:`SSH_PLD_TYPE_CMD <ssh_payload_type>`).

The command-type payload (:c:type:`struct ssh_command <ssh_command>`)
consists of an eight-byte command structure, followed by optional and
variable length command data. The length of this optional data is derived
from the frame payload length given in the corresponding frame, i.e. it is
``frame.len - sizeof(struct ssh_command)``. The command struct contains the
following fields, packed together and in order:

.. flat-table:: SSH Command
   :widths: 1 1 4
   :header-rows: 1

   * - Field
     - Type
     - Description

   * - |TYPE|
     - |u8|
     - Type of the payload. For commands always ``0x80``.

   * - |TC|
     - |u8|
     - Target category.

   * - |TID| (out)
     - |u8|
     - Target ID for outgoing (host to EC) commands.

   * - |TID| (in)
     - |u8|
     - Target ID for incoming (EC to host) commands.

   * - |IID|
     - |u8|
     - Instance ID.

   * - |RQID|
     - |u16|
     - Request ID.

   * - |CID|
     - |u8|
     - Command ID.

The command struct and data, in general, does not contain any failure
detection mechanism (e.g. CRCs), this is solely done on the frame level.

Command-type payloads are used by the host to send commands and requests to
the EC as well as by the EC to send responses and events back to the host.
We differentiate between requests (sent by the host), responses (sent by the
EC in response to a request), and events (sent by the EC without a preceding
request).

Commands and events are uniquely identified by their target category
(``TC``) and command ID (``CID``). The target category specifies a general
category for the command (e.g. system in general, vs. battery and AC, vs.
temperature, and so on), while the command ID specifies the command inside
that category. Only the combination of |TC| + |CID| is unique. Additionally,
commands have an instance ID (``IID``), which is used to differentiate
between different sub-devices. For example ``TC=3`` ``CID=1`` is a
request to get the temperature on a thermal sensor, where |IID| specifies
the respective sensor. If the instance ID is not used, it should be set to
zero. If instance IDs are used, they, in general, start with a value of one,
whereas zero may be used for instance independent queries, if applicable. A
response to a request should have the same target category, command ID, and
instance ID as the corresponding request.

Responses are matched to their corresponding request via the request ID
(``RQID``) field. This is a 16 bit wrapping counter similar to the sequence
ID on the frames. Note that the sequence ID of the frames for a
request-response pair does not match. Only the request ID has to match.
Frame-protocol wise these are two separate exchanges, and may even be
separated, e.g. by an event being sent after the request but before the
response. Not all commands produce a response, and this is not detectable by
|TC| + |CID|. It is the responsibility of the issuing party to wait for a
response (or signal this to the communication framework, as is done in
SAN/ACPI via the ``SNC`` flag).

Events are identified by unique and reserved request IDs. These IDs should
not be used by the host when sending a new request. They are used on the
host to, first, detect events and, second, match them with a registered
event handler. Request IDs for events are chosen by the host and directed to
the EC when setting up and enabling an event source (via the
enable-event-source request). The EC then uses the specified request ID for
events sent from the respective source. Note that an event should still be
identified by its target category, command ID, and, if applicable, instance
ID, as a single event source can send multiple different event types. In
general, however, a single target category should map to a single reserved
event request ID.

Furthermore, requests, responses, and events have an associated target ID
(``TID``). This target ID is split into output (host to EC) and input (EC to
host) fields, with the respecting other field (e.g. output field on incoming
messages) set to zero. Two ``TID`` values are known: Primary (``0x01``) and
secondary (``0x02``). In general, the response to a request should have the
same ``TID`` value, however, the field (output vs. input) should be used in
accordance to the direction in which the response is sent (i.e. on the input
field, as responses are generally sent from the EC to the host).

Note that, even though requests and events should be uniquely identifiable
by target category and command ID alone, the EC may require specific
target ID and instance ID values to accept a command. A command that is
accepted for ``TID=1``, for example, may not be accepted for ``TID=2``
and vice versa.

Limitations and Observations
============================

The protocol can, in theory, handle up to ``U8_MAX`` frames in parallel,
with up to ``U16_MAX`` pending requests (neglecting request IDs reserved for
events). In practice, however, this is more limited. From our testing
(although via a python and thus a user-space program), it seems that the EC
can handle up to four requests (mostly) reliably in parallel at a certain
time. With five or more requests in parallel, consistent discarding of
commands (ACKed frame but no command response) has been observed. For five
simultaneous commands, this reproducibly resulted in one command being
dropped and four commands being handled.

However, it has also been noted that, even with three requests in parallel,
occasional frame drops happen. Apart from this, with a limit of three
pending requests, no dropped commands (i.e. command being dropped but frame
carrying command being ACKed) have been observed. In any case, frames (and
possibly also commands) should be re-sent by the host if a certain timeout
is exceeded. This is done by the EC for frames with a timeout of one second,
up to two re-tries (i.e. three transmissions in total). The limit of
re-tries also applies to received NAKs, and, in a worst case scenario, can
lead to entire messages being dropped.

While this also seems to work fine for pending data frames as long as no
transmission failures occur, implementation and handling of these seems to
depend on the assumption that there is only one non-acknowledged data frame.
In particular, the detection of repeated frames relies on the last sequence
number. This means that, if a frame that has been successfully received by
the EC is sent again, e.g. due to the host not receiving an |ACK|, the EC
will only detect this if it has the sequence ID of the last frame received
by the EC. As an example: Sending two frames with ``SEQ=0`` and ``SEQ=1``
followed by a repetition of ``SEQ=0`` will not detect the second ``SEQ=0``
frame as such, and thus execute the command in this frame each time it has
been received, i.e. twice in this example. Sending ``SEQ=0``, ``SEQ=1`` and
then repeating ``SEQ=1`` will detect the second ``SEQ=1`` as repetition of
the first one and ignore it, thus executing the contained command only once.

In conclusion, this suggests a limit of at most one pending un-ACKed frame
(per party, effectively leading to synchronous communication regarding
frames) and at most three pending commands. The limit to synchronous frame
transfers seems to be consistent with behavior observed on Windows.


code:
========================
Linux Switchtec Support
========================

Microsemi's "Switchtec" line of PCI switch devices is already
supported by the kernel with standard PCI switch drivers. However, the
Switchtec device advertises a special management endpoint which
enables some additional functionality. This includes:

* Packet and Byte Counters
* Firmware Upgrades
* Event and Error logs
* Querying port link status
* Custom user firmware commands

The switchtec kernel module implements this functionality.

Interface
=========

The primary means of communicating with the Switchtec management firmware is
through the Memory-mapped Remote Procedure Call (MRPC) interface.
Commands are submitted to the interface with a 4-byte command
identifier and up to 1KB of command specific data. The firmware will
respond with a 4-byte return code and up to 1KB of command-specific
data. The interface only processes a single command at a time.

Userspace Interface
===================

The MRPC interface will be exposed to userspace through a simple char
device: /dev/switchtec#, one for each management endpoint in the system.

The char device has the following semantics:

* A write must consist of at least 4 bytes and no more than 1028 bytes.
  The first 4 bytes will be interpreted as the Command ID and the
  remainder will be used as the input data. A write will send the
  command to the firmware to begin processing.

* Each write must be followed by exactly one read. Any double write will
  produce an error and any read that doesn't follow a write will
  produce an error.

* A read will block until the firmware completes the command and return
  the 4-byte Command Return Value plus up to 1024 bytes of output
  data. (The length will be specified by the size parameter of the read
  call -- reading less than 4 bytes will produce an error.)

* The poll call will also be supported for userspace applications that
  need to do other things while waiting for the command to complete.

The following IOCTLs are also supported by the device:

* SWITCHTEC_IOCTL_FLASH_INFO - Retrieve firmware length and number
  of partitions in the device.

* SWITCHTEC_IOCTL_FLASH_PART_INFO - Retrieve address and lengeth for
  any specified partition in flash.

* SWITCHTEC_IOCTL_EVENT_SUMMARY - Read a structure of bitmaps
  indicating all uncleared events.

* SWITCHTEC_IOCTL_EVENT_CTL - Get the current count, clear and set flags
  for any event. This ioctl takes in a switchtec_ioctl_event_ctl struct
  with the event_id, index and flags set (index being the partition or PFF
  number for non-global events). It returns whether the event has
  occurred, the number of times and any event specific data. The flags
  can be used to clear the count or enable and disable actions to
  happen when the event occurs.
  By using the SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL flag,
  you can set an event to trigger a poll command to return with
  POLLPRI. In this way, userspace can wait for events to occur.

* SWITCHTEC_IOCTL_PFF_TO_PORT and SWITCHTEC_IOCTL_PORT_TO_PFF convert
  between PCI Function Framework number (used by the event system)
  and Switchtec Logic Port ID and Partition number (which is more
  user friendly).

Non-Transparent Bridge (NTB) Driver
===================================

An NTB hardware driver is provided for the Switchtec hardware in
ntb_hw_switchtec. Currently, it only supports switches configured with
exactly 2 NT partitions and zero or more non-NT partitions. It also requires
the following configuration settings:

* Both NT partitions must be able to access each other's GAS spaces.
  Thus, the bits in the GAS Access Vector under Management Settings
  must be set to support this.
* Kernel configuration MUST include support for NTB (CONFIG_NTB needs
  to be set)

NT EP BAR 2 will be dynamically configured as a Direct Window, and
the configuration file does not need to configure it explicitly.

Please refer to Documentation/driver-api/ntb.rst in Linux source tree for an overall
understanding of the Linux NTB stack. ntb_hw_switchtec works as an NTB
Hardware Driver in this stack.

repo_name: angery/linux


code:
===================
Sync File API Guide
===================

:Author: Gustavo Padovan <gustavo at padovan dot org>

This document serves as a guide for device drivers writers on what the
sync_file API is, and how drivers can support it. Sync file is the carrier of
the fences(struct dma_fence) that are needed to synchronize between drivers or
across process boundaries.

The sync_file API is meant to be used to send and receive fence information
to/from userspace. It enables userspace to do explicit fencing, where instead
of attaching a fence to the buffer a producer driver (such as a GPU or V4L
driver) sends the fence related to the buffer to userspace via a sync_file.

The sync_file then can be sent to the consumer (DRM driver for example), that
will not use the buffer for anything before the fence(s) signals, i.e., the
driver that issued the fence is not using/processing the buffer anymore, so it
signals that the buffer is ready to use. And vice-versa for the consumer ->
producer part of the cycle.

Sync files allows userspace awareness on buffer sharing synchronization between
drivers.

Sync file was originally added in the Android kernel but current Linux Desktop
can benefit a lot from it.

in-fences and out-fences
------------------------

Sync files can go either to or from userspace. When a sync_file is sent from
the driver to userspace we call the fences it contains 'out-fences'. They are
related to a buffer that the driver is processing or is going to process, so
the driver creates an out-fence to be able to notify, through
dma_fence_signal(), when it has finished using (or processing) that buffer.
Out-fences are fences that the driver creates.

On the other hand if the driver receives fence(s) through a sync_file from
userspace we call these fence(s) 'in-fences'. Receiving in-fences means that
we need to wait for the fence(s) to signal before using any buffer related to
the in-fences.

Creating Sync Files
-------------------

When a driver needs to send an out-fence userspace it creates a sync_file.

Interface::

	struct sync_file *sync_file_create(struct dma_fence *fence);

The caller pass the out-fence and gets back the sync_file. That is just the
first step, next it needs to install an fd on sync_file->file. So it gets an
fd::

	fd = get_unused_fd_flags(O_CLOEXEC);

and installs it on sync_file->file::

	fd_install(fd, sync_file->file);

The sync_file fd now can be sent to userspace.

If the creation process fail, or the sync_file needs to be released by any
other reason fput(sync_file->file) should be used.

Receiving Sync Files from Userspace
-----------------------------------

When userspace needs to send an in-fence to the driver it passes file descriptor
of the Sync File to the kernel. The kernel can then retrieve the fences
from it.

Interface::

	struct dma_fence *sync_file_get_fence(int fd);

The returned reference is owned by the caller and must be disposed of
afterwards using dma_fence_put(). In case of error, a NULL is returned instead.

References:

1. struct sync_file in include/linux/sync_file.h
2. All interfaces mentioned above defined in include/linux/sync_file.h


code:
=================================
target and iSCSI Interfaces Guide
=================================

Introduction and Overview
=========================

TBD

Target core device interfaces
=============================

This section is blank because no kerneldoc comments have been added to
drivers/target/target_core_device.c.

Target core transport interfaces
================================

.. kernel-doc:: drivers/target/target_core_transport.c
    :export:

Target-supported userspace I/O
==============================

.. kernel-doc:: drivers/target/target_core_user.c
    :doc: Userspace I/O

.. kernel-doc:: include/uapi/linux/target_core_user.h
    :doc: Ring Design

iSCSI helper functions
======================

.. kernel-doc:: drivers/scsi/libiscsi.c
   :export:

iSCSI boot information
======================

.. kernel-doc:: drivers/scsi/iscsi_boot_sysfs.c
   :export:

iSCSI TCP interfaces
====================

.. kernel-doc:: drivers/scsi/iscsi_tcp.c
   :internal:

.. kernel-doc:: drivers/scsi/libiscsi_tcp.c
   :export:


code:
=======================
CPU cooling APIs How To
=======================

Written by Amit Daniel Kachhap <amit.kachhap@linaro.org>

Updated: 6 Jan 2015

Copyright (c)  2012 Samsung Electronics Co., Ltd(http://www.samsung.com)

0. Introduction
===============

The generic cpu cooling(freq clipping) provides registration/unregistration APIs
to the caller. The binding of the cooling devices to the trip point is left for
the user. The registration APIs returns the cooling device pointer.

1. cpu cooling APIs
===================

1.1 cpufreq registration/unregistration APIs
--------------------------------------------

    ::

	struct thermal_cooling_device
	*cpufreq_cooling_register(struct cpumask *clip_cpus)

    This interface function registers the cpufreq cooling device with the name
    "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
    cooling devices.

   clip_cpus:
	cpumask of cpus where the frequency constraints will happen.

    ::

	struct thermal_cooling_device
	*of_cpufreq_cooling_register(struct cpufreq_policy *policy)

    This interface function registers the cpufreq cooling device with
    the name "thermal-cpufreq-%x" linking it with a device tree node, in
    order to bind it via the thermal DT code. This api can support multiple
    instances of cpufreq cooling devices.

    policy:
	CPUFreq policy.

    ::

	void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)

    This interface function unregisters the "thermal-cpufreq-%x" cooling device.

    cdev: Cooling device pointer which has to be unregistered.

2. Power models
===============

The power API registration functions provide a simple power model for
CPUs.  The current power is calculated as dynamic power (static power isn't
supported currently).  This power model requires that the operating-points of
the CPUs are registered using the kernel's opp library and the
`cpufreq_frequency_table` is assigned to the `struct device` of the
cpu.  If you are using CONFIG_CPUFREQ_DT then the
`cpufreq_frequency_table` should already be assigned to the cpu
device.

The dynamic power consumption of a processor depends on many factors.
For a given processor implementation the primary factors are:

- The time the processor spends running, consuming dynamic power, as
  compared to the time in idle states where dynamic consumption is
  negligible.  Herein we refer to this as 'utilisation'.
- The voltage and frequency levels as a result of DVFS.  The DVFS
  level is a dominant factor governing power consumption.
- In running time the 'execution' behaviour (instruction types, memory
  access patterns and so forth) causes, in most cases, a second order
  variation.  In pathological cases this variation can be significant,
  but typically it is of a much lesser impact than the factors above.

A high level dynamic power consumption model may then be represented as::

	Pdyn = f(run) * Voltage^2 * Frequency * Utilisation

f(run) here represents the described execution behaviour and its
result has a units of Watts/Hz/Volt^2 (this often expressed in
mW/MHz/uVolt^2)

The detailed behaviour for f(run) could be modelled on-line.  However,
in practice, such an on-line model has dependencies on a number of
implementation specific processor support and characterisation
factors.  Therefore, in initial implementation that contribution is
represented as a constant coefficient.  This is a simplification
consistent with the relative contribution to overall power variation.

In this simplified representation our model becomes::

	Pdyn = Capacitance * Voltage^2 * Frequency * Utilisation

Where `capacitance` is a constant that represents an indicative
running time dynamic power coefficient in fundamental units of
mW/MHz/uVolt^2.  Typical values for mobile CPUs might lie in range
from 100 to 500.  For reference, the approximate values for the SoC in
ARM's Juno Development Platform are 530 for the Cortex-A57 cluster and
140 for the Cortex-A53 cluster.


code:
.. SPDX-License-Identifier: GPL-2.0

================
CPU Idle Cooling
================

Situation:
----------

Under certain circumstances a SoC can reach a critical temperature
limit and is unable to stabilize the temperature around a temperature
control. When the SoC has to stabilize the temperature, the kernel can
act on a cooling device to mitigate the dissipated power. When the
critical temperature is reached, a decision must be taken to reduce
the temperature, that, in turn impacts performance.

Another situation is when the silicon temperature continues to
increase even after the dynamic leakage is reduced to its minimum by
clock gating the component. This runaway phenomenon can continue due
to the static leakage. The only solution is to power down the
component, thus dropping the dynamic and static leakage that will
allow the component to cool down.

Last but not least, the system can ask for a specific power budget but
because of the OPP density, we can only choose an OPP with a power
budget lower than the requested one and under-utilize the CPU, thus
losing performance. In other words, one OPP under-utilizes the CPU
with a power less than the requested power budget and the next OPP
exceeds the power budget. An intermediate OPP could have been used if
it were present.

Solutions:
----------

If we can remove the static and the dynamic leakage for a specific
duration in a controlled period, the SoC temperature will
decrease. Acting on the idle state duration or the idle cycle
injection period, we can mitigate the temperature by modulating the
power budget.

The Operating Performance Point (OPP) density has a great influence on
the control precision of cpufreq, however different vendors have a
plethora of OPP density, and some have large power gap between OPPs,
that will result in loss of performance during thermal control and
loss of power in other scenarios.

At a specific OPP, we can assume that injecting idle cycle on all CPUs
belong to the same cluster, with a duration greater than the cluster
idle state target residency, we lead to dropping the static and the
dynamic leakage for this period (modulo the energy needed to enter
this state). So the sustainable power with idle cycles has a linear
relation with the OPP’s sustainable power and can be computed with a
coefficient similar to::

	    Power(IdleCycle) = Coef x Power(OPP)

Idle Injection:
---------------

The base concept of the idle injection is to force the CPU to go to an
idle state for a specified time each control cycle, it provides
another way to control CPU power and heat in addition to
cpufreq. Ideally, if all CPUs belonging to the same cluster, inject
their idle cycles synchronously, the cluster can reach its power down
state with a minimum power consumption and reduce the static leakage
to almost zero.  However, these idle cycles injection will add extra
latencies as the CPUs will have to wakeup from a deep sleep state.

We use a fixed duration of idle injection that gives an acceptable
performance penalty and a fixed latency. Mitigation can be increased
or decreased by modulating the duty cycle of the idle injection.

::

     ^
     |
     |
     |-------                         -------
     |_______|_______________________|_______|___________

     <------>
       idle  <---------------------->
                    running

      <----------------------------->
              duty cycle 25%

The implementation of the cooling device bases the number of states on
the duty cycle percentage. When no mitigation is happening the cooling
device state is zero, meaning the duty cycle is 0%.

When the mitigation begins, depending on the governor's policy, a
starting state is selected. With a fixed idle duration and the duty
cycle (aka the cooling device state), the running duration can be
computed.

The governor will change the cooling device state thus the duty cycle
and this variation will modulate the cooling effect.

::

     ^
     |
     |
     |-------                 -------
     |_______|_______________|_______|___________

     <------>
       idle  <-------------->
                running

      <--------------------->
          duty cycle 33%

     ^
     |
     |
     |-------         -------
     |_______|_______|_______|___________

     <------>
       idle  <------>
              running

      <------------->
       duty cycle 50%

The idle injection duration value must comply with the constraints:

- It is less than or equal to the latency we tolerate when the
  mitigation begins. It is platform dependent and will depend on the
  user experience, reactivity vs performance trade off we want. This
  value should be specified.

- It is greater than the idle state’s target residency we want to go
  for thermal mitigation, otherwise we end up consuming more energy.

Power considerations
--------------------

When we reach the thermal trip point, we have to sustain a specified
power for a specific temperature but at this time we consume::

 Power = Capacitance x Voltage^2 x Frequency x Utilisation

... which is more than the sustainable power (or there is something
wrong in the system setup). The ‘Capacitance’ and ‘Utilisation’ are a
fixed value, ‘Voltage’ and the ‘Frequency’ are fixed artificially
because we don’t want to change the OPP. We can group the
‘Capacitance’ and the ‘Utilisation’ into a single term which is the
‘Dynamic Power Coefficient (Cdyn)’ Simplifying the above, we have::

 Pdyn = Cdyn x Voltage^2 x Frequency

The power allocator governor will ask us somehow to reduce our power
in order to target the sustainable power defined in the device
tree. So with the idle injection mechanism, we want an average power
(Ptarget) resulting in an amount of time running at full power on a
specific OPP and idle another amount of time. That could be put in a
equation::

 P(opp)target = ((Trunning x (P(opp)running) + (Tidle x P(opp)idle)) /
			(Trunning + Tidle)

  ...

 Tidle = Trunning x ((P(opp)running / P(opp)target) - 1)

At this point if we know the running period for the CPU, that gives us
the idle injection we need. Alternatively if we have the idle
injection duration, we can compute the running duration with::

 Trunning = Tidle / ((P(opp)running / P(opp)target) - 1)

Practically, if the running power is less than the targeted power, we
end up with a negative time value, so obviously the equation usage is
bound to a power reduction, hence a higher OPP is needed to have the
running power greater than the targeted power.

However, in this demonstration we ignore three aspects:

 * The static leakage is not defined here, we can introduce it in the
   equation but assuming it will be zero most of the time as it is
   difficult to get the values from the SoC vendors

 * The idle state wake up latency (or entry + exit latency) is not
   taken into account, it must be added in the equation in order to
   rigorously compute the idle injection

 * The injected idle duration must be greater than the idle state
   target residency, otherwise we end up consuming more energy and
   potentially invert the mitigation effect

So the final equation is::

 Trunning = (Tidle - Twakeup ) x
		(((P(opp)dyn + P(opp)static ) - P(opp)target) / P(opp)target )


code:
========================
Kernel driver exynos_tmu
========================

Supported chips:

* ARM Samsung Exynos4, Exynos5 series of SoC

  Datasheet: Not publicly available

Authors: Donggeun Kim <dg77.kim@samsung.com>
Authors: Amit Daniel <amit.daniel@samsung.com>

TMU controller Description:
---------------------------

This driver allows to read temperature inside Samsung Exynos4/5 series of SoC.

The chip only exposes the measured 8-bit temperature code value
through a register.
Temperature can be taken from the temperature code.
There are three equations converting from temperature to temperature code.

The three equations are:
  1. Two point trimming::

	Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1

  2. One point trimming::

	Tc = T + TI1 - 25

  3. No trimming::

	Tc = T + 50

  Tc:
       Temperature code, T: Temperature,
  TI1:
       Trimming info for 25 degree Celsius (stored at TRIMINFO register)
       Temperature code measured at 25 degree Celsius which is unchanged
  TI2:
       Trimming info for 85 degree Celsius (stored at TRIMINFO register)
       Temperature code measured at 85 degree Celsius which is unchanged

TMU(Thermal Management Unit) in Exynos4/5 generates interrupt
when temperature exceeds pre-defined levels.
The maximum number of configurable threshold is five.
The threshold levels are defined as follows::

  Level_0: current temperature > trigger_level_0 + threshold
  Level_1: current temperature > trigger_level_1 + threshold
  Level_2: current temperature > trigger_level_2 + threshold
  Level_3: current temperature > trigger_level_3 + threshold

The threshold and each trigger_level are set
through the corresponding registers.

When an interrupt occurs, this driver notify kernel thermal framework
with the function exynos_report_trigger.
Although an interrupt condition for level_0 can be set,
it can be used to synchronize the cooling action.

TMU driver description:
-----------------------

The exynos thermal driver is structured as::

					Kernel Core thermal framework
				(thermal_core.c, step_wise.c, cpufreq_cooling.c)
								^
								|
								|
  TMU configuration data -----> TMU Driver  <----> Exynos Core thermal wrapper
  (exynos_tmu_data.c)	      (exynos_tmu.c)	   (exynos_thermal_common.c)
  (exynos_tmu_data.h)	      (exynos_tmu.h)	   (exynos_thermal_common.h)

a) TMU configuration data:
		This consist of TMU register offsets/bitfields
		described through structure exynos_tmu_registers. Also several
		other platform data (struct exynos_tmu_platform_data) members
		are used to configure the TMU.
b) TMU driver:
		This component initialises the TMU controller and sets different
		thresholds. It invokes core thermal implementation with the call
		exynos_report_trigger.
c) Exynos Core thermal wrapper:
		This provides 3 wrapper function to use the
		Kernel core thermal framework. They are exynos_unregister_thermal,
		exynos_register_thermal and exynos_report_trigger.


code:
=====================
Exynos Emulation Mode
=====================

Copyright (C) 2012 Samsung Electronics

Written by Jonghwa Lee <jonghwa3.lee@samsung.com>

Description
-----------

Exynos 4x12 (4212, 4412) and 5 series provide emulation mode for thermal
management unit. Thermal emulation mode supports software debug for
TMU's operation. User can set temperature manually with software code
and TMU will read current temperature from user value not from sensor's
value.

Enabling CONFIG_THERMAL_EMULATION option will make this support
available. When it's enabled, sysfs node will be created as
/sys/devices/virtual/thermal/thermal_zone'zone id'/emul_temp.

The sysfs node, 'emul_node', will contain value 0 for the initial state.
When you input any temperature you want to update to sysfs node, it
automatically enable emulation mode and current temperature will be
changed into it.

(Exynos also supports user changeable delay time which would be used to
delay of changing temperature. However, this node only uses same delay
of real sensing time, 938us.)

Exynos emulation mode requires synchronous of value changing and
enabling. It means when you want to update the any value of delay or
next temperature, then you have to enable emulation mode at the same
time. (Or you have to keep the mode enabling.) If you don't, it fails to
change the value to updated one and just use last succeessful value
repeatedly. That's why this node gives users the right to change
termerpature only. Just one interface makes it more simply to use.

Disabling emulation mode only requires writing value 0 to sysfs node.

::

  TEMP	120 |
	    |
	100 |
	    |
	 80 |
	    |				 +-----------
	 60 |      			 |	    |
	    |		   +-------------|          |
	 40 |              |         	 |          |
	    |		   |		 |          |
	 20 |		   |		 |          +----------
	    |		   |		 |          |          |
	  0 |______________|_____________|__________|__________|_________
		   A		 A	    A		       A     TIME
		   |<----->|	 |<----->|  |<----->|	       |
		   | 938us |  	 |	 |  |       |          |
  emulation   : 0  50	   |  	 70      |  20      |          0
  current temp:   sensor   50		 70         20	      sensor


code:
.. SPDX-License-Identifier: GPL-2.0

=======
Thermal
=======

.. toctree::
   :maxdepth: 1

   cpu-cooling-api
   cpu-idle-cooling
   sysfs-api
   power_allocator

   exynos_thermal
   exynos_thermal_emulation
   intel_powerclamp
   nouveau_thermal
   x86_pkg_temperature_thermal
   intel_dptf


code:
.. SPDX-License-Identifier: GPL-2.0

===============================================================
Intel(R) Dynamic Platform and Thermal Framework Sysfs Interface
===============================================================

:Copyright: © 2022 Intel Corporation

:Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

Introduction
------------

Intel(R) Dynamic Platform and Thermal Framework (DPTF) is a platform
level hardware/software solution for power and thermal management.

As a container for multiple power/thermal technologies, DPTF provides
a coordinated approach for different policies to effect the hardware
state of a system.

Since it is a platform level framework, this has several components.
Some parts of the technology is implemented in the firmware and uses
ACPI and PCI devices to expose various features for monitoring and
control. Linux has a set of kernel drivers exposing hardware interface
to user space. This allows user space thermal solutions like
"Linux Thermal Daemon" to read platform specific thermal and power
tables to deliver adequate performance while keeping the system under
thermal limits.

DPTF ACPI Drivers interface
----------------------------

:file:`/sys/bus/platform/devices/<N>/uuids`, where <N>
=INT3400|INTC1040|INTC1041|INTC10A0

``available_uuids`` (RO)
	A set of UUIDs strings presenting available policies
	which should be notified to the firmware when the
	user space can support those policies.

	UUID strings:

	"42A441D6-AE6A-462b-A84B-4A8CE79027D3" : Passive 1

	"3A95C389-E4B8-4629-A526-C52C88626BAE" : Active

	"97C68AE7-15FA-499c-B8C9-5DA81D606E0A" : Critical

	"63BE270F-1C11-48FD-A6F7-3AF253FF3E2D" : Adaptive performance

	"5349962F-71E6-431D-9AE8-0A635B710AEE" : Emergency call

	"9E04115A-AE87-4D1C-9500-0F3E340BFE75" : Passive 2

	"F5A35014-C209-46A4-993A-EB56DE7530A1" : Power Boss

	"6ED722A7-9240-48A5-B479-31EEF723D7CF" : Virtual Sensor

	"16CAF1B7-DD38-40ED-B1C1-1B8A1913D531" : Cooling mode

	"BE84BABF-C4D4-403D-B495-3128FD44dAC1" : HDC

``current_uuid`` (RW)
	User space can write strings from available UUIDs, one at a
	time.

:file:`/sys/bus/platform/devices/<N>/`, where <N>
=INT3400|INTC1040|INTC1041|INTC10A0

``imok`` (WO)
	User space daemon write 1 to respond to firmware event
	for sending keep alive notification. User space receives
	THERMAL_EVENT_KEEP_ALIVE kobject uevent notification when
	firmware calls for user space to respond with imok ACPI
	method.

``odvp*`` (RO)
	Firmware thermal status variable values. Thermal tables
	calls for different processing based on these variable
	values.

``data_vault`` (RO)
	Binary thermal table. Refer to
	https:/github.com/intel/thermal_daemon for decoding
	thermal table.

ACPI Thermal Relationship table interface
------------------------------------------

:file:`/dev/acpi_thermal_rel`

	This device provides IOCTL interface to read standard ACPI
	thermal relationship tables via ACPI methods _TRT and _ART.
	These IOCTLs are defined in
	drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h

	IOCTLs:

	ACPI_THERMAL_GET_TRT_LEN: Get length of TRT table

	ACPI_THERMAL_GET_ART_LEN: Get length of ART table

	ACPI_THERMAL_GET_TRT_COUNT: Number of records in TRT table

	ACPI_THERMAL_GET_ART_COUNT: Number of records in ART table

	ACPI_THERMAL_GET_TRT: Read binary TRT table, length to read is
	provided via argument to ioctl().

	ACPI_THERMAL_GET_ART: Read binary ART table, length to read is
	provided via argument to ioctl().

DPTF ACPI Sensor drivers
-------------------------

DPTF Sensor drivers are presented as standard thermal sysfs thermal_zone.

DPTF ACPI Cooling drivers
--------------------------

DPTF cooling drivers are presented as standard thermal sysfs cooling_device.

DPTF Processor thermal PCI Driver interface
--------------------------------------------

:file:`/sys/bus/pci/devices/0000\:00\:04.0/power_limits/`

Refer to Documentation/power/powercap/powercap.rst for powercap
ABI.

``power_limit_0_max_uw`` (RO)
	Maximum powercap sysfs constraint_0_power_limit_uw for Intel RAPL

``power_limit_0_step_uw`` (RO)
	Power limit increment/decrements for Intel RAPL constraint 0 power limit

``power_limit_0_min_uw`` (RO)
	Minimum powercap sysfs constraint_0_power_limit_uw for Intel RAPL

``power_limit_0_tmin_us`` (RO)
	Minimum powercap sysfs constraint_0_time_window_us for Intel RAPL

``power_limit_0_tmax_us`` (RO)
	Maximum powercap sysfs constraint_0_time_window_us for Intel RAPL

``power_limit_1_max_uw`` (RO)
	Maximum powercap sysfs constraint_1_power_limit_uw for Intel RAPL

``power_limit_1_step_uw`` (RO)
	Power limit increment/decrements for Intel RAPL constraint 1 power limit

``power_limit_1_min_uw`` (RO)
	Minimum powercap sysfs constraint_1_power_limit_uw for Intel RAPL

``power_limit_1_tmin_us`` (RO)
	Minimum powercap sysfs constraint_1_time_window_us for Intel RAPL

``power_limit_1_tmax_us`` (RO)
	Maximum powercap sysfs constraint_1_time_window_us for Intel RAPL

:file:`/sys/bus/pci/devices/0000\:00\:04.0/`

``tcc_offset_degree_celsius`` (RW)
	TCC offset from the critical temperature where hardware will throttle
	CPU.

:file:`/sys/bus/pci/devices/0000\:00\:04.0/workload_request`

``workload_available_types`` (RO)
	Available workload types. User space can specify one of the workload type
	it is currently executing via workload_type. For example: idle, bursty,
	sustained etc.

``workload_type`` (RW)
	User space can specify any one of the available workload type using
	this interface.

DPTF Processor thermal RFIM interface
--------------------------------------------

RFIM interface allows adjustment of FIVR (Fully Integrated Voltage Regulator)
and DDR (Double Data Rate)frequencies to avoid RF interference with WiFi and 5G.

Switching voltage regulators (VR) generate radiated EMI or RFI at the
fundamental frequency and its harmonics. Some harmonics may interfere
with very sensitive wireless receivers such as Wi-Fi and cellular that
are integrated into host systems like notebook PCs.  One of mitigation
methods is requesting SOC integrated VR (IVR) switching frequency to a
small % and shift away the switching noise harmonic interference from
radio channels.  OEM or ODMs can use the driver to control SOC IVR
operation within the range where it does not impact IVR performance.

DRAM devices of DDR IO interface and their power plane can generate EMI
at the data rates. Similar to IVR control mechanism, Intel offers a
mechanism by which DDR data rates can be changed if several conditions
are met: there is strong RFI interference because of DDR; CPU power
management has no other restriction in changing DDR data rates;
PC ODMs enable this feature (real time DDR RFI Mitigation referred to as
DDR-RFIM) for Wi-Fi from BIOS.

FIVR attributes

:file:`/sys/bus/pci/devices/0000\:00\:04.0/fivr/`

``vco_ref_code_lo`` (RW)
	The VCO reference code is an 11-bit field and controls the FIVR
	switching frequency. This is the 3-bit LSB field.

``vco_ref_code_hi`` (RW)
	The VCO reference code is an 11-bit field and controls the FIVR
	switching frequency. This is the 8-bit MSB field.

``spread_spectrum_pct`` (RW)
	Set the FIVR spread spectrum clocking percentage

``spread_spectrum_clk_enable`` (RW)
	Enable/disable of the FIVR spread spectrum clocking feature

``rfi_vco_ref_code`` (RW)
	This field is a read only status register which reflects the
	current FIVR switching frequency

``fivr_fffc_rev`` (RW)
	This field indicated the revision of the FIVR HW.

DVFS attributes

:file:`/sys/bus/pci/devices/0000\:00\:04.0/dvfs/`

``rfi_restriction_run_busy`` (RW)
	Request the restriction of specific DDR data rate and set this
	value 1. Self reset to 0 after operation.

``rfi_restriction_err_code`` (RW)
	0 :Request is accepted, 1:Feature disabled,
	2: the request restricts more points than it is allowed

``rfi_restriction_data_rate_Delta`` (RW)
	Restricted DDR data rate for RFI protection: Lower Limit

``rfi_restriction_data_rate_Base`` (RW)
	Restricted DDR data rate for RFI protection: Upper Limit

``ddr_data_rate_point_0`` (RO)
	DDR data rate selection 1st point

``ddr_data_rate_point_1`` (RO)
	DDR data rate selection 2nd point

``ddr_data_rate_point_2`` (RO)
	DDR data rate selection 3rd point

``ddr_data_rate_point_3`` (RO)
	DDR data rate selection 4th point

``rfi_disable (RW)``
	Disable DDR rate change feature

DPTF Power supply and Battery Interface
----------------------------------------

Refer to Documentation/ABI/testing/sysfs-platform-dptf

DPTF Fan Control
----------------------------------------

Refer to Documentation/admin-guide/acpi/fan_performance_states.rst


code:
=======================
Intel Powerclamp Driver
=======================

By:
  - Arjan van de Ven <arjan@linux.intel.com>
  - Jacob Pan <jacob.jun.pan@linux.intel.com>

.. Contents:

	(*) Introduction
	    - Goals and Objectives

	(*) Theory of Operation
	    - Idle Injection
	    - Calibration

	(*) Performance Analysis
	    - Effectiveness and Limitations
	    - Power vs Performance
	    - Scalability
	    - Calibration
	    - Comparison with Alternative Techniques

	(*) Usage and Interfaces
	    - Generic Thermal Layer (sysfs)
	    - Kernel APIs (TBD)

INTRODUCTION
============

Consider the situation where a system’s power consumption must be
reduced at runtime, due to power budget, thermal constraint, or noise
level, and where active cooling is not preferred. Software managed
passive power reduction must be performed to prevent the hardware
actions that are designed for catastrophic scenarios.

Currently, P-states, T-states (clock modulation), and CPU offlining
are used for CPU throttling.

On Intel CPUs, C-states provide effective power reduction, but so far
they’re only used opportunistically, based on workload. With the
development of intel_powerclamp driver, the method of synchronizing
idle injection across all online CPU threads was introduced. The goal
is to achieve forced and controllable C-state residency.

Test/Analysis has been made in the areas of power, performance,
scalability, and user experience. In many cases, clear advantage is
shown over taking the CPU offline or modulating the CPU clock.

THEORY OF OPERATION
===================

Idle Injection
--------------

On modern Intel processors (Nehalem or later), package level C-state
residency is available in MSRs, thus also available to the kernel.

These MSRs are::

      #define MSR_PKG_C2_RESIDENCY      0x60D
      #define MSR_PKG_C3_RESIDENCY      0x3F8
      #define MSR_PKG_C6_RESIDENCY      0x3F9
      #define MSR_PKG_C7_RESIDENCY      0x3FA

If the kernel can also inject idle time to the system, then a
closed-loop control system can be established that manages package
level C-state. The intel_powerclamp driver is conceived as such a
control system, where the target set point is a user-selected idle
ratio (based on power reduction), and the error is the difference
between the actual package level C-state residency ratio and the target idle
ratio.

Injection is controlled by high priority kernel threads, spawned for
each online CPU.

These kernel threads, with SCHED_FIFO class, are created to perform
clamping actions of controlled duty ratio and duration. Each per-CPU
thread synchronizes its idle time and duration, based on the rounding
of jiffies, so accumulated errors can be prevented to avoid a jittery
effect. Threads are also bound to the CPU such that they cannot be
migrated, unless the CPU is taken offline. In this case, threads
belong to the offlined CPUs will be terminated immediately.

Running as SCHED_FIFO and relatively high priority, also allows such
scheme to work for both preemptable and non-preemptable kernels.
Alignment of idle time around jiffies ensures scalability for HZ
values. This effect can be better visualized using a Perf timechart.
The following diagram shows the behavior of kernel thread
kidle_inject/cpu. During idle injection, it runs monitor/mwait idle
for a given "duration", then relinquishes the CPU to other tasks,
until the next time interval.

The NOHZ schedule tick is disabled during idle time, but interrupts
are not masked. Tests show that the extra wakeups from scheduler tick
have a dramatic impact on the effectiveness of the powerclamp driver
on large scale systems (Westmere system with 80 processors).

::

  CPU0
		    ____________          ____________
  kidle_inject/0   |   sleep    |  mwait |  sleep     |
	  _________|            |________|            |_______
				 duration
  CPU1
		    ____________          ____________
  kidle_inject/1   |   sleep    |  mwait |  sleep     |
	  _________|            |________|            |_______
				^
				|
				|
				roundup(jiffies, interval)

Only one CPU is allowed to collect statistics and update global
control parameters. This CPU is referred to as the controlling CPU in
this document. The controlling CPU is elected at runtime, with a
policy that favors BSP, taking into account the possibility of a CPU
hot-plug.

In terms of dynamics of the idle control system, package level idle
time is considered largely as a non-causal system where its behavior
cannot be based on the past or current input. Therefore, the
intel_powerclamp driver attempts to enforce the desired idle time
instantly as given input (target idle ratio). After injection,
powerclamp monitors the actual idle for a given time window and adjust
the next injection accordingly to avoid over/under correction.

When used in a causal control system, such as a temperature control,
it is up to the user of this driver to implement algorithms where
past samples and outputs are included in the feedback. For example, a
PID-based thermal controller can use the powerclamp driver to
maintain a desired target temperature, based on integral and
derivative gains of the past samples.

Calibration
-----------
During scalability testing, it is observed that synchronized actions
among CPUs become challenging as the number of cores grows. This is
also true for the ability of a system to enter package level C-states.

To make sure the intel_powerclamp driver scales well, online
calibration is implemented. The goals for doing such a calibration
are:

a) determine the effective range of idle injection ratio
b) determine the amount of compensation needed at each target ratio

Compensation to each target ratio consists of two parts:

	a) steady state error compensation
	This is to offset the error occurring when the system can
	enter idle without extra wakeups (such as external interrupts).

	b) dynamic error compensation
	When an excessive amount of wakeups occurs during idle, an
	additional idle ratio can be added to quiet interrupts, by
	slowing down CPU activities.

A debugfs file is provided for the user to examine compensation
progress and results, such as on a Westmere system::

  [jacob@nex01 ~]$ cat
  /sys/kernel/debug/intel_powerclamp/powerclamp_calib
  controlling cpu: 0
  pct confidence steady dynamic (compensation)
  0       0       0       0
  1       1       0       0
  2       1       1       0
  3       3       1       0
  4       3       1       0
  5       3       1       0
  6       3       1       0
  7       3       1       0
  8       3       1       0
  ...
  30      3       2       0
  31      3       2       0
  32      3       1       0
  33      3       2       0
  34      3       1       0
  35      3       2       0
  36      3       1       0
  37      3       2       0
  38      3       1       0
  39      3       2       0
  40      3       3       0
  41      3       1       0
  42      3       2       0
  43      3       1       0
  44      3       1       0
  45      3       2       0
  46      3       3       0
  47      3       0       0
  48      3       2       0
  49      3       3       0

Calibration occurs during runtime. No offline method is available.
Steady state compensation is used only when confidence levels of all
adjacent ratios have reached satisfactory level. A confidence level
is accumulated based on clean data collected at runtime. Data
collected during a period without extra interrupts is considered
clean.

To compensate for excessive amounts of wakeup during idle, additional
idle time is injected when such a condition is detected. Currently,
we have a simple algorithm to double the injection ratio. A possible
enhancement might be to throttle the offending IRQ, such as delaying
EOI for level triggered interrupts. But it is a challenge to be
non-intrusive to the scheduler or the IRQ core code.

CPU Online/Offline
------------------
Per-CPU kernel threads are started/stopped upon receiving
notifications of CPU hotplug activities. The intel_powerclamp driver
keeps track of clamping kernel threads, even after they are migrated
to other CPUs, after a CPU offline event.

Performance Analysis
====================
This section describes the general performance data collected on
multiple systems, including Westmere (80P) and Ivy Bridge (4P, 8P).

Effectiveness and Limitations
-----------------------------
The maximum range that idle injection is allowed is capped at 50
percent. As mentioned earlier, since interrupts are allowed during
forced idle time, excessive interrupts could result in less
effectiveness. The extreme case would be doing a ping -f to generated
flooded network interrupts without much CPU acknowledgement. In this
case, little can be done from the idle injection threads. In most
normal cases, such as scp a large file, applications can be throttled
by the powerclamp driver, since slowing down the CPU also slows down
network protocol processing, which in turn reduces interrupts.

When control parameters change at runtime by the controlling CPU, it
may take an additional period for the rest of the CPUs to catch up
with the changes. During this time, idle injection is out of sync,
thus not able to enter package C- states at the expected ratio. But
this effect is minor, in that in most cases change to the target
ratio is updated much less frequently than the idle injection
frequency.

Scalability
-----------
Tests also show a minor, but measurable, difference between the 4P/8P
Ivy Bridge system and the 80P Westmere server under 50% idle ratio.
More compensation is needed on Westmere for the same amount of
target idle ratio. The compensation also increases as the idle ratio
gets larger. The above reason constitutes the need for the
calibration code.

On the IVB 8P system, compared to an offline CPU, powerclamp can
achieve up to 40% better performance per watt. (measured by a spin
counter summed over per CPU counting threads spawned for all running
CPUs).

Usage and Interfaces
====================
The powerclamp driver is registered to the generic thermal layer as a
cooling device. Currently, it’s not bound to any thermal zones::

  jacob@chromoly:/sys/class/thermal/cooling_device14$ grep . *
  cur_state:0
  max_state:50
  type:intel_powerclamp

cur_state allows user to set the desired idle percentage. Writing 0 to
cur_state will stop idle injection. Writing a value between 1 and
max_state will start the idle injection. Reading cur_state returns the
actual and current idle percentage. This may not be the same value
set by the user in that current idle percentage depends on workload
and includes natural idle. When idle injection is disabled, reading
cur_state returns value -1 instead of 0 which is to avoid confusing
100% busy state with the disabled state.

Example usage:
- To inject 25% idle time::

	$ sudo sh -c "echo 25 > /sys/class/thermal/cooling_device80/cur_state

If the system is not busy and has more than 25% idle time already,
then the powerclamp driver will not start idle injection. Using Top
will not show idle injection kernel threads.

If the system is busy (spin test below) and has less than 25% natural
idle time, powerclamp kernel threads will do idle injection. Forced
idle time is accounted as normal idle in that common code path is
taken as the idle task.

In this example, 24.1% idle is shown. This helps the system admin or
user determine the cause of slowdown, when a powerclamp driver is in action::

  Tasks: 197 total,   1 running, 196 sleeping,   0 stopped,   0 zombie
  Cpu(s): 71.2%us,  4.7%sy,  0.0%ni, 24.1%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
  Mem:   3943228k total,  1689632k used,  2253596k free,    74960k buffers
  Swap:  4087804k total,        0k used,  4087804k free,   945336k cached

    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
   3352 jacob     20   0  262m  644  428 S  286  0.0   0:17.16 spin
   3341 root     -51   0     0    0    0 D   25  0.0   0:01.62 kidle_inject/0
   3344 root     -51   0     0    0    0 D   25  0.0   0:01.60 kidle_inject/3
   3342 root     -51   0     0    0    0 D   25  0.0   0:01.61 kidle_inject/1
   3343 root     -51   0     0    0    0 D   25  0.0   0:01.60 kidle_inject/2
   2935 jacob     20   0  696m 125m  35m S    5  3.3   0:31.11 firefox
   1546 root      20   0  158m  20m 6640 S    3  0.5   0:26.97 Xorg
   2100 jacob     20   0 1223m  88m  30m S    3  2.3   0:23.68 compiz

Tests have shown that by using the powerclamp driver as a cooling
device, a PID based userspace thermal controller can manage to
control CPU temperature effectively, when no other thermal influence
is added. For example, a UltraBook user can compile the kernel under
certain temperature (below most active trip points).


code:
=====================
Kernel driver nouveau
=====================

Supported chips:

* NV43+

Authors: Martin Peres (mupuf) <martin.peres@free.fr>

Description
-----------

This driver allows to read the GPU core temperature, drive the GPU fan and
set temperature alarms.

Currently, due to the absence of in-kernel API to access HWMON drivers, Nouveau
cannot access any of the i2c external monitoring chips it may find. If you
have one of those, temperature and/or fan management through Nouveau's HWMON
interface is likely not to work. This document may then not cover your situation
entirely.

Temperature management
----------------------

Temperature is exposed under as a read-only HWMON attribute temp1_input.

In order to protect the GPU from overheating, Nouveau supports 4 configurable
temperature thresholds:

 * Fan_boost:
	Fan speed is set to 100% when reaching this temperature;
 * Downclock:
	The GPU will be downclocked to reduce its power dissipation;
 * Critical:
	The GPU is put on hold to further lower power dissipation;
 * Shutdown:
	Shut the computer down to protect your GPU.

WARNING:
	Some of these thresholds may not be used by Nouveau depending
	on your chipset.

The default value for these thresholds comes from the GPU's vbios. These
thresholds can be configured thanks to the following HWMON attributes:

 * Fan_boost: temp1_auto_point1_temp and temp1_auto_point1_temp_hyst;
 * Downclock: temp1_max and temp1_max_hyst;
 * Critical: temp1_crit and temp1_crit_hyst;
 * Shutdown: temp1_emergency and temp1_emergency_hyst.

NOTE: Remember that the values are stored as milli degrees Celsius. Don't forget
to multiply!

Fan management
--------------

Not all cards have a drivable fan. If you do, then the following HWMON
attributes should be available:

 * pwm1_enable:
	Current fan management mode (NONE, MANUAL or AUTO);
 * pwm1:
	Current PWM value (power percentage);
 * pwm1_min:
	The minimum PWM speed allowed;
 * pwm1_max:
	The maximum PWM speed allowed (bypassed when hitting Fan_boost);

You may also have the following attribute:

 * fan1_input:
	Speed in RPM of your fan.

Your fan can be driven in different modes:

 * 0: The fan is left untouched;
 * 1: The fan can be driven in manual (use pwm1 to change the speed);
 * 2; The fan is driven automatically depending on the temperature.

NOTE:
  Be sure to use the manual mode if you want to drive the fan speed manually

NOTE2:
  When operating in manual mode outside the vbios-defined
  [PWM_min, PWM_max] range, the reported fan speed (RPM) may not be accurate
  depending on your hardware.

Bug reports
-----------

Thermal management on Nouveau is new and may not work on all cards. If you have
inquiries, please ping mupuf on IRC (#nouveau, OFTC).

Bug reports should be filled on Freedesktop's bug tracker. Please follow
https://nouveau.freedesktop.org/wiki/Bugs


code:
=================================
Power allocator governor tunables
=================================

Trip points
-----------

The governor works optimally with the following two passive trip points:

1.  "switch on" trip point: temperature above which the governor
    control loop starts operating.  This is the first passive trip
    point of the thermal zone.

2.  "desired temperature" trip point: it should be higher than the
    "switch on" trip point.  This the target temperature the governor
    is controlling for.  This is the last passive trip point of the
    thermal zone.

PID Controller
--------------

The power allocator governor implements a
Proportional-Integral-Derivative controller (PID controller) with
temperature as the control input and power as the controlled output:

    P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power

where
   -  e = desired_temperature - current_temperature
   -  err_integral is the sum of previous errors
   -  diff_err = e - previous_error

It is similar to the one depicted below::

				      k_d
				       |
  current_temp                         |
       |                               v
       |              +----------+   +---+
       |       +----->| diff_err |-->| X |------+
       |       |      +----------+   +---+      |
       |       |                                |      tdp        actor
       |       |                      k_i       |       |  get_requested_power()
       |       |                       |        |       |        |     |
       |       |                       |        |       |        |     | ...
       v       |                       v        v       v        v     v
     +---+     |      +-------+      +---+    +---+   +---+   +----------+
     | S |-----+----->| sum e |----->| X |--->| S |-->| S |-->|power     |
     +---+     |      +-------+      +---+    +---+   +---+   |allocation|
       ^       |                                ^             +----------+
       |       |                                |                |     |
       |       |        +---+                   |                |     |
       |       +------->| X |-------------------+                v     v
       |                +---+                               granted performance
  desired_temperature     ^
			  |
			  |
		      k_po/k_pu

Sustainable power
-----------------

An estimate of the sustainable dissipatable power (in mW) should be
provided while registering the thermal zone.  This estimates the
sustained power that can be dissipated at the desired control
temperature.  This is the maximum sustained power for allocation at
the desired maximum temperature.  The actual sustained power can vary
for a number of reasons.  The closed loop controller will take care of
variations such as environmental conditions, and some factors related
to the speed-grade of the silicon.  `sustainable_power` is therefore
simply an estimate, and may be tuned to affect the aggressiveness of
the thermal ramp. For reference, the sustainable power of a 4" phone
is typically 2000mW, while on a 10" tablet is around 4500mW (may vary
depending on screen size). It is possible to have the power value
expressed in an abstract scale. The sustained power should be aligned
to the scale used by the related cooling devices.

If you are using device tree, do add it as a property of the
thermal-zone.  For example::

	thermal-zones {
		soc_thermal {
			polling-delay = <1000>;
			polling-delay-passive = <100>;
			sustainable-power = <2500>;
			...

Instead, if the thermal zone is registered from the platform code, pass a
`thermal_zone_params` that has a `sustainable_power`.  If no
`thermal_zone_params` were being passed, then something like below
will suffice::

	static const struct thermal_zone_params tz_params = {
		.sustainable_power = 3500,
	};

and then pass `tz_params` as the 5th parameter to
`thermal_zone_device_register()`

k_po and k_pu
-------------

The implementation of the PID controller in the power allocator
thermal governor allows the configuration of two proportional term
constants: `k_po` and `k_pu`.  `k_po` is the proportional term
constant during temperature overshoot periods (current temperature is
above "desired temperature" trip point).  Conversely, `k_pu` is the
proportional term constant during temperature undershoot periods
(current temperature below "desired temperature" trip point).

These controls are intended as the primary mechanism for configuring
the permitted thermal "ramp" of the system.  For instance, a lower
`k_pu` value will provide a slower ramp, at the cost of capping
available capacity at a low temperature.  On the other hand, a high
value of `k_pu` will result in the governor granting very high power
while temperature is low, and may lead to temperature overshooting.

The default value for `k_pu` is::

    2 * sustainable_power / (desired_temperature - switch_on_temp)

This means that at `switch_on_temp` the output of the controller's
proportional term will be 2 * `sustainable_power`.  The default value
for `k_po` is::

    sustainable_power / (desired_temperature - switch_on_temp)

Focusing on the proportional and feed forward values of the PID
controller equation we have::

    P_max = k_p * e + sustainable_power

The proportional term is proportional to the difference between the
desired temperature and the current one.  When the current temperature
is the desired one, then the proportional component is zero and
`P_max` = `sustainable_power`.  That is, the system should operate in
thermal equilibrium under constant load.  `sustainable_power` is only
an estimate, which is the reason for closed-loop control such as this.

Expanding `k_pu` we get::

    P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) +
	sustainable_power

where:

    - T_set is the desired temperature
    - T is the current temperature
    - T_on is the switch on temperature

When the current temperature is the switch_on temperature, the above
formula becomes::

    P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) +
	sustainable_power = 2 * sustainable_power + sustainable_power =
	3 * sustainable_power

Therefore, the proportional term alone linearly decreases power from
3 * `sustainable_power` to `sustainable_power` as the temperature
rises from the switch on temperature to the desired temperature.

k_i and integral_cutoff
-----------------------

`k_i` configures the PID loop's integral term constant.  This term
allows the PID controller to compensate for long term drift and for
the quantized nature of the output control: cooling devices can't set
the exact power that the governor requests.  When the temperature
error is below `integral_cutoff`, errors are accumulated in the
integral term.  This term is then multiplied by `k_i` and the result
added to the output of the controller.  Typically `k_i` is set low (1
or 2) and `integral_cutoff` is 0.

k_d
---

`k_d` configures the PID loop's derivative term constant.  It's
recommended to leave it as the default: 0.

Cooling device power API
========================

Cooling devices controlled by this governor must supply the additional
"power" API in their `cooling_device_ops`.  It consists on three ops:

1. ::

    int get_requested_power(struct thermal_cooling_device *cdev,
			    struct thermal_zone_device *tz, u32 *power);

@cdev:
	The `struct thermal_cooling_device` pointer
@tz:
	thermal zone in which we are currently operating
@power:
	pointer in which to store the calculated power

`get_requested_power()` calculates the power requested by the device
in milliwatts and stores it in @power .  It should return 0 on
success, -E* on failure.  This is currently used by the power
allocator governor to calculate how much power to give to each cooling
device.

2. ::

	int state2power(struct thermal_cooling_device *cdev, struct
			thermal_zone_device *tz, unsigned long state,
			u32 *power);

@cdev:
	The `struct thermal_cooling_device` pointer
@tz:
	thermal zone in which we are currently operating
@state:
	A cooling device state
@power:
	pointer in which to store the equivalent power

Convert cooling device state @state into power consumption in
milliwatts and store it in @power.  It should return 0 on success, -E*
on failure.  This is currently used by thermal core to calculate the
maximum power that an actor can consume.

3. ::

	int power2state(struct thermal_cooling_device *cdev, u32 power,
			unsigned long *state);

@cdev:
	The `struct thermal_cooling_device` pointer
@power:
	power in milliwatts
@state:
	pointer in which to store the resulting state

Calculate a cooling device state that would make the device consume at
most @power mW and store it in @state.  It should return 0 on success,
-E* on failure.  This is currently used by the thermal core to convert
a given power set by the power allocator governor to a state that the
cooling device can set.  It is a function because this conversion may
depend on external factors that may change so this function should the
best conversion given "current circumstances".

Cooling device weights
----------------------

Weights are a mechanism to bias the allocation among cooling
devices.  They express the relative power efficiency of different
cooling devices.  Higher weight can be used to express higher power
efficiency.  Weighting is relative such that if each cooling device
has a weight of one they are considered equal.  This is particularly
useful in heterogeneous systems where two cooling devices may perform
the same kind of compute, but with different efficiency.  For example,
a system with two different types of processors.

If the thermal zone is registered using
`thermal_zone_device_register()` (i.e., platform code), then weights
are passed as part of the thermal zone's `thermal_bind_parameters`.
If the platform is registered using device tree, then they are passed
as the `contribution` property of each map in the `cooling-maps` node.

Limitations of the power allocator governor
===========================================

The power allocator governor's PID controller works best if there is a
periodic tick.  If you have a driver that calls
`thermal_zone_device_update()` (or anything that ends up calling the
governor's `throttle()` function) repetitively, the governor response
won't be very good.  Note that this is not particular to this
governor, step-wise will also misbehave if you call its throttle()
faster than the normal thermal framework tick (due to interrupts for
example) as it will overreact.

Energy Model requirements
=========================

Another important thing is the consistent scale of the power values
provided by the cooling devices. All of the cooling devices in a single
thermal zone should have power values reported either in milli-Watts
or scaled to the same 'abstract scale'.


code:
===================================
Generic Thermal Sysfs driver How To
===================================

Written by Sujith Thomas <sujith.thomas@intel.com>, Zhang Rui <rui.zhang@intel.com>

Updated: 2 January 2008

Copyright (c)  2008 Intel Corporation

0. Introduction
===============

The generic thermal sysfs provides a set of interfaces for thermal zone
devices (sensors) and thermal cooling devices (fan, processor...) to register
with the thermal management solution and to be a part of it.

This how-to focuses on enabling new thermal zone and cooling devices to
participate in thermal management.
This solution is platform independent and any type of thermal zone devices
and cooling devices should be able to make use of the infrastructure.

The main task of the thermal sysfs driver is to expose thermal zone attributes
as well as cooling device attributes to the user space.
An intelligent thermal management application can make decisions based on
inputs from thermal zone attributes (the current temperature and trip point
temperature) and throttle appropriate devices.

- `[0-*]`	denotes any positive number starting from 0
- `[1-*]`	denotes any positive number starting from 1

1. thermal sysfs driver interface functions
===========================================

1.1 thermal zone device interface
---------------------------------

    ::

	struct thermal_zone_device
	*thermal_zone_device_register(char *type,
				      int trips, int mask, void *devdata,
				      struct thermal_zone_device_ops *ops,
				      const struct thermal_zone_params *tzp,
				      int passive_delay, int polling_delay))

    This interface function adds a new thermal zone device (sensor) to
    /sys/class/thermal folder as `thermal_zone[0-*]`. It tries to bind all the
    thermal cooling devices registered at the same time.

    type:
	the thermal zone type.
    trips:
	the total number of trip points this thermal zone supports.
    mask:
	Bit string: If 'n'th bit is set, then trip point 'n' is writable.
    devdata:
	device private data
    ops:
	thermal zone device call-backs.

	.bind:
		bind the thermal zone device with a thermal cooling device.
	.unbind:
		unbind the thermal zone device with a thermal cooling device.
	.get_temp:
		get the current temperature of the thermal zone.
	.set_trips:
		    set the trip points window. Whenever the current temperature
		    is updated, the trip points immediately below and above the
		    current temperature are found.
	.get_mode:
		   get the current mode (enabled/disabled) of the thermal zone.

			- "enabled" means the kernel thermal management is
			  enabled.
			- "disabled" will prevent kernel thermal driver action
			  upon trip points so that user applications can take
			  charge of thermal management.
	.set_mode:
		set the mode (enabled/disabled) of the thermal zone.
	.get_trip_type:
		get the type of certain trip point.
	.get_trip_temp:
			get the temperature above which the certain trip point
			will be fired.
	.set_emul_temp:
			set the emulation temperature which helps in debugging
			different threshold temperature points.
    tzp:
	thermal zone platform parameters.
    passive_delay:
	number of milliseconds to wait between polls when
	performing passive cooling.
    polling_delay:
	number of milliseconds to wait between polls when checking
	whether trip points have been crossed (0 for interrupt driven systems).

    ::

	void thermal_zone_device_unregister(struct thermal_zone_device *tz)

    This interface function removes the thermal zone device.
    It deletes the corresponding entry from /sys/class/thermal folder and
    unbinds all the thermal cooling devices it uses.

	::

	   struct thermal_zone_device
	   *thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
				void *data,
				const struct thermal_zone_of_device_ops *ops)

	This interface adds a new sensor to a DT thermal zone.
	This function will search the list of thermal zones described in
	device tree and look for the zone that refer to the sensor device
	pointed by dev->of_node as temperature providers. For the zone
	pointing to the sensor node, the sensor will be added to the DT
	thermal zone device.

	The parameters for this interface are:

	dev:
			Device node of sensor containing valid node pointer in
			dev->of_node.
	sensor_id:
			a sensor identifier, in case the sensor IP has more
			than one sensors
	data:
			a private pointer (owned by the caller) that will be
			passed back, when a temperature reading is needed.
	ops:
			`struct thermal_zone_of_device_ops *`.

			==============  =======================================
			get_temp	a pointer to a function that reads the
					sensor temperature. This is mandatory
					callback provided by sensor driver.
			set_trips	a pointer to a function that sets a
					temperature window. When this window is
					left the driver must inform the thermal
					core via thermal_zone_device_update.
			get_trend 	a pointer to a function that reads the
					sensor temperature trend.
			set_emul_temp	a pointer to a function that sets
					sensor emulated temperature.
			==============  =======================================

	The thermal zone temperature is provided by the get_temp() function
	pointer of thermal_zone_of_device_ops. When called, it will
	have the private pointer @data back.

	It returns error pointer if fails otherwise valid thermal zone device
	handle. Caller should check the return handle with IS_ERR() for finding
	whether success or not.

	::

	    void thermal_zone_of_sensor_unregister(struct device *dev,
						   struct thermal_zone_device *tzd)

	This interface unregisters a sensor from a DT thermal zone which was
	successfully added by interface thermal_zone_of_sensor_register().
	This function removes the sensor callbacks and private data from the
	thermal zone device registered with thermal_zone_of_sensor_register()
	interface. It will also silent the zone by remove the .get_temp() and
	get_trend() thermal zone device callbacks.

	::

	  struct thermal_zone_device
	  *devm_thermal_zone_of_sensor_register(struct device *dev,
				int sensor_id,
				void *data,
				const struct thermal_zone_of_device_ops *ops)

	This interface is resource managed version of
	thermal_zone_of_sensor_register().

	All details of thermal_zone_of_sensor_register() described in
	section 1.1.3 is applicable here.

	The benefit of using this interface to register sensor is that it
	is not require to explicitly call thermal_zone_of_sensor_unregister()
	in error path or during driver unbinding as this is done by driver
	resource manager.

	::

		void devm_thermal_zone_of_sensor_unregister(struct device *dev,
						struct thermal_zone_device *tzd)

	This interface is resource managed version of
	thermal_zone_of_sensor_unregister().
	All details of thermal_zone_of_sensor_unregister() described in
	section 1.1.4 is applicable here.
	Normally this function will not need to be called and the resource
	management code will ensure that the resource is freed.

	::

		int thermal_zone_get_slope(struct thermal_zone_device *tz)

	This interface is used to read the slope attribute value
	for the thermal zone device, which might be useful for platform
	drivers for temperature calculations.

	::

		int thermal_zone_get_offset(struct thermal_zone_device *tz)

	This interface is used to read the offset attribute value
	for the thermal zone device, which might be useful for platform
	drivers for temperature calculations.

1.2 thermal cooling device interface
------------------------------------

    ::

	struct thermal_cooling_device
	*thermal_cooling_device_register(char *name,
			void *devdata, struct thermal_cooling_device_ops *)

    This interface function adds a new thermal cooling device (fan/processor/...)
    to /sys/class/thermal/ folder as `cooling_device[0-*]`. It tries to bind itself
    to all the thermal zone devices registered at the same time.

    name:
	the cooling device name.
    devdata:
	device private data.
    ops:
	thermal cooling devices call-backs.

	.get_max_state:
		get the Maximum throttle state of the cooling device.
	.get_cur_state:
		get the Currently requested throttle state of the
		cooling device.
	.set_cur_state:
		set the Current throttle state of the cooling device.

    ::

	void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

    This interface function removes the thermal cooling device.
    It deletes the corresponding entry from /sys/class/thermal folder and
    unbinds itself from all the thermal zone devices using it.

1.3 interface for binding a thermal zone device with a thermal cooling device
-----------------------------------------------------------------------------

    ::

	int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
		int trip, struct thermal_cooling_device *cdev,
		unsigned long upper, unsigned long lower, unsigned int weight);

    This interface function binds a thermal cooling device to a particular trip
    point of a thermal zone device.

    This function is usually called in the thermal zone device .bind callback.

    tz:
	  the thermal zone device
    cdev:
	  thermal cooling device
    trip:
	  indicates which trip point in this thermal zone the cooling device
	  is associated with.
    upper:
	  the Maximum cooling state for this trip point.
	  THERMAL_NO_LIMIT means no upper limit,
	  and the cooling device can be in max_state.
    lower:
	  the Minimum cooling state can be used for this trip point.
	  THERMAL_NO_LIMIT means no lower limit,
	  and the cooling device can be in cooling state 0.
    weight:
	  the influence of this cooling device in this thermal
	  zone.  See 1.4.1 below for more information.

    ::

	int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
				int trip, struct thermal_cooling_device *cdev);

    This interface function unbinds a thermal cooling device from a particular
    trip point of a thermal zone device. This function is usually called in
    the thermal zone device .unbind callback.

    tz:
	the thermal zone device
    cdev:
	thermal cooling device
    trip:
	indicates which trip point in this thermal zone the cooling device
	is associated with.

1.4 Thermal Zone Parameters
---------------------------

    ::

	struct thermal_bind_params

    This structure defines the following parameters that are used to bind
    a zone with a cooling device for a particular trip point.

    .cdev:
	     The cooling device pointer
    .weight:
	     The 'influence' of a particular cooling device on this
	     zone. This is relative to the rest of the cooling
	     devices. For example, if all cooling devices have a
	     weight of 1, then they all contribute the same. You can
	     use percentages if you want, but it's not mandatory. A
	     weight of 0 means that this cooling device doesn't
	     contribute to the cooling of this zone unless all cooling
	     devices have a weight of 0. If all weights are 0, then
	     they all contribute the same.
    .trip_mask:
	       This is a bit mask that gives the binding relation between
	       this thermal zone and cdev, for a particular trip point.
	       If nth bit is set, then the cdev and thermal zone are bound
	       for trip point n.
    .binding_limits:
		     This is an array of cooling state limits. Must have
		     exactly 2 * thermal_zone.number_of_trip_points. It is an
		     array consisting of tuples <lower-state upper-state> of
		     state limits. Each trip will be associated with one state
		     limit tuple when binding. A NULL pointer means
		     <THERMAL_NO_LIMITS THERMAL_NO_LIMITS> on all trips.
		     These limits are used when binding a cdev to a trip point.
    .match:
	    This call back returns success(0) if the 'tz and cdev' need to
	    be bound, as per platform data.

    ::

	struct thermal_zone_params

    This structure defines the platform level parameters for a thermal zone.
    This data, for each thermal zone should come from the platform layer.
    This is an optional feature where some platforms can choose not to
    provide this data.

    .governor_name:
	       Name of the thermal governor used for this zone
    .no_hwmon:
	       a boolean to indicate if the thermal to hwmon sysfs interface
	       is required. when no_hwmon == false, a hwmon sysfs interface
	       will be created. when no_hwmon == true, nothing will be done.
	       In case the thermal_zone_params is NULL, the hwmon interface
	       will be created (for backward compatibility).
    .num_tbps:
	       Number of thermal_bind_params entries for this zone
    .tbp:
	       thermal_bind_params entries

2. sysfs attributes structure
=============================

==	================
RO	read only value
WO	write only value
RW	read/write value
==	================

Thermal sysfs attributes will be represented under /sys/class/thermal.
Hwmon sysfs I/F extension is also available under /sys/class/hwmon
if hwmon is compiled in or built as a module.

Thermal zone device sys I/F, created once it's registered::

  /sys/class/thermal/thermal_zone[0-*]:
    |---type:			Type of the thermal zone
    |---temp:			Current temperature
    |---mode:			Working mode of the thermal zone
    |---policy:			Thermal governor used for this zone
    |---available_policies:	Available thermal governors for this zone
    |---trip_point_[0-*]_temp:	Trip point temperature
    |---trip_point_[0-*]_type:	Trip point type
    |---trip_point_[0-*]_hyst:	Hysteresis value for this trip point
    |---emul_temp:		Emulated temperature set node
    |---sustainable_power:      Sustainable dissipatable power
    |---k_po:                   Proportional term during temperature overshoot
    |---k_pu:                   Proportional term during temperature undershoot
    |---k_i:                    PID's integral term in the power allocator gov
    |---k_d:                    PID's derivative term in the power allocator
    |---integral_cutoff:        Offset above which errors are accumulated
    |---slope:                  Slope constant applied as linear extrapolation
    |---offset:                 Offset constant applied as linear extrapolation

Thermal cooling device sys I/F, created once it's registered::

  /sys/class/thermal/cooling_device[0-*]:
    |---type:			Type of the cooling device(processor/fan/...)
    |---max_state:		Maximum cooling state of the cooling device
    |---cur_state:		Current cooling state of the cooling device
    |---stats:			Directory containing cooling device's statistics
    |---stats/reset:		Writing any value resets the statistics
    |---stats/time_in_state_ms:	Time (msec) spent in various cooling states
    |---stats/total_trans:	Total number of times cooling state is changed
    |---stats/trans_table:	Cooling state transition table

Then next two dynamic attributes are created/removed in pairs. They represent
the relationship between a thermal zone and its associated cooling device.
They are created/removed for each successful execution of
thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device.

::

  /sys/class/thermal/thermal_zone[0-*]:
    |---cdev[0-*]:		[0-*]th cooling device in current thermal zone
    |---cdev[0-*]_trip_point:	Trip point that cdev[0-*] is associated with
    |---cdev[0-*]_weight:       Influence of the cooling device in
				this thermal zone

Besides the thermal zone device sysfs I/F and cooling device sysfs I/F,
the generic thermal driver also creates a hwmon sysfs I/F for each _type_
of thermal zone device. E.g. the generic thermal driver registers one hwmon
class device and build the associated hwmon sysfs I/F for all the registered
ACPI thermal zones.

Please read Documentation/ABI/testing/sysfs-class-thermal for thermal
zone and cooling device attribute details.

::

  /sys/class/hwmon/hwmon[0-*]:
    |---name:			The type of the thermal zone devices
    |---temp[1-*]_input:	The current temperature of thermal zone [1-*]
    |---temp[1-*]_critical:	The critical trip point of thermal zone [1-*]

Please read Documentation/hwmon/sysfs-interface.rst for additional information.

3. A simple implementation
==========================

ACPI thermal zone may support multiple trip points like critical, hot,
passive, active. If an ACPI thermal zone supports critical, passive,
active[0] and active[1] at the same time, it may register itself as a
thermal_zone_device (thermal_zone1) with 4 trip points in all.
It has one processor and one fan, which are both registered as
thermal_cooling_device. Both are considered to have the same
effectiveness in cooling the thermal zone.

If the processor is listed in _PSL method, and the fan is listed in _AL0
method, the sys I/F structure will be built like this::

 /sys/class/thermal:
  |thermal_zone1:
    |---type:			acpitz
    |---temp:			37000
    |---mode:			enabled
    |---policy:			step_wise
    |---available_policies:	step_wise fair_share
    |---trip_point_0_temp:	100000
    |---trip_point_0_type:	critical
    |---trip_point_1_temp:	80000
    |---trip_point_1_type:	passive
    |---trip_point_2_temp:	70000
    |---trip_point_2_type:	active0
    |---trip_point_3_temp:	60000
    |---trip_point_3_type:	active1
    |---cdev0:			--->/sys/class/thermal/cooling_device0
    |---cdev0_trip_point:	1	/* cdev0 can be used for passive */
    |---cdev0_weight:           1024
    |---cdev1:			--->/sys/class/thermal/cooling_device3
    |---cdev1_trip_point:	2	/* cdev1 can be used for active[0]*/
    |---cdev1_weight:           1024

  |cooling_device0:
    |---type:			Processor
    |---max_state:		8
    |---cur_state:		0

  |cooling_device3:
    |---type:			Fan
    |---max_state:		2
    |---cur_state:		0

 /sys/class/hwmon:
  |hwmon0:
    |---name:			acpitz
    |---temp1_input:		37000
    |---temp1_crit:		100000

4. Export Symbol APIs
=====================

4.1. get_tz_trend
-----------------

This function returns the trend of a thermal zone, i.e the rate of change
of temperature of the thermal zone. Ideally, the thermal sensor drivers
are supposed to implement the callback. If they don't, the thermal
framework calculated the trend by comparing the previous and the current
temperature values.

4.2. get_thermal_instance
-------------------------

This function returns the thermal_instance corresponding to a given
{thermal_zone, cooling_device, trip_point} combination. Returns NULL
if such an instance does not exist.

4.3. thermal_cdev_update
------------------------

This function serves as an arbitrator to set the state of a cooling
device. It sets the cooling device to the deepest cooling state if
possible.

5. thermal_emergency_poweroff
=============================

On an event of critical trip temperature crossing the thermal framework
shuts down the system by calling hw_protection_shutdown(). The
hw_protection_shutdown() first attempts to perform an orderly shutdown
but accepts a delay after which it proceeds doing a forced power-off
or as last resort an emergency_restart.

The delay should be carefully profiled so as to give adequate time for
orderly poweroff.

If the delay is set to 0 emergency poweroff will not be supported. So a
carefully profiled non-zero positive value is a must for emergency
poweroff to be triggered.


code:
===================================
Kernel driver: x86_pkg_temp_thermal
===================================

Supported chips:

* x86: with package level thermal management

(Verify using: CPUID.06H:EAX[bit 6] =1)

Authors: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

Reference
---------

Intel® 64 and IA-32 Architectures Software Developer’s Manual (Jan, 2013):
Chapter 14.6: PACKAGE LEVEL THERMAL MANAGEMENT

Description
-----------

This driver register CPU digital temperature package level sensor as a thermal
zone with maximum two user mode configurable trip points. Number of trip points
depends on the capability of the package. Once the trip point is violated,
user mode can receive notification via thermal notification mechanism and can
take any action to control temperature.

Threshold management
--------------------
Each package will register as a thermal zone under /sys/class/thermal.

Example::

	/sys/class/thermal/thermal_zone1

This contains two trip points:

- trip_point_0_temp
- trip_point_1_temp

User can set any temperature between 0 to TJ-Max temperature. Temperature units
are in milli-degree Celsius. Refer to "Documentation/driver-api/thermal/sysfs-api.rst" for
thermal sys-fs details.

Any value other than 0 in these trip points, can trigger thermal notifications.
Setting 0, stops sending thermal notifications.

Thermal notifications:
To get kobject-uevent notifications, set the thermal zone
policy to "user_space".

For example::

	echo -n "user_space" > policy


code:
.. SPDX-License-Identifier: GPL-2.0

===
TTY
===

Teletypewriter (TTY) layer takes care of all those serial devices. Including
the virtual ones like pseudoterminal (PTY).

TTY structures
==============

There are several major TTY structures. Every TTY device in a system has a
corresponding struct tty_port. These devices are maintained by a TTY driver
which is struct tty_driver. This structure describes the driver but also
contains a reference to operations which could be performed on the TTYs. It is
struct tty_operations. Then, upon open, a struct tty_struct is allocated and
lives until the final close. During this time, several callbacks from struct
tty_operations are invoked by the TTY layer.

Every character received by the kernel (both from devices and users) is passed
through a preselected :doc:`tty_ldisc` (in
short ldisc; in C, struct tty_ldisc_ops). Its task is to transform characters
as defined by a particular ldisc or by user too. The default one is n_tty,
implementing echoes, signal handling, jobs control, special characters
processing, and more. The transformed characters are passed further to
user/device, depending on the source.

In-detail description of the named TTY structures is in separate documents:

.. toctree::
   :maxdepth: 2

   tty_driver
   tty_port
   tty_struct
   tty_ldisc
   tty_buffer
   tty_internals

Writing TTY Driver
==================

Before one starts writing a TTY driver, they must consider
:doc:`Serial <../serial/driver>` and :doc:`USB Serial <../../usb/usb-serial>`
layers first. Drivers for serial devices can often use one of these specific
layers to implement a serial driver. Only special devices should be handled
directly by the TTY Layer. If you are about to write such a driver, read on.

A *typical* sequence a TTY driver performs is as follows:

#. Allocate and register a TTY driver (module init)
#. Create and register TTY devices as they are probed (probe function)
#. Handle TTY operations and events like interrupts (TTY core invokes the
   former, the device the latter)
#. Remove devices as they are going away (remove function)
#. Unregister and free the TTY driver (module exit)

Steps regarding driver, i.e. 1., 3., and 5. are described in detail in
:doc:`tty_driver`. For the other two (devices handling), look into
:doc:`tty_port`.

Other Documentation
===================

Miscellaneous documentation can be further found in these documents:

.. toctree::
   :maxdepth: 2

   moxa-smartio
   n_gsm
   n_tty