mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge a229327733 ("Merge tag 'printk-for-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux") into android-mainline
Steps on the way to 5.17-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I6e68b1f6037ff9acffe7352ff72921e3a9ab4aa0
This commit is contained in:
76
Documentation/devicetree/bindings/thermal/rzg2l-thermal.yaml
Normal file
76
Documentation/devicetree/bindings/thermal/rzg2l-thermal.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/thermal/rzg2l-thermal.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/G2L Thermal Sensor Unit
|
||||
|
||||
description:
|
||||
On RZ/G2L SoCs, the thermal sensor unit (TSU) measures the
|
||||
temperature(Tj) inside the LSI.
|
||||
|
||||
maintainers:
|
||||
- Biju Das <biju.das.jz@bp.renesas.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a07g044-tsu # RZ/G2{L,LC}
|
||||
- const: renesas,rzg2l-tsu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- power-domains
|
||||
- resets
|
||||
- "#thermal-sensor-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r9a07g044-cpg.h>
|
||||
|
||||
tsu: thermal@10059400 {
|
||||
compatible = "renesas,r9a07g044-tsu",
|
||||
"renesas,rzg2l-tsu";
|
||||
reg = <0x10059400 0x400>;
|
||||
clocks = <&cpg CPG_MOD R9A07G044_TSU_PCLK>;
|
||||
resets = <&cpg R9A07G044_TSU_PRESETN>;
|
||||
power-domains = <&cpg>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu-thermal {
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <1000>;
|
||||
thermal-sensors = <&tsu 0>;
|
||||
|
||||
trips {
|
||||
sensor_crit: sensor-crit {
|
||||
temperature = <125000>;
|
||||
hysteresis = <1000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -5,7 +5,7 @@
|
||||
Referencing hierarchical data nodes
|
||||
===================================
|
||||
|
||||
:Copyright: |copy| 2018 Intel Corporation
|
||||
:Copyright: |copy| 2018, 2021 Intel Corporation
|
||||
:Author: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
|
||||
ACPI in general allows referring to device objects in the tree only.
|
||||
@@ -13,9 +13,9 @@ Hierarchical data extension nodes may not be referred to directly, hence this
|
||||
document defines a scheme to implement such references.
|
||||
|
||||
A reference consist of the device object name followed by one or more
|
||||
hierarchical data extension [1] keys. Specifically, the hierarchical data
|
||||
extension node which is referred to by the key shall lie directly under the
|
||||
parent object i.e. either the device object or another hierarchical data
|
||||
hierarchical data extension [dsd-guide] keys. Specifically, the hierarchical
|
||||
data extension node which is referred to by the key shall lie directly under
|
||||
the parent object i.e. either the device object or another hierarchical data
|
||||
extension node.
|
||||
|
||||
The keys in the hierarchical data nodes shall consist of the name of the node,
|
||||
@@ -33,7 +33,7 @@ extension key.
|
||||
Example
|
||||
=======
|
||||
|
||||
In the ASL snippet below, the "reference" _DSD property [2] contains a
|
||||
In the ASL snippet below, the "reference" _DSD property contains a
|
||||
device object reference to DEV0 and under that device object, a
|
||||
hierarchical data extension key "node@1" referring to the NOD1 object
|
||||
and lastly, a hierarchical data extension key "anothernode" referring to
|
||||
@@ -52,12 +52,14 @@ the ANOD object which is also the final target node of the reference.
|
||||
Name (NOD0, Package() {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "reg", 0 },
|
||||
Package () { "random-property", 3 },
|
||||
}
|
||||
})
|
||||
Name (NOD1, Package() {
|
||||
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
|
||||
Package () {
|
||||
Package () { "reg", 1 },
|
||||
Package () { "anothernode", "ANOD" },
|
||||
}
|
||||
})
|
||||
@@ -74,7 +76,11 @@ the ANOD object which is also the final target node of the reference.
|
||||
Name (_DSD, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "reference", ^DEV0, "node@1", "anothernode" },
|
||||
Package () {
|
||||
"reference", Package () {
|
||||
^DEV0, "node@1", "anothernode"
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -85,10 +91,6 @@ Documentation/firmware-guide/acpi/dsd/graph.rst.
|
||||
References
|
||||
==========
|
||||
|
||||
[1] Hierarchical Data Extension UUID For _DSD.
|
||||
<https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf>,
|
||||
referenced 2018-07-17.
|
||||
|
||||
[2] Device Properties UUID For _DSD.
|
||||
<https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf>,
|
||||
referenced 2016-10-04.
|
||||
[dsd-guide] DSD Guide.
|
||||
https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.adoc, referenced
|
||||
2021-11-30.
|
||||
|
||||
@@ -7,11 +7,11 @@ Graphs
|
||||
_DSD
|
||||
====
|
||||
|
||||
_DSD (Device Specific Data) [7] is a predefined ACPI device
|
||||
_DSD (Device Specific Data) [dsd-guide] is a predefined ACPI device
|
||||
configuration object that can be used to convey information on
|
||||
hardware features which are not specifically covered by the ACPI
|
||||
specification [1][6]. There are two _DSD extensions that are relevant
|
||||
for graphs: property [4] and hierarchical data extensions [5]. The
|
||||
specification [acpi]. There are two _DSD extensions that are relevant
|
||||
for graphs: property [dsd-guide] and hierarchical data extensions. The
|
||||
property extension provides generic key-value pairs whereas the
|
||||
hierarchical data extension supports nodes with references to other
|
||||
nodes, forming a tree. The nodes in the tree may contain properties as
|
||||
@@ -36,8 +36,9 @@ Ports and endpoints
|
||||
===================
|
||||
|
||||
The port and endpoint concepts are very similar to those in Devicetree
|
||||
[3]. A port represents an interface in a device, and an endpoint
|
||||
represents a connection to that interface.
|
||||
[devicetree, graph-bindings]. A port represents an interface in a device, and
|
||||
an endpoint represents a connection to that interface. Also see [data-node-ref]
|
||||
for generic data node references.
|
||||
|
||||
All port nodes are located under the device's "_DSD" node in the hierarchical
|
||||
data extension tree. The data extension related to each port node must begin
|
||||
@@ -153,25 +154,20 @@ the "ISP" device and vice versa.
|
||||
References
|
||||
==========
|
||||
|
||||
[1] _DSD (Device Specific Data) Implementation Guide.
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel-1_1.htm,
|
||||
referenced 2016-10-03.
|
||||
[acpi] Advanced Configuration and Power Interface Specification.
|
||||
https://uefi.org/specifications/ACPI/6.4/, referenced 2021-11-30.
|
||||
|
||||
[2] Devicetree. https://www.devicetree.org, referenced 2016-10-03.
|
||||
[data-node-ref] Documentation/firmware-guide/acpi/dsd/data-node-references.rst
|
||||
|
||||
[3] Documentation/devicetree/bindings/graph.txt
|
||||
[devicetree] Devicetree. https://www.devicetree.org, referenced 2016-10-03.
|
||||
|
||||
[4] Device Properties UUID For _DSD.
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf,
|
||||
referenced 2016-10-04.
|
||||
[dsd-guide] DSD Guide.
|
||||
https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.adoc, referenced
|
||||
2021-11-30.
|
||||
|
||||
[5] Hierarchical Data Extension UUID For _DSD.
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf,
|
||||
referenced 2016-10-04.
|
||||
|
||||
[6] Advanced Configuration and Power Interface Specification.
|
||||
https://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf,
|
||||
referenced 2016-10-04.
|
||||
|
||||
[7] _DSD Device Properties Usage Rules.
|
||||
[dsd-rules] _DSD Device Properties Usage Rules.
|
||||
Documentation/firmware-guide/acpi/DSD-properties-rules.rst
|
||||
|
||||
[graph-bindings] Common bindings for device graphs (Devicetree).
|
||||
https://github.com/devicetree-org/dt-schema/blob/main/schemas/graph.yaml,
|
||||
referenced 2021-11-30.
|
||||
|
||||
@@ -5,19 +5,20 @@
|
||||
Describing and referring to LEDs in ACPI
|
||||
========================================
|
||||
|
||||
Individual LEDs are described by hierarchical data extension [6] nodes under the
|
||||
Individual LEDs are described by hierarchical data extension [5] nodes under the
|
||||
device node, the LED driver chip. The "reg" property in the LED specific nodes
|
||||
tells the numerical ID of each individual LED output to which the LEDs are
|
||||
connected. [3] The hierarchical data nodes are named "led@X", where X is the
|
||||
connected. [leds] The hierarchical data nodes are named "led@X", where X is the
|
||||
number of the LED output.
|
||||
|
||||
Referring to LEDs in Device tree is documented in [4], in "flash-leds" property
|
||||
documentation. In short, LEDs are directly referred to by using phandles.
|
||||
Referring to LEDs in Device tree is documented in [video-interfaces], in
|
||||
"flash-leds" property documentation. In short, LEDs are directly referred to by
|
||||
using phandles.
|
||||
|
||||
While Device tree allows referring to any node in the tree[1], in ACPI
|
||||
references are limited to device nodes only [2]. For this reason using the same
|
||||
mechanism on ACPI is not possible. A mechanism to refer to non-device ACPI nodes
|
||||
is documented in [7].
|
||||
While Device tree allows referring to any node in the tree [devicetree], in
|
||||
ACPI references are limited to device nodes only [acpi]. For this reason using
|
||||
the same mechanism on ACPI is not possible. A mechanism to refer to non-device
|
||||
ACPI nodes is documented in [data-node-ref].
|
||||
|
||||
ACPI allows (as does DT) using integer arguments after the reference. A
|
||||
combination of the LED driver device reference and an integer argument,
|
||||
@@ -90,22 +91,17 @@ where
|
||||
References
|
||||
==========
|
||||
|
||||
[1] Device tree. https://www.devicetree.org, referenced 2019-02-21.
|
||||
[acpi] Advanced Configuration and Power Interface Specification.
|
||||
https://uefi.org/specifications/ACPI/6.4/, referenced 2021-11-30.
|
||||
|
||||
[2] Advanced Configuration and Power Interface Specification.
|
||||
https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf,
|
||||
referenced 2019-02-21.
|
||||
[data-node-ref] Documentation/firmware-guide/acpi/dsd/data-node-references.rst
|
||||
|
||||
[3] Documentation/devicetree/bindings/leds/common.txt
|
||||
[devicetree] Devicetree. https://www.devicetree.org, referenced 2019-02-21.
|
||||
|
||||
[4] Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
[dsd-guide] DSD Guide.
|
||||
https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.adoc, referenced
|
||||
2021-11-30.
|
||||
|
||||
[5] Device Properties UUID For _DSD.
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf,
|
||||
referenced 2019-02-21.
|
||||
[leds] Documentation/devicetree/bindings/leds/common.yaml
|
||||
|
||||
[6] Hierarchical Data Extension UUID For _DSD.
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf,
|
||||
referenced 2019-02-21.
|
||||
|
||||
[7] Documentation/firmware-guide/acpi/dsd/data-node-references.rst
|
||||
[video-interfaces] Documentation/devicetree/bindings/media/video-interfaces.yaml
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
MDIO bus and PHYs in ACPI
|
||||
=========================
|
||||
|
||||
The PHYs on an MDIO bus [1] are probed and registered using
|
||||
The PHYs on an MDIO bus [phy] are probed and registered using
|
||||
fwnode_mdiobus_register_phy().
|
||||
|
||||
Later, for connecting these PHYs to their respective MACs, the PHYs registered
|
||||
on the MDIO bus have to be referenced.
|
||||
|
||||
This document introduces two _DSD properties that are to be used
|
||||
for connecting PHYs on the MDIO bus [3] to the MAC layer.
|
||||
for connecting PHYs on the MDIO bus [dsd-properties-rules] to the MAC layer.
|
||||
|
||||
These properties are defined in accordance with the "Device
|
||||
Properties UUID For _DSD" [2] document and the
|
||||
Properties UUID For _DSD" [dsd-guide] document and the
|
||||
daffd814-6eba-4d8c-8a91-bc9bbf4aa301 UUID must be used in the Device
|
||||
Data Descriptors containing them.
|
||||
|
||||
@@ -48,22 +48,22 @@ as device object references (e.g. \_SB.MDI0.PHY1).
|
||||
phy-mode
|
||||
--------
|
||||
The "phy-mode" _DSD property is used to describe the connection to
|
||||
the PHY. The valid values for "phy-mode" are defined in [4].
|
||||
the PHY. The valid values for "phy-mode" are defined in [ethernet-controller].
|
||||
|
||||
managed
|
||||
-------
|
||||
Optional property, which specifies the PHY management type.
|
||||
The valid values for "managed" are defined in [4].
|
||||
The valid values for "managed" are defined in [ethernet-controller].
|
||||
|
||||
fixed-link
|
||||
----------
|
||||
The "fixed-link" is described by a data-only subnode of the
|
||||
MAC port, which is linked in the _DSD package via
|
||||
hierarchical data extension (UUID dbb8e3e6-5886-4ba6-8795-1319f52a966b
|
||||
in accordance with [5] "_DSD Implementation Guide" document).
|
||||
in accordance with [dsd-guide] "_DSD Implementation Guide" document).
|
||||
The subnode should comprise a required property ("speed") and
|
||||
possibly the optional ones - complete list of parameters and
|
||||
their values are specified in [4].
|
||||
their values are specified in [ethernet-controller].
|
||||
|
||||
The following ASL example illustrates the usage of these properties.
|
||||
|
||||
@@ -188,12 +188,14 @@ MAC node example with a "fixed-link" subnode.
|
||||
References
|
||||
==========
|
||||
|
||||
[1] Documentation/networking/phy.rst
|
||||
[phy] Documentation/networking/phy.rst
|
||||
|
||||
[2] https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
|
||||
[dsd-properties-rules]
|
||||
Documentation/firmware-guide/acpi/DSD-properties-rules.rst
|
||||
|
||||
[3] Documentation/firmware-guide/acpi/DSD-properties-rules.rst
|
||||
[ethernet-controller]
|
||||
Documentation/devicetree/bindings/net/ethernet-controller.yaml
|
||||
|
||||
[4] Documentation/devicetree/bindings/net/ethernet-controller.yaml
|
||||
|
||||
[5] https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.pdf
|
||||
[dsd-guide] DSD Guide.
|
||||
https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.adoc, referenced
|
||||
2021-11-30.
|
||||
|
||||
10
MAINTAINERS
10
MAINTAINERS
@@ -15403,6 +15403,7 @@ M: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
R: Steven Rostedt <rostedt@goodmis.org>
|
||||
R: John Ogness <john.ogness@linutronix.de>
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git
|
||||
F: include/linux/printk.h
|
||||
F: kernel/printk/
|
||||
|
||||
@@ -17741,12 +17742,17 @@ F: drivers/firmware/arm_sdei.c
|
||||
F: include/linux/arm_sdei.h
|
||||
F: include/uapi/linux/arm_sdei.h
|
||||
|
||||
SOFTWARE NODES
|
||||
SOFTWARE NODES AND DEVICE PROPERTIES
|
||||
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
R: Daniel Scally <djrscally@gmail.com>
|
||||
R: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
R: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
L: linux-acpi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/base/property.c
|
||||
F: drivers/base/swnode.c
|
||||
F: include/linux/fwnode.h
|
||||
F: include/linux/property.h
|
||||
|
||||
SOFTWARE RAID (Multiple Disks) SUPPORT
|
||||
M: Song Liu <song@kernel.org>
|
||||
@@ -20527,7 +20533,7 @@ M: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git
|
||||
F: Documentation/core-api/printk-formats.rst
|
||||
F: lib/test_printf.c
|
||||
F: lib/test_scanf.c
|
||||
|
||||
@@ -3581,7 +3581,6 @@ void device_del(struct device *dev)
|
||||
device_pm_remove(dev);
|
||||
driver_deferred_probe_del(dev);
|
||||
device_platform_notify_remove(dev);
|
||||
device_remove_properties(dev);
|
||||
device_links_purge(dev);
|
||||
|
||||
if (dev->bus)
|
||||
|
||||
@@ -507,54 +507,6 @@ struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_find_reference);
|
||||
|
||||
/**
|
||||
* device_remove_properties - Remove properties from a device object.
|
||||
* @dev: Device whose properties to remove.
|
||||
*
|
||||
* The function removes properties previously associated to the device
|
||||
* firmware node with device_add_properties(). Memory allocated to the
|
||||
* properties will also be released.
|
||||
*/
|
||||
void device_remove_properties(struct device *dev)
|
||||
{
|
||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||
|
||||
if (!fwnode)
|
||||
return;
|
||||
|
||||
if (is_software_node(fwnode->secondary)) {
|
||||
fwnode_remove_software_node(fwnode->secondary);
|
||||
set_secondary_fwnode(dev, NULL);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_remove_properties);
|
||||
|
||||
/**
|
||||
* device_add_properties - Add a collection of properties to a device object.
|
||||
* @dev: Device to add properties to.
|
||||
* @properties: Collection of properties to add.
|
||||
*
|
||||
* Associate a collection of device properties represented by @properties with
|
||||
* @dev. The function takes a copy of @properties.
|
||||
*
|
||||
* WARNING: The callers should not use this function if it is known that there
|
||||
* is no real firmware node associated with @dev! In that case the callers
|
||||
* should create a software node and assign it to @dev directly.
|
||||
*/
|
||||
int device_add_properties(struct device *dev,
|
||||
const struct property_entry *properties)
|
||||
{
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
fwnode = fwnode_create_software_node(properties, NULL);
|
||||
if (IS_ERR(fwnode))
|
||||
return PTR_ERR(fwnode);
|
||||
|
||||
set_secondary_fwnode(dev, fwnode);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_add_properties);
|
||||
|
||||
/**
|
||||
* fwnode_get_name - Return the name of a node
|
||||
* @fwnode: The firmware node
|
||||
@@ -1059,43 +1011,17 @@ fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
|
||||
|
||||
/**
|
||||
* fwnode_graph_get_remote_node - get remote parent node for given port/endpoint
|
||||
* @fwnode: pointer to parent fwnode_handle containing graph port/endpoint
|
||||
* @port_id: identifier of the parent port node
|
||||
* @endpoint_id: identifier of the endpoint node
|
||||
*
|
||||
* Return: Remote fwnode handle associated with remote endpoint node linked
|
||||
* to @node. Use fwnode_node_put() on it when done.
|
||||
*/
|
||||
struct fwnode_handle *
|
||||
fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port_id,
|
||||
u32 endpoint_id)
|
||||
static bool fwnode_graph_remote_available(struct fwnode_handle *ep)
|
||||
{
|
||||
struct fwnode_handle *endpoint = NULL;
|
||||
struct fwnode_handle *dev_node;
|
||||
bool available;
|
||||
|
||||
while ((endpoint = fwnode_graph_get_next_endpoint(fwnode, endpoint))) {
|
||||
struct fwnode_endpoint fwnode_ep;
|
||||
struct fwnode_handle *remote;
|
||||
int ret;
|
||||
dev_node = fwnode_graph_get_remote_port_parent(ep);
|
||||
available = fwnode_device_is_available(dev_node);
|
||||
fwnode_handle_put(dev_node);
|
||||
|
||||
ret = fwnode_graph_parse_endpoint(endpoint, &fwnode_ep);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
if (fwnode_ep.port != port_id || fwnode_ep.id != endpoint_id)
|
||||
continue;
|
||||
|
||||
remote = fwnode_graph_get_remote_port_parent(endpoint);
|
||||
if (!remote)
|
||||
return NULL;
|
||||
|
||||
return fwnode_device_is_available(remote) ? remote : NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return available;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node);
|
||||
|
||||
/**
|
||||
* fwnode_graph_get_endpoint_by_id - get endpoint by port and endpoint numbers
|
||||
@@ -1111,8 +1037,8 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node);
|
||||
* has not been found, look for the closest endpoint ID greater than the
|
||||
* specified one and return the endpoint that corresponds to it, if present.
|
||||
*
|
||||
* Do not return endpoints that belong to disabled devices, unless
|
||||
* FWNODE_GRAPH_DEVICE_DISABLED is passed in @flags.
|
||||
* Does not return endpoints that belong to disabled devices or endpoints that
|
||||
* are unconnected, unless FWNODE_GRAPH_DEVICE_DISABLED is passed in @flags.
|
||||
*
|
||||
* The returned endpoint needs to be released by calling fwnode_handle_put() on
|
||||
* it when it is not needed any more.
|
||||
@@ -1121,25 +1047,17 @@ struct fwnode_handle *
|
||||
fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
|
||||
u32 port, u32 endpoint, unsigned long flags)
|
||||
{
|
||||
struct fwnode_handle *ep = NULL, *best_ep = NULL;
|
||||
struct fwnode_handle *ep, *best_ep = NULL;
|
||||
unsigned int best_ep_id = 0;
|
||||
bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT;
|
||||
bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED);
|
||||
|
||||
while ((ep = fwnode_graph_get_next_endpoint(fwnode, ep))) {
|
||||
fwnode_graph_for_each_endpoint(fwnode, ep) {
|
||||
struct fwnode_endpoint fwnode_ep = { 0 };
|
||||
int ret;
|
||||
|
||||
if (enabled_only) {
|
||||
struct fwnode_handle *dev_node;
|
||||
bool available;
|
||||
|
||||
dev_node = fwnode_graph_get_remote_port_parent(ep);
|
||||
available = fwnode_device_is_available(dev_node);
|
||||
fwnode_handle_put(dev_node);
|
||||
if (!available)
|
||||
continue;
|
||||
}
|
||||
if (enabled_only && !fwnode_graph_remote_available(ep))
|
||||
continue;
|
||||
|
||||
ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep);
|
||||
if (ret < 0)
|
||||
@@ -1172,6 +1090,31 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
|
||||
|
||||
/**
|
||||
* fwnode_graph_get_endpoint_count - Count endpoints on a device node
|
||||
* @fwnode: The node related to a device
|
||||
* @flags: fwnode lookup flags
|
||||
* Count endpoints in a device node.
|
||||
*
|
||||
* If FWNODE_GRAPH_DEVICE_DISABLED flag is specified, also unconnected endpoints
|
||||
* and endpoints connected to disabled devices are counted.
|
||||
*/
|
||||
unsigned int fwnode_graph_get_endpoint_count(struct fwnode_handle *fwnode,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct fwnode_handle *ep;
|
||||
unsigned int count = 0;
|
||||
|
||||
fwnode_graph_for_each_endpoint(fwnode, ep) {
|
||||
if (flags & FWNODE_GRAPH_DEVICE_DISABLED ||
|
||||
fwnode_graph_remote_available(ep))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_count);
|
||||
|
||||
/**
|
||||
* fwnode_graph_parse_endpoint - parse common endpoint node properties
|
||||
* @fwnode: pointer to endpoint fwnode_handle
|
||||
@@ -1206,8 +1149,10 @@ fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
|
||||
|
||||
fwnode_graph_for_each_endpoint(fwnode, ep) {
|
||||
node = fwnode_graph_get_remote_port_parent(ep);
|
||||
if (!fwnode_device_is_available(node))
|
||||
if (!fwnode_device_is_available(node)) {
|
||||
fwnode_handle_put(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = match(node, con_id, data);
|
||||
fwnode_handle_put(node);
|
||||
|
||||
@@ -529,7 +529,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
|
||||
return -ENOENT;
|
||||
|
||||
if (nargs_prop) {
|
||||
error = property_entry_read_int_array(swnode->node->properties,
|
||||
error = property_entry_read_int_array(ref->node->properties,
|
||||
nargs_prop, sizeof(u32),
|
||||
&nargs_prop_val, 1);
|
||||
if (error)
|
||||
|
||||
@@ -1850,7 +1850,7 @@ static void quirk_huawei_pcie_sva(struct pci_dev *pdev)
|
||||
* can set it directly.
|
||||
*/
|
||||
if (!pdev->dev.of_node &&
|
||||
device_add_properties(&pdev->dev, properties))
|
||||
device_create_managed_software_node(&pdev->dev, properties, NULL))
|
||||
pci_warn(pdev, "could not add stall property");
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_HUAWEI, 0xa250, quirk_huawei_pcie_sva);
|
||||
|
||||
@@ -1845,7 +1845,6 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
|
||||
struct tegra_vi_channel *chan;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(vi->dev);
|
||||
int ret;
|
||||
struct fwnode_handle *remote = NULL;
|
||||
|
||||
/*
|
||||
* Walk the links to parse the full graph. Each channel will have
|
||||
@@ -1857,11 +1856,16 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
|
||||
* next channels.
|
||||
*/
|
||||
list_for_each_entry(chan, &vi->vi_chans, list) {
|
||||
remote = fwnode_graph_get_remote_node(fwnode, chan->portnos[0],
|
||||
0);
|
||||
if (!remote)
|
||||
struct fwnode_handle *ep, *remote;
|
||||
|
||||
ep = fwnode_graph_get_endpoint_by_id(fwnode,
|
||||
chan->portnos[0], 0, 0);
|
||||
if (!ep)
|
||||
continue;
|
||||
|
||||
remote = fwnode_graph_get_remote_port_parent(ep);
|
||||
fwnode_handle_put(ep);
|
||||
|
||||
ret = tegra_vi_graph_parse_one(chan, remote);
|
||||
fwnode_handle_put(remote);
|
||||
if (ret < 0 || list_empty(&chan->notifier.asd_list))
|
||||
|
||||
@@ -354,6 +354,15 @@ config RCAR_GEN3_THERMAL
|
||||
Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
|
||||
the Linux thermal framework.
|
||||
|
||||
config RZG2L_THERMAL
|
||||
tristate "Renesas RZ/G2L thermal driver"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
depends on OF
|
||||
help
|
||||
Enable this to plug the RZ/G2L thermal sensor driver into the Linux
|
||||
thermal framework.
|
||||
|
||||
config KIRKWOOD_THERMAL
|
||||
tristate "Temperature sensor on Marvell Kirkwood SoCs"
|
||||
depends on MACH_KIRKWOOD || COMPILE_TEST
|
||||
|
||||
@@ -37,6 +37,7 @@ obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
|
||||
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
|
||||
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
|
||||
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
|
||||
obj-$(CONFIG_RZG2L_THERMAL) += rzg2l_thermal.o
|
||||
obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
|
||||
obj-y += samsung/
|
||||
obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define TPS 0x4
|
||||
#define TRITSR 0x20 /* TMU immediate temp */
|
||||
|
||||
#define TER_ADC_PD BIT(30)
|
||||
#define TER_EN BIT(31)
|
||||
#define TRITSR_TEMP0_VAL_MASK 0xff
|
||||
#define TRITSR_TEMP1_VAL_MASK 0xff0000
|
||||
@@ -113,6 +114,8 @@ static void imx8mm_tmu_enable(struct imx8mm_tmu *tmu, bool enable)
|
||||
|
||||
val = readl_relaxed(tmu->base + TER);
|
||||
val = enable ? (val | TER_EN) : (val & ~TER_EN);
|
||||
if (tmu->socdata->version == TMU_VER2)
|
||||
val = enable ? (val & ~TER_ADC_PD) : (val | TER_ADC_PD);
|
||||
writel_relaxed(val, tmu->base + TER);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#define REG_SET 0x4
|
||||
#define REG_CLR 0x8
|
||||
@@ -194,6 +195,7 @@ static struct thermal_soc_data thermal_imx7d_data = {
|
||||
};
|
||||
|
||||
struct imx_thermal_data {
|
||||
struct device *dev;
|
||||
struct cpufreq_policy *policy;
|
||||
struct thermal_zone_device *tz;
|
||||
struct thermal_cooling_device *cdev;
|
||||
@@ -252,44 +254,15 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
const struct thermal_soc_data *soc_data = data->socdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
unsigned int n_meas;
|
||||
bool wait, run_measurement;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
run_measurement = !data->irq_enabled;
|
||||
if (!run_measurement) {
|
||||
/* Check if a measurement is currently in progress */
|
||||
regmap_read(map, soc_data->temp_data, &val);
|
||||
wait = !(val & soc_data->temp_valid_mask);
|
||||
} else {
|
||||
/*
|
||||
* Every time we measure the temperature, we will power on the
|
||||
* temperature sensor, enable measurements, take a reading,
|
||||
* disable measurements, power off the temperature sensor.
|
||||
*/
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->power_down_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->measure_temp_mask);
|
||||
|
||||
wait = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to the temp sensor designers, it may require up to ~17us
|
||||
* to complete a measurement.
|
||||
*/
|
||||
if (wait)
|
||||
usleep_range(20, 50);
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap_read(map, soc_data->temp_data, &val);
|
||||
|
||||
if (run_measurement) {
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->measure_temp_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->power_down_mask);
|
||||
}
|
||||
|
||||
if ((val & soc_data->temp_valid_mask) == 0) {
|
||||
dev_dbg(&tz->device, "temp measurement never finished\n");
|
||||
return -EAGAIN;
|
||||
@@ -328,6 +301,8 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
enable_irq(data->irq);
|
||||
}
|
||||
|
||||
pm_runtime_put(data->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -335,24 +310,16 @@ static int imx_change_mode(struct thermal_zone_device *tz,
|
||||
enum thermal_device_mode mode)
|
||||
{
|
||||
struct imx_thermal_data *data = tz->devdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
const struct thermal_soc_data *soc_data = data->socdata;
|
||||
|
||||
if (mode == THERMAL_DEVICE_ENABLED) {
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->power_down_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->measure_temp_mask);
|
||||
pm_runtime_get(data->dev);
|
||||
|
||||
if (!data->irq_enabled) {
|
||||
data->irq_enabled = true;
|
||||
enable_irq(data->irq);
|
||||
}
|
||||
} else {
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->measure_temp_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->power_down_mask);
|
||||
pm_runtime_put(data->dev);
|
||||
|
||||
if (data->irq_enabled) {
|
||||
disable_irq(data->irq);
|
||||
@@ -393,6 +360,11 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
|
||||
int temp)
|
||||
{
|
||||
struct imx_thermal_data *data = tz->devdata;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* do not allow changing critical threshold */
|
||||
if (trip == IMX_TRIP_CRITICAL)
|
||||
@@ -406,6 +378,8 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
|
||||
|
||||
imx_set_alarm_temp(data, temp);
|
||||
|
||||
pm_runtime_put(data->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -681,6 +655,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->dev = &pdev->dev;
|
||||
|
||||
map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
|
||||
if (IS_ERR(map)) {
|
||||
ret = PTR_ERR(map);
|
||||
@@ -800,6 +776,16 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||
data->socdata->power_down_mask);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->measure_temp_mask);
|
||||
/* After power up, we need a delay before first access can be done. */
|
||||
usleep_range(20, 50);
|
||||
|
||||
/* the core was configured and enabled just before */
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(data->dev);
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
goto disable_runtime_pm;
|
||||
|
||||
data->irq_enabled = true;
|
||||
ret = thermal_zone_device_enable(data->tz);
|
||||
@@ -814,10 +800,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||
goto thermal_zone_unregister;
|
||||
}
|
||||
|
||||
pm_runtime_put(data->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
thermal_zone_unregister:
|
||||
thermal_zone_device_unregister(data->tz);
|
||||
disable_runtime_pm:
|
||||
pm_runtime_put_noidle(data->dev);
|
||||
pm_runtime_disable(data->dev);
|
||||
clk_disable:
|
||||
clk_disable_unprepare(data->thermal_clk);
|
||||
legacy_cleanup:
|
||||
@@ -829,13 +820,9 @@ legacy_cleanup:
|
||||
static int imx_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_thermal_data *data = platform_get_drvdata(pdev);
|
||||
struct regmap *map = data->tempmon;
|
||||
|
||||
/* Disable measurements */
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->power_down_mask);
|
||||
if (!IS_ERR(data->thermal_clk))
|
||||
clk_disable_unprepare(data->thermal_clk);
|
||||
pm_runtime_put_noidle(data->dev);
|
||||
pm_runtime_disable(data->dev);
|
||||
|
||||
thermal_zone_device_unregister(data->tz);
|
||||
imx_thermal_unregister_legacy_cooling(data);
|
||||
@@ -858,9 +845,8 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev)
|
||||
ret = thermal_zone_device_disable(data->tz);
|
||||
if (ret)
|
||||
return ret;
|
||||
clk_disable_unprepare(data->thermal_clk);
|
||||
|
||||
return 0;
|
||||
return pm_runtime_force_suspend(data->dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused imx_thermal_resume(struct device *dev)
|
||||
@@ -868,19 +854,70 @@ static int __maybe_unused imx_thermal_resume(struct device *dev)
|
||||
struct imx_thermal_data *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(data->thermal_clk);
|
||||
ret = pm_runtime_force_resume(data->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Enabled thermal sensor after resume */
|
||||
ret = thermal_zone_device_enable(data->tz);
|
||||
return thermal_zone_device_enable(data->tz);
|
||||
}
|
||||
|
||||
static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct imx_thermal_data *data = dev_get_drvdata(dev);
|
||||
const struct thermal_soc_data *socdata = data->socdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
|
||||
socdata->measure_temp_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
|
||||
socdata->power_down_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_disable_unprepare(data->thermal_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
|
||||
imx_thermal_suspend, imx_thermal_resume);
|
||||
static int __maybe_unused imx_thermal_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct imx_thermal_data *data = dev_get_drvdata(dev);
|
||||
const struct thermal_soc_data *socdata = data->socdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(data->thermal_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
|
||||
socdata->power_down_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
|
||||
socdata->measure_temp_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* According to the temp sensor designers, it may require up to ~17us
|
||||
* to complete a measurement.
|
||||
*/
|
||||
usleep_range(20, 50);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops imx_thermal_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)
|
||||
SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend,
|
||||
imx_thermal_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver imx_thermal = {
|
||||
.driver = {
|
||||
|
||||
@@ -250,8 +250,9 @@ static int fill_art(char __user *ubuf)
|
||||
get_single_name(arts[i].source, art_user[i].source_device);
|
||||
get_single_name(arts[i].target, art_user[i].target_device);
|
||||
/* copy the rest int data in addition to source and target */
|
||||
memcpy(&art_user[i].weight, &arts[i].weight,
|
||||
sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2));
|
||||
BUILD_BUG_ON(sizeof(art_user[i].data) !=
|
||||
sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2));
|
||||
memcpy(&art_user[i].data, &arts[i].data, sizeof(art_user[i].data));
|
||||
}
|
||||
|
||||
if (copy_to_user(ubuf, art_user, art_len))
|
||||
|
||||
@@ -17,17 +17,19 @@
|
||||
struct art {
|
||||
acpi_handle source;
|
||||
acpi_handle target;
|
||||
u64 weight;
|
||||
u64 ac0_max;
|
||||
u64 ac1_max;
|
||||
u64 ac2_max;
|
||||
u64 ac3_max;
|
||||
u64 ac4_max;
|
||||
u64 ac5_max;
|
||||
u64 ac6_max;
|
||||
u64 ac7_max;
|
||||
u64 ac8_max;
|
||||
u64 ac9_max;
|
||||
struct_group(data,
|
||||
u64 weight;
|
||||
u64 ac0_max;
|
||||
u64 ac1_max;
|
||||
u64 ac2_max;
|
||||
u64 ac3_max;
|
||||
u64 ac4_max;
|
||||
u64 ac5_max;
|
||||
u64 ac6_max;
|
||||
u64 ac7_max;
|
||||
u64 ac8_max;
|
||||
u64 ac9_max;
|
||||
);
|
||||
} __packed;
|
||||
|
||||
struct trt {
|
||||
@@ -47,17 +49,19 @@ union art_object {
|
||||
struct {
|
||||
char source_device[8]; /* ACPI single name */
|
||||
char target_device[8]; /* ACPI single name */
|
||||
u64 weight;
|
||||
u64 ac0_max_level;
|
||||
u64 ac1_max_level;
|
||||
u64 ac2_max_level;
|
||||
u64 ac3_max_level;
|
||||
u64 ac4_max_level;
|
||||
u64 ac5_max_level;
|
||||
u64 ac6_max_level;
|
||||
u64 ac7_max_level;
|
||||
u64 ac8_max_level;
|
||||
u64 ac9_max_level;
|
||||
struct_group(data,
|
||||
u64 weight;
|
||||
u64 ac0_max_level;
|
||||
u64 ac1_max_level;
|
||||
u64 ac2_max_level;
|
||||
u64 ac3_max_level;
|
||||
u64 ac4_max_level;
|
||||
u64 ac5_max_level;
|
||||
u64 ac6_max_level;
|
||||
u64 ac7_max_level;
|
||||
u64 ac8_max_level;
|
||||
u64 ac9_max_level;
|
||||
);
|
||||
};
|
||||
u64 __data[ACPI_NR_ART_ELEMENTS];
|
||||
};
|
||||
|
||||
@@ -80,7 +80,8 @@ void proc_thermal_rfim_remove(struct pci_dev *pdev);
|
||||
int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
|
||||
void proc_thermal_mbox_remove(struct pci_dev *pdev);
|
||||
|
||||
int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u64 *cmd_resp);
|
||||
int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp);
|
||||
int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data);
|
||||
int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv);
|
||||
void proc_thermal_remove(struct proc_thermal_device *proc_priv);
|
||||
int proc_thermal_suspend(struct device *dev);
|
||||
|
||||
@@ -24,19 +24,15 @@
|
||||
|
||||
static DEFINE_MUTEX(mbox_lock);
|
||||
|
||||
static int send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u64 *cmd_resp)
|
||||
static int wait_for_mbox_ready(struct proc_thermal_device *proc_priv)
|
||||
{
|
||||
struct proc_thermal_device *proc_priv;
|
||||
u32 retries, data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mbox_lock);
|
||||
proc_priv = pci_get_drvdata(pdev);
|
||||
|
||||
/* Poll for rb bit == 0 */
|
||||
retries = MBOX_RETRY_COUNT;
|
||||
do {
|
||||
data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE));
|
||||
data = readl(proc_priv->mmio_base + MBOX_OFFSET_INTERFACE);
|
||||
if (data & BIT_ULL(MBOX_BUSY_BIT)) {
|
||||
ret = -EBUSY;
|
||||
continue;
|
||||
@@ -45,53 +41,78 @@ static int send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u64 *cm
|
||||
break;
|
||||
} while (--retries);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data)
|
||||
{
|
||||
struct proc_thermal_device *proc_priv;
|
||||
u32 reg_data;
|
||||
int ret;
|
||||
|
||||
proc_priv = pci_get_drvdata(pdev);
|
||||
|
||||
mutex_lock(&mbox_lock);
|
||||
|
||||
ret = wait_for_mbox_ready(proc_priv);
|
||||
if (ret)
|
||||
goto unlock_mbox;
|
||||
|
||||
if (cmd_id == MBOX_CMD_WORKLOAD_TYPE_WRITE)
|
||||
writel(cmd_data, (void __iomem *) ((proc_priv->mmio_base + MBOX_OFFSET_DATA)));
|
||||
|
||||
writel(data, (proc_priv->mmio_base + MBOX_OFFSET_DATA));
|
||||
/* Write command register */
|
||||
data = BIT_ULL(MBOX_BUSY_BIT) | cmd_id;
|
||||
writel(data, (void __iomem *) ((proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)));
|
||||
reg_data = BIT_ULL(MBOX_BUSY_BIT) | id;
|
||||
writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE));
|
||||
|
||||
/* Poll for rb bit == 0 */
|
||||
retries = MBOX_RETRY_COUNT;
|
||||
do {
|
||||
data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE));
|
||||
if (data & BIT_ULL(MBOX_BUSY_BIT)) {
|
||||
ret = -EBUSY;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
ret = -ENXIO;
|
||||
goto unlock_mbox;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (!cmd_resp)
|
||||
break;
|
||||
|
||||
if (cmd_id == MBOX_CMD_WORKLOAD_TYPE_READ)
|
||||
*cmd_resp = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_DATA));
|
||||
else
|
||||
*cmd_resp = readq((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_DATA));
|
||||
|
||||
break;
|
||||
} while (--retries);
|
||||
ret = wait_for_mbox_ready(proc_priv);
|
||||
|
||||
unlock_mbox:
|
||||
mutex_unlock(&mbox_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u64 *cmd_resp)
|
||||
static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp)
|
||||
{
|
||||
return send_mbox_cmd(pdev, cmd_id, cmd_data, cmd_resp);
|
||||
struct proc_thermal_device *proc_priv;
|
||||
u32 reg_data;
|
||||
int ret;
|
||||
|
||||
proc_priv = pci_get_drvdata(pdev);
|
||||
|
||||
mutex_lock(&mbox_lock);
|
||||
|
||||
ret = wait_for_mbox_ready(proc_priv);
|
||||
if (ret)
|
||||
goto unlock_mbox;
|
||||
|
||||
/* Write command register */
|
||||
reg_data = BIT_ULL(MBOX_BUSY_BIT) | id;
|
||||
writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE));
|
||||
|
||||
ret = wait_for_mbox_ready(proc_priv);
|
||||
if (ret)
|
||||
goto unlock_mbox;
|
||||
|
||||
if (id == MBOX_CMD_WORKLOAD_TYPE_READ)
|
||||
*resp = readl(proc_priv->mmio_base + MBOX_OFFSET_DATA);
|
||||
else
|
||||
*resp = readq(proc_priv->mmio_base + MBOX_OFFSET_DATA);
|
||||
|
||||
unlock_mbox:
|
||||
mutex_unlock(&mbox_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(processor_thermal_send_mbox_cmd);
|
||||
|
||||
int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp)
|
||||
{
|
||||
return send_mbox_read_cmd(pdev, id, resp);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL);
|
||||
|
||||
int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data)
|
||||
{
|
||||
return send_mbox_write_cmd(pdev, id, data);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL);
|
||||
|
||||
/* List of workload types */
|
||||
static const char * const workload_types[] = {
|
||||
@@ -104,7 +125,6 @@ static const char * const workload_types[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static ssize_t workload_available_types_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -146,7 +166,7 @@ static ssize_t workload_type_store(struct device *dev,
|
||||
|
||||
data |= ret;
|
||||
|
||||
ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data, NULL);
|
||||
ret = send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
@@ -161,7 +181,7 @@ static ssize_t workload_type_show(struct device *dev,
|
||||
u64 cmd_resp;
|
||||
int ret;
|
||||
|
||||
ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp);
|
||||
ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
@@ -186,8 +206,6 @@ static const struct attribute_group workload_req_attribute_group = {
|
||||
.name = "workload_request"
|
||||
};
|
||||
|
||||
|
||||
|
||||
static bool workload_req_created;
|
||||
|
||||
int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
|
||||
@@ -196,7 +214,7 @@ int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc
|
||||
int ret;
|
||||
|
||||
/* Check if there is a mailbox support, if fails return success */
|
||||
ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp);
|
||||
ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <linux/pci.h>
|
||||
#include "processor_thermal_device.h"
|
||||
|
||||
MODULE_IMPORT_NS(INT340X_THERMAL);
|
||||
|
||||
struct mmio_reg {
|
||||
int read_only;
|
||||
u32 offset;
|
||||
@@ -194,8 +196,7 @@ static ssize_t rfi_restriction_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u16 cmd_id = 0x0008;
|
||||
u64 cmd_resp;
|
||||
u16 id = 0x0008;
|
||||
u32 input;
|
||||
int ret;
|
||||
|
||||
@@ -203,7 +204,7 @@ static ssize_t rfi_restriction_store(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, input, &cmd_resp);
|
||||
ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -214,30 +215,30 @@ static ssize_t rfi_restriction_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
u16 cmd_id = 0x0007;
|
||||
u64 cmd_resp;
|
||||
u16 id = 0x0007;
|
||||
u64 resp;
|
||||
int ret;
|
||||
|
||||
ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp);
|
||||
ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%llu\n", cmd_resp);
|
||||
return sprintf(buf, "%llu\n", resp);
|
||||
}
|
||||
|
||||
static ssize_t ddr_data_rate_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
u16 cmd_id = 0x0107;
|
||||
u64 cmd_resp;
|
||||
u16 id = 0x0107;
|
||||
u64 resp;
|
||||
int ret;
|
||||
|
||||
ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp);
|
||||
ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%llu\n", cmd_resp);
|
||||
return sprintf(buf, "%llu\n", resp);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(rfi_restriction);
|
||||
|
||||
@@ -641,7 +641,7 @@ exit_set:
|
||||
}
|
||||
|
||||
/* bind to generic thermal layer as cooling device*/
|
||||
static struct thermal_cooling_device_ops powerclamp_cooling_ops = {
|
||||
static const struct thermal_cooling_device_ops powerclamp_cooling_ops = {
|
||||
.get_max_state = powerclamp_get_max_state,
|
||||
.get_cur_state = powerclamp_get_cur_state,
|
||||
.set_cur_state = powerclamp_set_cur_state,
|
||||
|
||||
242
drivers/thermal/rzg2l_thermal.c
Normal file
242
drivers/thermal/rzg2l_thermal.c
Normal file
@@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Renesas RZ/G2L TSU Thermal Sensor Driver
|
||||
*
|
||||
* Copyright (C) 2021 Renesas Electronics Corporation
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "thermal_hwmon.h"
|
||||
|
||||
#define CTEMP_MASK 0xFFF
|
||||
|
||||
/* default calibration values, if FUSE values are missing */
|
||||
#define SW_CALIB0_VAL 3148
|
||||
#define SW_CALIB1_VAL 503
|
||||
|
||||
/* Register offsets */
|
||||
#define TSU_SM 0x00
|
||||
#define TSU_ST 0x04
|
||||
#define TSU_SAD 0x0C
|
||||
#define TSU_SS 0x10
|
||||
|
||||
#define OTPTSUTRIM_REG(n) (0x18 + ((n) * 0x4))
|
||||
|
||||
/* Sensor Mode Register(TSU_SM) */
|
||||
#define TSU_SM_EN_TS BIT(0)
|
||||
#define TSU_SM_ADC_EN_TS BIT(1)
|
||||
#define TSU_SM_NORMAL_MODE (TSU_SM_EN_TS | TSU_SM_ADC_EN_TS)
|
||||
|
||||
/* TSU_ST bits */
|
||||
#define TSU_ST_START BIT(0)
|
||||
|
||||
#define TSU_SS_CONV_RUNNING BIT(0)
|
||||
|
||||
#define TS_CODE_AVE_SCALE(x) ((x) * 1000000)
|
||||
#define MCELSIUS(temp) ((temp) * MILLIDEGREE_PER_DEGREE)
|
||||
#define TS_CODE_CAP_TIMES 8 /* Capture times */
|
||||
|
||||
#define RZG2L_THERMAL_GRAN 500 /* milli Celsius */
|
||||
#define RZG2L_TSU_SS_TIMEOUT_US 1000
|
||||
|
||||
#define CURVATURE_CORRECTION_CONST 13
|
||||
|
||||
struct rzg2l_thermal_priv {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct thermal_zone_device *zone;
|
||||
struct reset_control *rstc;
|
||||
u32 calib0, calib1;
|
||||
};
|
||||
|
||||
static inline u32 rzg2l_thermal_read(struct rzg2l_thermal_priv *priv, u32 reg)
|
||||
{
|
||||
return ioread32(priv->base + reg);
|
||||
}
|
||||
|
||||
static inline void rzg2l_thermal_write(struct rzg2l_thermal_priv *priv, u32 reg,
|
||||
u32 data)
|
||||
{
|
||||
iowrite32(data, priv->base + reg);
|
||||
}
|
||||
|
||||
static int rzg2l_thermal_get_temp(void *devdata, int *temp)
|
||||
{
|
||||
struct rzg2l_thermal_priv *priv = devdata;
|
||||
u32 result = 0, dsensor, ts_code_ave;
|
||||
int val, i;
|
||||
|
||||
for (i = 0; i < TS_CODE_CAP_TIMES ; i++) {
|
||||
/* TSU repeats measurement at 20 microseconds intervals and
|
||||
* automatically updates the results of measurement. As per
|
||||
* the HW manual for measuring temperature we need to read 8
|
||||
* values consecutively and then take the average.
|
||||
* ts_code_ave = (ts_code[0] + ⋯ + ts_code[7]) / 8
|
||||
*/
|
||||
result += rzg2l_thermal_read(priv, TSU_SAD) & CTEMP_MASK;
|
||||
usleep_range(20, 30);
|
||||
}
|
||||
|
||||
ts_code_ave = result / TS_CODE_CAP_TIMES;
|
||||
|
||||
/* Calculate actual sensor value by applying curvature correction formula
|
||||
* dsensor = ts_code_ave / (1 + ts_code_ave * 0.000013). Here we are doing
|
||||
* integer calculation by scaling all the values by 1000000.
|
||||
*/
|
||||
dsensor = TS_CODE_AVE_SCALE(ts_code_ave) /
|
||||
(TS_CODE_AVE_SCALE(1) + (ts_code_ave * CURVATURE_CORRECTION_CONST));
|
||||
|
||||
/* The temperature Tj is calculated by the formula
|
||||
* Tj = (dsensor − calib1) * 165/ (calib0 − calib1) − 40
|
||||
* where calib0 and calib1 are the caliberation values.
|
||||
*/
|
||||
val = ((dsensor - priv->calib1) * (MCELSIUS(165) /
|
||||
(priv->calib0 - priv->calib1))) - MCELSIUS(40);
|
||||
|
||||
*temp = roundup(val, RZG2L_THERMAL_GRAN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct thermal_zone_of_device_ops rzg2l_tz_of_ops = {
|
||||
.get_temp = rzg2l_thermal_get_temp,
|
||||
};
|
||||
|
||||
static int rzg2l_thermal_init(struct rzg2l_thermal_priv *priv)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
rzg2l_thermal_write(priv, TSU_SM, TSU_SM_NORMAL_MODE);
|
||||
rzg2l_thermal_write(priv, TSU_ST, 0);
|
||||
|
||||
/* Before setting the START bit, TSU should be in normal operating
|
||||
* mode. As per the HW manual, it will take 60 µs to place the TSU
|
||||
* into normal operating mode.
|
||||
*/
|
||||
usleep_range(60, 80);
|
||||
|
||||
reg_val = rzg2l_thermal_read(priv, TSU_ST);
|
||||
reg_val |= TSU_ST_START;
|
||||
rzg2l_thermal_write(priv, TSU_ST, reg_val);
|
||||
|
||||
return readl_poll_timeout(priv->base + TSU_SS, reg_val,
|
||||
reg_val == TSU_SS_CONV_RUNNING, 50,
|
||||
RZG2L_TSU_SS_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static void rzg2l_thermal_reset_assert_pm_disable_put(struct platform_device *pdev)
|
||||
{
|
||||
struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
reset_control_assert(priv->rstc);
|
||||
}
|
||||
|
||||
static int rzg2l_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
thermal_remove_hwmon_sysfs(priv->zone);
|
||||
rzg2l_thermal_reset_assert_pm_disable_put(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzg2l_thermal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_zone_device *zone;
|
||||
struct rzg2l_thermal_priv *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
priv->dev = dev;
|
||||
priv->rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||
if (IS_ERR(priv->rstc))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->rstc),
|
||||
"failed to get cpg reset");
|
||||
|
||||
ret = reset_control_deassert(priv->rstc);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to deassert");
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
priv->calib0 = rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0));
|
||||
if (!priv->calib0)
|
||||
priv->calib0 = SW_CALIB0_VAL;
|
||||
|
||||
priv->calib1 = rzg2l_thermal_read(priv, OTPTSUTRIM_REG(1));
|
||||
if (!priv->calib1)
|
||||
priv->calib1 = SW_CALIB1_VAL;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
ret = rzg2l_thermal_init(priv);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to start TSU");
|
||||
goto err;
|
||||
}
|
||||
|
||||
zone = devm_thermal_zone_of_sensor_register(dev, 0, priv,
|
||||
&rzg2l_tz_of_ops);
|
||||
if (IS_ERR(zone)) {
|
||||
dev_err(dev, "Can't register thermal zone");
|
||||
ret = PTR_ERR(zone);
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->zone = zone;
|
||||
priv->zone->tzp->no_hwmon = false;
|
||||
ret = thermal_add_hwmon_sysfs(priv->zone);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
dev_dbg(dev, "TSU probed with %s caliberation values",
|
||||
rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0)) ? "hw" : "sw");
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
rzg2l_thermal_reset_assert_pm_disable_put(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id rzg2l_thermal_dt_ids[] = {
|
||||
{ .compatible = "renesas,rzg2l-tsu", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rzg2l_thermal_dt_ids);
|
||||
|
||||
static struct platform_driver rzg2l_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rzg2l_thermal",
|
||||
.of_match_table = rzg2l_thermal_dt_ids,
|
||||
},
|
||||
.probe = rzg2l_thermal_probe,
|
||||
.remove = rzg2l_thermal_remove,
|
||||
};
|
||||
module_platform_driver(rzg2l_thermal_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Renesas RZ/G2L TSU Thermal Sensor Driver");
|
||||
MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
63
fs/select.c
63
fs/select.c
@@ -459,9 +459,11 @@ get_max:
|
||||
return max;
|
||||
}
|
||||
|
||||
#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR)
|
||||
#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR)
|
||||
#define POLLEX_SET (EPOLLPRI)
|
||||
#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR |\
|
||||
EPOLLNVAL)
|
||||
#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR |\
|
||||
EPOLLNVAL)
|
||||
#define POLLEX_SET (EPOLLPRI | EPOLLNVAL)
|
||||
|
||||
static inline void wait_key_set(poll_table *wait, unsigned long in,
|
||||
unsigned long out, unsigned long bit,
|
||||
@@ -528,6 +530,7 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
|
||||
break;
|
||||
if (!(bit & all_bits))
|
||||
continue;
|
||||
mask = EPOLLNVAL;
|
||||
f = fdget(i);
|
||||
if (f.file) {
|
||||
wait_key_set(wait, in, out, bit,
|
||||
@@ -535,34 +538,34 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
|
||||
mask = vfs_poll(f.file, wait);
|
||||
|
||||
fdput(f);
|
||||
if ((mask & POLLIN_SET) && (in & bit)) {
|
||||
res_in |= bit;
|
||||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
if ((mask & POLLOUT_SET) && (out & bit)) {
|
||||
res_out |= bit;
|
||||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
if ((mask & POLLEX_SET) && (ex & bit)) {
|
||||
res_ex |= bit;
|
||||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
/* got something, stop busy polling */
|
||||
if (retval) {
|
||||
can_busy_loop = false;
|
||||
busy_flag = 0;
|
||||
|
||||
/*
|
||||
* only remember a returned
|
||||
* POLL_BUSY_LOOP if we asked for it
|
||||
*/
|
||||
} else if (busy_flag & mask)
|
||||
can_busy_loop = true;
|
||||
|
||||
}
|
||||
if ((mask & POLLIN_SET) && (in & bit)) {
|
||||
res_in |= bit;
|
||||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
if ((mask & POLLOUT_SET) && (out & bit)) {
|
||||
res_out |= bit;
|
||||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
if ((mask & POLLEX_SET) && (ex & bit)) {
|
||||
res_ex |= bit;
|
||||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
/* got something, stop busy polling */
|
||||
if (retval) {
|
||||
can_busy_loop = false;
|
||||
busy_flag = 0;
|
||||
|
||||
/*
|
||||
* only remember a returned
|
||||
* POLL_BUSY_LOOP if we asked for it
|
||||
*/
|
||||
} else if (busy_flag & mask)
|
||||
can_busy_loop = true;
|
||||
|
||||
}
|
||||
if (res_in)
|
||||
*rinp = res_in;
|
||||
|
||||
@@ -413,7 +413,7 @@ struct cgroup {
|
||||
/*
|
||||
* The bitmask of subsystems enabled on the child cgroups.
|
||||
* ->subtree_control is the one configured through
|
||||
* "cgroup.subtree_control" while ->child_ss_mask is the effective
|
||||
* "cgroup.subtree_control" while ->subtree_ss_mask is the effective
|
||||
* one which may have more subsystems enabled. Controller knobs
|
||||
* are made available iff it's enabled in ->subtree_control.
|
||||
*/
|
||||
|
||||
@@ -378,10 +378,6 @@ property_entries_dup(const struct property_entry *properties);
|
||||
|
||||
void property_entries_free(const struct property_entry *properties);
|
||||
|
||||
int device_add_properties(struct device *dev,
|
||||
const struct property_entry *properties);
|
||||
void device_remove_properties(struct device *dev);
|
||||
|
||||
bool device_dma_supported(struct device *dev);
|
||||
|
||||
enum dev_dma_attr device_get_dma_attr(struct device *dev);
|
||||
@@ -401,9 +397,6 @@ struct fwnode_handle *fwnode_graph_get_remote_port(
|
||||
const struct fwnode_handle *fwnode);
|
||||
struct fwnode_handle *fwnode_graph_get_remote_endpoint(
|
||||
const struct fwnode_handle *fwnode);
|
||||
struct fwnode_handle *
|
||||
fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port,
|
||||
u32 endpoint);
|
||||
|
||||
static inline bool fwnode_graph_is_endpoint(struct fwnode_handle *fwnode)
|
||||
{
|
||||
@@ -418,7 +411,8 @@ static inline bool fwnode_graph_is_endpoint(struct fwnode_handle *fwnode)
|
||||
* one.
|
||||
* @FWNODE_GRAPH_DEVICE_DISABLED: That the device to which the remote
|
||||
* endpoint of the given endpoint belongs to,
|
||||
* may be disabled.
|
||||
* may be disabled, or that the endpoint is not
|
||||
* connected.
|
||||
*/
|
||||
#define FWNODE_GRAPH_ENDPOINT_NEXT BIT(0)
|
||||
#define FWNODE_GRAPH_DEVICE_DISABLED BIT(1)
|
||||
@@ -426,6 +420,8 @@ static inline bool fwnode_graph_is_endpoint(struct fwnode_handle *fwnode)
|
||||
struct fwnode_handle *
|
||||
fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
|
||||
u32 port, u32 endpoint, unsigned long flags);
|
||||
unsigned int fwnode_graph_get_endpoint_count(struct fwnode_handle *fwnode,
|
||||
unsigned long flags);
|
||||
|
||||
#define fwnode_graph_for_each_endpoint(fwnode, child) \
|
||||
for (child = NULL; \
|
||||
|
||||
@@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(cgroup,
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, root )
|
||||
__field( int, id )
|
||||
__field( int, level )
|
||||
__field( u64, id )
|
||||
__string( path, path )
|
||||
),
|
||||
|
||||
@@ -71,7 +71,7 @@ DECLARE_EVENT_CLASS(cgroup,
|
||||
__assign_str(path, path);
|
||||
),
|
||||
|
||||
TP_printk("root=%d id=%d level=%d path=%s",
|
||||
TP_printk("root=%d id=%llu level=%d path=%s",
|
||||
__entry->root, __entry->id, __entry->level, __get_str(path))
|
||||
);
|
||||
|
||||
@@ -126,8 +126,8 @@ DECLARE_EVENT_CLASS(cgroup_migrate,
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, dst_root )
|
||||
__field( int, dst_id )
|
||||
__field( int, dst_level )
|
||||
__field( u64, dst_id )
|
||||
__field( int, pid )
|
||||
__string( dst_path, path )
|
||||
__string( comm, task->comm )
|
||||
@@ -142,7 +142,7 @@ DECLARE_EVENT_CLASS(cgroup_migrate,
|
||||
__assign_str(comm, task->comm);
|
||||
),
|
||||
|
||||
TP_printk("dst_root=%d dst_id=%d dst_level=%d dst_path=%s pid=%d comm=%s",
|
||||
TP_printk("dst_root=%d dst_id=%llu dst_level=%d dst_path=%s pid=%d comm=%s",
|
||||
__entry->dst_root, __entry->dst_id, __entry->dst_level,
|
||||
__get_str(dst_path), __entry->pid, __get_str(comm))
|
||||
);
|
||||
@@ -171,8 +171,8 @@ DECLARE_EVENT_CLASS(cgroup_event,
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, root )
|
||||
__field( int, id )
|
||||
__field( int, level )
|
||||
__field( u64, id )
|
||||
__string( path, path )
|
||||
__field( int, val )
|
||||
),
|
||||
@@ -185,7 +185,7 @@ DECLARE_EVENT_CLASS(cgroup_event,
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("root=%d id=%d level=%d path=%s val=%d",
|
||||
TP_printk("root=%d id=%llu level=%d path=%s val=%d",
|
||||
__entry->root, __entry->id, __entry->level, __get_str(path),
|
||||
__entry->val)
|
||||
);
|
||||
|
||||
@@ -2657,11 +2657,11 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
||||
if (src_cset->dead)
|
||||
return;
|
||||
|
||||
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
|
||||
|
||||
if (!list_empty(&src_cset->mg_preload_node))
|
||||
return;
|
||||
|
||||
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
|
||||
|
||||
WARN_ON(src_cset->mg_src_cgrp);
|
||||
WARN_ON(src_cset->mg_dst_cgrp);
|
||||
WARN_ON(!list_empty(&src_cset->mg_tasks));
|
||||
@@ -5755,7 +5755,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early)
|
||||
|
||||
/* Create the root cgroup state for this subsystem */
|
||||
ss->root = &cgrp_dfl_root;
|
||||
css = ss->css_alloc(cgroup_css(&cgrp_dfl_root.cgrp, ss));
|
||||
css = ss->css_alloc(NULL);
|
||||
/* We don't handle early failures gracefully */
|
||||
BUG_ON(IS_ERR(css));
|
||||
init_and_link_css(css, ss, &cgrp_dfl_root.cgrp);
|
||||
|
||||
@@ -615,19 +615,11 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
|
||||
struct cpuset *c, *par;
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
/* Each of our child cpusets must be a subset of us */
|
||||
ret = -EBUSY;
|
||||
cpuset_for_each_child(c, css, cur)
|
||||
if (!is_cpuset_subset(c, trial))
|
||||
goto out;
|
||||
|
||||
/* Remaining checks don't apply to root cpuset */
|
||||
ret = 0;
|
||||
/* The checks don't apply to root cpuset */
|
||||
if (cur == &top_cpuset)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
par = parent_cs(cur);
|
||||
|
||||
/* On legacy hierarchy, we must be a subset of our parent cpuset. */
|
||||
@@ -3552,7 +3544,7 @@ static struct cpuset *nearest_hardwall_ancestor(struct cpuset *cs)
|
||||
bool __cpuset_node_allowed(int node, gfp_t gfp_mask)
|
||||
{
|
||||
struct cpuset *cs; /* current cpuset ancestors */
|
||||
int allowed; /* is allocation in zone z allowed? */
|
||||
bool allowed; /* is allocation in zone z allowed? */
|
||||
unsigned long flags;
|
||||
|
||||
if (in_interrupt())
|
||||
|
||||
@@ -35,7 +35,7 @@ void cgroup_rstat_updated(struct cgroup *cgrp, int cpu)
|
||||
* instead of NULL, we can tell whether @cgrp is on the list by
|
||||
* testing the next pointer for NULL.
|
||||
*/
|
||||
if (cgroup_rstat_cpu(cgrp, cpu)->updated_next)
|
||||
if (data_race(cgroup_rstat_cpu(cgrp, cpu)->updated_next))
|
||||
return;
|
||||
|
||||
raw_spin_lock_irqsave(cpu_lock, flags);
|
||||
@@ -88,6 +88,7 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
|
||||
struct cgroup *root, int cpu)
|
||||
{
|
||||
struct cgroup_rstat_cpu *rstatc;
|
||||
struct cgroup *parent;
|
||||
|
||||
if (pos == root)
|
||||
return NULL;
|
||||
@@ -96,10 +97,14 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
|
||||
* We're gonna walk down to the first leaf and visit/remove it. We
|
||||
* can pick whatever unvisited node as the starting point.
|
||||
*/
|
||||
if (!pos)
|
||||
if (!pos) {
|
||||
pos = root;
|
||||
else
|
||||
/* return NULL if this subtree is not on-list */
|
||||
if (!cgroup_rstat_cpu(pos, cpu)->updated_next)
|
||||
return NULL;
|
||||
} else {
|
||||
pos = cgroup_parent(pos);
|
||||
}
|
||||
|
||||
/* walk down to the first leaf */
|
||||
while (true) {
|
||||
@@ -115,33 +120,25 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
|
||||
* However, due to the way we traverse, @pos will be the first
|
||||
* child in most cases. The only exception is @root.
|
||||
*/
|
||||
if (rstatc->updated_next) {
|
||||
struct cgroup *parent = cgroup_parent(pos);
|
||||
parent = cgroup_parent(pos);
|
||||
if (parent) {
|
||||
struct cgroup_rstat_cpu *prstatc;
|
||||
struct cgroup **nextp;
|
||||
|
||||
if (parent) {
|
||||
struct cgroup_rstat_cpu *prstatc;
|
||||
struct cgroup **nextp;
|
||||
prstatc = cgroup_rstat_cpu(parent, cpu);
|
||||
nextp = &prstatc->updated_children;
|
||||
while (*nextp != pos) {
|
||||
struct cgroup_rstat_cpu *nrstatc;
|
||||
|
||||
prstatc = cgroup_rstat_cpu(parent, cpu);
|
||||
nextp = &prstatc->updated_children;
|
||||
while (true) {
|
||||
struct cgroup_rstat_cpu *nrstatc;
|
||||
|
||||
nrstatc = cgroup_rstat_cpu(*nextp, cpu);
|
||||
if (*nextp == pos)
|
||||
break;
|
||||
WARN_ON_ONCE(*nextp == parent);
|
||||
nextp = &nrstatc->updated_next;
|
||||
}
|
||||
*nextp = rstatc->updated_next;
|
||||
nrstatc = cgroup_rstat_cpu(*nextp, cpu);
|
||||
WARN_ON_ONCE(*nextp == parent);
|
||||
nextp = &nrstatc->updated_next;
|
||||
}
|
||||
|
||||
rstatc->updated_next = NULL;
|
||||
return pos;
|
||||
*nextp = rstatc->updated_next;
|
||||
}
|
||||
|
||||
/* only happens for @root */
|
||||
return NULL;
|
||||
rstatc->updated_next = NULL;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* see cgroup_rstat_flush() */
|
||||
|
||||
@@ -282,7 +282,6 @@ static struct console *exclusive_console;
|
||||
static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
|
||||
|
||||
static int preferred_console = -1;
|
||||
static bool has_preferred_console;
|
||||
int console_set_on_cmdline;
|
||||
EXPORT_SYMBOL(console_set_on_cmdline);
|
||||
|
||||
@@ -2869,7 +2868,8 @@ early_param("keep_bootcon", keep_bootcon_setup);
|
||||
* Care need to be taken with consoles that are statically
|
||||
* enabled such as netconsole
|
||||
*/
|
||||
static int try_enable_new_console(struct console *newcon, bool user_specified)
|
||||
static int try_enable_preferred_console(struct console *newcon,
|
||||
bool user_specified)
|
||||
{
|
||||
struct console_cmdline *c;
|
||||
int i, err;
|
||||
@@ -2899,10 +2899,8 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
|
||||
return err;
|
||||
}
|
||||
newcon->flags |= CON_ENABLED;
|
||||
if (i == preferred_console) {
|
||||
if (i == preferred_console)
|
||||
newcon->flags |= CON_CONSDEV;
|
||||
has_preferred_console = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2917,6 +2915,21 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Try to enable the console unconditionally */
|
||||
static void try_enable_default_console(struct console *newcon)
|
||||
{
|
||||
if (newcon->index < 0)
|
||||
newcon->index = 0;
|
||||
|
||||
if (newcon->setup && newcon->setup(newcon, NULL) != 0)
|
||||
return;
|
||||
|
||||
newcon->flags |= CON_ENABLED;
|
||||
|
||||
if (newcon->device)
|
||||
newcon->flags |= CON_CONSDEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* The console driver calls this routine during kernel initialization
|
||||
* to register the console printing procedure with printk() and to
|
||||
@@ -2938,59 +2951,56 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
|
||||
*/
|
||||
void register_console(struct console *newcon)
|
||||
{
|
||||
struct console *bcon = NULL;
|
||||
struct console *con;
|
||||
bool bootcon_enabled = false;
|
||||
bool realcon_enabled = false;
|
||||
int err;
|
||||
|
||||
for_each_console(bcon) {
|
||||
if (WARN(bcon == newcon, "console '%s%d' already registered\n",
|
||||
bcon->name, bcon->index))
|
||||
for_each_console(con) {
|
||||
if (WARN(con == newcon, "console '%s%d' already registered\n",
|
||||
con->name, con->index))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* before we register a new CON_BOOT console, make sure we don't
|
||||
* already have a valid console
|
||||
*/
|
||||
if (newcon->flags & CON_BOOT) {
|
||||
for_each_console(bcon) {
|
||||
if (!(bcon->flags & CON_BOOT)) {
|
||||
pr_info("Too late to register bootconsole %s%d\n",
|
||||
newcon->name, newcon->index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for_each_console(con) {
|
||||
if (con->flags & CON_BOOT)
|
||||
bootcon_enabled = true;
|
||||
else
|
||||
realcon_enabled = true;
|
||||
}
|
||||
|
||||
if (console_drivers && console_drivers->flags & CON_BOOT)
|
||||
bcon = console_drivers;
|
||||
|
||||
if (!has_preferred_console || bcon || !console_drivers)
|
||||
has_preferred_console = preferred_console >= 0;
|
||||
/* Do not register boot consoles when there already is a real one. */
|
||||
if (newcon->flags & CON_BOOT && realcon_enabled) {
|
||||
pr_info("Too late to register bootconsole %s%d\n",
|
||||
newcon->name, newcon->index);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we want to use this console driver. If we
|
||||
* didn't select a console we take the first one
|
||||
* that registers here.
|
||||
* See if we want to enable this console driver by default.
|
||||
*
|
||||
* Nope when a console is preferred by the command line, device
|
||||
* tree, or SPCR.
|
||||
*
|
||||
* The first real console with tty binding (driver) wins. More
|
||||
* consoles might get enabled before the right one is found.
|
||||
*
|
||||
* Note that a console with tty binding will have CON_CONSDEV
|
||||
* flag set and will be first in the list.
|
||||
*/
|
||||
if (!has_preferred_console) {
|
||||
if (newcon->index < 0)
|
||||
newcon->index = 0;
|
||||
if (newcon->setup == NULL ||
|
||||
newcon->setup(newcon, NULL) == 0) {
|
||||
newcon->flags |= CON_ENABLED;
|
||||
if (newcon->device) {
|
||||
newcon->flags |= CON_CONSDEV;
|
||||
has_preferred_console = true;
|
||||
}
|
||||
if (preferred_console < 0) {
|
||||
if (!console_drivers || !console_drivers->device ||
|
||||
console_drivers->flags & CON_BOOT) {
|
||||
try_enable_default_console(newcon);
|
||||
}
|
||||
}
|
||||
|
||||
/* See if this console matches one we selected on the command line */
|
||||
err = try_enable_new_console(newcon, true);
|
||||
err = try_enable_preferred_console(newcon, true);
|
||||
|
||||
/* If not, try to match against the platform default(s) */
|
||||
if (err == -ENOENT)
|
||||
err = try_enable_new_console(newcon, false);
|
||||
err = try_enable_preferred_console(newcon, false);
|
||||
|
||||
/* printk() messages are not printed to the Braille console. */
|
||||
if (err || newcon->flags & CON_BRL)
|
||||
@@ -3002,8 +3012,10 @@ void register_console(struct console *newcon)
|
||||
* the real console are the same physical device, it's annoying to
|
||||
* see the beginning boot messages twice
|
||||
*/
|
||||
if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
|
||||
if (bootcon_enabled &&
|
||||
((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) {
|
||||
newcon->flags &= ~CON_PRINTBUFFER;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put this console in the list - keep the
|
||||
@@ -3059,15 +3071,15 @@ void register_console(struct console *newcon)
|
||||
pr_info("%sconsole [%s%d] enabled\n",
|
||||
(newcon->flags & CON_BOOT) ? "boot" : "" ,
|
||||
newcon->name, newcon->index);
|
||||
if (bcon &&
|
||||
if (bootcon_enabled &&
|
||||
((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
|
||||
!keep_bootcon) {
|
||||
/* We need to iterate through all boot consoles, to make
|
||||
* sure we print everything out, before we unregister them.
|
||||
*/
|
||||
for_each_console(bcon)
|
||||
if (bcon->flags & CON_BOOT)
|
||||
unregister_console(bcon);
|
||||
for_each_console(con)
|
||||
if (con->flags & CON_BOOT)
|
||||
unregister_console(con);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(register_console);
|
||||
|
||||
@@ -158,6 +158,9 @@ struct worker_pool {
|
||||
|
||||
unsigned long watchdog_ts; /* L: watchdog timestamp */
|
||||
|
||||
/* The current concurrency level. */
|
||||
atomic_t nr_running;
|
||||
|
||||
struct list_head worklist; /* L: list of pending works */
|
||||
|
||||
int nr_workers; /* L: total number of workers */
|
||||
@@ -181,19 +184,12 @@ struct worker_pool {
|
||||
struct hlist_node hash_node; /* PL: unbound_pool_hash node */
|
||||
int refcnt; /* PL: refcnt for unbound pools */
|
||||
|
||||
/*
|
||||
* The current concurrency level. As it's likely to be accessed
|
||||
* from other CPUs during try_to_wake_up(), put it in a separate
|
||||
* cacheline.
|
||||
*/
|
||||
atomic_t nr_running ____cacheline_aligned_in_smp;
|
||||
|
||||
/*
|
||||
* Destruction of pool is RCU protected to allow dereferences
|
||||
* from get_work_pool().
|
||||
*/
|
||||
struct rcu_head rcu;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
};
|
||||
|
||||
/*
|
||||
* The per-pool workqueue. While queued, the lower WORK_STRUCT_FLAG_BITS
|
||||
@@ -872,8 +868,17 @@ void wq_worker_running(struct task_struct *task)
|
||||
|
||||
if (!worker->sleeping)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If preempted by unbind_workers() between the WORKER_NOT_RUNNING check
|
||||
* and the nr_running increment below, we may ruin the nr_running reset
|
||||
* and leave with an unexpected pool->nr_running == 1 on the newly unbound
|
||||
* pool. Protect against such race.
|
||||
*/
|
||||
preempt_disable();
|
||||
if (!(worker->flags & WORKER_NOT_RUNNING))
|
||||
atomic_inc(&worker->pool->nr_running);
|
||||
preempt_enable();
|
||||
worker->sleeping = 0;
|
||||
}
|
||||
|
||||
@@ -882,8 +887,7 @@ void wq_worker_running(struct task_struct *task)
|
||||
* @task: task going to sleep
|
||||
*
|
||||
* This function is called from schedule() when a busy worker is
|
||||
* going to sleep. Preemption needs to be disabled to protect ->sleeping
|
||||
* assignment.
|
||||
* going to sleep.
|
||||
*/
|
||||
void wq_worker_sleeping(struct task_struct *task)
|
||||
{
|
||||
@@ -907,6 +911,16 @@ void wq_worker_sleeping(struct task_struct *task)
|
||||
worker->sleeping = 1;
|
||||
raw_spin_lock_irq(&pool->lock);
|
||||
|
||||
/*
|
||||
* Recheck in case unbind_workers() preempted us. We don't
|
||||
* want to decrement nr_running after the worker is unbound
|
||||
* and nr_running has been reset.
|
||||
*/
|
||||
if (worker->flags & WORKER_NOT_RUNNING) {
|
||||
raw_spin_unlock_irq(&pool->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The counterpart of the following dec_and_test, implied mb,
|
||||
* worklist not empty test sequence is in insert_work().
|
||||
@@ -1535,7 +1549,8 @@ out:
|
||||
* @work: work to queue
|
||||
*
|
||||
* We queue the work to a specific CPU, the caller must ensure it
|
||||
* can't go away.
|
||||
* can't go away. Callers that fail to ensure that the specified
|
||||
* CPU cannot go away will execute on a randomly chosen CPU.
|
||||
*
|
||||
* Return: %false if @work was already on a queue, %true otherwise.
|
||||
*/
|
||||
@@ -1815,14 +1830,8 @@ static void worker_enter_idle(struct worker *worker)
|
||||
if (too_many_workers(pool) && !timer_pending(&pool->idle_timer))
|
||||
mod_timer(&pool->idle_timer, jiffies + IDLE_WORKER_TIMEOUT);
|
||||
|
||||
/*
|
||||
* Sanity check nr_running. Because unbind_workers() releases
|
||||
* pool->lock between setting %WORKER_UNBOUND and zapping
|
||||
* nr_running, the warning may trigger spuriously. Check iff
|
||||
* unbind is not in progress.
|
||||
*/
|
||||
WARN_ON_ONCE(!(pool->flags & POOL_DISASSOCIATED) &&
|
||||
pool->nr_workers == pool->nr_idle &&
|
||||
/* Sanity check nr_running. */
|
||||
WARN_ON_ONCE(pool->nr_workers == pool->nr_idle &&
|
||||
atomic_read(&pool->nr_running));
|
||||
}
|
||||
|
||||
@@ -4983,38 +4992,22 @@ static void unbind_workers(int cpu)
|
||||
/*
|
||||
* We've blocked all attach/detach operations. Make all workers
|
||||
* unbound and set DISASSOCIATED. Before this, all workers
|
||||
* except for the ones which are still executing works from
|
||||
* before the last CPU down must be on the cpu. After
|
||||
* this, they may become diasporas.
|
||||
* must be on the cpu. After this, they may become diasporas.
|
||||
* And the preemption disabled section in their sched callbacks
|
||||
* are guaranteed to see WORKER_UNBOUND since the code here
|
||||
* is on the same cpu.
|
||||
*/
|
||||
for_each_pool_worker(worker, pool)
|
||||
worker->flags |= WORKER_UNBOUND;
|
||||
|
||||
pool->flags |= POOL_DISASSOCIATED;
|
||||
|
||||
raw_spin_unlock_irq(&pool->lock);
|
||||
|
||||
for_each_pool_worker(worker, pool) {
|
||||
kthread_set_per_cpu(worker->task, -1);
|
||||
WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, cpu_possible_mask) < 0);
|
||||
}
|
||||
|
||||
mutex_unlock(&wq_pool_attach_mutex);
|
||||
|
||||
/*
|
||||
* Call schedule() so that we cross rq->lock and thus can
|
||||
* guarantee sched callbacks see the %WORKER_UNBOUND flag.
|
||||
* This is necessary as scheduler callbacks may be invoked
|
||||
* from other cpus.
|
||||
*/
|
||||
schedule();
|
||||
|
||||
/*
|
||||
* Sched callbacks are disabled now. Zap nr_running.
|
||||
* After this, nr_running stays zero and need_more_worker()
|
||||
* and keep_working() are always true as long as the
|
||||
* worklist is not empty. This pool now behaves as an
|
||||
* unbound (in terms of concurrency management) pool which
|
||||
* The handling of nr_running in sched callbacks are disabled
|
||||
* now. Zap nr_running. After this, nr_running stays zero and
|
||||
* need_more_worker() and keep_working() are always true as
|
||||
* long as the worklist is not empty. This pool now behaves as
|
||||
* an unbound (in terms of concurrency management) pool which
|
||||
* are served by workers tied to the pool.
|
||||
*/
|
||||
atomic_set(&pool->nr_running, 0);
|
||||
@@ -5024,9 +5017,16 @@ static void unbind_workers(int cpu)
|
||||
* worker blocking could lead to lengthy stalls. Kick off
|
||||
* unbound chain execution of currently pending work items.
|
||||
*/
|
||||
raw_spin_lock_irq(&pool->lock);
|
||||
wake_up_worker(pool);
|
||||
|
||||
raw_spin_unlock_irq(&pool->lock);
|
||||
|
||||
for_each_pool_worker(worker, pool) {
|
||||
kthread_set_per_cpu(worker->task, -1);
|
||||
WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, cpu_possible_mask) < 0);
|
||||
}
|
||||
|
||||
mutex_unlock(&wq_pool_attach_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5062,17 +5062,6 @@ static void rebind_workers(struct worker_pool *pool)
|
||||
for_each_pool_worker(worker, pool) {
|
||||
unsigned int worker_flags = worker->flags;
|
||||
|
||||
/*
|
||||
* A bound idle worker should actually be on the runqueue
|
||||
* of the associated CPU for local wake-ups targeting it to
|
||||
* work. Kick all idle workers so that they migrate to the
|
||||
* associated CPU. Doing this in the same loop as
|
||||
* replacing UNBOUND with REBOUND is safe as no worker will
|
||||
* be bound before @pool->lock is released.
|
||||
*/
|
||||
if (worker_flags & WORKER_IDLE)
|
||||
wake_up_process(worker->task);
|
||||
|
||||
/*
|
||||
* We want to clear UNBOUND but can't directly call
|
||||
* worker_clr_flags() or adjust nr_running. Atomically
|
||||
|
||||
@@ -3564,7 +3564,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
|
||||
++fmt;
|
||||
|
||||
for ( ; *fmt && *fmt != ']'; ++fmt, ++len)
|
||||
set_bit((u8)*fmt, set);
|
||||
__set_bit((u8)*fmt, set);
|
||||
|
||||
/* no ']' or no character set found */
|
||||
if (!*fmt || !len)
|
||||
@@ -3574,7 +3574,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
|
||||
if (negate) {
|
||||
bitmap_complement(set, set, 256);
|
||||
/* exclude null '\0' byte */
|
||||
clear_bit(0, set);
|
||||
__clear_bit(0, set);
|
||||
}
|
||||
|
||||
/* match must be non-empty */
|
||||
|
||||
@@ -44,19 +44,17 @@ class LxDmesg(gdb.Command):
|
||||
sz = prb_desc_ring_type.get_type().sizeof
|
||||
desc_ring = utils.read_memoryview(inf, addr, sz).tobytes()
|
||||
|
||||
# read in descriptor array
|
||||
# read in descriptor count, size, and address
|
||||
off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8
|
||||
desc_ring_count = 1 << utils.read_u32(desc_ring, off)
|
||||
desc_sz = prb_desc_type.get_type().sizeof
|
||||
off = prb_desc_ring_type.get_type()['descs'].bitpos // 8
|
||||
addr = utils.read_ulong(desc_ring, off)
|
||||
descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes()
|
||||
desc_addr = utils.read_ulong(desc_ring, off)
|
||||
|
||||
# read in info array
|
||||
# read in info size and address
|
||||
info_sz = printk_info_type.get_type().sizeof
|
||||
off = prb_desc_ring_type.get_type()['infos'].bitpos // 8
|
||||
addr = utils.read_ulong(desc_ring, off)
|
||||
infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes()
|
||||
info_addr = utils.read_ulong(desc_ring, off)
|
||||
|
||||
# read in text data ring structure
|
||||
off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8
|
||||
@@ -64,12 +62,11 @@ class LxDmesg(gdb.Command):
|
||||
sz = prb_data_ring_type.get_type().sizeof
|
||||
text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes()
|
||||
|
||||
# read in text data
|
||||
# read in text data size and address
|
||||
off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8
|
||||
text_data_sz = 1 << utils.read_u32(text_data_ring, off)
|
||||
off = prb_data_ring_type.get_type()['data'].bitpos // 8
|
||||
addr = utils.read_ulong(text_data_ring, off)
|
||||
text_data = utils.read_memoryview(inf, addr, text_data_sz).tobytes()
|
||||
text_data_addr = utils.read_ulong(text_data_ring, off)
|
||||
|
||||
counter_off = atomic_long_type.get_type()['counter'].bitpos // 8
|
||||
|
||||
@@ -102,17 +99,20 @@ class LxDmesg(gdb.Command):
|
||||
desc_off = desc_sz * ind
|
||||
info_off = info_sz * ind
|
||||
|
||||
desc = utils.read_memoryview(inf, desc_addr + desc_off, desc_sz).tobytes()
|
||||
|
||||
# skip non-committed record
|
||||
state = 3 & (utils.read_u64(descs, desc_off + sv_off +
|
||||
counter_off) >> desc_flags_shift)
|
||||
state = 3 & (utils.read_u64(desc, sv_off + counter_off) >> desc_flags_shift)
|
||||
if state != desc_committed and state != desc_finalized:
|
||||
if did == head_id:
|
||||
break
|
||||
did = (did + 1) & desc_id_mask
|
||||
continue
|
||||
|
||||
begin = utils.read_ulong(descs, desc_off + begin_off) % text_data_sz
|
||||
end = utils.read_ulong(descs, desc_off + next_off) % text_data_sz
|
||||
begin = utils.read_ulong(desc, begin_off) % text_data_sz
|
||||
end = utils.read_ulong(desc, next_off) % text_data_sz
|
||||
|
||||
info = utils.read_memoryview(inf, info_addr + info_off, info_sz).tobytes()
|
||||
|
||||
# handle data-less record
|
||||
if begin & 1 == 1:
|
||||
@@ -125,16 +125,17 @@ class LxDmesg(gdb.Command):
|
||||
# skip over descriptor id
|
||||
text_start = begin + utils.get_long_type().sizeof
|
||||
|
||||
text_len = utils.read_u16(infos, info_off + len_off)
|
||||
text_len = utils.read_u16(info, len_off)
|
||||
|
||||
# handle truncated message
|
||||
if end - text_start < text_len:
|
||||
text_len = end - text_start
|
||||
|
||||
text = text_data[text_start:text_start + text_len].decode(
|
||||
encoding='utf8', errors='replace')
|
||||
text_data = utils.read_memoryview(inf, text_data_addr + text_start,
|
||||
text_len).tobytes()
|
||||
text = text_data[0:text_len].decode(encoding='utf8', errors='replace')
|
||||
|
||||
time_stamp = utils.read_u64(infos, info_off + ts_off)
|
||||
time_stamp = utils.read_u64(info, ts_off)
|
||||
|
||||
for line in text.splitlines():
|
||||
msg = u"[{time:12.6f}] {line}\n".format(
|
||||
|
||||
@@ -54,7 +54,6 @@ static double xk_1, xk_2; /* input temperature x[k-#] */
|
||||
*/
|
||||
int init_thermal_controller(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* init pid params */
|
||||
p_param.ts = ticktime;
|
||||
@@ -65,7 +64,7 @@ int init_thermal_controller(void)
|
||||
|
||||
p_param.t_target = target_temp_user;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void controller_reset(void)
|
||||
|
||||
Reference in New Issue
Block a user